uses pushing box to publish to google spreadsheets with a state machine instead of a while loop
Fork of GSM_PUSHING_BOX_STATE_MACHINE by
Diff: GSMLibrary.cpp
- Revision:
- 29:bc5f53f2922a
- Parent:
- 28:81f1c8bd3299
- Child:
- 30:421aae087064
diff -r 81f1c8bd3299 -r bc5f53f2922a GSMLibrary.cpp --- a/GSMLibrary.cpp Thu Apr 23 02:06:55 2015 +0000 +++ b/GSMLibrary.cpp Sat Apr 25 15:39:00 2015 +0000 @@ -4,28 +4,28 @@ #include <string.h> //Global defines -#define TIMEOUTLIMIT SECONDS_TIMEOUT/TIME_CONST //$change check with main code this will set up condition fior timeout. +#define TIMEOUTLIMIT SECONDS_TIMEOUT/TIME_CONST //Defines how many "ticks" of the GSM will constitute "timeout" of our "watchdog timer" //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 -#define BEGIN_SENSOR_DATA "$" +#define AT_CMGS "AT+CMGS=" RECEIVER_PHONE_NUMBER //Begin sending SMS with this send command and the phone number +#define NUM_SIZE 25 //Size of a temporary variable to help with concatenation of strings +#define BEGIN_SENSOR_DATA "$" //$ and % are parsed by using regex by the GUI for the receiver and indicate the start and end of data received #define END_SENSOR_DATA "%" -//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 AT_READ_MSG "AT+CMGL=\"REC UNREAD\"" //make sure device is in txt mode. -#define AT_DEL_R_MSGS "AT+QMGDA=\"DEL READ\"" +//Define AT commands to send +#define AT_OK "AT" //Ask GSM if everything is 'ok' +#define AT_CSQ "AT+CSQ" //Check signal strength +#define AT_CREG "AT+CREG?" //Check if GSM is registered on cellular network +#define AT_CNMI "AT+CNMI=2,0,0,0,0" //Turn off the notification that is normally received when text messages are received +#define AT_CMGF "AT+CMGF=1" //Turn on "text message mode" so we can characters (rather than PDU mode in which you send bytes) +#define AT_READ_MSG "AT+CMGL=\"REC UNREAD\"" //Read received messages that have not yet been read +#define AT_DEL_R_MSGS "AT+QMGDA=\"DEL READ\"" //Delete read messages -//Definition for AT responses +//Define expected responses for AT commands //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 @@ -33,38 +33,40 @@ #define AT_CNMI_RESPONSE "OK" #define AT_CMGF_RESPONSE "OK" #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_SENDSMS_RESPONSE "+CMGS:" // +CMGS: <id> this will include the message id, or CMS ERROR for error. #define AT_DEL_R_MSGS_RESPONSE "OK" //External variables -extern Serial pc; -extern Serial gsm; -extern uint8_t buffer[BUFFER_LENGTH];//buffer storing char +extern Serial pc; //To print output to computer +extern Serial gsm; //To communicate with GSM +extern uint8_t buffer[BUFFER_LENGTH]; //DMA queue //Internal variables gsm_states gsm_current_state = GSM_INITIALIZE; int timeout_count = 0; -char state_chars[] = "iosntmRPWD"; //init, ok, signalstrength, network, turn off notifications, messagemode, read, phone, writesms, del +char state_chars[] = "iosntmRPWD"; //For debugging - 1 char to represent each state: 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 send_enable = false; //Sending start and stop commands to GSM via SMS changes this variable. If true, we will send SMS messages of our data received 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 +char gsm_msg[MAX_SMS_LENGTH + 250]; //String storing SMS message that will be sent (add 250 length to give leeway) +char num[NUM_SIZE]; //Temporary string storage to help with concatenation of strings +//"Tick" of the GSM (i.e. this is a state machine) void gsm_tick() { - + //Don't do anything, unless i) we received a response from the GSM, ii) the watchdog timer timed out, or iii) or we are initializing the GSM if (queueHasResponse() || gsm_timeOut() || gsm_current_state == GSM_INITIALIZE) { //gsm_printState(); //&debug //printQueue(); //&debug gsm_nextStateLogic(); //Next state - gsm_mealyOutputs(); //Mealy outputs + gsm_mealyOutputs(); //Mealy outputs. This state machine is a little different because Mealy outputs come after the next state logic } } - + +//Prints the current state. To save time printing, simply prints 1 character to indicate the current state. void gsm_printState() { pc.printf("S:%c;", state_chars[gsm_current_state]); @@ -99,14 +101,14 @@ strcat(gsm_msg, num); snprintf(num, NUM_SIZE, "%f,", Sref); strcat(gsm_msg, num); - snprintf(num, NUM_SIZE, "%d:%d:%d,", hh, mm, ss); + snprintf(num, NUM_SIZE, "%d:%d:%d,", hh, mm, ss); //If there is no data from GPS, the time will just be "0:0:0" (that is okay) strcat(gsm_msg, num); - if (ns != NULL) //If there is a gps fix, ns will be set + if (ns != NULL) //If there is a gps fix (i.e. the gps has data on our location), ns will be set { - snprintf(num, NUM_SIZE, "%.4f,%.4f", (ns == 'N') ? lat : -lat, (we == 'E') ? lon : -lon); + snprintf(num, NUM_SIZE, "%.4f,%.4f", (ns == 'N') ? lat : -lat, (we == 'E') ? lon : -lon); //Use + or - rather than N/S, E/W strcat(gsm_msg, num); } - else strcat(gsm_msg, "0,0"); + else strcat(gsm_msg, "0,0"); //Otherwise just send 0's for latitude and longitude strcat(gsm_msg, END_SENSOR_DATA); send = true; //Mark that we are currently sending a message @@ -120,11 +122,11 @@ return ((!send) && send_enable) ? true : false; } -//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 +//Reset the gsm. Currently this only resets the state, whether we are currently sending a message, and whether there are messages to delete. +//It does not reset send_enable void gsm_reset() { - //If we are in the middle of sending a text message, exit this loop + //If we are in the middle of sending a text message, we need to "escape" out of this mode by sending the escape character if (gsm_current_state == GSM_AT_CMGS) sendCommand(SMS_ESCAPE_CHAR); @@ -134,13 +136,17 @@ } //Next state logic ----------------------------------------------------- +//Note how each state (except init) checks the response received to make sure +//GSM has properly executed the command. If the response is correct, it changes +//the state so that the next command will be sent in the gsm_mealyOutputs function +//below. void gsm_nextStateLogic() { switch(gsm_current_state) { case GSM_INITIALIZE: - timeout_count = 0; - gsm_current_state = GSM_AT_OK; //unconditional (check it) + timeout_count = 0; //No AT commands have been sent: this will send the first one + gsm_current_state = GSM_AT_OK; break; case GSM_AT_OK: if (findInQueue(AT_OK_RESPONSE, true)) @@ -153,7 +159,7 @@ case GSM_AT_CREG: if(findInQueue(AT_CREG_RESPONSE, true)) { - parseInt(); + parseInt(); //After the CREG response we receive two integers. The second should be '1' (see AT_CREG_RESPONSE #define) if(parseInt() == 1) gsm_current_state = GSM_AT_CNMI; } @@ -167,7 +173,7 @@ gsm_current_state = GSM_READ_MSG; break; case GSM_READ_MSG: - if(send_enable) //Check if we need to stop transmission of SMS + if(send_enable) //If we are currently sending SMS, check if we need to stop transmission of SMS { if(findInQueue(STOP_SMS_TRANSMISSION, true)) //Always stop sending if stop sequence received by SMS { @@ -178,13 +184,13 @@ gsm_current_state = GSM_AT_CMGS; //Continue sending SMS (change state accordingly) //Implicit: otherwise we will continue checking text messages in this state. } - else + else //If we are not yet sending SMS, check if we need to start transmission of SMS { 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 + send_enable = true; //Now we are in send SMS mode: whenever 'send' variable is set to true we will send an SMS + if (send) //Only begin sending a new SMS if user requested that we send SMS (i.e. there is data to send) gsm_current_state = GSM_AT_CMGS; //Start sending SMS (change state accordingly) } } @@ -198,12 +204,12 @@ { //pc.printf("(Wid%i)",parseInt());//&debug timeout_count = 0; //Reset timeout count - send = 0; //Indicate we are done sending the text message + send = false; //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 + gsm_current_state = GSM_DEL_R_MSGS; //Only delete messages if there are unread messages else { - gsm_current_state = GSM_READ_MSG; //Otherwise read text messages again + gsm_current_state = GSM_READ_MSG; //Otherwise skip the delete messages state; go read text messages again //pc.printf("(Dnone)");//&debug } } @@ -266,13 +272,14 @@ //pc.printf("This is a state error\r\n"); } } + //Initialize the GSM void gsm_initialize(){ - wait(2.3); + wait(2.3); //Wait for the GSM to turn on properly before doing this initialization SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; //enabling dmamux clock SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; // enebaling dma clock //pc.printf("initializing DMA...\r\n"); - // control register mux, enabling uart3 receive + // control register mux, enabling uart3 receive DMAMUX_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(8); // Enable request signal for channel 0 @@ -281,9 +288,10 @@ // select round-robin arbitration priority DMA_CR |= DMA_CR_ERCA_MASK; - //enabled error interrupt for DMA0 - //DMA_EEI = DMA_EEI_EEI0_MASK ; - //Addres for buffer + //enable error interrupt for DMA0 (commented out because we won't use interrupts for our implementation) + //DMA_EEI = DMA_EEI_EEI0_MASK; + + //Address for buffer DMA_TCD0_SADDR = (uint32_t) &UART_D_REG(UART3_BASE_PTR); DMA_TCD0_DADDR = (uint32_t) buffer; // Set an offset for source and destination address @@ -308,21 +316,18 @@ // enable interrupt call at end of major loop DMA_TCD0_CSR |= DMA_CSR_INTMAJOR_MASK; - //Activate dma trasnfer rx interrupt + //Activate dma transfer rx interrupt UART_C2_REG(UART3) |= UART_C2_RIE_MASK; UART_C5_REG(UART3) |= UART_C5_RDMAS_MASK | UART_C5_ILDMAS_MASK | UART_C5_LBKDDMAS_MASK; - //activate p fifo + //activate p fifo register UART_PFIFO_REG(UART3) |= UART_PFIFO_RXFE_MASK; //RXFE and buffer size of 1 word queueInit(); //pc.printf("done...\n\r"); } - - -//initialization debuging purposes -void print_registers() { - - +//For debugging: print registers related to DMA and UART setup +void print_registers() +{ pc.printf("\n\rDMA REGISTERS\n\r"); pc.printf("DMA_MUX: 0x%08x\r\n",DMAMUX_CHCFG0); pc.printf("SADDR0: 0x%08x\r\n",DMA_TCD0_SADDR); @@ -367,5 +372,4 @@ pc.printf("UART_TCFIFO_REG: %08x\r\n",UART_TCFIFO_REG(UART3)); pc.printf("UART_RWFIFO_REG: %08x\r\n",UART_RWFIFO_REG(UART3)); pc.printf("UART_RCFIFO_REG: %08x\r\n",UART_RCFIFO_REG(UART3)); - -} \ No newline at end of file +}