A simple WIP that logs data from a Grove sensor, and can send and receive information over USB and SMS.

Dependencies:   DHT DS_1337 SDFileSystem USBDevice mbed

Revision:
0:2df78a4443cd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Handlers/GprsHandler.cpp	Sun Apr 10 15:47:33 2016 +1000
@@ -0,0 +1,260 @@
+#ifdef ENABLE_GPRS_TESTING
+#include "GprsHandler.h"
+#include "mbed.h"
+#include "config.h"
+#include "UsbComms.h"
+#include "circbuff.h"
+#define TX_GSM P1_27
+#define RX_GSM P1_26
+
+// declare led3 to display GPRS handler state
+extern DigitalOut myled3;
+
+/*
+ * PINPWR to low on Q10 drives 3V3 to Q7, which drives Q5 to ground, which powers VBAT_900, with
+ * either VCC_BUCK or VCC_BAT
+ */
+#define PINPWR                  P1_2
+#define PINONOFF                P1_7
+
+#define REQ_SEND_SMS     0b00000001
+
+#define USB_BUFF_SIZE 256
+
+#define SIM900_SERIAL_TIMEOUT 10000
+
+GprsHandler::GprsHandler(MyTimers * _timer, UsbComms *_usb) : AbstractHandler(_timer)
+{
+    m_serial = new Serial(TX_GSM, RX_GSM);	// create object for UART comms
+    mode = gprs_Start;		// initialise state machine
+
+    m_sim900_pwr = new DigitalOut(PINPWR);		// create pin out for
+    m_sim900_on  = new DigitalOut(PINONOFF);
+    m_reqReg = 0;
+
+    m_usb = _usb;
+    m_rxBuff = new CircBuff(USB_BUFF_SIZE);
+
+    m_atReq = atreq_Test;
+}
+
+GprsHandler::~GprsHandler()
+{
+    // TODO Auto-generated destructor stub
+    delete m_serial;
+    delete m_rxBuff;
+    delete m_sim900_pwr;
+    delete m_sim900_on;
+}
+
+void GprsHandler::run()
+{
+    switch(mode)
+    {
+    case gprs_Start:
+
+        mode = gprs_PowerOff;
+        break;
+
+
+        // POWER HANDLERS
+
+    case gprs_PowerOff:
+        m_sim900_pwr->write(1);				// turn power supply off
+        m_sim900_on->write(1);
+        m_timer->SetTimer(MyTimers::tmr_GprsPower, 500);	// wait to settle
+        mode = gprs_PowerOffWait;
+        break;
+
+    case gprs_PowerOffWait:
+        if (!m_timer->GetTimer(MyTimers::tmr_GprsPower))
+        {
+            mode = gprs_PowerSupplyOn;		// timer has elapsed
+        }
+        break;
+
+    case gprs_PowerSupplyOn:
+        m_sim900_pwr->write(0);		// turn power supply on
+        m_sim900_on->write(0);		// from the ref: "drive the PWRKEY to a low level for 1 second then release."
+
+
+        m_timer->SetTimer(MyTimers::tmr_GprsPower, 1000);	// wait for one second
+        mode = gprs_PowerSupplyOnWait;						// go to wait state
+        break;
+
+    case gprs_PowerSupplyOnWait:
+        if (!m_timer->GetTimer(MyTimers::tmr_GprsPower))
+        {
+            mode = gprs_PowerSwitchOn;		// timer has elapsed
+        }
+        break;
+
+    case gprs_PowerSwitchOn:
+        m_sim900_on->write(1);		// release power key
+        m_timer->SetTimer(MyTimers::tmr_GprsPower, 500);	// wait to settle
+        mode = gprs_PowerSwitchOnWait;
+        break;
+
+    case gprs_PowerSwitchOnWait:
+        if (!m_timer->GetTimer(MyTimers::tmr_GprsPower))
+        {
+            mode = gprs_CheckATReqs;		// timer has elapsed
+        }
+        break;
+
+
+        // REQUEST HANDLERS
+
+    case gprs_CheckATReqs:
+        switch (m_atReq) {
+        case atreq_Test:
+            sprintf((char*)txBuf, "AT\r\n");
+            txBufLen = 4;
+            mode = gprs_PostTx;
+            break;
+
+        case atreq_CheckSMS:
+            sprintf((char*)txBuf, "AT+CMGL=\"ALL\"");
+            txBufLen = 13;
+            mode = gprs_PostTx;
+            break;
+
+        default:
+            m_atReq = atreq_Test;
+        }
+        break;
+
+
+        // TX/RX HANDLERS
+
+    case gprs_PostTx:
+        // use putc, other write functions in serial don't really seem to work
+        for (int i = 0; i < txBufLen; i++) {
+            m_serial->putc(txBuf[i]);
+        }
+
+        // make sure buffer is null terminated before printing to USB
+        txBuf[txBufLen+1] = 0;
+        m_usb->setRequest(UsbComms::usbreq_PrintToTerminalTimestamp, txBuf);
+
+        // clear the buffer
+        txBufLen = 0;
+
+        // set timeout
+        m_timer->SetTimer(MyTimers::tmr_GprsRxTx, SIM900_SERIAL_TIMEOUT);
+
+        // wait for a response
+        mode = gprs_WaitRx;
+        break;
+
+    case gprs_WaitRx:
+        if (m_timer->GetTimer(MyTimers::tmr_GprsRxTx))
+        {
+            // we have not timed out yet
+            // we need a generic rx handler here.
+            while (m_serial->readable())
+            {
+                char ch = m_serial->getc();
+
+                // save this to our rx circular buffer
+                m_rxBuff->putc(ch);
+
+                mode = gprs_CheckRx;
+    			wait(0.1);
+            }
+            // we have not timed out, and have not got anything back yet
+            // keep waiting in this state
+        }
+        else {
+        	m_usb->setRequest(UsbComms::usbreq_PrintToTerminalTimestamp, (char*)"SIM900 TIMEOUT!");
+            mode = gprs_RxTimeout;
+        }
+        break;
+
+    case gprs_CheckRx:
+        if (m_rxBuff->dataAvailable()) {
+
+            // read out
+            unsigned char s[50];
+            uint16_t len = m_rxBuff->read(s, 50);
+
+            // write to USB
+            m_usb->setRequest(UsbComms::usbreq_PrintToTerminalTimestamp, s);
+
+            // process the reply
+            switch(m_atReq) {
+            case atreq_Test:
+                // should have just gotten an ok back
+                bool bOk = false;
+                for (int i = 0; i < (len - 1); i++) {
+                    if ((s[i] == 'O') && (s[i+1] == 'K')) {
+                        bOk = true;
+                    }
+                }
+
+                if (bOk) {
+                    myled3 = 1;
+                    // so we know that comms are definitely OK.
+                    // now check to see what requests need to get fulfilled
+
+                    if (m_reqReg&REQ_SEND_SMS) {
+                        // we want to check what sms is
+                        m_atReq = atreq_SendSMS;
+
+                        m_reqReg &= ~REQ_SEND_SMS;
+                    }
+                    else {
+                        // no requests, but see if there are any received SMSs
+                        m_atReq = atreq_CheckSMS;
+                    }
+                }
+                else {
+                    // did not get the reply we were hoping for.
+                }
+                break;
+
+            default:
+                // todo: handle replies for checking/sending SMSs
+                m_atReq = atreq_Test;
+                break;
+            }
+        }
+        else {
+
+        }
+        m_timer->SetTimer(MyTimers::tmr_GprsRxTx, 2000);
+        // now that we're done here, go check what needs to get sent to the SIM900 next
+        mode = gprs_WaitUntilNextRequest;
+        break;
+        
+    case gprs_WaitUntilNextRequest:
+    	if (!m_timer->GetTimer(MyTimers::tmr_GprsRxTx)) {
+			mode = gprs_CheckATReqs;
+		}
+		break;
+    case gprs_RxTimeout:
+    case gprs_RxError:
+    default:
+        mode = gprs_Start;
+        break;
+
+
+    }
+}
+
+void GprsHandler::setRequest(int request, void *data)
+{
+    m_lastRequest = (request_t)request;
+    switch(request) {
+    case gprsreq_SmsSend:
+        GprsRequest *req = (GprsRequest*)data;
+
+        // make a copy
+        m_lastMessage = *req;     // there are strings, do i have to copy these manually?
+
+        // set the request
+        m_reqReg |= REQ_SEND_SMS;
+        break;
+    }
+}
+#endif