LMiC library swtiched to default eu868

Fork of LMiC by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers radio.cpp Source File

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