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:
dudmuck
Date:
Wed Nov 25 02:49:45 2015 +0000
Revision:
2:974cafbfb159
Parent:
1:d3b7bde3995c
Child:
4:85b2b647cb64
add US 8ch operation "hybrid"

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