Andrew Boyson
/
iot
Backing up an unused program in case of future need
Diff: esp.cpp
- Revision:
- 0:09f915e6f9f6
- Child:
- 2:06fa34661f19
diff -r 000000000000 -r 09f915e6f9f6 esp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/esp.cpp Wed Apr 13 09:21:02 2016 +0000 @@ -0,0 +1,344 @@ +#include "mbed.h" +#include "log.h" +#include "esp.h" +#include "io.h" +#include <stdarg.h> + + +#define RECV_TIMEOUT_MS 5000 +static RawSerial esp(p9, p10); // tx, rx + +//State +#define LINE_LENGTH 256 +#define IDLE 0 +#define IN_LINE 1 +#define IPD_WAIT_START 2 +#define IPD_READ 3 +#define SEND_DATA 4 +static int state; //Initialised in init + +//Solicited responses received +//============================ +#define LINE_LENGTH 256 +int EspLineAvailable; //Initialised in init; can be one of the values defined in esp.h +char EspLine[LINE_LENGTH]; +static char * pLineNext; //Initialised in init to EspLine +int addToLine(char c) +{ + if (pLineNext >= EspLine + LINE_LENGTH) return -1; + switch (c) + { + case 0: + *pLineNext = '\\'; + pLineNext++; + *pLineNext = '0'; + pLineNext++; + break; + case '\r': + case '\n': + break; + default: + *pLineNext = c; + pLineNext++; + break; + } + *pLineNext = 0; + return 0; +} + +//Unsolicited ntp or http requests +//================================ +void *EspIpdBuffer[4]; +int EspIpdBufferLen[4]; +int EspIpdReserved[4]; +int EspIpdLength; +int EspIpdId; +int EspDataAvailable; + +//Wrap around buffers +//=================== +#define RECV_BUFFER_LENGTH 1024 +#define SEND_BUFFER_LENGTH 1024 +static char recvbuffer[RECV_BUFFER_LENGTH]; +static char sendbuffer[SEND_BUFFER_LENGTH]; +static char* pRecvPush; //Initialised in init +static char* pRecvPull; //Initialised in init +static char* pSendPush; //Initialised in init +static char* pSendPull; //Initialised in init + +static void incrementPushPullPointer(char** pp, char* buffer, int bufferLength) +{ + (*pp)++; //increment the pointer by one + if (*pp == buffer + bufferLength) *pp = buffer; //if the pointer is now beyond the end then point it back to the start +} +static void recvpush(void) //Called by the esp data received interrupt +{ + while (esp.readable()) + { + int c = esp.getc(); + *pRecvPush = c; + incrementPushPullPointer(&pRecvPush, recvbuffer, RECV_BUFFER_LENGTH); + } +} +static int recvpull(void) //Called every scan. Returns the next byte or EOF if no more are available +{ + if (pRecvPull == pRecvPush) return EOF; + char c = *pRecvPull; + incrementPushPullPointer(&pRecvPull, recvbuffer, RECV_BUFFER_LENGTH); + return c; +} +static void sendpush(char c) //Called whenever something needs to be sent +{ + *pSendPush = c; + incrementPushPullPointer(&pSendPush, sendbuffer, SEND_BUFFER_LENGTH); +} +static int sendpull(void) //Called every scan. Returns the next byte or EOF if no more are available +{ + if (pSendPull == pSendPush) return EOF; + char c = *pSendPull; + incrementPushPullPointer(&pSendPull, sendbuffer, SEND_BUFFER_LENGTH); + return c; +} + +//Stuff to send +//============= +int EspLengthToSend; +const void * EspDataToSend; + +void EspSendStringF(char *fmt, ...) +{ + va_list argptr; + va_start(argptr, fmt); + int size = vsnprintf(NULL, 0, fmt, argptr); + char snd[size + 1]; + vsprintf(snd, fmt, argptr); + va_end(argptr); + EspSendString(snd); +} +void EspSendString(char* p) +{ + while(*p) sendpush(*p++); +} +void EspSendData(int length, const void * snd) +{ + const char* p = (char*)snd; + const char* e = (char*)snd + length; + while (p < e) sendpush(*p++); +} + + +//Reset ESP8266 zone +#define RESET_TIME_MS 250 +static DigitalOut espRunOnHighResetOnLow(p26); +int reset; //Set to 1 by EspReset (and hence EspInit); set to 0 by EspReleasefromReset +void EspResetAndStop() +{ + reset = true; + pRecvPush = recvbuffer; + pRecvPull = recvbuffer; + pSendPush = sendbuffer; + pSendPull = sendbuffer; + pLineNext = EspLine; + *pLineNext = 0; + EspLengthToSend = 0; + EspDataToSend = NULL; + state = IDLE; +} +void EspReleaseFromReset(void) +{ + reset = false; +} +void pulseResetPin() +{ + static Timer resetTimer; + + if (reset) + { + resetTimer.stop(); + resetTimer.reset(); + espRunOnHighResetOnLow = 0; + } + else + { + resetTimer.start(); + if (resetTimer.read_ms() > RESET_TIME_MS) + { + resetTimer.stop(); + espRunOnHighResetOnLow = 1; + } + } +} +//General commands +void EspInit() +{ + EspResetAndStop(); + esp.attach(&recvpush, Serial::RxIrq); + esp.baud(BAUD); + for (int i = 0; i < 4; i++) + { + EspIpdBuffer[i] = NULL; + EspIpdBufferLen[i] = 0; + EspIpdReserved[i] = 0; + } +} +void EspBaud(int baud) +{ + esp.baud(baud); +} + +//Main loop zone +int handleCharacter(char c) +{ + //Static variables. Initialised on first load. + static char ipdHeader[20]; + static char * pipdHeader; //Set to ipdHeader when a '+' is received + static int bytesRcvd; //Set to 0 when the ':' following the +IPD is received + static void * pData; //Set to EspIpdBuffer[EspIpdId] when the ':' following the +IPD is received + + switch(state) + { + case IDLE: + if (c == '+') + { + pipdHeader = ipdHeader; + *pipdHeader = 0; + state = IPD_WAIT_START; + } + else if (c == '>') + { + state = SEND_DATA; + } + else + { + pLineNext = EspLine; + *pLineNext = 0; + int r = addToLine(c); + if (r) + { + EspLineAvailable = ESP_OVERFLOW; + state = IDLE; + } + else + { + state = IN_LINE; + } + } + break; + case IN_LINE: + if (c == '\n') + { + EspLineAvailable = ESP_AVAILABLE; + state = IDLE; + } + else + { + int r = addToLine(c); + if (r) + { + EspLineAvailable = ESP_OVERFLOW; + state = IDLE; + } + } + break; + case IPD_WAIT_START: + if (pipdHeader == ipdHeader && c != 'I') //If the first character after the '+' is not 'I' then start a line instead + { + pLineNext = EspLine; + addToLine('+'); + addToLine(c); + state = IN_LINE; + } + else + { + *pipdHeader++ = c; + *pipdHeader = 0; + if (c == ':') + { + sscanf(ipdHeader, "IPD,%d,%d:", &EspIpdId, &EspIpdLength); + bytesRcvd = 0; + pData = EspIpdBuffer[EspIpdId]; + state = IPD_READ; + } + } + break; + case IPD_READ: + bytesRcvd++; + if (bytesRcvd <= EspIpdBufferLen[EspIpdId]) + { + *(char *)pData = c; + pData = (char *)pData + 1; + } + if (bytesRcvd == EspIpdLength) + { + if (bytesRcvd <= EspIpdBufferLen[EspIpdId]) EspDataAvailable = ESP_AVAILABLE; + else EspDataAvailable = ESP_OVERFLOW; + state = IDLE; + } + break; + case SEND_DATA: + EspSendData(EspLengthToSend, EspDataToSend); + state = IDLE; + break; + default: + LogF("Unknown state %d\n\r", state); + return -1; + } + return 0; +} +void sendAnyData() +{ + while(esp.writeable()) + { + int c = sendpull(); + if (c == EOF) break; + esp.putc(c); + } +} +int isTimeout() +{ + static Timer receiveTimer; + + if (state == IDLE) + { + receiveTimer.stop(); + receiveTimer.reset(); + } + else + { + receiveTimer.start(); + if (receiveTimer.read_ms() > RECV_TIMEOUT_MS) return true; + } + return false; +} +int EspMain() +{ + sendAnyData(); + + pulseResetPin(); + + //Reset line availability one shot + EspLineAvailable = ESP_IDLE; + EspDataAvailable = ESP_IDLE; + + if (isTimeout()) + { + if (state == IN_LINE) EspLineAvailable = ESP_TIMEOUT; + else EspDataAvailable = ESP_TIMEOUT; + state = IDLE; + return 0; + } + + //Handle any incoming characters + int c = recvpull(); + if (c != EOF) + { + LogPush(c); + int r = handleCharacter(c); //This will set the EspAvailable one-shots + if (r) return -1; + } + + return 0; +} + + +