Koichi Kurahashi
/
RPi_1114
Raspberry Pi Power Controller by LPC1114
Diff: main.cpp
- 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