end node on synchronous star LoRa network.
Dependencies: SX127x sx12xx_hal TSL2561
LoRaMacSingle.cpp
00001 /* */ 00002 00003 #include <math.h> 00004 #include "board.h" 00005 #include "radio.h" 00006 00007 #include "LoRaMacCrypto.h" 00008 #include "LoRaMacSingle.h" 00009 #include "LoRaMacTest.h" 00010 00011 #define BEACONS_MISSED_LIMIT 16 00012 00013 #define PING_SLOT_RESOLUTION_us 30000 00014 00015 #define PREAMBLE_SYMBS 8 00016 00017 #define TARGET_PRECESSION_us 3000 00018 #define BEACON_RX_TIMEOUT_LOCKED_us 8000 00019 00020 /*! 00021 * Maximum PHY layer payload size 00022 */ 00023 #define LORAMAC_PHY_MAXPAYLOAD 255 00024 00025 /*! 00026 * Maximum MAC commands buffer size 00027 */ 00028 #define LORA_MAC_COMMAND_MAX_LENGTH 15 00029 00030 LowPowerClock::time_point txDoneAt; 00031 00032 /*! 00033 * Device IEEE EUI 00034 */ 00035 static uint8_t *LoRaMacDevEui; 00036 00037 /*! 00038 * Application IEEE EUI 00039 */ 00040 static uint8_t *LoRaMacAppEui; 00041 00042 /*! 00043 * AES encryption/decryption cipher application key 00044 */ 00045 static uint8_t *LoRaMacAppKey; 00046 00047 /*! 00048 * AES encryption/decryption cipher network session key 00049 */ 00050 static uint8_t LoRaMacNwkSKey[] = 00051 { 00052 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00053 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00054 }; 00055 00056 /*! 00057 * AES encryption/decryption cipher application session key 00058 */ 00059 static uint8_t LoRaMacAppSKey[] = 00060 { 00061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 00063 }; 00064 00065 /*! 00066 * Device nonce is a random value extracted by issuing a sequence of RSSI 00067 * measurements 00068 */ 00069 static uint16_t LoRaMacDevNonce; 00070 00071 /*! 00072 * Network ID ( 3 bytes ) 00073 */ 00074 static uint32_t LoRaMacNetID; 00075 00076 /*! 00077 * Mote Address 00078 */ 00079 static uint32_t LoRaMacDevAddr; 00080 00081 /*! 00082 * Multicast channels linked list 00083 */ 00084 static MulticastParams_t *MulticastChannels = NULL; 00085 00086 /*! 00087 * Indicates if the node is connected to a private or public network 00088 */ 00089 static bool PublicNetwork; 00090 00091 uint8_t tx_buf_len; 00092 00093 static uint8_t rxFRMPayload[244]; 00094 00095 /*! 00096 * LoRaMAC frame counter. Each time a packet is sent the counter is incremented. 00097 * Only the 16 LSB bits are sent 00098 */ 00099 static uint32_t UpLinkCounter = 0; 00100 00101 /*! 00102 * LoRaMAC frame counter. Each time a packet is received the counter is incremented. 00103 * Only the 16 LSB bits are received 00104 */ 00105 static uint32_t DownLinkCounter = 0; 00106 00107 /*! 00108 * Used for test purposes. Disables the opening of the reception windows. 00109 */ 00110 static bool IsRxWindowsEnabled = true; 00111 00112 LowPowerTimeout rx_timeout; 00113 00114 /* how long this MCU (we're running on) takes to wake-up from deep-sleep */ 00115 microseconds mcu_wakeup_latency; 00116 00117 LowPowerClock::time_point rx_timeout_setAt; 00118 00119 /*! 00120 * Indicates if the MAC layer wants to send MAC commands 00121 */ 00122 static bool MacCommandsInNextTx = false; 00123 00124 /*! 00125 * Contains the current MacCommandsBuffer index 00126 */ 00127 static uint8_t MacCommandsBufferIndex = 0; 00128 00129 /*! 00130 * Contains the current MacCommandsBuffer index for MAC commands to repeat 00131 */ 00132 static uint8_t MacCommandsBufferToRepeatIndex = 0; 00133 00134 /*! 00135 * Buffer containing the MAC layer commands 00136 */ 00137 static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; 00138 00139 /*! 00140 * Buffer containing the MAC layer commands which must be repeated 00141 */ 00142 static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; 00143 00144 #define BEACON_SIZE 6 /* bytes */ 00145 #define BEACON_CHANNEL_DR LORAMAC_DEFAULT_DATARATE 00146 00147 00148 #ifdef SX128x_H 00149 // 0 1 2 3 4 5 6 7 00150 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 6, 5 }; 00151 #define SF_FROM_DR0 12 /* DR0 is sf12 */ 00152 #define SF_FROM_DR1 11 /* DR1 is sf11 */ 00153 #define SF_FROM_DR2 10 /* DR2 is sf10 */ 00154 #define SF_FROM_DR3 9 /* DR3 is sf9 */ 00155 #define SF_FROM_DR4 8 /* DR4 is sf8 */ 00156 #define SF_FROM_DR5 7 /* DR5 is sf7 */ 00157 #define SF_FROM_DR6 6 /* DR5 is sf6 */ 00158 #define SF_FROM_DR7 5 /* DR7 is sf5 */ 00159 00160 00161 const int8_t TxPowers[] = { 12, 5 }; 00162 #define LORAMAC_FIRST_CHANNEL ( (uint32_t)2486.9e6 ) 00163 #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)300e3 ) 00164 #define LORA_MAX_NB_CHANNELS 8 00165 00166 #define LORA_BANDWIDTH_KHZ 200 00167 00168 /* end sx1280 */ 00169 #elif defined( USE_BAND_915_SINGLE ) 00170 /*! 00171 * Data rates table definition 00172 DR: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/ 00173 const uint8_t Datarates[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 }; 00174 #define SF_FROM_DR8 12 00175 #define SF_FROM_DR9 11 00176 #define SF_FROM_DR10 10 00177 #define SF_FROM_DR11 9 00178 #define SF_FROM_DR12 8 00179 #define SF_FROM_DR13 7 00180 00181 /*! 00182 * Tx output powers table definition 00183 */ 00184 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 00185 const int8_t TxPowers[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0 }; 00186 #define LORAMAC_FIRST_CHANNEL ( (uint32_t)910.0e6 ) 00187 #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)800e3 ) 00188 #define LORA_MAX_NB_CHANNELS 8 00189 00190 #define LORA_BANDWIDTH_KHZ 500 00191 00192 /* end us915 */ 00193 #elif defined(USE_BAND_433) 00194 // DR: 0 1 2 3 4 5 6 7 00195 const uint8_t Datarates[] = { 12, 11, 10, 9, 8, 7, 7, 50 }; 00196 #define SF_FROM_DR0 12 00197 #define SF_FROM_DR1 11 00198 #define SF_FROM_DR2 10 00199 #define SF_FROM_DR3 9 00200 #define SF_FROM_DR4 8 00201 #define SF_FROM_DR5 7 00202 00203 const int8_t TxPowers[] = { 10, 7, 4, 1, -2, -5 }; 00204 #define LORA_BANDWIDTH_KHZ 125 00205 00206 #define LORAMAC_FIRST_CHANNEL ( (uint32_t)433.32e6 ) 00207 #define LORAMAC_STEPWIDTH_CHANNEL ( (uint32_t)200e3 ) 00208 #define LORA_MAX_NB_CHANNELS 7 00209 00210 /* end USE_BAND_433 */ 00211 #else 00212 #error "Please define a frequency band in the compiler options." 00213 #endif 00214 00215 #define _SF_FROM_DR(dr) SF_FROM_DR ## dr 00216 #define SF_FROM_DR_(x) _SF_FROM_DR(x) 00217 00218 #ifdef SX128x_H 00219 00220 #define FASTEST_SF 5 00221 /* ratio of symbol period to time from end of packet to RxDone interrupt */ 00222 // sp 200KHz 160 320 640 1280 2560 5120 10240 20480 00223 // usLatency 200KHz implicit-6byte 90 228 436 880 2020 4200 8800 19300 00224 // SF: 5 6 7 8 9 10 11 12 00225 const float rxLatencyFactorFromSF[8] = { 0.56, 0.72, 0.68, 0.69, 0.79, 0.82, 0.86, 0.94 }; 00226 00227 #elif defined(SX126x_H) || defined(SX127x_H) 00228 00229 #define FASTEST_SF 5 00230 /* ratio of symbol period to time from end of packet to RxDone interrupt */ 00231 // sp 500KHz 64 128 256 512 1024 2048 4096 8192 00232 // usLatency 500KHz implicit-6byte 92 184 376 780 1680 3680 7720 00233 // SF: 5 6 7 8 9 10 11 12 00234 const float rxLatencyFactorFromSF[8] = { 0.72, 0.72, 0.72, 0.73, 0.76, 0.82, 0.90, 0.94 }; 00235 00236 #endif /* SX126x_H || SX127x_H */ 00237 00238 static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS]; // populated in init 00239 00240 #define BEACON_GUARD_us 2000000 // pre-beacon start 00241 #define BEACON_RESERVED_us 2120000 // post-beacon start 00242 00243 #define MIN_SYMBOL_TIMEOUT 8 // number of symbols to keep receiver open for 00244 00245 /*! 00246 * LoRaMac parameters 00247 */ 00248 LoRaMacParams_t LoRaMacParams; 00249 00250 /*! 00251 * LoRaMac default parameters 00252 */ 00253 LoRaMacParams_t LoRaMacParamsDefaults; 00254 00255 /*! 00256 * Uplink messages repetitions counter 00257 */ 00258 static uint8_t ChannelsNbRepCounter = 0; 00259 00260 /*! 00261 * Current channel index 00262 */ 00263 static uint8_t Channel; 00264 00265 /*! 00266 * LoRaMac upper layer event functions 00267 */ 00268 static LoRaMacPrimitives_t *LoRaMacPrimitives; 00269 00270 /*! 00271 * LoRaMac upper layer callback functions 00272 */ 00273 static LoRaMacCallback_t *LoRaMacCallbacks; 00274 00275 /*! 00276 * LoRaMac duty cycle delayed Tx timer 00277 */ 00278 LowPowerTimeout tx_timeout; 00279 00280 /*! 00281 * LoRaMac reception windows delay 00282 * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME 00283 * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME 00284 */ 00285 microseconds RxWindowDelay_us; 00286 00287 typedef enum { 00288 BEACON_STATE_NONE = 0, 00289 BEACON_STATE_FIRST_ACQ, 00290 BEACON_STATE_ACQ_ERROR, 00291 BEACON_STATE_LOCKED, 00292 } beacon_state_e; 00293 00294 static struct beacon_struct { 00295 int rx_precession_us; // positive: rxing before tx start, negative: rxing after tx start 00296 LowPowerClock::time_point rx_setup_at; 00297 LowPowerClock::time_point LastBeaconRxAt; // was LastBeaconRx_us, updated only at beacon reception 00298 LowPowerClock::time_point sendAt; 00299 microseconds lastSendAtErr; 00300 int last_BeaconRxTimerError_us; 00301 int known_working_BeaconRxTimerError_us; 00302 00303 unsigned symbol_period_us; 00304 00305 uint8_t Precess_symbols; // how many symbols we want to start receiver before expected transmitter 00306 uint16_t nSymbsTimeout; 00307 unsigned SymbolTimeout_us; 00308 uint8_t num_missed; 00309 uint8_t num_consecutive_ok; 00310 00311 beacon_state_e state; 00312 00313 uint16_t tx_slot_offset; 00314 uint16_t periodicity_slots; 00315 uint32_t beaconStartToRxDone; 00316 uint16_t sendOpportunities; 00317 00318 LowPowerTimeout timeout_rx; 00319 LowPowerTimeout timeout_guard; 00320 bool guard; 00321 } BeaconCtx; 00322 00323 /*! 00324 * Rx window parameters 00325 */ 00326 typedef struct 00327 { 00328 int8_t Datarate; 00329 uint32_t RxWindowTimeout; 00330 } RxConfigParams_t; 00331 00332 /*! 00333 * Rx windows params 00334 */ 00335 static RxConfigParams_t RxWindowsParam; 00336 00337 /*! 00338 * Acknowledge timeout timer. Used for packet retransmissions. 00339 */ 00340 static LowPowerTimeout AckTimeoutTimer; 00341 00342 /*! 00343 * Number of trials for the Join Request 00344 */ 00345 static uint8_t JoinRequestTrials; 00346 00347 /*! 00348 * Maximum number of trials for the Join Request 00349 */ 00350 static uint8_t MaxJoinRequestTrials; 00351 00352 /*! 00353 * Structure to hold an MCPS indication data. 00354 */ 00355 static McpsIndication_t McpsIndication; 00356 00357 /*! 00358 * Structure to hold MCPS confirm data. 00359 */ 00360 static McpsConfirm_t McpsConfirm; 00361 00362 /*! 00363 * Structure to hold MLME confirm data. 00364 */ 00365 static MlmeConfirm_t MlmeConfirm; 00366 00367 /*! 00368 * Structure to hold MLME indication data. 00369 */ 00370 static MlmeIndication_t MlmeIndication; 00371 00372 /*! 00373 * LoRaMac tx/rx operation state 00374 */ 00375 volatile LoRaMacFlags_t LoRaMacFlags; 00376 00377 /*! 00378 * \brief This function prepares the MAC to abort the execution of function 00379 * OnRadioRxDone in case of a reception error. 00380 */ 00381 static void PrepareRxDoneAbort( void ); 00382 00383 /*! 00384 * \brief Function executed on Radio Tx Timeout event 00385 */ 00386 static void OnRadioTxTimeout( void ); 00387 00388 /*! 00389 * \brief Function executed on Radio Rx error event 00390 */ 00391 static void OnRadioRxError( void ); 00392 00393 /*! 00394 * \brief Function executed on Radio Rx Timeout event 00395 */ 00396 static void OnRadioRxTimeout( void ); 00397 00398 /*! 00399 * \brief Function executed on AckTimeout timer event 00400 */ 00401 static void OnAckTimeoutTimerEvent( void ); 00402 00403 /*! 00404 * \brief Adds a new MAC command to be sent. 00405 * 00406 * \Remark MAC layer internal function 00407 * 00408 * \param [in] cmd MAC command to be added 00409 * [MOTE_MAC_LINK_CHECK_REQ, 00410 * MOTE_MAC_LINK_ADR_ANS, 00411 * MOTE_MAC_DUTY_CYCLE_ANS, 00412 * MOTE_MAC_RX2_PARAM_SET_ANS, 00413 * MOTE_MAC_DEV_STATUS_ANS 00414 * MOTE_MAC_NEW_CHANNEL_ANS] 00415 * \param [in] p1 1st parameter ( optional depends on the command ) 00416 * \param [in] p2 2nd parameter ( optional depends on the command ) 00417 * 00418 * \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full] 00419 */ 00420 static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ); 00421 00422 /*! 00423 * \brief Parses the MAC commands which must be repeated. 00424 * 00425 * \Remark MAC layer internal function 00426 * 00427 * \param [IN] cmdBufIn Buffer which stores the MAC commands to send 00428 * \param [IN] length Length of the input buffer to parse 00429 * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be 00430 * repeated. 00431 * 00432 * \retval Size of the MAC commands to repeat. 00433 */ 00434 static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ); 00435 00436 /*! 00437 * \brief Verifies, if a value is in a given range. 00438 * 00439 * \param value Value to verify, if it is in range 00440 * 00441 * \param min Minimum possible value 00442 * 00443 * \param max Maximum possible value 00444 * 00445 * \retval Returns the maximum valid tx power 00446 */ 00447 static bool ValueInRange( int8_t value, int8_t min, int8_t max ); 00448 00449 00450 /*! 00451 * \brief Decodes MAC commands in the fOpts field and in the payload 00452 */ 00453 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ); 00454 00455 /*! 00456 * \brief LoRaMAC layer generic send frame 00457 * 00458 * \param [IN] macHdr MAC header field 00459 * \param [IN] fPort MAC payload port 00460 * \param [IN] fBuffer MAC data buffer to be sent 00461 * \param [IN] fBufferSize MAC data buffer size 00462 * \retval status Status of the operation. 00463 */ 00464 LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); 00465 00466 /*! 00467 * \brief LoRaMAC layer frame buffer initialization 00468 * 00469 * \param [IN] macHdr MAC header field 00470 * \param [IN] fCtrl MAC frame control field 00471 * \param [IN] fOpts MAC commands buffer 00472 * \param [IN] fPort MAC payload port 00473 * \param [IN] fBuffer MAC data buffer to be sent 00474 * \param [IN] fBufferSize MAC data buffer size 00475 * \retval status Status of the operation. 00476 */ 00477 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); 00478 00479 /*! 00480 * \brief Sets the radio in continuous transmission mode 00481 * 00482 * \remark Uses the radio parameters set on the previous transmission. 00483 * 00484 * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode 00485 * \retval status Status of the operation. 00486 */ 00487 LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ); 00488 00489 /*! 00490 * \brief Sets the radio in continuous transmission mode 00491 * 00492 * \remark Uses the radio parameters set on the previous transmission. 00493 * 00494 * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode 00495 * \param [IN] frequency RF frequency to be set. 00496 * \param [IN] power RF ouptput power to be set. 00497 * \retval status Status of the operation. 00498 */ 00499 LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power ); 00500 00501 #ifdef SX127x_H 00502 void printLoraIrqs(bool clear) 00503 { 00504 pc_printf("\r\nIrqFlags:"); 00505 if (Radio::lora.RegIrqFlags.bits.CadDetected) 00506 pc_printf("CadDetected "); 00507 if (Radio::lora.RegIrqFlags.bits.FhssChangeChannel) { 00508 pc_printf("FhssChangeChannel:%d ", Radio::lora.RegHopChannel.bits.FhssPresentChannel); 00509 } 00510 if (Radio::lora.RegIrqFlags.bits.CadDone) 00511 pc_printf("CadDone "); 00512 if (Radio::lora.RegIrqFlags.bits.TxDone) 00513 pc_printf("TxDone-dio0:%d ", Radio::radio.dio0.read()); 00514 if (Radio::lora.RegIrqFlags.bits.ValidHeader) 00515 pc_printf("[42mValidHeader[0m "); 00516 if (Radio::lora.RegIrqFlags.bits.PayloadCrcError) 00517 pc_printf("[41mPayloadCrcError[0m "); 00518 if (Radio::lora.RegIrqFlags.bits.RxDone) 00519 pc_printf("[42mRxDone[0m "); 00520 if (Radio::lora.RegIrqFlags.bits.RxTimeout) 00521 pc_printf("RxTimeout "); 00522 00523 pc_printf("\r\n"); 00524 00525 if (clear) 00526 Radio::radio.write_reg(REG_LR_IRQFLAGS, Radio::lora.RegIrqFlags.octet); 00527 } 00528 00529 void printOpMode() 00530 { 00531 Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE); 00532 switch (Radio::radio.RegOpMode.bits.Mode) { 00533 case RF_OPMODE_SLEEP: pc_printf("[7msleep[0m"); break; 00534 case RF_OPMODE_STANDBY: pc_printf("[7mstby[0m"); break; 00535 case RF_OPMODE_SYNTHESIZER_TX: pc_printf("[33mfstx[0m"); break; 00536 case RF_OPMODE_TRANSMITTER: pc_printf("[31mtx[0m"); break; 00537 case RF_OPMODE_SYNTHESIZER_RX: pc_printf("[33mfsrx[0m"); break; 00538 case RF_OPMODE_RECEIVER: pc_printf("[32mrx[0m"); break; 00539 case 6: 00540 if (Radio::radio.RegOpMode.bits.LongRangeMode) 00541 pc_printf("[42mrxs[0m"); 00542 else 00543 pc_printf("-6-"); 00544 break; // todo: different lora/fsk 00545 case 7: 00546 if (Radio::radio.RegOpMode.bits.LongRangeMode) 00547 pc_printf("[45mcad[0m"); 00548 else 00549 pc_printf("-7-"); 00550 break; // todo: different lora/fsk 00551 } 00552 } 00553 #endif /* SX127x_H */ 00554 00555 /*! 00556 * \brief Resets MAC specific parameters to default 00557 */ 00558 static void ResetMacParameters( void ); 00559 00560 void 00561 loramac_print_status() 00562 { 00563 int until_beacon = BeaconCtx.rx_setup_at.time_since_epoch().count() - LowPowerClock::now().time_since_epoch().count(); 00564 mac_printf("until_beacon:%d ", until_beacon); 00565 mac_printf("DR%u=sf%u guard:%d\r\n", 00566 LoRaMacParams.ChannelsDatarate_fixed , 00567 Datarates[LoRaMacParams.ChannelsDatarate_fixed ], 00568 BeaconCtx.guard 00569 ); 00570 #ifdef SX128x_H 00571 status_t status; 00572 Radio::radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet); 00573 switch (status.bits.cmdStatus) { 00574 case 1: pc_printf("success"); break; 00575 case 2: pc_printf("dataAvail"); break; 00576 case 3: pc_printf("cmdTimeout"); break; 00577 case 4: pc_printf("cmdErr"); break; 00578 case 5: pc_printf("exeFail"); break; 00579 case 6: pc_printf("txdone"); break; 00580 default: pc_printf("cmdStatus:<%u>", status.bits.cmdStatus); break; 00581 } 00582 pc_printf(" "); 00583 switch (status.bits.chipMode) { 00584 case 2: pc_printf("stdby_rc"); break; 00585 case 3: pc_printf("stdby_xosc"); break; 00586 case 4: pc_printf("fs"); break; 00587 case 5: pc_printf("\e[32mrx\e[0m"); break; 00588 case 6: pc_printf("\e[31mtx\e[0m"); break; 00589 default: pc_printf("chipMode:<%u>", status.bits.chipMode); break; 00590 } 00591 LoRaPktPar0_t LoRaPktPar0; 00592 LoRaPktPar0.octet = Radio::radio.readReg(REG_ADDR_LORA_PKTPAR0, 1); 00593 pc_printf(" bw:%u sf%u ", LoRaPktPar0.bits.modem_bw, LoRaPktPar0.bits.modem_sf); 00594 mac_printf("loraSync:%04x\r\n", Radio::radio.readReg(REG_ADDR_LORA_SYNC, 2)); 00595 #elif defined(SX127x_H) 00596 Radio::radio.RegPaConfig.octet = Radio::radio.read_reg(REG_PACONFIG); 00597 if (Radio::radio.RegPaConfig.bits.PaSelect) 00598 pc_printf("PA_BOOST "); 00599 else 00600 pc_printf("RFO "); 00601 00602 Radio::radio.RegOpMode.octet = Radio::radio.read_reg(REG_OPMODE); 00603 pc_printf("%.3fMHz sf%ubw%u ", Radio::radio.get_frf_MHz(), Radio::lora.getSf(), Radio::lora.getBw()); 00604 pc_printf("dio0pin:%u ", Radio::radio.dio0.read()); 00605 printOpMode(); 00606 if (!Radio::radio.RegOpMode.bits.LongRangeMode) { 00607 pc_printf("FSK\r\n"); 00608 return; 00609 } 00610 00611 Radio::lora.RegIrqFlags.octet = Radio::radio.read_reg(REG_LR_IRQFLAGS); 00612 printLoraIrqs(false); 00613 00614 Radio::lora.RegTest33.octet = Radio::radio.read_reg(REG_LR_TEST33); // invert_i_q 00615 Radio::lora.RegDriftInvert.octet = Radio::radio.read_reg(REG_LR_DRIFT_INVERT); 00616 pc_printf("modemstat:%02x, rxinv:%x,%x\r\n", Radio::radio.read_reg(REG_LR_MODEMSTAT), Radio::lora.RegTest33.octet, Radio::lora.RegDriftInvert.octet); 00617 Radio::radio.RegDioMapping1.octet = Radio::radio.read_reg(REG_DIOMAPPING1); 00618 pc_printf("\r\ndio0map:%u\r\n", Radio::radio.RegDioMapping1.bits.Dio0Mapping); 00619 pc_printf("FIfoAddrPtr:%02x RxBase:%02x\r\n", Radio::radio.read_reg(REG_LR_FIFOADDRPTR), Radio::radio.read_reg(REG_LR_FIFORXBASEADDR)); 00620 #elif defined(SX126x_H) 00621 status_t status; 00622 Radio::radio.xfer(OPCODE_GET_STATUS, 0, 1, &status.octet); 00623 switch (status.bits.chipMode) { 00624 case 2: mac_printf("STBY_RC"); break; 00625 case 3: mac_printf("STBY_XOSC"); break; 00626 case 4: mac_printf("FS"); break; 00627 case 5: mac_printf("RX"); break; 00628 case 6: mac_printf("TX"); break; 00629 default: mac_printf("%u", status.bits.chipMode); break; 00630 } 00631 pc_printf(" "); 00632 switch (status.bits.cmdStatus) { 00633 case 1: mac_printf("rfu"); break; 00634 case 2: mac_printf("dataAvail"); break; 00635 case 3: mac_printf("timeout"); break; 00636 case 4: mac_printf("err"); break; 00637 case 5: mac_printf("fail"); break; 00638 case 6: mac_printf("txdone"); break; 00639 default: mac_printf("%u", status.bits.cmdStatus); break; 00640 } 00641 loraConfig0_t conf0; 00642 conf0.octet = Radio::radio.readReg(REG_ADDR_LORA_CONFIG0, 1); 00643 // bw7=125 bw8=250 b9=500 00644 mac_printf(" bw:%u sf%u\r\n", conf0.bits.modem_bw, conf0.bits.modem_sf); 00645 loraConfig1_t conf1; 00646 conf1.octet = Radio::radio.readReg(REG_ADDR_LORA_CONFIG1, 1); 00647 mac_printf("inviq:%u cr%u\r\n", conf1.bits.rx_invert_iq, conf1.bits.tx_coding_rate); 00648 mac_printf("loraSync:%04x\r\n", Radio::radio.readReg(REG_ADDR_LORA_SYNC, 2)); 00649 #endif /* ..SX126x_H */ 00650 } 00651 00652 static void RxWindowSetup( uint32_t freq, int8_t datarate, uint16_t timeout, bool rxContinuous ) 00653 { 00654 uint8_t downlinkDatarate = Datarates[datarate]; 00655 00656 Radio::SetChannel( freq ); 00657 00658 // Store downlink datarate 00659 McpsIndication.RxDatarate = ( uint8_t ) datarate; 00660 00661 Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, downlinkDatarate, 1); 00662 00663 // preambleLen, fixLen, crcOn, invIQ 00664 Radio::LoRaPacketConfig(PREAMBLE_SYMBS, false, false, true); 00665 Radio::SetLoRaSymbolTimeout(timeout); 00666 Radio::SetRxMaxPayloadLength(LORAMAC_PHY_MAXPAYLOAD); 00667 00668 } // ..RxWindowSetup() 00669 00670 static void OnRxWindowTimerEvent( void ) 00671 { 00672 RxWindowSetup(Channels[Channel].Frequency, RxWindowsParam.Datarate, RxWindowsParam.RxWindowTimeout, false); 00673 Radio::Rx( LoRaMacParams.MaxRxWindow ); 00674 } 00675 00676 static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError ); 00677 00678 LowPowerClock::time_point rxto_irqAt; 00679 00680 static void OnRadioTxDone_topHalf() 00681 { 00682 rxto_irqAt = LowPowerClock::now(); 00683 } 00684 00685 static void OnRadioTxDone_bh() 00686 { 00687 // Setup timers 00688 if (IsRxWindowsEnabled) 00689 { 00690 rx_timeout_setAt = rxto_irqAt + RxWindowDelay_us; 00691 rx_timeout.attach_absolute(&OnRxWindowTimerEvent, rx_timeout_setAt); 00692 if (LoRaMacFlags.Bits.NodeAckRequested) 00693 { 00694 microseconds us(ACK_TIMEOUT_us + randr(-ACK_TIMEOUT_RND_us, ACK_TIMEOUT_RND_us)); 00695 us += RxWindowDelay_us; 00696 AckTimeoutTimer.attach(&OnAckTimeoutTimerEvent, us - mcu_wakeup_latency); 00697 } 00698 } 00699 else 00700 { 00701 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 00702 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; 00703 00704 if( LoRaMacFlags.Value == 0 ) 00705 { 00706 LoRaMacFlags.Bits.McpsReq = 1; 00707 } 00708 LoRaMacFlags.Bits.MacDone = 1; 00709 } 00710 00711 if (!LoRaMacFlags.Bits.NodeAckRequested) 00712 { 00713 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 00714 ChannelsNbRepCounter++; 00715 } 00716 00717 MlmeIndication.MlmeIndication = MLME_TXDONE; 00718 MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 00719 LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); 00720 00721 Radio::Standby( ); 00722 00723 txDoneAt = Radio::irqAt /*+ lpt_offset*/; 00724 } 00725 00726 00727 static void application_callbacks() 00728 { 00729 if (LoRaMacFlags.Bits.McpsInd ) { 00730 LoRaMacFlags.Bits.McpsInd = 0; 00731 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); 00732 } 00733 00734 if (LoRaMacFlags.Bits.McpsReq ) { 00735 LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm ); 00736 LoRaMacFlags.Bits.McpsReq = 0; 00737 } 00738 } 00739 00740 static void PrepareRxDoneAbort( void ) 00741 { 00742 if (LoRaMacFlags.Bits.NodeAckRequested) 00743 { 00744 OnAckTimeoutTimerEvent( ); 00745 } 00746 00747 LoRaMacFlags.Bits.McpsInd = 1; 00748 LoRaMacFlags.Bits.MacDone = 1; 00749 00750 application_callbacks(); 00751 } 00752 00753 void send_bh() 00754 { 00755 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_SEND; 00756 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_SEND; 00757 McpsConfirm.TxPower = LoRaMacParams.ChannelsTxPower ; 00758 McpsConfirm.UpLinkFrequency = Channels[Channel].Frequency ; 00759 00760 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) // joining is channel hunting 00761 Radio::SetChannel( Channels[Channel].Frequency ); 00762 00763 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) 00764 { 00765 JoinRequestTrials++; 00766 mac_printf("join %luhz try%u DR%u\r\n", Channels[Channel].Frequency, JoinRequestTrials, LoRaMacParams.ChannelsDatarate_fixed ); 00767 } 00768 00769 Radio::set_tx_dbm(TxPowers[LoRaMacParams.ChannelsTxPower ]); 00770 Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, Datarates[LoRaMacParams.ChannelsDatarate_fixed ], 1); 00771 00772 // preambleLen, fixLen, crcOn, invIQ 00773 Radio::LoRaPacketConfig(PREAMBLE_SYMBS, false, true, false); 00774 Radio::Send(tx_buf_len, 0, 0, 0); 00775 00776 LoRaMacFlags.Bits.uplink_pending = 0; // sent 00777 00778 // Compute Rx1 windows parameters, taken at TxDone 00779 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) { 00780 microseconds us(LoRaMacParams.JoinAcceptDelay_us - TARGET_PRECESSION_us); 00781 RxWindowDelay_us = us - mcu_wakeup_latency; 00782 } else { 00783 microseconds us(LoRaMacParams.ReceiveDelay_us - TARGET_PRECESSION_us); 00784 RxWindowDelay_us = us - mcu_wakeup_latency; 00785 } 00786 00787 } // ..send_bh() 00788 00789 void send_callback() 00790 { 00791 LowPowerClock::time_point now = BeaconCtx.sendAt + BeaconCtx.lastSendAtErr; 00792 00793 if (BeaconCtx.guard) { 00794 /* last send, this will be restarted after beacon sent */ 00795 return; 00796 } 00797 BeaconCtx.sendOpportunities++; 00798 00799 microseconds ping_slot_us(BeaconCtx.periodicity_slots * PING_SLOT_RESOLUTION_us); 00800 BeaconCtx.sendAt += ping_slot_us; 00801 if (BeaconCtx.state == BEACON_STATE_LOCKED) { 00802 float sinceBeacon = now.time_since_epoch().count() - BeaconCtx.LastBeaconRxAt.time_since_epoch().count(); 00803 float ratio = sinceBeacon / BEACON_INTERVAL_us; 00804 microseconds duration_err_us((int)(BeaconCtx.last_BeaconRxTimerError_us * ratio)); 00805 tx_timeout.attach_absolute(&send_callback, BeaconCtx.sendAt + duration_err_us - mcu_wakeup_latency); 00806 BeaconCtx.lastSendAtErr = duration_err_us; 00807 } else { 00808 microseconds duration_err_us(0); 00809 tx_timeout.attach_absolute(&send_callback, BeaconCtx.sendAt - mcu_wakeup_latency); 00810 BeaconCtx.lastSendAtErr = duration_err_us; 00811 } 00812 00813 if (LoRaMacFlags.Bits.uplink_pending) { 00814 us_timestamp_t untilGuard = (BeaconCtx.rx_setup_at.time_since_epoch().count() - BEACON_GUARD_us) - LowPowerClock::now().time_since_epoch().count(); 00815 if (untilGuard > (RECEIVE_DELAY_us + TARGET_PRECESSION_us)) 00816 LoRaMacFlags.Bits.send = 1; 00817 } 00818 } 00819 00820 void OnRxBeaconSetup() 00821 { 00822 BeaconCtx.guard = false; 00823 LoRaMacFlags.Bits.expecting_beacon = true; 00824 00825 Radio::Rx(2000); 00826 00827 BeaconCtx.lastSendAtErr = microseconds(0); 00828 } 00829 00830 void guard_callback() 00831 { 00832 BeaconCtx.guard = true; 00833 Radio::Standby( ); 00834 Radio::SetChannel( Channels[Channel].Frequency ); 00835 00836 tx_timeout.detach(); 00837 mac_printf("sendOpportunities:%u\r\n", BeaconCtx.sendOpportunities); 00838 BeaconCtx.sendOpportunities = 0; 00839 00840 // preambleLen, fixLen, crcOn, invIQ 00841 Radio::LoRaPacketConfig(PREAMBLE_SYMBS, true, false, false); 00842 Radio::LoRaModemConfig(LORA_BANDWIDTH_KHZ, Datarates[BEACON_CHANNEL_DR], 1); 00843 Radio::SetFixedPayloadLength(BEACON_SIZE); 00844 00845 #ifdef SX128x_H 00846 /* explicit to implicit header: does sx1280 really need this a 2nd time? */ 00847 // preambleLen, fixLen, crcOn, invIQ 00848 Radio::LoRaPacketConfig(PREAMBLE_SYMBS, true, false, false); 00849 #endif /* SX128x_H */ 00850 Radio::SetLoRaSymbolTimeout(BeaconCtx.nSymbsTimeout); 00851 } 00852 00853 static void us_to_nSymbTimeout(unsigned us) 00854 { 00855 mac_printf("symTo:%u ", us); 00856 BeaconCtx.nSymbsTimeout = us / BeaconCtx.symbol_period_us; 00857 if (BeaconCtx.nSymbsTimeout < (MIN_SYMBOL_TIMEOUT+BeaconCtx.Precess_symbols)) { 00858 BeaconCtx.nSymbsTimeout = MIN_SYMBOL_TIMEOUT+BeaconCtx.Precess_symbols; 00859 } else if (BeaconCtx.nSymbsTimeout > 255) 00860 BeaconCtx.nSymbsTimeout = 255; 00861 00862 BeaconCtx.SymbolTimeout_us = BeaconCtx.nSymbsTimeout * BeaconCtx.symbol_period_us; 00863 mac_printf("%u\r\n", BeaconCtx.nSymbsTimeout); 00864 } 00865 00866 static uint16_t beacon_crc( uint8_t *buffer, uint16_t length ) 00867 { 00868 // The CRC calculation follows CCITT 00869 const uint16_t polynom = 0x1021; 00870 // CRC initial value 00871 uint16_t crc = 0x0000; 00872 00873 if( buffer == NULL ) 00874 { 00875 return 0; 00876 } 00877 00878 for( uint16_t i = 0; i < length; ++i ) 00879 { 00880 crc ^= ( uint16_t ) buffer[i] << 8; 00881 for( uint16_t j = 0; j < 8; ++j ) 00882 { 00883 crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); 00884 } 00885 } 00886 00887 return crc; 00888 } 00889 00890 void rx_beacon(uint16_t size) 00891 { 00892 static bool compensate_precession = false; 00893 int32_t compensation = 0; 00894 /* have beacon end, need beacon start */ 00895 microseconds beacon_start_offset_us(BeaconCtx.beaconStartToRxDone); 00896 LowPowerClock::time_point ThisBeaconRxAt = Radio::irqAt - beacon_start_offset_us; 00897 00898 BeaconCtx.num_consecutive_ok++; 00899 mac_printf("rx_beacon %llu ", Radio::irqAt.time_since_epoch().count()); 00900 BeaconCtx.rx_precession_us = ThisBeaconRxAt.time_since_epoch().count() - BeaconCtx.rx_setup_at.time_since_epoch().count(); 00901 if (BeaconCtx.state != BEACON_STATE_FIRST_ACQ) { 00902 BeaconCtx.known_working_BeaconRxTimerError_us = BeaconCtx.last_BeaconRxTimerError_us; 00903 BeaconCtx.last_BeaconRxTimerError_us = (ThisBeaconRxAt.time_since_epoch().count() - BeaconCtx.LastBeaconRxAt.time_since_epoch().count()) - (BEACON_INTERVAL_us * (BeaconCtx.num_missed+1)); 00904 00905 if (BeaconCtx.num_missed > 0) { 00906 /* Timer error is measured over more than one beacon period. 00907 * Scale to error seen over single beacon period */ 00908 BeaconCtx.last_BeaconRxTimerError_us /= BeaconCtx.num_missed + 1; 00909 } 00910 00911 if (BeaconCtx.state == BEACON_STATE_ACQ_ERROR) { 00912 mac_printf("-->LOCKED "); 00913 BeaconCtx.state = BEACON_STATE_LOCKED; 00914 compensate_precession = true; 00915 } 00916 } else { 00917 /* ignore precession at first acquisition because it has slot resolution added */ 00918 mac_printf("-->ACQ_ERROR "); 00919 // next beacon will give us our crystal error 00920 BeaconCtx.state = BEACON_STATE_ACQ_ERROR; 00921 } 00922 00923 mac_printf("err%d=%llu-%llu ", BeaconCtx.last_BeaconRxTimerError_us, ThisBeaconRxAt.time_since_epoch().count(), BeaconCtx.LastBeaconRxAt.time_since_epoch().count()); 00924 if (BeaconCtx.num_missed > 0) 00925 mac_printf("missed%u ", BeaconCtx.num_missed); 00926 00927 mac_printf(" rx-before-tx:%d ", BeaconCtx.rx_precession_us); 00928 if (BeaconCtx.last_BeaconRxTimerError_us > 40000 || BeaconCtx.last_BeaconRxTimerError_us < -40000) { 00929 BeaconCtx.timeout_rx.detach(); 00930 BeaconCtx.timeout_guard.detach(); 00931 mac_printf("halt\r\n"); 00932 for (;;) asm("nop"); 00933 } 00934 BeaconCtx.LastBeaconRxAt = ThisBeaconRxAt; 00935 00936 if (BeaconCtx.state == BEACON_STATE_LOCKED) { 00937 if (compensate_precession) { 00938 compensation = BeaconCtx.rx_precession_us - TARGET_PRECESSION_us + BeaconCtx.last_BeaconRxTimerError_us; 00939 mac_printf(" comp%ld", compensation); 00940 } 00941 } 00942 00943 // reference tick for uplink schedule: when gateway started beacon 00944 microseconds send_offset_us(BeaconCtx.rx_precession_us + (BeaconCtx.tx_slot_offset * PING_SLOT_RESOLUTION_us)); 00945 BeaconCtx.sendAt = BeaconCtx.rx_setup_at + send_offset_us; 00946 tx_timeout.attach_absolute(&send_callback, BeaconCtx.sendAt - mcu_wakeup_latency); 00947 mac_printf("sendAt:%llu ", BeaconCtx.sendAt.time_since_epoch().count()); 00948 00949 microseconds us_to_next_beacon(BEACON_INTERVAL_us + compensation); 00950 BeaconCtx.rx_setup_at += us_to_next_beacon; 00951 00952 BeaconCtx.timeout_rx.attach_absolute(&OnRxBeaconSetup, BeaconCtx.rx_setup_at - mcu_wakeup_latency); 00953 microseconds beacon_guard_us(BEACON_GUARD_us); 00954 BeaconCtx.timeout_guard.attach_absolute(&guard_callback, BeaconCtx.rx_setup_at - beacon_guard_us - mcu_wakeup_latency); 00955 00956 BeaconCtx.num_missed = 0; 00957 00958 MlmeIndication.MlmeIndication = MLME_BEACON; 00959 MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED; 00960 LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); 00961 00962 /* check beacon payload */ 00963 uint16_t calc_crc = beacon_crc(Radio::radio.rx_buf, 4); 00964 uint16_t rx_crc = Radio::radio.rx_buf[4]; 00965 rx_crc |= Radio::radio.rx_buf[5] << 8; 00966 if (rx_crc == calc_crc) { 00967 unsigned int rx = Radio::radio.rx_buf[0]; 00968 rx |= Radio::radio.rx_buf[1] << 8; 00969 rx |= Radio::radio.rx_buf[2] << 16; 00970 rx |= Radio::radio.rx_buf[3] << 24; 00971 if (rx != 0) { 00972 McpsIndication.McpsIndication = MCPS_MULTICAST; 00973 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 00974 McpsIndication.Buffer = Radio::radio.rx_buf; 00975 McpsIndication.BufferSize = 4; 00976 McpsIndication.RxData = true; 00977 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); 00978 } 00979 } else 00980 mac_printf("calc_crc:%04x rx_crc:%04x\r\n", calc_crc, rx_crc); 00981 } // ..rx_beacon() 00982 00983 00984 #define JOIN_ACCEPT_MAX_SIZE 34 00985 static void OnRadioRxDone(uint8_t size, float rssi, float snr ) 00986 { 00987 uint8_t _jaDecrypted[JOIN_ACCEPT_MAX_SIZE]; 00988 LoRaMacHeader_t macHdr; 00989 LoRaMacFrameCtrl_t fCtrl; 00990 bool skipIndication = false; 00991 00992 uint8_t pktHeaderLen = 0; 00993 uint32_t address = 0; 00994 uint8_t appPayloadStartIndex = 0; 00995 uint8_t port = 0xFF; 00996 uint8_t frameLen = 0; 00997 uint32_t mic = 0; 00998 uint32_t micRx = 0; 00999 01000 uint16_t sequenceCounter = 0; 01001 uint16_t sequenceCounterPrev = 0; 01002 uint16_t sequenceCounterDiff = 0; 01003 uint32_t downLinkCounter = 0; 01004 01005 MulticastParams_t *curMulticastParams = NULL; 01006 uint8_t *nwkSKey = LoRaMacNwkSKey; 01007 uint8_t *appSKey = LoRaMacAppSKey; 01008 01009 uint8_t multicast = 0; 01010 01011 bool isMicOk = false; 01012 01013 McpsConfirm.AckReceived = false; 01014 McpsIndication.Rssi = rssi; 01015 McpsIndication.Snr = snr; 01016 McpsIndication.Port = 0; 01017 McpsIndication.Multicast = 0; 01018 McpsIndication.FramePending = 0; 01019 McpsIndication.Buffer = NULL; 01020 McpsIndication.BufferSize = 0; 01021 McpsIndication.RxData = false; 01022 McpsIndication.AckReceived = false; 01023 McpsIndication.DownLinkCounter = 0; 01024 McpsIndication.McpsIndication = MCPS_UNCONFIRMED; 01025 01026 Radio::Sleep( ); 01027 01028 if (LoRaMacFlags.Bits.expecting_beacon) { 01029 rx_beacon(size); 01030 LoRaMacFlags.Bits.expecting_beacon = false; 01031 return; 01032 } 01033 01034 macHdr.Value = Radio::radio.rx_buf[pktHeaderLen++]; 01035 01036 switch( macHdr.Bits.MType ) 01037 { 01038 case FRAME_TYPE_JOIN_ACCEPT: 01039 if (LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) 01040 { 01041 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_JOIN_ACCEPT; 01042 PrepareRxDoneAbort( ); 01043 return; 01044 } 01045 LoRaMacJoinDecrypt ( Radio::radio.rx_buf + 1, size - 1, LoRaMacAppKey, &_jaDecrypted[1]); 01046 01047 _jaDecrypted[0] = macHdr.Value ; 01048 01049 LoRaMacJoinComputeMic ( _jaDecrypted, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic ); 01050 01051 micRx |= ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN]; 01052 micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 1] << 8 ); 01053 micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 2] << 16 ); 01054 micRx |= ( ( uint32_t )_jaDecrypted[size - LORAMAC_MFR_LEN + 3] << 24 ); 01055 01056 if( micRx == mic ) 01057 { 01058 uint32_t beaconDur; 01059 LoRaMacJoinComputeSKeys ( LoRaMacAppKey, _jaDecrypted + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey ); 01060 01061 LoRaMacNetID = ( uint32_t )_jaDecrypted[4]; 01062 LoRaMacNetID |= ( ( uint32_t )_jaDecrypted[5] << 8 ); 01063 LoRaMacNetID |= ( ( uint32_t )_jaDecrypted[6] << 16 ); 01064 01065 LoRaMacDevAddr = ( uint32_t )_jaDecrypted[7]; 01066 LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[8] << 8 ); 01067 LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[9] << 16 ); 01068 LoRaMacDevAddr |= ( ( uint32_t )_jaDecrypted[10] << 24 ); 01069 01070 // DLSettings 01071 LoRaMacParams.Rx1DrOffset = ( _jaDecrypted[11] >> 4 ) & 0x07; 01072 01073 LoRaMacParams.ReceiveDelay_us = ( _jaDecrypted[12] & 0x0F ); 01074 if( LoRaMacParams.ReceiveDelay_us == 0 ) 01075 LoRaMacParams.ReceiveDelay_us = RECEIVE_DELAY_us; 01076 else 01077 LoRaMacParams.ReceiveDelay_us *= 10; 01078 01079 uint16_t beaconTimingDelay = _jaDecrypted[13] & 0xff; 01080 beaconTimingDelay |= _jaDecrypted[14] << 8; 01081 01082 mac_printf("%lx slots:%x (rxdelay %lu)", LoRaMacDevAddr, beaconTimingDelay, LoRaMacParams.ReceiveDelay_us); 01083 { 01084 unsigned us_to_beacon = ( PING_SLOT_RESOLUTION_us * beaconTimingDelay ); 01085 mac_printf(" us_to_beacon:%u ", us_to_beacon); 01086 // time to beacon given as referenced to end of join request uplink 01087 microseconds tx_done_to_rx_start_us(us_to_beacon - PPM_BEACON_INTERVAL); 01088 BeaconCtx.rx_setup_at = txDoneAt + tx_done_to_rx_start_us; 01089 BeaconCtx.timeout_rx.attach_absolute(&OnRxBeaconSetup, BeaconCtx.rx_setup_at - mcu_wakeup_latency); 01090 microseconds beacon_guard_us(BEACON_GUARD_us); 01091 BeaconCtx.timeout_guard.attach_absolute(&guard_callback, BeaconCtx.rx_setup_at - (beacon_guard_us + mcu_wakeup_latency)); 01092 01093 mac_printf("beaconIn:%llu\r\n", BeaconCtx.rx_setup_at.time_since_epoch().count() - LowPowerClock::now().time_since_epoch().count()); 01094 } 01095 01096 BeaconCtx.tx_slot_offset = _jaDecrypted[15]; 01097 BeaconCtx.tx_slot_offset |= _jaDecrypted[16] << 8; 01098 BeaconCtx.periodicity_slots = _jaDecrypted[17]; 01099 BeaconCtx.periodicity_slots |= _jaDecrypted[18] << 8; 01100 01101 beaconDur = _jaDecrypted[22]; 01102 beaconDur <<= 8; 01103 beaconDur |= _jaDecrypted[21]; 01104 beaconDur <<= 8; 01105 beaconDur |= _jaDecrypted[20]; 01106 beaconDur <<= 8; 01107 beaconDur |= _jaDecrypted[19]; 01108 BeaconCtx.beaconStartToRxDone = beaconDur + (rxLatencyFactorFromSF[SF_FROM_DR_(LORAMAC_DEFAULT_DATARATE)-FASTEST_SF] * BeaconCtx.symbol_period_us); 01109 01110 01111 /* nowSlot: now vs previous beacon */ 01112 microseconds beacon_interval_us(BEACON_INTERVAL_us); 01113 BeaconCtx.LastBeaconRxAt = BeaconCtx.rx_setup_at - beacon_interval_us; 01114 unsigned us_since_last_beacon = LowPowerClock::now().time_since_epoch().count() - BeaconCtx.LastBeaconRxAt.time_since_epoch().count(); 01115 unsigned nowSlot = us_since_last_beacon / PING_SLOT_RESOLUTION_us; 01116 unsigned useSlot = BeaconCtx.tx_slot_offset; 01117 while (useSlot < nowSlot) 01118 useSlot += BeaconCtx.periodicity_slots; 01119 01120 mac_printf("beaconDur:0x%lx (%lu) useSlot:%u nowSlot:%u ", beaconDur, BeaconCtx.beaconStartToRxDone, useSlot, nowSlot); 01121 microseconds ping_slot_offset_us(useSlot * PING_SLOT_RESOLUTION_us); 01122 BeaconCtx.sendAt = BeaconCtx.LastBeaconRxAt + ping_slot_offset_us; 01123 01124 mac_printf("sendIn:%lld\r\n", BeaconCtx.sendAt.time_since_epoch().count() - LowPowerClock::now().time_since_epoch().count()); 01125 tx_timeout.attach_absolute(send_callback, BeaconCtx.sendAt - mcu_wakeup_latency); 01126 BeaconCtx.sendOpportunities = 0; 01127 01128 BeaconCtx.state = BEACON_STATE_FIRST_ACQ; 01129 BeaconCtx.guard = false; 01130 BeaconCtx.num_missed = 0; 01131 BeaconCtx.rx_precession_us = 0; 01132 BeaconCtx.num_consecutive_ok = 0; 01133 BeaconCtx.last_BeaconRxTimerError_us = -PPM_BEACON_INTERVAL; 01134 BeaconCtx.known_working_BeaconRxTimerError_us = -PPM_BEACON_INTERVAL; 01135 /* first beacon reception needs to open for 30ms timing resolution */ 01136 BeaconCtx.Precess_symbols = ceil((float)(TARGET_PRECESSION_us / BeaconCtx.symbol_period_us)); 01137 BeaconCtx.SymbolTimeout_us = PING_SLOT_RESOLUTION_us + (PPM_BEACON_INTERVAL * 4); // error unknown at start 01138 BeaconCtx.nSymbsTimeout = BeaconCtx.SymbolTimeout_us / BeaconCtx.symbol_period_us; 01139 if (BeaconCtx.nSymbsTimeout < MIN_SYMBOL_TIMEOUT) 01140 BeaconCtx.nSymbsTimeout = MIN_SYMBOL_TIMEOUT; 01141 else if (BeaconCtx.nSymbsTimeout > 255) 01142 BeaconCtx.nSymbsTimeout = 255; 01143 mac_printf("startSymbTo:%u ", BeaconCtx.nSymbsTimeout); 01144 01145 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01146 LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = true; 01147 LoRaMacParams.ChannelsDatarate_fixed = LoRaMacParamsDefaults.ChannelsDatarate_fixed ; 01148 } 01149 else 01150 { 01151 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; 01152 mac_printf("join-mic-fail size:%u\r\n", size); 01153 JoinRequestTrials = MaxJoinRequestTrials; // stop trying 01154 } 01155 LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); 01156 LoRaMacFlags.Bits.MlmeReq = 0; // MacMlmeConfirm() called 01157 break; 01158 case FRAME_TYPE_DATA_CONFIRMED_DOWN: 01159 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: 01160 { 01161 address = Radio::radio.rx_buf[pktHeaderLen++]; 01162 address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 8 ); 01163 address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 16 ); 01164 address |= ( (uint32_t)Radio::radio.rx_buf[pktHeaderLen++] << 24 ); 01165 01166 if( address != LoRaMacDevAddr ) 01167 { 01168 curMulticastParams = MulticastChannels; 01169 while( curMulticastParams != NULL ) 01170 { 01171 if( address == curMulticastParams->Address ) 01172 { 01173 multicast = 1; 01174 nwkSKey = curMulticastParams->NwkSKey ; 01175 appSKey = curMulticastParams->AppSKey ; 01176 downLinkCounter = curMulticastParams->DownLinkCounter ; 01177 break; 01178 } 01179 curMulticastParams = curMulticastParams->Next ; 01180 } 01181 if( multicast == 0 ) 01182 { 01183 // We are not the destination of this frame. 01184 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL; 01185 PrepareRxDoneAbort( ); 01186 return; 01187 } 01188 } 01189 else 01190 { 01191 multicast = 0; 01192 nwkSKey = LoRaMacNwkSKey; 01193 appSKey = LoRaMacAppSKey; 01194 downLinkCounter = DownLinkCounter; 01195 } 01196 01197 fCtrl.Value = Radio::radio.rx_buf[pktHeaderLen++]; 01198 01199 sequenceCounter = ( uint16_t )Radio::radio.rx_buf[pktHeaderLen++]; 01200 sequenceCounter |= ( uint16_t )Radio::radio.rx_buf[pktHeaderLen++] << 8; 01201 01202 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen ; 01203 01204 micRx |= ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN]; 01205 micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 1] << 8 ); 01206 micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 2] << 16 ); 01207 micRx |= ( ( uint32_t )Radio::radio.rx_buf[size - LORAMAC_MFR_LEN + 3] << 24 ); 01208 01209 sequenceCounterPrev = ( uint16_t )downLinkCounter; 01210 sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev ); 01211 01212 if( sequenceCounterDiff < ( 1 << 15 ) ) 01213 { 01214 downLinkCounter += sequenceCounterDiff; 01215 LoRaMacComputeMic( Radio::radio.rx_buf, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic ); 01216 if( micRx == mic ) 01217 { 01218 isMicOk = true; 01219 } 01220 } 01221 else 01222 { 01223 // check for sequence roll-over 01224 uint32_t downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff; 01225 LoRaMacComputeMic( Radio::radio.rx_buf, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic ); 01226 if( micRx == mic ) 01227 { 01228 isMicOk = true; 01229 downLinkCounter = downLinkCounterTmp; 01230 } 01231 } 01232 01233 // Check for a the maximum allowed counter difference 01234 if( sequenceCounterDiff >= MAX_FCNT_GAP ) 01235 { 01236 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS; 01237 McpsIndication.DownLinkCounter = downLinkCounter; 01238 PrepareRxDoneAbort( ); 01239 return; 01240 } 01241 01242 if( isMicOk == true ) 01243 { 01244 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01245 McpsIndication.Multicast = multicast; 01246 McpsIndication.FramePending = fCtrl.Bits.FPending ; 01247 McpsIndication.Buffer = NULL; 01248 McpsIndication.BufferSize = 0; 01249 McpsIndication.DownLinkCounter = downLinkCounter; 01250 01251 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01252 01253 MacCommandsBufferToRepeatIndex = 0; 01254 01255 // Update 32 bits downlink counter 01256 if( multicast == 1 ) 01257 { 01258 McpsIndication.McpsIndication = MCPS_MULTICAST; 01259 01260 if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) && 01261 ( curMulticastParams->DownLinkCounter != 0 ) ) 01262 { 01263 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; 01264 McpsIndication.DownLinkCounter = downLinkCounter; 01265 PrepareRxDoneAbort( ); 01266 return; 01267 } 01268 curMulticastParams->DownLinkCounter = downLinkCounter; 01269 } 01270 else 01271 { 01272 if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) 01273 { 01274 LoRaMacFlags.Bits.SrvAckRequested = true; 01275 McpsIndication.McpsIndication = MCPS_CONFIRMED; 01276 01277 if( ( DownLinkCounter == downLinkCounter ) && 01278 ( DownLinkCounter != 0 ) ) 01279 { 01280 // Duplicated confirmed downlink. Skip indication. 01281 // In this case, the MAC layer shall accept the MAC commands 01282 // which are included in the downlink retransmission. 01283 // It should not provide the same frame to the application 01284 // layer again. 01285 skipIndication = true; 01286 } 01287 } 01288 else 01289 { 01290 LoRaMacFlags.Bits.SrvAckRequested = false; 01291 McpsIndication.McpsIndication = MCPS_UNCONFIRMED; 01292 01293 if( ( DownLinkCounter == downLinkCounter ) && 01294 ( DownLinkCounter != 0 ) ) 01295 { 01296 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; 01297 McpsIndication.DownLinkCounter = downLinkCounter; 01298 PrepareRxDoneAbort( ); 01299 return; 01300 } 01301 } 01302 DownLinkCounter = downLinkCounter; 01303 } 01304 01305 // This must be done before parsing the payload and the MAC commands. 01306 // We need to reset the MacCommandsBufferIndex here, since we need 01307 // to take retransmissions and repititions into account. Error cases 01308 // will be handled in function OnMacStateCheckTimerEvent. 01309 if( McpsConfirm.McpsRequest == MCPS_CONFIRMED ) 01310 { 01311 if( fCtrl.Bits.Ack == 1 ) 01312 {// Reset MacCommandsBufferIndex when we have received an ACK. 01313 MacCommandsBufferIndex = 0; 01314 } 01315 } 01316 else 01317 {// Reset the variable if we have received any valid frame. 01318 MacCommandsBufferIndex = 0; 01319 } 01320 01321 // Process payload and MAC commands 01322 if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 ) 01323 { 01324 port = Radio::radio.rx_buf[appPayloadStartIndex++]; 01325 frameLen = ( size - 4 ) - appPayloadStartIndex; 01326 01327 McpsIndication.Port = port; 01328 01329 if( port == 0 ) 01330 { 01331 // Only allow frames which do not have fOpts 01332 if( fCtrl.Bits.FOptsLen == 0 ) 01333 { 01334 uint8_t macDecrypt[16]; 01335 LoRaMacPayloadDecrypt ( Radio::radio.rx_buf + appPayloadStartIndex, 01336 frameLen, 01337 nwkSKey, 01338 address, 01339 DOWN_LINK, 01340 downLinkCounter, 01341 macDecrypt); 01342 01343 // Decode frame payload MAC commands 01344 ProcessMacCommands( macDecrypt, 0, frameLen, snr ); 01345 } 01346 else 01347 { 01348 skipIndication = true; 01349 } 01350 } 01351 else 01352 { 01353 if( fCtrl.Bits.FOptsLen > 0 ) 01354 { 01355 // Decode Options field MAC commands. Omit the fPort. 01356 ProcessMacCommands( Radio::radio.rx_buf, 8, appPayloadStartIndex - 1, snr ); 01357 } 01358 01359 LoRaMacPayloadDecrypt ( Radio::radio.rx_buf + appPayloadStartIndex, 01360 frameLen, 01361 appSKey, 01362 address, 01363 DOWN_LINK, 01364 downLinkCounter, 01365 rxFRMPayload); 01366 01367 if( skipIndication == false ) 01368 { 01369 McpsIndication.Buffer = rxFRMPayload; 01370 McpsIndication.BufferSize = frameLen; 01371 McpsIndication.RxData = true; 01372 } 01373 } 01374 } 01375 else 01376 { 01377 if( fCtrl.Bits.FOptsLen > 0 ) 01378 { 01379 // Decode Options field MAC commands 01380 ProcessMacCommands( Radio::radio.rx_buf, 8, appPayloadStartIndex, snr ); 01381 } 01382 } 01383 01384 if( skipIndication == false ) 01385 { 01386 // Check if the frame is an acknowledgement 01387 if( fCtrl.Bits.Ack == 1 ) 01388 { 01389 McpsConfirm.AckReceived = true; 01390 McpsIndication.AckReceived = true; 01391 01392 // Stop the AckTimeout timer as no more retransmissions 01393 // are needed. 01394 } 01395 else 01396 { 01397 McpsConfirm.AckReceived = false; 01398 } 01399 } 01400 // Provide always an indication, skip the callback to the user application, 01401 // in case of a confirmed downlink retransmission. 01402 LoRaMacFlags.Bits.McpsInd = 1; 01403 LoRaMacFlags.Bits.McpsIndSkip = skipIndication; 01404 } 01405 else 01406 { 01407 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; 01408 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; 01409 PrepareRxDoneAbort( ); 01410 return; 01411 } 01412 } 01413 break; 01414 case FRAME_TYPE_PROPRIETARY: 01415 { 01416 McpsIndication.McpsIndication = MCPS_PROPRIETARY; 01417 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01418 McpsIndication.Buffer = Radio::radio.rx_buf; 01419 McpsIndication.BufferSize = size - pktHeaderLen; 01420 01421 LoRaMacFlags.Bits.McpsInd = 1; 01422 break; 01423 } 01424 default: 01425 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE; 01426 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_RX_MTYPE; 01427 mac_printf("%d:macHdr:%02x(%f,%f) ", size, macHdr.Value , rssi, snr); 01428 PrepareRxDoneAbort( ); 01429 break; 01430 } 01431 LoRaMacFlags.Bits.MacDone = 1; 01432 01433 application_callbacks(); 01434 01435 } // ..OnRadioRxDone() 01436 01437 static void OnRadioTxTimeout( void ) 01438 { 01439 Radio::Sleep( ); 01440 01441 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; 01442 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT; 01443 LoRaMacFlags.Bits.MacDone = 1; 01444 } 01445 01446 static void OnRadioRxError( void ) 01447 { 01448 Radio::Sleep( ); 01449 01450 if (LoRaMacFlags.Bits.NodeAckRequested) 01451 { 01452 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR; 01453 } 01454 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_ERROR; 01455 01456 LoRaMacFlags.Bits.MacDone = 1; 01457 } 01458 01459 static void 01460 join_send() 01461 { 01462 LoRaMacFlags.Bits.join_send = 1; 01463 } 01464 01465 static void ScheduleTx( void ) 01466 { 01467 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) 01468 LoRaMacFlags.Bits.send = 1; // immediately send join asychronously 01469 else 01470 LoRaMacFlags.Bits.uplink_pending = 1; // send synchronously 01471 } 01472 01473 static void 01474 join_send_bh() 01475 { 01476 if (JoinRequestTrials < MaxJoinRequestTrials) { 01477 LoRaMacHeader_t macHdr; 01478 LoRaMacFrameCtrl_t fCtrl; 01479 01480 if (++Channel == LORA_MAX_NB_CHANNELS) 01481 Channel = 0; 01482 mac_printf("<join-ch%u>", Channel); 01483 01484 macHdr.Value = 0; 01485 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; 01486 01487 fCtrl.Value = 0; 01488 fCtrl.Bits.Adr = 0; 01489 01490 /* In case of join request retransmissions, the stack must prepare 01491 * the frame again, because the network server keeps track of the random 01492 * LoRaMacDevNonce values to prevent reply attacks. */ 01493 PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); 01494 01495 ScheduleTx(); 01496 } else { 01497 MlmeConfirm.MlmeRequest = MLME_JOIN; 01498 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; 01499 LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); 01500 } 01501 } // ..join_send_bh() 01502 01503 static void OnRadioRxTimeout( void ) 01504 { 01505 Radio::Sleep( ); 01506 01507 pc_printf("OnRadioRxTimeout eb%u\r\n", LoRaMacFlags.Bits.expecting_beacon); 01508 if (LoRaMacFlags.Bits.expecting_beacon) { 01509 float ourErrSecs = BeaconCtx.known_working_BeaconRxTimerError_us / 1000000.0; 01510 01511 LoRaMacFlags.Bits.expecting_beacon = false; 01512 01513 microseconds rx_next_us(BEACON_INTERVAL_us + BeaconCtx.known_working_BeaconRxTimerError_us); 01514 BeaconCtx.rx_setup_at += rx_next_us; 01515 microseconds pre_rx_us(PPM_BEACON_INTERVAL / 4); // come up early when missed 01516 BeaconCtx.rx_setup_at -= pre_rx_us; 01517 us_to_nSymbTimeout(BeaconCtx.SymbolTimeout_us + PPM_BEACON_INTERVAL); 01518 mac_printf("beacon timeout ourErr:%f SymbTo:%u(%uus)\r\n", ourErrSecs, BeaconCtx.nSymbsTimeout, BeaconCtx.SymbolTimeout_us); 01519 01520 BeaconCtx.timeout_rx.attach_absolute(&OnRxBeaconSetup, BeaconCtx.rx_setup_at - mcu_wakeup_latency); 01521 microseconds guard_us(BEACON_GUARD_us); 01522 BeaconCtx.timeout_guard.attach_absolute(&guard_callback, BeaconCtx.rx_setup_at - (guard_us + mcu_wakeup_latency)); 01523 01524 if (++BeaconCtx.num_missed > BEACONS_MISSED_LIMIT) { 01525 LoRaMacFlags.Bits.reJoin = 1; 01526 } else { 01527 MlmeIndication.MlmeIndication = MLME_BEACON; 01528 MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_BEACON_LOST; 01529 LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication ); 01530 } 01531 01532 microseconds base((BEACON_INTERVAL_us + BeaconCtx.known_working_BeaconRxTimerError_us) * BeaconCtx.num_missed); 01533 BeaconCtx.sendAt = BeaconCtx.LastBeaconRxAt + base; 01534 microseconds tx_slot_us(BeaconCtx.tx_slot_offset * PING_SLOT_RESOLUTION_us); 01535 BeaconCtx.sendAt += tx_slot_us; 01536 tx_timeout.attach_absolute(&send_callback, BeaconCtx.sendAt - mcu_wakeup_latency); 01537 01538 BeaconCtx.num_consecutive_ok = 0; 01539 } else { 01540 if (LoRaMacFlags.Bits.MlmeReq && ( MlmeConfirm.MlmeRequest == MLME_JOIN )) { 01541 /* no join accept received: join retry */ 01542 microseconds us((JoinRequestTrials*20000) + randr(0, 70000)); 01543 tx_timeout.attach(&join_send, us - mcu_wakeup_latency); 01544 } 01545 } 01546 01547 if (LoRaMacFlags.Bits.NodeAckRequested) 01548 { 01549 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; 01550 } 01551 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT; 01552 LoRaMacFlags.Bits.MacDone = 1; 01553 01554 application_callbacks(); 01555 } // ..OnRadioRxTimeout(); 01556 01557 static void OnAckTimeoutTimerEvent( void ) 01558 { 01559 } 01560 01561 static bool ValueInRange( int8_t value, int8_t min, int8_t max ) 01562 { 01563 if( ( value >= min ) && ( value <= max ) ) 01564 { 01565 return true; 01566 } 01567 return false; 01568 } 01569 01570 static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) 01571 { 01572 LoRaMacStatus_t status = LORAMAC_STATUS_BUSY; 01573 // The maximum buffer length must take MAC commands to re-send into account. 01574 uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; 01575 01576 switch( cmd ) 01577 { 01578 case MOTE_MAC_LINK_CHECK_REQ: 01579 if( MacCommandsBufferIndex < bufLen ) 01580 { 01581 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 01582 // No payload for this command 01583 status = LORAMAC_STATUS_OK; 01584 } 01585 break; 01586 case MOTE_MAC_RX_PARAM_SETUP_ANS: 01587 if( MacCommandsBufferIndex < ( bufLen - 1 ) ) 01588 { 01589 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 01590 // Status: Datarate ACK, Channel ACK 01591 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 01592 status = LORAMAC_STATUS_OK; 01593 } 01594 break; 01595 case MOTE_MAC_DEV_STATUS_ANS: 01596 if( MacCommandsBufferIndex < ( bufLen - 2 ) ) 01597 { 01598 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 01599 // 1st byte Battery 01600 // 2nd byte Margin 01601 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 01602 MacCommandsBuffer[MacCommandsBufferIndex++] = p2; 01603 status = LORAMAC_STATUS_OK; 01604 } 01605 break; 01606 case MOTE_MAC_RX_TIMING_SETUP_ANS: 01607 if( MacCommandsBufferIndex < bufLen ) 01608 { 01609 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 01610 // No payload for this answer 01611 status = LORAMAC_STATUS_OK; 01612 } 01613 break; 01614 default: 01615 return LORAMAC_STATUS_SERVICE_UNKNOWN; 01616 } 01617 if( status == LORAMAC_STATUS_OK ) 01618 { 01619 MacCommandsInNextTx = true; 01620 } 01621 return status; 01622 } 01623 01624 static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) 01625 { 01626 uint8_t i = 0; 01627 uint8_t cmdCount = 0; 01628 01629 if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) 01630 { 01631 return 0; 01632 } 01633 01634 for( i = 0; i < length; i++ ) 01635 { 01636 switch( cmdBufIn[i] ) 01637 { 01638 // STICKY 01639 case MOTE_MAC_RX_PARAM_SETUP_ANS: 01640 { 01641 cmdBufOut[cmdCount++] = cmdBufIn[i++]; 01642 cmdBufOut[cmdCount++] = cmdBufIn[i]; 01643 break; 01644 } 01645 case MOTE_MAC_RX_TIMING_SETUP_ANS: 01646 { 01647 cmdBufOut[cmdCount++] = cmdBufIn[i]; 01648 break; 01649 } 01650 // NON-STICKY 01651 case MOTE_MAC_DEV_STATUS_ANS: 01652 { // 2 bytes payload 01653 i += 2; 01654 break; 01655 } 01656 case MOTE_MAC_LINK_CHECK_REQ: 01657 { // 0 byte payload 01658 break; 01659 } 01660 default: 01661 break; 01662 } 01663 } 01664 01665 return cmdCount; 01666 } 01667 01668 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ) 01669 { 01670 while( macIndex < commandsSize ) 01671 { 01672 // Decode Frame MAC commands 01673 switch( payload[macIndex++] ) 01674 { 01675 case SRV_MAC_LINK_CHECK_ANS: 01676 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01677 MlmeConfirm.DemodMargin = payload[macIndex++]; 01678 MlmeConfirm.NbGateways = payload[macIndex++]; 01679 break; 01680 case SRV_MAC_DEV_STATUS_REQ: 01681 { 01682 uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE; 01683 if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) ) 01684 { 01685 batteryLevel = LoRaMacCallbacks->GetBatteryLevel( ); 01686 } 01687 AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr ); 01688 break; 01689 } 01690 case SRV_MAC_RX_TIMING_SETUP_REQ: 01691 { 01692 uint8_t delay = payload[macIndex++] & 0x0F; 01693 01694 if( delay == 0 ) 01695 { 01696 delay++; 01697 } 01698 LoRaMacParams.ReceiveDelay_us = delay * 1e6; 01699 AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); 01700 } 01701 break; 01702 default: 01703 // Unknown command. ABORT MAC commands processing 01704 return; 01705 } 01706 } 01707 } 01708 01709 LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) 01710 { 01711 LoRaMacFrameCtrl_t fCtrl; 01712 LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; 01713 01714 fCtrl.Value = 0; 01715 fCtrl.Bits.FOptsLen = 0; 01716 fCtrl.Bits.FPending = 0; 01717 fCtrl.Bits.Ack = false; 01718 fCtrl.Bits.AdrAckReq = false; 01719 fCtrl.Bits.Adr = false; 01720 01721 // Prepare the frame 01722 status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize ); 01723 01724 // Validate status 01725 if( status != LORAMAC_STATUS_OK ) 01726 { 01727 return status; 01728 } 01729 01730 // Reset confirm parameters 01731 McpsConfirm.AckReceived = false; 01732 McpsConfirm.UpLinkCounter = UpLinkCounter; 01733 01734 ScheduleTx(); 01735 01736 return LORAMAC_STATUS_OK; 01737 } 01738 01739 01740 static void ResetMacParameters( void ) 01741 { 01742 LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = false; 01743 01744 // Counters 01745 UpLinkCounter = 0; 01746 DownLinkCounter = 0; 01747 01748 ChannelsNbRepCounter = 0; 01749 01750 MacCommandsBufferIndex = 0; 01751 MacCommandsBufferToRepeatIndex = 0; 01752 01753 IsRxWindowsEnabled = true; 01754 01755 LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower ; 01756 LoRaMacParams.ChannelsDatarate_fixed = LoRaMacParamsDefaults.ChannelsDatarate_fixed ; 01757 01758 LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset ; 01759 01760 LoRaMacFlags.Bits.NodeAckRequested = false; 01761 LoRaMacFlags.Bits.SrvAckRequested = false; 01762 MacCommandsInNextTx = false; 01763 01764 // Reset Multicast downlink counters 01765 MulticastParams_t *cur = MulticastChannels; 01766 while( cur != NULL ) 01767 { 01768 cur->DownLinkCounter = 0; 01769 cur = cur->Next ; 01770 } 01771 01772 } 01773 01774 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) 01775 { 01776 uint16_t i; 01777 uint32_t mic = 0; 01778 const void* payload = fBuffer; 01779 uint8_t framePort = fPort; 01780 uint8_t LoRaMacTxPayloadLen = 0; 01781 01782 LoRaMacFlags.Bits.NodeAckRequested = false; 01783 tx_buf_len = 0; 01784 01785 if( fBuffer == NULL ) 01786 { 01787 fBufferSize = 0; 01788 } 01789 01790 LoRaMacTxPayloadLen = fBufferSize; 01791 01792 Radio::radio.tx_buf[tx_buf_len++] = macHdr->Value ; 01793 01794 switch( macHdr->Bits.MType ) 01795 { 01796 case FRAME_TYPE_JOIN_REQ: 01797 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacAppEui, 8 ); 01798 tx_buf_len += 8; 01799 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); 01800 tx_buf_len += 8; 01801 01802 LoRaMacDevNonce = Radio::Random( ); 01803 01804 Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; 01805 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; 01806 01807 LoRaMacJoinComputeMic ( Radio::radio.tx_buf, tx_buf_len & 0xFF, LoRaMacAppKey, &mic ); 01808 01809 Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; 01810 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; 01811 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; 01812 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; 01813 01814 break; 01815 case FRAME_TYPE_DATA_CONFIRMED_UP: 01816 LoRaMacFlags.Bits.NodeAckRequested = true; 01817 //Intentional fallthrough 01818 case FRAME_TYPE_DATA_UNCONFIRMED_UP: 01819 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) 01820 { 01821 return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet 01822 } 01823 01824 fCtrl->Bits.AdrAckReq = 0; 01825 01826 if( LoRaMacFlags.Bits.SrvAckRequested == true ) 01827 { 01828 LoRaMacFlags.Bits.SrvAckRequested = false; 01829 fCtrl->Bits.Ack = 1; 01830 } 01831 01832 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr ) & 0xFF; 01833 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; 01834 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; 01835 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 24 ) & 0xFF; 01836 01837 Radio::radio.tx_buf[tx_buf_len++] = fCtrl->Value ; 01838 01839 Radio::radio.tx_buf[tx_buf_len++] = UpLinkCounter & 0xFF; 01840 Radio::radio.tx_buf[tx_buf_len++] = ( UpLinkCounter >> 8 ) & 0xFF; 01841 01842 // Copy the MAC commands which must be re-send into the MAC command buffer 01843 memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); 01844 MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; 01845 01846 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 01847 { 01848 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) ) 01849 { 01850 fCtrl->Bits.FOptsLen += MacCommandsBufferIndex; 01851 01852 // Update FCtrl field with new value of OptionsLength 01853 Radio::radio.tx_buf[0x05] = fCtrl->Value ; 01854 for( i = 0; i < MacCommandsBufferIndex; i++ ) 01855 { 01856 Radio::radio.tx_buf[tx_buf_len++] = MacCommandsBuffer[i]; 01857 } 01858 } 01859 } 01860 else 01861 { 01862 if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) ) 01863 { 01864 LoRaMacTxPayloadLen = MacCommandsBufferIndex; 01865 payload = MacCommandsBuffer; 01866 framePort = 0; 01867 } 01868 } 01869 MacCommandsInNextTx = false; 01870 // Store MAC commands which must be re-send in case the device does not receive a downlink anymore 01871 MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); 01872 if( MacCommandsBufferToRepeatIndex > 0 ) 01873 { 01874 MacCommandsInNextTx = true; 01875 } 01876 01877 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 01878 { 01879 Radio::radio.tx_buf[tx_buf_len++] = framePort; 01880 01881 if( framePort == 0 ) 01882 { 01883 LoRaMacPayloadEncrypt ( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &Radio::radio.tx_buf[tx_buf_len] ); 01884 } 01885 else 01886 { 01887 LoRaMacPayloadEncrypt ( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &Radio::radio.tx_buf[tx_buf_len] ); 01888 } 01889 } 01890 tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; 01891 01892 LoRaMacComputeMic( Radio::radio.tx_buf, tx_buf_len, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic ); 01893 01894 Radio::radio.tx_buf[tx_buf_len + 0] = mic & 0xFF; 01895 Radio::radio.tx_buf[tx_buf_len + 1] = ( mic >> 8 ) & 0xFF; 01896 Radio::radio.tx_buf[tx_buf_len + 2] = ( mic >> 16 ) & 0xFF; 01897 Radio::radio.tx_buf[tx_buf_len + 3] = ( mic >> 24 ) & 0xFF; 01898 01899 tx_buf_len += LORAMAC_MFR_LEN; 01900 01901 break; 01902 case FRAME_TYPE_PROPRIETARY: 01903 if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 01904 { 01905 memcpy1( Radio::radio.tx_buf + tx_buf_len, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen ); 01906 tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; 01907 } 01908 break; 01909 default: 01910 return LORAMAC_STATUS_SERVICE_UNKNOWN; 01911 } 01912 01913 return LORAMAC_STATUS_OK; 01914 } 01915 01916 01917 LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ) 01918 { 01919 int8_t txPowerIndex = 0; 01920 int8_t txPower = 0; 01921 01922 txPowerIndex = LoRaMacParams.ChannelsTxPower ; 01923 txPower = TxPowers[txPowerIndex]; 01924 Radio::SetTxContinuousWave( Channels[Channel].Frequency, txPower, timeout ); 01925 01926 return LORAMAC_STATUS_OK; 01927 } 01928 01929 LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power ) 01930 { 01931 Radio::SetTxContinuousWave( frequency, power, timeout ); 01932 01933 return LORAMAC_STATUS_OK; 01934 } 01935 01936 void seconds() 01937 { 01938 mac_printf("second\r\n"); 01939 } 01940 01941 void on_dio0_top_half() 01942 { 01943 } 01944 01945 unsigned get_symbol_period_us(uint8_t sf) 01946 { 01947 float bwMHz = LORA_BANDWIDTH_KHZ / 1000.0; 01948 // return symbol period in microseconds 01949 return (1 << sf) / bwMHz; 01950 } 01951 01952 const RadioEvents_t rev = { 01953 /* Dio0_top_half */ on_dio0_top_half, 01954 /* TxDone_topHalf */ OnRadioTxDone_topHalf, 01955 /* TxDone_botHalf */ OnRadioTxDone_bh, 01956 /* TxTimeout */ OnRadioTxTimeout, 01957 /* RxDone */ OnRadioRxDone, 01958 /* RxTimeout */ OnRadioRxTimeout, 01959 /* RxError */ OnRadioRxError, 01960 /* FhssChangeChannel */NULL, 01961 /* CadDone */ NULL 01962 }; 01963 01964 osThreadId_t tid_main; 01965 01966 void sleep_test_callback() 01967 { 01968 txDoneAt = LowPowerClock::now(); 01969 osThreadFlagsSet(tid_main, 1); 01970 } 01971 01972 LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks ) 01973 { 01974 if (primitives == NULL) 01975 { 01976 return LORAMAC_STATUS_PARAMETER_INVALID; 01977 } 01978 01979 if( ( primitives->MacMcpsConfirm == NULL ) || 01980 ( primitives->MacMcpsIndication == NULL ) || 01981 ( primitives->MacMlmeConfirm == NULL ) ) 01982 { 01983 return LORAMAC_STATUS_PARAMETER_INVALID; 01984 } 01985 01986 LoRaMacPrimitives = primitives; 01987 LoRaMacCallbacks = callbacks; 01988 01989 LoRaMacFlags.Value = 0; 01990 01991 JoinRequestTrials = 0; 01992 MaxJoinRequestTrials = 255; 01993 01994 BeaconCtx.symbol_period_us = get_symbol_period_us(Datarates[LORAMAC_DEFAULT_DATARATE]); 01995 01996 // Reset to defaults 01997 LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; 01998 LoRaMacParamsDefaults.ChannelsDatarate_fixed = LORAMAC_DEFAULT_DATARATE; 01999 02000 LoRaMacParamsDefaults.SystemMaxRxError_ms = 20; 02001 LoRaMacParamsDefaults.MinRxSymbols = (LoRaMacParamsDefaults.SystemMaxRxError_ms * 1000) / BeaconCtx.symbol_period_us; 02002 if (LoRaMacParamsDefaults.MinRxSymbols < MIN_SYMBOL_TIMEOUT) 02003 LoRaMacParamsDefaults.MinRxSymbols = MIN_SYMBOL_TIMEOUT; 02004 02005 LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW; 02006 02007 LoRaMacParamsDefaults.ReceiveDelay_us = RECEIVE_DELAY_us; 02008 LoRaMacParamsDefaults.JoinAcceptDelay_us = JOIN_ACCEPT_DELAY_us; 02009 02010 LoRaMacParamsDefaults.ChannelsNbRep = 1; 02011 LoRaMacParamsDefaults.Rx1DrOffset = 0; 02012 02013 for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS; i++ ) 02014 { 02015 Channels[i].Frequency = LORAMAC_FIRST_CHANNEL + (i * LORAMAC_STEPWIDTH_CHANNEL); 02016 Channels[i].DrRange .Value = (LORAMAC_MAX_DATARATE << 4) | LORAMAC_MIN_DATARATE; 02017 Channels[i].Band = 0; 02018 } 02019 02020 // Init parameters which are not set in function ResetMacParameters 02021 LoRaMacParams.SystemMaxRxError_ms = LoRaMacParamsDefaults.SystemMaxRxError_ms ; 02022 LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols ; 02023 LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow ; 02024 LoRaMacParams.ReceiveDelay_us = LoRaMacParamsDefaults.ReceiveDelay_us; 02025 LoRaMacParams.JoinAcceptDelay_us = LoRaMacParamsDefaults.JoinAcceptDelay_us; 02026 LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep ; 02027 02028 ResetMacParameters( ); 02029 if (LoRaMacCryptoInit() < 0) { 02030 return LORAMAC_STATUS_SERVICE_UNKNOWN; 02031 } 02032 02033 // Initialize Radio driver 02034 Radio::Init(&rev); 02035 02036 { 02037 unsigned sum = 0; 02038 sleep_manager_unlock_deep_sleep(); 02039 tid_main = ThisThread::get_id(); 02040 /*** How long this MCU takes to wake up from deep-sleep ***/ 02041 for (unsigned n = 0; n < 16; n++) { 02042 long end, start; 02043 txDoneAt = LowPowerClock::now(); 02044 start = txDoneAt.time_since_epoch().count(); 02045 02046 LoRaMacFlags.Value = 0; 02047 rx_timeout.attach(sleep_test_callback, 10ms); 02048 ThisThread::flags_wait_any(1); 02049 end = LowPowerClock::now().time_since_epoch().count(); 02050 sum += (end - start) - 10000; 02051 } 02052 LoRaMacFlags.Value = 0; 02053 sum >>= 4; // 16 samples = 2^4 02054 printf("mcu takes %uus to wake up\r\n", sum); 02055 mcu_wakeup_latency = microseconds(sum); 02056 } 02057 02058 // Random seed initialization 02059 srand1( Radio::Random( ) ); 02060 02061 PublicNetwork = true; 02062 Radio::SetPublicNetwork( PublicNetwork ); 02063 Radio::Sleep( ); 02064 02065 RxWindowsParam = ComputeRxWindowParameters(LORAMAC_DEFAULT_DATARATE, LoRaMacParams.SystemMaxRxError_ms ); 02066 02067 return LORAMAC_STATUS_OK; 02068 } // ..LoRaMacInitialization() 02069 02070 LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t * txInfo ) 02071 { 02072 uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; 02073 02074 if( txInfo == NULL ) 02075 { 02076 return LORAMAC_STATUS_PARAMETER_INVALID; 02077 } 02078 02079 txInfo->CurrentPayloadSize = LORAMAC_PHY_MAXPAYLOAD; 02080 02081 if( txInfo->CurrentPayloadSize >= fOptLen ) 02082 { 02083 txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; 02084 } 02085 else 02086 { 02087 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; 02088 } 02089 02090 return LORAMAC_STATUS_OK; 02091 } 02092 02093 LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet ) 02094 { 02095 LoRaMacStatus_t status = LORAMAC_STATUS_OK; 02096 02097 if( mibGet == NULL ) 02098 { 02099 return LORAMAC_STATUS_PARAMETER_INVALID; 02100 } 02101 02102 switch( mibGet->Type ) 02103 { 02104 case MIB_NETWORK_JOINED: 02105 { 02106 mibGet->Param .IsNetworkJoined = LoRaMacFlags.Bits.IsLoRaMacNetworkJoined; 02107 break; 02108 } 02109 case MIB_NET_ID: 02110 { 02111 mibGet->Param .NetID = LoRaMacNetID; 02112 break; 02113 } 02114 case MIB_DEV_ADDR: 02115 { 02116 mibGet->Param .DevAddr = LoRaMacDevAddr; 02117 break; 02118 } 02119 case MIB_NWK_SKEY: 02120 { 02121 mibGet->Param .NwkSKey = LoRaMacNwkSKey; 02122 break; 02123 } 02124 case MIB_APP_SKEY: 02125 { 02126 mibGet->Param .AppSKey = LoRaMacAppSKey; 02127 break; 02128 } 02129 case MIB_PUBLIC_NETWORK: 02130 { 02131 mibGet->Param .EnablePublicNetwork = PublicNetwork; 02132 break; 02133 } 02134 case MIB_CHANNELS_NB_REP: 02135 { 02136 mibGet->Param .ChannelNbRep = LoRaMacParams.ChannelsNbRep ; 02137 break; 02138 } 02139 case MIB_MAX_RX_WINDOW_DURATION: 02140 { 02141 mibGet->Param .MaxRxWindow = LoRaMacParams.MaxRxWindow ; 02142 break; 02143 } 02144 case MIB_CHANNELS_DEFAULT_TX_POWER: 02145 { 02146 mibGet->Param .ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower ; 02147 break; 02148 } 02149 case MIB_CHANNELS_TX_POWER: 02150 { 02151 mibGet->Param .ChannelsTxPower = LoRaMacParams.ChannelsTxPower ; 02152 break; 02153 } 02154 case MIB_UPLINK_COUNTER: 02155 { 02156 mibGet->Param .UpLinkCounter = UpLinkCounter; 02157 break; 02158 } 02159 case MIB_DOWNLINK_COUNTER: 02160 { 02161 mibGet->Param .DownLinkCounter = DownLinkCounter; 02162 break; 02163 } 02164 case MIB_MULTICAST_CHANNEL: 02165 { 02166 mibGet->Param .MulticastList = MulticastChannels; 02167 break; 02168 } 02169 case MIB_SYSTEM_MAX_RX_ERROR: 02170 { 02171 mibGet->Param .SystemMaxRxError_ms = LoRaMacParams.SystemMaxRxError_ms ; 02172 break; 02173 } 02174 case MIB_MIN_RX_SYMBOLS: 02175 { 02176 mibGet->Param .MinRxSymbols = LoRaMacParams.MinRxSymbols ; 02177 break; 02178 } 02179 default: 02180 status = LORAMAC_STATUS_SERVICE_UNKNOWN; 02181 break; 02182 } 02183 02184 return status; 02185 } 02186 02187 LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet ) 02188 { 02189 LoRaMacStatus_t status = LORAMAC_STATUS_OK; 02190 02191 if( mibSet == NULL ) 02192 { 02193 return LORAMAC_STATUS_PARAMETER_INVALID; 02194 } 02195 02196 switch( mibSet->Type ) 02197 { 02198 case MIB_NETWORK_JOINED: 02199 { 02200 LoRaMacFlags.Bits.IsLoRaMacNetworkJoined = mibSet->Param .IsNetworkJoined ; 02201 if (!LoRaMacFlags.Bits.IsLoRaMacNetworkJoined) { 02202 mac_printf("beaconDetach\r\n"); 02203 BeaconCtx.timeout_rx.detach(); 02204 BeaconCtx.timeout_guard.detach(); 02205 BeaconCtx.state = BEACON_STATE_NONE; 02206 } 02207 break; 02208 } 02209 case MIB_NET_ID: 02210 { 02211 LoRaMacNetID = mibSet->Param .NetID ; 02212 break; 02213 } 02214 case MIB_DEV_ADDR: 02215 { 02216 LoRaMacDevAddr = mibSet->Param .DevAddr ; 02217 break; 02218 } 02219 case MIB_NWK_SKEY: 02220 { 02221 if( mibSet->Param .NwkSKey != NULL ) 02222 { 02223 memcpy1( LoRaMacNwkSKey, mibSet->Param .NwkSKey , 02224 sizeof( LoRaMacNwkSKey ) ); 02225 } 02226 else 02227 { 02228 status = LORAMAC_STATUS_PARAMETER_INVALID; 02229 } 02230 break; 02231 } 02232 case MIB_APP_SKEY: 02233 { 02234 if( mibSet->Param .AppSKey != NULL ) 02235 { 02236 memcpy1( LoRaMacAppSKey, mibSet->Param .AppSKey , 02237 sizeof( LoRaMacAppSKey ) ); 02238 } 02239 else 02240 { 02241 status = LORAMAC_STATUS_PARAMETER_INVALID; 02242 } 02243 break; 02244 } 02245 case MIB_PUBLIC_NETWORK: 02246 { 02247 PublicNetwork = mibSet->Param .EnablePublicNetwork ; 02248 Radio::SetPublicNetwork( PublicNetwork ); 02249 break; 02250 } 02251 case MIB_CHANNELS_NB_REP: 02252 { 02253 if( ( mibSet->Param .ChannelNbRep >= 1 ) && 02254 ( mibSet->Param .ChannelNbRep <= 15 ) ) 02255 { 02256 LoRaMacParams.ChannelsNbRep = mibSet->Param .ChannelNbRep ; 02257 } 02258 else 02259 { 02260 status = LORAMAC_STATUS_PARAMETER_INVALID; 02261 } 02262 break; 02263 } 02264 case MIB_MAX_RX_WINDOW_DURATION: 02265 { 02266 LoRaMacParams.MaxRxWindow = mibSet->Param .MaxRxWindow ; 02267 break; 02268 } 02269 case MIB_CHANNELS_DEFAULT_TX_POWER: 02270 { 02271 if( ValueInRange( mibSet->Param .ChannelsDefaultTxPower , 02272 LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) 02273 { 02274 LoRaMacParamsDefaults.ChannelsTxPower = mibSet->Param .ChannelsDefaultTxPower ; 02275 } 02276 else 02277 { 02278 status = LORAMAC_STATUS_PARAMETER_INVALID; 02279 } 02280 break; 02281 } 02282 case MIB_CHANNELS_TX_POWER: 02283 { 02284 if( ValueInRange( mibSet->Param .ChannelsTxPower , 02285 LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) 02286 { 02287 LoRaMacParams.ChannelsTxPower = mibSet->Param .ChannelsTxPower ; 02288 } 02289 else 02290 { 02291 status = LORAMAC_STATUS_PARAMETER_INVALID; 02292 } 02293 break; 02294 } 02295 case MIB_UPLINK_COUNTER: 02296 { 02297 UpLinkCounter = mibSet->Param .UpLinkCounter ; 02298 break; 02299 } 02300 case MIB_DOWNLINK_COUNTER: 02301 { 02302 DownLinkCounter = mibSet->Param .DownLinkCounter ; 02303 break; 02304 } 02305 case MIB_SYSTEM_MAX_RX_ERROR: 02306 { 02307 LoRaMacParams.SystemMaxRxError_ms = LoRaMacParamsDefaults.SystemMaxRxError_ms = mibSet->Param .SystemMaxRxError_ms ; 02308 break; 02309 } 02310 case MIB_MIN_RX_SYMBOLS: 02311 { 02312 LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param .MinRxSymbols ; 02313 break; 02314 } 02315 default: 02316 status = LORAMAC_STATUS_SERVICE_UNKNOWN; 02317 break; 02318 } 02319 02320 return status; 02321 } 02322 02323 LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam ) 02324 { 02325 if( channelParam == NULL ) 02326 { 02327 return LORAMAC_STATUS_PARAMETER_INVALID; 02328 } 02329 02330 // Reset downlink counter 02331 channelParam->DownLinkCounter = 0; 02332 02333 if( MulticastChannels == NULL ) 02334 { 02335 // New node is the fist element 02336 MulticastChannels = channelParam; 02337 } 02338 else 02339 { 02340 MulticastParams_t *cur = MulticastChannels; 02341 02342 // Search the last node in the list 02343 while( cur->Next != NULL ) 02344 { 02345 cur = cur->Next ; 02346 } 02347 // This function always finds the last node 02348 cur->Next = channelParam; 02349 } 02350 02351 return LORAMAC_STATUS_OK; 02352 } 02353 02354 LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam ) 02355 { 02356 if( channelParam == NULL ) 02357 { 02358 return LORAMAC_STATUS_PARAMETER_INVALID; 02359 } 02360 02361 if( MulticastChannels != NULL ) 02362 { 02363 if( MulticastChannels == channelParam ) 02364 { 02365 // First element 02366 MulticastChannels = channelParam->Next ; 02367 } 02368 else 02369 { 02370 MulticastParams_t *cur = MulticastChannels; 02371 02372 // Search the node in the list 02373 while( cur->Next && cur->Next != channelParam ) 02374 { 02375 cur = cur->Next ; 02376 } 02377 // If we found the node, remove it 02378 if( cur->Next ) 02379 { 02380 cur->Next = channelParam->Next ; 02381 } 02382 } 02383 channelParam->Next = NULL; 02384 } 02385 02386 return LORAMAC_STATUS_OK; 02387 } 02388 02389 LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest ) 02390 { 02391 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; 02392 LoRaMacHeader_t macHdr; 02393 02394 if( mlmeRequest == NULL ) 02395 { 02396 return LORAMAC_STATUS_PARAMETER_INVALID; 02397 } 02398 02399 memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) ); 02400 02401 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_MLMEREQ; 02402 02403 switch( mlmeRequest->Type ) 02404 { 02405 case MLME_JOIN: 02406 { 02407 if( ( mlmeRequest->Req.Join .DevEui == NULL ) || 02408 ( mlmeRequest->Req.Join .AppEui == NULL ) || 02409 ( mlmeRequest->Req.Join .AppKey == NULL ) || 02410 ( mlmeRequest->Req.Join .NbTrials == 0 ) ) 02411 { 02412 return LORAMAC_STATUS_PARAMETER_INVALID; 02413 } 02414 02415 // Enables at least the usage of all datarates. 02416 if( mlmeRequest->Req.Join .NbTrials < 48 ) 02417 { 02418 mlmeRequest->Req.Join .NbTrials = 48; 02419 } 02420 02421 LoRaMacFlags.Bits.MlmeReq = 1; 02422 MlmeConfirm.MlmeRequest = mlmeRequest->Type ; 02423 02424 LoRaMacDevEui = mlmeRequest->Req.Join .DevEui ; 02425 LoRaMacAppEui = mlmeRequest->Req.Join .AppEui ; 02426 LoRaMacAppKey = mlmeRequest->Req.Join .AppKey ; 02427 MaxJoinRequestTrials = mlmeRequest->Req.Join .NbTrials ; 02428 02429 // Reset variable JoinRequestTrials 02430 JoinRequestTrials = 0; 02431 02432 // Setup header information 02433 macHdr.Value = 0; 02434 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; 02435 02436 ResetMacParameters( ); 02437 LoRaMacFlags.Bits.expecting_beacon = false; 02438 BeaconCtx.state = BEACON_STATE_NONE; 02439 02440 Channel = 0; // start with first channel 02441 mac_printf("<ch0>"); 02442 mac_printf("mlme-join-send ch%u\r\n", Channel); 02443 status = Send( &macHdr, 0, NULL, 0 ); 02444 break; 02445 } 02446 case MLME_LINK_CHECK: 02447 { 02448 LoRaMacFlags.Bits.MlmeReq = 1; 02449 // LoRaMac will send this command piggy-pack 02450 MlmeConfirm.MlmeRequest = mlmeRequest->Type ; 02451 02452 status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 ); 02453 break; 02454 } 02455 case MLME_TXCW: 02456 { 02457 MlmeConfirm.MlmeRequest = mlmeRequest->Type ; 02458 LoRaMacFlags.Bits.MlmeReq = 1; 02459 status = SetTxContinuousWave( mlmeRequest->Req.TxCw .Timeout ); 02460 break; 02461 } 02462 case MLME_TXCW_1: 02463 { 02464 MlmeConfirm.MlmeRequest = mlmeRequest->Type ; 02465 LoRaMacFlags.Bits.MlmeReq = 1; 02466 status = SetTxContinuousWave1( mlmeRequest->Req.TxCw .Timeout , mlmeRequest->Req.TxCw .Frequency , mlmeRequest->Req.TxCw .Power ); 02467 break; 02468 } 02469 default: 02470 break; 02471 } 02472 02473 if( status != LORAMAC_STATUS_OK ) 02474 { 02475 LoRaMacFlags.Bits.NodeAckRequested = false; 02476 LoRaMacFlags.Bits.MlmeReq = 0; 02477 } 02478 02479 return status; 02480 } 02481 02482 LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest ) 02483 { 02484 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; 02485 LoRaMacHeader_t macHdr; 02486 uint8_t fPort = 0; 02487 void *fBuffer; 02488 uint16_t fBufferSize; 02489 bool readyToSend = false; 02490 02491 if( mcpsRequest == NULL ) 02492 { 02493 return LORAMAC_STATUS_PARAMETER_INVALID; 02494 } 02495 02496 macHdr.Value = 0; 02497 memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) ); 02498 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR_MCPSREQ; 02499 02500 switch( mcpsRequest->Type ) 02501 { 02502 case MCPS_UNCONFIRMED: 02503 { 02504 readyToSend = true; 02505 02506 macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; 02507 fPort = mcpsRequest->Req.Unconfirmed .fPort ; 02508 fBuffer = mcpsRequest->Req.Unconfirmed .fBuffer ; 02509 fBufferSize = mcpsRequest->Req.Unconfirmed .fBufferSize ; 02510 break; 02511 } 02512 case MCPS_CONFIRMED: 02513 { 02514 readyToSend = true; 02515 02516 macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP; 02517 fPort = mcpsRequest->Req.Confirmed .fPort ; 02518 fBuffer = mcpsRequest->Req.Confirmed .fBuffer ; 02519 fBufferSize = mcpsRequest->Req.Confirmed .fBufferSize ; 02520 break; 02521 } 02522 case MCPS_PROPRIETARY: 02523 { 02524 readyToSend = true; 02525 02526 macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY; 02527 fBuffer = mcpsRequest->Req.Proprietary .fBuffer ; 02528 fBufferSize = mcpsRequest->Req.Proprietary .fBufferSize ; 02529 break; 02530 } 02531 default: 02532 break; 02533 } 02534 02535 if (readyToSend) 02536 { 02537 status = Send( &macHdr, fPort, fBuffer, fBufferSize ); 02538 if (status == LORAMAC_STATUS_OK) 02539 { 02540 McpsConfirm.McpsRequest = mcpsRequest->Type ; 02541 LoRaMacFlags.Bits.McpsReq = 1; 02542 } 02543 else 02544 { 02545 LoRaMacFlags.Bits.NodeAckRequested = false; 02546 } 02547 } 02548 02549 return status; 02550 } 02551 02552 void LoRaMacTestRxWindowsOn( bool enable ) 02553 { 02554 IsRxWindowsEnabled = enable; 02555 } 02556 02557 void LoRaMacTestSetMic( uint16_t txPacketCounter ) 02558 { 02559 UpLinkCounter = txPacketCounter; 02560 //IsUpLinkCounterFixed = true; 02561 } 02562 02563 void LoRaMacTestSetChannel( uint8_t channel ) 02564 { 02565 mac_printf("set-testch%u\r\n", channel); 02566 Channel = channel; 02567 } 02568 02569 02570 static RxConfigParams_t ComputeRxWindowParameters( int8_t datarate, uint32_t rxError ) 02571 { 02572 RxConfigParams_t rxConfigParams = { 0, 0 }; 02573 double tSymbol = 0.0; 02574 02575 rxConfigParams.Datarate = datarate; 02576 02577 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) 02578 if( datarate == DR_7 ) 02579 { // FSK 02580 tSymbol = ( 1.0 / ( double )Datarates[datarate] ) * 8.0; // 1 symbol equals 1 byte 02581 } 02582 else 02583 #endif 02584 { // LoRa 02585 tSymbol = ( ( double )( 1 << Datarates[datarate] ) / LORA_BANDWIDTH_KHZ ) * 1e3; 02586 } 02587 02588 rxConfigParams.RxWindowTimeout = MAX( ( uint32_t )ceil( ( ( 2 * LoRaMacParams.MinRxSymbols - 8 ) * tSymbol + 2 * rxError ) / tSymbol ), LoRaMacParams.MinRxSymbols ); // Computed number of symbols 02589 mac_printf("RxWindowTimeout:%lu\r\n", rxConfigParams.RxWindowTimeout); 02590 02591 return rxConfigParams; 02592 } 02593 02594 void LoRaMacBottomHalf() 02595 { 02596 if (LoRaMacFlags.Bits.join_send) { 02597 join_send_bh(); 02598 LoRaMacFlags.Bits.join_send = 0; 02599 } 02600 if (LoRaMacFlags.Bits.send) { 02601 send_bh(); 02602 LoRaMacFlags.Bits.send = 0; 02603 } 02604 02605 if (LoRaMacFlags.Bits.reJoin) { 02606 MlmeReq_t mlmeReq; 02607 mlmeReq.Type = MLME_JOIN; 02608 02609 mlmeReq.Req.Join .DevEui = LoRaMacDevEui; 02610 mlmeReq.Req.Join .AppEui = LoRaMacAppEui; 02611 mlmeReq.Req.Join .AppKey = LoRaMacAppKey; 02612 mlmeReq.Req.Join .NbTrials = 255; 02613 02614 if (LoRaMacMlmeRequest(&mlmeReq) == LORAMAC_STATUS_OK) 02615 LoRaMacFlags.Bits.reJoin = 0; 02616 } 02617 02618 Radio::service(); 02619 }
Generated on Wed Jul 13 2022 01:56:41 by 1.7.2