Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of LMiC by
radio.cpp
00001 /******************************************************************************* 00002 * Copyright (c) 2014-2015 IBM Corporation. 00003 * All rights reserved. This program and the accompanying materials 00004 * are made available under the terms of the Eclipse Public License v1.0 00005 * which accompanies this distribution, and is available at 00006 * http://www.eclipse.org/legal/epl-v10.html 00007 * 00008 * Contributors: 00009 * IBM Zurich Research Lab - initial API, implementation and documentation 00010 * Semtech Apps Team - Modified to support the MBED sx1276 driver 00011 * library. 00012 * Possibility to use original or Semtech's MBED 00013 * radio driver. The selection is done by setting 00014 * USE_SMTC_RADIO_DRIVER preprocessing directive 00015 * in lmic.h 00016 *******************************************************************************/ 00017 00018 #include "lmic.h" 00019 00020 #if USE_SMTC_RADIO_DRIVER 00021 #include "sx1276-hal.h" 00022 00023 /*! 00024 * Syncword for lora networks 00025 */ 00026 #define LORA_MAC_SYNCWORD 0x34 00027 00028 /* 00029 * Callback functions prototypes 00030 */ 00031 /*! 00032 * @brief Function to be executed on Radio Tx Done event 00033 */ 00034 void OnTxDone( void ); 00035 00036 /*! 00037 * @brief Function to be executed on Radio Rx Done event 00038 */ 00039 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); 00040 00041 /*! 00042 * @brief Function executed on Radio Tx Timeout event 00043 */ 00044 void OnTxTimeout( void ); 00045 00046 /*! 00047 * @brief Function executed on Radio Rx Timeout event 00048 */ 00049 void OnRxTimeout( void ); 00050 00051 /*! 00052 * @brief Function executed on Radio Rx Error event 00053 */ 00054 void OnRxError( void ); 00055 00056 /*! 00057 * @brief Function executed on Radio Fhss Change Channel event 00058 */ 00059 void OnFhssChangeChannel( uint8_t channelIndex ); 00060 00061 /*! 00062 * @brief Function executed on CAD Done event 00063 */ 00064 void OnCadDone( void ); 00065 00066 /*! 00067 * Radio events function pointer 00068 */ 00069 static RadioEvents_t RadioEvents; 00070 00071 /* 00072 * Radio object declraration 00073 */ 00074 SX1276MB1xAS Radio( NULL ); 00075 00076 static const u2_t LORA_RXDONE_FIXUP[] = { 00077 [FSK] = us2osticks(0), // ( 0 ticks) 00078 [SF7] = us2osticks(0), // ( 0 ticks) 00079 [SF8] = us2osticks(1648), // ( 54 ticks) 00080 [SF9] = us2osticks(3265), // ( 107 ticks) 00081 [SF10] = us2osticks(7049), // ( 231 ticks) 00082 [SF11] = us2osticks(13641), // ( 447 ticks) 00083 [SF12] = us2osticks(31189), // (1022 ticks) 00084 }; 00085 00086 void OnTxDone( void ) 00087 { 00088 ostime_t now = os_getTime( ); 00089 // save exact tx time 00090 LMIC.txend = now - us2osticks( RADIO_WAKEUP_TIME ); // TXDONE FIXUP 00091 00092 // go from stanby to sleep 00093 Radio.Sleep( ); 00094 // run os job (use preset func ptr) 00095 os_setCallback( &LMIC.osjob, LMIC.osjob.func ); 00096 } 00097 00098 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) 00099 { 00100 ostime_t now = os_getTime( ); 00101 // save exact rx time 00102 if( getBw( LMIC.rps ) == BW125 ) 00103 { 00104 now -= LORA_RXDONE_FIXUP[getSf( LMIC.rps )]; 00105 } 00106 LMIC.rxtime = now; 00107 // read the PDU and inform the MAC that we received something 00108 LMIC.dataLen = size; 00109 // now read the FIFO 00110 memcpy( LMIC.frame, payload, size ); 00111 // read rx quality parameters 00112 LMIC.snr = snr; // SNR [dB] * 4 00113 LMIC.rssi = rssi; // RSSI [dBm] (-196...+63) 00114 00115 // go from stanby to sleep 00116 Radio.Sleep( ); 00117 // run os job (use preset func ptr) 00118 os_setCallback( &LMIC.osjob, LMIC.osjob.func ); 00119 } 00120 00121 void OnTxTimeout( void ) 00122 { 00123 ostime_t now = os_getTime( ); 00124 00125 // indicate error 00126 LMIC.dataLen = 0; 00127 00128 // go from stanby to sleep 00129 Radio.Sleep( ); 00130 // run os job (use preset func ptr) 00131 os_setCallback( &LMIC.osjob, LMIC.osjob.func ); 00132 } 00133 00134 void OnRxTimeout( void ) 00135 { 00136 ostime_t now = os_getTime( ); 00137 // indicate timeout 00138 LMIC.dataLen = 0; 00139 00140 // go from stanby to sleep 00141 Radio.Sleep( ); 00142 // run os job (use preset func ptr) 00143 os_setCallback( &LMIC.osjob, LMIC.osjob.func ); 00144 } 00145 00146 void OnRxError( void ) 00147 { 00148 ostime_t now = os_getTime( ); 00149 00150 // indicate error 00151 LMIC.dataLen = 0; 00152 00153 // go from stanby to sleep 00154 Radio.Sleep( ); 00155 // run os job (use preset func ptr) 00156 os_setCallback( &LMIC.osjob, LMIC.osjob.func ); 00157 } 00158 00159 /*! 00160 * LMIC API implementation 00161 */ 00162 // RADIO STATE 00163 // (initialized by radio_init( ), used by radio_rand1( )) 00164 static u1_t randbuf[16]; 00165 00166 // get random seed from wideband noise rssi 00167 void radio_init( void ) 00168 { 00169 hal_disableIRQs( ); 00170 00171 // Initialize Radio driver 00172 RadioEvents.TxDone = OnTxDone; 00173 RadioEvents.RxDone = OnRxDone; 00174 RadioEvents.RxError = OnRxError; 00175 RadioEvents.TxTimeout = OnTxTimeout; 00176 RadioEvents.RxTimeout = OnRxTimeout; 00177 Radio.Init( &RadioEvents ); 00178 00179 // seed 15-byte randomness via noise rssi 00180 // Set LoRa modem ON 00181 Radio.SetModem( MODEM_LORA ); 00182 // Disable LoRa modem interrupts 00183 Radio.Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | 00184 RFLR_IRQFLAGS_RXDONE | 00185 RFLR_IRQFLAGS_PAYLOADCRCERROR | 00186 RFLR_IRQFLAGS_VALIDHEADER | 00187 RFLR_IRQFLAGS_TXDONE | 00188 RFLR_IRQFLAGS_CADDONE | 00189 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | 00190 RFLR_IRQFLAGS_CADDETECTED ); 00191 00192 // Set radio in continuous reception 00193 Radio.Rx( 0 ); 00194 00195 for( int i = 1; i < 16; i++ ) 00196 { 00197 for( int j = 0; j < 8; j++ ) 00198 { 00199 u1_t b; // wait for two non-identical subsequent least-significant bits 00200 while( ( b = Radio.Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) == ( Radio.Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) ); 00201 randbuf[i] = ( randbuf[i] << 1 ) | b; 00202 } 00203 } 00204 randbuf[0] = 16; // set initial index 00205 00206 // Change LoRa modem SyncWord 00207 Radio.Write( REG_LR_SYNCWORD, LORA_MAC_SYNCWORD ); 00208 00209 Radio.Sleep( ); 00210 00211 hal_enableIRQs( ); 00212 } 00213 00214 // return next random byte derived from seed buffer 00215 // (buf[0] holds index of next byte to be returned) 00216 u1_t radio_rand1( void ) 00217 { 00218 u1_t i = randbuf[0]; 00219 ASSERT( i != 0 ); 00220 if( i == 16 ) 00221 { 00222 os_aes( AES_ENC, randbuf, 16 ); // encrypt seed with any key 00223 i = 0; 00224 } 00225 u1_t v = randbuf[i++]; 00226 randbuf[0] = i; 00227 return v; 00228 } 00229 00230 void os_radio( u1_t mode ) 00231 { 00232 hal_disableIRQs( ); 00233 switch( mode ) 00234 { 00235 case RADIO_RST: 00236 // put radio to sleep 00237 Radio.Sleep( ); 00238 break; 00239 00240 case RADIO_TX: 00241 // transmit frame now 00242 //ASSERT( Radio.GetState( ) == IDLE ); 00243 00244 Radio.SetChannel( LMIC.freq ); 00245 if( getSf( LMIC.rps ) == FSK ) 00246 { // FSK modem 00247 Radio.SetTxConfig( MODEM_FSK, LMIC.txpow, 25e3, 0, 50e3, 0, 5, false, true, 0, 0, false, 3e6 ); 00248 } 00249 else 00250 { // LoRa modem 00251 00252 Radio.SetTxConfig( MODEM_LORA, LMIC.txpow, 0, getBw( LMIC.rps ), getSf( LMIC.rps ) + 6, getCr( LMIC.rps ) + 1, 8, getIh( LMIC.rps ) ? true : false, ( getNocrc( LMIC.rps ) == 0 ) ? true : false, 0, 0, false, 3e6 ); 00253 } 00254 00255 //starttx( ); // buf=LMIC.frame, len=LMIC.dataLen 00256 Radio.Send( LMIC.frame, LMIC.dataLen ); 00257 break; 00258 00259 case RADIO_RX: 00260 // receive frame now (exactly at rxtime) 00261 //ASSERT( Radio.GetState( ) == IDLE ); 00262 00263 Radio.SetChannel( LMIC.freq ); 00264 if( getSf( LMIC.rps ) == FSK ) 00265 { // FSK modem 00266 //Radio.SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, false ); 00267 Radio.SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, true ); 00268 } 00269 else 00270 { // LoRa modem 00271 if( ( getSf( LMIC.rps ) <= SF9 ) && ( LMIC.rxsyms < 8 ) ) 00272 { 00273 Radio.SetRxConfig( MODEM_LORA, getBw( LMIC.rps ), getSf( LMIC.rps ) + 6, getCr( LMIC.rps ) + 1, 0, 8, LMIC.rxsyms + 3, getIh( LMIC.rps ) ? true : false, getIh( LMIC.rps ), ( getNocrc( LMIC.rps ) == 0 ) ? true : false, 0, 0, true, false ); 00274 } 00275 else 00276 { 00277 Radio.SetRxConfig( MODEM_LORA, getBw( LMIC.rps ), getSf( LMIC.rps ) + 6, getCr( LMIC.rps ) + 1, 0, 8, LMIC.rxsyms, getIh( LMIC.rps ) ? true : false, getIh( LMIC.rps ), ( getNocrc( LMIC.rps ) == 0 ) ? true : false, 0, 0, true, false ); 00278 } 00279 } 00280 00281 // now instruct the radio to receive 00282 hal_waitUntil( LMIC.rxtime ); // busy wait until exact rx time 00283 00284 //startrx( RXMODE_SINGLE ); // buf = LMIC.frame, time = LMIC.rxtime, timeout=LMIC.rxsyms 00285 if( getSf( LMIC.rps ) == FSK ) 00286 { // FSK modem 00287 Radio.Rx( 50e3 ); // Max Rx window 50 ms 00288 } 00289 else 00290 { // LoRa modem 00291 Radio.Rx( 3e6 ); // Max Rx window 3 seconds 00292 } 00293 break; 00294 00295 case RADIO_RXON: 00296 // start scanning for beacon now 00297 00298 //ASSERT( Radio.GetState( ) == IDLE ); 00299 00300 Radio.SetChannel( LMIC.freq ); 00301 if( getSf( LMIC.rps ) == FSK ) 00302 { // FSK modem 00303 Radio.SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, true ); 00304 } 00305 else 00306 { // LoRa modem 00307 Radio.SetRxConfig( MODEM_LORA, getBw( LMIC.rps ), getSf( LMIC.rps ) + 6, getCr( LMIC.rps ) + 1, 0, 8, LMIC.rxsyms, getIh( LMIC.rps ) ? true : false, getIh( LMIC.rps ), ( getNocrc( LMIC.rps ) == 0 ) ? true : false, 0, 0, true, true ); 00308 } 00309 00310 //startrx( RXMODE_SCAN ); // buf = LMIC.frame 00311 Radio.Rx( 0 ); 00312 break; 00313 } 00314 hal_enableIRQs( ); 00315 } 00316 00317 #else 00318 00319 // ---------------------------------------- 00320 // Registers Mapping 00321 #define RegFifo 0x00 // common 00322 #define RegOpMode 0x01 // common 00323 #define FSKRegBitrateMsb 0x02 00324 #define FSKRegBitrateLsb 0x03 00325 #define FSKRegFdevMsb 0x04 00326 #define FSKRegFdevLsb 0x05 00327 #define RegFrfMsb 0x06 // common 00328 #define RegFrfMid 0x07 // common 00329 #define RegFrfLsb 0x08 // common 00330 #define RegPaConfig 0x09 // common 00331 #define RegPaRamp 0x0A // common 00332 #define RegOcp 0x0B // common 00333 #define RegLna 0x0C // common 00334 #define FSKRegRxConfig 0x0D 00335 #define LORARegFifoAddrPtr 0x0D 00336 #define FSKRegRssiConfig 0x0E 00337 #define LORARegFifoTxBaseAddr 0x0E 00338 #define FSKRegRssiCollision 0x0F 00339 #define LORARegFifoRxBaseAddr 0x0F 00340 #define FSKRegRssiThresh 0x10 00341 #define LORARegFifoRxCurrentAddr 0x10 00342 #define FSKRegRssiValue 0x11 00343 #define LORARegIrqFlagsMask 0x11 00344 #define FSKRegRxBw 0x12 00345 #define LORARegIrqFlags 0x12 00346 #define FSKRegAfcBw 0x13 00347 #define LORARegRxNbBytes 0x13 00348 #define FSKRegOokPeak 0x14 00349 #define LORARegRxHeaderCntValueMsb 0x14 00350 #define FSKRegOokFix 0x15 00351 #define LORARegRxHeaderCntValueLsb 0x15 00352 #define FSKRegOokAvg 0x16 00353 #define LORARegRxPacketCntValueMsb 0x16 00354 #define LORARegRxpacketCntValueLsb 0x17 00355 #define LORARegModemStat 0x18 00356 #define LORARegPktSnrValue 0x19 00357 #define FSKRegAfcFei 0x1A 00358 #define LORARegPktRssiValue 0x1A 00359 #define FSKRegAfcMsb 0x1B 00360 #define LORARegRssiValue 0x1B 00361 #define FSKRegAfcLsb 0x1C 00362 #define LORARegHopChannel 0x1C 00363 #define FSKRegFeiMsb 0x1D 00364 #define LORARegModemConfig1 0x1D 00365 #define FSKRegFeiLsb 0x1E 00366 #define LORARegModemConfig2 0x1E 00367 #define FSKRegPreambleDetect 0x1F 00368 #define LORARegSymbTimeoutLsb 0x1F 00369 #define FSKRegRxTimeout1 0x20 00370 #define LORARegPreambleMsb 0x20 00371 #define FSKRegRxTimeout2 0x21 00372 #define LORARegPreambleLsb 0x21 00373 #define FSKRegRxTimeout3 0x22 00374 #define LORARegPayloadLength 0x22 00375 #define FSKRegRxDelay 0x23 00376 #define LORARegPayloadMaxLength 0x23 00377 #define FSKRegOsc 0x24 00378 #define LORARegHopPeriod 0x24 00379 #define FSKRegPreambleMsb 0x25 00380 #define LORARegFifoRxByteAddr 0x25 00381 #define LORARegModemConfig3 0x26 00382 #define FSKRegPreambleLsb 0x26 00383 #define FSKRegSyncConfig 0x27 00384 #define LORARegFeiMsb 0x28 00385 #define FSKRegSyncValue1 0x28 00386 #define LORAFeiMib 0x29 00387 #define FSKRegSyncValue2 0x29 00388 #define LORARegFeiLsb 0x2A 00389 #define FSKRegSyncValue3 0x2A 00390 #define FSKRegSyncValue4 0x2B 00391 #define LORARegRssiWideband 0x2C 00392 #define FSKRegSyncValue5 0x2C 00393 #define FSKRegSyncValue6 0x2D 00394 #define FSKRegSyncValue7 0x2E 00395 #define FSKRegSyncValue8 0x2F 00396 #define FSKRegPacketConfig1 0x30 00397 #define FSKRegPacketConfig2 0x31 00398 #define LORARegDetectOptimize 0x31 00399 #define FSKRegPayloadLength 0x32 00400 #define FSKRegNodeAdrs 0x33 00401 #define LORARegInvertIQ 0x33 00402 #define FSKRegBroadcastAdrs 0x34 00403 #define FSKRegFifoThresh 0x35 00404 #define FSKRegSeqConfig1 0x36 00405 #define FSKRegSeqConfig2 0x37 00406 #define LORARegDetectionThreshold 0x37 00407 #define FSKRegTimerResol 0x38 00408 #define FSKRegTimer1Coef 0x39 00409 #define LORARegSyncWord 0x39 00410 #define FSKRegTimer2Coef 0x3A 00411 #define FSKRegImageCal 0x3B 00412 #define FSKRegTemp 0x3C 00413 #define FSKRegLowBat 0x3D 00414 #define FSKRegIrqFlags1 0x3E 00415 #define FSKRegIrqFlags2 0x3F 00416 #define RegDioMapping1 0x40 // common 00417 #define RegDioMapping2 0x41 // common 00418 #define RegVersion 0x42 // common 00419 // #define RegAgcRef 0x43 // common 00420 // #define RegAgcThresh1 0x44 // common 00421 // #define RegAgcThresh2 0x45 // common 00422 // #define RegAgcThresh3 0x46 // common 00423 // #define RegPllHop 0x4B // common 00424 // #define RegTcxo 0x58 // common 00425 #define RegPaDac 0x5A // common 00426 // #define RegPll 0x5C // common 00427 // #define RegPllLowPn 0x5E // common 00428 // #define RegFormerTemp 0x6C // common 00429 // #define RegBitRateFrac 0x70 // common 00430 00431 // ---------------------------------------- 00432 // spread factors and mode for RegModemConfig2 00433 #define SX1272_MC2_FSK 0x00 00434 #define SX1272_MC2_SF7 0x70 00435 #define SX1272_MC2_SF8 0x80 00436 #define SX1272_MC2_SF9 0x90 00437 #define SX1272_MC2_SF10 0xA0 00438 #define SX1272_MC2_SF11 0xB0 00439 #define SX1272_MC2_SF12 0xC0 00440 // bandwidth for RegModemConfig1 00441 #define SX1272_MC1_BW_125 0x00 00442 #define SX1272_MC1_BW_250 0x40 00443 #define SX1272_MC1_BW_500 0x80 00444 // coding rate for RegModemConfig1 00445 #define SX1272_MC1_CR_4_5 0x08 00446 #define SX1272_MC1_CR_4_6 0x10 00447 #define SX1272_MC1_CR_4_7 0x18 00448 #define SX1272_MC1_CR_4_8 0x20 00449 #define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive 00450 #define SX1272_MC1_RX_PAYLOAD_CRCON 0x02 00451 #define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12 00452 // transmit power configuration for RegPaConfig 00453 #define SX1272_PAC_PA_SELECT_PA_BOOST 0x80 00454 #define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00 00455 00456 00457 // sx1276 RegModemConfig1 00458 #define SX1276_MC1_BW_125 0x70 00459 #define SX1276_MC1_BW_250 0x80 00460 #define SX1276_MC1_BW_500 0x90 00461 #define SX1276_MC1_CR_4_5 0x02 00462 #define SX1276_MC1_CR_4_6 0x04 00463 #define SX1276_MC1_CR_4_7 0x06 00464 #define SX1276_MC1_CR_4_8 0x08 00465 00466 #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01 00467 00468 // sx1276 RegModemConfig2 00469 #define SX1276_MC2_RX_PAYLOAD_CRCON 0x04 00470 00471 // sx1276 RegModemConfig3 00472 #define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08 00473 #define SX1276_MC3_AGCAUTO 0x04 00474 00475 // preamble for lora networks (nibbles swapped) 00476 #define LORA_MAC_PREAMBLE 0x34 00477 00478 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A 00479 #ifdef CFG_sx1276_radio 00480 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70 00481 #elif CFG_sx1272_radio 00482 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74 00483 #endif 00484 00485 00486 00487 // ---------------------------------------- 00488 // Constants for radio registers 00489 #define OPMODE_LORA 0x80 00490 #define OPMODE_MASK 0x07 00491 #define OPMODE_SLEEP 0x00 00492 #define OPMODE_STANDBY 0x01 00493 #define OPMODE_FSTX 0x02 00494 #define OPMODE_TX 0x03 00495 #define OPMODE_FSRX 0x04 00496 #define OPMODE_RX 0x05 00497 #define OPMODE_RX_SINGLE 0x06 00498 #define OPMODE_CAD 0x07 00499 00500 // ---------------------------------------- 00501 // Bits masking the corresponding IRQs from the radio 00502 #define IRQ_LORA_RXTOUT_MASK 0x80 00503 #define IRQ_LORA_RXDONE_MASK 0x40 00504 #define IRQ_LORA_CRCERR_MASK 0x20 00505 #define IRQ_LORA_HEADER_MASK 0x10 00506 #define IRQ_LORA_TXDONE_MASK 0x08 00507 #define IRQ_LORA_CDDONE_MASK 0x04 00508 #define IRQ_LORA_FHSSCH_MASK 0x02 00509 #define IRQ_LORA_CDDETD_MASK 0x01 00510 00511 #define IRQ_FSK1_MODEREADY_MASK 0x80 00512 #define IRQ_FSK1_RXREADY_MASK 0x40 00513 #define IRQ_FSK1_TXREADY_MASK 0x20 00514 #define IRQ_FSK1_PLLLOCK_MASK 0x10 00515 #define IRQ_FSK1_RSSI_MASK 0x08 00516 #define IRQ_FSK1_TIMEOUT_MASK 0x04 00517 #define IRQ_FSK1_PREAMBLEDETECT_MASK 0x02 00518 #define IRQ_FSK1_SYNCADDRESSMATCH_MASK 0x01 00519 #define IRQ_FSK2_FIFOFULL_MASK 0x80 00520 #define IRQ_FSK2_FIFOEMPTY_MASK 0x40 00521 #define IRQ_FSK2_FIFOLEVEL_MASK 0x20 00522 #define IRQ_FSK2_FIFOOVERRUN_MASK 0x10 00523 #define IRQ_FSK2_PACKETSENT_MASK 0x08 00524 #define IRQ_FSK2_PAYLOADREADY_MASK 0x04 00525 #define IRQ_FSK2_CRCOK_MASK 0x02 00526 #define IRQ_FSK2_LOWBAT_MASK 0x01 00527 00528 // ---------------------------------------- 00529 // DIO function mappings D0D1D2D3 00530 #define MAP_DIO0_LORA_RXDONE 0x00 // 00------ 00531 #define MAP_DIO0_LORA_TXDONE 0x40 // 01------ 00532 #define MAP_DIO1_LORA_RXTOUT 0x00 // --00---- 00533 #define MAP_DIO1_LORA_NOP 0x30 // --11---- 00534 #define MAP_DIO2_LORA_NOP 0xC0 // ----11-- 00535 00536 #define MAP_DIO0_FSK_READY 0x00 // 00------ (packet sent / payload ready) 00537 #define MAP_DIO1_FSK_NOP 0x30 // --11---- 00538 #define MAP_DIO2_FSK_TXNOP 0x04 // ----01-- 00539 #define MAP_DIO2_FSK_TIMEOUT 0x08 // ----10-- 00540 00541 00542 // FSK IMAGECAL defines 00543 #define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F 00544 #define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80 00545 #define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default 00546 00547 #define RF_IMAGECAL_IMAGECAL_MASK 0xBF 00548 #define RF_IMAGECAL_IMAGECAL_START 0x40 00549 00550 #define RF_IMAGECAL_IMAGECAL_RUNNING 0x20 00551 #define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default 00552 00553 00554 // RADIO STATE 00555 // (initialized by radio_init(), used by radio_rand1()) 00556 static u1_t randbuf[16]; 00557 00558 00559 #ifdef CFG_sx1276_radio 00560 #define LNA_RX_GAIN (0x20|0x1) 00561 #elif CFG_sx1272_radio 00562 #define LNA_RX_GAIN (0x20|0x03) 00563 #else 00564 #error Missing CFG_sx1272_radio/CFG_sx1276_radio 00565 #endif 00566 00567 #define RADIO_DBG 00568 #if defined(RADIO_DBG) 00569 DigitalOut txStateIo( PB_8 ); 00570 DigitalOut rxStateIo( PB_9 ); 00571 #endif 00572 00573 static void writeReg (u1_t addr, u1_t data ) { 00574 hal_pin_nss(0); 00575 hal_spi(addr | 0x80); 00576 hal_spi(data); 00577 hal_pin_nss(1); 00578 } 00579 00580 static u1_t readReg (u1_t addr) { 00581 hal_pin_nss(0); 00582 hal_spi(addr & 0x7F); 00583 u1_t val = hal_spi(0x00); 00584 hal_pin_nss(1); 00585 return val; 00586 } 00587 00588 static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len) { 00589 hal_pin_nss(0); 00590 hal_spi(addr | 0x80); 00591 for (u1_t i=0; i<len; i++) { 00592 hal_spi(buf[i]); 00593 } 00594 hal_pin_nss(1); 00595 } 00596 00597 static void readBuf (u1_t addr, xref2u1_t buf, u1_t len) { 00598 hal_pin_nss(0); 00599 hal_spi(addr & 0x7F); 00600 for (u1_t i=0; i<len; i++) { 00601 buf[i] = hal_spi(0x00); 00602 } 00603 hal_pin_nss(1); 00604 } 00605 00606 static void opmode (u1_t mode) { 00607 writeReg(RegOpMode, (readReg(RegOpMode) & ~OPMODE_MASK) | mode); 00608 } 00609 00610 static void opmodeLora() { 00611 u1_t u = OPMODE_LORA; 00612 #ifdef CFG_sx1276_radio 00613 u |= 0x8; // TBD: sx1276 high freq 00614 #endif 00615 writeReg(RegOpMode, u); 00616 } 00617 00618 static void opmodeFSK() { 00619 u1_t u = 0; 00620 #ifdef CFG_sx1276_radio 00621 u |= 0x8; // TBD: sx1276 high freq 00622 #endif 00623 writeReg(RegOpMode, u); 00624 } 00625 00626 // configure LoRa modem (cfg1, cfg2) 00627 static void configLoraModem () { 00628 sf_t sf = getSf(LMIC.rps); 00629 00630 #ifdef CFG_sx1276_radio 00631 u1_t mc1 = 0, mc2 = 0, mc3 = 0; 00632 00633 switch (getBw(LMIC.rps)) { 00634 case BW125: mc1 |= SX1276_MC1_BW_125; break; 00635 case BW250: mc1 |= SX1276_MC1_BW_250; break; 00636 case BW500: mc1 |= SX1276_MC1_BW_500; break; 00637 default: 00638 ASSERT(0); 00639 } 00640 switch( getCr(LMIC.rps) ) { 00641 case CR_4_5: mc1 |= SX1276_MC1_CR_4_5; break; 00642 case CR_4_6: mc1 |= SX1276_MC1_CR_4_6; break; 00643 case CR_4_7: mc1 |= SX1276_MC1_CR_4_7; break; 00644 case CR_4_8: mc1 |= SX1276_MC1_CR_4_8; break; 00645 default: 00646 ASSERT(0); 00647 } 00648 00649 if (getIh(LMIC.rps)) { 00650 mc1 |= SX1276_MC1_IMPLICIT_HEADER_MODE_ON; 00651 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length 00652 } 00653 // set ModemConfig1 00654 writeReg(LORARegModemConfig1, mc1); 00655 00656 mc2 = (SX1272_MC2_SF7 + ((sf-1)<<4)); 00657 if (getNocrc(LMIC.rps) == 0) { 00658 mc2 |= SX1276_MC2_RX_PAYLOAD_CRCON; 00659 } 00660 writeReg(LORARegModemConfig2, mc2); 00661 00662 mc3 = SX1276_MC3_AGCAUTO; 00663 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) { 00664 mc3 |= SX1276_MC3_LOW_DATA_RATE_OPTIMIZE; 00665 } 00666 writeReg(LORARegModemConfig3, mc3); 00667 #elif CFG_sx1272_radio 00668 u1_t mc1 = (getBw(LMIC.rps)<<6); 00669 00670 switch( getCr(LMIC.rps) ) { 00671 case CR_4_5: mc1 |= SX1272_MC1_CR_4_5; break; 00672 case CR_4_6: mc1 |= SX1272_MC1_CR_4_6; break; 00673 case CR_4_7: mc1 |= SX1272_MC1_CR_4_7; break; 00674 case CR_4_8: mc1 |= SX1272_MC1_CR_4_8; break; 00675 } 00676 00677 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) { 00678 mc1 |= SX1272_MC1_LOW_DATA_RATE_OPTIMIZE; 00679 } 00680 00681 if (getNocrc(LMIC.rps) == 0) { 00682 mc1 |= SX1272_MC1_RX_PAYLOAD_CRCON; 00683 } 00684 00685 if (getIh(LMIC.rps)) { 00686 mc1 |= SX1272_MC1_IMPLICIT_HEADER_MODE_ON; 00687 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length 00688 } 00689 // set ModemConfig1 00690 writeReg(LORARegModemConfig1, mc1); 00691 00692 // set ModemConfig2 (sf, AgcAutoOn=1 SymbTimeoutHi=00) 00693 writeReg(LORARegModemConfig2, (SX1272_MC2_SF7 + ((sf-1)<<4)) | 0x04); 00694 #else 00695 #error Missing CFG_sx1272_radio/CFG_sx1276_radio 00696 #endif /* CFG_sx1272_radio */ 00697 } 00698 00699 static void configChannel () { 00700 // set frequency: FQ = (FRF * 32 Mhz) / (2 ^ 19) 00701 u8_t frf = ((u8_t)LMIC.freq << 19) / 32000000; 00702 writeReg(RegFrfMsb, (u1_t)(frf>>16)); 00703 writeReg(RegFrfMid, (u1_t)(frf>> 8)); 00704 writeReg(RegFrfLsb, (u1_t)(frf>> 0)); 00705 } 00706 00707 00708 00709 static void configPower () { 00710 #ifdef CFG_sx1276_radio 00711 // no boost used for now 00712 s1_t pw = (s1_t)LMIC.txpow; 00713 if(pw >= 17) { 00714 pw = 15; 00715 } else if(pw < 2) { 00716 pw = 2; 00717 } 00718 // check board type for BOOST pin 00719 writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf))); 00720 writeReg(RegPaDac, readReg(RegPaDac)|0x4); 00721 00722 #elif CFG_sx1272_radio 00723 // set PA config (2-17 dBm using PA_BOOST) 00724 s1_t pw = (s1_t)LMIC.txpow; 00725 if(pw > 17) { 00726 pw = 17; 00727 } else if(pw < 2) { 00728 pw = 2; 00729 } 00730 writeReg(RegPaConfig, (u1_t)(0x80|(pw-2))); 00731 #else 00732 #error Missing CFG_sx1272_radio/CFG_sx1276_radio 00733 #endif /* CFG_sx1272_radio */ 00734 } 00735 00736 static void txfsk () { 00737 // select FSK modem (from sleep mode) 00738 writeReg(RegOpMode, 0x10); // FSK, BT=0.5 00739 ASSERT(readReg(RegOpMode) == 0x10); 00740 // enter standby mode (required for FIFO loading)) 00741 opmode(OPMODE_STANDBY); 00742 #if defined(RADIO_DBG) 00743 txStateIo = 0; 00744 rxStateIo = 0; 00745 #endif 00746 // set bitrate 00747 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps 00748 writeReg(FSKRegBitrateLsb, 0x80); 00749 // set frequency deviation 00750 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz 00751 writeReg(FSKRegFdevLsb, 0x99); 00752 // frame and packet handler settings 00753 writeReg(FSKRegPreambleMsb, 0x00); 00754 writeReg(FSKRegPreambleLsb, 0x05); 00755 writeReg(FSKRegSyncConfig, 0x12); 00756 writeReg(FSKRegPacketConfig1, 0xD0); 00757 writeReg(FSKRegPacketConfig2, 0x40); 00758 writeReg(FSKRegSyncValue1, 0xC1); 00759 writeReg(FSKRegSyncValue2, 0x94); 00760 writeReg(FSKRegSyncValue3, 0xC1); 00761 // configure frequency 00762 configChannel(); 00763 // configure output power 00764 configPower(); 00765 00766 // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP 00767 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP); 00768 00769 // initialize the payload size and address pointers 00770 writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload)) 00771 00772 // download length byte and buffer to the radio FIFO 00773 writeReg(RegFifo, LMIC.dataLen); 00774 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen); 00775 00776 // enable antenna switch for TX 00777 hal_pin_rxtx(1); 00778 00779 // now we actually start the transmission 00780 opmode(OPMODE_TX); 00781 #if defined(RADIO_DBG) 00782 txStateIo = 1; 00783 #endif 00784 } 00785 00786 static void txlora () { 00787 // select LoRa modem (from sleep mode) 00788 //writeReg(RegOpMode, OPMODE_LORA); 00789 opmodeLora(); 00790 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0); 00791 00792 // enter standby mode (required for FIFO loading)) 00793 opmode(OPMODE_STANDBY); 00794 #if defined(RADIO_DBG) 00795 txStateIo = 0; 00796 rxStateIo = 0; 00797 #endif 00798 // configure LoRa modem (cfg1, cfg2) 00799 configLoraModem(); 00800 // configure frequency 00801 configChannel(); 00802 // configure output power 00803 writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec 00804 configPower(); 00805 // set sync word 00806 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE); 00807 00808 // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP 00809 writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP); 00810 // clear all radio IRQ flags 00811 writeReg(LORARegIrqFlags, 0xFF); 00812 // mask all IRQs but TxDone 00813 writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK); 00814 00815 // initialize the payload size and address pointers 00816 writeReg(LORARegFifoTxBaseAddr, 0x00); 00817 writeReg(LORARegFifoAddrPtr, 0x00); 00818 writeReg(LORARegPayloadLength, LMIC.dataLen); 00819 00820 // download buffer to the radio FIFO 00821 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen); 00822 00823 // enable antenna switch for TX 00824 hal_pin_rxtx(1); 00825 00826 // now we actually start the transmission 00827 opmode(OPMODE_TX); 00828 } 00829 00830 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen) 00831 static void starttx () { 00832 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP ); 00833 if(getSf(LMIC.rps) == FSK) { // FSK modem 00834 txfsk(); 00835 } else { // LoRa modem 00836 txlora(); 00837 } 00838 // the radio will go back to STANDBY mode as soon as the TX is finished 00839 // the corresponding IRQ will inform us about completion. 00840 } 00841 00842 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI }; 00843 00844 static const u1_t rxlorairqmask[] = { 00845 [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK, 00846 [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK, 00847 [RXMODE_RSSI] = 0x00, 00848 }; 00849 00850 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen]) 00851 static void rxlora (u1_t rxmode) { 00852 // select LoRa modem (from sleep mode) 00853 opmodeLora(); 00854 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0); 00855 // enter standby mode (warm up)) 00856 opmode(OPMODE_STANDBY); 00857 #if defined(RADIO_DBG) 00858 txStateIo = 0; 00859 rxStateIo = 0; 00860 #endif 00861 // don't use MAC settings at startup 00862 if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan 00863 writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1); 00864 writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2); 00865 } else { // single or continuous rx mode 00866 // configure LoRa modem (cfg1, cfg2) 00867 configLoraModem(); 00868 // configure frequency 00869 configChannel(); 00870 } 00871 // set LNA gain 00872 writeReg(RegLna, LNA_RX_GAIN); 00873 // set max payload size 00874 writeReg(LORARegPayloadMaxLength, 64); 00875 // use inverted I/Q signal (prevent mote-to-mote communication) 00876 writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6)); 00877 // set symbol timeout (for single rx) 00878 writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms); 00879 // set sync word 00880 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE); 00881 00882 // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP 00883 writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP); 00884 // clear all radio IRQ flags 00885 writeReg(LORARegIrqFlags, 0xFF); 00886 // enable required radio IRQs 00887 writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]); 00888 00889 // enable antenna switch for RX 00890 hal_pin_rxtx(0); 00891 00892 // now instruct the radio to receive 00893 if (rxmode == RXMODE_SINGLE) { // single rx 00894 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time 00895 opmode(OPMODE_RX_SINGLE); 00896 #if defined(RADIO_DBG) 00897 rxStateIo = 1; 00898 #endif 00899 } else { // continous rx (scan or rssi) 00900 opmode(OPMODE_RX); 00901 #if defined(RADIO_DBG) 00902 rxStateIo = 1; 00903 #endif 00904 } 00905 } 00906 00907 static void rxfsk (u1_t rxmode) { 00908 // only single rx (no continuous scanning, no noise sampling) 00909 ASSERT( rxmode == RXMODE_SINGLE ); 00910 // select FSK modem (from sleep mode) 00911 //writeReg(RegOpMode, 0x00); // (not LoRa) 00912 opmodeFSK(); 00913 ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0); 00914 // enter standby mode (warm up)) 00915 opmode(OPMODE_STANDBY); 00916 #if defined(RADIO_DBG) 00917 txStateIo = 0; 00918 rxStateIo = 0; 00919 #endif 00920 // configure frequency 00921 configChannel(); 00922 // set LNA gain 00923 //writeReg(RegLna, 0x20|0x03); // max gain, boost enable 00924 writeReg(RegLna, LNA_RX_GAIN); 00925 // configure receiver 00926 writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!? 00927 // set receiver bandwidth 00928 writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb 00929 // set AFC bandwidth 00930 writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB 00931 // set preamble detection 00932 writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors 00933 // set sync config 00934 writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync 00935 // set packet config 00936 writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter 00937 writeReg(FSKRegPacketConfig2, 0x40); // packet mode 00938 // set sync value 00939 writeReg(FSKRegSyncValue1, 0xC1); 00940 writeReg(FSKRegSyncValue2, 0x94); 00941 writeReg(FSKRegSyncValue3, 0xC1); 00942 // set preamble timeout 00943 writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2); 00944 // set bitrate 00945 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps 00946 writeReg(FSKRegBitrateLsb, 0x80); 00947 // set frequency deviation 00948 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz 00949 writeReg(FSKRegFdevLsb, 0x99); 00950 00951 // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut 00952 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT); 00953 00954 // enable antenna switch for RX 00955 hal_pin_rxtx(0); 00956 00957 // now instruct the radio to receive 00958 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time 00959 opmode(OPMODE_RX); // no single rx mode available in FSK 00960 #if defined(RADIO_DBG) 00961 rxStateIo = 1; 00962 #endif 00963 } 00964 00965 static void startrx (u1_t rxmode) { 00966 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP ); 00967 if(getSf(LMIC.rps) == FSK) { // FSK modem 00968 rxfsk(rxmode); 00969 } else { // LoRa modem 00970 rxlora(rxmode); 00971 } 00972 // the radio will go back to STANDBY mode as soon as the RX is finished 00973 // or timed out, and the corresponding IRQ will inform us about completion. 00974 } 00975 00976 // get random seed from wideband noise rssi 00977 void radio_init () { 00978 hal_disableIRQs(); 00979 00980 // manually reset radio 00981 #ifdef CFG_sx1276_radio 00982 hal_pin_rst(0); // drive RST pin low 00983 #else 00984 hal_pin_rst(1); // drive RST pin high 00985 #endif 00986 hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us 00987 hal_pin_rst(2); // configure RST pin floating! 00988 hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms 00989 00990 opmode(OPMODE_SLEEP); 00991 #if defined(RADIO_DBG) 00992 txStateIo = 0; 00993 rxStateIo = 0; 00994 #endif 00995 // some sanity checks, e.g., read version number 00996 u1_t v = readReg(RegVersion); 00997 #ifdef CFG_sx1276_radio 00998 ASSERT(v == 0x12 ); 00999 #elif CFG_sx1272_radio 01000 ASSERT(v == 0x22); 01001 #else 01002 #error Missing CFG_sx1272_radio/CFG_sx1276_radio 01003 #endif 01004 // seed 15-byte randomness via noise rssi 01005 rxlora(RXMODE_RSSI); 01006 while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx 01007 for(int i=1; i<16; i++) { 01008 for(int j=0; j<8; j++) { 01009 u1_t b; // wait for two non-identical subsequent least-significant bits 01010 while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) ); 01011 randbuf[i] = (randbuf[i] << 1) | b; 01012 } 01013 } 01014 randbuf[0] = 16; // set initial index 01015 01016 #ifdef CFG_sx1276mb1_board 01017 // chain calibration 01018 writeReg(RegPaConfig, 0); 01019 01020 // Launch Rx chain calibration for LF band 01021 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); 01022 while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; } 01023 01024 // Sets a Frequency in HF band 01025 u4_t frf = 868000000; 01026 writeReg(RegFrfMsb, (u1_t)(frf>>16)); 01027 writeReg(RegFrfMid, (u1_t)(frf>> 8)); 01028 writeReg(RegFrfLsb, (u1_t)(frf>> 0)); 01029 01030 // Launch Rx chain calibration for HF band 01031 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); 01032 while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; } 01033 #endif /* CFG_sx1276mb1_board */ 01034 01035 opmode(OPMODE_SLEEP); 01036 #if defined(RADIO_DBG) 01037 txStateIo = 0; 01038 rxStateIo = 0; 01039 #endif 01040 hal_enableIRQs(); 01041 } 01042 01043 // return next random byte derived from seed buffer 01044 // (buf[0] holds index of next byte to be returned) 01045 u1_t radio_rand1 () { 01046 u1_t i = randbuf[0]; 01047 ASSERT( i != 0 ); 01048 if( i==16 ) { 01049 os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key 01050 i = 0; 01051 } 01052 u1_t v = randbuf[i++]; 01053 randbuf[0] = i; 01054 return v; 01055 } 01056 01057 u1_t radio_rssi () { 01058 hal_disableIRQs(); 01059 u1_t r = readReg(LORARegRssiValue); 01060 hal_enableIRQs(); 01061 return r; 01062 } 01063 01064 static const u2_t LORA_RXDONE_FIXUP[] = { 01065 [FSK] = us2osticks(0), // ( 0 ticks) 01066 [SF7] = us2osticks(0), // ( 0 ticks) 01067 [SF8] = us2osticks(1648), // ( 54 ticks) 01068 [SF9] = us2osticks(3265), // ( 107 ticks) 01069 [SF10] = us2osticks(7049), // ( 231 ticks) 01070 [SF11] = us2osticks(13641), // ( 447 ticks) 01071 [SF12] = us2osticks(31189), // (1022 ticks) 01072 }; 01073 01074 // called by hal ext IRQ handler 01075 // (radio goes to stanby mode after tx/rx operations) 01076 void radio_irq_handler (u1_t dio) { 01077 ostime_t now = os_getTime(); 01078 if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem 01079 u1_t flags = readReg(LORARegIrqFlags); 01080 if( flags & IRQ_LORA_TXDONE_MASK ) { 01081 // save exact tx time 01082 LMIC.txend = now - us2osticks(43); // TXDONE FIXUP 01083 } else if( flags & IRQ_LORA_RXDONE_MASK ) { 01084 // save exact rx time 01085 if(getBw(LMIC.rps) == BW125) { 01086 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)]; 01087 } 01088 LMIC.rxtime = now; 01089 // read the PDU and inform the MAC that we received something 01090 LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ? 01091 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes); 01092 // set FIFO read address pointer 01093 writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr)); 01094 // now read the FIFO 01095 readBuf(RegFifo, LMIC.frame, LMIC.dataLen); 01096 // read rx quality parameters 01097 LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4 01098 LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63) 01099 } else if( flags & IRQ_LORA_RXTOUT_MASK ) { 01100 // indicate timeout 01101 LMIC.dataLen = 0; 01102 } 01103 // mask all radio IRQs 01104 writeReg(LORARegIrqFlagsMask, 0xFF); 01105 // clear radio IRQ flags 01106 writeReg(LORARegIrqFlags, 0xFF); 01107 } else { // FSK modem 01108 u1_t flags1 = readReg(FSKRegIrqFlags1); 01109 u1_t flags2 = readReg(FSKRegIrqFlags2); 01110 if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) { 01111 // save exact tx time 01112 LMIC.txend = now; 01113 } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) { 01114 // save exact rx time 01115 LMIC.rxtime = now; 01116 // read the PDU and inform the MAC that we received something 01117 LMIC.dataLen = readReg(FSKRegPayloadLength); 01118 // now read the FIFO 01119 readBuf(RegFifo, LMIC.frame, LMIC.dataLen); 01120 // read rx quality parameters 01121 LMIC.snr = 0; // determine snr 01122 LMIC.rssi = 0; // determine rssi 01123 } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) { 01124 // indicate timeout 01125 LMIC.dataLen = 0; 01126 } else { 01127 while(1); 01128 } 01129 } 01130 // go from stanby to sleep 01131 opmode(OPMODE_SLEEP); 01132 #if defined(RADIO_DBG) 01133 txStateIo = 0; 01134 rxStateIo = 0; 01135 #endif 01136 // run os job (use preset func ptr) 01137 os_setCallback(&LMIC.osjob, LMIC.osjob.func); 01138 } 01139 01140 void os_radio (u1_t mode) { 01141 hal_disableIRQs(); 01142 switch (mode) { 01143 case RADIO_RST: 01144 // put radio to sleep 01145 opmode(OPMODE_SLEEP); 01146 #if defined(RADIO_DBG) 01147 txStateIo = 0; 01148 rxStateIo = 0; 01149 #endif 01150 break; 01151 01152 case RADIO_TX: 01153 // transmit frame now 01154 starttx(); // buf=LMIC.frame, len=LMIC.dataLen 01155 #if defined(RADIO_DBG) 01156 txStateIo = 1; 01157 #endif 01158 break; 01159 01160 case RADIO_RX: 01161 // receive frame now (exactly at rxtime) 01162 startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms 01163 #if defined(RADIO_DBG) 01164 rxStateIo = 1; 01165 #endif 01166 break; 01167 01168 case RADIO_RXON: 01169 // start scanning for beacon now 01170 startrx(RXMODE_SCAN); // buf=LMIC.frame 01171 #if defined(RADIO_DBG) 01172 rxStateIo = 1; 01173 #endif 01174 break; 01175 } 01176 hal_enableIRQs(); 01177 } 01178 01179 #endif // USE_SMTC_RADIO_DRIVER
Generated on Thu Jul 14 2022 20:52:24 by
1.7.2
