Based on https://developer.mbed.org/users/jbaker66/notebook/adafruit-fona-800-minigsm/

Dependents:   Smart_Car_Seat_v1

Files at this revision

API Documentation at this revision

Comitter:
jd0205
Date:
Wed May 03 21:05:54 2017 +0000
Commit message:
personal changes;

Changed in this revision

Adafruit_FONA.cpp Show annotated file Show diff for this revision Revisions of this file
Adafruit_FONA.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 58ff0234d7bb Adafruit_FONA.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_FONA.cpp	Wed May 03 21:05:54 2017 +0000
@@ -0,0 +1,1447 @@
+/***************************************************
+  This is a library for our Adafruit FONA Cellular Module
+
+  Designed specifically to work with the Adafruit FONA
+  ----> http://www.adafruit.com/products/1946
+  ----> http://www.adafruit.com/products/1963
+
+  These displays use TTL Serial to communicate, 2 pins are required to
+  interface
+  Adafruit invests time and resources providing this open source code,
+  please support Adafruit and open-source hardware by purchasing
+  products from Adafruit!
+
+  Written by Limor Fried/Ladyada for Adafruit Industries.
+  BSD license, all text above must be included in any redistribution
+ ****************************************************/
+ 
+ /*
+  *  Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768
+  */
+#include <algorithm>
+#include "Adafruit_FONA.h"
+
+#define HIGH 1
+#define LOW 0
+
+/*
+Notes George is taking:
+sendCheckReply returns a boolean where its true when FONA responds with the string of its second input
+
+*/
+
+
+bool Adafruit_FONA::begin(int baudrate) {
+    mySerial.baud(baudrate); //set the baud rate of the fona serial connection
+    mySerial.attach(this, &Adafruit_FONA::onSerialDataReceived, Serial::RxIrq); //attached onSerialDataReceived as Serial receive interrupt
+    
+    // INIT Reboot process
+    _rstpin = HIGH;
+    wait_ms(10);
+    _rstpin = LOW;
+    wait_ms(100);
+    _rstpin = HIGH;
+    
+    // give 3 seconds to reboot
+    wait_ms(3000);
+    
+    // flushes the serial port
+    while (readable()) getc();
+    
+    // Make sure FONA is alive
+    sendCheckReply("AT", "OK");
+    wait_ms(100);
+    sendCheckReply("AT", "OK");
+    wait_ms(100);
+    sendCheckReply("AT", "OK");
+    wait_ms(100);
+    
+    // turn off Echo!
+    sendCheckReply("ATE0", "OK");
+    wait_ms(100);
+    
+    // Just checks if the FONA even responds, if it doesnt, then return false
+    if (! sendCheckReply("ATE0", "OK")) {
+        return false;
+    }
+    
+    return true;
+}
+
+void Adafruit_FONA::setEventListener(EventListener *eventListener) {
+    this->eventListener = eventListener;
+}
+
+/********* Stream ********************************************/
+
+int Adafruit_FONA::_putc(int value) {
+    return mySerial.putc(value);
+}
+
+int Adafruit_FONA::_getc() {
+    __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
+    
+    // Wait for data if the buffer is empty
+    if (isRxBufferEmpty()) {
+        __enable_irq(); // End Critical Section - need to allow rx interrupt to get new characters for buffer
+        
+        while(isRxBufferEmpty());
+        
+        __disable_irq(); // Start Critical Section - don't interrupt while changing global buffer variables
+    }
+    
+    int data = rxBuffer[rxBufferOutIndex];
+    incrementRxBufferOutIndex();
+    
+    __enable_irq(); // End Critical Section
+    
+    return data;
+}
+
+int Adafruit_FONA::readable() {
+    return !isRxBufferEmpty();
+}
+
+void Adafruit_FONA::onSerialDataReceived() {
+    while (mySerial.readable() && !isRxBufferFull()) {
+        int data = mySerial.getc();
+        rxBuffer[rxBufferInIndex] = data;
+        
+        //
+        // Analyze the received data in order to detect events like RING or NO CARRIER
+        //
+        
+        // Copy the data in the current line
+        if (currentReceivedLineSize < RX_BUFFER_SIZE && data != '\r' && data != '\n') {
+            currentReceivedLine[currentReceivedLineSize] = (char) data;
+            currentReceivedLineSize++;
+        }
+        
+        // Check if the line is complete
+        if (data == '\n') {
+            currentReceivedLine[currentReceivedLineSize] = 0;
+            
+            if (eventListener != NULL) {
+                // Check if we have a special event
+                if (strcmp(currentReceivedLine, "RING") == 0) {
+                    eventListener->onRing();
+                } else if (strcmp(currentReceivedLine, "NO CARRIER") == 0) {
+                    eventListener->onNoCarrier();
+                }
+            }
+            
+            currentReceivedLineSize = 0;
+        }
+        
+        incrementRxBufferInIndex();
+    }
+}
+
+/********* Real Time Clock ********************************************/
+
+bool Adafruit_FONA::enableRTC(uint8_t i) {
+    if (! sendCheckReply("AT+CLTS=", i, "OK")) 
+        return false;
+    return sendCheckReply("AT&W", "OK");
+}
+
+/********* BATTERY & ADC ********************************************/
+
+/* returns value in mV (uint16_t) */
+bool Adafruit_FONA::getBattVoltage(uint16_t *v) {
+    return sendParseReply("AT+CBC", "+CBC: ", v, ',', 2);
+}
+
+/* returns the percentage charge of battery as reported by sim800 */
+bool Adafruit_FONA::getBattPercent(uint16_t *p) {
+    return sendParseReply("AT+CBC", "+CBC: ", p, ',', 1);
+}
+
+bool Adafruit_FONA::getADCVoltage(uint16_t *v) {
+    return sendParseReply("AT+CADC?", "+CADC: 1,", v);
+}
+
+/********* SIM ***********************************************************/
+
+bool Adafruit_FONA::unlockSIM(char *pin)
+{
+    char sendbuff[14] = "AT+CPIN=";
+    sendbuff[8] = pin[0];
+    sendbuff[9] = pin[1];
+    sendbuff[10] = pin[2];
+    sendbuff[11] = pin[3];
+    sendbuff[12] = NULL;
+    
+    return sendCheckReply(sendbuff, "OK");
+}
+
+uint8_t Adafruit_FONA::getSIMCCID(char *ccid) {
+    getReply("AT+CCID");
+    // up to 20 chars
+    strncpy(ccid, replybuffer, 20);
+    ccid[20] = 0;
+    
+    readline(); // eat 'OK'
+    
+    return strlen(ccid);
+}
+
+/********* IMEI **********************************************************/
+
+uint8_t Adafruit_FONA::getIMEI(char *imei) {
+    getReply("AT+GSN");
+    
+    // up to 15 chars
+    strncpy(imei, replybuffer, 15);
+    imei[15] = 0;
+    
+    readline(); // eat 'OK'
+    
+    return strlen(imei);
+}
+
+/********* NETWORK *******************************************************/
+
+uint8_t Adafruit_FONA::getNetworkStatus(void) {
+    uint16_t status;
+    
+    if (! sendParseReply("AT+CREG?", "+CREG: ", &status, ',', 1)) return 0;
+    
+    return status;
+}
+
+
+uint8_t Adafruit_FONA::getRSSI(void) {
+    uint16_t reply;
+    
+    if (! sendParseReply("AT+CSQ", "+CSQ: ", &reply) ) return 0;
+    
+    return reply;
+}
+
+/********* AUDIO *******************************************************/
+
+bool Adafruit_FONA::setAudio(uint8_t a) {
+    // 0 is headset, 1 is external audio
+    if (a > 1) return false;
+    
+    return sendCheckReply("AT+CHFA=", a, "OK");
+}
+
+uint8_t Adafruit_FONA::getVolume(void) {
+    uint16_t reply;
+    
+    if (! sendParseReply("AT+CLVL?", "+CLVL: ", &reply) ) return 0;
+    
+    return reply;
+}
+
+bool Adafruit_FONA::setVolume(uint8_t i) {
+    return sendCheckReply("AT+CLVL=", i, "OK");
+}
+
+
+bool Adafruit_FONA::playDTMF(char dtmf) {
+    char str[4];
+    str[0] = '\"';
+    str[1] = dtmf;
+    str[2] = '\"';
+    str[3] = 0;
+    return sendCheckReply("AT+CLDTMF=3,", str, "OK");
+}
+
+bool Adafruit_FONA::playToolkitTone(uint8_t t, uint16_t len) {
+    return sendCheckReply("AT+STTONE=1,", t, len, "OK");
+}
+
+bool Adafruit_FONA::setMicVolume(uint8_t a, uint8_t level) {
+    // 0 is headset, 1 is external audio
+    if (a > 1) return false;
+    
+    return sendCheckReply("AT+CMIC=", a, level, "OK");
+}
+
+/********* FM RADIO *******************************************************/
+
+
+bool Adafruit_FONA::FMradio(bool onoff, uint8_t a) {
+    if (! onoff) {
+        return sendCheckReply("AT+FMCLOSE", "OK");
+    }
+    
+    // 0 is headset, 1 is external audio
+    if (a > 1) return false;
+    
+    return sendCheckReply("AT+FMOPEN=", a, "OK");
+}
+
+bool Adafruit_FONA::tuneFMradio(uint16_t station) {
+    // Fail if FM station is outside allowed range.
+    if ((station < 870) || (station > 1090))
+        return false;
+    
+    return sendCheckReply("AT+FMFREQ=", station, "OK");
+}
+
+bool Adafruit_FONA::setFMVolume(uint8_t i) {
+    // Fail if volume is outside allowed range (0-6).
+    if (i > 6) {
+    return false;
+    }
+    // Send FM volume command and verify response.
+    return sendCheckReply("AT+FMVOLUME=", i, "OK");
+}
+
+int8_t Adafruit_FONA::getFMVolume() {
+    uint16_t level;
+    
+    if (! sendParseReply("AT+FMVOLUME?", "+FMVOLUME: ", &level) ) return 0;
+    
+    return level;
+}
+
+int8_t Adafruit_FONA::getFMSignalLevel(uint16_t station) {
+    // Fail if FM station is outside allowed range.
+    if ((station < 875) || (station > 1080)) {
+        return -1;
+    }   
+    
+    // Send FM signal level query command.
+    // Note, need to explicitly send timeout so right overload is chosen.
+    getReply("AT+FMSIGNAL=", station, FONA_DEFAULT_TIMEOUT_MS);
+    // Check response starts with expected value.
+    char *p = strstr(replybuffer, "+FMSIGNAL: ");
+    if (p == 0) return -1;
+    p+=11;
+    // Find second colon to get start of signal quality.
+    p = strchr(p, ':');
+    if (p == 0) return -1;
+    p+=1;
+    // Parse signal quality.
+    int8_t level = atoi(p);
+    readline();  // eat the "OK"
+    return level;
+}
+
+/********* PWM/BUZZER **************************************************/
+
+bool Adafruit_FONA::setPWM(uint16_t period, uint8_t duty) {
+    if (period > 2000) return false;
+    if (duty > 100) return false;
+    
+    return sendCheckReply("AT+SPWM=0,", period, duty, "OK");
+}
+
+/********* CALL PHONES **************************************************/
+bool Adafruit_FONA::callPhone(char *number) {
+    char sendbuff[35] = "ATD";
+    strncpy(sendbuff+3, number, min((int)30, (int)strlen(number)));
+    uint8_t x = strlen(sendbuff);
+    sendbuff[x] = ';';
+    sendbuff[x+1] = 0;
+    
+    return sendCheckReply(sendbuff, "OK");
+}
+
+bool Adafruit_FONA::hangUp(void) {
+    return sendCheckReply("ATH0", "OK");
+}
+
+bool Adafruit_FONA::pickUp(void) {
+    return sendCheckReply("ATA", "OK");
+}
+
+void Adafruit_FONA::onIncomingCall() {
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("> Incoming call...\r\n");
+#endif
+    _incomingCall = true;
+}
+
+bool Adafruit_FONA::callerIdNotification(bool enable) {
+    if(enable){
+        _ringIndicatorInterruptIn.fall(this, &Adafruit_FONA::onIncomingCall);
+        return sendCheckReply("AT+CLIP=1", "OK");
+    }
+    
+    _ringIndicatorInterruptIn.fall(NULL);
+    return sendCheckReply("AT+CLIP=0", "OK");
+}
+
+bool Adafruit_FONA::incomingCallNumber(char* phonenum) {
+    //+CLIP: "<incoming phone number>",145,"",0,"",0
+    if(!_incomingCall)
+        return false;
+    
+    readline();
+    while(!strcmp(replybuffer, "RING") == 0) {
+        flushInput();
+        readline();
+    }
+    
+    readline(); //reads incoming phone number line
+    
+    parseReply("+CLIP: \"", phonenum, '"');
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("Phone Number: %s\r\n", replybuffer);
+#endif
+    
+    _incomingCall = false;
+    return true;
+}
+
+/********* SMS **********************************************************/
+
+uint8_t Adafruit_FONA::getSMSInterrupt(void) {
+    uint16_t reply;
+    
+    if (! sendParseReply("AT+CFGRI?", "+CFGRI: ", &reply) ) return 0;
+    
+    return reply;
+}
+
+bool Adafruit_FONA::setSMSInterrupt(uint8_t i) {
+    return sendCheckReply("AT+CFGRI=", i, "OK");
+}
+
+int8_t Adafruit_FONA::getNumSMS(void) {
+    uint16_t numsms;
+    
+    if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
+    // ask how many sms are stored
+    
+    if (! sendParseReply("AT+CPMS?", "+CPMS: \"SM_P\",", &numsms) ) return -1;
+    
+    return numsms;
+}
+
+// Reading SMS's is a bit involved so we don't use helpers that may cause delays or debug
+// printouts!
+bool Adafruit_FONA::readSMS(uint8_t i, char *smsbuff, uint16_t maxlen, uint16_t *readlen) {
+    // text mode
+    if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
+    
+    // show all text mode parameters
+    if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
+    
+    // parse out the SMS len
+    uint16_t thesmslen = 0;
+    
+    //getReply(F("AT+CMGR="), i, 1000);  //  do not print debug!
+    mySerial.printf("AT+CMGR=%d\r\n", i);
+    readline(1000); // timeout
+    
+    // parse it out...
+    if (! parseReply("+CMGR:", &thesmslen, ',', 11)) {
+        *readlen = 0;
+        return false;
+    }
+    
+    readRaw(thesmslen);
+    
+    flushInput();
+    
+    uint16_t thelen = min(maxlen, (uint16_t)strlen(replybuffer));
+    strncpy(smsbuff, replybuffer, thelen);
+    smsbuff[thelen] = 0; // end the string
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("%s\r\n", replybuffer);
+#endif
+    *readlen = thelen;
+    return true;
+}
+
+// Retrieve the sender of the specified SMS message and copy it as a string to
+// the sender buffer.  Up to senderlen characters of the sender will be copied
+// and a null terminator will be added if less than senderlen charactesr are
+// copied to the result.  Returns true if a result was successfully retrieved,
+// otherwise false.
+bool Adafruit_FONA::getSMSSender(uint8_t i, char *sender, int senderlen) {
+    // Ensure text mode and all text mode parameters are sent.
+    if (! sendCheckReply("AT+CMGF=1", "OK")) return false;
+    if (! sendCheckReply("AT+CSDH=1", "OK")) return false;
+    // Send command to retrieve SMS message and parse a line of response.
+    mySerial.printf("AT+CMGR=%d\r\n", i);
+    readline(1000);
+    // Parse the second field in the response.
+    bool result = parseReplyQuoted("+CMGR:", sender, senderlen, ',', 1);
+    // Drop any remaining data from the response.
+    flushInput();
+    return result;
+}
+
+bool Adafruit_FONA::sendSMS(char *smsaddr, char *smsmsg) {
+    if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
+    
+    char sendcmd[30] = "AT+CMGS=\"";
+    strncpy(sendcmd+9, smsaddr, 30-9-2);  // 9 bytes beginning, 2 bytes for close quote + null
+    sendcmd[strlen(sendcmd)] = '\"';
+    
+    if (! sendCheckReply(sendcmd, "> ")) return false;
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("> %s\r\n", smsmsg);
+#endif
+    mySerial.printf("%s\r\n\r\n", smsmsg);
+    mySerial.putc(0x1A);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("^Z\r\n");
+#endif
+    readline(10000); // read the +CMGS reply, wait up to 10 seconds!!!
+    //Serial.print("* "); Serial.println(replybuffer);
+    if (strstr(replybuffer, "+CMGS") == 0) {
+        return false;
+    }
+    readline(1000); // read OK
+    //Serial.print("* "); Serial.println(replybuffer);
+    
+    if (strcmp(replybuffer, "OK") != 0) {
+        return false;
+    }
+    
+    return true;
+}
+
+
+bool Adafruit_FONA::deleteSMS(uint8_t i) {
+    if (! sendCheckReply("AT+CMGF=1", "OK")) return -1;
+    // read an sms
+    char sendbuff[12] = "AT+CMGD=000";
+    sendbuff[8] = (i / 100) + '0';
+    i %= 100;
+    sendbuff[9] = (i / 10) + '0';
+    i %= 10;
+    sendbuff[10] = i + '0';
+    
+    return sendCheckReply(sendbuff, "OK", 2000);
+}
+
+/********* TIME **********************************************************/
+
+bool Adafruit_FONA::enableNetworkTimeSync(bool onoff) {
+    if (onoff) {
+        if (! sendCheckReply("AT+CLTS=1", "OK"))
+            return false;
+    } else {
+        if (! sendCheckReply("AT+CLTS=0", "OK"))
+            return false;
+    }
+    
+    flushInput(); // eat any 'Unsolicted Result Code'
+    
+    return true;
+}
+
+bool Adafruit_FONA::enableNTPTimeSync(bool onoff, const char* ntpserver) {
+    if (onoff) {
+        if (! sendCheckReply("AT+CNTPCID=1", "OK"))
+            return false;
+        
+        mySerial.printf("AT+CNTP=\"");
+        if (ntpserver != 0) {
+            mySerial.printf(ntpserver);
+        } else {
+            mySerial.printf("pool.ntp.org");
+        }
+        mySerial.printf("\",0\r\n");
+        readline(FONA_DEFAULT_TIMEOUT_MS);
+        if (strcmp(replybuffer, "OK") != 0)
+            return false;
+        
+        if (! sendCheckReply("AT+CNTP", "OK", 10000))
+            return false;
+        
+        uint16_t status;
+        readline(10000);
+        if (! parseReply("+CNTP:", &status))
+            return false;
+    } else {
+        if (! sendCheckReply("AT+CNTPCID=0", "OK"))
+            return false;
+    }
+    
+    return true;
+}
+
+bool Adafruit_FONA::getTime(char* buff, uint16_t maxlen) {
+    getReply("AT+CCLK?", (uint16_t) 10000);
+    if (strncmp(replybuffer, "+CCLK: ", 7) != 0)
+        return false;
+    
+    char *p = replybuffer+7;
+    uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
+    strncpy(buff, p, lentocopy+1);
+    buff[lentocopy] = 0;
+    
+    readline(); // eat OK
+    
+    return true;
+}
+
+/********* GPS **********************************************************/
+
+
+bool Adafruit_FONA::enableGPS(bool onoff) {
+    uint16_t state;
+    
+    // first check if its already on or off
+    if (! sendParseReply("AT+CGPSPWR?", "+CGPSPWR: ", &state) )
+        return false;
+    
+    if (onoff && !state) {
+        if (! sendCheckReply("AT+CGPSPWR=1", "OK"))
+            return false;
+    } else if (!onoff && state) {
+        if (! sendCheckReply("AT+CGPSPWR=0", "OK"))
+            return false;
+    }
+    return true;
+}
+
+int8_t Adafruit_FONA::GPSstatus(void) {
+    getReply("AT+CGPSSTATUS?");
+    
+    char *p = strstr(replybuffer, "+CGPSSTATUS: Location ");
+    if (p == 0) return -1;
+    
+    p+=22;
+    
+    readline(); // eat 'OK'
+    
+    
+    if (p[0] == 'U') return 0;
+    if (p[0] == 'N') return 1;
+    if (p[0] == '2') return 2;
+    if (p[0] == '3') return 3;
+    
+    // else
+    return 0;
+}
+
+uint8_t Adafruit_FONA::getGPS(uint8_t arg, char *buffer, uint8_t maxbuff) {
+    int32_t x = arg;
+    
+    getReply("AT+CGPSINF=", x);
+    
+    char *p = strstr(replybuffer, "CGPSINF: ");
+    if (p == 0){
+        buffer[0] = 0;
+        return 0;
+    }
+    p+=9;
+    uint8_t len = max((uint8_t)(maxbuff-1), (uint8_t)strlen(p));
+    strncpy(buffer, p, len);
+    buffer[len] = 0;
+    
+    readline(); // eat 'OK'
+    return len;
+}
+
+bool Adafruit_FONA::getGPS(float *lat, float *lon, float *speed_kph, float *heading, float *altitude) {
+    char gpsbuffer[120];
+    
+    // we need at least a 2D fix
+    if (GPSstatus() < 2)
+        return false;
+    
+    // grab the mode 2^5 gps csv from the sim808
+    uint8_t res_len = getGPS(32, gpsbuffer, 120);
+    
+    // make sure we have a response
+    if (res_len == 0)
+        return false;
+    
+    // skip mode
+    char *tok = strtok(gpsbuffer, ",");
+    if (! tok) return false;
+    
+    // skip date
+    tok = strtok(NULL, ",");
+    if (! tok) return false;
+    
+    // skip fix
+    tok = strtok(NULL, ",");
+    if (! tok) return false;
+    
+    // grab the latitude
+    char *latp = strtok(NULL, ",");
+    if (! latp) return false;
+    
+    // grab latitude direction
+    char *latdir = strtok(NULL, ",");
+    if (! latdir) return false;
+    
+    // grab longitude
+    char *longp = strtok(NULL, ",");
+    if (! longp) return false;
+    
+    // grab longitude direction
+    char *longdir = strtok(NULL, ",");
+    if (! longdir) return false;
+    
+    double latitude = atof(latp);
+    double longitude = atof(longp);
+    
+    // convert latitude from minutes to decimal
+    float degrees = floor(latitude / 100);
+    double minutes = latitude - (100 * degrees);
+    minutes /= 60;
+    degrees += minutes;
+    
+    // turn direction into + or -
+    if (latdir[0] == 'S') degrees *= -1;
+    
+    *lat = degrees;
+    
+    // convert longitude from minutes to decimal
+    degrees = floor(longitude / 100);
+    minutes = longitude - (100 * degrees);
+    minutes /= 60;
+    degrees += minutes;
+    
+    // turn direction into + or -
+    if (longdir[0] == 'W') degrees *= -1;
+    
+    *lon = degrees;
+    
+    // only grab speed if needed
+    if (speed_kph != NULL) {
+        
+        // grab the speed in knots
+        char *speedp = strtok(NULL, ",");
+        if (! speedp) return false;
+        
+        // convert to kph
+        *speed_kph = atof(speedp) * 1.852;
+        
+    }
+    
+    // only grab heading if needed
+    if (heading != NULL) {
+        
+        // grab the speed in knots
+        char *coursep = strtok(NULL, ",");
+        if (! coursep) return false;
+        
+        *heading = atof(coursep);
+    
+    }
+    
+    // no need to continue
+    if (altitude == NULL)
+        return true;
+    
+    // we need at least a 3D fix for altitude
+    if (GPSstatus() < 3)
+        return false;
+    
+    // grab the mode 0 gps csv from the sim808
+    res_len = getGPS(0, gpsbuffer, 120);
+    
+    // make sure we have a response
+    if (res_len == 0)
+        return false;
+    
+    // skip mode
+    tok = strtok(gpsbuffer, ",");
+    if (! tok) return false;
+    
+    // skip lat
+    tok = strtok(NULL, ",");
+    if (! tok) return false;
+    
+    // skip long
+    tok = strtok(NULL, ",");
+    if (! tok) return false;
+    
+    // grab altitude
+    char *altp = strtok(NULL, ",");
+    if (! altp) return false;
+    
+    *altitude = atof(altp);
+    
+    return true;
+}
+
+bool Adafruit_FONA::enableGPSNMEA(uint8_t i) {
+    char sendbuff[15] = "AT+CGPSOUT=000";
+    sendbuff[11] = (i / 100) + '0';
+    i %= 100;
+    sendbuff[12] = (i / 10) + '0';
+    i %= 10;
+    sendbuff[13] = i + '0';
+    
+    return sendCheckReply(sendbuff, "OK", 2000);
+}
+
+
+/********* GPRS **********************************************************/
+
+
+bool Adafruit_FONA::enableGPRS(bool onoff) {
+    if (onoff) {
+        // disconnect all sockets
+        sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000);
+        
+        if (! sendCheckReply("AT+CGATT=1", "OK", 10000))
+            return false;
+        
+        // set bearer profile! connection type GPRS
+        if (! sendCheckReply("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"", "OK", 10000))
+            return false;
+        
+        // set bearer profile access point name
+        if (apn) {
+            // Send command AT+SAPBR=3,1,"APN","<apn value>" where <apn value> is the configured APN value.
+            if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"APN\",", apn, "OK", 10000))
+                return false;
+            
+            // set username/password
+            if (apnusername) {
+                // Send command AT+SAPBR=3,1,"USER","<user>" where <user> is the configured APN username.
+                if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"USER\",", apnusername, "OK", 10000))
+                    return false;
+            }
+            if (apnpassword) {
+                // Send command AT+SAPBR=3,1,"PWD","<password>" where <password> is the configured APN password.
+                if (! sendCheckReplyQuoted("AT+SAPBR=3,1,\"PWD\",", apnpassword, "OK", 10000))
+                    return false;
+            }
+        }
+        
+        // open GPRS context
+        if (! sendCheckReply("AT+SAPBR=1,1", "OK", 10000))
+            return false;
+    } else {
+        // disconnect all sockets
+        if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000))
+            return false;
+        
+        // close GPRS context
+        if (! sendCheckReply("AT+SAPBR=0,1", "OK", 10000))
+            return false;
+        
+        if (! sendCheckReply("AT+CGATT=0", "OK", 10000))
+            return false;
+    }
+    return true;
+}
+
+uint8_t Adafruit_FONA::GPRSstate(void) {
+    uint16_t state;
+    
+    if (! sendParseReply("AT+CGATT?", "+CGATT: ", &state) )
+        return -1;
+    
+    return state;
+}
+
+void Adafruit_FONA::setGPRSNetworkSettings(const char* apn, const char* ausername, const char* apassword) {
+    this->apn = (char*) apn;
+    this->apnusername = (char*) ausername;
+    this->apnpassword = (char*) apassword;
+}
+
+bool Adafruit_FONA::getGSMLoc(uint16_t *errorcode, char *buff, uint16_t maxlen) {
+    getReply("AT+CIPGSMLOC=1,1", (uint16_t)10000);
+    
+    if (! parseReply("+CIPGSMLOC: ", errorcode))
+        return false;
+    
+    char *p = replybuffer+14;
+    uint16_t lentocopy = min((uint16_t)(maxlen-1), (uint16_t)strlen(p));
+    strncpy(buff, p, lentocopy+1);
+    
+    readline(); // eat OK
+    
+    return true;
+}
+
+bool Adafruit_FONA::getGSMLoc(float *lat, float *lon) {
+    uint16_t returncode;
+    char gpsbuffer[120];
+    
+    // make sure we could get a response
+    if (! getGSMLoc(&returncode, gpsbuffer, 120))
+        return false;
+    
+    // make sure we have a valid return code
+    if (returncode != 0)
+        return false;
+    
+    // tokenize the gps buffer to locate the lat & long
+    char *latp = strtok(gpsbuffer, ",");
+    if (! latp) return false;
+    
+    char *longp = strtok(NULL, ",");
+    if (! longp) return false;
+    
+    *lat = atof(latp);
+    *lon = atof(longp);
+    
+    return true;
+}
+
+/********* TCP FUNCTIONS  ************************************/
+
+
+bool Adafruit_FONA::TCPconnect(char *server, uint16_t port) {
+    flushInput();
+    
+    // close all old connections
+    if (! sendCheckReply("AT+CIPSHUT", "SHUT OK", 5000) ) return false;
+    
+    // single connection at a time
+    if (! sendCheckReply("AT+CIPMUX=0", "OK") ) return false;
+    
+    // manually read data
+    if (! sendCheckReply("AT+CIPRXGET=1", "OK") ) return false;
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
+#endif
+    
+    mySerial.printf("AT+CIPSTART=\"TCP\",\"%s\",\"%d\"\r\n", server, port);
+    
+    if (! expectReply("OK")) return false;
+    if (! expectReply("CONNECT OK")) return false;
+    return true;
+}
+
+bool Adafruit_FONA::TCPclose(void) {
+    return sendCheckReply("AT+CIPCLOSE", "OK");
+}
+
+bool Adafruit_FONA::TCPconnected(void) {
+    if (! sendCheckReply("AT+CIPSTATUS", "OK", 100) ) return false;
+    readline(100);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return (strcmp(replybuffer, "STATE: CONNECT OK") == 0);
+}
+
+bool Adafruit_FONA::TCPsend(char *packet, uint8_t len) {
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("AT+CIPSEND=%d\r\n", len);
+    
+    for (uint16_t i=0; i<len; i++) {
+        printf(" 0x%#02x", packet[i]);
+    }
+    printf("\r\n");
+#endif
+    
+    
+    mySerial.printf("AT+CIPSEND=%d\r\n", len);
+    readline();
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    if (replybuffer[0] != '>') return false;
+    
+    for (uint16_t i=0; i<len; i++) {
+        mySerial.putc(packet[i]);
+    }
+    readline(3000); // wait up to 3 seconds to send the data
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    
+    return (strcmp(replybuffer, "SEND OK") == 0);
+}
+
+uint16_t Adafruit_FONA::TCPavailable(void) {
+    uint16_t avail;
+    
+    if (! sendParseReply("AT+CIPRXGET=4", "+CIPRXGET: 4,", &avail, ',', 0) ) return false;
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("%d bytes available\r\n", avail);
+#endif
+    
+    return avail;
+}
+
+
+uint16_t Adafruit_FONA::TCPread(uint8_t *buff, uint8_t len) {
+    uint16_t avail;
+    
+    mySerial.printf("AT+CIPRXGET=2,%d\r\n", len);
+    readline();
+    if (! parseReply("+CIPRXGET: 2,", &avail, ',', 0)) return false;
+    
+    readRaw(avail);
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("%d bytes read\r\n", avail);
+    for (uint8_t i=0;i<avail;i++) {
+        printf(" 0x%#02x", replybuffer[i]);
+    }
+    printf("\r\n");
+#endif
+    
+    memcpy(buff, replybuffer, avail);
+    
+    return avail;
+}
+
+/********* HTTP LOW LEVEL FUNCTIONS  ************************************/
+
+bool Adafruit_FONA::HTTP_init() {
+    return sendCheckReply("AT+HTTPINIT", "OK");
+}
+
+bool Adafruit_FONA::HTTP_term() {
+    return sendCheckReply("AT+HTTPTERM", "OK");
+}
+
+void Adafruit_FONA::HTTP_para_start(const char* parameter, bool quoted) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> AT+HTTPPARA=\"%s\"\r\n", parameter);
+#endif
+    
+    mySerial.printf("AT+HTTPPARA=\"%s", parameter);
+    if (quoted)
+        mySerial.printf("\",\"");
+    else
+        mySerial.printf("\",");
+}
+
+bool Adafruit_FONA::HTTP_para_end(bool quoted) {
+    if (quoted)
+        mySerial.printf("\"\r\n");
+    else
+        mySerial.printf("\r\n");
+    
+    return expectReply("OK");
+}
+
+bool Adafruit_FONA::HTTP_para(const char* parameter, const char* value) {
+    HTTP_para_start(parameter, true);
+    mySerial.printf(value);
+    return HTTP_para_end(true);
+}
+
+bool Adafruit_FONA::HTTP_para(const char* parameter, int32_t value) {
+    HTTP_para_start(parameter, false);
+    mySerial.printf("%d", value);
+    return HTTP_para_end(false);
+}
+
+bool Adafruit_FONA::HTTP_data(uint32_t size, uint32_t maxTime) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> AT+HTTPDATA=%d,%d\r\n", size, maxTime);
+#endif
+    
+    mySerial.printf("AT+HTTPDATA=%d,%d\r\n", size, maxTime);
+    
+    return expectReply("DOWNLOAD");
+}
+
+bool Adafruit_FONA::HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout) {
+    // Send request.
+    if (! sendCheckReply("AT+HTTPACTION=", method, "OK"))
+        return false;
+    
+    // Parse response status and size.
+    readline(timeout);
+    if (! parseReply("+HTTPACTION:", status, ',', 1))
+        return false;
+    if (! parseReply("+HTTPACTION:", datalen, ',', 2))
+        return false;
+    
+    return true;
+}
+
+bool Adafruit_FONA::HTTP_readall(uint16_t *datalen) {
+    getReply("AT+HTTPREAD");
+    if (! parseReply("+HTTPREAD:", datalen, ',', 0))
+        return false;
+    
+    return true;
+}
+
+bool Adafruit_FONA::HTTP_ssl(bool onoff) {
+    return sendCheckReply("AT+HTTPSSL=", onoff ? 1 : 0, "OK");
+}
+
+/********* HTTP HIGH LEVEL FUNCTIONS ***************************/
+
+bool Adafruit_FONA::HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen){
+    if (! HTTP_setup(url))
+        return false;
+    
+    // HTTP GET
+    if (! HTTP_action(FONA_HTTP_GET, status, datalen))
+        return false;
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("Status: %d\r\n", *status);
+    printf("Len: %d\r\n", *datalen);
+#endif
+    
+    // HTTP response data
+    if (! HTTP_readall(datalen))
+        return false;
+    
+    return true;
+}
+
+void Adafruit_FONA::HTTP_GET_end(void) {
+    HTTP_term();
+}
+
+bool Adafruit_FONA::HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen) {
+    if (! HTTP_setup(url))
+        return false;
+    
+    if (! HTTP_para("CONTENT", contenttype)) {
+        return false;
+    }
+    
+    // HTTP POST data
+    if (! HTTP_data(postdatalen, 10000))
+        return false;
+    for (uint16_t i = 0; i < postdatalen; i++) {
+        mySerial.putc(postdata[i]);
+    }
+    if (! expectReply("OK"))
+        return false;
+    
+    // HTTP POST
+    if (! HTTP_action(FONA_HTTP_POST, status, datalen))
+        return false;
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("Status: %d\r\n", *status);
+    printf("Len: %d\r\n", *datalen);
+#endif
+    
+    // HTTP response data
+    if (! HTTP_readall(datalen))
+        return false;
+    
+    return true;
+}
+
+void Adafruit_FONA::HTTP_POST_end(void) {
+    HTTP_term();
+}
+
+void Adafruit_FONA::setUserAgent(const char* useragent) {
+    this->useragent = (char*) useragent;
+}
+
+void Adafruit_FONA::setHTTPSRedirect(bool onoff) {
+    httpsredirect = onoff;
+}
+
+/********* HTTP HELPERS ****************************************/
+
+bool Adafruit_FONA::HTTP_setup(char *url) {
+    // Handle any pending
+    HTTP_term();
+    
+    // Initialize and set parameters
+    if (! HTTP_init())
+        return false;
+    if (! HTTP_para("CID", 1))
+        return false;
+    if (! HTTP_para("UA", useragent))
+        return false;
+    if (! HTTP_para("URL", url))
+        return false;
+    
+    // HTTPS redirect
+    if (httpsredirect) {
+        if (! HTTP_para("REDIR",1))
+            return false;
+        
+        if (! HTTP_ssl(true))
+            return false;
+    }
+    
+    return true;
+}
+
+
+/********* HELPERS *********************************************/
+
+bool Adafruit_FONA::expectReply(const char* reply, uint16_t timeout) {
+    readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return (strcmp(replybuffer, reply) == 0);
+}
+
+/********* LOW LEVEL *******************************************/
+
+void Adafruit_FONA::flushInput() {
+    // Read all available serial input to flush pending data.
+    uint16_t timeoutloop = 0;
+    while (timeoutloop++ < 40) {
+        while(readable()) {
+            getc();
+            timeoutloop = 0;  // If char was received reset the timer
+        }
+        wait_ms(1);
+    }
+}
+
+uint16_t Adafruit_FONA::readRaw(uint16_t b) {
+    uint16_t idx = 0;
+    
+    while (b && (idx < sizeof(replybuffer)-1)) {
+        if (readable()) {
+            replybuffer[idx] = getc();
+            idx++;
+            b--;
+        }
+    }
+    replybuffer[idx] = 0;
+    
+    return idx;
+}
+
+// This function just reads the output from FONA after an AT command is sent to it
+uint8_t Adafruit_FONA::readline(uint16_t timeout, bool multiline) {
+    uint16_t replyidx = 0;
+    
+    while (timeout--) {
+        if (replyidx >= 254) {
+            break;
+        }
+    
+        while(readable()) {
+            char c =  getc();
+            if (c == '\r') continue;
+            if (c == 0xA) {
+                if (replyidx == 0)   // the first 0x0A is ignored
+                    continue;
+                
+                if (!multiline) {
+                    timeout = 0;         // the second 0x0A is the end of the line
+                    break;
+                }
+            }
+            replybuffer[replyidx] = c;
+            replyidx++;
+        }
+    
+        if (timeout == 0) {
+            break;
+        }
+        wait_ms(1);
+    }
+    replybuffer[replyidx] = 0;  // null term
+    return replyidx;
+}
+
+uint8_t Adafruit_FONA::getReply(const char* send, uint16_t timeout) {
+    flushInput();
+
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> %s\r\n", send);
+#endif
+
+    mySerial.printf("%s\r\n",send);
+
+    uint8_t l = readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return l;
+}
+
+// Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(const char* prefix, char* suffix, uint16_t timeout) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> %s%s\r\n", prefix, suffix);
+#endif
+    
+    mySerial.printf("%s%s\r\n", prefix, suffix);
+    
+    uint8_t l = readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return l;
+}
+
+// Send prefix, suffix, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix, uint16_t timeout) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> %s%d\r\n", prefix, suffix);
+#endif
+    
+    mySerial.printf("%s%d\r\n", prefix, suffix);
+    
+    uint8_t l = readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return l;
+}
+
+// Send prefix, suffix, suffix2, and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> %s%d,%d\r\n", prefix, suffix1, suffix2);
+#endif
+    
+    mySerial.printf("%s%d,%d\r\n", prefix, suffix1, suffix2);
+    
+    uint8_t l = readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return l;
+}
+
+// Send prefix, ", suffix, ", and newline. Return response (and also set replybuffer with response).
+uint8_t Adafruit_FONA::getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout) {
+    flushInput();
+    
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t---> %s\"%s\"\r\n", prefix, suffix);
+#endif
+    
+    mySerial.printf("%s\"%s\"\r\n", prefix, suffix);
+    
+    uint8_t l = readline(timeout);
+#ifdef ADAFRUIT_FONA_DEBUG
+    printf("\t<--- %s\r\n", replybuffer);
+#endif
+    return l;
+}
+
+
+bool Adafruit_FONA::sendCheckReply(const char *send, const char *reply, uint16_t timeout) {
+    getReply(send, timeout);
+    
+    return (strcmp(replybuffer, reply) == 0);
+}
+
+// Send prefix, suffix, and newline.  Verify FONA response matches reply parameter.
+bool Adafruit_FONA::sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout) {
+    getReply(prefix, suffix, timeout);
+    return (strcmp(replybuffer, reply) == 0);
+}
+
+// Send prefix, suffix, and newline.  Verify FONA response matches reply parameter.
+bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout) {
+    getReply(prefix, suffix, timeout);
+    return (strcmp(replybuffer, reply) == 0);
+}
+
+// Send prefix, suffix, suffix2, and newline.  Verify FONA response matches reply parameter.
+bool Adafruit_FONA::sendCheckReply(const char* prefix, int32_t suffix1, int32_t suffix2, const char* reply, uint16_t timeout) {
+    getReply(prefix, suffix1, suffix2, timeout);
+    return (strcmp(replybuffer, reply) == 0);
+}
+
+// Send prefix, ", suffix, ", and newline.  Verify FONA response matches reply parameter.
+bool Adafruit_FONA::sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout) {
+  getReplyQuoted(prefix, suffix, timeout);
+  return (strcmp(replybuffer, reply) == 0);
+}
+
+bool Adafruit_FONA::parseReply(const char* toreply, uint16_t *v, char divider, uint8_t index) {
+    char *p = strstr(replybuffer, toreply);  // get the pointer to the voltage
+    if (p == 0) return false;
+    p += strlen(toreply);
+    
+    for (uint8_t i=0; i<index;i++) {
+        // increment dividers
+        p = strchr(p, divider);
+        if (!p) return false;
+        p++;
+    }
+    
+    *v = atoi(p);
+    
+    return true;
+}
+
+bool Adafruit_FONA::parseReply(const char* toreply, char *v, char divider, uint8_t index) {
+    uint8_t i=0;
+    char *p = strstr(replybuffer, toreply);
+    if (p == 0) return false;
+    p+=strlen(toreply);
+    
+    for (i=0; i<index;i++) {
+        // increment dividers
+        p = strchr(p, divider);
+        if (!p) return false;
+        p++;
+    }
+    
+    for(i=0; i<strlen(p);i++) {
+        if(p[i] == divider)
+            break;
+        v[i] = p[i];
+    }
+    
+    v[i] = '\0';
+    
+    return true;
+}
+
+// Parse a quoted string in the response fields and copy its value (without quotes)
+// to the specified character array (v).  Only up to maxlen characters are copied
+// into the result buffer, so make sure to pass a large enough buffer to handle the
+// response.
+bool Adafruit_FONA::parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index) {
+    uint8_t i=0, j;
+    // Verify response starts with toreply.
+    char *p = strstr(replybuffer, toreply);
+    if (p == 0) return false;
+    p+=strlen(toreply);
+    
+    // Find location of desired response field.
+    for (i=0; i<index;i++) {
+        // increment dividers
+        p = strchr(p, divider);
+        if (!p) return false;
+            p++;
+    }
+    
+    // Copy characters from response field into result string.
+    for(i=0, j=0; j<maxlen && i<strlen(p); ++i) {
+        // Stop if a divier is found.
+        if(p[i] == divider)
+            break;
+        // Skip any quotation marks.
+        else if(p[i] == '"')
+            continue;
+        v[j++] = p[i];
+    }
+    
+    // Add a null terminator if result string buffer was not filled.
+    if (j < maxlen)
+        v[j] = '\0';
+    
+    return true;
+}
+
+bool Adafruit_FONA::sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider, uint8_t index) {
+    getReply(tosend);
+    
+    if (! parseReply(toreply, v, divider, index)) return false;
+    
+    readline(); // eat 'OK'
+    
+    return true;
+}
\ No newline at end of file
diff -r 000000000000 -r 58ff0234d7bb Adafruit_FONA.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_FONA.h	Wed May 03 21:05:54 2017 +0000
@@ -0,0 +1,542 @@
+/***************************************************
+  This is a library for our Adafruit FONA Cellular Module
+
+  Designed specifically to work with the Adafruit FONA
+  ----> http://www.adafruit.com/products/1946
+  ----> http://www.adafruit.com/products/1963
+
+  These displays use TTL Serial to communicate, 2 pins are required to
+  interface
+  Adafruit invests time and resources providing this open source code,
+  please support Adafruit and open-source hardware by purchasing
+  products from Adafruit!
+
+  Written by Limor Fried/Ladyada for Adafruit Industries.
+  BSD license, all text above must be included in any redistribution
+ ****************************************************/
+ 
+ /*
+  *  Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768
+  */
+ 
+#ifndef ADAFRUIT_FONA_H
+#define ADAFRUIT_FONA_H
+
+#include "mbed.h"
+
+//#define ADAFRUIT_FONA_DEBUG
+
+#define FONA_HEADSETAUDIO 0
+#define FONA_EXTAUDIO 1
+
+#define FONA_STTONE_DIALTONE 1
+#define FONA_STTONE_BUSY 2
+#define FONA_STTONE_CONGESTION 3
+#define FONA_STTONE_PATHACK 4
+#define FONA_STTONE_DROPPED 5
+#define FONA_STTONE_ERROR 6
+#define FONA_STTONE_CALLWAIT 7
+#define FONA_STTONE_RINGING 8
+#define FONA_STTONE_BEEP 16
+#define FONA_STTONE_POSTONE 17
+#define FONA_STTONE_ERRTONE 18
+#define FONA_STTONE_INDIANDIALTONE 19
+#define FONA_STTONE_USADIALTONE 20
+
+#define FONA_DEFAULT_TIMEOUT_MS 500 //timeout between send AT and reply from FONA
+
+#define FONA_HTTP_GET   0
+#define FONA_HTTP_POST  1
+#define FONA_HTTP_HEAD  2 
+
+#define RX_BUFFER_SIZE  255
+
+/** Adafruit FONA 800H Class
+*  Modified by George Tzintzarov & Jesse Baker 03/14/2016 for use in mbed LPC1768
+*/
+
+class Adafruit_FONA : public Stream {
+    public:
+/**
+Listener for FONA events. Inherit this class to customize.
+@code
+#define FONA_RST p12
+#define FONA_TX p13
+#define FONA_RX p14
+#define FONA_RI p11
+
+Adafruit_FONA my_fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
+DigitalOut led1(LED1); 
+class FonaEventListener : public Adafruit_FONA::EventListener {
+    virtual void onRing() {
+        led1 = 1;
+}
+
+    virtual void onNoCarrier() {
+        led1 = 0; 
+    }
+};
+FonaEventListener fonaEventListener;
+my_fona.setEventListener(&fonaEventListener);
+@endcode
+*/
+        
+        class EventListener {
+            public:
+                /**
+                 * Method called when somebody call the FONA.
+                 */
+                virtual void onRing() = 0;
+                
+                /**
+                 * Method called when the calling person stop his call.
+                 */
+                virtual void onNoCarrier() = 0;
+        };
+    
+    public:
+        /** Create instance of the Adafruit_FONA
+        @param tx Set mbed TX 
+        @param rx Set mbed RX
+        @param rst Set reset pin
+        @param ringIndicator Set ring indicator pin. This is to let mbed know if there is an incoming call
+        */
+        
+        Adafruit_FONA(PinName tx, PinName rx, PinName rst, PinName ringIndicator) :
+            _rstpin(rst, false), _ringIndicatorInterruptIn(ringIndicator),
+            apn("FONAnet"), apnusername(NULL), apnpassword(NULL), httpsredirect(false), useragent("FONA"),
+            _incomingCall(false), eventListener(NULL), mySerial(tx, rx), rxBufferInIndex(0), rxBufferOutIndex(0), 
+            currentReceivedLineSize(0) {}
+            
+        /** Built-in Test to see if FONA is connected
+        @param baudrate test and set at baudrate
+        @return true upon success
+        @return false upon failure. Most likely something is not hooked up.
+        
+EXAMPLE CODE:
+        @code
+// See if the FONA is responding
+// fona is an instance of Adafruit_FONA
+if (! fona.begin(9600)) {
+    printf("Couldn't find FONA\r\n");
+    while (1);
+}
+        @endcode
+        */
+        bool begin(int baudrate);
+        
+        /** Set the event listener for incoming calls
+        @param eventListener A pointer to the event listener
+        @see Adafruit_FONA::EventListener for specific example
+        */
+        
+        void setEventListener(EventListener *eventListener);
+        
+        // Stream----------------------------------------------------------------------
+        virtual int _putc(int value);
+        virtual int _getc();
+        
+        /** Check if FONA has anything in its output buffer
+        @return 0 if nothing
+        */
+        int readable(void);
+        
+        // RTC----------------------------------------------------------------------
+        bool enableRTC(uint8_t i); // i = 0 <=> disable, i = 1 <=> enable
+        
+        // Battery and ADC----------------------------------------------------------------------
+        /** Get ADC voltage from external pin
+        @param v uint16_t pointer to insert ADC voltage data
+        @return TRUE if successful
+        
+EXAMPLE CODE:
+        @code
+// read the ADC
+// fona is an instance of Adafruit_FONA
+uint16_t adc;
+if (! fona.getADCVoltage(&adc)) {
+    printf("Failed to read ADC\r\n");
+} 
+else {
+    printf("ADC = %d mV\r\n", adc);
+}
+        @endcode
+        */
+        bool getADCVoltage(uint16_t *v);
+        
+        /** Get battery percentage level
+        @param p uint16_t pointer to insert battery percent data
+        @return TRUE if successful
+        
+EXAMPLE CODE:
+        @code
+// read the battery percent level
+// fona is an instance of Adafruit_FONA
+uint16_t vbatPer;
+if (! fona.getBattPercent(&vbatPer)) {
+    printf("Failed to read Batt\r\n");
+} 
+else {
+    printf("VPct = %d%%\r\n", vbatPer);
+}
+        @endcode
+        */
+        
+        bool getBattPercent(uint16_t *p);
+        
+        /** Get battery voltage level
+        @param v uint16_t pointer to insert battery voltage data
+        @return TRUE if successful
+        
+EXAMPLE CODE:
+        @code
+// read the battery voltage
+// fona is an instance of Adafruit_FONA
+uint16_t vbat;
+if (! fona.getBattPercent(&vbat)) {
+    printf("Failed to read Batt\r\n");
+} 
+else {
+    printf("Vbat = %d%%\r\n", vbat);
+}
+        @endcode
+        */
+        bool getBattVoltage(uint16_t *v);
+        
+        // SIM query----------------------------------------------------------------------
+        /** Unlock SIM if needed
+        @param pin 4 digit char arrary
+        @return TRUE if successful
+        */        
+        bool unlockSIM(char *pin);
+        /** Get the SIM chip card interface device (CCID)
+        @param ccid make sure it is at least 21 bytes long
+        @return length of CCID
+        */
+        
+        uint8_t getSIMCCID(char *ccid);
+        /** Get the Network Status of FONA
+        @return Code 0-5 
+        @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 80
+        */
+        uint8_t getNetworkStatus(void);
+        
+        /** Get the RSSI of the network signal
+        @return RSSI value in dBm per below reference
+        
+        EXAMPLE
+        @code
+// read the RSSI
+uint8_t n = fona.getRSSI();
+int8_t r = 0;
+
+pcSerial.printf("RSSI = %d: ", n);
+if (n == 0) r = -115;
+if (n == 1) r = -111;
+if (n == 31) r = -52;
+if ((n >= 2) && (n <= 30)) {
+    r = map(n, 2, 30, -110, -54);
+}
+printf("%d dBm\r\n", r);
+
+// helper function MAP to do calculations
+long MAP(long x, long in_min, long in_max, long out_min, long out_max)
+{
+    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+        @endcode
+        @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 82
+        */
+        uint8_t getRSSI(void);
+        
+        // IMEI----------------------------------------------------------------------
+        /** Get the International Mobile Station Equipment Identity (IMEI)
+        @param imei A char array with minimum length 16
+        @return The IMEI of the device
+        
+EXAMPLE CODE:
+        @code
+// Print SIM card IMEI number.
+char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
+uint8_t imeiLen = fona.getIMEI(imei); //fona is an instance of Adafruit_FONA
+if (imeiLen > 0) {
+    pcSerial.printf("SIM card IMEI: %s\r\n", imei);
+}
+        @endcode
+        */
+        uint8_t getIMEI(char *imei);
+        
+        // set Audio output----------------------------------------------------------------------
+        /** Set the Audio Output interface
+        @param a 0 is headset, 1 is external audio
+        @return TRUE if successful
+        */
+        bool setAudio(uint8_t a);
+
+        /** Set the Audio Volume
+        @param i a unit8_t volume number
+        @return TRUE if successful
+        */
+        bool setVolume(uint8_t i);
+
+        /** Get the Audio Volume
+        @return the current volume
+        */
+        uint8_t getVolume(void);
+        bool playToolkitTone(uint8_t t, uint16_t len);
+        bool setMicVolume(uint8_t a, uint8_t level);
+        bool playDTMF(char tone);
+        
+        // FM radio functions----------------------------------------------------------------------
+        /** Tune the FM radio
+        @param station frequency, for example 107.9 MHz -> 1079 
+        @return TRUE if successful
+        */
+        bool tuneFMradio(uint16_t station);
+
+        /** FM radio set output
+        @param onoff bool to turn on if TRUE
+        @param a 0 (default) is headset, 1 is external audio
+        @return TRUE if successful
+        */
+        bool FMradio(bool onoff, uint8_t a = FONA_HEADSETAUDIO);
+
+        /** Set the FM Radio Volume
+        @param i a unit8_t volume number
+        @return TRUE if successful
+        */
+        bool setFMVolume(uint8_t i);
+
+        /** Get the FM Volume
+        @return the current FM volume
+        */
+        int8_t getFMVolume();
+
+        /** Get the FM signal strength
+        @param station a unit8_t volume number
+        @return TRUE if successful
+        */
+        int8_t getFMSignalLevel(uint16_t station);
+        
+        // SMS handling----------------------------------------------------------------------
+        /** Set the SMS Interrupt
+        @param i 0 = OFF, 1 = ON with TCPIP, FTP, and URC control Ring Indicator Pin, 2 = ON with only TCPIP control
+        @return TRUE if successful
+        @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 152
+        */
+        bool setSMSInterrupt(uint8_t i);
+
+        /** Get SMS Interrupt Setting
+        @return setting
+        @see https://www.adafruit.com/datasheets/sim800_series_at_command_manual_v1.01.pdf page 152
+        */
+        uint8_t getSMSInterrupt(void);
+
+        /** Set the SMS Interrupt
+        @return number of SMS messages in inbox
+        */
+        int8_t getNumSMS(void);
+
+        /** Read SMS
+        @param i sms number in memory
+        @param smsbuff char pointer to char array
+        @param max Maximum length of smsbuff
+        @param readsize the size in bytes of the SMS
+        @return TRUE if successful
+        */
+        bool readSMS(uint8_t i, char *smsbuff, uint16_t max, uint16_t *readsize);
+
+        /** Send SMS
+        @param smsaddr Phone number to send out
+        @param smsmsg Char array containing message
+        @return TRUE if successful
+        */
+        bool sendSMS(char *smsaddr, char *smsmsg);
+
+        /** Delete SMS
+        @param i number of SMS in memory
+        @return TRUE if successful
+        */
+        bool deleteSMS(uint8_t i);
+
+        /** Send SMS
+        @param i Number of SMS in memory
+        @param sender Char array to store the sender number
+        @param senderlen length of sender
+        @return TRUE if successful
+        */
+        bool getSMSSender(uint8_t i, char *sender, int senderlen);
+        
+        // Time----------------------------------------------------------------------
+        /** Enable FONA to sync time with the cellular network
+        @param onoff on = true, off = false
+        @return TRUE if successful
+        */
+        bool enableNetworkTimeSync(bool onoff);
+
+        /** Enable FONA to sync time with the time server
+        @param onoff true = on, false = off
+        @return TRUE if successful
+        */
+        bool enableNTPTimeSync(bool onoff, const char* ntpserver=0);
+
+        /** Retrieve the current time from the enabled server
+        @param buff char array to store time value. Given as "yy/MM/dd,hh:mm:ss+zz"
+        @param maxlen Maximum length of the char array
+        @return TRUE if successful
+        */
+        bool getTime(char* buff, uint16_t maxlen);
+
+        // GPRS handling----------------------------------------------------------------------
+        bool enableGPRS(bool onoff);
+        uint8_t GPRSstate(void);
+        bool getGSMLoc(uint16_t *replycode, char *buff, uint16_t maxlen);
+        bool getGSMLoc(float *lat, float *lon);
+        void setGPRSNetworkSettings(const char* apn, const char* username=0, const char* password=0);
+
+        // GPS handling----------------------------------------------------------------------
+        bool enableGPS(bool onoff);
+        int8_t GPSstatus(void);
+        uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff);
+        bool getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0);
+        bool enableGPSNMEA(uint8_t nmea);
+
+        // TCP raw connections----------------------------------------------------------------------
+        bool TCPconnect(char *server, uint16_t port);
+        bool TCPclose(void);
+        bool TCPconnected(void);
+        bool TCPsend(char *packet, uint8_t len);
+        uint16_t TCPavailable(void);
+        uint16_t TCPread(uint8_t *buff, uint8_t len);
+
+        // HTTP low level interface (maps directly to SIM800 commands).----------------------------------------------------------------------
+        bool HTTP_init();
+        bool HTTP_term();
+        void HTTP_para_start(const char* parameter, bool quoted = true);
+        bool HTTP_para_end(bool quoted = true);
+        bool HTTP_para(const char* parameter, const char *value);
+        bool HTTP_para(const char* parameter, int32_t value);
+        bool HTTP_data(uint32_t size, uint32_t maxTime=10000);
+        bool HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout = 10000);
+        bool HTTP_readall(uint16_t *datalen);
+        bool HTTP_ssl(bool onoff);
+
+        // HTTP high level interface (easier to use, less flexible).----------------------------------------------------------------------
+        bool HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen);
+        void HTTP_GET_end(void);
+        bool HTTP_POST_start(char *url, const char* contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen);
+        void HTTP_POST_end(void);
+        void setUserAgent(const char* useragent);
+
+        // HTTPS----------------------------------------------------------------------
+        void setHTTPSRedirect(bool onoff);
+
+        // PWM (buzzer)----------------------------------------------------------------------
+        /** Control the buzzer capability of the PWM out on the FONA
+        @param period of the buzzing cycle (max 2000)
+        @param duty the duty cycle of the buzzer (0 to 100)
+        @return TRUE if successful
+        */
+        bool setPWM(uint16_t period, uint8_t duty = 50);
+
+        // Phone calls----------------------------------------------------------------------
+        /** Call a phone
+        @param phonenum a character array of the phone number
+        @return TRUE if successful
+        */
+        bool callPhone(char *phonenum);
+
+        /** Hang up a phone call
+        */
+        bool hangUp(void);
+
+        /** Answer a phone call
+        */
+        bool pickUp(void);
+
+        /** Enable/disable caller ID
+        @param enable true to enable, false to disable
+        @return TRUE if successful
+        */
+        bool callerIdNotification(bool enable);
+
+        /** Retrieve the incoming call number
+        @param phonenum a character array of the phone number calling
+        @return TRUE if successful
+        */
+        bool incomingCallNumber(char* phonenum);
+
+        // Helper functions to verify responses.
+        bool expectReply(const char* reply, uint16_t timeout = 10000);
+
+    private:
+        DigitalOut _rstpin;
+        InterruptIn _ringIndicatorInterruptIn;
+
+        char replybuffer[255]; // the output of getreply(), readline() is the function that changes the replybuffer
+        char* apn;
+        char* apnusername;
+        char* apnpassword;
+        bool httpsredirect;
+        char* useragent;
+
+        volatile bool _incomingCall;
+        EventListener *eventListener;
+        Serial mySerial;
+
+        // Circular buffer used to receive serial data from an interruption
+        int rxBuffer[RX_BUFFER_SIZE + 1];
+        volatile int rxBufferInIndex; // Index where new data is added to the buffer
+        volatile int rxBufferOutIndex; // Index where data is removed from the buffer
+        char currentReceivedLine[RX_BUFFER_SIZE]; // Array containing the current received line
+        int currentReceivedLineSize;
+
+        inline bool isRxBufferFull() {
+            return ((rxBufferInIndex + 1) % RX_BUFFER_SIZE) == rxBufferOutIndex;
+        }
+
+        inline bool isRxBufferEmpty() {
+            return rxBufferInIndex == rxBufferOutIndex;
+        }
+
+        inline void incrementRxBufferInIndex() {
+            rxBufferInIndex = (rxBufferInIndex + 1) % RX_BUFFER_SIZE;
+        }
+
+        inline void incrementRxBufferOutIndex() {
+            rxBufferOutIndex = (rxBufferOutIndex + 1) % RX_BUFFER_SIZE;
+        }
+
+        /**
+         * Method called when Serial data is received (interrupt routine).
+         */
+        void onSerialDataReceived();
+
+        // HTTP helpers
+        bool HTTP_setup(char *url);
+
+        void flushInput();
+        uint16_t readRaw(uint16_t b);
+        uint8_t readline(uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS, bool multiline = false);
+        uint8_t getReply(const char* send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        uint8_t getReply(const char* prefix, char *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        uint8_t getReply(const char* prefix, int32_t suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        uint8_t getReply(const char* prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout); // Don't set default value or else function call is ambiguous.
+        uint8_t getReplyQuoted(const char* prefix, const char* suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+
+        bool sendCheckReply(const char* send, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        bool sendCheckReply(const char* prefix, char *suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        bool sendCheckReply(const char* prefix, int32_t suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        bool sendCheckReply(const char* prefix, int32_t suffix, int32_t suffix2, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+        bool sendCheckReplyQuoted(const char* prefix, const char* suffix, const char* reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+
+        bool parseReply(const char* toreply, uint16_t *v, char divider  = ',', uint8_t index=0);
+        bool parseReply(const char* toreply, char *v, char divider  = ',', uint8_t index=0);
+        bool parseReplyQuoted(const char* toreply, char* v, int maxlen, char divider, uint8_t index);
+
+        bool sendParseReply(const char* tosend, const char* toreply, uint16_t *v, char divider = ',', uint8_t index = 0);
+
+        void onIncomingCall();
+};
+
+#endif
\ No newline at end of file