Aloha implementation of LoRa technology

Dependencies:   SX1276Lib mbed

Fork of SX1276PingPong by Semtech

main.cpp

Committer:
rba90
Date:
2016-05-31
Revision:
15:f790f35839db
Parent:
14:c7251480feb9
Child:
16:c3c6b13c3c42

File content as of revision 15:f790f35839db:

#include "mbed.h"
#include "main.h"
#include "sx1276-hal.h"
#include "debug.h"
#include "Aloha.h"
#include "AlohaPacket.h"

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

#define RF_FREQUENCY                                    868000000 // Hz
#define TX_OUTPUT_POWER                                 14        // 14 dBm
#define LORA_BANDWIDTH                              2         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         5         // Symbols
#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


#define RX_TIMEOUT_VALUE                                3500000   // in us
#define BUFFER_SIZE                                     4 // Define the payload size here

DigitalOut led(LED2);

uint16_t BufferSize = BUFFER_SIZE;
uint8_t Buffer[BUFFER_SIZE];

int16_t RssiValue = 0.0;
int8_t SnrValue = 0.0;

/*
 *  Global variables declarations
 */
typedef enum
{
    LOWPOWER = 0,
    IDLE,
    
    RX,
    RX_TIMEOUT,
    RX_ERROR,
    
    TX,
    TX_TIMEOUT,
    
    CAD,
    CAD_DONE
}AppStates_t;

volatile AppStates_t State = LOWPOWER;


/*!
 * Radio events function pointer
 */
static RadioEvents_t RadioEvents;

/*
 *  Global variables declarations
 */
SX1276MB1xAS Radio( NULL );

// aloha protocol
Aloha aloha;

void setExpire()
{
    if (aloha.attempts >= ALOHA_MAX_ATTEMPT)
    {
        aloha.state = Aloha::EXPIRED;
    }
    else
    {
        aloha.state = Aloha::RETRANSMIT;
        aloha.delay = aloha.delay * aloha.delay;
    }
}

void RadioInit()
{
    // Initialize Radio driver
    RadioEvents.TxDone = OnTxDone;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.RxError = OnRxError;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    Radio.Init( &RadioEvents );
    
    // detect radio hardware
    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 ));
    
    // set radio frequency channel
    Radio.SetChannel( RF_FREQUENCY ); 
    
    // set radio parameter
    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                         LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                         LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                         LORA_IQ_INVERSION_ON, 2000000 );
    
    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                         LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                         LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
                         LORA_IQ_INVERSION_ON, true );
}


int main() 
{  
    RadioInit();
    
    while (1)
    {
        switch( State )
        {
        case RX:
            // if the receive frame is an ack, then cancel the timer
            // otherwise process the frame
            HeaderStruct header;
            memset(&header, 0, sizeof(header));
            
            if (header.fid == 0x01)
            {
                aloha.AlohaAckTimeout.detach();
            }
            
            // TODO: process the frame
            break;
        case TX:
            // transmit done
            // then set state to aloha pending and start the timer
            aloha.state = Aloha::PENDING;
            aloha.delay = Radio.Random();
            aloha.AlohaAckTimeout.detach();
            aloha.AlohaAckTimeout.attach_us(&setExpire, aloha.delay);
            aloha.attempts += 1;
            break;
        case RX_TIMEOUT:
            // enter listening mode
            break;
        case RX_ERROR:
            // we don't handle crc failed situation
            break;
        case TX_TIMEOUT:
            // we don't handle hardware error
            break;
        case LOWPOWER:
            break;
        default:
            break;
        }
        
        switch (aloha.state)
        {
        case Aloha::IDLE:
            // transmit packet if any
            break;
        
        case Aloha::PENDING:
            // set rx time
            break;
            
        case Aloha::RETRANSMIT:
            // send the packet again
            // and setup the timer with new backoff delay
            aloha.AlohaAckTimeout.attach(&setExpire, aloha.delay);
            aloha.state = Aloha::PENDING;
            break;
        case Aloha::EXPIRED:
            // give up the transmission
            // back to idle
            aloha.state = Aloha::IDLE;
            break;
        }
    }
}

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