Basic MAC data interface for LoRa transceiver

Dependencies:   L2Frame crc

Dependents:   LoRaBaseStation LoRaTerminal

Committer:
rba90
Date:
Thu Jul 14 11:48:18 2016 +0000
Revision:
2:fa264e48d5f7
Parent:
0:e2ccabf3f30c
Child:
3:47fa0a59089a
update

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 0:e2ccabf3f30c 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 // select operating channel
rba90 0:e2ccabf3f30c 107 Radio.SetChannel( RF_FREQUENCY );
rba90 0:e2ccabf3f30c 108
rba90 0:e2ccabf3f30c 109 // configure radio tx and rx properties
rba90 0:e2ccabf3f30c 110 updateSettings();
rba90 0:e2ccabf3f30c 111
rba90 0:e2ccabf3f30c 112 // entering passive receiver mode by default
rba90 0:e2ccabf3f30c 113 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 114 }
rba90 0:e2ccabf3f30c 115
rba90 0:e2ccabf3f30c 116 void AlohaTransceiver::updateSettings()
rba90 0:e2ccabf3f30c 117 {
rba90 0:e2ccabf3f30c 118 #if USE_MODEM_LORA == 1
rba90 0:e2ccabf3f30c 119
rba90 0:e2ccabf3f30c 120 Radio.SetTxConfig( MODEM_LORA, Settings.Power, 0, Settings.Bandwidth,
rba90 0:e2ccabf3f30c 121 Settings.Datarate, Settings.Coderate,
rba90 0:e2ccabf3f30c 122 Settings.PreambleLen, Settings.FixLen,
rba90 0:e2ccabf3f30c 123 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 124 Settings.IqInverted, Settings.TxTimeout );
rba90 0:e2ccabf3f30c 125
rba90 0:e2ccabf3f30c 126 Radio.SetRxConfig( MODEM_LORA, Settings.Bandwidth, Settings.Datarate,
rba90 0:e2ccabf3f30c 127 Settings.Coderate, 0, Settings.PreambleLen,
rba90 0:e2ccabf3f30c 128 Settings.SymbolTimeout, Settings.FixLen, Settings.PayloadLen,
rba90 0:e2ccabf3f30c 129 Settings.CrcOn, Settings.FreqHopOn, Settings.HopPeriod,
rba90 0:e2ccabf3f30c 130 Settings.IqInverted, Settings.RxContinuous );
rba90 0:e2ccabf3f30c 131
rba90 0:e2ccabf3f30c 132 #elif USE_MODEM_FSK == 1
rba90 0:e2ccabf3f30c 133 #error "FSK not implemented"
rba90 0:e2ccabf3f30c 134 #else
rba90 0:e2ccabf3f30c 135 #error "Please define a modem in the compiler options."
rba90 0:e2ccabf3f30c 136 #endif
rba90 0:e2ccabf3f30c 137 }
rba90 0:e2ccabf3f30c 138
rba90 0:e2ccabf3f30c 139 void AlohaTransceiver::poll()
rba90 0:e2ccabf3f30c 140 {
rba90 0:e2ccabf3f30c 141 switch( State )
rba90 0:e2ccabf3f30c 142 {
rba90 0:e2ccabf3f30c 143 case RX:
rba90 0:e2ccabf3f30c 144 {
rba90 0:e2ccabf3f30c 145 printf("RX::rssi = %d snr = %d\r\n", RssiValue, SnrValue);
rba90 0:e2ccabf3f30c 146
rba90 0:e2ccabf3f30c 147 // create new frame instance
rba90 0:e2ccabf3f30c 148 AlohaFrame frame(Buffer, BufferSize);
rba90 0:e2ccabf3f30c 149
rba90 0:e2ccabf3f30c 150 // execute callback functions
rba90 0:e2ccabf3f30c 151 if (AlohaTypeCallbackTable[frame.getType()] != NULL)
rba90 0:e2ccabf3f30c 152 {
rba90 0:e2ccabf3f30c 153 AlohaTypeCallbackTable[frame.getType()](&frame);
rba90 0:e2ccabf3f30c 154 }
rba90 0:e2ccabf3f30c 155
rba90 0:e2ccabf3f30c 156 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 157 State = LOWPOWER;
rba90 0:e2ccabf3f30c 158 break;
rba90 0:e2ccabf3f30c 159 }
rba90 0:e2ccabf3f30c 160 case TX:
rba90 0:e2ccabf3f30c 161 {
rba90 0:e2ccabf3f30c 162 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 163 State = LOWPOWER;
rba90 0:e2ccabf3f30c 164 break;
rba90 0:e2ccabf3f30c 165 }
rba90 0:e2ccabf3f30c 166 case RX_TIMEOUT:
rba90 0:e2ccabf3f30c 167 {
rba90 0:e2ccabf3f30c 168 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 169 State = LOWPOWER;
rba90 0:e2ccabf3f30c 170 break;
rba90 0:e2ccabf3f30c 171 }
rba90 0:e2ccabf3f30c 172 case RX_ERROR:
rba90 0:e2ccabf3f30c 173 {
rba90 0:e2ccabf3f30c 174 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 175 State = LOWPOWER;
rba90 0:e2ccabf3f30c 176 break;
rba90 0:e2ccabf3f30c 177 }
rba90 0:e2ccabf3f30c 178 case TX_TIMEOUT:
rba90 0:e2ccabf3f30c 179 {
rba90 0:e2ccabf3f30c 180 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 181 State = LOWPOWER;
rba90 0:e2ccabf3f30c 182 break;
rba90 0:e2ccabf3f30c 183 }
rba90 0:e2ccabf3f30c 184 case LOWPOWER:
rba90 0:e2ccabf3f30c 185 {
rba90 0:e2ccabf3f30c 186 break;
rba90 0:e2ccabf3f30c 187 }
rba90 0:e2ccabf3f30c 188 default:
rba90 0:e2ccabf3f30c 189 {
rba90 0:e2ccabf3f30c 190 State = LOWPOWER;
rba90 0:e2ccabf3f30c 191 break;
rba90 0:e2ccabf3f30c 192 }
rba90 0:e2ccabf3f30c 193 }
rba90 0:e2ccabf3f30c 194 }
rba90 0:e2ccabf3f30c 195
rba90 0:e2ccabf3f30c 196 void AlohaTransceiver::send(uint8_t *buffer, int length)
rba90 0:e2ccabf3f30c 197 {
rba90 0:e2ccabf3f30c 198 Radio.Rx( 0 );
rba90 0:e2ccabf3f30c 199 Radio.Send(buffer, length);
rba90 0:e2ccabf3f30c 200 Radio.Rx( RX_TIMEOUT_VALUE );
rba90 0:e2ccabf3f30c 201 }
rba90 0:e2ccabf3f30c 202
rba90 0:e2ccabf3f30c 203 void AlohaTransceiver::registerType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 204 {
rba90 0:e2ccabf3f30c 205 AlohaTypeCallbackTable[type] = f;
rba90 0:e2ccabf3f30c 206 }
rba90 0:e2ccabf3f30c 207
rba90 0:e2ccabf3f30c 208 void AlohaTransceiver::deRegisterType(AlohaFrame::AlohaType_t type, aloha_callback_func f)
rba90 0:e2ccabf3f30c 209 {
rba90 0:e2ccabf3f30c 210 AlohaTypeCallbackTable[type] = NULL;
rba90 0:e2ccabf3f30c 211 }
rba90 0:e2ccabf3f30c 212
rba90 2:fa264e48d5f7 213 int16_t AlohaTransceiver::getRssi()
rba90 2:fa264e48d5f7 214 {
rba90 2:fa264e48d5f7 215 return RssiValue;
rba90 2:fa264e48d5f7 216 }
rba90 2:fa264e48d5f7 217
rba90 2:fa264e48d5f7 218 int8_t AlohaTransceiver::getSnr()
rba90 2:fa264e48d5f7 219 {
rba90 2:fa264e48d5f7 220 return SnrValue;
rba90 2:fa264e48d5f7 221 }
rba90 2:fa264e48d5f7 222
rba90 0:e2ccabf3f30c 223 void OnTxDone( void )
rba90 0:e2ccabf3f30c 224 {
rba90 0:e2ccabf3f30c 225 Radio.Sleep( );
rba90 0:e2ccabf3f30c 226 State = TX;
rba90 0:e2ccabf3f30c 227 printf( "> OnTxDone\n\r" );
rba90 0:e2ccabf3f30c 228 }
rba90 0:e2ccabf3f30c 229
rba90 0:e2ccabf3f30c 230 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
rba90 0:e2ccabf3f30c 231 {
rba90 0:e2ccabf3f30c 232 Radio.Sleep( );
rba90 0:e2ccabf3f30c 233
rba90 0:e2ccabf3f30c 234 // safeguard: if size exceeded maximum buffer size, it will cause memory overflow
rba90 0:e2ccabf3f30c 235 BufferSize = size ? BUFFER_SIZE : size <= BUFFER_SIZE;
rba90 0:e2ccabf3f30c 236
rba90 0:e2ccabf3f30c 237 memcpy( Buffer, payload, BufferSize );
rba90 0:e2ccabf3f30c 238 RssiValue = rssi;
rba90 0:e2ccabf3f30c 239 SnrValue = snr;
rba90 0:e2ccabf3f30c 240 State = RX;
rba90 0:e2ccabf3f30c 241 printf( "> OnRxDone\n\r" );
rba90 0:e2ccabf3f30c 242 }
rba90 0:e2ccabf3f30c 243
rba90 0:e2ccabf3f30c 244 void OnTxTimeout( void )
rba90 0:e2ccabf3f30c 245 {
rba90 0:e2ccabf3f30c 246 Radio.Sleep( );
rba90 0:e2ccabf3f30c 247 State = TX_TIMEOUT;
rba90 0:e2ccabf3f30c 248 printf( "> OnTxTimeout\n\r" );
rba90 0:e2ccabf3f30c 249 }
rba90 0:e2ccabf3f30c 250
rba90 0:e2ccabf3f30c 251 void OnRxTimeout( void )
rba90 0:e2ccabf3f30c 252 {
rba90 0:e2ccabf3f30c 253 Radio.Sleep( );
rba90 0:e2ccabf3f30c 254 Buffer[ BufferSize ] = 0;
rba90 0:e2ccabf3f30c 255 State = RX_TIMEOUT;
rba90 0:e2ccabf3f30c 256 printf( "> OnRxTimeout\n\r" );
rba90 0:e2ccabf3f30c 257 }
rba90 0:e2ccabf3f30c 258
rba90 0:e2ccabf3f30c 259 void OnRxError( void )
rba90 0:e2ccabf3f30c 260 {
rba90 0:e2ccabf3f30c 261 Radio.Sleep( );
rba90 0:e2ccabf3f30c 262 State = RX_ERROR;
rba90 0:e2ccabf3f30c 263 printf( "> OnRxError\n\r" );
rba90 0:e2ccabf3f30c 264 }