uses pushing box to publish to google spreadsheets with a state machine instead of a while loop

Dependents:   DCS_FINAL_CODE

Fork of GSM_PUSHING_BOX_STATE_MACHINE by DCS_TEAM

Revision:
24:7d2ff444d6d8
Parent:
23:5227fb014aad
Child:
25:9de265c5bb28
--- a/GSMLibrary.cpp	Tue Mar 24 18:39:13 2015 +0000
+++ b/GSMLibrary.cpp	Sat Apr 11 23:21:46 2015 +0000
@@ -1,30 +1,40 @@
+//Libraries
 #include "GSMLibrary.h"
 #include "gsmqueue.h"
 #include <string.h>
 
-#define TIME_CONST .3
-#define SECONDS_TIMEOUT 40
+//Global defines
 #define TIMEOUTLIMIT SECONDS_TIMEOUT/TIME_CONST //$change check with main code this will set up condition fior timeout.
+#define BEGIN_PHOTODIODE_DATA "CLS:"
+#define BEGIN_GPS_DATA "GPS:"
 
-//definition for AT comands
+//Extra defines for transmitter
+#define START_SMS_TRANSMISSION "START"
+#define STOP_SMS_TRANSMISSION "STOP"
+#define GPS_SMS_TRANSMISSION "GPS"
+#define RECEIVER_PHONE_NUMBER "\"+13853357314\""
+#define AT_CMGS "AT+CMGS=" RECEIVER_PHONE_NUMBER
+#define NUM_SIZE 25
+
+//definition for AT comands to send
 #define AT_OK "AT"
 #define AT_CSQ "AT+CSQ" 
 #define AT_CREG "AT+CREG?"
+#define AT_CNMI "AT+CNMI=2,0,0,0,0"
 #define AT_CMGF "AT+CMGF=1"
-#define RECEIVER_PHONE_NUMBER "\"+12083608384\""
-#define AT_CMGS "AT+CMGS=" RECEIVER_PHONE_NUMBER 
-#define MESSAGE_BODY "stress test\32\32"
+#define AT_READ_MSG "AT+CMGL=\"REC UNREAD\"" //make sure device is in txt mode.
+#define AT_DEL_R_MSGS "AT+QMGDA=\"DEL READ\""
 
-
-//Definition for AT repsonses
+//Definition for AT responses
 //Please notice that after ":" the gsm will usually send aditional information
 #define AT_OK_RESPONSE "OK" //Response after sending "AT" message
 #define AT_CSQ_RESPONSE "+CSQ:" //+CSQ: <arg1>,<arg2> where <arg1> is signal strength arg1 = 0-30 where a number below 10 means low signal strength and 99 is not knwn or detectable signal and arg2 is bit error rate form 0-7, 99 will represent error 
 #define AT_CREG_RESPONSE "+CREG:"//+CREG: <arg1>,<arg2> where <arg1> = 0-2(see AT command descriptions), <arg2> =  0-5, 0 not registered to nework and not looking for one. 1 is conected to network, 2 is not conected but searching
+#define AT_CNMI_RESPONSE "OK"
 #define AT_CMGF_RESPONSE "OK"
-#define AT_CMGS_RESPONSE ">"  //Message is written aftersymbol
-#define AT_SENDSMS_RESPONSE ">" // +CMGS: <id> this will include the message id. CMGS ERROR for error and 
-#define AT_SUCCESS_RESPONSE "+CMGS:"
+#define AT_CMGS_RESPONSE ">"  //Received after you give the GSM the phone number. (We mistakenly thought it was received a second time after SMS was sent... this is not true!)
+#define AT_SENDSMS_RESPONSE "+CMGS:" // +CMGS: <id> this will include the message id. CMS ERROR for error.
+#define AT_DEL_R_MSGS_RESPONSE "OK"
 
 //External variables
 extern Serial pc;
@@ -33,184 +43,238 @@
 
 //Internal variables
 gsm_states gsm_current_state = GSM_INITIALIZE;
-char send = 0;
 int timeout_count = 0;
