Demo for the Adafruit_FONA_3G_Library. This is a port of the FONAtest available here: https://github.com/adafruit/Adafruit_FONA_Library/tree/master/examples/FONAtest .

Dependencies:   mbed Adafruit_FONA_3G

main.cpp

Committer:
Nels885
Date:
2019-02-27
Revision:
0:ea718d60afce

File content as of revision 0:ea718d60afce:

/*************************************************** 
  This is an example 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
  ----> http://www.adafruit.com/products/2468
  ----> http://www.adafruit.com/products/2542
 
  These cellular modules 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 Marc PLOUHINEC 27/06/2015 for use in mbed
  *  Modified by Lionel VOIRIN 27/02/2019 for use FONA 3G
  */
 
/* 
THIS CODE IS STILL IN PROGRESS!
 
Open up the serial console on the Arduino at 4800 baud to interact with FONA
 
Note that if you need to set a GPRS APN, username, and password scroll down to
the commented section below just before the main "while (true)" loop.
*/

#include <ctype.h>
#include "mbed.h"

#include "Adafruit_FONA.h"

#define FONA_KEY        p8
#define FONA_RST        p15
#define FONA_TX         p13
#define FONA_RX         p14

#define FONA_BAUDRATE   115200
#define PC_BAUDRATE     115200

// this is a large buffer for replies
char replybuffer[255];

Serial pcSerial(USBTX, USBRX);
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_KEY);

// Functions defined after main()
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;
void printMenu(void);
void flushSerial();
char readBlocking();
uint16_t readnumber();
long map(long x, long in_min, long in_max, long out_min, long out_max);

