Merge branch 'upstreamedge' into feature/acceleration-per-tick
[clinton/Smoothieware.git] / src / libs / Pin.cpp
index b104f2d..a147111 100644 (file)
@@ -1,19 +1,33 @@
 #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
 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);
@@ -30,7 +44,7 @@ Pin* Pin::from_string(std::string value){
             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:-
@@ -40,8 +54,7 @@ Pin* Pin::from_string(std::string value){
                 // v = set pin to pull down
                 // - = set pin to no pull up or down
                 // @ = set pin to repeater mode
-                bool done= false;
-                while(!done) {
+                for (;*cn;cn++) {
                     switch(*cn) {
                         case '!':
                             this->inverting = true;
@@ -64,29 +77,26 @@ Pin* Pin::from_string(std::string value){
                         default:
                             // skip any whitespace following the pin index
                             if (!is_whitespace(*cn))
-                                done = true;
+                                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); }
@@ -99,7 +109,7 @@ Pin* Pin::as_open_drain(){
 
 // Configure this pin as a repeater
 Pin* Pin::as_repeater(){
-    if (this->pin >= 32) return this;
+    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)); }
@@ -110,23 +120,24 @@ Pin* Pin::as_repeater(){
     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->pin >= 32) 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;
+       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)); }
@@ -140,7 +151,7 @@ Pin* Pin::pull_up(){
 
 // 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)); }
@@ -151,3 +162,49 @@ Pin* Pin::pull_down(){
     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;
+    }
+}