Elmo Terminal provides functionality to test Lora radio and access SX1272 chip registers delivered with Elmo board. This firmware allows the user to control the LoRa radio parameters (eg. frequency, bandwidth, spreading factor etc.) by entering console commands via serial terminal. Application also contains "Ping-Pong" and data transmission functionalities.

Dependencies:   SX1272lib mbed

Fork of Elmo-Terminal by Michal Leksinski

RadioContex.cpp

Committer:
WGorniak
Date:
2015-10-22
Revision:
12:26045241f50f
Parent:
10:e4cbc7292f40

File content as of revision 12:26045241f50f:

#include "assert.h"

#include "RadioContex.h"
#include "Settings.h"
#include "dbg.h"


/* Set this flag to '1' to display debug messages on the console */

#define DEBUG_MESSAGE   0
#define RX_TIMEOUT_VALUE                                3500000   // in us
#define BUFFER_SIZE                                     32        // Define the payload size here

    // Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation
    #define USE_MODEM_LORA  1
    #define USE_MODEM_FSK   !USE_MODEM_LORA

    #if USE_MODEM_LORA == 1

        #define LORA_FIX_LENGTH_PAYLOAD_ON                  false
        #define LORA_FHSS_ENABLED                           false
        #define LORA_NB_SYMB_HOP                            4
        #define LORA_IQ_INVERSION_ON                        false
        #define LORA_CRC_ENABLED                            true

    #elif USE_MODEM_FSK == 1

        #define FSK_FDEV                                    25000     // Hz
        #define FSK_DATARATE                                19200     // bps
        #define FSK_BANDWIDTH                               50000     // Hz
        #define FSK_AFC_BANDWIDTH                           83333     // Hz
        #define FSK_PREAMBLE_LENGTH                         5         // Same for Tx and Rx
        #define FSK_FIX_LENGTH_PAYLOAD_ON                   false
        #define FSK_CRC_ENABLED                             true

    #else
        #error "Please define a modem in the compiler options."
    #endif


RadioContex* RadioContex::thi = 0;

const char* RadioContex::rx_error_msg = "rx_error";
const char* RadioContex::rx_timeout_msg = "rx_timeout";


RadioContex::RadioContex (Settings* settings)
    : radio_ (0)
{
    assert(thi == 0);
    thi = this;
    BufferSize = BUFFER_SIZE;
    State = LOWPOWER;

    sendCntr = 0;

    radio_ = new SX1272BRD ( RadioContex::StaticOnTxDone, RadioContex::StaticOnTxTimeout, RadioContex::StaticOnRxDone,
                                RadioContex::StaticOnRxTimeout, RadioContex::StaticOnRxError, NULL, NULL,
                                RF_SPI_MOSI, RF_SPI_MISO, RF_SPI_SCK, RF_SPI_CS,
                                RF_RESET, RF_DIO0, RF_DIO1, RF_DIO2, RF_DIO3, RF_DIO4, RF_DIO5,
                                RF_RXTX_SW );

    // verify the connection with the board
    while( radio_->Read( REG_VERSION ) == 0x00  )
    {
        debug( "Radio could not be detected!\n\r", NULL );
        wait( 1 );
    }

    radio_->SetChannel( settings->aget("freq") * 1000 );

#if USE_MODEM_LORA == 1

    debug_if( LORA_FHSS_ENABLED, "> Radio start LORA FHSS Mode < \n\r");
    debug_if( !LORA_FHSS_ENABLED, "> Radio start LORA Mode < \n\r");
    
    if (!settings->aget("paBoost"))
    {
        if(settings->aget("power")>14)
        {
            printf("RFO mode, limiting power to 14 dBm\r\n");
            settings->set("power",14);
        }
    }

    radio_->SetTxConfig( MODEM_LORA, settings->aget("power") , 0, settings->aget("bandwidth"),
                        settings->aget("dataRate"), settings->aget("codeRate"),
                        settings->aget("preambleLen"), LORA_FIX_LENGTH_PAYLOAD_ON,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, 2000000, settings->aget("paBoost"));

    radio_->SetRxConfig( MODEM_LORA, settings->aget("bandwidth"),
                        settings->aget("dataRate"), settings->aget("codeRate"), 0, settings->aget("preambleLen"),
                        settings->aget("symbTimeout"), LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
                         LORA_IQ_INVERSION_ON, true );

#elif USE_MODEM_FSK == 1

    debug("\n\n\r              > FSK Mode < \n\n\r");
    radio_->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
                         FSK_DATARATE, 0,
                         FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
                         FSK_CRC_ENABLED, 0, 0, 0, 2000000 );

    radio_->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
                         0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
                         0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
                         0, 0, false, true );

