This software example demonstrates the downlink capabilities of the SIGFOX network.

Dependencies:   QW_Sensors mbed

Fork of HelloWorld - QW Development kit by Quicksand micro-electronics

main.cpp

Committer:
quicksand
Date:
2017-03-14
Revision:
4:1d707586e24d
Parent:
3:4da15d6e1429

File content as of revision 4:1d707586e24d:

#include "mbed.h"
#include "math.h"

/* The 4 onboard LEDs */
BusOut leds(PB_6, PA_7, PA_6, PA_5);

/*
DigitalOut LED_0 (PB_6);
DigitalOut LED_1 (PA_7);
DigitalOut LED_2 (PA_6);
DigitalOut LED_3 (PA_5);
*/

/* The 2 user buttons */
InterruptIn SW1(PA_8);
InterruptIn SW2(PB_10);

/* Function prototypes */
void buttoninterrupt();
void beat();
void sertmout();
bool modem_command_check_ok(char * command);
void modem_setup();
void downlink();
void error();

bool ser_timeout = false;
bool go_downlink = false;

/* Serial port over USB */
Serial pc(USBTX, USBRX);

/* Serial connection to sigfox modem */
Serial modem(PA_9, PA_10);

void binToString(char *inputData, int dataLength, char *outputData)   // Note outputdata must be 2 x inputdata + 1 in size!
{

    for (int i = 0; i<dataLength; i++) {
        sprintf(outputData+2*i,"%02X",*(inputData+i));
    }
    outputData[dataLength*2] = 0; // in theory redundant, the last sprintf should have done this but just to be sure...
}

void error()
{
    pc.printf("Something went wrong, please try again\n\r");
    int i = 0;
    // Failure, blink rapidly:
    while(i < 25) {
        leds = 0b0000;
        wait_ms(100);
        leds = 0b1111;
        wait_ms(100);
        i++;
    }
}

/* Button 1 ISR */
void buttoninterrupt()
{
    go_downlink = true;
}

int main()
{

    /* Setup TD120x */
    wait(3);
    modem_setup();
    leds = 0b1111;
    /* Setup button interrupts */
    SW2.fall(&buttoninterrupt);
    SW1.fall(&buttoninterrupt);

    while(1) {
        if(go_downlink) {
            downlink();
            go_downlink = false;
        }
        if(pc.readable()) {
            modem.putc(pc.getc());
        }
        if(modem.readable()) {
            pc.putc(modem.getc());
        }
    }
}