-char gsm_msg[MAX_MSG_SIZE + 1]; //1 extra for Ctrl+Z
+char state_chars[] = "iosntmRPWD";  //init, ok, signalstrength, network, turn off notifications, messagemode, read, phone, writesms, del
+
+//Extras for transmitter
+char send = false;  //if true => we will send something (only if send_enable is true)
+char send_enable = false;   //Sending start and stop commands to GSM via SMS changes this variable
+char undeleted_msgs = true; //At the beginning assume we have undeleted messages
+char gsm_msg[MAX_SMS_LENGTH + 250]; //String storing SMS message to send to GSMMaximum (add 250 length to give leeway)
+char num[NUM_SIZE];   //Temporary string storage to convert numbers
 
 void gsm_tick()
 {
-    if (getGSMIdleBit() || gsm_timeOut() || (send && gsm_current_state == GSM_INITIALIZE))  //question with send...
+
+    if (queueHasResponse() || gsm_timeOut() || gsm_current_state == GSM_INITIALIZE)
     {
-        resetGSMIdleBit();  //reset GSM idle bit
+        gsm_printState();   //&debug
+        printQueue();   //&debug
         gsm_nextStateLogic();   //Next state
         gsm_mealyOutputs(); //Mealy outputs
-        flushQueue();       //Flush the queue
     }
 }
-
-
-
+ 
+void gsm_printState()
+{
+    pc.printf("S:%c;", state_chars[gsm_current_state]);
+}
+ 
 //Advance timeout counter; if timeout, return true
 bool gsm_timeOut()
 {
     if(++timeout_count >= TIMEOUTLIMIT){
-        timeout_count=0; 
-        gsm_current_state = GSM_INITIALIZE;
+        timeout_count = 0; 
+        gsm_reset();
         return true;
     }
     else
         return false;     
 }
 
-//Have the GSM send a message
-void gsm_send_sms(char msg[])
+//Have the GSM send data - L = long, S = short, hh/mm/ss for time, "lat ns" for latitute, "lon we" for longitude
+void gsm_send_data(float L, float Lref, float S, float Sref, int hh, int mm, int ss, float lat, char ns, float lon, char we)
 {
-    send = 1;
-    strcpy(gsm_msg,msg);  //If we need to optimize later we can do that, but this is more robust
-    strcat(gsm_msg,"\x1A");
+    if (!gsm_ready())   //Don't send if gsm not ready
+        return;
+    
+    //Concatenate photodiode data
+    gsm_msg[0] = NULL;
+    strcat(gsm_msg, BEGIN_PHOTODIODE_DATA);
+    snprintf(num, NUM_SIZE, ",%d:%d:%d,", hh, mm, ss);
+    strcat(gsm_msg, num);
+    snprintf(num, NUM_SIZE, "%f,", L);
+    strcat(gsm_msg, num);
+    snprintf(num, NUM_SIZE, "%f,", Lref);
+    strcat(gsm_msg, num);
+    snprintf(num, NUM_SIZE, "%f,", S);
+    strcat(gsm_msg, num);
+    snprintf(num, NUM_SIZE, "%f;\n", Sref);
+    strcat(gsm_msg, num);
+
+    //Concatenate gps data
+    strcat(gsm_msg, BEGIN_GPS_DATA);
+    if (ns != NULL) //If there is a gps fix, ns will be set
+    { 
+        snprintf(num, NUM_SIZE, ",%.4f%c,%.4f%c;", lat, ns, lon, we);
+        strcat(gsm_msg, num);
+    }
+        else strcat(gsm_msg, ",NONE;");
+    
+    send = true;    //Mark that we are currently sending a message
+    strcat(gsm_msg, SMS_END_CHAR);  //Add SMS end char
 }
-
-//Return true if gsm is ready
+ 
+//Return true if gsm is ready to send sms
+//This only occurs if send = false (not currently sending a message) AND gsm received start sequence
 bool gsm_ready()
 {
-    return (send == 0) ? true : false;
+    return ((!send) && send_enable) ? true : false;
 }
-
-//Reset the gsm
+ 
+//Reset the gsm. Currently this only resets the state and whether we are currently sending a message
+//It does not reset send_enable or undeleted_msgs
 void gsm_reset()
 {
+    //If we are in the middle of sending a text message, exit this loop
+    if (gsm_current_state == GSM_AT_CMGS)
+        sendCommand(SMS_ESCAPE_CHAR);
+    
     gsm_current_state = GSM_INITIALIZE;
+    undeleted_msgs = true;
+    send = false;
 }