int main()
{
    pcSerial.baud(PC_BAUDRATE);
    wait(1);
    pcSerial.printf("\r\n");

    pcSerial.printf("FONA basic test\r\n");
    pcSerial.printf("Initializing....(May take 3 seconds)\r\n");

    // See if the FONA is responding
    if (! fona.begin(FONA_BAUDRATE)) {
        pcSerial.printf("Couldn't find FONA\r\n");
        while (1);
    }
    type = fona.type();
    pcSerial.printf("FONA is OK\r\n");
    pcSerial.printf("Found ");
    switch (type) {
        case FONA800L:
            pcSerial.printf("FONA 800L\r\n");
            break;
        case FONA800H:
            pcSerial.printf("FONA 800H\r\n");
            break;
        case FONA808_V1:
            pcSerial.printf("FONA 808 (v1)\r\n");
            break;
        case FONA808_V2:
            pcSerial.printf("FONA 808 (v2)\r\n");
            break;
        case FONA3G_A:
            pcSerial.printf("FONA 3G (American)\r\n");
            break;
        case FONA3G_E:
            pcSerial.printf("FONA 3G (European)\r\n");
            break;
        default:
            pcSerial.printf("???\r\n");
            break;
    }
    
    // Print SIM card IMEI number.
    char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
    uint8_t imeiLen = fona.getIMEI(imei);
    if (imeiLen > 0) {
        pcSerial.printf("SIM card IMEI: %s\r\n", imei);
    }

    printMenu();

    while (true) {
        pcSerial.printf("FONA> ");
        while (! pcSerial.readable() ) {
            if (fona.readable()) {
                pcSerial.putc(fona.getc());
            }
        }

        char command = pcSerial.getc();
        pcSerial.printf("%c\r\n", command);


        switch (command) {
            case '?': {
                printMenu();
                break;
            }

            case 'a': {
                // read the ADC
                uint16_t adc;
                if (! fona.getADCVoltage(&adc)) {
                    pcSerial.printf("Failed to read ADC\r\n");
                } else {
                    pcSerial.printf("ADC = %d mV\r\n", adc);
                }
                break;
            }

            case 'b': {
                // read the battery voltage and percentage
                uint16_t vbat;
                if (! fona.getBattVoltage(&vbat)) {
                    pcSerial.printf("Failed to read Batt\r\n");
                } else {
                    pcSerial.printf("VBat = %d mV\r\n", vbat);
                }

                if (! fona.getBattPercent(&vbat)) {
                    pcSerial.printf("Failed to read Batt\r\n");
                } else {
                    pcSerial.printf("VPct = %d%%\r\n", vbat);
                }

                break;
            }

            case 'U': {
                // Unlock the SIM with a PIN code
                char PIN[5];
                flushSerial();
                pcSerial.printf("Enter 4-digit PIN\r\n");
                readline(PIN, 3);
                pcSerial.printf("%s\r\n", PIN);
                pcSerial.printf("Unlocking SIM card: ");
                if (! fona.unlockSIM(PIN)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            case 'C': {
                // read the CCID
                fona.getSIMCCID(replybuffer);  // make sure replybuffer is at least 21 bytes!
                pcSerial.printf("SIM CCID = %s\r\n", replybuffer);
                break;
            }

            case 'i': {
                // 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);
                }
                pcSerial.printf("%d dBm\r\n", r);

                break;
            }

            case 'n': {
                // read the network/cellular status
                uint8_t n = fona.getNetworkStatus();
                pcSerial.printf("Network status %d: ", n);
                if (n == 0) pcSerial.printf("Not registered\r\n");
                if (n == 1) pcSerial.printf("Registered (home)\r\n");
                if (n == 2) pcSerial.printf("Not registered (searching)\r\n");
                if (n == 3) pcSerial.printf("Denied\r\n");
                if (n == 4) pcSerial.printf("Unknown\r\n");
                if (n == 5) pcSerial.printf("Registered roaming\r\n");
                break;
            }

            /*** Audio ***/
            case 'v': {
                // set volume
                flushSerial();
                pcSerial.printf("Set Vol %%");
                uint8_t vol = readnumber();
                pcSerial.printf("\r\n");
                if (! fona.setVolume(vol)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            case 'V': {
                uint8_t v = fona.getVolume();
                pcSerial.printf("%d%%\r\n", v);

                break;
            }

            case 'H': {
                // Set Headphone output
                if (! fona.setAudio(FONA_HEADSETAUDIO)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                fona.setMicVolume(FONA_HEADSETAUDIO, 15);
                break;
            }
            case 'e': {
                // Set External output
                if (! fona.setAudio(FONA_EXTAUDIO)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }

                fona.setMicVolume(FONA_EXTAUDIO, 10);
                break;
            }

            case 'T': {
                // play tone
                flushSerial();
                pcSerial.printf("Play tone #");
                uint8_t kittone = readnumber();
                pcSerial.printf("\r\n");
                // play for 1 second (1000 ms)
                if (! fona.playToolkitTone(kittone, 1000)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            /*** FM Radio ***/

            case 'f': {
                // get freq
                flushSerial();
                pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): ");
                uint16_t station = readnumber();
                pcSerial.printf("\r\n");
                // FM radio ON using headset
                if (fona.FMradio(true, FONA_HEADSETAUDIO)) {
                    pcSerial.printf("Opened\r\n");
                }
                if (! fona.tuneFMradio(station)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("Tuned\r\n");
                }
                break;
            }
            case 'F': {
                // FM radio off
                if (! fona.FMradio(false)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }
            case 'm': {
                // Set FM volume.
                flushSerial();
                pcSerial.printf("Set FM Vol [0-6]:");
                uint8_t vol = readnumber();
                pcSerial.printf("\r\n");
                if (!fona.setFMVolume(vol)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }
            case 'M': {
                // Get FM volume.
                int8_t fmvol = fona.getFMVolume();
                if (fmvol < 0) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("FM volume: %d\r\n", fmvol);
                }
                break;
            }
            case 'q': {
                // Get FM station signal level (in decibels).
                flushSerial();
                pcSerial.printf("FM Freq (eg 1011 == 101.1 MHz): ");
                uint16_t station = readnumber();
                pcSerial.printf("\r\n");
                int8_t level = fona.getFMSignalLevel(station);
                if (level < 0) {
                    pcSerial.printf("Failed! Make sure FM radio is on (tuned to station).\r\n");
                } else {
                    pcSerial.printf("Signal level (dB): %d\r\n", level);
                }
                break;
            }

            /*** PWM ***/

            case 'P': {
                // PWM Buzzer output @ 2KHz max
                flushSerial();
                pcSerial.printf("PWM Freq, 0 = Off, (1-2000): ");
                uint16_t freq = readnumber();
                pcSerial.printf("\r\n");
                if (! fona.setPWM(freq)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            /*** Call ***/
            case 'c': {
                // call a phone!
                char number[30];
                flushSerial();
                pcSerial.printf("Call #");
                readline(number, 30);
                pcSerial.printf("\r\n");
                pcSerial.printf("Calling %s\r\n", number);
                if (!fona.callPhone(number)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("Sent!\r\n");
                }

                break;
            }
            case 'h': {
                // hang up!
                if (! fona.hangUp()) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            case 'p': {
                // pick up!
                if (! fona.pickUp()) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("OK!\r\n");
                }
                break;
            }

            /*** SMS ***/

            case 'N': {
                // read the number of SMS's!
                int8_t smsnum = fona.getNumSMS();
                if (smsnum < 0) {
                    pcSerial.printf("Could not read # SMS\r\n");
                } else {
                    pcSerial.printf("%d SMS's on SIM card!\r\n", smsnum);
                }
                break;
            }
            case 'r': {
                // read an SMS
                flushSerial();
                pcSerial.printf("Read #");
                uint8_t smsn = readnumber();
                pcSerial.printf("\r\nReading SMS #%d\r\n", smsn);

                // Retrieve SMS sender address/phone number.
                if (! fona.getSMSSender(smsn, replybuffer, 250)) {
                    pcSerial.printf("Failed!\r\n");
                    break;
                }
                pcSerial.printf("FROM: %s\r\n", replybuffer);

                // Retrieve SMS value.
                uint16_t smslen;
                if (! fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len!
                    pcSerial.printf("Failed!\r\n");
                    break;
                }
                pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen);
                pcSerial.printf("%s\r\n", replybuffer);
                pcSerial.printf("*****\r\n");

                break;
            }
            case 'R': {
                // read all SMS
                int8_t smsnum = fona.getNumSMS();
                uint16_t smslen;
                for (int8_t smsn=1; smsn<=smsnum; smsn++) {
                    pcSerial.printf("\r\nReading SMS #%d\r\n", smsn);
                    if (!fona.readSMS(smsn, replybuffer, 250, &smslen)) {  // pass in buffer and max len!
                        pcSerial.printf("Failed!\r\n");
                        break;
                    }
                    // if the length is zero, its a special case where the index number is higher
                    // so increase the max we'll look at!
                    if (smslen == 0) {
                        pcSerial.printf("[empty slot]\r\n");
                        smsnum++;
                        continue;
                    }

                    pcSerial.printf("***** SMS #%d (%d) bytes *****\r\n", smsn, smslen);
                    pcSerial.printf("%s\r\n", replybuffer);
                    pcSerial.printf("*****\r\n");
                }
                break;
            }

            case 'd': {
                // delete an SMS
                flushSerial();
                pcSerial.printf("Delete #");
                uint8_t smsn = readnumber();

                pcSerial.printf("\r\nDeleting SMS #%d\r\n", smsn);
                if (fona.deleteSMS(smsn)) {
                    pcSerial.printf("OK!\r\n");
                } else {
                    pcSerial.printf("Couldn't delete\r\n");
                }
                break;
            }

            case 's': {
                // send an SMS!
                char sendto[21], message[141];
                flushSerial();
                pcSerial.printf("Send to #");
                readline(sendto, 11);
                pcSerial.printf("%s\r\n", sendto);
                pcSerial.printf("Type out one-line message (140 char): ");
                readline(message, 10);
                pcSerial.printf("%s\r\n", message);
                if (!fona.sendSMS(sendto, message)) {
                    pcSerial.printf("Failed\r\n");
                } else {
                    pcSerial.printf("Sent!\r\n");
                }

                break;
            }

            /*** Time ***/

            case 'y': {
                // enable network time sync
                if (!fona.enableNetworkTimeSync(true))
                    pcSerial.printf("Failed to enable\r\n");
                break;
            }

            case 'Y': {
                // enable NTP time sync
                if (!fona.enableNTPTimeSync(true, "pool.ntp.org"))
                    pcSerial.printf("Failed to enable\r\n");
                break;
            }

            case 't': {
                // read the time
                char buffer[23];

                fona.getTime(buffer, 23);  // make sure replybuffer is at least 23 bytes!
                pcSerial.printf("Time = %s\r\n", buffer);
                break;
            }

            /*********************************** GPS (SIM808 only) */

            case 'o': {
                // turn GPS off
                if (!fona.enableGPS(false))
                    pcSerial.printf("Failed to turn off\r\n");
                break;
            }
            case 'O': {
                // turn GPS on
                if (!fona.enableGPS(true))
                    pcSerial.printf("Failed to turn on\r\n");
                break;
            }
            case 'x': {
                int8_t stat;
                // check GPS fix
                stat = fona.GPSstatus();
                if (stat < 0)
                    pcSerial.printf("Failed to query\r\n");
                if (stat == 0) pcSerial.printf("GPS off\r\n");
                if (stat == 1) pcSerial.printf("No fix\r\n");
                if (stat == 2) pcSerial.printf("2D fix\r\n");
                if (stat == 3) pcSerial.printf("3D fix\r\n");
                break;
            }

            case 'L': {
                // check for GPS location
                char gpsdata[80];
                fona.getGPS(0, gpsdata, 80);
                pcSerial.printf("Reply in format: mode,longitude,latitude,altitude,utctime(yyyymmddHHMMSS),ttff,satellites,speed,course\r\n");
                pcSerial.printf("%s\r\n", gpsdata);

                break;
            }

            case 'E': {
                flushSerial();
                pcSerial.printf("GPS NMEA output sentences (0 = off, 34 = RMC+GGA, 255 = all)\r\n");
                uint8_t nmeaout = readnumber();

                // turn on NMEA output
                fona.enableGPSNMEA(nmeaout);

                break;
            }

            /*********************************** GPRS */

            case 'g': {
                // turn GPRS off
                if (!fona.enableGPRS(false))
                    pcSerial.printf("Failed to turn off\r\n");
                break;
            }
            case 'G': {
                // turn GPRS on
                if (!fona.enableGPRS(true))
                    pcSerial.printf("Failed to turn on\r\n");
                break;
            }
            case 'l': {
                // check for GSMLOC (requires GPRS)
                uint16_t returncode;

                if (!fona.getGSMLoc(&returncode, replybuffer, 250))
                    pcSerial.printf("Failed!\r\n");
                if (returncode == 0) {
                    pcSerial.printf("%s\r\n", replybuffer);
                } else {
                    pcSerial.printf("Fail code #%d\r\n", returncode);
                }

                break;
            }
            case 'w': {
                // read website URL
                uint16_t statuscode;
                int16_t length;
                char url[80];

                flushSerial();
                pcSerial.printf("NOTE: in beta! Use small webpages to read!\r\n");
                pcSerial.printf("URL to read (e.g. www.adafruit.com/testwifi/index.html):\r\n");
                pcSerial.printf("http://");
                readline(url, 79);
                pcSerial.printf("%s\r\n", url);

                pcSerial.printf("****\r\n");
                if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) {
                    pcSerial.printf("Failed!\r\n");
                    break;
                }
                while (length > 0) {
                    while (fona.readable()) {
                        char c = fona.getc();
                        pcSerial.putc(c);
                        length--;
                        if (! length) break;
                    }
                }
                pcSerial.printf("\r\n****\r\n");
                fona.HTTP_GET_end();
                break;
            }

            case 'W': {
                // Post data to website
                uint16_t statuscode;
                int16_t length;
                char url[80];
                char data[80];

                flushSerial();
                pcSerial.printf("NOTE: in beta! Use simple websites to post!\r\n");
                pcSerial.printf("URL to post (e.g. httpbin.org/post):\r\n");
                pcSerial.printf("http://");
                readline(url, 79);
                pcSerial.printf("%s\r\n", url);
                pcSerial.printf("Data to post (e.g. \"foo\" or \"{\"simple\":\"json\"}\"):\r\n");
                readline(data, 79);
                pcSerial.printf("%s\r\n", data);

                pcSerial.printf("****\r\n");
                if (!fona.HTTP_POST_start(url, "text/plain", (uint8_t *) data, strlen(data), &statuscode, (uint16_t *)&length)) {
                    pcSerial.printf("Failed!\r\n");
                    break;
                }
                while (length > 0) {
                    while (fona.readable()) {
                        char c = fona.getc();
                        pcSerial.putc(c);
                        length--;
                        if (! length) break;
                    }
                }
                pcSerial.printf("\r\n****\r\n");
                fona.HTTP_POST_end();
                break;
            }
            /*****************************************/

            case 'S': {
                pcSerial.printf("Creating SERIAL TUBE\r\n");
                while (1) {
                    while (pcSerial.readable()) {
                        wait_ms(1);
                        fona.putc(pcSerial.getc());
                    }
                    if (fona.readable()) {
                        pcSerial.putc(fona.getc());
                    }
                }
            }

            default: {
                pcSerial.printf("Unknown command\r\n");
                break;
            }
        }
        // flush input
        flushSerial();
        while (fona.readable()) {
            pcSerial.putc(fona.getc());
        }
    }

}


void printMenu(void)
{
    pcSerial.printf("-------------------------------------\r\n");
    pcSerial.printf("[?] Print this menu\r\n");
    pcSerial.printf("[a] read the ADC (2.8V max)\r\n");
    pcSerial.printf("[b] read the Battery V and %% charged\r\n");
    pcSerial.printf("[C] read the SIM CCID\r\n");
    pcSerial.printf("[U] Unlock SIM with PIN code\r\n");
    pcSerial.printf("[i] read RSSI\r\n");
    pcSerial.printf("[n] get Network status\r\n");
    pcSerial.printf("[v] set audio Volume\r\n");
    pcSerial.printf("[V] get Volume\r\n");
    pcSerial.printf("[H] set Headphone audio\r\n");
    pcSerial.printf("[e] set External audio\r\n");
    pcSerial.printf("[T] play audio Tone\r\n");
    pcSerial.printf("[P] PWM/Buzzer out\r\n");

    // FM (SIM800 only)
    pcSerial.printf("[f] tune FM radio\r\n");
    pcSerial.printf("[F] turn off FM\r\n");
    pcSerial.printf("[m] set FM volume\r\n");
    pcSerial.printf("[M] get FM volume\r\n");
    pcSerial.printf("[q] get FM station signal level\r\n");

    // Phone
    pcSerial.printf("[c] make phone Call\r\n");
    pcSerial.printf("[h] Hang up phone\r\n");
    pcSerial.printf("[p] Pick up phone\r\n");

    // SMS
    pcSerial.printf("[N] Number of SMSs\r\n");
    pcSerial.printf("[r] Read SMS #\r\n");
    pcSerial.printf("[R] Read All SMS\r\n");
    pcSerial.printf("[d] Delete SMS #\r\n");
    pcSerial.printf("[s] Send SMS\r\n");

    // Time
    pcSerial.printf("[y] Enable network time sync\r\n");
    pcSerial.printf("[Y] Enable NTP time sync (GPRS)\r\n");
    pcSerial.printf("[t] Get network time\r\n");

    // GPRS
    pcSerial.printf("[G] Enable GPRS\r\n");
    pcSerial.printf("[g] Disable GPRS\r\n");
    pcSerial.printf("[l] Query GSMLOC (GPRS)\r\n");
    pcSerial.printf("[w] Read webpage (GPRS)\r\n");
    pcSerial.printf("[W] Post to website (GPRS)\r\n");

    // GPS
    pcSerial.printf("[O] Turn GPS on (SIM808)\r\n");
    pcSerial.printf("[o] Turn GPS off (SIM808)\r\n");
    pcSerial.printf("[x] GPS fix status (SIM808)\r\n");
    pcSerial.printf("[L] Query GPS location (SIM808)\r\n");
    pcSerial.printf("[E] Raw NMEA out (SIM808)\r\n");

    pcSerial.printf("[S] create Serial passthru tunnel\r\n");
    pcSerial.printf("-------------------------------------\r\n");
    pcSerial.printf("\r\n");
}

void flushSerial()
{
    while (pcSerial.readable())
        pcSerial.getc();
}

char readBlocking()
{
    while (!pcSerial.readable());
    return pcSerial.getc();
}

uint16_t readnumber()
{
    uint16_t x = 0;
    char c;
    while (! isdigit(c = readBlocking())) {
        //pcSerial.putc(c);
    }
    pcSerial.putc(c);
    x = c - '0';
    while (isdigit(c = readBlocking())) {
        pcSerial.putc(c);
        x *= 10;
        x += c - '0';
    }
    return x;
}

uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout)
{
    uint16_t buffidx = 0;
    bool timeoutvalid = true;
    if (timeout == 0) timeoutvalid = false;

    while (true) {
        if (buffidx > maxbuff) {
            //pcSerial.printf("SPACE\r\n");
            break;
        }

        while(pcSerial.readable()) {
            char c =  pcSerial.getc();

            //pcSerial.printf("%02x#%c\r\n", c, c);

            if (c == '\r') continue;
            if (c == 0xA) {
                if (buffidx == 0)   // the first 0x0A is ignored
                    continue;

                timeout = 0;         // the second 0x0A is the end of the line
                timeoutvalid = true;
                break;
            }
            buff[buffidx] = c;
            buffidx++;
        }

        if (timeoutvalid && timeout == 0) {
            //pcSerial.printf("TIMEOUT\r\n");
            break;
        }
        wait_ms(1);
    }
    buff[buffidx] = 0;  // null term
    return buffidx;
}

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;
}