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