Raspberry Pi Power Controller by LPC1114

Dependencies:   mbed

Revision:
2:f6265132c464
Parent:
1:10aa79121f61
Child:
3:b7b9d3d4eed8
--- a/main.cpp	Wed Jan 04 23:27:19 2017 +0000
+++ b/main.cpp	Fri Jan 13 10:44:29 2017 +0000
@@ -1,145 +1,564 @@
 #include "mbed.h"
 
 
+const int   kMaxInteger      = 32767;
+const float fFloatScaleValue = 1024.0;  // factor to convert long <-> float
+
+//
+//  common definition
+//
+
 #define kCommandAddress 0x50
-#define MaxReceiveBufferSize 100
+
 
-#define kCommandUp      'u'     //  i2c command : up - power on
-#define kCommandDown    'd'     //              : down - power off
-#define kCommandLED     'l'     //              : led - on/off/flash
+//  internal gpio map
+//
+//  dp5  : SDA - RPi's SDA / pad
+//  dp14 : on board LED
+//  dp15 : rx - RPi's TXD
+//  dp16 : tx - RPi's RXD
+//  dp17 : out - RPi's power switch
+//  dp23 : reset - RPi's GPIO24
+//  dp24 : isp - RPI's GPIO23
+//  dp25 : in - sw1 / pad
+//  dp27 : SCL - RPi's SCL / pad
+
+
 
-#define kLED_Off    0   // LED off
-#define kLED_On     1   // LED on
-#define kLED_Flash  2   // LED flash 
+//  pad map
+//
+//  dp1  digital Pwm        : Pwm
+//  dp2  digital Pwm        : Pwm
+//  dp4  digital analog     : digital in
+//  dp5  I2C(SDA)           : RPi(master)'s SDA / pad
+//  dp6  digital            : digital in
+//  dp9  digital analog     : analog
+//  dp10 digital analog     : analog
+//  dp11 digital analog     : analog
+//  dp13 digital analog
+//  do18 digital Pwm        : Pwm
+//  dp25 digital in         : sw1 / pad
+//  dp26 digital            : digital out
+//  dp27 I2C(SCL)           : RPi(master)'s SCL / pad
+//  dp28 digital            : digital out
+
+
 
 
+//
+//  I2C typical command format
+//
+//  [0] = command
+//  [1] = target ch
+//  [2] = format
+//        0 : binary
+//            [3...] : long
+//        1 : ascii string
+//            [3...] : c string
+//
+//  endian : little endian
+//
+
+#define kCommandUp          0x10    //  i2c command : RPi power on
+#define kCommandDown        0x11    //              : RPi power off
+
+#define kCommandLED         0x20    //              : led - on/off/flash
+
+#define kCommandAnalogRead  0x30    //              : read analog port
+#define kCommandAnalogReset 0x31    //              : reset read buffer
+#define kCommandAnalogStart 0x32    //              : start fill buffer       
+#define kCommandAnalogStop  0x33    //              : stop  fill buffer
+#define kCommandAnalogLoad  0x34    //              : load analog data
+
+#define kCommandPwm         0x40    //              : output Pwm
+#define kCommandPwmPeriod   0x41    //              : set Pwm period in uSec
+
+#define kCommandDigitalIn   0x50    //              : input  digital
+
+#define kCommandDigitalOut  0x60    //              : output digital
+
+
+#define kCommandModeBinary  0x00    //  binary mode
+#define kCommandModeASCII   0x10    //  ascii  mode    
+
+//
+//  I2C
+//
+
+#define MaxReceiveBufferSize 100    //  i2c receiving buffer length
+
 I2CSlave slave(dp5, dp27);
 
+
+
+//
+//  RPi Power Controll
+//
+//  [0] command
+//      turn on : kCommandUp
+//      turn off : kCommandDown
+//  [1] ch
+//      always 0
+//  [2] format
+//      0 : binary mode
+//      1 : c string mode
+//  [3...] data
+//      binary mode : little endian long
+//      ascii mode  : c string
+//
+
 DigitalOut rpiPower(dp17);
 DigitalOut led(dp14);
 
