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: gsmqueue.cpp
- Revision:
- 24:7d2ff444d6d8
- Parent:
- 13:9ac5ff131214
- Child:
- 27:fe1c7eaf5b88
--- a/gsmqueue.cpp Tue Mar 24 18:39:13 2015 +0000 +++ b/gsmqueue.cpp Sat Apr 11 23:21:46 2015 +0000 @@ -1,44 +1,112 @@ #include "gsmqueue.h" -#include "mbed.h" -/* queue.cpp +#include "GSMLibrary.h" +#include <string.h> + +/* gsmqueue.cpp * Contains functions to read from the DMA buffer in a queue fashion */ + +#define LAST_UNPRINTABLE_CHAR 31 + extern Serial pc; +extern Serial gsm; char buffer[BUFFER_LENGTH]; char* queueHead; +char* queueHeadExp; //Expected location of queueHead after gsm.puts() finishes executing -//Initialize variables +//Public functions ------------------------------------------------------------------------------ +//Initialize variables void queueInit() { - //The buffer is initialized in init.cpp + //The buffer is initialized in GSMLibrary.cpp queueHead = QUEUETAIL; + queueHeadExp = queueHead; +} + +//Send gsm a command (don't forget to flush queue and increment past QUEUETAIL +//by the number of characters send) +void sendCommand(char* sPtr) +{ + flushQueue(); //This "removes" any characters remaining in the queue + int size = strlen(sPtr); + if (size > 0 && size <= MAX_SMS_LENGTH) //Don't send if too long or negative size + { + //Send the command + gsm.puts(sPtr); + //The increment part below: Effectively "removes" characters we just sent from the buffer + // by advancing queueHead by size - 1, or size + 2 + // size - 1 is because SMS_END_CHAR does not show up on the DMA. + // size + 2 is for "\n\r" that gets transmitted after we send the command + if (sPtr[size - 1] == SMS_END_CHAR[0]) + { + queueHeadExp = incrementIndex(queueHead, size - 1); + // Don't add "\n" because already included in string (this is when we are sending a message) + } + else + { + queueHeadExp = incrementIndex(queueHead, size + 2); + gsm.puts("\n"); //make there be a \r\n in what we send (this is perfect.) + //Why not "\r\n"? Previously we had thought the extra \r was added due to \r\n coming + // through the command line: scanf only removed the \n as whitespace. However, upon + // further investigation we realized this behavior occurs because the gsm.puts function + // adds a "\r" at the end of your string, independent of whether it was already present + // in the string you sent to it. (Except if you only send "\n", in which case it does + // not follow it with a "\r".) Thus we need to simply add "\n" because the "\r" is + // already added by the gsm.puts command. + } + pc.printf("C:%s\r\n", sPtr); //&debug - to know we have sent this message + } + else //Else: error message + { + pc.printf("Error: AT command exceeded maximum length"); + gsm_reset(); + } +} + +//Return true if GSM has sent complete response already +//If GSM is idle and queue is not empty, return true +//If the last command was successfully sent, advance queueHead to queueHeadExp +bool queueHasResponse() +{ + if (getGSMIdleBit()) + { //If tail has advanced past the end of our last sent command, queue has new data + int dataReceived = queueSize(QUEUETAIL) - queueSize(queueHeadExp); + if (dataReceived >= 0) + queueHead = queueHeadExp; //Upon equality, last command was successfully sent + return (dataReceived > 0); //Data received only if characters present beyond "equality" point + } + else + return false; //Still busy; wait until transmission ended } //Find an occurrence of the given string in the buffer. -//Only advance queueHead until a matching string is found. +//If advanceQueueHead is true, advance queueHead just until a matching string is found. //The given string terminates in NULL (\0) -bool findInQueue(char* str) +bool findInQueue(char* str, bool advanceQueueHead) { //Check that string to find is not empty if (*str == NULL) return false; - while (queueHead != QUEUETAIL) + char* head = queueHead; + while (head != QUEUETAIL) { //Does the character match the begin char? - if (*queueHead == *str){ + if (*head == *str){ //Check the remaining characters char* sPos = str; char* qPos = 0; - for (qPos = queueHead; qPos != QUEUETAIL; qPos = incrementIndex(qPos)){ + for (qPos = head; qPos != QUEUETAIL; qPos = incrementIndex(qPos)){ //Compare the next char if (*qPos == *sPos) { ++sPos; //Increment index (prefix incrementation). - if (*sPos == NULL) //If finished, update queueHead, return true. + if (*sPos == NULL) //If finished, update head, return true. { - queueHead = incrementIndex(qPos); + head = incrementIndex(qPos); + if (advanceQueueHead) + queueHead = head; return true; } } @@ -47,49 +115,14 @@ } } //Increment queue index for next iteration - queueHead = incrementIndex(queueHead); + head = incrementIndex(head); } - //We never finished, so return false + //We never succeeded, so return false + if (advanceQueueHead) + queueHead = head; return false; } -//Increment queue index by 1 -char* incrementIndex(char* pointerToIncrement) -{ - if((pointerToIncrement + 1) < (buffer + BUFFER_LENGTH)) - return (pointerToIncrement + 1); - else - return buffer; -} - -//clear queue -void flushQueue() -{ - queueHead = QUEUETAIL; -} - -//$debug - print queue elements -void printQueue() -{ - char* qPos = queueHead; - pc.printf("Queue:"); - while (qPos != QUEUETAIL) - { - //Print the current character - if (*qPos == '\n') - pc.printf("\\n"); - else if (*qPos == '\r') - pc.printf("\\r"); - else - pc.printf("%C",*qPos); - - - //Increment index - qPos = incrementIndex(qPos); - } - pc.printf("\n\r"); -} - //Parse through characters until first integer is found //Advance qHead until you reach the next non-numeric character //Does not read negative integers; returns -1 if unsuccessful @@ -116,11 +149,77 @@ return val; } +//$debug - print queue elements +void printQueue() +{ + char* qPos = queueHead; + pc.printf("Q:"); + while (qPos != QUEUETAIL) + { + //Print the current character + if (*qPos <= LAST_UNPRINTABLE_CHAR) + { + if (*qPos == '\n') + pc.printf("\\n"); + else if (*qPos == '\r') + pc.printf("\\r"); + else + pc.printf("\0%x", *qPos); + } + else + pc.printf("%C",*qPos); + + + //Increment index + qPos = incrementIndex(qPos); + } +} + + +//Internal functions --------------------------------------------------------------------------------- + +//Get the GSM DMA idle bit (if 1, indicates we already received a response) +bool getGSMIdleBit() +{ + return (UART_S1_IDLE_MASK & UART_S1_REG(UART3)) >> UART_S1_IDLE_SHIFT; +} + //Returns true if the character is numeric bool isNumeric(char* qPos) { return ('0' <= *qPos && *qPos <= '9'); } + +//Increment queue position by 1 (Note: this function is only used by gsmqueue.cpp) +char* incrementIndex(char* pointerToIncrement) +{ + if((pointerToIncrement + 1) < (buffer + BUFFER_LENGTH)) + return (pointerToIncrement + 1); + else + return buffer; +} + +//Increment queue position by n (Note: this function is only used by gsmqueue.cpp) +char* incrementIndex(char* pointerToIncrement, int n) +{ + int initialIndex = pointerToIncrement - buffer; + int incrementedIndex = (initialIndex + n) % BUFFER_LENGTH; + return incrementedIndex + buffer; +} + +//Get size of the queue from reference point of tail parameter +int queueSize(char* tail) +{ + int headDiff = queueHead - buffer; + int tailDiff = tail - buffer; + return (tailDiff + BUFFER_LENGTH - headDiff) % BUFFER_LENGTH; +} + +//Clear queue (Note: this function is only used by gsmqueue.cpp) +void flushQueue() +{ + queueHead = QUEUETAIL; +} //Reset the GSM DMA idle bit to 0 void resetGSMIdleBit() @@ -128,8 +227,3 @@ UART_S1_REG(UART3) &= ~UART_S1_IDLE_MASK; } -//Get the GSM DMA idle bit (if 1, indicates we already received a response) -bool getGSMIdleBit() -{ - return (UART_S1_IDLE_MASK & UART_S1_REG(UART3)) >> UART_S1_IDLE_SHIFT; -} \ No newline at end of file