#else

#error "Please define a modem in the compiler options."

#endif

}


RadioContex::States_t RadioContex::getState() const
{
    return State;
}


bool RadioContex::setState(States_t newState)
{
    State = newState;
    return true;
}

extern std::string to_string(const int32_t val);

bool RadioContex::Send(std::string arg)
{
    std::string ss(" ");
    ss.append(to_string(sendCntr));
    arg.append(ss);

    const uint8_t* msg = (const unsigned char *)(arg.c_str());
    uint16_t msgSize = static_cast<uint16_t>(arg.size());

    strcpy( ( char* )Buffer, ( char* )msg );
    // We fill the buffer with numbers for the payload
    for(int i = msgSize; i < BufferSize; i++ )
    {
        Buffer[i] = i - msgSize;
    }
    sendCntr++;

    wait_ms( 10 );
    radio_->Send( Buffer, BufferSize );
    debug("%s\r\n", arg.c_str());
    return true;
}

bool RadioContex::initReceive()
{
    radio_->Rx( RX_TIMEOUT_VALUE );
    return true;
}

bool RadioContex::pool_rx()
{
    switch( State )
    {
    case RX:
        Buffer[BUFFER_SIZE-1] = 0;
        State = LOWPOWER;
        radio_->Rx( RX_TIMEOUT_VALUE );
//        Buffer[0] = 0;
        return true;
    case RX_TIMEOUT:
    case RX_ERROR:
    case IDLE:
        radio_->Rx( RX_TIMEOUT_VALUE );
        State = LOWPOWER;
        /* no break */
    case LOWPOWER:
        break;
    default:
        State = LOWPOWER;
    }
    return false;
}


Radio& RadioContex::radio()
{
    return *radio_;
}

RadioContex::~RadioContex ()
{
    radio_->Reset();
    delete radio_;
    thi = 0;
    debug( "> Radio stop <\n\r" );
    // TODO Auto-generated destructor stub
}

void RadioContex::StaticOnTxDone()
{
    thi->OnTxDone();
}

void RadioContex::StaticOnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    thi->OnRxDone(payload, size, rssi, snr);
}

void RadioContex::StaticOnTxTimeout( void )
{
    thi->OnTxTimeout();
}

void RadioContex::StaticOnRxTimeout( void )
{
    thi->OnRxTimeout();
}

void RadioContex::StaticOnRxError( void )
{
    thi->OnRxError();
}

void RadioContex::OnTxDone( void )
{
    radio_->Sleep( );
    State = TX;
    debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" );
}

void RadioContex::OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    radio_->Sleep( );
    BufferSize = size;
    memcpy( Buffer, payload, BufferSize );
    RssiValue = rssi;
    SnrValue = snr;
    State = RX;
    debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" );
}

void RadioContex::OnTxTimeout( void )
{
    radio_->Sleep( );
    State = TX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" );
}

void RadioContex::OnRxTimeout( void )
{
    radio_->Sleep( );
    Buffer[ BufferSize ] = 0;
    State = RX_TIMEOUT;
    debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" );
}

void RadioContex::OnRxError( void )
{
    radio_->Sleep( );
    State = RX_ERROR;
    debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" );
}