IBM LoRa MAC in C (LMiC) mbed library port

Dependents:   lora-temperature LoRaWAN-lmic-app_HS LoRaWAN-lmic-app_huynh

LoRa WAN in C for sx1276 shield

Currently version 1.5


LoRaWAN network configuration for end-device

The following three pieces of information uniquely identifies end-device to network to allow over-the-air activation. These are stored in the end-device prior to join procedure.

AppEUI

Uniquely identifies application provider of end-device.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t APPEUI[8]  = { 0x01, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x25, 0x00 };

This is copied into LMIC by os_getArtEui() callback function in application.

DevEUI

End-device ID, unique to each end-node.

Least-significant byte first, 8 bytes, use reverse memcpy() to keep same order as shown on lora server.

example C code

static const u1_t DEVEUI[8]  = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x25, 0x00 }; 

This is copied into LMIC by os_getDevEui() callback function in application.

AppKey (aka DevKey)

128-bit (16byte) AES key.

example C code

static const u1_t DEVKEY[16] = { 0xe4, 0x72, 0x71, 0xc5, 0xf5, 0x30, 0xa9, 0x9f, 0xcf, 0xc4, 0x0e, 0xab, 0xea, 0xd7, 0x19, 0x42 };

This is copied into LMIC by os_getDevKey() callback function in application.

Using over-the air activation, the end-device (LMIC) performs a join procedure every time it starts for first time, or has lost session context information. When join procedure has successfully completed, the end-device will have a network session key (NwkSKey) and an application session key (AppSKey), which are used for encryption and message integrity check.


US915 configuration with http://us01-iot.semtech.com/

  • log in to server
  • click on Applications
  • find your application and click it
  • go to configure motes
  • to create a mote, you may enter a new DevEUI
    • you may copy-paste the 16byte application key from an already existing mote, if you desire.
CHNL_HYBRID125KHz500KHz
defined valuechannelschannel
00 to 764
18 to 1565
216 to 2366
324 to 3167
432 to 3968
540 to 4769
648 to 5570
756 to 6371
undef0 to 6364 to 71
Committer:
mluis
Date:
Tue Mar 31 13:36:56 2015 +0000
Revision:
1:d3b7bde3995c
Parent:
0:62d1edcc13d1
Child:
2:974cafbfb159
Child:
3:519c71d29a06
Updated LMiC to release v1.4 (http://www.zurich.ibm.com/pdf/lrsc/lmic-release-v1.4.zip)

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