Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Wed Jul 27 04:37:34 2016 +0000
Revision:
11:3e1ff29da71a
Parent:
10:065a4b58c6ff
Child:
15:0dc9df48687a
Use destination to identify packet

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 11:3e1ff29da71a 56 AlohaTransceiver::AlohaTransceiver(uint8_t id)
rba90 0:e2ccabf3f30c 57 {
rba90 11:3e1ff29da71a 58 // store unique device id
rba90 11:3e1ff29da71a 59 deviceId = id;
rba90 11:3e1ff29da71a 60
rba90 0:e2ccabf3f30c 61 // configure properties
rba90 0:e2ccabf3f30c 62 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 63 Settings.Power = TX_OUTPUT_POWER;
rba90 0:e2ccabf3f30c 64 Settings.Bandwidth = LORA_BANDWIDTH;
rba90 0:e2ccabf3f30c 65 Settings.Datarate = LORA_SPREADING_FACTOR;
rba90 0:e2ccabf3f30c 66 Settings.Coderate = LORA_CODINGRATE;
rba90 0:e2ccabf3f30c 67 Settings.PreambleLen = LORA_PREAMBLE_LENGTH;
rba90 0:e2ccabf3f30c 68 Settings.SymbolTimeout = LORA_SYMBOL_TIMEOUT;
rba90 0:e2ccabf3f30c 69 Settings.FixLen = LORA_FIX_LENGTH_PAYLOAD_ON;
rba90 0:e2ccabf3f30c 70 Settings.PayloadLen = 0;
rba90 0:e2ccabf3f30c 71 Settings.CrcOn = LORA_CRC_ENABLED;
rba90 0:e2ccabf3f30c 72 Settings.FreqHopOn = LORA_FHSS_ENABLED;
rba90 0:e2ccabf3f30c 73 Settings.HopPeriod = LORA_NB_SYMB_HOP;
rba90 0:e2ccabf3f30c 74 Settings.IqInverted = LORA_IQ_INVERSION_ON;
rba90 0:e2ccabf3f30c 75 Settings.RxContinuous = true;
rba90 0:e2ccabf3f30c 76 Settings.TxTimeout = TX_TIMEOUT_VALUE;
rba90 0:e2ccabf3f30c 77
rba90 0:e2ccabf3f30c 78 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 79 // TODO: Complete settings for FSK mode
rba90 0:e2ccabf3f30c 80 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 81 #else
rba90 0:e2ccabf3f30c 82 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 83 #endif
rba90 0:e2ccabf3f30c 84 }
rba90 0:e2ccabf3f30c 85
rba90 0:e2ccabf3f30c 86 AlohaTransceiver::~AlohaTransceiver()
rba90 0:e2ccabf3f30c 87 {
rba90 0:e2ccabf3f30c 88
rba90 0:e2ccabf3f30c 89 }
rba90 0:e2ccabf3f30c 90
rba90 6:f545f5aa7de3 91 void AlohaTransceiver::boardInit()
rba90 0:e2ccabf3f30c 92 {
rba90 0:e2ccabf3f30c 93 // configure callback functions
rba90 0:e2ccabf3f30c 94 RadioEvents.TxDone = OnTxDone;
rba90 0:e2ccabf3f30c 95 RadioEvents.RxDone = OnRxDone;
rba90 0:e2ccabf3f30c 96 RadioEvents.RxError = OnRxError;
rba90 0:e2ccabf3f30c 97 RadioEvents.TxTimeout = OnTxTimeout;
rba90 0:e2ccabf3f30c 98 RadioEvents.RxTimeout = OnRxTimeout;
rba90 0:e2ccabf3f30c 99 Radio.Init( &RadioEvents );
rba90 0:e2ccabf3f30c 100
rba90 0:e2ccabf3f30c 101 // verify the connection with the board
rba90 0:e2ccabf3f30c 102 while( Radio.Read( REG_VERSION ) == 0x00 )
rba90 0:e2ccabf3f30c 103 {
rba90 0:e2ccabf3f30c 104 printf( "Radio could not be detected!\n\r" );
rba90 0:e2ccabf3f30c 105 wait( 1 );
rba90 0:e2ccabf3f30c 106 }
rba90 0:e2ccabf3f30c 107 printf("RadioRegVersion: %d\r\n", Radio.Read( REG_VERSION ));
rba90 0:e2ccabf3f30c 108 }
rba90 0:e2ccabf3f30c 109
rba90 0:e2ccabf3f30c 110 void AlohaTransceiver::updateSettings()
rba90 0:e2ccabf3f30c 111 {
rba90 6:f545f5aa7de3 112 Radio.SetChannel( RF_FREQUENCY );
rba90 0:e2ccabf3f30c 113 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 114
rba90 0:e2ccabf3f30c 115 Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
rba90 0:e2ccabf3f30c 116 Settings.Datarate, Settings.Coderate,
rba90 0:e2ccabf3f30c 117 Settings.PreambleLen, Settings.FixLen,
rba90 0:e2ccabf3f30c 118 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 119 Settings.IqInverted, Settings.TxTimeout );
rba90 0:e2ccabf3f30c 120
rba90 0:e2ccabf3f30c 121 Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
rba90 0:e2ccabf3f30c 122 Settings.Coderate, 0, Settings.PreambleLen,
rba90 0:e2ccabf3f30c 123 Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
rba90 0:e2ccabf3f30c 124 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 125 Settings.IqInverted, Settings.RxContinuous );
rba90 0:e2ccabf3f30c 126
rba90 0:e2ccabf3f30c 127 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 128 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 129 #else
rba90 0:e2ccabf3f30c 130 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 131 #endif
rba90 0:e2ccabf3f30c 132 }
rba90 0:e2ccabf3f30c 133
rba90 6:f545f5aa7de3 134 void AlohaTransceiver::enable()
rba90 6:f545f5aa7de3 135 {
rba90 6:f545f5aa7de3 136 // entering passive receiver mode
rba90 10:065a4b58c6ff 137 Radio.Rx( 0 );
rba90 6:f545f5aa7de3 138 }
rba90 6:f545f5aa7de3 139
rba90 0:e2ccabf3f30c 140 void AlohaTransceiver::poll()
rba90 0:e2ccabf3f30c 141 {
rba90 0:e2ccabf3f30c 142 switch( State )
rba90 0:e2ccabf3f30c 143 {
rba90 0:e2ccabf3f30c 144 case RX:
rba90 5:c3741633dc6f 145 {
rba90 0:e2ccabf3f30c 146 // create new frame instance
rba90 0:e2ccabf3f30c 147 AlohaFrame frame(Buffer, BufferSize);
rba90 0:e2ccabf3f30c 148
rba90 11:3e1ff29da71a 149 // check destination
rba90 11:3e1ff29da71a 150 // if the destination is the device id, then processing, otherwise drop the packet and continue
rba90 11:3e1ff29da71a 151 // listening
rba90 11:3e1ff29da71a 152 if (frame.getDestinationAddress() == (deviceId & 0x0f))
rba90 0:e2ccabf3f30c 153 {
rba90 11:3e1ff29da71a 154 // check registered callback function
rba90 11:3e1ff29da71a 155 // execute callback functions if registered
rba90 11:3e1ff29da71a 156 if (AlohaTypeCallbackTable[frame.getType()] != NULL)
rba90 11:3e1ff29da71a 157 {
rba90 11:3e1ff29da71a 158 AlohaTypeCallbackTable[frame.getType()](&frame);
rba90 11:3e1ff29da71a 159 }
rba90 0:e2ccabf3f30c 160 }
rba90 0:e2ccabf3f30c 161
rba90 10:065a4b58c6ff 162 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 163 State = LOWPOWER;
rba90 0:e2ccabf3f30c 164 break;
rba90 0:e2ccabf3f30c 165 }
rba90 0:e2ccabf3f30c 166 case TX:
rba90 0:e2ccabf3f30c 167 {
rba90 10:065a4b58c6ff 168 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 169 State = LOWPOWER;
rba90 0:e2ccabf3f30c 170 break;
rba90 0:e2ccabf3f30c 171 }
rba90 0:e2ccabf3f30c 172 case RX_TIMEOUT:
rba90 0:e2ccabf3f30c 173 {
rba90 10:065a4b58c6ff 174 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 175 State = LOWPOWER;
rba90 0:e2ccabf3f30c 176 break;
rba90 0:e2ccabf3f30c 177 }
rba90 0:e2ccabf3f30c 178 case RX_ERROR:
rba90 0:e2ccabf3f30c 179 {
rba90 10:065a4b58c6ff 180 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 181 State = LOWPOWER;
rba90 0:e2ccabf3f30c 182 break;
rba90 0:e2ccabf3f30c 183 }
rba90 0:e2ccabf3f30c 184 case TX_TIMEOUT:
rba90 0:e2ccabf3f30c 185 {
rba90 10:065a4b58c6ff 186 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 187 State = LOWPOWER;
rba90 0:e2ccabf3f30c 188 break;
rba90 0:e2ccabf3f30c 189 }
rba90 0:e2ccabf3f30c 190 case LOWPOWER:
rba90 0:e2ccabf3f30c 191 {
rba90 0:e2ccabf3f30c 192 break;
rba90 0:e2ccabf3f30c 193 }
rba90 0:e2ccabf3f30c 194 default:
rba90 0:e2ccabf3f30c 195 {
rba90 0:e2ccabf3f30c 196 State = LOWPOWER;
rba90 0:e2ccabf3f30c 197 break;
rba90 0:e2ccabf3f30c 198 }
rba90 0:e2ccabf3f30c 199 }
rba90 0:e2ccabf3f30c 200 }
rba90 0:e2ccabf3f30c 201
rba90 0:e2ccabf3f30c 202 void AlohaTransceiver::send(uint8_t *buffer, int length)
rba90 0:e2ccabf3f30c 203 {
rba90 0:e2ccabf3f30c 204 Radio.Send(buffer, length);
rba90 10:065a4b58c6ff 205 State = LOWPOWER;
rba90 0:e2ccabf3f30c 206 }
rba90 0:e2ccabf3f30c 207
rba90 0:e2ccabf3f30c 208 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 209 {
rba90 0:e2ccabf3f30c 210 AlohaTypeCallbackTable[type] = f;
rba90 0:e2ccabf3f30c 211 }
rba90 0:e2ccabf3f30c 212
rba90 0:e2ccabf3f30c 213 void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 214 {
rba90 0:e2ccabf3f30c 215 AlohaTypeCallbackTable[type] = NULL;
rba90 0:e2ccabf3f30c 216 }
rba90 0:e2ccabf3f30c 217
rba90 2:fa264e48d5f7 218 int16_t AlohaTransceiver::getRssi()
rba90 2:fa264e48d5f7 219 {
rba90 2:fa264e48d5f7 220 return RssiValue;
rba90 2:fa264e48d5f7 221 }
rba90 2:fa264e48d5f7 222
rba90 2:fa264e48d5f7 223 int8_t AlohaTransceiver::getSnr()
rba90 2:fa264e48d5f7 224 {
rba90 2:fa264e48d5f7 225 return SnrValue;
rba90 2:fa264e48d5f7 226 }
rba90 2:fa264e48d5f7 227
rba90 11:3e1ff29da71a 228 uint8_t AlohaTransceiver::getDeviceId()
rba90 11:3e1ff29da71a 229 {
rba90 11:3e1ff29da71a 230 return deviceId;
rba90 11:3e1ff29da71a 231 }
rba90 11:3e1ff29da71a 232
rba90 11:3e1ff29da71a 233 void AlohaTransceiver::setDeviceId(uint8_t id)
rba90 11:3e1ff29da71a 234 {
rba90 11:3e1ff29da71a 235 deviceId = id;
rba90 11:3e1ff29da71a 236 }
rba90 11:3e1ff29da71a 237
rba90 8:4bda842f73d4 238 #if USE_MODEM_LORA == 1
rba90 8:4bda842f73d4 239 AlohaTransceiver::LoRaSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 240 {
rba90 8:4bda842f73d4 241 return &Settings;
rba90 8:4bda842f73d4 242 }
rba90 8:4bda842f73d4 243
rba90 8:4bda842f73d4 244 #elif USE_MODEM_FSK == 1
rba90 8:4bda842f73d4 245 AlohaTransceiver::FskSettings_t *AlohaTransceiver::getSettings()
rba90 8:4bda842f73d4 246 {
rba90 8:4bda842f73d4 247 return &Settings;
rba90 8:4bda842f73d4 248 }
rba90 8:4bda842f73d4 249 #else
rba90 8:4bda842f73d4 250 #error "Please define a modem in the compiler options."
rba90 8:4bda842f73d4 251 #endif
rba90 8:4bda842f73d4 252
rba90 0:e2ccabf3f30c 253 void OnTxDone( void )
rba90 0:e2ccabf3f30c 254 {
rba90 0:e2ccabf3f30c 255 Radio.Sleep( );
rba90 0:e2ccabf3f30c 256 State = TX;
rba90 0:e2ccabf3f30c 257 printf( "> OnTxDone\n\r" );
rba90 0:e2ccabf3f30c 258 }
rba90 0:e2ccabf3f30c 259
rba90 0:e2ccabf3f30c 260 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
rba90 0:e2ccabf3f30c 261 {
rba90 0:e2ccabf3f30c 262 Radio.Sleep( );
rba90 0:e2ccabf3f30c 263
rba90 0:e2ccabf3f30c 264 // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
rba90 0:e2ccabf3f30c 265 BufferSize = size ? BUFFER_SIZE : size <= BUFFER_SIZE;
rba90 0:e2ccabf3f30c 266
rba90 0:e2ccabf3f30c 267 memcpy( Buffer, payload, BufferSize );
rba90 0:e2ccabf3f30c 268 RssiValue = rssi;
rba90 0:e2ccabf3f30c 269 SnrValue = snr;
rba90 0:e2ccabf3f30c 270 State = RX;
rba90 0:e2ccabf3f30c 271 printf( "> OnRxDone\n\r" );
rba90 0:e2ccabf3f30c 272 }
rba90 0:e2ccabf3f30c 273
rba90 0:e2ccabf3f30c 274 void OnTxTimeout( void )
rba90 0:e2ccabf3f30c 275 {
rba90 0:e2ccabf3f30c 276 Radio.Sleep( );
rba90 0:e2ccabf3f30c 277 State = TX_TIMEOUT;
rba90 0:e2ccabf3f30c 278 printf( "> OnTxTimeout\n\r" );
rba90 0:e2ccabf3f30c 279 }
rba90 0:e2ccabf3f30c 280
rba90 0:e2ccabf3f30c 281 void OnRxTimeout( void )
rba90 0:e2ccabf3f30c 282 {
rba90 0:e2ccabf3f30c 283 Radio.Sleep( );
rba90 0:e2ccabf3f30c 284 Buffer[ BufferSize ] = 0;
rba90 0:e2ccabf3f30c 285 State = RX_TIMEOUT;
rba90 0:e2ccabf3f30c 286 printf( "> OnRxTimeout\n\r" );
rba90 0:e2ccabf3f30c 287 }
rba90 0:e2ccabf3f30c 288
rba90 0:e2ccabf3f30c 289 void OnRxError( void )
rba90 0:e2ccabf3f30c 290 {
rba90 0:e2ccabf3f30c 291 Radio.Sleep( );
rba90 0:e2ccabf3f30c 292 State = RX_ERROR;
rba90 0:e2ccabf3f30c 293 printf( "> OnRxError\n\r" );
rba90 0:e2ccabf3f30c 294 }