Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

AlohaTransceiver.cpp

Committer:
rba90
Date:
2016-07-17
Revision:
7:bc08d51535b6
Parent:
6:f545f5aa7de3
Child:
8:4bda842f73d4

File content as of revision 7:bc08d51535b6:

#include "AlohaTransceiver.h"
#include "mbed.h"
#include "radio.h"
#include "AlohaFrame.h"

// declear the type of radio state
typedef enum
{
    LOWPOWER = 0,
    IDLE,

    RX,
    RX_TIMEOUT,
    RX_ERROR,

    TX,
    TX_TIMEOUT,

    CAD,
    CAD_DONE
}AppStates_t;

// radio driver related variables
static uint16_t BufferSize;
static uint8_t Buffer[BUFFER_SIZE];

static int16_t RssiValue;
static int8_t SnrValue;

static volatile AppStates_t State;
static RadioEvents_t RadioEvents;

// callback functions for radio driver
void OnTxDone();
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
void OnTxTimeout();
void OnRxTimeout();
void OnRxError();
void OnFhssChangeChannel( uint8_t channelIndex );
void OnCadDone();

// radio driver
#ifdef BUILD_FOR_BS
SX1276MB1xAS Radio( NULL );
#endif

#ifdef BUILD_FOR_TERMINAL
SX1276inAir Radio( NULL );
#endif


/*
 * Abstract interface for accessing radio driver
 */

AlohaTransceiver::AlohaTransceiver()
{
    // configure properties
#if USE_MODEM_LORA == 1
    Settings.Power = TX_OUTPUT_POWER;
    Settings.Bandwidth = LORA_BANDWIDTH;
    Settings.Datarate = LORA_SPREADING_FACTOR;
    Settings.Coderate = LORA_CODINGRATE;
    Settings.PreambleLen = LORA_PREAMBLE_LENGTH;
    Settings.SymbolTimeout = LORA_SYMBOL_TIMEOUT;
    Settings.FixLen = LORA_FIX_LENGTH_PAYLOAD_ON;
    Settings.PayloadLen = 0;
    Settings.CrcOn = LORA_CRC_ENABLED;
    Settings.FreqHopOn = LORA_FHSS_ENABLED;
    Settings.HopPeriod = LORA_NB_SYMB_HOP;
    Settings.IqInverted = LORA_IQ_INVERSION_ON;
    Settings.RxContinuous = true;
    Settings.TxTimeout = TX_TIMEOUT_VALUE;

#elif USE_MODEM_FSK == 1
    // TODO: Complete settings for FSK mode
    #error "FSK not implemented"
#else
    #error "Please define a modem in the compiler options."
#endif
}

AlohaTransceiver::~AlohaTransceiver()
{

}

void AlohaTransceiver::boardInit()
{
    // configure callback functions
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.RxError = OnRxError;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    Radio.Init( &RadioEvents );

    // verify the connection with the board
    while( Radio.Read( REG_VERSION ) == 0x00  )
    {
        printf( "Radio could not be detected!\n\r" );
        wait( 1 );
    }
    printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
}

void AlohaTransceiver::updateSettings()
{
    Radio.SetChannel( RF_FREQUENCY );
#if USE_MODEM_LORA == 1

    Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
                         Settings.Datarate, Settings.Coderate,
                         Settings.PreambleLen, Settings.FixLen,
                         Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
                         Settings.IqInverted, Settings.TxTimeout );

    Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
                         Settings.Coderate, 0, Settings.PreambleLen,
                         Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
                         Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
                         Settings.IqInverted, Settings.RxContinuous );

#elif USE_MODEM_FSK == 1
    #error "FSK not implemented"
#else
    #error "Please define a modem in the compiler options."
#endif
}

void AlohaTransceiver::enable()
{
    // entering passive receiver mode
    Radio.Rx( RX_TIMEOUT_VALUE );
}

void AlohaTransceiver::poll()
{
    switch( State )
    {
        case RX:
        {   
            // create new frame instance
            AlohaFrame frame(Buffer, BufferSize);
            
            // execute callback functions
            if (AlohaTypeCallbackTable[frame.getType()] != NULL)
            {
                AlohaTypeCallbackTable[frame.getType()](&frame);
            }

            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        }
        case TX:
        {
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        }
        case RX_TIMEOUT:
        {
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        }
        case RX_ERROR:
        {
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        }
        case TX_TIMEOUT:
        {
            Radio.Rx( RX_TIMEOUT_VALUE );
            State = LOWPOWER;
            break;
        }
        case LOWPOWER:
        {
            break;
        }
        default:
        {
            State = LOWPOWER;
            break;
        }
    }
}

void AlohaTransceiver::send(uint8_t *buffer, int length)
{
    Radio.Rx( 0 );
    Radio.Send(buffer, length);
    Radio.Rx( RX_TIMEOUT_VALUE );
}

void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
{
    AlohaTypeCallbackTable[type] = f;
}

void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
{
    AlohaTypeCallbackTable[type] = NULL;
}

int16_t AlohaTransceiver::getRssi()
{
    return RssiValue;
}

int8_t AlohaTransceiver::getSnr()
{
    return SnrValue;
}

void OnTxDone( void )
{
    Radio.Sleep( );
    State = TX;
    printf( "> OnTxDone\n\r" );
}

void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Radio.Sleep( );

    // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
    BufferSize = size ? BUFFER_SIZE : size <= BUFFER_SIZE;

    memcpy( Buffer, payload, BufferSize );
    RssiValue = rssi;
    SnrValue = snr;
    State = RX;
    printf( "> OnRxDone\n\r" );
}

void OnTxTimeout( void )
{
    Radio.Sleep( );
    State = TX_TIMEOUT;
    printf( "> OnTxTimeout\n\r" );
}

void OnRxTimeout( void )
{
    Radio.Sleep( );
    Buffer[ BufferSize ] = 0;
    State = RX_TIMEOUT;
    printf( "> OnRxTimeout\n\r" );
}

void OnRxError( void )
{
    Radio.Sleep( );
    State = RX_ERROR;
    printf( "> OnRxError\n\r" );
}