This library is a Snootlab's library's translation to use Akene on mbed boards instead of Arduino ones. The functions Akene.begin() and Akene.send() work perfectly, but no real checkup has been made for the other functions. Feel free to implement what you want to make your device work on mbed.

Dependencies:   mbed

Akene.cpp

Committer:
Remitte
Date:
2015-11-27
Revision:
1:ce17068deacf
Parent:
0:48c5b5c0395e

File content as of revision 1:ce17068deacf:

/*
This file is a Snootlab's source code file's translation to use Akene on mbed boards instead of Arduino ones.
The functions Akene.begin() and Akene.send() work perfectly, but no real checkup has been made for the other functions.
Feel free to implement what you want to make your device work on mbed.

This translation is due to a Polytech Paris UPMC project led by Rémi Jourdain with the help of Clément Maciejewski.

Visit <http://snootlab.com>
Copyright (C) 2013-2015 Snootlab. All rights reserved.

Akene is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Akene is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Akene.  If not, see <http://www.gnu.org/licenses/>.
*/


#include "mbed.h"
#include "Akene.h"

Akene_ Akene;

Akene_::Akene_() :
    _serial(P4_28, P4_29) { //P4_25 = Tx P4_29 = Rx 
     //Since _lastSend is unsigned, this is infinity
    _lastSend = -1;
    _T.start();
}

Akene_::~Akene_() { 
    _T.stop();
}

void Akene_::begin() {
    _serial.baud(9600);
    //Remove un-ended commands from TST's buffer
    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)';');
    //Wait for the "KO;"
    while(_serial.readable() == 0);
    _serial.getc(); //'K'
    while(_serial.readable() == 0);
    _serial.getc(); //'O'
    while(_serial.readable() == 0);
    _serial.getc(); //';'
}


bool Akene_::isReady() {

    // IMPORTANT WARNING. PLEASE READ BEFORE MODIFYING THE CODE
    //
    // The Sigfox network operates on public frequencies. To comply with
    // radio regulation, it can send radio data a maximum of 1% of the time
    // to leave room to other devices using the same frequencies.
    //
    // Sending a message takes about 6 seconds (it's sent 3 times for
    // redundancy purposes), meaning the interval between messages should
    // be 10 minutes.
    //
    // Also make sure your send rate complies with the restrictions set
    // by the particular subscription contract you have with your Sigfox
    // network operator.
    //
    // FAILING TO COMPLY WITH THESE CONSTRAINTS MAY CAUSE YOUR MODEM
    // TO BE BLOCKED BY YOUR SIFGOX NETWORK OPERATOR.
    //
    // You've been warned!

    unsigned long currentTime = _T.read_ms();
    if(currentTime >= _lastSend && (currentTime - _lastSend) <= 600000) {
        return false;
    }

    // Time is ok, ask the modem's status
    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)'S');
    _serial.putc((uint8_t)'F');
    _serial.putc((uint8_t)'P');
    _serial.putc((uint8_t)';');

    return _nextReturn() == OK;
}

bool Akene_::send(const void* data, uint8_t len) {
    uint8_t* bytes = (uint8_t*)data;

    if(!isReady()) {
        return false;
    }

    // See comment in isReady()
    _lastSend = _T.read_ms();

    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)'S');
    _serial.putc((uint8_t)'F');
    _serial.putc((uint8_t)'M');
    _serial.putc(len);
    for(uint8_t i = 0; i < len; ++i) {
        _serial.putc(bytes[i]);
    }
    _serial.putc(';');

    uint8_t ok = _nextReturn();
    if(ok == OK) {
        _nextReturn(); //SENT
        return true;
    }
    return false;
}

uint8_t Akene_::getRev() {
    char c;
    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)'S');
    _serial.putc((uint8_t)'F');
    _serial.putc((uint8_t)'v');
    _serial.putc((uint8_t)';');

    while(_serial.readable() == 0);
    c = _serial.getc(); //'K' or something else
    if(c == 'K'){
    while(_serial.readable() == 0);
    _serial.getc(); //'O'
    while(_serial.readable() == 0);
    _serial.getc(); //';'
    return 0;
    }
    else {
    uint8_t rev = 10 * c - '0';
    while(_serial.readable() == 0);
    rev += (_serial.getc() - '0');
    while(_serial.readable() == 0);
        _serial.getc(); //'O'
    while(_serial.readable() == 0);
        _serial.getc(); //'K'
    while(_serial.readable() == 0);
        _serial.getc(); //';'
        return rev;
    }
}

unsigned long Akene_::getID() {
    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)'S');
    _serial.putc((uint8_t)'F');
    _serial.putc((uint8_t)'I');
    _serial.putc((uint8_t)'D');
    _serial.putc((uint8_t)';');

    //Response is [byte1, byte2, ..., byteN, 'O', 'K']
    uint8_t response[8] = {0};
    uint8_t i = 0;
    uint8_t c;
    while(!_serial.readable());
    c = _serial.getc();
    while(c != ';') {
        response[i] = c;
        while(!_serial.readable());
        ++i;
        c = _serial.getc();
    }

    unsigned long id = 0;

    for(uint8_t j = 0; j < i-2; ++j) {
        id += response[j] << ((i-3-j) * 8);
    }

    return id;
}
//Power value:
//0 -25 -30 dBm
//1 0dBm
//2 14dBm
//3 16dBm
//4 18dBm
//5 Max (18-19dBm)
bool Akene_::setPower(uint8_t power) {
    power = power % 6; //It's 0-5
    _serial.putc((uint8_t)'\0');
    _serial.putc((uint8_t)'S');
    _serial.putc((uint8_t)'F');
    _serial.putc((uint8_t)'G');
    _serial.putc(power);
    _serial.putc((uint8_t)';');

    return _nextReturn() == OK;
}

uint8_t Akene_::_nextReturn() {
    while(!_serial.readable());
    char fstChar = _serial.getc();
    while(_serial.getc() != ';');
    return fstChar;
}