Merge pull request #549 from PetteriAimonen/edge
[clinton/Smoothieware.git] / src / libs / Pin.cpp
1 #include "Pin.h"
2 #include "utils.h"
3
4 // mbed libraries for hardware pwm
5 #include "PwmOut.h"
6 #include "PinNames.h"
7
8 Pin::Pin(){
9 this->inverting= false;
10 }
11
12 // Make a new pin object from a string
13 Pin* Pin::from_string(std::string value){
14 LPC_GPIO_TypeDef* gpios[5] ={LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4};
15
16 // cs is the current position in the string
17 const char* cs = value.c_str();
18 // cn is the position of the next char after the number we just read
19 char* cn = NULL;
20
21 // grab first integer as port. pointer to first non-digit goes in cn
22 this->port_number = strtol(cs, &cn, 10);
23 // if cn > cs then strtol read at least one digit
24 if ((cn > cs) && (port_number <= 4)){
25 // translate port index into something useful
26 this->port = gpios[(unsigned int) this->port_number];
27 // if the char after the first integer is a . then we should expect a pin index next
28 if (*cn == '.'){
29 // move pointer to first digit (hopefully) of pin index
30 cs = ++cn;
31
32 // grab pin index.
33 this->pin = strtol(cs, &cn, 10);
34
35 // if strtol read some numbers, cn will point to the first non-digit
36 if ((cn > cs) && (pin < 32)){
37 this->port->FIOMASK &= ~(1 << this->pin);
38
39 // now check for modifiers:-
40 // ! = invert pin
41 // o = set pin to open drain
42 // ^ = set pin to pull up
43 // v = set pin to pull down
44 // - = set pin to no pull up or down
45 // @ = set pin to repeater mode
46 for (;*cn;cn++) {
47 switch(*cn) {
48 case '!':
49 this->inverting = true;
50 break;
51 case 'o':
52 as_open_drain();
53 break;
54 case '^':
55 pull_up();
56 break;
57 case 'v':
58 pull_down();
59 break;
60 case '-':
61 pull_none();
62 break;
63 case '@':
64 as_repeater();
65 break;
66 default:
67 // skip any whitespace following the pin index
68 if (!is_whitespace(*cn))
69 return this;
70 }
71 }
72 return this;
73 }
74 }
75 }
76
77 // from_string failed. TODO: some sort of error
78 port_number = 0;
79 port = gpios[0];
80 pin = 255;
81 inverting = false;
82 return this;
83 }
84
85 // Configure this pin as OD
86 Pin* Pin::as_open_drain(){
87 if (this->pin >= 32) return this;
88 if( this->port_number == 0 ){ LPC_PINCON->PINMODE_OD0 |= (1<<this->pin); }
89 if( this->port_number == 1 ){ LPC_PINCON->PINMODE_OD1 |= (1<<this->pin); }
90 if( this->port_number == 2 ){ LPC_PINCON->PINMODE_OD2 |= (1<<this->pin); }
91 if( this->port_number == 3 ){ LPC_PINCON->PINMODE_OD3 |= (1<<this->pin); }
92 if( this->port_number == 4 ){ LPC_PINCON->PINMODE_OD4 |= (1<<this->pin); }
93 pull_none(); // no pull up by default
94 return this;
95 }
96
97
98 // Configure this pin as a repeater
99 Pin* Pin::as_repeater(){
100 if (this->pin >= 32) return this;
101 // Set the two bits for this pin as 01
102 if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE0 &= ~(2<<( this->pin *2)); }
103 if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE1 &= ~(2<<((this->pin-16)*2)); }
104 if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE2 &= ~(2<<( this->pin *2)); }
105 if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE3 &= ~(2<<((this->pin-16)*2)); }
106 if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE4 &= ~(2<<( this->pin *2)); }
107 if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE7 &= ~(2<<((this->pin-16)*2)); }
108 if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE9 &= ~(2<<((this->pin-16)*2)); }
109 return this;
110 }
111
112 // Configure this pin as no pullup or pulldown
113 Pin* Pin::pull_none(){
114 if (this->pin >= 32) return this;
115 // Set the two bits for this pin as 10
116 if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE0 &= ~(1<<( this->pin *2)); }
117 if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE1 &= ~(1<<((this->pin-16)*2)); }
118 if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE2 &= ~(1<<( this->pin *2)); }
119 if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE3 &= ~(1<<((this->pin-16)*2)); }
120 if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE4 &= ~(1<<( this->pin *2)); }
121 if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE7 &= ~(1<<((this->pin-16)*2)); }
122 if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE9 &= ~(1<<((this->pin-16)*2)); }
123 return this;
124 }
125
126 // Configure this pin as a pullup
127 Pin* Pin::pull_up(){
128 if (this->pin >= 32) return this;
129 // Set the two bits for this pin as 00
130 if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 &= ~(3<<( this->pin *2)); }
131 if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 &= ~(3<<((this->pin-16)*2)); }
132 if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 &= ~(3<<( this->pin *2)); }
133 if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 &= ~(3<<((this->pin-16)*2)); }
134 if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 &= ~(3<<( this->pin *2)); }
135 if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 &= ~(3<<((this->pin-16)*2)); }
136 if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 &= ~(3<<((this->pin-16)*2)); }
137 return this;
138 }
139
140 // Configure this pin as a pulldown
141 Pin* Pin::pull_down(){
142 if (this->pin >= 32) return this;
143 // Set the two bits for this pin as 11
144 if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (3<<( this->pin *2)); }
145 if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (3<<((this->pin-16)*2)); }
146 if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 |= (3<<( this->pin *2)); }
147 if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 |= (3<<((this->pin-16)*2)); }
148 if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 |= (3<<( this->pin *2)); }
149 if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 |= (3<<((this->pin-16)*2)); }
150 if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (3<<((this->pin-16)*2)); }
151 return this;
152 }
153
154 // If available on this pin, return mbed hardware pwm class for this pin
155 mbed::PwmOut* Pin::hardware_pwm()
156 {
157 if (port_number == 1)
158 {
159 if (pin == 18) { return new mbed::PwmOut(P1_18); }
160 if (pin == 20) { return new mbed::PwmOut(P1_20); }
161 if (pin == 21) { return new mbed::PwmOut(P1_21); }
162 if (pin == 23) { return new mbed::PwmOut(P1_23); }
163 if (pin == 24) { return new mbed::PwmOut(P1_24); }
164 if (pin == 26) { return new mbed::PwmOut(P1_26); }
165 }
166 else if (port_number == 2)
167 {
168 if (pin == 0) { return new mbed::PwmOut(P2_0); }
169 if (pin == 1) { return new mbed::PwmOut(P2_1); }
170 if (pin == 2) { return new mbed::PwmOut(P2_2); }
171 if (pin == 3) { return new mbed::PwmOut(P2_3); }
172 if (pin == 4) { return new mbed::PwmOut(P2_4); }
173 if (pin == 5) { return new mbed::PwmOut(P2_5); }
174 }
175 else if (port_number == 3)
176 {
177 if (pin == 25) { return new mbed::PwmOut(P3_25); }
178 if (pin == 26) { return new mbed::PwmOut(P3_26); }
179 }
180 return NULL;
181 }