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