Basic MAC data interface for LoRa transceiver
Dependents: LoRaBaseStation LoRaTerminal
AlohaTransceiver.cpp
- Committer:
- rba90
- Date:
- 2016-09-02
- Revision:
- 24:8f31c33c7675
- Parent:
- 23:4b51a8e27f6a
- Child:
- 25:bcd1cee4e5a8
File content as of revision 24:8f31c33c7675:
#include "AlohaTransceiver.h" #include "mbed.h" #include "radio.h" #include "debug.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 DRIVER_SX1276 SX1276MB1xAS Radio( NULL ); #endif #ifdef DRIVER_INAIR 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 ) { #ifdef DEBUG_ALOHA debug( "Radio could not be detected!\n\r" ); #endif wait( 1 ); } #ifdef DEBUG_ALOHA printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION )); #endif } 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: { // transmit packet when the radio is free if (AlohaTxQueue.getCounter() > 0) { AlohaFrame *frame = AlohaTxQueue.dequeue(); // create a buffer for transmit uint8_t frame_length = frame->getPayloadLength() + FIXED_BYTE; 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); // free memory delete frame; } break; } default: { State = LOWPOWER; break; } } } bool AlohaTransceiver::send(BasicPacket *packet) { // for the reason that we only transmit basic packet format, the // length is always 8 uint8_t payload_length = 8; // get destination address uint8_t destination_address = findNextHop(packet->getDestinationID()); // serialize the packet from upper layer uint8_t buffer[payload_length]; memset(buffer, 0x0, sizeof(buffer)); // copy bytes into buffer packet->serialize(buffer); // create a new frame AlohaFrame *frame = new AlohaFrame(); // set properfies // set payload as data frame->setType(AlohaFrame::Aloha_Data); // set payload length (8 bytes for BasicPacket) frame->setPayloadLength(payload_length); // set mac layer device id frame->setSourceAddress(deviceId); // set mac layer destination id // for multiple hop system, the destination is the next hop // in this case, we use destination id from upper layer frame->setDestinationAddress(packet->getDestinationID()); // set full message flag (always true in this case) frame->setFullMessageFlag(0x1); // use dest_addr as key for accessing sequence id // the seqid should increase as it successfully transmit the packet frame->setSequenceID(seqid[destination_address]++); // set payload for (uint8_t i = 0; i < payload_length; i++) { frame->setPayload(i, buffer[i]); } // calculate crc frame->generateCrc(); // push frame to the back of queue AlohaTxQueue.enqueue(frame); return true; } 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; } uint8_t AlohaTransceiver::findNextHop(uint8_t addr) { // TODO: maintain a routing lookup table for choosing shortest path return addr; } #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; #ifdef DEBUG_ALOHA debug("> OnTxDone\n\r" ); #endif } 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; #ifdef DEBUG_ALOHA debug("> OnRxDone\n\r" ); #endif } void OnTxTimeout( void ) { Radio.Sleep( ); State = TX_TIMEOUT; #ifdef DEBUG_ALOHA debug("> OnTxTimeout\n\r" ); #endif } void OnRxTimeout( void ) { Radio.Sleep( ); Buffer[ BufferSize ] = 0; State = RX_TIMEOUT; #ifdef DEBUG_ALOHA debug("> OnRxTimeout\n\r" ); #endif } void OnRxError( void ) { Radio.Sleep( ); State = RX_ERROR; #ifdef DEBUG_ALOHA debug( "> OnRxError\n\r" ); #endif }