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
gsmqueue.cpp
- Committer:
- DeWayneDennis
- Date:
- 2015-11-06
- Revision:
- 33:2ae9a4eb6433
- Parent:
- 32:424896b5adbe
File content as of revision 33:2ae9a4eb6433:
#include "gsmqueue.h" #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 //External variables extern Serial pc; //Print data to serial connection with computer //Serial gsm(D3,D2); //UART connection with GSM //Internal variables for a queue (wrap-around implementation) //Note that the DMA (direct memory access) stores data in this queue. Therefore, QUEUETAIL is incremented //by the DMA and we only read its value. Our queue's purpose is to read data communicated to us //by the GSM without having to consume processor cycles. Unfortunately when we write data to the Serial //port, the DMA will still write it to the buffer. For this reason, the sendCommand() function counts //the number of characters we send over UART so we can ignore those characters in the queue. char buffer[BUFFER_LENGTH]; //Stores the characters in the queue char* queueHead; //Queue head - marks where to read from next char* queueHeadExp; //Expected location of queueHead after gsm.puts() finishes executing //Public functions ------------------------------------------------------------------------------ //Initialize variables void queueInit() { //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. //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 advanceQueueHead) { //Check that string to find is not empty if (*str == NULL) return false; char* head = queueHead; while (head != QUEUETAIL) { //Does the character match the begin char? if (*head == *str){ //Check the remaining characters char* sPos = str; char* qPos = 0; 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 head, return true. { head = incrementIndex(qPos); if (advanceQueueHead) queueHead = head; return true; } } else //Not equal, so exit for loop and try again at a different location break; } } //Increment queue index for next iteration head = incrementIndex(head); } //We never succeeded, so return false if (advanceQueueHead) queueHead = head; return false; } //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 int parseInt() { //Check if queue is empty first if (queueHead == QUEUETAIL) return -1; //Advance to first numeric character while (!isNumeric(queueHead)) { queueHead = incrementIndex(queueHead); if (queueHead == QUEUETAIL) return -1; } //Continue until first non-numeric character int val = 0; while (queueHead != QUEUETAIL && isNumeric(queueHead)) { val *= 10; val += (int)(*queueHead - '0'); queueHead = incrementIndex(queueHead); } 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; }