void downlink()
{
    leds = 0b0000;
    pc.printf("Requesting bidirectional data\n\r");
    if(modem_command_check_ok("AT$SF=0102030405060708090A0B0C,2,1")) {
        pc.printf("Done sending request, waiting to start reception...\n\r");
        char * beginString = "+RX BEGIN";
        char * beginStringPtr;
        beginStringPtr = beginString;
        bool begin_rx = false;

        /* Turn off all LED*/
        leds = 0b1111;
        /* Timeout */
        Timeout tmout;
        ser_timeout = false;
        tmout.attach(&sertmout, 35.0);
        /* Animation while waiting for downlink */
        int c;
        int animation = 0;
        while(!ser_timeout && !begin_rx) {

            while (modem.readable() && !ser_timeout && !begin_rx) {
                c = modem.getc();
                if ( (char)c == *beginStringPtr ) beginStringPtr++;
                else beginStringPtr = beginString;
                if ( *beginStringPtr == 0 ) {
                    begin_rx = true;
                    pc.printf("Entering reception window\n\r");
                }
            }
            animation = (animation + 1)%150000;
            if(animation == 0)      leds = 0b1110;
            if(animation == 25000)  leds = 0b1101;
            if(animation == 50000)  leds = 0b1011;
            if(animation == 75000)  leds = 0b0111;
            if(animation == 100000) leds = 0b1011;
            if(animation == 125000) leds = 0b1101;
        }
        /* turn off timeout timer */
        tmout.detach();
        if(ser_timeout) error();
        else {
            /* Turn on outer LEDs*/
            leds = 0b0110;
            /* Read the data */
            // check if reception window ended
            char * readyString = "+RX END";
            char * readyStringPtr;
            readyStringPtr = readyString;
            bool rx_ready = false;
            int c;
            char rx_buffer[128];
            int i = 0;
            int j = 0;
            tmout.attach(&sertmout, 30.0);
            ser_timeout = false;
            while(modem.readable() && !ser_timeout && !rx_ready)
                while (((c = modem.getc()) > 0) && !ser_timeout && !rx_ready) {
                    rx_buffer[i++] = (char)c;
                    pc.putc((char)c);
                    if ( (char)c == *readyStringPtr ) readyStringPtr++;
                    else readyStringPtr = readyString;
                    if ( *readyStringPtr == 0 ) {
                        rx_ready = true;
                    }
                }
            rx_buffer[i++] = 0; // EOS
            tmout.detach();
            if(ser_timeout) error();
            else {
                /* Turn off all LED*/
                leds = 0b1111;
                pc.printf("\n\rReception done, received data:\n\r");
                /* removing spaces, new lines, start and end markings */
                for(i = 0, j = 0; i < strlen(rx_buffer); i++) {
                    rx_buffer[i-j] = rx_buffer[i];
                    if(rx_buffer[i] == ' ' || rx_buffer[i] == '\n' || rx_buffer[i] == '\r' || rx_buffer[i] == '+' || rx_buffer[i] == '=' || (rx_buffer[i] > 'A' && rx_buffer[i] < 'Z'))
                        j++;
                }
                /* do not forget EOS again! */
                rx_buffer[i-j] = 0;

                if(strlen(rx_buffer) != 0) {
                    /* Print received data without spaces and markers */
                    for(j = 0; j < strlen(rx_buffer); j++) pc.putc(rx_buffer[j]);

                    char buff[32];

                    /* Extract tap and store to int (in this case you would have been able to just print the received data)*/
                    memcpy( buff, &rx_buffer[0], 8 );
                    buff[8] = '\0';
                    int tap = (int)strtol(buff, NULL, 16);

                    /* Extract Client data*/
                    memcpy( buff, &rx_buffer[8], 4 );
                    buff[4] = '\0';
                    int client = (int)strtol(buff, NULL, 16);

                    /* Exctract the RSSI */
                    memcpy( buff, &rx_buffer[12], 4 );
                    buff[4] = '\0';
                    int16_t rssi = (int16_t)strtol(buff, NULL, 16);

                    pc.printf("\n\rMessage received on tap: %X\n\r", tap);
                    pc.printf("Client data: %X\n\r", client);
                    pc.printf("RSSI level: %d\n\r", rssi);

                    if(rssi > -90) leds = 0b0000;
                    else if (rssi > -110) leds = 0b0001;
                    else if (rssi > -130) leds = 0b0011;
                    else leds = 0b0111;
                } else {
                    pc.printf("\n\rNo valid downlink data received!\n\r");
                    error();
                }
            }
        }


    } else {
        // Failure, blink rapidly indefinetly:
        error();
    }
}

void modem_setup()
{
    /* Reset to factory defaults */
    if(modem_command_check_ok("AT&F")) {
        pc.printf("Factory reset succesfull\r\n");
    } else {
        pc.printf("Factory reset TD120x failed\r\n");
    }
    /* Disable local echo */
    modem.printf("ATE0\n");
    if(modem_command_check_ok("ATE0")) {
        pc.printf("Local echo disabled\r\n");
    }
    /* Write to mem */
    if(modem_command_check_ok("AT&W")) {
        pc.printf("Settings saved!\r\n");
    }
}

/* ISR for serial timeout */
void sertmout()
{
    ser_timeout = true;
}

bool modem_command_check_ok(char * command)
{
    /* first clear serial data buffers */
    while(modem.readable()) modem.getc();
    /* Timeout for response of the modem */
    Timeout tmout;
    ser_timeout = false;
    // check if ok or error is received
    char * readyString = "OK";
    char * readyStringPtr;
    readyStringPtr = readyString;
    char * errorString = "ERROR";
    char * errorStringPtr;
    errorStringPtr = errorString;
    /* Flag to set when we get 'OK' response */
    bool ok = false;
    bool error = false;
    /* Print command to TD120x */
    modem.printf(command);
    /* Newline to activate command */
    modem.printf("\n");
    /* Wait untill serial feedback, max 10 seconds before timeout */
    tmout.attach(&sertmout, 10.0);
    int c;
    while(!ser_timeout && !ok && !error)
        if(modem.readable())
            while (((c = modem.getc()) > 0) && !ser_timeout  && !ok && !error) {
                if ( (char)c == *readyStringPtr ) readyStringPtr++;
                else readyStringPtr = readyString;
                if ( *readyStringPtr == 0 ) {
                    ok = true;
                }
                if ( (char)c == *errorStringPtr ) errorStringPtr++;
                else errorStringPtr = errorString;
                if ( *errorStringPtr == 0 ) {
                    error = true;
                }
            }
    tmout.detach();
    if(ser_timeout) return false;
    else return ok;
}