LMiC adapted to work with SX1272MB2xAS LoRa shield.

Fork of LMiC by Timothy Mulrooney

Committer:
GTsapparellas
Date:
Mon Apr 02 12:04:59 2018 +0000
Revision:
8:5879e83f632a
Parent:
7:29058a7ccf23
LoRa Node consisting of FRDM-K64F along with SX1272MB2xAS LoRa shield employed through IBM's LMiC library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mluis 0:62d1edcc13d1 1 /*******************************************************************************
mluis 1:d3b7bde3995c 2 * Copyright (c) 2014-2015 IBM Corporation.
mluis 0:62d1edcc13d1 3 * All rights reserved. This program and the accompanying materials
mluis 0:62d1edcc13d1 4 * are made available under the terms of the Eclipse Public License v1.0
mluis 0:62d1edcc13d1 5 * which accompanies this distribution, and is available at
mluis 0:62d1edcc13d1 6 * http://www.eclipse.org/legal/epl-v10.html
mluis 0:62d1edcc13d1 7 *
mluis 0:62d1edcc13d1 8 * Contributors:
mluis 0:62d1edcc13d1 9 * IBM Zurich Research Lab - initial API, implementation and documentation
mluis 0:62d1edcc13d1 10 * Semtech Apps Team - Modified to support the MBED sx1276 driver
mluis 0:62d1edcc13d1 11 * library.
mluis 0:62d1edcc13d1 12 * Possibility to use original or Semtech's MBED
mluis 0:62d1edcc13d1 13 * radio driver. The selection is done by setting
mluis 0:62d1edcc13d1 14 * USE_SMTC_RADIO_DRIVER preprocessing directive
mluis 0:62d1edcc13d1 15 * in lmic.h
GTsapparellas 8:5879e83f632a 16 *
GTsapparellas 8:5879e83f632a 17 * /////////////////////////////////////////////////////////////////////////////
GTsapparellas 8:5879e83f632a 18 *
GTsapparellas 8:5879e83f632a 19 * Used by Giorgos Tsapparellas for Internet of Things (IoT) smart monitoring
GTsapparellas 8:5879e83f632a 20 * device for agriculture using LoRaWAN technology.
GTsapparellas 8:5879e83f632a 21 *
GTsapparellas 8:5879e83f632a 22 * Date of issued copy: 25 January 2018
GTsapparellas 8:5879e83f632a 23 *
GTsapparellas 8:5879e83f632a 24 * Modifications:
GTsapparellas 8:5879e83f632a 25 * - Updated to support MBED sx1272 driver library.
GTsapparellas 8:5879e83f632a 26 * - Disabled continuous reception od sx1272 LoRa shield under radio_init funtion
GTsapparellas 8:5879e83f632a 27 * as it is used only for transmitting data.
mluis 0:62d1edcc13d1 28 *******************************************************************************/
mluis 1:d3b7bde3995c 29
mluis 0:62d1edcc13d1 30 #include "lmic.h"
tmulrooney 5:464c1f2d6cbb 31 #include "debug.h"
mluis 0:62d1edcc13d1 32
mluis 0:62d1edcc13d1 33 #if USE_SMTC_RADIO_DRIVER
tmulrooney 5:464c1f2d6cbb 34 #include "sx1272-hal.h"
mluis 0:62d1edcc13d1 35
mluis 0:62d1edcc13d1 36 /*!
mluis 1:d3b7bde3995c 37 * Syncword for lora networks
mluis 0:62d1edcc13d1 38 */
mluis 1:d3b7bde3995c 39 #define LORA_MAC_SYNCWORD 0x34
mluis 0:62d1edcc13d1 40
mluis 0:62d1edcc13d1 41 /*
mluis 0:62d1edcc13d1 42 * Callback functions prototypes
mluis 0:62d1edcc13d1 43 */
mluis 0:62d1edcc13d1 44 /*!
mluis 0:62d1edcc13d1 45 * @brief Function to be executed on Radio Tx Done event
mluis 0:62d1edcc13d1 46 */
mluis 0:62d1edcc13d1 47 void OnTxDone( void );
mluis 0:62d1edcc13d1 48
mluis 0:62d1edcc13d1 49 /*!
mluis 0:62d1edcc13d1 50 * @brief Function to be executed on Radio Rx Done event
mluis 0:62d1edcc13d1 51 */
mluis 0:62d1edcc13d1 52 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
mluis 0:62d1edcc13d1 53
mluis 0:62d1edcc13d1 54 /*!
mluis 0:62d1edcc13d1 55 * @brief Function executed on Radio Tx Timeout event
mluis 0:62d1edcc13d1 56 */
mluis 0:62d1edcc13d1 57 void OnTxTimeout( void );
mluis 0:62d1edcc13d1 58
mluis 0:62d1edcc13d1 59 /*!
mluis 0:62d1edcc13d1 60 * @brief Function executed on Radio Rx Timeout event
mluis 0:62d1edcc13d1 61 */
mluis 0:62d1edcc13d1 62 void OnRxTimeout( void );
mluis 0:62d1edcc13d1 63
mluis 0:62d1edcc13d1 64 /*!
mluis 0:62d1edcc13d1 65 * @brief Function executed on Radio Rx Error event
mluis 0:62d1edcc13d1 66 */
mluis 0:62d1edcc13d1 67 void OnRxError( void );
mluis 0:62d1edcc13d1 68
mluis 0:62d1edcc13d1 69 /*!
mluis 0:62d1edcc13d1 70 * @brief Function executed on Radio Fhss Change Channel event
mluis 0:62d1edcc13d1 71 */
mluis 0:62d1edcc13d1 72 void OnFhssChangeChannel( uint8_t channelIndex );
mluis 0:62d1edcc13d1 73
mluis 0:62d1edcc13d1 74 /*!
mluis 0:62d1edcc13d1 75 * @brief Function executed on CAD Done event
mluis 0:62d1edcc13d1 76 */
mluis 0:62d1edcc13d1 77 void OnCadDone( void );
mluis 0:62d1edcc13d1 78
mluis 3:519c71d29a06 79 /*!
mluis 3:519c71d29a06 80 * Radio events function pointer
mluis 3:519c71d29a06 81 */
mluis 3:519c71d29a06 82 static RadioEvents_t RadioEvents;
mluis 3:519c71d29a06 83
mluis 0:62d1edcc13d1 84 /*
mluis 0:62d1edcc13d1 85 * Radio object declraration
mluis 0:62d1edcc13d1 86 */
tmulrooney 5:464c1f2d6cbb 87 //SX1272MB1xAS Radio( NULL );
GTsapparellas 8:5879e83f632a 88 SX1272MB2xAS *Radio;
mluis 0:62d1edcc13d1 89
mluis 0:62d1edcc13d1 90 static const u2_t LORA_RXDONE_FIXUP[] = {
mluis 0:62d1edcc13d1 91 [FSK] = us2osticks(0), // ( 0 ticks)
mluis 0:62d1edcc13d1 92 [SF7] = us2osticks(0), // ( 0 ticks)
mluis 0:62d1edcc13d1 93 [SF8] = us2osticks(1648), // ( 54 ticks)
mluis 0:62d1edcc13d1 94 [SF9] = us2osticks(3265), // ( 107 ticks)
mluis 0:62d1edcc13d1 95 [SF10] = us2osticks(7049), // ( 231 ticks)
mluis 0:62d1edcc13d1 96 [SF11] = us2osticks(13641), // ( 447 ticks)
mluis 0:62d1edcc13d1 97 [SF12] = us2osticks(31189), // (1022 ticks)
mluis 0:62d1edcc13d1 98 };
mluis 0:62d1edcc13d1 99
mluis 0:62d1edcc13d1 100 void OnTxDone( void )
mluis 0:62d1edcc13d1 101 {
GTsapparellas 8:5879e83f632a 102 //debug("OnTxDone enter\r\n");
mluis 0:62d1edcc13d1 103 ostime_t now = os_getTime( );
mluis 0:62d1edcc13d1 104 // save exact tx time
mluis 1:d3b7bde3995c 105 LMIC.txend = now - us2osticks( RADIO_WAKEUP_TIME ); // TXDONE FIXUP
mluis 0:62d1edcc13d1 106
mluis 0:62d1edcc13d1 107 // go from stanby to sleep
tmulrooney 5:464c1f2d6cbb 108 Radio->Sleep( );
mluis 0:62d1edcc13d1 109 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 110 os_setCallback( &LMIC.osjob, LMIC.osjob.func );
mluis 0:62d1edcc13d1 111 }
mluis 0:62d1edcc13d1 112
mluis 0:62d1edcc13d1 113 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
mluis 0:62d1edcc13d1 114 {
GTsapparellas 8:5879e83f632a 115 //debug("OnRxDone enter\r\n");
mluis 0:62d1edcc13d1 116 ostime_t now = os_getTime( );
mluis 0:62d1edcc13d1 117 // save exact rx time
mluis 1:d3b7bde3995c 118 if( getBw( LMIC.rps ) == BW125 )
mluis 1:d3b7bde3995c 119 {
mluis 1:d3b7bde3995c 120 now -= LORA_RXDONE_FIXUP[getSf( LMIC.rps )];
mluis 1:d3b7bde3995c 121 }
mluis 1:d3b7bde3995c 122 LMIC.rxtime = now;
mluis 0:62d1edcc13d1 123 // read the PDU and inform the MAC that we received something
mluis 0:62d1edcc13d1 124 LMIC.dataLen = size;
mluis 0:62d1edcc13d1 125 // now read the FIFO
mluis 0:62d1edcc13d1 126 memcpy( LMIC.frame, payload, size );
mluis 0:62d1edcc13d1 127 // read rx quality parameters
mluis 1:d3b7bde3995c 128 LMIC.snr = snr; // SNR [dB] * 4
mluis 1:d3b7bde3995c 129 LMIC.rssi = rssi; // RSSI [dBm] (-196...+63)
mluis 0:62d1edcc13d1 130
mluis 0:62d1edcc13d1 131 // go from stanby to sleep
tmulrooney 5:464c1f2d6cbb 132 Radio->Sleep( );
mluis 0:62d1edcc13d1 133 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 134 os_setCallback( &LMIC.osjob, LMIC.osjob.func );
mluis 0:62d1edcc13d1 135 }
mluis 0:62d1edcc13d1 136
mluis 0:62d1edcc13d1 137 void OnTxTimeout( void )
mluis 0:62d1edcc13d1 138 {
GTsapparellas 8:5879e83f632a 139 //debug("OnTxTimeout enter\r\n");
tmulrooney 5:464c1f2d6cbb 140 ostime_t now = os_getTime( );
mluis 0:62d1edcc13d1 141
mluis 0:62d1edcc13d1 142 // indicate error
mluis 1:d3b7bde3995c 143 LMIC.dataLen = 0;
mluis 1:d3b7bde3995c 144
mluis 0:62d1edcc13d1 145 // go from stanby to sleep
tmulrooney 5:464c1f2d6cbb 146 Radio->Sleep( );
mluis 0:62d1edcc13d1 147 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 148 os_setCallback( &LMIC.osjob, LMIC.osjob.func );
mluis 0:62d1edcc13d1 149 }
mluis 0:62d1edcc13d1 150
mluis 0:62d1edcc13d1 151 void OnRxTimeout( void )
mluis 0:62d1edcc13d1 152 {
GTsapparellas 8:5879e83f632a 153 //debug("OnRxTimeout enter\r\n");
tmulrooney 5:464c1f2d6cbb 154 ostime_t now = os_getTime( );
mluis 0:62d1edcc13d1 155 // indicate timeout
mluis 0:62d1edcc13d1 156 LMIC.dataLen = 0;
mluis 0:62d1edcc13d1 157
mluis 0:62d1edcc13d1 158 // go from stanby to sleep
tmulrooney 5:464c1f2d6cbb 159 Radio->Sleep( );
mluis 0:62d1edcc13d1 160 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 161 os_setCallback( &LMIC.osjob, LMIC.osjob.func );
mluis 0:62d1edcc13d1 162 }
mluis 0:62d1edcc13d1 163
mluis 0:62d1edcc13d1 164 void OnRxError( void )
mluis 0:62d1edcc13d1 165 {
GTsapparellas 8:5879e83f632a 166 //debug("OnRxError enter\r\n");
mluis 0:62d1edcc13d1 167 ostime_t now = os_getTime( );
mluis 0:62d1edcc13d1 168
mluis 0:62d1edcc13d1 169 // indicate error
mluis 0:62d1edcc13d1 170 LMIC.dataLen = 0;
mluis 0:62d1edcc13d1 171
mluis 0:62d1edcc13d1 172 // go from stanby to sleep
tmulrooney 5:464c1f2d6cbb 173 Radio->Sleep( );
mluis 0:62d1edcc13d1 174 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 175 os_setCallback( &LMIC.osjob, LMIC.osjob.func );
mluis 0:62d1edcc13d1 176 }
mluis 0:62d1edcc13d1 177
mluis 0:62d1edcc13d1 178 /*!
mluis 0:62d1edcc13d1 179 * LMIC API implementation
mluis 0:62d1edcc13d1 180 */
mluis 0:62d1edcc13d1 181 // RADIO STATE
mluis 0:62d1edcc13d1 182 // (initialized by radio_init( ), used by radio_rand1( ))
mluis 0:62d1edcc13d1 183 static u1_t randbuf[16];
mluis 0:62d1edcc13d1 184
mluis 0:62d1edcc13d1 185 // get random seed from wideband noise rssi
mluis 0:62d1edcc13d1 186 void radio_init( void )
mluis 0:62d1edcc13d1 187 {
GTsapparellas 8:5879e83f632a 188 //debug_str("radio_init1 enter\r\n");
GTsapparellas 8:5879e83f632a 189 Radio = new SX1272MB2xAS(NULL);
tmulrooney 6:eed5fd627a2b 190 hal_disableIRQs( );
mluis 3:519c71d29a06 191
mluis 3:519c71d29a06 192 // Initialize Radio driver
mluis 3:519c71d29a06 193 RadioEvents.TxDone = OnTxDone;
mluis 3:519c71d29a06 194 RadioEvents.RxDone = OnRxDone;
mluis 3:519c71d29a06 195 RadioEvents.RxError = OnRxError;
mluis 3:519c71d29a06 196 RadioEvents.TxTimeout = OnTxTimeout;
mluis 3:519c71d29a06 197 RadioEvents.RxTimeout = OnRxTimeout;
tmulrooney 5:464c1f2d6cbb 198 Radio->Init( &RadioEvents );
mluis 0:62d1edcc13d1 199
mluis 0:62d1edcc13d1 200 // seed 15-byte randomness via noise rssi
mluis 0:62d1edcc13d1 201 // Set LoRa modem ON
tmulrooney 5:464c1f2d6cbb 202 Radio->SetModem( MODEM_LORA );
mluis 0:62d1edcc13d1 203 // Disable LoRa modem interrupts
tmulrooney 5:464c1f2d6cbb 204 Radio->Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT |
mluis 0:62d1edcc13d1 205 RFLR_IRQFLAGS_RXDONE |
mluis 0:62d1edcc13d1 206 RFLR_IRQFLAGS_PAYLOADCRCERROR |
mluis 0:62d1edcc13d1 207 RFLR_IRQFLAGS_VALIDHEADER |
mluis 0:62d1edcc13d1 208 RFLR_IRQFLAGS_TXDONE |
mluis 0:62d1edcc13d1 209 RFLR_IRQFLAGS_CADDONE |
mluis 0:62d1edcc13d1 210 RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
mluis 0:62d1edcc13d1 211 RFLR_IRQFLAGS_CADDETECTED );
mluis 0:62d1edcc13d1 212
mluis 0:62d1edcc13d1 213 // Set radio in continuous reception
GTsapparellas 8:5879e83f632a 214 /*Radio->Rx( 0 );
mluis 0:62d1edcc13d1 215
mluis 0:62d1edcc13d1 216 for( int i = 1; i < 16; i++ )
mluis 0:62d1edcc13d1 217 {
mluis 0:62d1edcc13d1 218 for( int j = 0; j < 8; j++ )
mluis 0:62d1edcc13d1 219 {
mluis 0:62d1edcc13d1 220 u1_t b; // wait for two non-identical subsequent least-significant bits
tmulrooney 5:464c1f2d6cbb 221 while( ( b = Radio->Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) == ( Radio->Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) );
mluis 0:62d1edcc13d1 222 randbuf[i] = ( randbuf[i] << 1 ) | b;
mluis 0:62d1edcc13d1 223 }
GTsapparellas 8:5879e83f632a 224 }*/
mluis 0:62d1edcc13d1 225 randbuf[0] = 16; // set initial index
GTsapparellas 8:5879e83f632a 226
mluis 0:62d1edcc13d1 227 // Change LoRa modem SyncWord
tmulrooney 5:464c1f2d6cbb 228 Radio->Write( REG_LR_SYNCWORD, LORA_MAC_SYNCWORD );
mluis 0:62d1edcc13d1 229
tmulrooney 5:464c1f2d6cbb 230 Radio->Sleep( );
mluis 0:62d1edcc13d1 231
mluis 0:62d1edcc13d1 232 hal_enableIRQs( );
GTsapparellas 8:5879e83f632a 233 //debug_str("radio_init exit\r\n");
mluis 0:62d1edcc13d1 234 }
mluis 0:62d1edcc13d1 235
mluis 0:62d1edcc13d1 236 // return next random byte derived from seed buffer
mluis 0:62d1edcc13d1 237 // (buf[0] holds index of next byte to be returned)
mluis 0:62d1edcc13d1 238 u1_t radio_rand1( void )
mluis 0:62d1edcc13d1 239 {
GTsapparellas 8:5879e83f632a 240 //debug("radio_rand1 enter\r\n");
mluis 0:62d1edcc13d1 241 u1_t i = randbuf[0];
mluis 0:62d1edcc13d1 242 ASSERT( i != 0 );
mluis 0:62d1edcc13d1 243 if( i == 16 )
mluis 0:62d1edcc13d1 244 {
mluis 0:62d1edcc13d1 245 os_aes( AES_ENC, randbuf, 16 ); // encrypt seed with any key
mluis 0:62d1edcc13d1 246 i = 0;
mluis 0:62d1edcc13d1 247 }
mluis 0:62d1edcc13d1 248 u1_t v = randbuf[i++];
mluis 0:62d1edcc13d1 249 randbuf[0] = i;
mluis 0:62d1edcc13d1 250 return v;
mluis 0:62d1edcc13d1 251 }
mluis 0:62d1edcc13d1 252
mluis 0:62d1edcc13d1 253 void os_radio( u1_t mode )
mluis 0:62d1edcc13d1 254 {
GTsapparellas 8:5879e83f632a 255 //debug_val("os_radio enter ",mode);
mluis 0:62d1edcc13d1 256 hal_disableIRQs( );
mluis 0:62d1edcc13d1 257 switch( mode )
mluis 0:62d1edcc13d1 258 {
mluis 0:62d1edcc13d1 259 case RADIO_RST:
mluis 0:62d1edcc13d1 260 // put radio to sleep
tmulrooney 5:464c1f2d6cbb 261 Radio->Sleep( );
mluis 0:62d1edcc13d1 262 break;
mluis 0:62d1edcc13d1 263
mluis 0:62d1edcc13d1 264 case RADIO_TX:
mluis 0:62d1edcc13d1 265 // transmit frame now
mluis 0:62d1edcc13d1 266 //ASSERT( Radio.GetState( ) == IDLE );
mluis 0:62d1edcc13d1 267
tmulrooney 5:464c1f2d6cbb 268 Radio->SetChannel( LMIC.freq );
mluis 0:62d1edcc13d1 269 if( getSf( LMIC.rps ) == FSK )
mluis 0:62d1edcc13d1 270 { // FSK modem
tmulrooney 5:464c1f2d6cbb 271 Radio->SetTxConfig( MODEM_FSK, LMIC.txpow, 25e3, 0, 50e3, 0, 5, false, true, 0, 0, false, 3e6 );
mluis 0:62d1edcc13d1 272 }
mluis 0:62d1edcc13d1 273 else
mluis 0:62d1edcc13d1 274 { // LoRa modem
mluis 0:62d1edcc13d1 275
tmulrooney 5:464c1f2d6cbb 276 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 );
mluis 0:62d1edcc13d1 277 }
mluis 0:62d1edcc13d1 278
mluis 0:62d1edcc13d1 279 //starttx( ); // buf=LMIC.frame, len=LMIC.dataLen
tmulrooney 5:464c1f2d6cbb 280 Radio->Send( LMIC.frame, LMIC.dataLen );
mluis 0:62d1edcc13d1 281 break;
mluis 0:62d1edcc13d1 282
mluis 0:62d1edcc13d1 283 case RADIO_RX:
mluis 0:62d1edcc13d1 284 // receive frame now (exactly at rxtime)
mluis 0:62d1edcc13d1 285 //ASSERT( Radio.GetState( ) == IDLE );
mluis 0:62d1edcc13d1 286
tmulrooney 5:464c1f2d6cbb 287 Radio->SetChannel( LMIC.freq );
mluis 0:62d1edcc13d1 288 if( getSf( LMIC.rps ) == FSK )
mluis 0:62d1edcc13d1 289 { // FSK modem
mluis 0:62d1edcc13d1 290 //Radio.SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, false );
tmulrooney 5:464c1f2d6cbb 291 Radio->SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, true );
mluis 0:62d1edcc13d1 292 }
mluis 0:62d1edcc13d1 293 else
mluis 0:62d1edcc13d1 294 { // LoRa modem
mluis 1:d3b7bde3995c 295 if( ( getSf( LMIC.rps ) <= SF9 ) && ( LMIC.rxsyms < 8 ) )
mluis 1:d3b7bde3995c 296 {
tmulrooney 5:464c1f2d6cbb 297 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 );
mluis 1:d3b7bde3995c 298 }
mluis 1:d3b7bde3995c 299 else
mluis 1:d3b7bde3995c 300 {
tmulrooney 5:464c1f2d6cbb 301 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 );
mluis 1:d3b7bde3995c 302 }
mluis 0:62d1edcc13d1 303 }
mluis 0:62d1edcc13d1 304
mluis 0:62d1edcc13d1 305 // now instruct the radio to receive
mluis 0:62d1edcc13d1 306 hal_waitUntil( LMIC.rxtime ); // busy wait until exact rx time
mluis 0:62d1edcc13d1 307
mluis 0:62d1edcc13d1 308 //startrx( RXMODE_SINGLE ); // buf = LMIC.frame, time = LMIC.rxtime, timeout=LMIC.rxsyms
mluis 0:62d1edcc13d1 309 if( getSf( LMIC.rps ) == FSK )
mluis 0:62d1edcc13d1 310 { // FSK modem
tmulrooney 5:464c1f2d6cbb 311 Radio->Rx( 50e3 ); // Max Rx window 50 ms
mluis 0:62d1edcc13d1 312 }
mluis 0:62d1edcc13d1 313 else
mluis 0:62d1edcc13d1 314 { // LoRa modem
tmulrooney 5:464c1f2d6cbb 315 Radio->Rx( 3e6 ); // Max Rx window 3 seconds
mluis 0:62d1edcc13d1 316 }
mluis 0:62d1edcc13d1 317 break;
mluis 0:62d1edcc13d1 318
mluis 0:62d1edcc13d1 319 case RADIO_RXON:
mluis 0:62d1edcc13d1 320 // start scanning for beacon now
mluis 0:62d1edcc13d1 321
mluis 0:62d1edcc13d1 322 //ASSERT( Radio.GetState( ) == IDLE );
mluis 0:62d1edcc13d1 323
tmulrooney 5:464c1f2d6cbb 324 Radio->SetChannel( LMIC.freq );
mluis 0:62d1edcc13d1 325 if( getSf( LMIC.rps ) == FSK )
mluis 0:62d1edcc13d1 326 { // FSK modem
tmulrooney 5:464c1f2d6cbb 327 Radio->SetRxConfig( MODEM_FSK, 50e3, 50e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, true );
mluis 0:62d1edcc13d1 328 }
mluis 0:62d1edcc13d1 329 else
mluis 0:62d1edcc13d1 330 { // LoRa modem
tmulrooney 5:464c1f2d6cbb 331 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 );
mluis 0:62d1edcc13d1 332 }
mluis 0:62d1edcc13d1 333
mluis 1:d3b7bde3995c 334 //startrx( RXMODE_SCAN ); // buf = LMIC.frame
tmulrooney 5:464c1f2d6cbb 335 Radio->Rx( 0 );
mluis 0:62d1edcc13d1 336 break;
mluis 0:62d1edcc13d1 337 }
mluis 0:62d1edcc13d1 338 hal_enableIRQs( );
mluis 0:62d1edcc13d1 339 }
mluis 0:62d1edcc13d1 340
mluis 0:62d1edcc13d1 341 #else
mluis 0:62d1edcc13d1 342
mluis 0:62d1edcc13d1 343 // ----------------------------------------
mluis 0:62d1edcc13d1 344 // Registers Mapping
mluis 0:62d1edcc13d1 345 #define RegFifo 0x00 // common
mluis 0:62d1edcc13d1 346 #define RegOpMode 0x01 // common
mluis 0:62d1edcc13d1 347 #define FSKRegBitrateMsb 0x02
mluis 0:62d1edcc13d1 348 #define FSKRegBitrateLsb 0x03
mluis 0:62d1edcc13d1 349 #define FSKRegFdevMsb 0x04
mluis 0:62d1edcc13d1 350 #define FSKRegFdevLsb 0x05
mluis 0:62d1edcc13d1 351 #define RegFrfMsb 0x06 // common
mluis 0:62d1edcc13d1 352 #define RegFrfMid 0x07 // common
mluis 0:62d1edcc13d1 353 #define RegFrfLsb 0x08 // common
mluis 0:62d1edcc13d1 354 #define RegPaConfig 0x09 // common
mluis 0:62d1edcc13d1 355 #define RegPaRamp 0x0A // common
mluis 0:62d1edcc13d1 356 #define RegOcp 0x0B // common
mluis 0:62d1edcc13d1 357 #define RegLna 0x0C // common
mluis 0:62d1edcc13d1 358 #define FSKRegRxConfig 0x0D
mluis 0:62d1edcc13d1 359 #define LORARegFifoAddrPtr 0x0D
mluis 0:62d1edcc13d1 360 #define FSKRegRssiConfig 0x0E
mluis 0:62d1edcc13d1 361 #define LORARegFifoTxBaseAddr 0x0E
mluis 0:62d1edcc13d1 362 #define FSKRegRssiCollision 0x0F
mluis 0:62d1edcc13d1 363 #define LORARegFifoRxBaseAddr 0x0F
mluis 0:62d1edcc13d1 364 #define FSKRegRssiThresh 0x10
mluis 0:62d1edcc13d1 365 #define LORARegFifoRxCurrentAddr 0x10
mluis 0:62d1edcc13d1 366 #define FSKRegRssiValue 0x11
mluis 0:62d1edcc13d1 367 #define LORARegIrqFlagsMask 0x11
mluis 0:62d1edcc13d1 368 #define FSKRegRxBw 0x12
mluis 0:62d1edcc13d1 369 #define LORARegIrqFlags 0x12
mluis 0:62d1edcc13d1 370 #define FSKRegAfcBw 0x13
mluis 0:62d1edcc13d1 371 #define LORARegRxNbBytes 0x13
mluis 0:62d1edcc13d1 372 #define FSKRegOokPeak 0x14
mluis 0:62d1edcc13d1 373 #define LORARegRxHeaderCntValueMsb 0x14
mluis 0:62d1edcc13d1 374 #define FSKRegOokFix 0x15
mluis 0:62d1edcc13d1 375 #define LORARegRxHeaderCntValueLsb 0x15
mluis 0:62d1edcc13d1 376 #define FSKRegOokAvg 0x16
mluis 0:62d1edcc13d1 377 #define LORARegRxPacketCntValueMsb 0x16
mluis 0:62d1edcc13d1 378 #define LORARegRxpacketCntValueLsb 0x17
mluis 0:62d1edcc13d1 379 #define LORARegModemStat 0x18
mluis 0:62d1edcc13d1 380 #define LORARegPktSnrValue 0x19
mluis 0:62d1edcc13d1 381 #define FSKRegAfcFei 0x1A
mluis 0:62d1edcc13d1 382 #define LORARegPktRssiValue 0x1A
mluis 0:62d1edcc13d1 383 #define FSKRegAfcMsb 0x1B
mluis 0:62d1edcc13d1 384 #define LORARegRssiValue 0x1B
mluis 0:62d1edcc13d1 385 #define FSKRegAfcLsb 0x1C
mluis 0:62d1edcc13d1 386 #define LORARegHopChannel 0x1C
mluis 0:62d1edcc13d1 387 #define FSKRegFeiMsb 0x1D
mluis 0:62d1edcc13d1 388 #define LORARegModemConfig1 0x1D
mluis 0:62d1edcc13d1 389 #define FSKRegFeiLsb 0x1E
mluis 0:62d1edcc13d1 390 #define LORARegModemConfig2 0x1E
mluis 0:62d1edcc13d1 391 #define FSKRegPreambleDetect 0x1F
mluis 0:62d1edcc13d1 392 #define LORARegSymbTimeoutLsb 0x1F
mluis 0:62d1edcc13d1 393 #define FSKRegRxTimeout1 0x20
mluis 0:62d1edcc13d1 394 #define LORARegPreambleMsb 0x20
mluis 0:62d1edcc13d1 395 #define FSKRegRxTimeout2 0x21
mluis 0:62d1edcc13d1 396 #define LORARegPreambleLsb 0x21
mluis 0:62d1edcc13d1 397 #define FSKRegRxTimeout3 0x22
mluis 0:62d1edcc13d1 398 #define LORARegPayloadLength 0x22
mluis 0:62d1edcc13d1 399 #define FSKRegRxDelay 0x23
mluis 0:62d1edcc13d1 400 #define LORARegPayloadMaxLength 0x23
mluis 0:62d1edcc13d1 401 #define FSKRegOsc 0x24
mluis 0:62d1edcc13d1 402 #define LORARegHopPeriod 0x24
mluis 0:62d1edcc13d1 403 #define FSKRegPreambleMsb 0x25
mluis 0:62d1edcc13d1 404 #define LORARegFifoRxByteAddr 0x25
mluis 0:62d1edcc13d1 405 #define LORARegModemConfig3 0x26
mluis 0:62d1edcc13d1 406 #define FSKRegPreambleLsb 0x26
mluis 0:62d1edcc13d1 407 #define FSKRegSyncConfig 0x27
mluis 0:62d1edcc13d1 408 #define LORARegFeiMsb 0x28
mluis 0:62d1edcc13d1 409 #define FSKRegSyncValue1 0x28
mluis 0:62d1edcc13d1 410 #define LORAFeiMib 0x29
mluis 0:62d1edcc13d1 411 #define FSKRegSyncValue2 0x29
mluis 0:62d1edcc13d1 412 #define LORARegFeiLsb 0x2A
mluis 0:62d1edcc13d1 413 #define FSKRegSyncValue3 0x2A
mluis 0:62d1edcc13d1 414 #define FSKRegSyncValue4 0x2B
mluis 0:62d1edcc13d1 415 #define LORARegRssiWideband 0x2C
mluis 0:62d1edcc13d1 416 #define FSKRegSyncValue5 0x2C
mluis 0:62d1edcc13d1 417 #define FSKRegSyncValue6 0x2D
mluis 0:62d1edcc13d1 418 #define FSKRegSyncValue7 0x2E
mluis 0:62d1edcc13d1 419 #define FSKRegSyncValue8 0x2F
mluis 0:62d1edcc13d1 420 #define FSKRegPacketConfig1 0x30
mluis 0:62d1edcc13d1 421 #define FSKRegPacketConfig2 0x31
mluis 0:62d1edcc13d1 422 #define LORARegDetectOptimize 0x31
mluis 0:62d1edcc13d1 423 #define FSKRegPayloadLength 0x32
mluis 0:62d1edcc13d1 424 #define FSKRegNodeAdrs 0x33
mluis 0:62d1edcc13d1 425 #define LORARegInvertIQ 0x33
mluis 0:62d1edcc13d1 426 #define FSKRegBroadcastAdrs 0x34
mluis 0:62d1edcc13d1 427 #define FSKRegFifoThresh 0x35
mluis 0:62d1edcc13d1 428 #define FSKRegSeqConfig1 0x36
mluis 0:62d1edcc13d1 429 #define FSKRegSeqConfig2 0x37
mluis 0:62d1edcc13d1 430 #define LORARegDetectionThreshold 0x37
mluis 0:62d1edcc13d1 431 #define FSKRegTimerResol 0x38
mluis 0:62d1edcc13d1 432 #define FSKRegTimer1Coef 0x39
mluis 0:62d1edcc13d1 433 #define LORARegSyncWord 0x39
mluis 0:62d1edcc13d1 434 #define FSKRegTimer2Coef 0x3A
mluis 0:62d1edcc13d1 435 #define FSKRegImageCal 0x3B
mluis 0:62d1edcc13d1 436 #define FSKRegTemp 0x3C
mluis 0:62d1edcc13d1 437 #define FSKRegLowBat 0x3D
mluis 0:62d1edcc13d1 438 #define FSKRegIrqFlags1 0x3E
mluis 0:62d1edcc13d1 439 #define FSKRegIrqFlags2 0x3F
mluis 0:62d1edcc13d1 440 #define RegDioMapping1 0x40 // common
mluis 0:62d1edcc13d1 441 #define RegDioMapping2 0x41 // common
mluis 0:62d1edcc13d1 442 #define RegVersion 0x42 // common
mluis 0:62d1edcc13d1 443 // #define RegAgcRef 0x43 // common
mluis 0:62d1edcc13d1 444 // #define RegAgcThresh1 0x44 // common
mluis 0:62d1edcc13d1 445 // #define RegAgcThresh2 0x45 // common
mluis 0:62d1edcc13d1 446 // #define RegAgcThresh3 0x46 // common
mluis 0:62d1edcc13d1 447 // #define RegPllHop 0x4B // common
mluis 0:62d1edcc13d1 448 // #define RegTcxo 0x58 // common
mluis 0:62d1edcc13d1 449 #define RegPaDac 0x5A // common
mluis 0:62d1edcc13d1 450 // #define RegPll 0x5C // common
mluis 0:62d1edcc13d1 451 // #define RegPllLowPn 0x5E // common
mluis 0:62d1edcc13d1 452 // #define RegFormerTemp 0x6C // common
mluis 0:62d1edcc13d1 453 // #define RegBitRateFrac 0x70 // common
mluis 0:62d1edcc13d1 454
mluis 0:62d1edcc13d1 455 // ----------------------------------------
mluis 0:62d1edcc13d1 456 // spread factors and mode for RegModemConfig2
mluis 0:62d1edcc13d1 457 #define SX1272_MC2_FSK 0x00
mluis 0:62d1edcc13d1 458 #define SX1272_MC2_SF7 0x70
mluis 0:62d1edcc13d1 459 #define SX1272_MC2_SF8 0x80
mluis 0:62d1edcc13d1 460 #define SX1272_MC2_SF9 0x90
mluis 0:62d1edcc13d1 461 #define SX1272_MC2_SF10 0xA0
mluis 0:62d1edcc13d1 462 #define SX1272_MC2_SF11 0xB0
mluis 0:62d1edcc13d1 463 #define SX1272_MC2_SF12 0xC0
mluis 0:62d1edcc13d1 464 // bandwidth for RegModemConfig1
mluis 0:62d1edcc13d1 465 #define SX1272_MC1_BW_125 0x00
mluis 0:62d1edcc13d1 466 #define SX1272_MC1_BW_250 0x40
mluis 0:62d1edcc13d1 467 #define SX1272_MC1_BW_500 0x80
mluis 0:62d1edcc13d1 468 // coding rate for RegModemConfig1
mluis 0:62d1edcc13d1 469 #define SX1272_MC1_CR_4_5 0x08
mluis 0:62d1edcc13d1 470 #define SX1272_MC1_CR_4_6 0x10
mluis 0:62d1edcc13d1 471 #define SX1272_MC1_CR_4_7 0x18
mluis 0:62d1edcc13d1 472 #define SX1272_MC1_CR_4_8 0x20
mluis 0:62d1edcc13d1 473 #define SX1272_MC1_IMPLICIT_HEADER_MODE_ON 0x04 // required for receive
mluis 0:62d1edcc13d1 474 #define SX1272_MC1_RX_PAYLOAD_CRCON 0x02
mluis 0:62d1edcc13d1 475 #define SX1272_MC1_LOW_DATA_RATE_OPTIMIZE 0x01 // mandated for SF11 and SF12
mluis 0:62d1edcc13d1 476 // transmit power configuration for RegPaConfig
mluis 0:62d1edcc13d1 477 #define SX1272_PAC_PA_SELECT_PA_BOOST 0x80
mluis 0:62d1edcc13d1 478 #define SX1272_PAC_PA_SELECT_RFIO_PIN 0x00
mluis 0:62d1edcc13d1 479
mluis 0:62d1edcc13d1 480
mluis 0:62d1edcc13d1 481 // sx1276 RegModemConfig1
mluis 0:62d1edcc13d1 482 #define SX1276_MC1_BW_125 0x70
mluis 0:62d1edcc13d1 483 #define SX1276_MC1_BW_250 0x80
mluis 0:62d1edcc13d1 484 #define SX1276_MC1_BW_500 0x90
mluis 0:62d1edcc13d1 485 #define SX1276_MC1_CR_4_5 0x02
mluis 0:62d1edcc13d1 486 #define SX1276_MC1_CR_4_6 0x04
mluis 0:62d1edcc13d1 487 #define SX1276_MC1_CR_4_7 0x06
mluis 0:62d1edcc13d1 488 #define SX1276_MC1_CR_4_8 0x08
mluis 0:62d1edcc13d1 489
mluis 0:62d1edcc13d1 490 #define SX1276_MC1_IMPLICIT_HEADER_MODE_ON 0x01
mluis 0:62d1edcc13d1 491
mluis 0:62d1edcc13d1 492 // sx1276 RegModemConfig2
mluis 0:62d1edcc13d1 493 #define SX1276_MC2_RX_PAYLOAD_CRCON 0x04
mluis 0:62d1edcc13d1 494
mluis 0:62d1edcc13d1 495 // sx1276 RegModemConfig3
mluis 0:62d1edcc13d1 496 #define SX1276_MC3_LOW_DATA_RATE_OPTIMIZE 0x08
mluis 0:62d1edcc13d1 497 #define SX1276_MC3_AGCAUTO 0x04
mluis 0:62d1edcc13d1 498
mluis 0:62d1edcc13d1 499 // preamble for lora networks (nibbles swapped)
mluis 1:d3b7bde3995c 500 #define LORA_MAC_PREAMBLE 0x34
mluis 0:62d1edcc13d1 501
mluis 0:62d1edcc13d1 502 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1 0x0A
mluis 0:62d1edcc13d1 503 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 504 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x70
mluis 0:62d1edcc13d1 505 #elif CFG_sx1272_radio
mluis 0:62d1edcc13d1 506 #define RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2 0x74
mluis 0:62d1edcc13d1 507 #endif
mluis 0:62d1edcc13d1 508
mluis 0:62d1edcc13d1 509
mluis 0:62d1edcc13d1 510
mluis 0:62d1edcc13d1 511 // ----------------------------------------
mluis 0:62d1edcc13d1 512 // Constants for radio registers
mluis 0:62d1edcc13d1 513 #define OPMODE_LORA 0x80
mluis 0:62d1edcc13d1 514 #define OPMODE_MASK 0x07
mluis 0:62d1edcc13d1 515 #define OPMODE_SLEEP 0x00
mluis 0:62d1edcc13d1 516 #define OPMODE_STANDBY 0x01
mluis 0:62d1edcc13d1 517 #define OPMODE_FSTX 0x02
mluis 0:62d1edcc13d1 518 #define OPMODE_TX 0x03
mluis 0:62d1edcc13d1 519 #define OPMODE_FSRX 0x04
mluis 0:62d1edcc13d1 520 #define OPMODE_RX 0x05
mluis 0:62d1edcc13d1 521 #define OPMODE_RX_SINGLE 0x06
mluis 0:62d1edcc13d1 522 #define OPMODE_CAD 0x07
mluis 0:62d1edcc13d1 523
mluis 0:62d1edcc13d1 524 // ----------------------------------------
mluis 0:62d1edcc13d1 525 // Bits masking the corresponding IRQs from the radio
mluis 0:62d1edcc13d1 526 #define IRQ_LORA_RXTOUT_MASK 0x80
mluis 0:62d1edcc13d1 527 #define IRQ_LORA_RXDONE_MASK 0x40
mluis 0:62d1edcc13d1 528 #define IRQ_LORA_CRCERR_MASK 0x20
mluis 0:62d1edcc13d1 529 #define IRQ_LORA_HEADER_MASK 0x10
mluis 0:62d1edcc13d1 530 #define IRQ_LORA_TXDONE_MASK 0x08
mluis 0:62d1edcc13d1 531 #define IRQ_LORA_CDDONE_MASK 0x04
mluis 0:62d1edcc13d1 532 #define IRQ_LORA_FHSSCH_MASK 0x02
mluis 0:62d1edcc13d1 533 #define IRQ_LORA_CDDETD_MASK 0x01
mluis 0:62d1edcc13d1 534
mluis 0:62d1edcc13d1 535 #define IRQ_FSK1_MODEREADY_MASK 0x80
mluis 0:62d1edcc13d1 536 #define IRQ_FSK1_RXREADY_MASK 0x40
mluis 0:62d1edcc13d1 537 #define IRQ_FSK1_TXREADY_MASK 0x20
mluis 0:62d1edcc13d1 538 #define IRQ_FSK1_PLLLOCK_MASK 0x10
mluis 0:62d1edcc13d1 539 #define IRQ_FSK1_RSSI_MASK 0x08
mluis 0:62d1edcc13d1 540 #define IRQ_FSK1_TIMEOUT_MASK 0x04
mluis 0:62d1edcc13d1 541 #define IRQ_FSK1_PREAMBLEDETECT_MASK 0x02
mluis 0:62d1edcc13d1 542 #define IRQ_FSK1_SYNCADDRESSMATCH_MASK 0x01
mluis 0:62d1edcc13d1 543 #define IRQ_FSK2_FIFOFULL_MASK 0x80
mluis 0:62d1edcc13d1 544 #define IRQ_FSK2_FIFOEMPTY_MASK 0x40
mluis 0:62d1edcc13d1 545 #define IRQ_FSK2_FIFOLEVEL_MASK 0x20
mluis 0:62d1edcc13d1 546 #define IRQ_FSK2_FIFOOVERRUN_MASK 0x10
mluis 0:62d1edcc13d1 547 #define IRQ_FSK2_PACKETSENT_MASK 0x08
mluis 0:62d1edcc13d1 548 #define IRQ_FSK2_PAYLOADREADY_MASK 0x04
mluis 0:62d1edcc13d1 549 #define IRQ_FSK2_CRCOK_MASK 0x02
mluis 0:62d1edcc13d1 550 #define IRQ_FSK2_LOWBAT_MASK 0x01
mluis 0:62d1edcc13d1 551
mluis 0:62d1edcc13d1 552 // ----------------------------------------
mluis 0:62d1edcc13d1 553 // DIO function mappings D0D1D2D3
mluis 0:62d1edcc13d1 554 #define MAP_DIO0_LORA_RXDONE 0x00 // 00------
mluis 0:62d1edcc13d1 555 #define MAP_DIO0_LORA_TXDONE 0x40 // 01------
mluis 0:62d1edcc13d1 556 #define MAP_DIO1_LORA_RXTOUT 0x00 // --00----
mluis 0:62d1edcc13d1 557 #define MAP_DIO1_LORA_NOP 0x30 // --11----
mluis 0:62d1edcc13d1 558 #define MAP_DIO2_LORA_NOP 0xC0 // ----11--
mluis 0:62d1edcc13d1 559
mluis 0:62d1edcc13d1 560 #define MAP_DIO0_FSK_READY 0x00 // 00------ (packet sent / payload ready)
mluis 0:62d1edcc13d1 561 #define MAP_DIO1_FSK_NOP 0x30 // --11----
mluis 0:62d1edcc13d1 562 #define MAP_DIO2_FSK_TXNOP 0x04 // ----01--
mluis 0:62d1edcc13d1 563 #define MAP_DIO2_FSK_TIMEOUT 0x08 // ----10--
mluis 0:62d1edcc13d1 564
mluis 0:62d1edcc13d1 565
mluis 0:62d1edcc13d1 566 // FSK IMAGECAL defines
mluis 0:62d1edcc13d1 567 #define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F
mluis 0:62d1edcc13d1 568 #define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80
mluis 0:62d1edcc13d1 569 #define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default
mluis 0:62d1edcc13d1 570
mluis 0:62d1edcc13d1 571 #define RF_IMAGECAL_IMAGECAL_MASK 0xBF
mluis 0:62d1edcc13d1 572 #define RF_IMAGECAL_IMAGECAL_START 0x40
mluis 0:62d1edcc13d1 573
mluis 0:62d1edcc13d1 574 #define RF_IMAGECAL_IMAGECAL_RUNNING 0x20
mluis 0:62d1edcc13d1 575 #define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default
mluis 0:62d1edcc13d1 576
mluis 0:62d1edcc13d1 577
mluis 0:62d1edcc13d1 578 // RADIO STATE
mluis 0:62d1edcc13d1 579 // (initialized by radio_init(), used by radio_rand1())
mluis 0:62d1edcc13d1 580 static u1_t randbuf[16];
mluis 0:62d1edcc13d1 581
mluis 0:62d1edcc13d1 582
mluis 0:62d1edcc13d1 583 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 584 #define LNA_RX_GAIN (0x20|0x1)
mluis 0:62d1edcc13d1 585 #elif CFG_sx1272_radio
mluis 0:62d1edcc13d1 586 #define LNA_RX_GAIN (0x20|0x03)
mluis 0:62d1edcc13d1 587 #else
mluis 0:62d1edcc13d1 588 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
mluis 0:62d1edcc13d1 589 #endif
mluis 0:62d1edcc13d1 590
mluis 1:d3b7bde3995c 591 #define RADIO_DBG
mluis 1:d3b7bde3995c 592 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 593 DigitalOut txStateIo( PB_8 );
mluis 1:d3b7bde3995c 594 DigitalOut rxStateIo( PB_9 );
mluis 1:d3b7bde3995c 595 #endif
mluis 1:d3b7bde3995c 596
tmulrooney 5:464c1f2d6cbb 597 static void writeReg (u1_t addr, u1_t data )
tmulrooney 5:464c1f2d6cbb 598 {
tmulrooney 5:464c1f2d6cbb 599 debug("writeReg enter 0x%02X 0x%02X\r\n",addr,data);
mluis 0:62d1edcc13d1 600 hal_pin_nss(0);
mluis 0:62d1edcc13d1 601 hal_spi(addr | 0x80);
mluis 0:62d1edcc13d1 602 hal_spi(data);
mluis 0:62d1edcc13d1 603 hal_pin_nss(1);
mluis 0:62d1edcc13d1 604 }
mluis 0:62d1edcc13d1 605
tmulrooney 5:464c1f2d6cbb 606 static u1_t readReg (u1_t addr)
tmulrooney 5:464c1f2d6cbb 607 {
mluis 0:62d1edcc13d1 608 hal_pin_nss(0);
mluis 0:62d1edcc13d1 609 hal_spi(addr & 0x7F);
mluis 0:62d1edcc13d1 610 u1_t val = hal_spi(0x00);
mluis 0:62d1edcc13d1 611 hal_pin_nss(1);
tmulrooney 5:464c1f2d6cbb 612 debug("readReg exit 0x%02X 0x%02X\r\n",addr,val);
mluis 0:62d1edcc13d1 613 return val;
mluis 0:62d1edcc13d1 614 }
mluis 0:62d1edcc13d1 615
tmulrooney 5:464c1f2d6cbb 616 static void writeBuf (u1_t addr, xref2u1_t buf, u1_t len)
tmulrooney 5:464c1f2d6cbb 617 {
tmulrooney 5:464c1f2d6cbb 618 debug("writeBuf enter 0x%02X\r\n",addr);
mluis 0:62d1edcc13d1 619 hal_pin_nss(0);
mluis 0:62d1edcc13d1 620 hal_spi(addr | 0x80);
tmulrooney 5:464c1f2d6cbb 621 for (u1_t i=0; i<len; i++)
tmulrooney 5:464c1f2d6cbb 622 {
tmulrooney 5:464c1f2d6cbb 623 debug(" 0x%02X\r\n",buf[i]);
mluis 0:62d1edcc13d1 624 hal_spi(buf[i]);
mluis 0:62d1edcc13d1 625 }
mluis 0:62d1edcc13d1 626 hal_pin_nss(1);
tmulrooney 5:464c1f2d6cbb 627 debug("\r\n");
mluis 0:62d1edcc13d1 628 }
mluis 0:62d1edcc13d1 629
tmulrooney 5:464c1f2d6cbb 630 static void readBuf (u1_t addr, xref2u1_t buf, u1_t len)
tmulrooney 5:464c1f2d6cbb 631 {
tmulrooney 5:464c1f2d6cbb 632 debug("readBuf enter 0x%02X\r\n",addr);
mluis 0:62d1edcc13d1 633 hal_pin_nss(0);
mluis 0:62d1edcc13d1 634 hal_spi(addr & 0x7F);
mluis 0:62d1edcc13d1 635 for (u1_t i=0; i<len; i++) {
mluis 0:62d1edcc13d1 636 buf[i] = hal_spi(0x00);
tmulrooney 5:464c1f2d6cbb 637 debug(" 0x%02X\r\n",buf[i]);
mluis 0:62d1edcc13d1 638 }
mluis 0:62d1edcc13d1 639 hal_pin_nss(1);
tmulrooney 5:464c1f2d6cbb 640 debug("\r\n");
mluis 0:62d1edcc13d1 641 }
mluis 0:62d1edcc13d1 642
tmulrooney 5:464c1f2d6cbb 643 static void opmode (u1_t mode)
tmulrooney 5:464c1f2d6cbb 644 {
tmulrooney 5:464c1f2d6cbb 645 debug("opmode enter %d\r\n",mode);
mluis 0:62d1edcc13d1 646 writeReg(RegOpMode, (readReg(RegOpMode) & ~OPMODE_MASK) | mode);
mluis 0:62d1edcc13d1 647 }
mluis 0:62d1edcc13d1 648
tmulrooney 5:464c1f2d6cbb 649 static void opmodeLora()
tmulrooney 5:464c1f2d6cbb 650 {
tmulrooney 5:464c1f2d6cbb 651 debug("opmodeLora enter\r\n");
tmulrooney 5:464c1f2d6cbb 652 u1_t u = OPMODE_LORA;
mluis 0:62d1edcc13d1 653 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 654 u |= 0x8; // TBD: sx1276 high freq
mluis 0:62d1edcc13d1 655 #endif
mluis 0:62d1edcc13d1 656 writeReg(RegOpMode, u);
mluis 0:62d1edcc13d1 657 }
mluis 0:62d1edcc13d1 658
tmulrooney 5:464c1f2d6cbb 659 static void opmodeFSK()
tmulrooney 5:464c1f2d6cbb 660 {
tmulrooney 5:464c1f2d6cbb 661 debug("opmodeFSK enter\r\n");
mluis 0:62d1edcc13d1 662 u1_t u = 0;
mluis 0:62d1edcc13d1 663 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 664 u |= 0x8; // TBD: sx1276 high freq
mluis 0:62d1edcc13d1 665 #endif
mluis 0:62d1edcc13d1 666 writeReg(RegOpMode, u);
mluis 0:62d1edcc13d1 667 }
mluis 0:62d1edcc13d1 668
mluis 0:62d1edcc13d1 669 // configure LoRa modem (cfg1, cfg2)
tmulrooney 5:464c1f2d6cbb 670 static void configLoraModem ()
tmulrooney 5:464c1f2d6cbb 671 {
tmulrooney 5:464c1f2d6cbb 672 debug("configLoraModem enter\r\n");
mluis 0:62d1edcc13d1 673 sf_t sf = getSf(LMIC.rps);
mluis 0:62d1edcc13d1 674
mluis 0:62d1edcc13d1 675 #ifdef CFG_sx1276_radio
mluis 1:d3b7bde3995c 676 u1_t mc1 = 0, mc2 = 0, mc3 = 0;
mluis 0:62d1edcc13d1 677
mluis 1:d3b7bde3995c 678 switch (getBw(LMIC.rps)) {
mluis 1:d3b7bde3995c 679 case BW125: mc1 |= SX1276_MC1_BW_125; break;
mluis 1:d3b7bde3995c 680 case BW250: mc1 |= SX1276_MC1_BW_250; break;
mluis 1:d3b7bde3995c 681 case BW500: mc1 |= SX1276_MC1_BW_500; break;
mluis 1:d3b7bde3995c 682 default:
mluis 1:d3b7bde3995c 683 ASSERT(0);
mluis 1:d3b7bde3995c 684 }
mluis 1:d3b7bde3995c 685 switch( getCr(LMIC.rps) ) {
mluis 1:d3b7bde3995c 686 case CR_4_5: mc1 |= SX1276_MC1_CR_4_5; break;
mluis 1:d3b7bde3995c 687 case CR_4_6: mc1 |= SX1276_MC1_CR_4_6; break;
mluis 1:d3b7bde3995c 688 case CR_4_7: mc1 |= SX1276_MC1_CR_4_7; break;
mluis 1:d3b7bde3995c 689 case CR_4_8: mc1 |= SX1276_MC1_CR_4_8; break;
mluis 1:d3b7bde3995c 690 default:
mluis 1:d3b7bde3995c 691 ASSERT(0);
mluis 1:d3b7bde3995c 692 }
mluis 0:62d1edcc13d1 693
mluis 1:d3b7bde3995c 694 if (getIh(LMIC.rps)) {
mluis 1:d3b7bde3995c 695 mc1 |= SX1276_MC1_IMPLICIT_HEADER_MODE_ON;
mluis 1:d3b7bde3995c 696 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
mluis 1:d3b7bde3995c 697 }
mluis 1:d3b7bde3995c 698 // set ModemConfig1
mluis 1:d3b7bde3995c 699 writeReg(LORARegModemConfig1, mc1);
mluis 0:62d1edcc13d1 700
mluis 1:d3b7bde3995c 701 mc2 = (SX1272_MC2_SF7 + ((sf-1)<<4));
mluis 1:d3b7bde3995c 702 if (getNocrc(LMIC.rps) == 0) {
mluis 1:d3b7bde3995c 703 mc2 |= SX1276_MC2_RX_PAYLOAD_CRCON;
mluis 1:d3b7bde3995c 704 }
mluis 1:d3b7bde3995c 705 writeReg(LORARegModemConfig2, mc2);
mluis 1:d3b7bde3995c 706
mluis 1:d3b7bde3995c 707 mc3 = SX1276_MC3_AGCAUTO;
mluis 1:d3b7bde3995c 708 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
mluis 1:d3b7bde3995c 709 mc3 |= SX1276_MC3_LOW_DATA_RATE_OPTIMIZE;
mluis 1:d3b7bde3995c 710 }
mluis 1:d3b7bde3995c 711 writeReg(LORARegModemConfig3, mc3);
mluis 0:62d1edcc13d1 712 #elif CFG_sx1272_radio
mluis 1:d3b7bde3995c 713 u1_t mc1 = (getBw(LMIC.rps)<<6);
mluis 0:62d1edcc13d1 714
mluis 1:d3b7bde3995c 715 switch( getCr(LMIC.rps) ) {
mluis 1:d3b7bde3995c 716 case CR_4_5: mc1 |= SX1272_MC1_CR_4_5; break;
mluis 1:d3b7bde3995c 717 case CR_4_6: mc1 |= SX1272_MC1_CR_4_6; break;
mluis 1:d3b7bde3995c 718 case CR_4_7: mc1 |= SX1272_MC1_CR_4_7; break;
mluis 1:d3b7bde3995c 719 case CR_4_8: mc1 |= SX1272_MC1_CR_4_8; break;
mluis 1:d3b7bde3995c 720 }
mluis 1:d3b7bde3995c 721
mluis 1:d3b7bde3995c 722 if ((sf == SF11 || sf == SF12) && getBw(LMIC.rps) == BW125) {
mluis 1:d3b7bde3995c 723 mc1 |= SX1272_MC1_LOW_DATA_RATE_OPTIMIZE;
mluis 1:d3b7bde3995c 724 }
mluis 1:d3b7bde3995c 725
mluis 1:d3b7bde3995c 726 if (getNocrc(LMIC.rps) == 0) {
mluis 1:d3b7bde3995c 727 mc1 |= SX1272_MC1_RX_PAYLOAD_CRCON;
mluis 1:d3b7bde3995c 728 }
mluis 1:d3b7bde3995c 729
mluis 1:d3b7bde3995c 730 if (getIh(LMIC.rps)) {
mluis 1:d3b7bde3995c 731 mc1 |= SX1272_MC1_IMPLICIT_HEADER_MODE_ON;
mluis 1:d3b7bde3995c 732 writeReg(LORARegPayloadLength, getIh(LMIC.rps)); // required length
mluis 1:d3b7bde3995c 733 }
mluis 1:d3b7bde3995c 734 // set ModemConfig1
mluis 1:d3b7bde3995c 735 writeReg(LORARegModemConfig1, mc1);
mluis 1:d3b7bde3995c 736
mluis 1:d3b7bde3995c 737 // set ModemConfig2 (sf, AgcAutoOn=1 SymbTimeoutHi=00)
mluis 1:d3b7bde3995c 738 writeReg(LORARegModemConfig2, (SX1272_MC2_SF7 + ((sf-1)<<4)) | 0x04);
mluis 0:62d1edcc13d1 739 #else
mluis 0:62d1edcc13d1 740 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
mluis 0:62d1edcc13d1 741 #endif /* CFG_sx1272_radio */
mluis 0:62d1edcc13d1 742 }
mluis 0:62d1edcc13d1 743
tmulrooney 5:464c1f2d6cbb 744 static void configChannel ()
tmulrooney 5:464c1f2d6cbb 745 {
mluis 0:62d1edcc13d1 746 // set frequency: FQ = (FRF * 32 Mhz) / (2 ^ 19)
mluis 0:62d1edcc13d1 747 u8_t frf = ((u8_t)LMIC.freq << 19) / 32000000;
tmulrooney 5:464c1f2d6cbb 748 debug("configChannel enter %d %lld\r\n",LMIC.freq, frf);
mluis 0:62d1edcc13d1 749 writeReg(RegFrfMsb, (u1_t)(frf>>16));
mluis 0:62d1edcc13d1 750 writeReg(RegFrfMid, (u1_t)(frf>> 8));
mluis 0:62d1edcc13d1 751 writeReg(RegFrfLsb, (u1_t)(frf>> 0));
mluis 0:62d1edcc13d1 752 }
mluis 0:62d1edcc13d1 753
mluis 0:62d1edcc13d1 754
mluis 0:62d1edcc13d1 755
tmulrooney 5:464c1f2d6cbb 756 static void configPower ()
tmulrooney 5:464c1f2d6cbb 757 {
tmulrooney 5:464c1f2d6cbb 758 debug("configPower enter\r\n");
mluis 0:62d1edcc13d1 759 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 760 // no boost used for now
mluis 0:62d1edcc13d1 761 s1_t pw = (s1_t)LMIC.txpow;
mluis 1:d3b7bde3995c 762 if(pw >= 17) {
mluis 1:d3b7bde3995c 763 pw = 15;
mluis 1:d3b7bde3995c 764 } else if(pw < 2) {
mluis 1:d3b7bde3995c 765 pw = 2;
mluis 0:62d1edcc13d1 766 }
mluis 0:62d1edcc13d1 767 // check board type for BOOST pin
mluis 1:d3b7bde3995c 768 writeReg(RegPaConfig, (u1_t)(0x80|(pw&0xf)));
mluis 0:62d1edcc13d1 769 writeReg(RegPaDac, readReg(RegPaDac)|0x4);
mluis 0:62d1edcc13d1 770
mluis 0:62d1edcc13d1 771 #elif CFG_sx1272_radio
mluis 0:62d1edcc13d1 772 // set PA config (2-17 dBm using PA_BOOST)
mluis 0:62d1edcc13d1 773 s1_t pw = (s1_t)LMIC.txpow;
mluis 0:62d1edcc13d1 774 if(pw > 17) {
mluis 1:d3b7bde3995c 775 pw = 17;
mluis 0:62d1edcc13d1 776 } else if(pw < 2) {
mluis 1:d3b7bde3995c 777 pw = 2;
mluis 0:62d1edcc13d1 778 }
mluis 0:62d1edcc13d1 779 writeReg(RegPaConfig, (u1_t)(0x80|(pw-2)));
mluis 0:62d1edcc13d1 780 #else
mluis 0:62d1edcc13d1 781 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
mluis 0:62d1edcc13d1 782 #endif /* CFG_sx1272_radio */
mluis 0:62d1edcc13d1 783 }
mluis 0:62d1edcc13d1 784
tmulrooney 5:464c1f2d6cbb 785 static void txfsk ()
tmulrooney 5:464c1f2d6cbb 786 {
tmulrooney 7:29058a7ccf23 787 debug_str("txfsk enter\r\n");
mluis 0:62d1edcc13d1 788 // select FSK modem (from sleep mode)
mluis 0:62d1edcc13d1 789 writeReg(RegOpMode, 0x10); // FSK, BT=0.5
mluis 0:62d1edcc13d1 790 ASSERT(readReg(RegOpMode) == 0x10);
mluis 0:62d1edcc13d1 791 // enter standby mode (required for FIFO loading))
mluis 0:62d1edcc13d1 792 opmode(OPMODE_STANDBY);
mluis 1:d3b7bde3995c 793 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 794 txStateIo = 0;
mluis 1:d3b7bde3995c 795 rxStateIo = 0;
mluis 1:d3b7bde3995c 796 #endif
mluis 0:62d1edcc13d1 797 // set bitrate
mluis 0:62d1edcc13d1 798 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
mluis 0:62d1edcc13d1 799 writeReg(FSKRegBitrateLsb, 0x80);
mluis 0:62d1edcc13d1 800 // set frequency deviation
mluis 0:62d1edcc13d1 801 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
mluis 0:62d1edcc13d1 802 writeReg(FSKRegFdevLsb, 0x99);
mluis 0:62d1edcc13d1 803 // frame and packet handler settings
mluis 0:62d1edcc13d1 804 writeReg(FSKRegPreambleMsb, 0x00);
mluis 0:62d1edcc13d1 805 writeReg(FSKRegPreambleLsb, 0x05);
mluis 0:62d1edcc13d1 806 writeReg(FSKRegSyncConfig, 0x12);
mluis 0:62d1edcc13d1 807 writeReg(FSKRegPacketConfig1, 0xD0);
mluis 0:62d1edcc13d1 808 writeReg(FSKRegPacketConfig2, 0x40);
mluis 0:62d1edcc13d1 809 writeReg(FSKRegSyncValue1, 0xC1);
mluis 0:62d1edcc13d1 810 writeReg(FSKRegSyncValue2, 0x94);
mluis 0:62d1edcc13d1 811 writeReg(FSKRegSyncValue3, 0xC1);
mluis 0:62d1edcc13d1 812 // configure frequency
mluis 0:62d1edcc13d1 813 configChannel();
mluis 0:62d1edcc13d1 814 // configure output power
mluis 0:62d1edcc13d1 815 configPower();
mluis 0:62d1edcc13d1 816
mluis 0:62d1edcc13d1 817 // set the IRQ mapping DIO0=PacketSent DIO1=NOP DIO2=NOP
mluis 0:62d1edcc13d1 818 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TXNOP);
mluis 0:62d1edcc13d1 819
mluis 0:62d1edcc13d1 820 // initialize the payload size and address pointers
mluis 0:62d1edcc13d1 821 writeReg(FSKRegPayloadLength, LMIC.dataLen+1); // (insert length byte into payload))
mluis 0:62d1edcc13d1 822
mluis 0:62d1edcc13d1 823 // download length byte and buffer to the radio FIFO
mluis 0:62d1edcc13d1 824 writeReg(RegFifo, LMIC.dataLen);
mluis 0:62d1edcc13d1 825 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
mluis 0:62d1edcc13d1 826
mluis 0:62d1edcc13d1 827 // enable antenna switch for TX
mluis 0:62d1edcc13d1 828 hal_pin_rxtx(1);
mluis 0:62d1edcc13d1 829
mluis 0:62d1edcc13d1 830 // now we actually start the transmission
mluis 0:62d1edcc13d1 831 opmode(OPMODE_TX);
mluis 1:d3b7bde3995c 832 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 833 txStateIo = 1;
mluis 1:d3b7bde3995c 834 #endif
mluis 0:62d1edcc13d1 835 }
mluis 0:62d1edcc13d1 836
tmulrooney 5:464c1f2d6cbb 837 static void txlora ()
tmulrooney 5:464c1f2d6cbb 838 {
tmulrooney 7:29058a7ccf23 839 debug_str("txlora enter\r\n");
mluis 0:62d1edcc13d1 840 // select LoRa modem (from sleep mode)
mluis 0:62d1edcc13d1 841 //writeReg(RegOpMode, OPMODE_LORA);
mluis 0:62d1edcc13d1 842 opmodeLora();
mluis 0:62d1edcc13d1 843 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
mluis 0:62d1edcc13d1 844
mluis 0:62d1edcc13d1 845 // enter standby mode (required for FIFO loading))
mluis 0:62d1edcc13d1 846 opmode(OPMODE_STANDBY);
mluis 1:d3b7bde3995c 847 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 848 txStateIo = 0;
mluis 1:d3b7bde3995c 849 rxStateIo = 0;
mluis 1:d3b7bde3995c 850 #endif
mluis 0:62d1edcc13d1 851 // configure LoRa modem (cfg1, cfg2)
mluis 0:62d1edcc13d1 852 configLoraModem();
mluis 0:62d1edcc13d1 853 // configure frequency
mluis 0:62d1edcc13d1 854 configChannel();
mluis 0:62d1edcc13d1 855 // configure output power
mluis 0:62d1edcc13d1 856 writeReg(RegPaRamp, (readReg(RegPaRamp) & 0xF0) | 0x08); // set PA ramp-up time 50 uSec
mluis 0:62d1edcc13d1 857 configPower();
mluis 0:62d1edcc13d1 858 // set sync word
mluis 0:62d1edcc13d1 859 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
mluis 0:62d1edcc13d1 860
mluis 0:62d1edcc13d1 861 // set the IRQ mapping DIO0=TxDone DIO1=NOP DIO2=NOP
mluis 0:62d1edcc13d1 862 writeReg(RegDioMapping1, MAP_DIO0_LORA_TXDONE|MAP_DIO1_LORA_NOP|MAP_DIO2_LORA_NOP);
mluis 0:62d1edcc13d1 863 // clear all radio IRQ flags
mluis 0:62d1edcc13d1 864 writeReg(LORARegIrqFlags, 0xFF);
mluis 0:62d1edcc13d1 865 // mask all IRQs but TxDone
mluis 0:62d1edcc13d1 866 writeReg(LORARegIrqFlagsMask, ~IRQ_LORA_TXDONE_MASK);
mluis 0:62d1edcc13d1 867
mluis 0:62d1edcc13d1 868 // initialize the payload size and address pointers
mluis 0:62d1edcc13d1 869 writeReg(LORARegFifoTxBaseAddr, 0x00);
mluis 0:62d1edcc13d1 870 writeReg(LORARegFifoAddrPtr, 0x00);
mluis 0:62d1edcc13d1 871 writeReg(LORARegPayloadLength, LMIC.dataLen);
mluis 0:62d1edcc13d1 872
mluis 0:62d1edcc13d1 873 // download buffer to the radio FIFO
mluis 0:62d1edcc13d1 874 writeBuf(RegFifo, LMIC.frame, LMIC.dataLen);
mluis 0:62d1edcc13d1 875
mluis 0:62d1edcc13d1 876 // enable antenna switch for TX
mluis 0:62d1edcc13d1 877 hal_pin_rxtx(1);
mluis 0:62d1edcc13d1 878
mluis 0:62d1edcc13d1 879 // now we actually start the transmission
mluis 0:62d1edcc13d1 880 opmode(OPMODE_TX);
mluis 0:62d1edcc13d1 881 }
mluis 0:62d1edcc13d1 882
mluis 0:62d1edcc13d1 883 // start transmitter (buf=LMIC.frame, len=LMIC.dataLen)
tmulrooney 5:464c1f2d6cbb 884 static void starttx ()
tmulrooney 5:464c1f2d6cbb 885 {
tmulrooney 7:29058a7ccf23 886 debug_str("starttx enter\r\n");
mluis 0:62d1edcc13d1 887 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
mluis 0:62d1edcc13d1 888 if(getSf(LMIC.rps) == FSK) { // FSK modem
mluis 0:62d1edcc13d1 889 txfsk();
mluis 0:62d1edcc13d1 890 } else { // LoRa modem
mluis 0:62d1edcc13d1 891 txlora();
mluis 0:62d1edcc13d1 892 }
mluis 0:62d1edcc13d1 893 // the radio will go back to STANDBY mode as soon as the TX is finished
mluis 0:62d1edcc13d1 894 // the corresponding IRQ will inform us about completion.
mluis 0:62d1edcc13d1 895 }
mluis 0:62d1edcc13d1 896
mluis 0:62d1edcc13d1 897 enum { RXMODE_SINGLE, RXMODE_SCAN, RXMODE_RSSI };
mluis 0:62d1edcc13d1 898
mluis 0:62d1edcc13d1 899 static const u1_t rxlorairqmask[] = {
mluis 0:62d1edcc13d1 900 [RXMODE_SINGLE] = IRQ_LORA_RXDONE_MASK|IRQ_LORA_RXTOUT_MASK,
mluis 0:62d1edcc13d1 901 [RXMODE_SCAN] = IRQ_LORA_RXDONE_MASK,
mluis 0:62d1edcc13d1 902 [RXMODE_RSSI] = 0x00,
mluis 0:62d1edcc13d1 903 };
mluis 0:62d1edcc13d1 904
mluis 0:62d1edcc13d1 905 // start LoRa receiver (time=LMIC.rxtime, timeout=LMIC.rxsyms, result=LMIC.frame[LMIC.dataLen])
tmulrooney 5:464c1f2d6cbb 906 static void rxlora (u1_t rxmode)
tmulrooney 5:464c1f2d6cbb 907 {
tmulrooney 7:29058a7ccf23 908 debug_str("rxlora enter\r\n");
mluis 0:62d1edcc13d1 909 // select LoRa modem (from sleep mode)
mluis 0:62d1edcc13d1 910 opmodeLora();
mluis 0:62d1edcc13d1 911 ASSERT((readReg(RegOpMode) & OPMODE_LORA) != 0);
mluis 0:62d1edcc13d1 912 // enter standby mode (warm up))
mluis 0:62d1edcc13d1 913 opmode(OPMODE_STANDBY);
mluis 1:d3b7bde3995c 914 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 915 txStateIo = 0;
mluis 1:d3b7bde3995c 916 rxStateIo = 0;
mluis 1:d3b7bde3995c 917 #endif
mluis 0:62d1edcc13d1 918 // don't use MAC settings at startup
mluis 0:62d1edcc13d1 919 if(rxmode == RXMODE_RSSI) { // use fixed settings for rssi scan
mluis 0:62d1edcc13d1 920 writeReg(LORARegModemConfig1, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG1);
mluis 0:62d1edcc13d1 921 writeReg(LORARegModemConfig2, RXLORA_RXMODE_RSSI_REG_MODEM_CONFIG2);
mluis 0:62d1edcc13d1 922 } else { // single or continuous rx mode
mluis 0:62d1edcc13d1 923 // configure LoRa modem (cfg1, cfg2)
mluis 0:62d1edcc13d1 924 configLoraModem();
mluis 0:62d1edcc13d1 925 // configure frequency
mluis 0:62d1edcc13d1 926 configChannel();
mluis 0:62d1edcc13d1 927 }
mluis 0:62d1edcc13d1 928 // set LNA gain
mluis 0:62d1edcc13d1 929 writeReg(RegLna, LNA_RX_GAIN);
mluis 0:62d1edcc13d1 930 // set max payload size
mluis 0:62d1edcc13d1 931 writeReg(LORARegPayloadMaxLength, 64);
mluis 0:62d1edcc13d1 932 // use inverted I/Q signal (prevent mote-to-mote communication)
mluis 0:62d1edcc13d1 933 writeReg(LORARegInvertIQ, readReg(LORARegInvertIQ)|(1<<6));
mluis 0:62d1edcc13d1 934 // set symbol timeout (for single rx)
mluis 0:62d1edcc13d1 935 writeReg(LORARegSymbTimeoutLsb, LMIC.rxsyms);
mluis 0:62d1edcc13d1 936 // set sync word
mluis 0:62d1edcc13d1 937 writeReg(LORARegSyncWord, LORA_MAC_PREAMBLE);
mluis 0:62d1edcc13d1 938
mluis 0:62d1edcc13d1 939 // configure DIO mapping DIO0=RxDone DIO1=RxTout DIO2=NOP
mluis 0:62d1edcc13d1 940 writeReg(RegDioMapping1, MAP_DIO0_LORA_RXDONE|MAP_DIO1_LORA_RXTOUT|MAP_DIO2_LORA_NOP);
mluis 0:62d1edcc13d1 941 // clear all radio IRQ flags
mluis 0:62d1edcc13d1 942 writeReg(LORARegIrqFlags, 0xFF);
mluis 0:62d1edcc13d1 943 // enable required radio IRQs
mluis 0:62d1edcc13d1 944 writeReg(LORARegIrqFlagsMask, ~rxlorairqmask[rxmode]);
mluis 0:62d1edcc13d1 945
mluis 0:62d1edcc13d1 946 // enable antenna switch for RX
mluis 0:62d1edcc13d1 947 hal_pin_rxtx(0);
mluis 0:62d1edcc13d1 948
mluis 0:62d1edcc13d1 949 // now instruct the radio to receive
mluis 0:62d1edcc13d1 950 if (rxmode == RXMODE_SINGLE) { // single rx
mluis 0:62d1edcc13d1 951 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
mluis 1:d3b7bde3995c 952 opmode(OPMODE_RX_SINGLE);
mluis 1:d3b7bde3995c 953 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 954 rxStateIo = 1;
mluis 1:d3b7bde3995c 955 #endif
mluis 0:62d1edcc13d1 956 } else { // continous rx (scan or rssi)
mluis 1:d3b7bde3995c 957 opmode(OPMODE_RX);
mluis 1:d3b7bde3995c 958 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 959 rxStateIo = 1;
mluis 1:d3b7bde3995c 960 #endif
mluis 0:62d1edcc13d1 961 }
mluis 0:62d1edcc13d1 962 }
mluis 0:62d1edcc13d1 963
tmulrooney 5:464c1f2d6cbb 964 static void rxfsk (u1_t rxmode)
tmulrooney 5:464c1f2d6cbb 965 {
tmulrooney 7:29058a7ccf23 966 debug_str("rxfsk enter\r\n");
mluis 0:62d1edcc13d1 967 // only single rx (no continuous scanning, no noise sampling)
mluis 0:62d1edcc13d1 968 ASSERT( rxmode == RXMODE_SINGLE );
mluis 0:62d1edcc13d1 969 // select FSK modem (from sleep mode)
mluis 0:62d1edcc13d1 970 //writeReg(RegOpMode, 0x00); // (not LoRa)
mluis 0:62d1edcc13d1 971 opmodeFSK();
mluis 0:62d1edcc13d1 972 ASSERT((readReg(RegOpMode) & OPMODE_LORA) == 0);
mluis 0:62d1edcc13d1 973 // enter standby mode (warm up))
mluis 0:62d1edcc13d1 974 opmode(OPMODE_STANDBY);
mluis 1:d3b7bde3995c 975 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 976 txStateIo = 0;
mluis 1:d3b7bde3995c 977 rxStateIo = 0;
mluis 1:d3b7bde3995c 978 #endif
mluis 0:62d1edcc13d1 979 // configure frequency
mluis 0:62d1edcc13d1 980 configChannel();
mluis 0:62d1edcc13d1 981 // set LNA gain
mluis 0:62d1edcc13d1 982 //writeReg(RegLna, 0x20|0x03); // max gain, boost enable
mluis 0:62d1edcc13d1 983 writeReg(RegLna, LNA_RX_GAIN);
mluis 0:62d1edcc13d1 984 // configure receiver
mluis 0:62d1edcc13d1 985 writeReg(FSKRegRxConfig, 0x1E); // AFC auto, AGC, trigger on preamble?!?
mluis 0:62d1edcc13d1 986 // set receiver bandwidth
mluis 0:62d1edcc13d1 987 writeReg(FSKRegRxBw, 0x0B); // 50kHz SSb
mluis 0:62d1edcc13d1 988 // set AFC bandwidth
mluis 0:62d1edcc13d1 989 writeReg(FSKRegAfcBw, 0x12); // 83.3kHz SSB
mluis 0:62d1edcc13d1 990 // set preamble detection
mluis 0:62d1edcc13d1 991 writeReg(FSKRegPreambleDetect, 0xAA); // enable, 2 bytes, 10 chip errors
mluis 0:62d1edcc13d1 992 // set sync config
mluis 0:62d1edcc13d1 993 writeReg(FSKRegSyncConfig, 0x12); // no auto restart, preamble 0xAA, enable, fill FIFO, 3 bytes sync
mluis 0:62d1edcc13d1 994 // set packet config
mluis 0:62d1edcc13d1 995 writeReg(FSKRegPacketConfig1, 0xD8); // var-length, whitening, crc, no auto-clear, no adr filter
mluis 0:62d1edcc13d1 996 writeReg(FSKRegPacketConfig2, 0x40); // packet mode
mluis 0:62d1edcc13d1 997 // set sync value
mluis 0:62d1edcc13d1 998 writeReg(FSKRegSyncValue1, 0xC1);
mluis 0:62d1edcc13d1 999 writeReg(FSKRegSyncValue2, 0x94);
mluis 0:62d1edcc13d1 1000 writeReg(FSKRegSyncValue3, 0xC1);
mluis 0:62d1edcc13d1 1001 // set preamble timeout
mluis 0:62d1edcc13d1 1002 writeReg(FSKRegRxTimeout2, 0xFF);//(LMIC.rxsyms+1)/2);
mluis 0:62d1edcc13d1 1003 // set bitrate
mluis 0:62d1edcc13d1 1004 writeReg(FSKRegBitrateMsb, 0x02); // 50kbps
mluis 0:62d1edcc13d1 1005 writeReg(FSKRegBitrateLsb, 0x80);
mluis 0:62d1edcc13d1 1006 // set frequency deviation
mluis 0:62d1edcc13d1 1007 writeReg(FSKRegFdevMsb, 0x01); // +/- 25kHz
mluis 0:62d1edcc13d1 1008 writeReg(FSKRegFdevLsb, 0x99);
mluis 0:62d1edcc13d1 1009
mluis 0:62d1edcc13d1 1010 // configure DIO mapping DIO0=PayloadReady DIO1=NOP DIO2=TimeOut
mluis 0:62d1edcc13d1 1011 writeReg(RegDioMapping1, MAP_DIO0_FSK_READY|MAP_DIO1_FSK_NOP|MAP_DIO2_FSK_TIMEOUT);
mluis 0:62d1edcc13d1 1012
mluis 0:62d1edcc13d1 1013 // enable antenna switch for RX
mluis 0:62d1edcc13d1 1014 hal_pin_rxtx(0);
mluis 0:62d1edcc13d1 1015
mluis 0:62d1edcc13d1 1016 // now instruct the radio to receive
mluis 0:62d1edcc13d1 1017 hal_waitUntil(LMIC.rxtime); // busy wait until exact rx time
mluis 0:62d1edcc13d1 1018 opmode(OPMODE_RX); // no single rx mode available in FSK
mluis 1:d3b7bde3995c 1019 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1020 rxStateIo = 1;
mluis 1:d3b7bde3995c 1021 #endif
mluis 0:62d1edcc13d1 1022 }
mluis 0:62d1edcc13d1 1023
tmulrooney 5:464c1f2d6cbb 1024 static void startrx (u1_t rxmode)
tmulrooney 5:464c1f2d6cbb 1025 {
tmulrooney 7:29058a7ccf23 1026 debug_str("startrx enter\r\n");
mluis 0:62d1edcc13d1 1027 ASSERT( (readReg(RegOpMode) & OPMODE_MASK) == OPMODE_SLEEP );
mluis 0:62d1edcc13d1 1028 if(getSf(LMIC.rps) == FSK) { // FSK modem
mluis 0:62d1edcc13d1 1029 rxfsk(rxmode);
mluis 0:62d1edcc13d1 1030 } else { // LoRa modem
mluis 0:62d1edcc13d1 1031 rxlora(rxmode);
mluis 0:62d1edcc13d1 1032 }
mluis 0:62d1edcc13d1 1033 // the radio will go back to STANDBY mode as soon as the RX is finished
mluis 0:62d1edcc13d1 1034 // or timed out, and the corresponding IRQ will inform us about completion.
mluis 0:62d1edcc13d1 1035 }
mluis 0:62d1edcc13d1 1036
mluis 0:62d1edcc13d1 1037 // get random seed from wideband noise rssi
tmulrooney 5:464c1f2d6cbb 1038 void radio_init ()
tmulrooney 5:464c1f2d6cbb 1039 {
tmulrooney 5:464c1f2d6cbb 1040 debug("radio_init2 enter\r\n");
tmulrooney 5:464c1f2d6cbb 1041 Radio = new SX1272MB1xAS(NULL);
mluis 0:62d1edcc13d1 1042 hal_disableIRQs();
mluis 0:62d1edcc13d1 1043
mluis 0:62d1edcc13d1 1044 // manually reset radio
GTsapparellas 8:5879e83f632a 1045 #ifdef CFG_sx1272_radio
mluis 0:62d1edcc13d1 1046 hal_pin_rst(0); // drive RST pin low
mluis 0:62d1edcc13d1 1047 #else
mluis 0:62d1edcc13d1 1048 hal_pin_rst(1); // drive RST pin high
mluis 0:62d1edcc13d1 1049 #endif
mluis 0:62d1edcc13d1 1050 hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us
mluis 0:62d1edcc13d1 1051 hal_pin_rst(2); // configure RST pin floating!
mluis 0:62d1edcc13d1 1052 hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms
mluis 0:62d1edcc13d1 1053
mluis 0:62d1edcc13d1 1054 opmode(OPMODE_SLEEP);
mluis 1:d3b7bde3995c 1055 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1056 txStateIo = 0;
mluis 1:d3b7bde3995c 1057 rxStateIo = 0;
mluis 1:d3b7bde3995c 1058 #endif
mluis 0:62d1edcc13d1 1059 // some sanity checks, e.g., read version number
mluis 0:62d1edcc13d1 1060 u1_t v = readReg(RegVersion);
mluis 0:62d1edcc13d1 1061 #ifdef CFG_sx1276_radio
mluis 0:62d1edcc13d1 1062 ASSERT(v == 0x12 );
mluis 0:62d1edcc13d1 1063 #elif CFG_sx1272_radio
mluis 0:62d1edcc13d1 1064 ASSERT(v == 0x22);
mluis 0:62d1edcc13d1 1065 #else
mluis 0:62d1edcc13d1 1066 #error Missing CFG_sx1272_radio/CFG_sx1276_radio
mluis 0:62d1edcc13d1 1067 #endif
mluis 0:62d1edcc13d1 1068 // seed 15-byte randomness via noise rssi
mluis 0:62d1edcc13d1 1069 rxlora(RXMODE_RSSI);
mluis 0:62d1edcc13d1 1070 while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx
mluis 0:62d1edcc13d1 1071 for(int i=1; i<16; i++) {
mluis 0:62d1edcc13d1 1072 for(int j=0; j<8; j++) {
mluis 0:62d1edcc13d1 1073 u1_t b; // wait for two non-identical subsequent least-significant bits
mluis 0:62d1edcc13d1 1074 while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) );
mluis 0:62d1edcc13d1 1075 randbuf[i] = (randbuf[i] << 1) | b;
mluis 0:62d1edcc13d1 1076 }
mluis 0:62d1edcc13d1 1077 }
mluis 0:62d1edcc13d1 1078 randbuf[0] = 16; // set initial index
mluis 0:62d1edcc13d1 1079
mluis 1:d3b7bde3995c 1080 #ifdef CFG_sx1276mb1_board
mluis 0:62d1edcc13d1 1081 // chain calibration
mluis 0:62d1edcc13d1 1082 writeReg(RegPaConfig, 0);
mluis 0:62d1edcc13d1 1083
mluis 0:62d1edcc13d1 1084 // Launch Rx chain calibration for LF band
mluis 0:62d1edcc13d1 1085 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
mluis 0:62d1edcc13d1 1086 while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; }
mluis 0:62d1edcc13d1 1087
mluis 0:62d1edcc13d1 1088 // Sets a Frequency in HF band
mluis 0:62d1edcc13d1 1089 u4_t frf = 868000000;
mluis 0:62d1edcc13d1 1090 writeReg(RegFrfMsb, (u1_t)(frf>>16));
mluis 0:62d1edcc13d1 1091 writeReg(RegFrfMid, (u1_t)(frf>> 8));
mluis 0:62d1edcc13d1 1092 writeReg(RegFrfLsb, (u1_t)(frf>> 0));
mluis 0:62d1edcc13d1 1093
mluis 0:62d1edcc13d1 1094 // Launch Rx chain calibration for HF band
mluis 0:62d1edcc13d1 1095 writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START);
mluis 0:62d1edcc13d1 1096 while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; }
mluis 1:d3b7bde3995c 1097 #endif /* CFG_sx1276mb1_board */
mluis 0:62d1edcc13d1 1098
mluis 0:62d1edcc13d1 1099 opmode(OPMODE_SLEEP);
mluis 1:d3b7bde3995c 1100 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1101 txStateIo = 0;
mluis 1:d3b7bde3995c 1102 rxStateIo = 0;
mluis 1:d3b7bde3995c 1103 #endif
mluis 0:62d1edcc13d1 1104 hal_enableIRQs();
mluis 0:62d1edcc13d1 1105 }
mluis 0:62d1edcc13d1 1106
mluis 0:62d1edcc13d1 1107 // return next random byte derived from seed buffer
mluis 0:62d1edcc13d1 1108 // (buf[0] holds index of next byte to be returned)
tmulrooney 5:464c1f2d6cbb 1109 u1_t radio_rand1 ()
tmulrooney 5:464c1f2d6cbb 1110 {
tmulrooney 5:464c1f2d6cbb 1111 debug("radio_rand1 enter\r\n");
mluis 0:62d1edcc13d1 1112 u1_t i = randbuf[0];
mluis 0:62d1edcc13d1 1113 ASSERT( i != 0 );
mluis 0:62d1edcc13d1 1114 if( i==16 ) {
mluis 0:62d1edcc13d1 1115 os_aes(AES_ENC, randbuf, 16); // encrypt seed with any key
mluis 0:62d1edcc13d1 1116 i = 0;
mluis 0:62d1edcc13d1 1117 }
mluis 0:62d1edcc13d1 1118 u1_t v = randbuf[i++];
mluis 0:62d1edcc13d1 1119 randbuf[0] = i;
mluis 0:62d1edcc13d1 1120 return v;
mluis 0:62d1edcc13d1 1121 }
mluis 0:62d1edcc13d1 1122
tmulrooney 5:464c1f2d6cbb 1123 u1_t radio_rssi ()
tmulrooney 5:464c1f2d6cbb 1124 {
tmulrooney 5:464c1f2d6cbb 1125 debug("radio_rssi enter\r\n");
mluis 0:62d1edcc13d1 1126 hal_disableIRQs();
mluis 0:62d1edcc13d1 1127 u1_t r = readReg(LORARegRssiValue);
mluis 0:62d1edcc13d1 1128 hal_enableIRQs();
mluis 0:62d1edcc13d1 1129 return r;
mluis 0:62d1edcc13d1 1130 }
mluis 0:62d1edcc13d1 1131
mluis 0:62d1edcc13d1 1132 static const u2_t LORA_RXDONE_FIXUP[] = {
mluis 0:62d1edcc13d1 1133 [FSK] = us2osticks(0), // ( 0 ticks)
mluis 0:62d1edcc13d1 1134 [SF7] = us2osticks(0), // ( 0 ticks)
mluis 0:62d1edcc13d1 1135 [SF8] = us2osticks(1648), // ( 54 ticks)
mluis 0:62d1edcc13d1 1136 [SF9] = us2osticks(3265), // ( 107 ticks)
mluis 0:62d1edcc13d1 1137 [SF10] = us2osticks(7049), // ( 231 ticks)
mluis 0:62d1edcc13d1 1138 [SF11] = us2osticks(13641), // ( 447 ticks)
mluis 0:62d1edcc13d1 1139 [SF12] = us2osticks(31189), // (1022 ticks)
mluis 0:62d1edcc13d1 1140 };
mluis 0:62d1edcc13d1 1141
mluis 0:62d1edcc13d1 1142 // called by hal ext IRQ handler
mluis 0:62d1edcc13d1 1143 // (radio goes to stanby mode after tx/rx operations)
tmulrooney 5:464c1f2d6cbb 1144 void radio_irq_handler (u1_t dio)
tmulrooney 5:464c1f2d6cbb 1145 {
tmulrooney 7:29058a7ccf23 1146 debug_val("radio_irq_handler enter %d\r\n",dio);
mluis 0:62d1edcc13d1 1147 ostime_t now = os_getTime();
mluis 0:62d1edcc13d1 1148 if( (readReg(RegOpMode) & OPMODE_LORA) != 0) { // LORA modem
mluis 1:d3b7bde3995c 1149 u1_t flags = readReg(LORARegIrqFlags);
mluis 1:d3b7bde3995c 1150 if( flags & IRQ_LORA_TXDONE_MASK ) {
mluis 1:d3b7bde3995c 1151 // save exact tx time
mluis 1:d3b7bde3995c 1152 LMIC.txend = now - us2osticks(43); // TXDONE FIXUP
mluis 1:d3b7bde3995c 1153 } else if( flags & IRQ_LORA_RXDONE_MASK ) {
mluis 1:d3b7bde3995c 1154 // save exact rx time
mluis 1:d3b7bde3995c 1155 if(getBw(LMIC.rps) == BW125) {
mluis 1:d3b7bde3995c 1156 now -= LORA_RXDONE_FIXUP[getSf(LMIC.rps)];
mluis 1:d3b7bde3995c 1157 }
mluis 1:d3b7bde3995c 1158 LMIC.rxtime = now;
mluis 1:d3b7bde3995c 1159 // read the PDU and inform the MAC that we received something
mluis 1:d3b7bde3995c 1160 LMIC.dataLen = (readReg(LORARegModemConfig1) & SX1272_MC1_IMPLICIT_HEADER_MODE_ON) ?
mluis 1:d3b7bde3995c 1161 readReg(LORARegPayloadLength) : readReg(LORARegRxNbBytes);
mluis 1:d3b7bde3995c 1162 // set FIFO read address pointer
mluis 1:d3b7bde3995c 1163 writeReg(LORARegFifoAddrPtr, readReg(LORARegFifoRxCurrentAddr));
mluis 1:d3b7bde3995c 1164 // now read the FIFO
mluis 1:d3b7bde3995c 1165 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
mluis 1:d3b7bde3995c 1166 // read rx quality parameters
mluis 1:d3b7bde3995c 1167 LMIC.snr = readReg(LORARegPktSnrValue); // SNR [dB] * 4
mluis 1:d3b7bde3995c 1168 LMIC.rssi = readReg(LORARegPktRssiValue) - 125 + 64; // RSSI [dBm] (-196...+63)
mluis 1:d3b7bde3995c 1169 } else if( flags & IRQ_LORA_RXTOUT_MASK ) {
mluis 1:d3b7bde3995c 1170 // indicate timeout
mluis 1:d3b7bde3995c 1171 LMIC.dataLen = 0;
mluis 1:d3b7bde3995c 1172 }
mluis 0:62d1edcc13d1 1173 // mask all radio IRQs
mluis 0:62d1edcc13d1 1174 writeReg(LORARegIrqFlagsMask, 0xFF);
mluis 0:62d1edcc13d1 1175 // clear radio IRQ flags
mluis 0:62d1edcc13d1 1176 writeReg(LORARegIrqFlags, 0xFF);
mluis 0:62d1edcc13d1 1177 } else { // FSK modem
mluis 1:d3b7bde3995c 1178 u1_t flags1 = readReg(FSKRegIrqFlags1);
mluis 1:d3b7bde3995c 1179 u1_t flags2 = readReg(FSKRegIrqFlags2);
mluis 1:d3b7bde3995c 1180 if( flags2 & IRQ_FSK2_PACKETSENT_MASK ) {
mluis 1:d3b7bde3995c 1181 // save exact tx time
mluis 1:d3b7bde3995c 1182 LMIC.txend = now;
mluis 0:62d1edcc13d1 1183 } else if( flags2 & IRQ_FSK2_PAYLOADREADY_MASK ) {
mluis 1:d3b7bde3995c 1184 // save exact rx time
mluis 1:d3b7bde3995c 1185 LMIC.rxtime = now;
mluis 1:d3b7bde3995c 1186 // read the PDU and inform the MAC that we received something
mluis 1:d3b7bde3995c 1187 LMIC.dataLen = readReg(FSKRegPayloadLength);
mluis 1:d3b7bde3995c 1188 // now read the FIFO
mluis 1:d3b7bde3995c 1189 readBuf(RegFifo, LMIC.frame, LMIC.dataLen);
mluis 1:d3b7bde3995c 1190 // read rx quality parameters
mluis 1:d3b7bde3995c 1191 LMIC.snr = 0; // determine snr
mluis 1:d3b7bde3995c 1192 LMIC.rssi = 0; // determine rssi
mluis 1:d3b7bde3995c 1193 } else if( flags1 & IRQ_FSK1_TIMEOUT_MASK ) {
mluis 1:d3b7bde3995c 1194 // indicate timeout
mluis 1:d3b7bde3995c 1195 LMIC.dataLen = 0;
mluis 1:d3b7bde3995c 1196 } else {
mluis 0:62d1edcc13d1 1197 while(1);
mluis 0:62d1edcc13d1 1198 }
mluis 0:62d1edcc13d1 1199 }
mluis 0:62d1edcc13d1 1200 // go from stanby to sleep
mluis 0:62d1edcc13d1 1201 opmode(OPMODE_SLEEP);
mluis 1:d3b7bde3995c 1202 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1203 txStateIo = 0;
mluis 1:d3b7bde3995c 1204 rxStateIo = 0;
mluis 1:d3b7bde3995c 1205 #endif
mluis 0:62d1edcc13d1 1206 // run os job (use preset func ptr)
mluis 0:62d1edcc13d1 1207 os_setCallback(&LMIC.osjob, LMIC.osjob.func);
mluis 0:62d1edcc13d1 1208 }
mluis 0:62d1edcc13d1 1209
tmulrooney 5:464c1f2d6cbb 1210 void os_radio (u1_t mode)
tmulrooney 5:464c1f2d6cbb 1211 {
GTsapparellas 8:5879e83f632a 1212 //debug("os_radio enter\r\n");
GTsapparellas 8:5879e83f632a 1213 // hal_disableIRQs();
mluis 0:62d1edcc13d1 1214 switch (mode) {
mluis 0:62d1edcc13d1 1215 case RADIO_RST:
mluis 0:62d1edcc13d1 1216 // put radio to sleep
mluis 0:62d1edcc13d1 1217 opmode(OPMODE_SLEEP);
mluis 1:d3b7bde3995c 1218 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1219 txStateIo = 0;
mluis 1:d3b7bde3995c 1220 rxStateIo = 0;
mluis 1:d3b7bde3995c 1221 #endif
mluis 0:62d1edcc13d1 1222 break;
mluis 0:62d1edcc13d1 1223
mluis 0:62d1edcc13d1 1224 case RADIO_TX:
mluis 1:d3b7bde3995c 1225 // transmit frame now
mluis 0:62d1edcc13d1 1226 starttx(); // buf=LMIC.frame, len=LMIC.dataLen
mluis 1:d3b7bde3995c 1227 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1228 txStateIo = 1;
mluis 1:d3b7bde3995c 1229 #endif
mluis 0:62d1edcc13d1 1230 break;
mluis 0:62d1edcc13d1 1231
mluis 0:62d1edcc13d1 1232 case RADIO_RX:
mluis 1:d3b7bde3995c 1233 // receive frame now (exactly at rxtime)
mluis 0:62d1edcc13d1 1234 startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms
mluis 1:d3b7bde3995c 1235 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1236 rxStateIo = 1;
mluis 1:d3b7bde3995c 1237 #endif
mluis 0:62d1edcc13d1 1238 break;
mluis 0:62d1edcc13d1 1239
mluis 0:62d1edcc13d1 1240 case RADIO_RXON:
mluis 0:62d1edcc13d1 1241 // start scanning for beacon now
mluis 0:62d1edcc13d1 1242 startrx(RXMODE_SCAN); // buf=LMIC.frame
mluis 1:d3b7bde3995c 1243 #if defined(RADIO_DBG)
mluis 1:d3b7bde3995c 1244 rxStateIo = 1;
mluis 1:d3b7bde3995c 1245 #endif
mluis 0:62d1edcc13d1 1246 break;
mluis 0:62d1edcc13d1 1247 }
mluis 0:62d1edcc13d1 1248 hal_enableIRQs();
mluis 0:62d1edcc13d1 1249 }
mluis 0:62d1edcc13d1 1250
mluis 0:62d1edcc13d1 1251 #endif // USE_SMTC_RADIO_DRIVER