-
+ 
 //Next state logic -----------------------------------------------------
 void gsm_nextStateLogic()
 {
-    printQueue(); //$debug
-
+    //printQueue(); //$debug
+ 
     switch(gsm_current_state)
     {
         case GSM_INITIALIZE:
-            pc.printf("gsm_initialize state\r\n");//&debug
             timeout_count = 0;
-            if (send)
-                gsm_current_state = GSM_AT_OK;   //unconditional (check it)
+            gsm_current_state = GSM_AT_OK;   //unconditional (check it)
             break;
         case GSM_AT_OK:
-            pc.printf("inside AT_OK state\r\n");//&debug
-            if (findInQueue(AT_OK_RESPONSE))
+            if (findInQueue(AT_OK_RESPONSE, true))
                 gsm_current_state = GSM_AT_CSQ;
             break;
         case GSM_AT_CSQ:
-            pc.printf("inside AT_CSQ state \r\n");//&debug
-            if(findInQueue(AT_CSQ_RESPONSE))
+            if(findInQueue(AT_CSQ_RESPONSE, true))
                 gsm_current_state = GSM_AT_CREG;
             break;
         case GSM_AT_CREG:
-            pc.printf("gsm_creg state\r\n");//&debug
-            if(findInQueue(AT_CREG_RESPONSE))
+            if(findInQueue(AT_CREG_RESPONSE, true))
             {
-                pc.printf("creg parse Int1: %d\r\n",parseInt());//&debug
-                int q = parseInt();
-                pc.printf("creg parse Int2: %d\r\n",q);//&debug
-                if(q == 1)
-                    gsm_current_state = GSM_AT_CMGF;
+                parseInt();
+                if(parseInt() == 1)
+                    gsm_current_state = GSM_AT_CNMI;
             } 
             break;
+        case GSM_AT_CNMI:
+            if(findInQueue(AT_CNMI_RESPONSE, true))
+                gsm_current_state = GSM_AT_CMGF;
+            break;  
         case GSM_AT_CMGF:
-            pc.printf("gsm_cmgf state\r\n");//&debug
-            if(findInQueue(AT_CMGF_RESPONSE))
-                gsm_current_state = GSM_AT_CMGS;
+            if(findInQueue(AT_CMGF_RESPONSE, true))
+                gsm_current_state = GSM_READ_MSG;
+            break;
+        case GSM_READ_MSG:
+            if(send_enable) //Check if we need to stop transmission of SMS
+            {
+                if(findInQueue(STOP_SMS_TRANSMISSION, true))  //Always stop sending if stop sequence received by SMS
+                {
+                    undeleted_msgs = true;
+                    send_enable = false;    //Set send_enable to indicate we will stop sending SMS
+                }
+                else if (send) //Only continue sending if we didn't find stop sequence AND user requested that we send sms
+                    gsm_current_state = GSM_AT_CMGS;    //Continue sending SMS (change state accordingly)
+                //Implicit: otherwise we will continue checking text messages in this state.
+            }
+            else
+            {
+                if(findInQueue(START_SMS_TRANSMISSION, true))
+                {
+                    undeleted_msgs = true;
+                    send_enable = true;
+                    if (send) //Only continue sending if we found start sequence AND user requested that we send sms
+                        gsm_current_state = GSM_AT_CMGS;    //Start sending SMS (change state accordingly)
+                }
+            }
             break;
         case GSM_AT_CMGS:
-            pc.printf("gsm_cmgs state\r\n");//&debug
-            if(findInQueue(AT_CMGS_RESPONSE))
+            if(findInQueue(AT_CMGS_RESPONSE, true))
                 gsm_current_state = GSM_AT_SENDSMS;
             break;
         case GSM_AT_SENDSMS:
-            pc.printf("gsm_send_sms state\r\n");//&debug
-            if(findInQueue(AT_SENDSMS_RESPONSE))    //>
+            if(findInQueue(AT_SENDSMS_RESPONSE, true))
             {
-                //Check if the "successfully sent" has also already been received (most likely
-                //this won't be the case, but if it has been >500 ms there's a possibility
-                //we've received both the messages during the same call to our state machine.)
-                if(findInQueue(AT_SUCCESS_RESPONSE))
+                pc.printf("(Wid%i)",parseInt());//&debug
+                timeout_count = 0;  //Reset timeout count
+                send = 0;   //Indicate we are done sending the text message
+                if (undeleted_msgs) //Check if we need to delete read messages
+                    gsm_current_state = GSM_DEL_R_MSGS; //Only delete messages if there are no unread messages
+                else
                 {
-                    pc.printf("Message SENT! msgID: %iY\r\n",parseInt());//&debug
-                    send = 0;
-                    gsm_current_state = GSM_INITIALIZE; //Skip success state (we've received both)
+                    gsm_current_state = GSM_READ_MSG;   //Otherwise read text messages again
+                    pc.printf("(Dnone)");//&debug 
                 }
-                else
-                    gsm_current_state = GSM_SUCCESS;    //Go to success state
             }
             else
-                gsm_current_state = GSM_AT_CMGS;        //Try resending the message (until timeout)
+            {
+                pc.printf("(Werr)"); //&debug
+                gsm_current_state = GSM_AT_CMGS;    //If failed, try resending the message (i.e. continue until timeout)
+            }
             break;
-        case GSM_SUCCESS:
-            pc.printf("gsm_success state\r\n");//&debug
-            if(findInQueue(AT_SUCCESS_RESPONSE))
+        case GSM_DEL_R_MSGS:
+            if (findInQueue(AT_DEL_R_MSGS_RESPONSE, true))
             {
-                pc.printf("Message SENT! msgID: %iY\r\n",parseInt());//&debug
+                undeleted_msgs = false;
+                pc.printf("(Dsucc)");   //&debug
             }
-            send = 0;
-            gsm_current_state = GSM_INITIALIZE;     //We will restart regardless of whether it worked
+            else
+                pc.printf("(Derr)");    //&debug
+            gsm_current_state = GSM_READ_MSG;
             break;
         default:
-            pc.printf("This is a state error");
+            pc.printf("This is a state error\r\n");
     }
 }
