#include "Pin.h"
-
#include "utils.h"
+// mbed libraries for hardware pwm
+#include "PwmOut.h"
+#include "InterruptIn.h"
+#include "PinNames.h"
+#include "port_api.h"
+
Pin::Pin(){
this->inverting= false;
+ this->valid= false;
+ this->pin= 32;
+ this->port= nullptr;
}
// Make a new pin object from a string
-// TODO : Comment this more, how does it work ?
Pin* Pin::from_string(std::string value){
+ if(value == "nc") {
+ this->valid= false;
+ return this; // optimize the nc case
+ }
+
LPC_GPIO_TypeDef* gpios[5] ={LPC_GPIO0,LPC_GPIO1,LPC_GPIO2,LPC_GPIO3,LPC_GPIO4};
// cs is the current position in the string
const char* cs = value.c_str();
// cn is the position of the next char after the number we just read
char* cn = NULL;
+ valid= true;
// grab first integer as port. pointer to first non-digit goes in cn
this->port_number = strtol(cs, &cn, 10);
this->pin = strtol(cs, &cn, 10);
// if strtol read some numbers, cn will point to the first non-digit
- if ((cn > cs) & (pin < 32)){
+ if ((cn > cs) && (pin < 32)){
this->port->FIOMASK &= ~(1 << this->pin);
// now check for modifiers:-
// o = set pin to open drain
// ^ = set pin to pull up
// v = set pin to pull down
- bool done= false;
- while(!done) {
- // skip any whitespace following the pin index
- while (is_whitespace(*cn)) cn++;
+ // - = set pin to no pull up or down
+ // @ = set pin to repeater mode
+ for (;*cn;cn++) {
switch(*cn) {
case '!':
this->inverting = true;
case 'v':
pull_down();
break;
+ case '-':
+ pull_none();
+ break;
+ case '@':
+ as_repeater();
+ break;
default:
- done= true;
+ // skip any whitespace following the pin index
+ if (!is_whitespace(*cn))
+ return this;
}
- if(!done) cn++;
}
-
-
return this;
}
}
}
// from_string failed. TODO: some sort of error
+ valid= false;
port_number = 0;
port = gpios[0];
- pin = 255;
+ pin = 32;
inverting = false;
return this;
}
// Configure this pin as OD
Pin* Pin::as_open_drain(){
- if (this->pin >= 32) return this;
+ if (!this->valid) return this;
if( this->port_number == 0 ){ LPC_PINCON->PINMODE_OD0 |= (1<<this->pin); }
if( this->port_number == 1 ){ LPC_PINCON->PINMODE_OD1 |= (1<<this->pin); }
if( this->port_number == 2 ){ LPC_PINCON->PINMODE_OD2 |= (1<<this->pin); }
if( this->port_number == 3 ){ LPC_PINCON->PINMODE_OD3 |= (1<<this->pin); }
if( this->port_number == 4 ){ LPC_PINCON->PINMODE_OD4 |= (1<<this->pin); }
+ pull_none(); // no pull up by default
+ return this;
+}
+
+
+// Configure this pin as a repeater
+Pin* Pin::as_repeater(){
+ if (!this->valid) return this;
+ // Set the two bits for this pin as 01
+ if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE0 &= ~(2<<( this->pin *2)); }
+ if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE1 &= ~(2<<((this->pin-16)*2)); }
+ if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE2 &= ~(2<<( this->pin *2)); }
+ if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE3 &= ~(2<<((this->pin-16)*2)); }
+ if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE4 &= ~(2<<( this->pin *2)); }
+ if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE7 &= ~(2<<((this->pin-16)*2)); }
+ if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (1<<( this->pin*2)); LPC_PINCON->PINMODE9 &= ~(2<<((this->pin-16)*2)); }
return this;
}
+// Configure this pin as no pullup or pulldown
+Pin* Pin::pull_none(){
+ if (!this->valid) return this;
+ // Set the two bits for this pin as 10
+ if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE0 &= ~(1<<( this->pin *2)); }
+ if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE1 &= ~(1<<((this->pin-16)*2)); }
+ if( this->port_number == 1 && this->pin < 16 ){ LPC_PINCON->PINMODE2 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE2 &= ~(1<<( this->pin *2)); }
+ if( this->port_number == 1 && this->pin >= 16 ){ LPC_PINCON->PINMODE3 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE3 &= ~(1<<((this->pin-16)*2)); }
+ if( this->port_number == 2 && this->pin < 16 ){ LPC_PINCON->PINMODE4 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE4 &= ~(1<<( this->pin *2)); }
+ if( this->port_number == 3 && this->pin >= 16 ){ LPC_PINCON->PINMODE7 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE7 &= ~(1<<((this->pin-16)*2)); }
+ if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (2<<( this->pin*2)); LPC_PINCON->PINMODE9 &= ~(1<<((this->pin-16)*2)); }
+ return this;
+}
+
// Configure this pin as a pullup
Pin* Pin::pull_up(){
- if (this->pin >= 32) return this;
+ if (!this->valid) return this;
// Set the two bits for this pin as 00
if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 &= ~(3<<( this->pin *2)); }
if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 &= ~(3<<((this->pin-16)*2)); }
// Configure this pin as a pulldown
Pin* Pin::pull_down(){
- if (this->pin >= 32) return this;
+ if (!this->valid) return this;
// Set the two bits for this pin as 11
if( this->port_number == 0 && this->pin < 16 ){ LPC_PINCON->PINMODE0 |= (3<<( this->pin *2)); }
if( this->port_number == 0 && this->pin >= 16 ){ LPC_PINCON->PINMODE1 |= (3<<((this->pin-16)*2)); }
if( this->port_number == 4 && this->pin >= 16 ){ LPC_PINCON->PINMODE9 |= (3<<((this->pin-16)*2)); }
return this;
}
+
+// If available on this pin, return mbed hardware pwm class for this pin
+mbed::PwmOut* Pin::hardware_pwm()
+{
+ if (port_number == 1)
+ {
+ if (pin == 18) { return new mbed::PwmOut(P1_18); }
+ if (pin == 20) { return new mbed::PwmOut(P1_20); }
+ if (pin == 21) { return new mbed::PwmOut(P1_21); }
+ if (pin == 23) { return new mbed::PwmOut(P1_23); }
+ if (pin == 24) { return new mbed::PwmOut(P1_24); }
+ if (pin == 26) { return new mbed::PwmOut(P1_26); }
+ }
+ else if (port_number == 2)
+ {
+ if (pin == 0) { return new mbed::PwmOut(P2_0); }
+ if (pin == 1) { return new mbed::PwmOut(P2_1); }
+ if (pin == 2) { return new mbed::PwmOut(P2_2); }
+ if (pin == 3) { return new mbed::PwmOut(P2_3); }
+ if (pin == 4) { return new mbed::PwmOut(P2_4); }
+ if (pin == 5) { return new mbed::PwmOut(P2_5); }
+ }
+ else if (port_number == 3)
+ {
+ if (pin == 25) { return new mbed::PwmOut(P3_25); }
+ if (pin == 26) { return new mbed::PwmOut(P3_26); }
+ }
+ return nullptr;
+}
+
+mbed::InterruptIn* Pin::interrupt_pin()
+{
+ if(!this->valid) return nullptr;
+
+ // set as input
+ as_input();
+
+ if (port_number == 0 || port_number == 2) {
+ PinName pinname = port_pin((PortName)port_number, pin);
+ return new mbed::InterruptIn(pinname);
+
+ }else{
+ this->valid= false;
+ return nullptr;
+ }
+}