Elmo Terminal provides functionality to test Lora radio and access SX1272 chip registers delivered with Elmo board. Also contains example ping-pong application.

Dependencies:   SX1272lib mbed-src

RadioContex.cpp

Committer:
WGorniak
Date:
2015-10-01
Revision:
4:2767f13b0a75
Parent:
2:8d8295a51f68
Child:
6:453b018a9ba0

File content as of revision 4:2767f13b0a75:

#include "assert.h"

#include "RadioContex.h"
#include "Settings.h"
#include "dbg.h"
#include <sstream>


/* 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");

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


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

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