Basic MAC data interface for LoRa transceiver
Dependents: LoRaBaseStation LoRaTerminal
AlohaTransceiver.cpp
- Committer:
- rba90
- Date:
- 2016-08-11
- Revision:
- 17:c6e2e2cd6e5f
- Parent:
- 15:0dc9df48687a
- Child:
- 18:3e6483550f25
File content as of revision 17:c6e2e2cd6e5f:
#include "AlohaTransceiver.h" #include "mbed.h" #include "radio.h" #include "AlohaFrame.h" #include "RingBuffer.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(uint8_t id) { // store unique device id deviceId = id; // initialize sequenceid memset(seqid, 0x0, sizeof(seqid)); // 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( 0 ); } void AlohaTransceiver::poll() { switch( State ) { case RX: { // create new frame instance AlohaFrame frame(Buffer, BufferSize); // check destination // if the destination is the device id, then processing, otherwise drop the packet and continue // listening if (frame.getDestinationAddress() == (deviceId & 0x0f)) { // currently we only have 1 payload per frame uint8_t payload_length = frame.getPayloadLength(); uint8_t payload[payload_length]; uint8_t src_addr = frame.getSourceAddress(); uint8_t type = frame.getType(); // extract payload for (uint8_t i = 0; i < payload_length; i++) { payload[i] = frame.getPayload(i); } // check registered callback function // execute callback functions if registered if (AlohaTypeCallbackTable[type] != NULL) { AlohaTypeCallbackTable[type](payload, payload_length, src_addr); } } Radio.Rx( 0 ); State = LOWPOWER; break; } case TX: { Radio.Rx( 0 ); State = LOWPOWER; break; } case RX_TIMEOUT: { Radio.Rx( 0 ); State = LOWPOWER; break; } case RX_ERROR: { Radio.Rx( 0 ); State = LOWPOWER; break; } case TX_TIMEOUT: { Radio.Rx( 0 ); State = LOWPOWER; break; } case LOWPOWER: { break; } default: { State = LOWPOWER; break; } } } bool AlohaTransceiver::send(uint8_t *payload, uint8_t payload_length, uint8_t dest_addr) { // assume the user will not transmit payload longer than 16 bytes if (payload_length > 16) { return false; } // create a new frame AlohaFrame frame; uint8_t frame_length = payload_length + FIXED_BYTE; frame.setType(AlohaFrame::Aloha_Data); frame.setPayloadLength(payload_length); frame.setSourceAddress(deviceId); frame.setDestinationAddress(dest_addr & 0x0f); frame.setFullMessageFlag(0x1); frame.setSequenceID(seqid[dest_addr]++); // use dest_addr as key for accessing sequence id // the seqid should increase as it successfully transmit the packet for (uint8_t i = 0; i < payload_length; i++) { frame.setPayload(i, payload[i]); } // calculate crc frame.generateCrc(); // create a buffer for transmit uint8_t buffer[frame_length]; // 4 fix fields memset(buffer, 0x0, sizeof(buffer)); // copy content to buffer frame.serialize(buffer); // send to radio Radio.Send(buffer, frame_length); State = LOWPOWER; return true; } bool AlohaTransceiver::send(AlohaFrame *frame) { // TODO: finish this return false; } 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; } uint8_t AlohaTransceiver::getDeviceID() { return deviceId; } void AlohaTransceiver::setDeviceID(uint8_t id) { deviceId = id; } #if USE_MODEM_LORA == 1 AlohaTransceiver::LoRaSettings_t *AlohaTransceiver::getSettings() { return &Settings; } #elif USE_MODEM_FSK == 1 AlohaTransceiver::FskSettings_t *AlohaTransceiver::getSettings() { return &Settings; } #else #error "Please define a modem in the compiler options." #endif 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" ); }