Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Wed Jul 27 03:42:12 2016 +0000
Revision:
10:065a4b58c6ff
Parent:
9:3074f6e08d8e
Child:
11:3e1ff29da71a
enter continuous receiver mode while the timer never expires

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rba90 0:e2ccabf3f30c 1 #include "AlohaTransceiver.h"
rba90 0:e2ccabf3f30c 2 #include "mbed.h"
rba90 0:e2ccabf3f30c 3 #include "radio.h"
rba90 0:e2ccabf3f30c 4 #include "AlohaFrame.h"
rba90 0:e2ccabf3f30c 5
rba90 0:e2ccabf3f30c 6 // declear the type of radio state
rba90 0:e2ccabf3f30c 7 typedef enum
rba90 0:e2ccabf3f30c 8 {
rba90 0:e2ccabf3f30c 9 LOWPOWER = 0,
rba90 0:e2ccabf3f30c 10 IDLE,
rba90 0:e2ccabf3f30c 11
rba90 0:e2ccabf3f30c 12 RX,
rba90 0:e2ccabf3f30c 13 RX_TIMEOUT,
rba90 0:e2ccabf3f30c 14 RX_ERROR,
rba90 0:e2ccabf3f30c 15
rba90 0:e2ccabf3f30c 16 TX,
rba90 0:e2ccabf3f30c 17 TX_TIMEOUT,
rba90 0:e2ccabf3f30c 18
rba90 0:e2ccabf3f30c 19 CAD,
rba90 0:e2ccabf3f30c 20 CAD_DONE
rba90 0:e2ccabf3f30c 21 }AppStates_t;
rba90 0:e2ccabf3f30c 22
rba90 0:e2ccabf3f30c 23 // radio driver related variables
rba90 0:e2ccabf3f30c 24 static uint16_t BufferSize;
rba90 0:e2ccabf3f30c 25 static uint8_t Buffer[BUFFER_SIZE];
rba90 0:e2ccabf3f30c 26
rba90 0:e2ccabf3f30c 27 static int16_t RssiValue;
rba90 0:e2ccabf3f30c 28 static int8_t SnrValue;
rba90 0:e2ccabf3f30c 29
rba90 0:e2ccabf3f30c 30 static volatile AppStates_t State;
rba90 0:e2ccabf3f30c 31 static RadioEvents_t RadioEvents;
rba90 0:e2ccabf3f30c 32
rba90 0:e2ccabf3f30c 33 // callback functions for radio driver
rba90 0:e2ccabf3f30c 34 void OnTxDone();
rba90 0:e2ccabf3f30c 35 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
rba90 0:e2ccabf3f30c 36 void OnTxTimeout();
rba90 0:e2ccabf3f30c 37 void OnRxTimeout();
rba90 0:e2ccabf3f30c 38 void OnRxError();
rba90 0:e2ccabf3f30c 39 void OnFhssChangeChannel( uint8_t channelIndex );
rba90 0:e2ccabf3f30c 40 void OnCadDone();
rba90 0:e2ccabf3f30c 41
rba90 0:e2ccabf3f30c 42 // radio driver
rba90 0:e2ccabf3f30c 43 #ifdef BUILD_FOR_BS
rba90 0:e2ccabf3f30c 44 SX1276MB1xAS Radio( NULL );
rba90 0:e2ccabf3f30c 45 #endif
rba90 0:e2ccabf3f30c 46
rba90 0:e2ccabf3f30c 47 #ifdef BUILD_FOR_TERMINAL
rba90 0:e2ccabf3f30c 48 SX1276inAir Radio( NULL );
rba90 0:e2ccabf3f30c 49 #endif
rba90 0:e2ccabf3f30c 50
rba90 0:e2ccabf3f30c 51
rba90 0:e2ccabf3f30c 52 /*
rba90 0:e2ccabf3f30c 53 * Abstract interface for accessing radio driver
rba90 0:e2ccabf3f30c 54 */
rba90 0:e2ccabf3f30c 55
rba90 0:e2ccabf3f30c 56 AlohaTransceiver::AlohaTransceiver()
rba90 0:e2ccabf3f30c 57 {
rba90 0:e2ccabf3f30c 58 // configure properties
rba90 0:e2ccabf3f30c 59 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 60 Settings.Power = TX_OUTPUT_POWER;
rba90 0:e2ccabf3f30c 61 Settings.Bandwidth = LORA_BANDWIDTH;
rba90 0:e2ccabf3f30c 62 Settings.Datarate = LORA_SPREADING_FACTOR;
rba90 0:e2ccabf3f30c 63 Settings.Coderate = LORA_CODINGRATE;
rba90 0:e2ccabf3f30c 64 Settings.PreambleLen = LORA_PREAMBLE_LENGTH;
rba90 0:e2ccabf3f30c 65 Settings.SymbolTimeout = LORA_SYMBOL_TIMEOUT;
rba90 0:e2ccabf3f30c 66 Settings.FixLen = LORA_FIX_LENGTH_PAYLOAD_ON;
rba90 0:e2ccabf3f30c 67 Settings.PayloadLen = 0;
rba90 0:e2ccabf3f30c 68 Settings.CrcOn = LORA_CRC_ENABLED;
rba90 0:e2ccabf3f30c 69 Settings.FreqHopOn = LORA_FHSS_ENABLED;
rba90 0:e2ccabf3f30c 70 Settings.HopPeriod = LORA_NB_SYMB_HOP;
rba90 0:e2ccabf3f30c 71 Settings.IqInverted = LORA_IQ_INVERSION_ON;
rba90 0:e2ccabf3f30c 72 Settings.RxContinuous = true;
rba90 0:e2ccabf3f30c 73 Settings.TxTimeout = TX_TIMEOUT_VALUE;
rba90 0:e2ccabf3f30c 74
rba90 0:e2ccabf3f30c 75 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 76 // TODO: Complete settings for FSK mode
rba90 0:e2ccabf3f30c 77 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 78 #else
rba90 0:e2ccabf3f30c 79 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 80 #endif
rba90 0:e2ccabf3f30c 81 }
rba90 0:e2ccabf3f30c 82
rba90 0:e2ccabf3f30c 83 AlohaTransceiver::~AlohaTransceiver()
rba90 0:e2ccabf3f30c 84 {
rba90 0:e2ccabf3f30c 85
rba90 0:e2ccabf3f30c 86 }
rba90 0:e2ccabf3f30c 87
rba90 6:f545f5aa7de3 88 void AlohaTransceiver::boardInit()
rba90 0:e2ccabf3f30c 89 {
rba90 0:e2ccabf3f30c 90 // configure callback functions
rba90 0:e2ccabf3f30c 91 RadioEvents.TxDone = OnTxDone;
rba90 0:e2ccabf3f30c 92 RadioEvents.RxDone = OnRxDone;
rba90 0:e2ccabf3f30c 93 RadioEvents.RxError = OnRxError;
rba90 0:e2ccabf3f30c 94 RadioEvents.TxTimeout = OnTxTimeout;
rba90 0:e2ccabf3f30c 95 RadioEvents.RxTimeout = OnRxTimeout;
rba90 0:e2ccabf3f30c 96 Radio.Init( &RadioEvents );
rba90 0:e2ccabf3f30c 97
rba90 0:e2ccabf3f30c 98 // verify the connection with the board
rba90 0:e2ccabf3f30c 99 while( Radio.Read( REG_VERSION ) == 0x00 )
rba90 0:e2ccabf3f30c 100 {
rba90 0:e2ccabf3f30c 101 printf( "Radio could not be detected!\n\r" );
rba90 0:e2ccabf3f30c 102 wait( 1 );
rba90 0:e2ccabf3f30c 103 }
rba90 0:e2ccabf3f30c 104 printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
rba90 0:e2ccabf3f30c 105 }
rba90 0:e2ccabf3f30c 106
rba90 0:e2ccabf3f30c 107 void AlohaTransceiver::updateSettings()
rba90 0:e2ccabf3f30c 108 {
rba90 6:f545f5aa7de3 109 Radio.SetChannel( RF_FREQUENCY );
rba90 0:e2ccabf3f30c 110 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 111
rba90 0:e2ccabf3f30c 112 Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
rba90 0:e2ccabf3f30c 113 Settings.Datarate, Settings.Coderate,
rba90 0:e2ccabf3f30c 114 Settings.PreambleLen, Settings.FixLen,
rba90 0:e2ccabf3f30c 115 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 116 Settings.IqInverted, Settings.TxTimeout );
rba90 0:e2ccabf3f30c 117
rba90 0:e2ccabf3f30c 118 Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
rba90 0:e2ccabf3f30c 119 Settings.Coderate, 0, Settings.PreambleLen,
rba90 0:e2ccabf3f30c 120 Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
rba90 0:e2ccabf3f30c 121 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 122 Settings.IqInverted, Settings.RxContinuous );
rba90 0:e2ccabf3f30c 123
rba90 0:e2ccabf3f30c 124 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 125 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 126 #else
rba90 0:e2ccabf3f30c 127 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 128 #endif
rba90 0:e2ccabf3f30c 129 }
rba90 0:e2ccabf3f30c 130
rba90 6:f545f5aa7de3 131 void AlohaTransceiver::enable()
rba90 6:f545f5aa7de3 132 {
rba90 6:f545f5aa7de3 133 // entering passive receiver mode
rba90 10:065a4b58c6ff 134 Radio.Rx( 0 );
rba90 6:f545f5aa7de3 135 }
rba90 6:f545f5aa7de3 136
rba90 0:e2ccabf3f30c 137 void AlohaTransceiver::poll()
rba90 0:e2ccabf3f30c 138 {
rba90 0:e2ccabf3f30c 139 switch( State )
rba90 0:e2ccabf3f30c 140 {
rba90 0:e2ccabf3f30c 141 case RX:
rba90 5:c3741633dc6f 142 {
rba90 0:e2ccabf3f30c 143 // create new frame instance
rba90 0:e2ccabf3f30c 144 AlohaFrame frame(Buffer, BufferSize);
rba90 0:e2ccabf3f30c 145
rba90 0:e2ccabf3f30c 146 // execute callback functions
rba90 0:e2ccabf3f30c 147 if (AlohaTypeCallbackTable[frame.getType()] != NULL)
rba90 0:e2ccabf3f30c 148 {
rba90 0:e2ccabf3f30c 149 AlohaTypeCallbackTable[frame.getType()](&frame);
rba90 0:e2ccabf3f30c 150 }
rba90 0:e2ccabf3f30c 151
rba90 10:065a4b58c6ff 152 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 153 State = LOWPOWER;
rba90 0:e2ccabf3f30c 154 break;
rba90 0:e2ccabf3f30c 155 }
rba90 0:e2ccabf3f30c 156 case TX:
rba90 0:e2ccabf3f30c 157 {
rba90 10:065a4b58c6ff 158 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 159 State = LOWPOWER;
rba90 0:e2ccabf3f30c 160 break;
rba90 0:e2ccabf3f30c 161 }
rba90 0:e2ccabf3f30c 162 case RX_TIMEOUT:
rba90 0:e2ccabf3f30c 163 {
rba90 10:065a4b58c6ff 164 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 165 State = LOWPOWER;
rba90 0:e2ccabf3f30c 166 break;
rba90 0:e2ccabf3f30c 167 }
rba90 0:e2ccabf3f30c 168 case RX_ERROR:
rba90 0:e2ccabf3f30c 169 {
rba90 10:065a4b58c6ff 170 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 171 State = LOWPOWER;
rba90 0:e2ccabf3f30c 172 break;
rba90 0:e2ccabf3f30c 173 }
rba90 0:e2ccabf3f30c 174 case TX_TIMEOUT:
rba90 0:e2ccabf3f30c 175 {
rba90 10:065a4b58c6ff 176 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 177 State = LOWPOWER;
rba90 0:e2ccabf3f30c 178 break;
rba90 0:e2ccabf3f30c 179 }
rba90 0:e2ccabf3f30c 180 case LOWPOWER:
rba90 0:e2ccabf3f30c 181 {
rba90 0:e2ccabf3f30c 182 break;
rba90 0:e2ccabf3f30c 183 }
rba90 0:e2ccabf3f30c 184 default:
rba90 0:e2ccabf3f30c 185 {
rba90 0:e2ccabf3f30c 186 State = LOWPOWER;
rba90 0:e2ccabf3f30c 187 break;
rba90 0:e2ccabf3f30c 188 }
rba90 0:e2ccabf3f30c 189 }
rba90 0:e2ccabf3f30c 190 }
rba90 0:e2ccabf3f30c 191
rba90 0:e2ccabf3f30c 192 void AlohaTransceiver::send(uint8_t *buffer, int length)
rba90 0:e2ccabf3f30c 193 {
rba90 0:e2ccabf3f30c 194 Radio.Send(buffer, length);
rba90 10:065a4b58c6ff 195 State = LOWPOWER;
rba90 0:e2ccabf3f30c 196 }
rba90 0:e2ccabf3f30c 197
rba90 0:e2ccabf3f30c 198 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 199 {
rba90 0:e2ccabf3f30c 200 AlohaTypeCallbackTable[type] = f;
rba90 0:e2ccabf3f30c 201 }
rba90 0:e2ccabf3f30c 202
rba90 0:e2ccabf3f30c 203 void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 204 {
rba90 0:e2ccabf3f30c 205 AlohaTypeCallbackTable[type] = NULL;
rba90 0:e2ccabf3f30c 206 }
rba90 0:e2ccabf3f30c 207
rba90 2:fa264e48d5f7 208 int16_t AlohaTransceiver::getRssi()
rba90 2:fa264e48d5f7 209 {
rba90 2:fa264e48d5f7 210 return RssiValue;
rba90 2:fa264e48d5f7 211 }
rba90 2:fa264e48d5f7 212
rba90 2:fa264e48d5f7 213 int8_t AlohaTransceiver::getSnr()
rba90 2:fa264e48d5f7 214 {
rba90 2:fa264e48d5f7 215 return SnrValue;
rba90 2:fa264e48d5f7 216 }
rba90 2:fa264e48d5f7 217
rba90 8:4bda842f73d4 218 #if USE_MODEM_LORA == 1
rba90 8:4bda842f73d4 219 AlohaTransceiver::LoRaSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 220 {
rba90 8:4bda842f73d4 221 return &Settings;
rba90 8:4bda842f73d4 222 }
rba90 8:4bda842f73d4 223
rba90 8:4bda842f73d4 224 #elif USE_MODEM_FSK == 1
rba90 8:4bda842f73d4 225 AlohaTransceiver::FskSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 226 {
rba90 8:4bda842f73d4 227 return &Settings;
rba90 8:4bda842f73d4 228 }
rba90 8:4bda842f73d4 229 #else
rba90 8:4bda842f73d4 230 #error "Please define a modem in the compiler options."
rba90 8:4bda842f73d4 231 #endif
rba90 8:4bda842f73d4 232
rba90 0:e2ccabf3f30c 233 void OnTxDone( void )
rba90 0:e2ccabf3f30c 234 {
rba90 0:e2ccabf3f30c 235 Radio.Sleep( );
rba90 0:e2ccabf3f30c 236 State = TX;
rba90 0:e2ccabf3f30c 237 printf( "> OnTxDone\n\r" );
rba90 0:e2ccabf3f30c 238 }
rba90 0:e2ccabf3f30c 239
rba90 0:e2ccabf3f30c 240 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
rba90 0:e2ccabf3f30c 241 {
rba90 0:e2ccabf3f30c 242 Radio.Sleep( );
rba90 0:e2ccabf3f30c 243
rba90 0:e2ccabf3f30c 244 // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
rba90 0:e2ccabf3f30c 245 BufferSize = size ? BUFFER_SIZE : size <= BUFFER_SIZE;
rba90 0:e2ccabf3f30c 246
rba90 0:e2ccabf3f30c 247 memcpy( Buffer, payload, BufferSize );
rba90 0:e2ccabf3f30c 248 RssiValue = rssi;
rba90 0:e2ccabf3f30c 249 SnrValue = snr;
rba90 0:e2ccabf3f30c 250 State = RX;
rba90 0:e2ccabf3f30c 251 printf( "> OnRxDone\n\r" );
rba90 0:e2ccabf3f30c 252 }
rba90 0:e2ccabf3f30c 253
rba90 0:e2ccabf3f30c 254 void OnTxTimeout( void )
rba90 0:e2ccabf3f30c 255 {
rba90 0:e2ccabf3f30c 256 Radio.Sleep( );
rba90 0:e2ccabf3f30c 257 State = TX_TIMEOUT;
rba90 0:e2ccabf3f30c 258 printf( "> OnTxTimeout\n\r" );
rba90 0:e2ccabf3f30c 259 }
rba90 0:e2ccabf3f30c 260
rba90 0:e2ccabf3f30c 261 void OnRxTimeout( void )
rba90 0:e2ccabf3f30c 262 {
rba90 0:e2ccabf3f30c 263 Radio.Sleep( );
rba90 0:e2ccabf3f30c 264 Buffer[ BufferSize ] = 0;
rba90 0:e2ccabf3f30c 265 State = RX_TIMEOUT;
rba90 0:e2ccabf3f30c 266 printf( "> OnRxTimeout\n\r" );
rba90 0:e2ccabf3f30c 267 }
rba90 0:e2ccabf3f30c 268
rba90 0:e2ccabf3f30c 269 void OnRxError( void )
rba90 0:e2ccabf3f30c 270 {
rba90 0:e2ccabf3f30c 271 Radio.Sleep( );
rba90 0:e2ccabf3f30c 272 State = RX_ERROR;
rba90 0:e2ccabf3f30c 273 printf( "> OnRxError\n\r" );
rba90 0:e2ccabf3f30c 274 }