-DigitalIn sw1(dp25);
-const int SW_OFF = 1;
-const int SW_ON  = 0;   // pull up
-int waitForSw1Release = 0;
-
+int powerMode = kCommandUp;
 
-int powerMode = kCommandUp;
-int ledMode   = kLED_Flash;
-int sw1Mode   = SW_OFF;
-
-
-static char buf[MaxReceiveBufferSize];
-
-Ticker second;
-long onTimer  = -1;
-long offTimer = -1;
-
-void powerOff() {
+void powerOff()
+{
     rpiPower  = 0;
     powerMode = kCommandDown;
 }
 
-void powerOn() {
+void powerOn()
+{
     rpiPower  = 1;
     powerMode = kCommandUp;
 }
 
 
-void ledOn() {
+
+//  led modes
+//
+//  [0] command
+//      led comtrol
+//  [1] ch
+//      always 0
+//  [2] mode
+//      0 : turn off
+//      1 : turn on
+//      2 : flash
+//
+
+#define kLED_Off    0   // LED off
+#define kLED_On     1   // LED on
+#define kLED_Flash  2   // LED flash 
+
+int ledMode   = kLED_Flash;
+
+
+void ledOn()
+{
     led     = 1;
     ledMode = kLED_On;
 }
 
-void ledOff() {
+void ledOff()
+{
     led     = 0;
     ledMode = kLED_Off;
 }
 
 
-void funcSecond() {
+
+
+//
+//  on board Switch
+//
+DigitalIn sw1(dp25);
+const int SW_OFF = 1;
+const int SW_ON  = 0;   // pull up
+
+int sw1Mode   = SW_OFF;
+int waitForSw1Release = 0;
+
+
+//
+//  ADC
+//
+
+#define kMaxAnalogChannels      3       //  analog read channels .... never change
+#define kMinAnalogPeriod    10000       //  10mSec is minimum
+#define kMaxAnalogPeriod 10000000       //   10Sec is maximum
+
+const int kMaxAnalogBufferSize  = 256;  //  analog read buffer size
+
+typedef struct {
+    unsigned short count;
+    unsigned short buffer[kMaxAnalogBufferSize];
+} AnalogBuffer;
+
+AnalogBuffer analogBuffer[kMaxAnalogChannels];
+
+AnalogIn analogIn[kMaxAnalogChannels] = {dp9, dp10, dp11};
+Ticker analogTicker[kMaxAnalogChannels];
+//Ticker t1, t2, t0;
+
+
+void analogTickerVectors(int ch) {
+    if (ch >= 0 && ch < kMaxAnalogChannels) {
+        AnalogBuffer *p = &analogBuffer[ch];
+        unsigned short count = p->count;
+        if (count < (kMaxAnalogBufferSize-1)) {
+            float f = analogIn[ch];
+            unsigned short v = f * fFloatScaleValue;
+            p->buffer[count++] = v;
+            p->count = count;
+        }
+    }
+}
+
+
+
+void analogTickerVector0()
+{
+    analogTickerVectors(0);
+}
+
+void analogTickerVector1()
+{
+    analogTickerVectors(1);
+}
+
+void analogTickerVector2()
+{
+    analogTickerVectors(2);
+}
+
+
+
+float execAnalogIn(int ch)
+{
+    if (ch >= 0 && kMaxAnalogChannels) {
+        return analogIn[ch];
+    }
+    return -1;
+}
+
+
+int execAnalogReset(int ch)
+{
+    if (ch >= 0 && ch < kMaxAnalogChannels) {
+        analogTicker[ch].detach();
+        analogBuffer[ch].count = 0;
+        return 0;
+    }
+    return -1;
+}
+
+
+int execAnalogStart(int ch, long value)
+{
+    if (ch >=0 && ch < kMaxAnalogChannels) {
+        analogBuffer[ch].count = 0;
+        value *= 1000;
+        if (value < kMinAnalogPeriod || value > kMaxAnalogPeriod) {
+            value = 1000;    //  1 sec
+        }
+        switch (ch) {
+            case 0: analogTicker[ch].attach_us(&analogTickerVector0, value);  break;
+            case 1: analogTicker[ch].attach_us(&analogTickerVector1, value);  break;
+            case 2: analogTicker[ch].attach_us(&analogTickerVector2, value);  break;
+        }
+        return 0;
+    }
+
+    return -1;
+}
+
+
+int execAnalogStop(int ch)
+{
+    if (ch >= 0 && ch < kMaxAnalogChannels) {
+        analogTicker[ch].detach();
+        return 0;
+    }
+    return -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//
+//  Digital Read
+//
+const int kMaxDigitalInChannels = 2;
+
+DigitalIn digitalIn[kMaxDigitalInChannels] = {dp4,dp6};
+
+int execDigitalIn(int ch)
+{
+    if (ch >= 0 && ch < kMaxDigitalInChannels) {
+        return digitalIn[ch];
+    }
+    return -1;
+}
+
+
+
+//
+//  Digital Write
+//
+
+const int kMaxDigitalOutChannels = 2;
+
+DigitalOut digitalOut[kMaxDigitalOutChannels] = {dp26,dp28};
+
+int execDigitalOut(int ch, long value)
+{
+    if (ch >= 0 && ch < kMaxDigitalOutChannels) {
+        digitalOut[ch] = value == 0 ? 0 : 1;
+        return 0;
+    }
+    return -1;
+}
+
+
+//
+//  Pwm
+//
+
+const int kMaxPwmChannels = 3;
+
+PwmOut Pwm[kMaxPwmChannels] = {dp1, dp2, dp18};
+
+int execSetPwmPeriod(int ch, long value)
+{
+    if (ch > 0 && ch < kMaxPwmChannels && value >= 0 && value <= kMaxInteger) {
+        Pwm[ch].period_us(value);
+        return 0;
+    }
+    return -1;
+}
+
+int execPwmOut(int ch, long value)
+{
+    if (ch > 0 && ch < kMaxPwmChannels) {
+        float f = value / fFloatScaleValue;
+        Pwm[ch] = f;
+        return 0;
+    }
+
+    return -1;
+}
+
+
+
+
+//
+//  clock for RPi's timer and LED Flashing
+//
+Ticker second;
+long onTimer  = -1;
+long offTimer = -1;
+
+void funcSecond()
+{
     if (onTimer > 0) {
         onTimer --;
         if (onTimer == 0) {
             powerOn();
-            onTimer = -1;      
+            onTimer = -1;
         }
-    }  
+    }
     if (offTimer > 0) {
         offTimer --;
         if (offTimer == 0) {
             powerOff();
-            offTimer = -1;      
+            offTimer = -1;
         }
-    }  
-    
+    }
+
     if (ledMode == kLED_Flash) {
         led = 1;
         wait_ms(10);
         led = 0;
-    }  
+    }
 }
 
+
+
+//
+//  main routine
+//
+
+static char buf[MaxReceiveBufferSize];
+
 int main()
 {
+    char strBuf[16];
+    char prevCommand = 0;
+    char prevCh      = 0;
+    char prevMode    = 0;
+
+    for (int i = 0; i < kMaxAnalogChannels; i++) {
+        analogBuffer[i].count = 0;
+    }
+    
     slave.address(kCommandAddress);
     second.attach(funcSecond, 1);
-    
+
     sw1.mode(PullNone);
-    
+
     powerOn();
-    
+
     while(1) {
         if (sw1 == SW_ON) {
             wait_ms(5);
             waitForSw1Release = 1;
         }
-        
+
         if (waitForSw1Release && sw1 == SW_OFF) {
             if (powerMode == kCommandUp) {
                 powerOff();
             } else {
                 powerOn();
             }
-            waitForSw1Release = 0; 
+            waitForSw1Release = 0;
         }
+
         int status = slave.receive();
-        long t = 0;
+        long value = 0;
         switch (status) {
-            case I2CSlave::WriteAddressed:
+            case I2CSlave::WriteAddressed: {
                 if (slave.read(buf, MaxReceiveBufferSize)) {
-                    switch(buf[0]) {
-                    case kCommandUp:
-                        t = atol(buf+1);
-                        if (t > 0) {
-                            onTimer = t;
-                        } else if (t == 0) {
-                            powerOn();
-                        }
-                        break;
+                    char command = buf[0];
+                    char ch      = buf[1];
+                    char mode    = buf[2];
+                    value = 0;
+                    if (mode == kCommandModeBinary) {
+                        long *p = (long *)buf+3;
+                        value = *p;
+                        if (value < 0) value = 0;
+                    } else if (mode == kCommandModeASCII) {
+                        value = atol(buf+3);
+                    }
+
+                    switch(command) {
+                        case kCommandUp:
+                            if (value > 0) {
+                                onTimer = value;
+                            } else if (value == 0) {
+                                powerOn();
+                            }
+                            break;
+
+                        case kCommandDown:
+                            if (value > 0) {
+                                offTimer = value;
+                            } else if (value == 0) {
+                                powerOff();
+                            }
+                            break;
+                        case kCommandLED:
+                            switch (mode) {
+                                case 0:
+                                    ledOff();
+                                    break;
+                                case 1:
+                                    ledOn();
+                                    break;
+                                case 2:
+                                    ledMode = kLED_Flash;
+                                    break;
+                            }
+                            break;
+
+                        case kCommandAnalogReset:
+                            execAnalogReset(ch);
+                            break;
+
+                        case kCommandAnalogStart:
+                            execAnalogStart(ch, value);
+                            break;
+
+                        case kCommandAnalogStop:
+                            execAnalogStop(ch);
+                            break;
+
+                        case kCommandPwm:
+                            execPwmOut(ch, value);
+                            break;
+
+                        case kCommandPwmPeriod:
+                            execSetPwmPeriod(ch, value);
+                            break;
+
+                        case kCommandDigitalOut:
+                            execDigitalOut(ch, value);
+                            break;
+
+                        case kCommandDigitalIn:
+                        case kCommandAnalogRead:
+                        case kCommandAnalogLoad:
+                            ledOn();
+                            prevCommand = command;
+                            prevCh      = ch;
+                            prevMode    = mode;
+                            break;
                         
-                    case kCommandDown:
-                        t = atol(buf+1);
-                        if (t > 0) {
-                            offTimer = t;
-                        } else if (t == 0) {
-                            powerOff();
-                        }
-                        break;    
-                    case kCommandLED:
-                        switch (buf[1]) {
-                        case '0': ledOff();             break;
-                        case '1': ledOn();              break;
-                        case 'f': ledMode = kLED_Flash; break;
-                        }
+                        default:
+                            prevCommand = 0;
+                            break;
+                            
                     }
                 }
                 break;
+            }
+
+            case I2CSlave::ReadAddressed: {
+                
+                switch(prevCommand) {
+                    case kCommandAnalogRead:
+                        float f = execAnalogIn(prevCh);
+                        if (prevMode == kCommandModeBinary) {
+                            value = f * fFloatScaleValue;   // 10bit = 1024.0
+                            slave.write((const char *)&value, sizeof(value));
+                        } else {
+                            sprintf(strBuf, "%f", f);
+                            slave.write(strBuf, strlen(strBuf)+1);
+                        }
+                        break;
+
+                    case kCommandAnalogLoad:     //  no ascii mode
+                        if (prevCh < kMaxAnalogChannels) {
+                            AnalogBuffer *p = &analogBuffer[prevCh];
+//                            __disable_irq();
+                            unsigned short count = p->count;
+                            slave.write((const char *)p, sizeof(unsigned short)*(count+1));
+//                            __enable_irq();
+                            p->count = 0;
+                        }
+                        break;
+
+
+                    case kCommandDigitalIn:
+                        value = execDigitalIn(prevCh);
+                        if (prevMode == kCommandModeBinary) {
+                            slave.write((const char *)&value, sizeof(value));
+                        } else {
+                            sprintf(strBuf, "%ld", value);
+                            slave.write((const char *)strBuf, strlen(strBuf)+1);
+                        }
+                        break;
+                }
+                slave.stop();
+                break;
+            }
 
             default:
                 wait_ms(1);
                 break;
         }
     }
-}
-
+}
\ No newline at end of file