-
+ 
 //Mealy output logic ------------------------------------------------------
 void gsm_mealyOutputs()
 {
     switch(gsm_current_state)
     {
         case GSM_INITIALIZE:
-            pc.printf("No Mealy initialize state output\r\n");//&debug
             break;
         case GSM_AT_OK:
-            pc.printf("sending AT_OK\r\n");//&debug
-            gsm.puts(AT_OK);
-            gsm.puts("\r\n"); 
+            sendCommand(AT_OK);
             break;
         case GSM_AT_CSQ:
-            pc.printf("sending AT_CSQ\r\n");//&debug
-            gsm.puts(AT_CSQ);
-            gsm.puts("\r\n"); 
+            sendCommand(AT_CSQ);
             break;
         case GSM_AT_CREG:
-            pc.printf("sending AT_CREG\r\n");//&debug
-            gsm.puts(AT_CREG);
-            gsm.puts("\r\n"); 
+            sendCommand(AT_CREG);
             break;
-        case GSM_AT_CMGF:   
-            pc.printf("sending AT_CMGF\r\n");//&debug
-            gsm.puts(AT_CMGF);
-            gsm.puts("\r\n"); 
-            break;
+        case GSM_AT_CNMI:
+            sendCommand(AT_CNMI);
+            break; 
+        case GSM_AT_CMGF:
+            sendCommand(AT_CMGF);
+            break;         
+        case GSM_READ_MSG:
+            sendCommand(AT_READ_MSG);
+            break; 
         case GSM_AT_CMGS:   
-            pc.printf("sending AT_CMGS\r\n");//&debug
-            gsm.puts(AT_CMGS);
-            gsm.puts("\r\n"); 
+            sendCommand(AT_CMGS);
             break;
         case GSM_AT_SENDSMS:
-            pc.printf("sending message\r\n");//&debug
-            gsm.puts(gsm_msg); //substitute char included
-            gsm.puts("\r\n"); 
+            sendCommand(gsm_msg); //end char included
             break;
-        case GSM_SUCCESS:
-            pc.printf("No Mealy success state output\r\n");//&debug 
+        case GSM_DEL_R_MSGS:
+            sendCommand(AT_DEL_R_MSGS);
             break;
         default:
-            pc.printf("This is a state error");
+            pc.printf("This is a state error\r\n");
     }
 }
-
-
 //Initialize the GSM
 void gsm_initialize(){  
       SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; //enabling dmamux clock
       SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;  // enebaling dma clock
-      pc.printf("initializing tregisters...!\r\n");
+      pc.printf("initializing DMA...\r\n");
      // control register mux, enabling uart3 receive        
      DMAMUX_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(8); 
      
@@ -253,11 +317,11 @@
     //activate p fifo   
     UART_PFIFO_REG(UART3) |= UART_PFIFO_RXFE_MASK; //RXFE and buffer size of 1 word
     queueInit();
-    pc.printf("Initialization done...\n\r");
+    pc.printf("done...\n\r");
 }
-
-
-
+ 
+ 
+ 
 //initialization debuging purposes
 void print_registers() {