LoRaWAN end device MAC layer for SX1272 and SX1276. Supports LoRaWAN-1.0 and LoRaWAN-1.1
Dependents: LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more
LoRaMac1v1.cpp
00001 00002 #include "LoRaMacPrivate.h" 00003 #include "LoRaMacCrypto.h" 00004 00005 //#define ADR_ACK_LIMIT 64 00006 //#define ADR_ACK_DELAY 32 00007 #define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4) 00008 #define RECEIVE_DELAY1_us 1000000 00009 #define LORAMAC_MFR_LEN 4 00010 00011 /*! 00012 * LoRaMAC Battery level indicator 00013 */ 00014 typedef enum eLoRaMacBatteryLevel 00015 { 00016 /*! 00017 * External power source 00018 */ 00019 BAT_LEVEL_EXT_SRC = 0x00, 00020 /*! 00021 * Battery level empty 00022 */ 00023 BAT_LEVEL_EMPTY = 0x01, 00024 /*! 00025 * Battery level full 00026 */ 00027 BAT_LEVEL_FULL = 0xFE, 00028 /*! 00029 * Battery level - no measurement available 00030 */ 00031 BAT_LEVEL_NO_MEASURE = 0xFF, 00032 }LoRaMacBatteryLevel_t; 00033 00034 /*! 00035 * LoRaMac internal state 00036 */ 00037 flags_t flags; 00038 00039 void (*function_pending)(void); // one-shot 00040 00041 /*! 00042 * Current channel index 00043 */ 00044 uint8_t Channel; 00045 00046 static MlmeIndication_t MlmeIndication; 00047 static MlmeConfirm_t MlmeConfirm; 00048 static McpsIndication_t McpsIndication; 00049 static McpsConfirm_t McpsConfirm; 00050 00051 uint32_t LoRaMacDevAddr; 00052 uint32_t LoRaMacNetID; 00053 static skey_t keys; 00054 00055 uint8_t MacCommandsBufferToRepeatIndex; 00056 uint8_t MacCommandsBufferIndex; 00057 uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; 00058 static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; 00059 00060 LoRaMacParams_t LoRaMacParams; 00061 00062 #ifdef LORAWAN_JOIN_EUI 00063 static const uint8_t *LoRaMacDevEui; 00064 static const uint8_t *LoRaMacJoinEui; 00065 static const uint8_t *RootNwkKey; 00066 static const uint8_t *RootAppKey; 00067 static uint8_t MaxJoinRequestTrials; 00068 static uint8_t JSEncKey[16]; // TODO move to keys 00069 static uint8_t JSIntKey[16]; // TODO move to keys 00070 static uint8_t JoinReqType; 00071 static uint16_t LoRaMacDevNonce; 00072 uint16_t RJcount0; 00073 00074 static uint32_t FCntUp; 00075 static uint32_t NFCntDown; /**< set to next expected value */ 00076 static uint32_t AFCntDown; /**< set to next expected value */ 00077 #endif /* LORAWAN_JOIN_EUI */ 00078 00079 static uint16_t ADR_ACK_LIMIT; 00080 static uint16_t ADR_ACK_DELAY; 00081 00082 DeviceClass_t LoRaMacDeviceClass; 00083 uint8_t tx_buf_len; 00084 const LoRaMacHeader_t * uplinkMHDR = (LoRaMacHeader_t *)&Radio::radio.tx_buf[0]; 00085 00086 static uint32_t RxWindow1Delay_us; 00087 static uint32_t RxWindow2Delay_us; 00088 00089 LoRaMacHeader_t last_up_macHdr; 00090 static uint8_t rxFRMPayload[244]; 00091 00092 static const LoRaMacPrimitives_t *LoRaMacPrimitives; 00093 static const LoRaMacCallback_t *LoRaMacCallbacks; 00094 00095 /*! 00096 * LoRaMAC frame counter. Each time a packet is received the counter is incremented. 00097 * Only the 16 LSB bits are received 00098 */ 00099 static uint16_t ConfFCntDown; 00100 static uint16_t ConfFCntUp; 00101 00102 static void PrepareRxDoneAbort(LoRaMacEventInfoStatus_t); 00103 00104 void OnRadioRxTimeout(void); 00105 00106 LoRaMacStatus_t 00107 AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) 00108 { 00109 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; 00110 // The maximum buffer length must take MAC commands to re-send into account. 00111 uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; 00112 00113 MAC_PRINTF("AddMacCommand(%02x, %02x, %02x)\r\n", cmd, p1, p2); 00114 switch( cmd ) 00115 { 00116 case MOTE_MAC_LINK_CHECK_REQ: 00117 case MOTE_MAC_DEVICE_TIME_REQ: 00118 if( MacCommandsBufferIndex < bufLen ) 00119 { 00120 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00121 // No payload for this command 00122 status = LORAMAC_STATUS_OK; 00123 } 00124 break; 00125 case MOTE_MAC_LINK_ADR_ANS: 00126 if( MacCommandsBufferIndex < ( bufLen - 1 ) ) 00127 { 00128 MAC_PRINTF("LINK_ADR_ANS %02x ", p1); 00129 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00130 // Margin 00131 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00132 status = LORAMAC_STATUS_OK; 00133 } 00134 break; 00135 case MOTE_MAC_DUTY_CYCLE_ANS: 00136 if( MacCommandsBufferIndex < bufLen ) 00137 { 00138 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00139 // No payload for this answer 00140 status = LORAMAC_STATUS_OK; 00141 } 00142 break; 00143 case MOTE_MAC_RX_PARAM_SETUP_ANS: 00144 if( MacCommandsBufferIndex < ( bufLen - 1 ) ) 00145 { 00146 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00147 // Status: Datarate ACK, Channel ACK 00148 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00149 status = LORAMAC_STATUS_OK; 00150 } 00151 break; 00152 case MOTE_MAC_DEV_STATUS_ANS: 00153 if( MacCommandsBufferIndex < ( bufLen - 2 ) ) 00154 { 00155 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00156 // 1st byte Battery 00157 // 2nd byte Margin 00158 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00159 MacCommandsBuffer[MacCommandsBufferIndex++] = p2; 00160 status = LORAMAC_STATUS_OK; 00161 } 00162 break; 00163 case MOTE_MAC_NEW_CHANNEL_ANS: 00164 if( MacCommandsBufferIndex < ( bufLen - 1 ) ) 00165 { 00166 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00167 // Status: Datarate range OK, Channel frequency OK 00168 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00169 status = LORAMAC_STATUS_OK; 00170 } 00171 break; 00172 case MOTE_MAC_RX_TIMING_SETUP_ANS: 00173 if( MacCommandsBufferIndex < bufLen ) 00174 { 00175 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00176 // No payload for this answer 00177 status = LORAMAC_STATUS_OK; 00178 } 00179 break; 00180 #ifdef LORAWAN_JOIN_EUI 00181 case MOTE_MAC_REKEY_IND: 00182 if( MacCommandsBufferIndex < bufLen-1 ) 00183 { 00184 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00185 // minor version: 00186 if (RootAppKey == NULL) 00187 MacCommandsBuffer[MacCommandsBufferIndex++] = 0; // lorawan1v0 00188 else 00189 MacCommandsBuffer[MacCommandsBufferIndex++] = 1; // lorawan1v1 00190 00191 status = LORAMAC_STATUS_OK; 00192 } 00193 break; 00194 case MOTE_MAC_REJOIN_PARAM_ANS: 00195 if( MacCommandsBufferIndex < bufLen-1 ) 00196 { 00197 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00198 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00199 status = LORAMAC_STATUS_OK; 00200 } 00201 break; 00202 #else 00203 case MOTE_MAC_RESET_IND: 00204 if( MacCommandsBufferIndex < bufLen-1 ) 00205 { 00206 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00207 // minor version: 00208 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00209 status = LORAMAC_STATUS_OK; 00210 } 00211 break; 00212 #endif /* !LORAWAN_JOIN_EUI */ 00213 case MOTE_MAC_MODE_IND: 00214 if( MacCommandsBufferIndex < bufLen-1 ) 00215 { 00216 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; 00217 MacCommandsBuffer[MacCommandsBufferIndex++] = p1; 00218 status = LORAMAC_STATUS_OK; 00219 } 00220 break; 00221 default: 00222 MAC_PRINTF("unknown-addCmd %02x\r\n", cmd); 00223 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00224 } // ..switch( cmd ) 00225 00226 if( status == LORAMAC_STATUS_OK ) 00227 { 00228 flags.MacCommandsInNextTx = true; 00229 } 00230 return status; 00231 } // ..AddMacCommand() 00232 00233 00234 LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout ) 00235 { 00236 int8_t txPowerIndex = 0; 00237 int8_t txPower = 0; 00238 00239 txPowerIndex = region_LimitTxPower( LoRaMacParams.ChannelsTxPower ); 00240 txPower = TxPowers[txPowerIndex]; 00241 00242 Radio::SetTxContinuousWave( Channels[Channel].FreqHz, txPower, timeout ); 00243 00244 flags.uplink_in_progress = 1; 00245 00246 return LORAMAC_STATUS_OK; 00247 } 00248 00249 __attribute__((weak)) LoRaMacStatus_t 00250 LoRaMacMlmeRequestClassB( const MlmeReq_t *mlmeRequest ) 00251 { 00252 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00253 } 00254 00255 __attribute__((weak)) LoRaMacStatus_t 00256 AddMacCommandClassB( uint8_t cmd, uint8_t p1, uint8_t p2 ) 00257 { 00258 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00259 } 00260 00261 __attribute__((weak)) void 00262 ResetMacParametersClassB() 00263 { 00264 } 00265 00266 static void ResetMacParameters( void ) 00267 { 00268 #ifdef LORAWAN_JOIN_EUI 00269 flags.IsLoRaMacNetworkJoined = 0; 00270 NFCntDown = 0; 00271 AFCntDown = 0; 00272 #endif /* LORAWAN_JOIN_EUI */ 00273 00274 #ifdef DUTY_ENABLE 00275 DutyInit(); 00276 #endif /* DUTY_ENABLE */ 00277 00278 MacCommandsBufferIndex = 0; 00279 MacCommandsBufferToRepeatIndex = 0; 00280 00281 //IsRxWindowsEnabled = true; 00282 00283 LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower ; 00284 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate ; 00285 00286 LoRaMacParams.MaxRxWindow_us = LoRaMacParamsDefaults.MaxRxWindow_us ; 00287 LoRaMacParams.ReceiveDelay1_us = LoRaMacParamsDefaults.ReceiveDelay1_us ; 00288 LoRaMacParams.ReceiveDelay2_us = LoRaMacParamsDefaults.ReceiveDelay2_us ; 00289 #ifdef LORAWAN_JOIN_EUI 00290 LoRaMacParams.JoinAcceptDelay1_us = LoRaMacParamsDefaults.JoinAcceptDelay1_us ; 00291 LoRaMacParams.JoinAcceptDelay2_us = LoRaMacParamsDefaults.JoinAcceptDelay2_us ; 00292 #endif /* LORAWAN_JOIN_EUI */ 00293 00294 LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset ; 00295 LoRaMacParams.NbTrans = LoRaMacParamsDefaults.NbTrans ; 00296 00297 LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel ; 00298 00299 memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask , ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask , sizeof( LoRaMacParams.ChannelsMask ) ); 00300 LoRaMacParams.NbEnabledChannels = LoRaMacParamsDefaults.NbEnabledChannels; 00301 00302 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 00303 memcpy( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask , sizeof( LoRaMacParams.ChannelsMask ) ); 00304 #endif 00305 00306 LoRaMacParams.MaxListenTime = LoRaMacParamsDefaults.MaxListenTime; 00307 00308 00309 flags.SrvAckRequested = false; 00310 flags.MacCommandsInNextTx = false; 00311 00312 // Initialize channel index. 00313 Channel = LORA_MAX_NB_CHANNELS; 00314 00315 ResetMacParametersClassB(); 00316 00317 } // ..ResetMacParameters() 00318 00319 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ) 00320 { 00321 uint16_t maxN = 0; 00322 uint8_t payloadSize; 00323 00324 // Get the maximum payload length 00325 maxN = MaxPayloadOfDatarate[datarate]; 00326 00327 // Calculate the resulting payload size 00328 payloadSize = ( lenN + fOptsLen ); 00329 00330 // Validation of the application payload size 00331 if( payloadSize <= maxN ) 00332 { 00333 return true; 00334 } 00335 return false; 00336 } 00337 00338 static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) 00339 { 00340 uint8_t i = 0; 00341 uint8_t cmdCount = 0; 00342 00343 if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) 00344 { 00345 return 0; 00346 } 00347 00348 for( i = 0; i < length; i++ ) 00349 { 00350 switch( cmdBufIn[i] ) 00351 { 00352 // STICKY 00353 case MOTE_MAC_RX_PARAM_SETUP_ANS: 00354 { 00355 cmdBufOut[cmdCount++] = cmdBufIn[i++]; 00356 cmdBufOut[cmdCount++] = cmdBufIn[i]; 00357 break; 00358 } 00359 case MOTE_MAC_RX_TIMING_SETUP_ANS: 00360 { 00361 cmdBufOut[cmdCount++] = cmdBufIn[i]; 00362 break; 00363 } 00364 // NON-STICKY 00365 case MOTE_MAC_DEV_STATUS_ANS: 00366 { // 2 bytes payload 00367 i += 2; 00368 break; 00369 } 00370 case MOTE_MAC_MODE_IND: 00371 case MOTE_MAC_LINK_ADR_ANS: 00372 case MOTE_MAC_NEW_CHANNEL_ANS: 00373 { // 1 byte payload 00374 i++; 00375 break; 00376 } 00377 case SRV_MAC_ADR_PARAM_SETUP_ANS: 00378 case MOTE_MAC_DUTY_CYCLE_ANS: 00379 case MOTE_MAC_LINK_CHECK_REQ: 00380 { // 0 byte payload 00381 break; 00382 } 00383 default: 00384 break; 00385 } 00386 } 00387 00388 return cmdCount; 00389 } // ..ParseMacCommandsToRepeat() 00390 00391 LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) 00392 { 00393 uint32_t fcnt_up; 00394 uint16_t i; 00395 #ifdef LORAWAN_JOIN_EUI 00396 uint32_t mic = 0; 00397 #endif /* LORAWAN_JOIN_EUI */ 00398 const void* payload = fBuffer; 00399 uint8_t framePort = fPort; 00400 uint8_t LoRaMacTxPayloadLen = 0; 00401 00402 tx_buf_len = 0; 00403 00404 if( fBuffer == NULL ) 00405 { 00406 fBufferSize = 0; 00407 } 00408 00409 LoRaMacTxPayloadLen = fBufferSize; 00410 00411 Radio::radio.tx_buf[tx_buf_len++] = macHdr->Value ; 00412 00413 switch( macHdr->Bits.MType ) 00414 { 00415 #ifdef LORAWAN_JOIN_EUI 00416 case FRAME_TYPE_JOIN_REQ: 00417 if (LoRaMacJoinEui == NULL || LoRaMacDevEui == NULL) 00418 return LORAMAC_STATUS_PARAMETER_INVALID; 00419 00420 RxWindow1Delay_us = LoRaMacParams.JoinAcceptDelay1_us - RADIO_WAKEUP_TIME_us; 00421 RxWindow2Delay_us = LoRaMacParams.JoinAcceptDelay2_us - RADIO_WAKEUP_TIME_us; 00422 00423 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacJoinEui, 8 ); 00424 tx_buf_len += 8; 00425 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); 00426 tx_buf_len += 8; 00427 00428 if (RootAppKey == NULL) 00429 LoRaMacDevNonce = Radio::Random(); /* lorawan 1.0 */ 00430 else { 00431 LoRaMacDevNonce = eeprom_read(EEPROM_DEVNONCE); 00432 /* joinReq DevNonce value is never re-used in 1v1 */ 00433 if (eeprom_increment_value(EEPROM_DEVNONCE) < 0) 00434 return LORAMAC_STATUS_EEPROM_FAIL; 00435 } 00436 MAC_PRINTF("DevNonce:%u ", LoRaMacDevNonce); 00437 00438 Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; 00439 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; 00440 00441 if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, RootNwkKey, &mic) < 0) 00442 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00443 00444 Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; 00445 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; 00446 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; 00447 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; 00448 00449 break; 00450 case FRAME_TYPE_REJOIN_REQ: 00451 RxWindow1Delay_us = LoRaMacParams.JoinAcceptDelay1_us - RADIO_WAKEUP_TIME_us; 00452 RxWindow2Delay_us = LoRaMacParams.JoinAcceptDelay2_us - RADIO_WAKEUP_TIME_us; 00453 00454 Radio::radio.tx_buf[tx_buf_len++] = JoinReqType; 00455 00456 tx_buf_len = tx_buf_len; 00457 00458 if (JoinReqType == 0 || JoinReqType == 2) { 00459 LoRaMacDevNonce = RJcount0++; 00460 /* NetID + DevEUI */ 00461 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID ) & 0xFF; 00462 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID >> 8 ) & 0xFF; 00463 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacNetID >> 16 ) & 0xFF; 00464 00465 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); 00466 tx_buf_len += 8; 00467 00468 Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; 00469 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; 00470 00471 if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, keys.SNwkSIntKey, &mic) < 0) 00472 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00473 00474 } else if (JoinReqType == 1) { 00475 /* JoinEUI + DevEUI */ 00476 LoRaMacDevNonce = eeprom_read(EEPROM_RJCOUNT1); 00477 if (eeprom_increment_value(EEPROM_RJCOUNT1) < 0) 00478 return LORAMAC_STATUS_EEPROM_FAIL; 00479 00480 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacJoinEui, 8 ); 00481 tx_buf_len += 8; 00482 memcpyr( Radio::radio.tx_buf + tx_buf_len, LoRaMacDevEui, 8 ); 00483 tx_buf_len += 8; 00484 00485 Radio::radio.tx_buf[tx_buf_len++] = LoRaMacDevNonce & 0xFF; 00486 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevNonce >> 8 ) & 0xFF; 00487 00488 //print_buf(JSIntKey, 16, "JSIntKey"); 00489 if (LoRaMacJoinComputeMic(false, Radio::radio.tx_buf, tx_buf_len & 0xFF, JSIntKey, &mic) < 0) 00490 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00491 00492 } 00493 00494 Radio::radio.tx_buf[tx_buf_len++] = mic & 0xFF; 00495 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 8 ) & 0xFF; 00496 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 16 ) & 0xFF; 00497 Radio::radio.tx_buf[tx_buf_len++] = ( mic >> 24 ) & 0xFF; 00498 MAC_PRINTF("up-rejoin-frame len%u type%u\r\n", tx_buf_len, JoinReqType); 00499 break; 00500 #endif /* LORAWAN_JOIN_EUI */ 00501 case FRAME_TYPE_DATA_CONFIRMED_UP: 00502 //Intentional fallthrough 00503 case FRAME_TYPE_DATA_UNCONFIRMED_UP: 00504 #ifdef LORAWAN_JOIN_EUI 00505 if (!flags.IsLoRaMacNetworkJoined) 00506 { 00507 return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet 00508 } 00509 00510 if (flags.OptNeg && flags.need_ReKeyConf) { 00511 /* lorawan1v1 need rekeying confirmation */ 00512 LoRaMacStatus_t s = AddMacCommand(MOTE_MAC_REKEY_IND, 0, 0); 00513 if (s != LORAMAC_STATUS_OK) 00514 return s; 00515 if (McpsIndication.ADR_ACK_CNT > ADR_ACK_DELAY) { 00516 /* give up sending rekey indication, try joining again */ 00517 flags.IsLoRaMacNetworkJoined = false; 00518 return LORAMAC_STATUS_NO_NETWORK_JOINED; 00519 } 00520 } 00521 fcnt_up = FCntUp; 00522 #else 00523 if (flags.need_ResetConf) { 00524 LoRaMacStatus_t s = AddMacCommand(MOTE_MAC_RESET_IND, flags.OptNeg, 0); 00525 if (s != LORAMAC_STATUS_OK) 00526 return s; 00527 } 00528 fcnt_up = eeprom_read(EEPROM_FCNTUP); 00529 #endif /* LORAWAN_JOIN_EUI */ 00530 00531 00532 if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate , MacCommandsBufferIndex ) == false ) 00533 { 00534 MAC_PRINTF("LoRaMacTxPayloadLen%u, FOptsLen%u\r\n", LoRaMacTxPayloadLen, MacCommandsBufferIndex); 00535 return LORAMAC_STATUS_LENGTH_ERROR; 00536 } 00537 00538 RxWindow1Delay_us = LoRaMacParams.ReceiveDelay1_us - RADIO_WAKEUP_TIME_us; 00539 RxWindow2Delay_us = LoRaMacParams.ReceiveDelay2_us - RADIO_WAKEUP_TIME_us; 00540 00541 if( flags.SrvAckRequested == true ) 00542 { 00543 flags.SrvAckRequested = false; 00544 fCtrl->Bits.Ack = 1; 00545 } 00546 00547 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr ) & 0xFF; 00548 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; 00549 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; 00550 Radio::radio.tx_buf[tx_buf_len++] = ( LoRaMacDevAddr >> 24 ) & 0xFF; 00551 00552 Radio::radio.tx_buf[tx_buf_len++] = fCtrl->Value; 00553 00554 // FCntUp will be inserted in SendFrameOnChannel(), where MIC is inserted also 00555 tx_buf_len += 2; 00556 00557 ConfFCntUp = 0; 00558 if (flags.OptNeg) { 00559 if (macHdr->Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) { 00560 #ifdef LORAWAN_JOIN_EUI 00561 ConfFCntUp = FCntUp; 00562 #else 00563 ConfFCntUp = eeprom_read(EEPROM_FCNTUP); 00564 #endif /* LORAWAN_JOIN_EUI */ 00565 } 00566 } 00567 00568 // Copy the MAC commands which must be re-send into the MAC command buffer 00569 memcpy( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); 00570 MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; 00571 00572 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 00573 { 00574 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( flags.MacCommandsInNextTx == true ) ) 00575 { 00576 MAC_PRINTF("uplink mac-cmds %u into FOpts at %u ", MacCommandsBufferIndex, tx_buf_len); 00577 fCtrl->Bits.FOptsLen += MacCommandsBufferIndex; 00578 // Update FCtrl field with new value of OptionsLength 00579 Radio::radio.tx_buf[0x05] = fCtrl->Value; 00580 00581 /* lorawan1v1: encode FOpts using NWkSEncKey */ 00582 if (flags.OptNeg) { 00583 LoRaMacEncrypt(0, MacCommandsBuffer, MacCommandsBufferIndex, keys.NwkSEncKey, LoRaMacDevAddr, UP_LINK, fcnt_up, Radio::radio.tx_buf + tx_buf_len); 00584 tx_buf_len += MacCommandsBufferIndex; 00585 } else { 00586 for( i = 0; i < MacCommandsBufferIndex; i++ ) 00587 { 00588 Radio::radio.tx_buf[tx_buf_len++] = MacCommandsBuffer[i]; 00589 MAC_PRINTF("%02x ", MacCommandsBuffer[i]); 00590 } 00591 MAC_PRINTF(" fCtrl->Value:%02x\r\n", Radio::radio.tx_buf[0x05]); 00592 } 00593 } 00594 } 00595 else 00596 { 00597 if( ( MacCommandsBufferIndex > 0 ) && ( flags.MacCommandsInNextTx ) ) 00598 { 00599 MAC_PRINTF("uplink mac-cmds %u port0 ", MacCommandsBufferIndex); 00600 for (i = 0; i < MacCommandsBufferIndex; i++) 00601 MAC_PRINTF("%02x ", MacCommandsBuffer[i]); 00602 MAC_PRINTF("\r\n"); 00603 LoRaMacTxPayloadLen = MacCommandsBufferIndex; 00604 payload = MacCommandsBuffer; 00605 framePort = 0; 00606 } 00607 } 00608 flags.MacCommandsInNextTx = false; 00609 // Store MAC commands which must be re-send in case the device does not receive a downlink anymore 00610 MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); 00611 if( MacCommandsBufferToRepeatIndex > 0 ) 00612 { 00613 flags.MacCommandsInNextTx = true; 00614 } 00615 MacCommandsBufferIndex = 0; 00616 00617 if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 00618 { 00619 const uint8_t* keyPtr; 00620 Radio::radio.tx_buf[tx_buf_len++] = framePort; 00621 00622 if( framePort == 0 ) 00623 { 00624 DEBUG_CRYPT_BUF(keys.NwkSEncKey, 16, "NwkSEncKey", 0); 00625 keyPtr = keys.NwkSEncKey; 00626 } 00627 else 00628 { 00629 DEBUG_CRYPT_BUF(keys.AppSKey, 16, "AppSKey", 0); 00630 keyPtr = keys.AppSKey; 00631 } 00632 LoRaMacEncrypt(1, (uint8_t* ) payload, LoRaMacTxPayloadLen, keyPtr, LoRaMacDevAddr, UP_LINK, fcnt_up, Radio::radio.tx_buf + tx_buf_len); 00633 } 00634 tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; 00635 /* mic cacluation in SendFrameOnChannel() */ 00636 break; 00637 case FRAME_TYPE_PROPRIETARY: 00638 if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) ) 00639 { 00640 memcpy( Radio::radio.tx_buf + tx_buf_len, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen ); 00641 tx_buf_len = tx_buf_len + LoRaMacTxPayloadLen; 00642 } 00643 break; 00644 default: 00645 return LORAMAC_STATUS_SERVICE_UNKNOWN; 00646 } 00647 00648 flags.uplink_mtype = macHdr->Bits.MType ; 00649 flags.uplink_in_progress = LoRaMacParams.NbTrans ; 00650 00651 return LORAMAC_STATUS_OK; 00652 } // ..PrepareFrame() 00653 00654 LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) 00655 { 00656 LoRaMacFrameCtrl_t fCtrl; 00657 LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; 00658 00659 fCtrl.Value = 0; 00660 fCtrl.Bits.FOptsLen = 0; 00661 if( LoRaMacDeviceClass == CLASS_B ) 00662 { 00663 fCtrl.Bits.FPending = 1; 00664 } 00665 else 00666 { 00667 fCtrl.Bits.FPending = 0; 00668 } 00669 fCtrl.Bits.Ack = false; 00670 fCtrl.Bits.AdrAckReq = false; 00671 fCtrl.Bits.Adr = flags.AdrCtrlOn; 00672 00673 // Prepare the frame 00674 status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize ); 00675 00676 // Validate status 00677 if( status != LORAMAC_STATUS_OK ) 00678 { 00679 return status; 00680 } 00681 00682 // Reset confirm parameters 00683 McpsConfirm.NbRetries = 0; 00684 McpsConfirm.AckReceived = false; 00685 00686 status = LORAMAC_STATUS_OK; 00687 if (flags.rxing) 00688 function_pending = region_ScheduleTx; 00689 else 00690 region_ScheduleTx( ); 00691 00692 return status; 00693 } // ..Send() 00694 00695 LoRaMacStatus_t waitingFor; 00696 00697 LoRaMacStatus_t 00698 LoRaMacMlmeRequest( const MlmeReq_t *mlmeRequest ) 00699 { 00700 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; 00701 #ifdef LORAWAN_JOIN_EUI 00702 LoRaMacHeader_t macHdr; 00703 #endif /* LORAWAN_JOIN_EUI */ 00704 00705 if( mlmeRequest == NULL ) 00706 { 00707 return LORAMAC_STATUS_PARAMETER_INVALID; 00708 } 00709 00710 if (flags.uplink_in_progress > 0) { 00711 MAC_PRINTF("LoRaMacMlmeRequest() BUSY\r\n"); 00712 return waitingFor; 00713 } 00714 00715 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MLMEREQ; 00716 MlmeIndication.MlmeIndication = mlmeRequest->Type; 00717 00718 waitingFor = LORAMAC_STATUS_WAITING_FOR_TXSTART; 00719 00720 MAC_PRINTF("LoRaMacMlmeRequest() "); 00721 switch( mlmeRequest->Type ) 00722 { 00723 #ifdef LORAWAN_JOIN_EUI 00724 case MLME_JOIN: 00725 { 00726 if( ( mlmeRequest->Req.Join.DevEui == NULL ) || 00727 ( mlmeRequest->Req.Join.JoinEui == NULL ) || 00728 ( mlmeRequest->Req.Join.NwkKey == NULL ) || 00729 ( mlmeRequest->Req.Join.NbTrials == 0 ) ) 00730 { 00731 return LORAMAC_STATUS_PARAMETER_INVALID; 00732 } 00733 00734 LoRaMacDevEui = mlmeRequest->Req.Join.DevEui; 00735 LoRaMacJoinEui = mlmeRequest->Req.Join.JoinEui; 00736 RootNwkKey = mlmeRequest->Req.Join.NwkKey; 00737 RootAppKey = mlmeRequest->Req.Join.AppKey; 00738 MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials; 00739 00740 /*if (RootAppKey != NULL) {*/ 00741 LoRaMacGenerateJoinKey(0x05, RootNwkKey, LoRaMacDevEui, JSEncKey); 00742 //print_buf(JSEncKey, 16, "new-JSEncKey"); 00743 LoRaMacGenerateJoinKey(0x06, RootNwkKey, LoRaMacDevEui, JSIntKey); 00744 //print_buf(JSIntKey, 16, "new-JSIntKey"); 00745 /*}*/ 00746 JoinReqType = 0xff; 00747 00748 // Reset variable JoinRequestTrials 00749 MlmeIndication.JoinRequestTrials = 0; 00750 00751 // Setup header information 00752 macHdr.Value = 0; 00753 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; 00754 00755 ResetMacParameters( ); 00756 00757 // Add a +1, since we start to count from 0 00758 LoRaMacParams.ChannelsDatarate = region_AlternateDatarate( MlmeIndication.JoinRequestTrials + 1 ); 00759 00760 status = Send( &macHdr, 0, NULL, 0 ); 00761 break; 00762 } 00763 case MLME_REJOIN_1: 00764 if ( mlmeRequest->Req.Join.JoinEui == NULL ) 00765 return LORAMAC_STATUS_PARAMETER_INVALID; 00766 00767 LoRaMacJoinEui = mlmeRequest->Req.Join.JoinEui; 00768 JoinReqType = 0x01; 00769 // fall-thru 00770 case MLME_REJOIN_0: 00771 case MLME_REJOIN_2: // Type2 can only be sent via mac-command 00772 if( ( mlmeRequest->Req.Join.DevEui == NULL ) || 00773 ( mlmeRequest->Req.Join.NwkKey == NULL ) || 00774 ( mlmeRequest->Req.Join.NbTrials == 0 ) ) 00775 { 00776 MAC_PRINTF(" (missing %p %p %d)\n", 00777 mlmeRequest->Req.Join.DevEui, 00778 mlmeRequest->Req.Join.NwkKey, 00779 mlmeRequest->Req.Join.NbTrials 00780 ); 00781 return LORAMAC_STATUS_PARAMETER_INVALID; 00782 } 00783 00784 RootNwkKey = mlmeRequest->Req.Join.NwkKey; 00785 LoRaMacDevEui = mlmeRequest->Req.Join.DevEui; 00786 LoRaMacGenerateJoinKey(0x05, RootNwkKey, LoRaMacDevEui, JSEncKey); 00787 LoRaMacGenerateJoinKey(0x06, RootNwkKey, LoRaMacDevEui, JSIntKey); 00788 00789 RootAppKey = mlmeRequest->Req.Join.AppKey; 00790 00791 macHdr.Value = 0; 00792 macHdr.Bits.MType = FRAME_TYPE_REJOIN_REQ; 00793 00794 if (mlmeRequest->Type == MLME_REJOIN_0) 00795 JoinReqType = 0x00; 00796 else if (mlmeRequest->Type == MLME_REJOIN_2) 00797 JoinReqType = 0x02; 00798 00799 MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials; 00800 00801 status = Send( &macHdr, 0, NULL, 0 ); 00802 break; 00803 #endif /* LORAWAN_JOIN_EUI */ 00804 case MLME_LINK_CHECK: 00805 status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 ); 00806 break; 00807 case MLME_TIME_REQ: 00808 status = AddMacCommand( MOTE_MAC_DEVICE_TIME_REQ, 0, 0 ); 00809 break; 00810 case MLME_TXCW: 00811 status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout ); 00812 break; 00813 case MLME_PING_SLOT_INFO: 00814 { 00815 uint8_t value = mlmeRequest->Req.PingSlotInfo.Value; 00816 status = LoRaMacMlmeRequestClassB(mlmeRequest); 00817 if (status == LORAMAC_STATUS_OK) 00818 status = AddMacCommandClassB( MOTE_MAC_PING_SLOT_INFO_REQ, value, 0 ); 00819 break; 00820 } 00821 case MLME_BEACON_ACQUISITION: 00822 case MLME_BEACON_TIMING: 00823 status = LoRaMacMlmeRequestClassB(mlmeRequest); 00824 break; 00825 default: 00826 break; 00827 } // ...switch( mlmeRequest->Type ) 00828 00829 if( status != LORAMAC_STATUS_OK ) 00830 MlmeConfirm.MlmeRequest = MLME_NONE; 00831 else 00832 { 00833 MlmeConfirm.MlmeRequest = mlmeRequest->Type; 00834 } 00835 00836 return status; 00837 } // ..LoRaMacMlmeRequest() 00838 00839 LoRaMacStatus_t 00840 LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet ) 00841 { 00842 LoRaMacStatus_t status = LORAMAC_STATUS_OK; 00843 00844 switch( mibGet->Type ) { 00845 case MIB_APP_SKEY: 00846 mibGet->Param.key = keys.AppSKey; 00847 break; 00848 case MIB_FNwkSIntKey: 00849 mibGet->Param.key = keys.FNwkSIntKey; 00850 break; 00851 case MIB_SNwkSIntKey: 00852 mibGet->Param.key = keys.SNwkSIntKey; 00853 break; 00854 case MIB_NwkSEncKey: 00855 mibGet->Param.key = keys.NwkSEncKey; 00856 break; 00857 case MIB_NwkSKey: 00858 /* lorawan 1.0 */ 00859 mibGet->Param.key = keys.FNwkSIntKey; 00860 break; 00861 case MIB_RX2_CHANNEL: 00862 mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel ; 00863 break; 00864 case MIB_DEVICE_CLASS: 00865 mibGet->Param.Class = LoRaMacDeviceClass; 00866 break; 00867 case MIB_ADR: 00868 mibGet->Param.AdrEnable = flags.AdrCtrlOn; 00869 break; 00870 case MIB_DEV_ADDR: 00871 mibGet->Param.DevAddr = LoRaMacDevAddr; 00872 break; 00873 case MIB_PUBLIC_NETWORK: 00874 mibGet->Param.EnablePublicNetwork = flags.PublicNetwork; 00875 break; 00876 case MIB_CHANNELS_MASK: 00877 mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask ; 00878 LoRaMacParams.NbEnabledChannels = region_CountNbEnabledChannels(); 00879 break; 00880 case MIB_MAX_LISTEN_TIME: 00881 mibGet->Param.MaxListenTime = LoRaMacParams.MaxListenTime; 00882 break; 00883 #ifdef LORAWAN_JOIN_EUI 00884 case MIB_NETWORK_JOINED: 00885 mibGet->Param.IsNetworkJoined = flags.IsLoRaMacNetworkJoined; 00886 break; 00887 #endif /* LORAWAN_JOIN_EUI */ 00888 } // ..switch( mibGet->Type ) 00889 00890 return status; 00891 } 00892 00893 00894 LoRaMacStatus_t 00895 LoRaMacQueryTxPossible(uint8_t size, LoRaMacTxInfo_t* txInfo) 00896 { 00897 int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate ; 00898 uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; 00899 00900 if( txInfo == NULL ) 00901 { 00902 return LORAMAC_STATUS_PARAMETER_INVALID; 00903 } 00904 00905 //AdrNextDr( flags.AdrCtrlOn, false, &datarate ); 00906 00907 txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate]; 00908 00909 if( txInfo->CurrentPayloadSize >= fOptLen ) 00910 { 00911 txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; 00912 } 00913 else 00914 { 00915 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; 00916 } 00917 00918 if( ValidatePayloadLength( size, datarate, 0 ) == false ) 00919 { 00920 return LORAMAC_STATUS_LENGTH_ERROR; 00921 } 00922 00923 if( ValidatePayloadLength( size, datarate, fOptLen ) == false ) 00924 { 00925 return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; 00926 } 00927 00928 return LORAMAC_STATUS_OK; 00929 } 00930 00931 LoRaMacStatus_t 00932 LoRaMacMcpsRequest( McpsReq_t *mcpsRequest ) 00933 { 00934 LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN; 00935 LoRaMacHeader_t macHdr; 00936 uint8_t fPort = 0; 00937 void *fBuffer; 00938 uint16_t fBufferSize; 00939 int8_t datarate; 00940 bool readyToSend = false; 00941 00942 if( mcpsRequest == NULL ) 00943 { 00944 return LORAMAC_STATUS_PARAMETER_INVALID; 00945 } 00946 if (flags.uplink_in_progress > 0) { 00947 MAC_PRINTF("LoRaMacMcpsRequest() in_progress BUSY%u\r\n", flags.uplink_in_progress); 00948 return waitingFor; 00949 } 00950 if (ConfFCntUp > 0) { 00951 // unacknowledged confirmed uplink pending, must resend previous uplink 00952 MAC_PRINTF("LoRaMacMcpsRequest() ConfFCntUp%u\r\n", ConfFCntUp); 00953 return LORAMAC_STATUS_BUSY_UPCONF; 00954 } 00955 00956 #ifdef LORAWAN_JOIN_EUI 00957 if (!flags.IsLoRaMacNetworkJoined) 00958 return LORAMAC_STATUS_NO_NETWORK_JOINED; 00959 #endif /* LORAWAN_JOIN_EUI */ 00960 00961 macHdr.Value = 0; 00962 memset ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) ); 00963 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_MCPSREQ; 00964 McpsConfirm.McpsRequest = mcpsRequest->Type; 00965 00966 datarate = mcpsRequest->Req.Datarate; 00967 fBufferSize = mcpsRequest->Req.fBufferSize; 00968 fBuffer = mcpsRequest->Req.fBuffer; 00969 readyToSend = true; 00970 00971 switch( mcpsRequest->Type ) 00972 { 00973 case MCPS_UNCONFIRMED: 00974 { 00975 macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; 00976 fPort = mcpsRequest->Req.fPort; 00977 break; 00978 } 00979 case MCPS_CONFIRMED: 00980 { 00981 //AckTimeoutRetriesCounter = 1; 00982 //AckTimeoutRetries = mcpsRequest->Req.NbTrials; 00983 00984 macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP; 00985 fPort = mcpsRequest->Req.fPort; 00986 break; 00987 } 00988 case MCPS_PROPRIETARY: 00989 { 00990 macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY; 00991 break; 00992 } 00993 default: 00994 readyToSend = false; 00995 break; 00996 } 00997 00998 if( readyToSend == true ) 00999 { 01000 if( flags.AdrCtrlOn == false ) 01001 { 01002 if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true ) 01003 { 01004 LoRaMacParams.ChannelsDatarate = datarate; 01005 } 01006 else 01007 { 01008 return LORAMAC_STATUS_PARAMETER_INVALID; 01009 } 01010 } 01011 01012 status = Send( &macHdr, fPort, fBuffer, fBufferSize ); 01013 } 01014 01015 return status; 01016 } // ..LoRaMacMcpsRequest() 01017 01018 __attribute__((weak)) LoRaMacStatus_t 01019 SwitchClassB( DeviceClass_t deviceClass ) 01020 { 01021 return LORAMAC_STATUS_DEVICE_OFF; 01022 } 01023 01024 void 01025 RxWindowSetup( unsigned freq, int8_t datarate, unsigned bandwidth, uint16_t timeout) 01026 { 01027 uint8_t downlinkDatarate = Datarates[datarate]; 01028 unsigned bwKHz; 01029 01030 switch (bandwidth) { 01031 case 0: bwKHz = 125; break; 01032 case 1: bwKHz = 250; break; 01033 case 2: bwKHz = 500; break; 01034 default: bwKHz = 0; /* fail */ break; 01035 } 01036 01037 MAC_PRINTF(" rxwin-dr%u-sf%u ", datarate, downlinkDatarate); 01038 Radio::SetChannel( freq ); 01039 01040 // Store downlink datarate 01041 McpsIndication.RxDatarate = ( uint8_t ) datarate; 01042 01043 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868) || defined(USE_BAND_ARIB_8CH) 01044 if( datarate == DR_7 ) 01045 { 01046 Radio::GFSKModemConfig(downlinkDatarate * 1000, 50, 25000); 01047 Radio::GFSKPacketConfig(5, false, true); 01048 } 01049 else 01050 { 01051 Radio::LoRaModemConfig(bwKHz, downlinkDatarate, 1); 01052 Radio::LoRaPacketConfig(8, false, false, true); 01053 Radio::SetLoRaSymbolTimeout(timeout); 01054 } 01055 #elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 01056 Radio::LoRaModemConfig(bwKHz, downlinkDatarate, 1); 01057 Radio::LoRaPacketConfig(8, false, false, true); 01058 Radio::SetLoRaSymbolTimeout(timeout); 01059 #endif 01060 01061 Radio::SetRxMaxPayloadLength(MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD); 01062 } //..RxWindowSetup() 01063 01064 LowPowerTimeout RxWindowEvent1; 01065 LowPowerTimeout RxWindowEvent2; 01066 01067 static void RxWindow2Start( void ) 01068 { 01069 /* TODO: join accept rx2 channel unique */ 01070 if (LoRaMacDeviceClass == CLASS_C) 01071 Radio::Rx( 0 ); // Continuous mode 01072 else 01073 Radio::Rx( LoRaMacParams.MaxRxWindow_us ); 01074 01075 McpsIndication.RxSlot = 2; 01076 } 01077 01078 static void mlme_confirm(LoRaMacEventInfoStatus_t status) 01079 { 01080 MlmeConfirm.Status = status; 01081 01082 if (MlmeConfirm.MlmeRequest != MLME_NONE) { 01083 if (LoRaMacPrimitives->MacMlmeConfirm != NULL) 01084 LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm ); 01085 01086 MlmeConfirm.MlmeRequest = MLME_NONE; 01087 MlmeIndication.MlmeIndication = MLME_NONE; 01088 } 01089 } 01090 01091 static void mcps_confirm(LoRaMacEventInfoStatus_t status) 01092 { 01093 McpsConfirm.Status = status; 01094 01095 if (McpsConfirm.McpsRequest != MCPS_NONE) { 01096 if (LoRaMacPrimitives->MacMcpsConfirm) 01097 LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm ); 01098 01099 McpsConfirm.McpsRequest = MCPS_NONE; 01100 } 01101 } 01102 01103 #if defined(LORAWAN_JOIN_EUI) 01104 static struct { 01105 bool forced; 01106 uint8_t dr; 01107 uint8_t type; 01108 uint8_t retries; 01109 uint8_t Period; 01110 LowPowerTimeout event; 01111 struct { 01112 uint8_t MaxTimeN; 01113 uint8_t MaxCountN; 01114 unsigned uplinks_since; 01115 bool enabled; 01116 } type0; 01117 } rejoin; 01118 void _rejoin_retry(void); 01119 01120 void rejoin_retry() 01121 { 01122 LoRaMacStatus_t status; 01123 LoRaMacHeader_t macHdr; 01124 01125 macHdr.Value = 0; 01126 macHdr.Bits.MType = FRAME_TYPE_REJOIN_REQ; 01127 LoRaMacParams.ChannelsDatarate = rejoin.dr; 01128 JoinReqType = rejoin.type; 01129 status = Send( &macHdr, 0, NULL, 0 ); 01130 if (status != LORAMAC_STATUS_OK) { 01131 MAC_PRINTF("rejoin-send-failed%d ", status); 01132 } 01133 01134 MAC_PRINTF("Rejoin%u ", JoinReqType); 01135 if (rejoin.forced) { 01136 if (--rejoin.retries > 0) { 01137 us_timestamp_t period_us = (1 << rejoin.Period) + random_at_most(32000000); 01138 rejoin.event.attach_us(_rejoin_retry, period_us); 01139 MAC_PRINTF("try%u", rejoin.retries); 01140 } else 01141 rejoin.forced = false; 01142 } 01143 MAC_PRINTF("\r\n"); 01144 } 01145 01146 void _rejoin_retry() 01147 { 01148 if (flags.uplink_in_progress > 0) { 01149 function_pending = rejoin_retry; 01150 } else 01151 rejoin_retry(); 01152 } 01153 #endif /* LORAWAN_JOIN_EUI */ 01154 01155 void 01156 finish_uplink(LoRaMacEventInfoStatus_t status) 01157 { 01158 if ((flags.uplink_in_progress > 0 && McpsIndication.RxSlot == 2) || status == LORAMAC_EVENT_INFO_STATUS_OK) { 01159 if ((uplinkMHDR->Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP && status == LORAMAC_EVENT_INFO_STATUS_OK) || uplinkMHDR->Bits.MType != FRAME_TYPE_DATA_CONFIRMED_UP) { 01160 flags.uplink_in_progress--; 01161 } 01162 01163 if (flags.uplink_in_progress > 0) { 01164 McpsIndication.Status = status; 01165 if (LoRaMacPrimitives->MacMcpsIndication != NULL) 01166 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); 01167 01168 if (flags.rxing) 01169 function_pending = region_ScheduleTx; 01170 else { 01171 region_ScheduleTx( ); 01172 } 01173 } else 01174 region_session_start(status); 01175 } 01176 01177 #ifdef LORAWAN_JOIN_EUI 01178 LoRaMacHeader_t macHdr; 01179 macHdr.Value = Radio::radio.tx_buf[0]; 01180 if (macHdr.Bits.MType != FRAME_TYPE_REJOIN_REQ) { 01181 if (rejoin.type0.enabled && --rejoin.type0.uplinks_since == 0) { 01182 rejoin.type0.uplinks_since = 1 << (rejoin.type0.MaxCountN + 4); 01183 01184 rejoin.type = 0; 01185 rejoin_retry(); 01186 return; 01187 } 01188 } 01189 #endif /* LORAWAN_JOIN_EUI */ 01190 01191 waitingFor = LORAMAC_STATUS_OK; 01192 01193 if (function_pending != NULL) { 01194 function_pending(); 01195 function_pending = NULL; 01196 } 01197 } // ..finish_uplink() 01198 01199 LowPowerTimeout TxDelayedEvent; 01200 01201 void OnTxDelayedIsr() 01202 { 01203 flags.OnTxDelayed = true; 01204 } 01205 01206 static void OnTxDelayedTimerEvent() 01207 { 01208 MAC_PRINTF("OnTxDelayedTimerEvent() "); 01209 #ifdef LORAWAN_JOIN_EUI 01210 LoRaMacHeader_t macHdr; 01211 LoRaMacFrameCtrl_t fCtrl; 01212 01213 if (!flags.IsLoRaMacNetworkJoined) 01214 { 01215 // Add a +1, since we start to count from 0 01216 LoRaMacParams.ChannelsDatarate = region_AlternateDatarate( MlmeIndication.JoinRequestTrials + 1 ); 01217 01218 macHdr.Value = 0; 01219 macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; 01220 01221 fCtrl.Value = 0; 01222 fCtrl.Bits.Adr = flags.AdrCtrlOn; 01223 01224 /* In case of join request retransmissions, the stack must prepare 01225 * the frame again, because the network server keeps track of the random 01226 * LoRaMacDevNonce values to prevent reply attacks. */ 01227 PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); 01228 /* TODO PrepareFrame() != LORAMAC_STATUS_OK */ 01229 } 01230 #endif /* LORAWAN_JOIN_EUI */ 01231 01232 if (flags.rxing) 01233 function_pending = region_ScheduleTx; 01234 else { 01235 region_ScheduleTx( ); 01236 } 01237 } // ..OnTxDelayedTimerEvent() 01238 01239 static void RxWindow2Setup(void) 01240 { 01241 MAC_PRINTF("RxWindow2Setup %uhz dr%u", LoRaMacParams.Rx2Channel .FrequencyHz, LoRaMacParams.Rx2Channel .Datarate); 01242 RxWindowSetup( 01243 LoRaMacParams.Rx2Channel .FrequencyHz, 01244 LoRaMacParams.Rx2Channel .Datarate, 01245 region_GetRxBandwidth( LoRaMacParams.Rx2Channel .Datarate ), 01246 region_GetRxSymbolTimeout( LoRaMacParams.Rx2Channel .Datarate ) 01247 ); 01248 01249 waitingFor = LORAMAC_STATUS_WAITING_FOR_RX2; 01250 } 01251 01252 static void 01253 PrepareRxDoneAbort(LoRaMacEventInfoStatus_t status) 01254 { 01255 MAC_PRINTF("rxAbort "); 01256 if( ( McpsIndication.RxSlot == 1 ) && ( LoRaMacDeviceClass == CLASS_C ) ) 01257 { 01258 RxWindow2Setup(); 01259 RxWindow2Start(); // start continuous rx2 reception 01260 } 01261 01262 #ifdef LORAWAN_JOIN_EUI 01263 if (!flags.IsLoRaMacNetworkJoined && LoRaMacJoinEui != NULL && LoRaMacDevEui == NULL) { 01264 TxDelayedEvent.attach_us(OnTxDelayedIsr, 1000000); 01265 MAC_PRINTF("RxDoneAbort-join-tx-delay"); 01266 } 01267 #endif /* LORAWAN_JOIN_EUI */ 01268 01269 01270 McpsIndication.Status = status; 01271 if (LoRaMacPrimitives->MacMcpsIndication != NULL) 01272 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxAbort 01273 01274 mcps_confirm(status); // RXAbort 01275 mlme_confirm(status); 01276 01277 finish_uplink(status); 01278 01279 MAC_PRINTF("\r\n"); 01280 01281 } // ..PrepareRxDoneAbort() 01282 01283 01284 static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass ) 01285 { 01286 LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID; 01287 01288 switch( LoRaMacDeviceClass ) 01289 { 01290 case CLASS_A: 01291 { 01292 MAC_PRINTF("CLASS_A "); 01293 if (deviceClass == CLASS_B) 01294 status = SwitchClassB(deviceClass); 01295 01296 if (deviceClass == CLASS_C) 01297 { 01298 MAC_PRINTF("->C "); 01299 LoRaMacDeviceClass = deviceClass; 01300 RxWindow2Setup(); 01301 RxWindow2Start(); // continuous rx2 reception 01302 if (flags.OptNeg) { 01303 AddMacCommand(MOTE_MAC_MODE_IND, LoRaMacDeviceClass, 0); 01304 } 01305 01306 status = LORAMAC_STATUS_OK; 01307 } 01308 break; 01309 } 01310 case CLASS_B: 01311 { 01312 MAC_PRINTF("CLASS_B "); 01313 if( deviceClass == CLASS_A ) 01314 { 01315 MAC_PRINTF("->A "); 01316 LoRaMacDeviceClass = deviceClass; 01317 status = LORAMAC_STATUS_OK; 01318 } 01319 break; 01320 } 01321 case CLASS_C: 01322 { 01323 MAC_PRINTF("CLASS_C "); 01324 if( deviceClass == CLASS_A ) 01325 { 01326 MAC_PRINTF("->A "); 01327 LoRaMacDeviceClass = deviceClass; 01328 if (flags.OptNeg) { 01329 AddMacCommand(MOTE_MAC_MODE_IND, LoRaMacDeviceClass, 0); 01330 } 01331 01332 // Set the radio into sleep to setup a defined state 01333 Radio::Sleep(); 01334 01335 status = LORAMAC_STATUS_OK; 01336 } 01337 break; 01338 } 01339 } 01340 01341 MAC_PRINTF("\r\n"); 01342 return status; 01343 } 01344 01345 LoRaMacStatus_t 01346 LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet ) 01347 { 01348 LoRaMacStatus_t status = LORAMAC_STATUS_OK; 01349 01350 if (mibSet == NULL) 01351 return LORAMAC_STATUS_PARAMETER_INVALID; 01352 01353 if (flags.uplink_in_progress > 0) 01354 return waitingFor; 01355 01356 switch (mibSet->Type) { 01357 case MIB_CHANNELS_MASK: 01358 if( mibSet->Param.ChannelsMask ) 01359 { 01360 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 01361 bool chanMaskState = true; 01362 01363 #if defined( USE_BAND_915_HYBRID ) 01364 chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask ); 01365 #endif 01366 if( chanMaskState == true ) 01367 { 01368 if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 2 ) && 01369 ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) ) 01370 { 01371 status = LORAMAC_STATUS_PARAMETER_INVALID; 01372 } 01373 else 01374 { 01375 memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask , 01376 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); 01377 for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ ) 01378 { 01379 // Disable channels which are no longer available 01380 ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask [i]; 01381 } 01382 } 01383 } 01384 else 01385 { 01386 status = LORAMAC_STATUS_PARAMETER_INVALID; 01387 } 01388 #elif defined( USE_BAND_470 ) 01389 memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask , 01390 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); 01391 #else 01392 memcpy( ( uint8_t* ) LoRaMacParams.ChannelsMask , 01393 ( uint8_t* ) mibSet->Param.ChannelsMask, 2 ); 01394 #endif 01395 LoRaMacParams.NbEnabledChannels = region_CountNbEnabledChannels(); 01396 } 01397 else 01398 { 01399 status = LORAMAC_STATUS_PARAMETER_INVALID; 01400 } 01401 break; 01402 #ifdef LORAWAN_JOIN_EUI 01403 /* values which cannot be set in OTA */ 01404 case MIB_NwkSKey: 01405 case MIB_SNwkSIntKey: 01406 case MIB_NwkSEncKey: 01407 case MIB_FNwkSIntKey: 01408 case MIB_APP_SKEY: 01409 case MIB_DEV_ADDR: 01410 case MIB_NETWORK_JOINED: 01411 #endif 01412 case MIB_RX2_CHANNEL: 01413 return LORAMAC_STATUS_PARAMETER_INVALID; 01414 case MIB_DEVICE_CLASS: 01415 status = SwitchClass(mibSet->Param.Class); 01416 break; 01417 case MIB_ADR: 01418 flags.AdrCtrlOn = mibSet->Param.AdrEnable; 01419 break; 01420 case MIB_PUBLIC_NETWORK: 01421 flags.PublicNetwork = mibSet->Param.EnablePublicNetwork; 01422 Radio::SetPublicNetwork( flags.PublicNetwork ); 01423 break; 01424 case MIB_MAX_LISTEN_TIME: 01425 LoRaMacParams.MaxListenTime = mibSet->Param.MaxListenTime; 01426 break; 01427 #ifndef LORAWAN_JOIN_EUI 01428 case MIB_SNwkSIntKey: 01429 flags.have_SNwkSIntKey = 1; 01430 memcpy( keys.SNwkSIntKey, mibSet->Param.key, sizeof(keys.SNwkSIntKey) ); 01431 if (flags.have_NwkSEncKey) { 01432 flags.OptNeg = 1; 01433 flags.need_ResetConf = 1; 01434 } 01435 break; 01436 case MIB_NwkSEncKey: 01437 flags.have_NwkSEncKey = 1; 01438 memcpy( keys.NwkSEncKey, mibSet->Param.key, sizeof(keys.NwkSEncKey) ); 01439 if (flags.have_SNwkSIntKey) { 01440 flags.OptNeg = 1; 01441 flags.need_ResetConf = 1; 01442 } 01443 break; 01444 case MIB_APP_SKEY: 01445 memcpy( keys.AppSKey, mibSet->Param.key, sizeof( keys.AppSKey ) ); 01446 break; 01447 case MIB_FNwkSIntKey: 01448 memcpy( keys.FNwkSIntKey, mibSet->Param.key, sizeof( keys.FNwkSIntKey ) ); 01449 break; 01450 case MIB_NwkSKey: 01451 /* lorawan 1.0 ABP */ 01452 memcpy( keys.FNwkSIntKey, mibSet->Param.key, sizeof( keys.FNwkSIntKey ) ); 01453 memcpy( keys.SNwkSIntKey, mibSet->Param.key, sizeof( keys.SNwkSIntKey) ); 01454 memcpy( keys.NwkSEncKey, mibSet->Param.key, sizeof( keys.NwkSEncKey) ); 01455 flags.OptNeg = 0; 01456 break; 01457 case MIB_DEV_ADDR: 01458 LoRaMacDevAddr = mibSet->Param.DevAddr; 01459 break; 01460 #endif /* !LORAWAN_JOIN_EUI */ 01461 } // ..switch( mibSet->Type ) 01462 01463 return status; 01464 } // ..LoRaMacMibSetRequestConfirm() 01465 01466 __attribute__((weak)) LoRaMacStatus_t 01467 LoRaMacClassBInitialization( void ) 01468 { 01469 return LORAMAC_STATUS_OK; 01470 } 01471 01472 01473 static void RxWindow1Start( void ) 01474 { 01475 if (LoRaMacDeviceClass == CLASS_C) { 01476 Radio::Standby(); 01477 region_rx1_setup(Channel); 01478 } 01479 01480 Radio::Rx( LoRaMacParams.MaxRxWindow_us ); 01481 01482 McpsIndication.RxSlot = 1; 01483 } 01484 01485 volatile us_timestamp_t tx_done_at; 01486 01487 static void OnRadioTxDone( ) 01488 { 01489 if ((RxWindow1Delay_us < 100000 || RxWindow1Delay_us > 10000000) || 01490 (RxWindow2Delay_us < 100000 || RxWindow2Delay_us > 10000000)) 01491 { 01492 PrepareRxDoneAbort(LORAMAC_EVENT_INFO_BAD_RX_DELAY); 01493 return; 01494 } 01495 // Setup timers 01496 RxWindowEvent1.attach_us(RxWindow1Start, RxWindow1Delay_us); 01497 waitingFor = LORAMAC_STATUS_WAITING_FOR_RX1; 01498 McpsIndication.RxSlot = 0; 01499 01500 tx_done_at = Radio::irqAt; 01501 01502 if (LoRaMacDeviceClass != CLASS_C) 01503 { 01504 RxWindowEvent2.attach_us(RxWindow2Start, RxWindow2Delay_us); 01505 region_rx1_setup(Channel); 01506 Radio::Sleep(); 01507 } 01508 else 01509 { 01510 RxWindow2Setup(); 01511 RxWindow2Start(); 01512 // simulate timeout to complete uplink 01513 RxWindowEvent2.attach_us(OnRadioRxTimeout, RxWindow2Delay_us + 256000); 01514 } 01515 01516 // Store last tx channel 01517 //LastTxChannel = Channel; 01518 #ifdef DUTY_ENABLE 01519 DutyTxDone(at_us); 01520 #endif /* DUTY_ENABLE */ 01521 01522 } // ..OnRadioTxDone() 01523 01524 static void OnRadioTxTimeout( void ) 01525 { 01526 if( LoRaMacDeviceClass != CLASS_C ) 01527 { 01528 Radio::Sleep(); 01529 } 01530 else 01531 { 01532 RxWindow2Setup(); 01533 RxWindow2Start(); 01534 } 01535 01536 finish_uplink(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); 01537 01538 mcps_confirm(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); 01539 mlme_confirm(LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT); 01540 } // ..OnRadioTxTimeout() 01541 01542 __attribute__((weak)) bool 01543 beacon_rx_done_payload(uint16_t size) 01544 { 01545 return false; 01546 } 01547 01548 static void 01549 print_mtype(uint8_t mt) 01550 { 01551 #ifdef MAC_DEBUG 01552 const char* cp; 01553 switch (mt) { 01554 #ifdef LORAWAN_JOIN_EUI 01555 case FRAME_TYPE_JOIN_REQ: cp = "JOIN_REQ "; break; 01556 case FRAME_TYPE_JOIN_ACCEPT: cp = "JOIN_ACC "; break; 01557 case FRAME_TYPE_REJOIN_REQ: cp = "REJOIN_REQ"; break; 01558 #endif /* LORAWAN_JOIN_EUI */ 01559 case FRAME_TYPE_DATA_UNCONFIRMED_UP: cp = "UNCONF_UP"; break; 01560 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: cp = "UNCONF_DN"; break; 01561 case FRAME_TYPE_DATA_CONFIRMED_UP: cp = "CONF_UP"; break; 01562 case FRAME_TYPE_DATA_CONFIRMED_DOWN: cp = "CONF_DN"; break; 01563 case FRAME_TYPE_PROPRIETARY: cp = "P"; break; 01564 default: return; 01565 } 01566 MAC_PRINTF("MTYPE_%s ", cp); 01567 #endif /* MAC_DEBUG */ 01568 } 01569 01570 /* bool a: true=AFCntDown, false=NFCntDown */ 01571 uint32_t get_fcntdwn(bool a) 01572 { 01573 #ifdef LORAWAN_JOIN_EUI 01574 if (a) 01575 return AFCntDown; 01576 else 01577 return NFCntDown; 01578 #else 01579 if (a) 01580 return eeprom_read(EEPROM_AFCNTDWN); 01581 else 01582 return eeprom_read(EEPROM_NFCNTDWN); 01583 #endif 01584 } 01585 01586 __attribute__((weak)) bool 01587 ProcessMacCommandsClassB(const uint8_t* payload, uint8_t* macIndex) 01588 { 01589 return false; /* false: not taken */ 01590 } 01591 01592 01593 static bool ValidateDatarate( int8_t datarate, uint16_t* channelsMask ) 01594 { 01595 if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false ) 01596 { 01597 return false; 01598 } 01599 for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ ) 01600 { 01601 for( uint8_t j = 0; j < 16; j++ ) 01602 { 01603 if( ( ( channelsMask[k] & ( 1 << j ) ) != 0 ) ) 01604 {// Check datarate validity for enabled channels 01605 if( ValueInRange( datarate, Channels[i + j].DrRange.Fields.Min, Channels[i + j].DrRange.Fields.Max ) == true ) 01606 { 01607 // At least 1 channel has been found we can return OK. 01608 return true; 01609 } 01610 } 01611 } 01612 } 01613 return false; 01614 } 01615 01616 static bool Rx2FreqInRange( uint32_t freq ) 01617 { 01618 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) || defined (USE_BAND_ARIB_8CH) 01619 if( Radio::CheckRfFrequency( freq ) == true ) 01620 #elif defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 01621 if( ( Radio::CheckRfFrequency( freq ) == true ) && 01622 ( freq >= LORAMAC_FIRST_RX1_CHANNEL ) && 01623 ( freq <= LORAMAC_LAST_RX1_CHANNEL ) && 01624 ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX1_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX1_CHANNEL ) == 0 ) ) 01625 #endif 01626 { 01627 return true; 01628 } 01629 return false; 01630 } 01631 01632 __attribute__((weak)) void 01633 deviceTimeClassB(uint32_t secs, uint32_t subsecs) 01634 { 01635 } 01636 01637 /* return -1 for unknown mac cmd */ 01638 static int 01639 ProcessMacCommands(const uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, float snr) 01640 { 01641 uint8_t buf[2]; 01642 int ret = 0; 01643 01644 MACC_PRINTF("ProcessMacCommands(, %u, %u,,) ", macIndex, commandsSize); 01645 while (macIndex < commandsSize) 01646 { 01647 MACC_PRINTF("ProcessMacCommands %u(0x%02x): ", macIndex, payload[macIndex]); 01648 // Decode Frame MAC commands 01649 switch (payload[macIndex++]) 01650 { 01651 case SRV_MAC_LINK_CHECK_ANS: 01652 MACC_PRINTF("LINK_CHECK_ANS "); 01653 buf[0] = payload[macIndex++]; 01654 buf[1] = payload[macIndex++]; 01655 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01656 MlmeConfirm.fields.link.DemodMargin = buf[0]; 01657 MlmeConfirm.fields.link.NbGateways = buf[1]; 01658 break; 01659 case SRV_MAC_MODE_CONF: 01660 break; 01661 case SRV_MAC_LINK_ADR_REQ: 01662 MACC_PRINTF("LINK_ADR_REQ "); 01663 { 01664 uint8_t i; 01665 int8_t txPower = 0; 01666 uint8_t Redundancy = 0; 01667 adr_t adr; 01668 01669 adr.status = 0x07; 01670 // Initialize local copy of the channels mask array 01671 for( i = 0; i < 6; i++ ) 01672 { 01673 adr.channelsMask[i] = LoRaMacParams.ChannelsMask [i]; 01674 } 01675 adr.datarate = payload[macIndex++]; 01676 txPower = adr.datarate & 0x0F; 01677 adr.datarate = ( adr.datarate >> 4 ) & 0x0F; 01678 MACC_PRINTF("dr%u power%u ", adr.datarate, txPower); 01679 01680 if( ( flags.AdrCtrlOn == false ) && 01681 ( ( LoRaMacParams.ChannelsDatarate != adr.datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) ) 01682 { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower 01683 MACC_PRINTF("AdrCtrlOn:%u dr%u != dr%u, %d != %d\r\n", flags.AdrCtrlOn, 01684 LoRaMacParams.ChannelsDatarate , adr.datarate, 01685 LoRaMacParams.ChannelsTxPower , txPower 01686 ); 01687 // Answer the server with fail status 01688 // Power ACK = 0 01689 // Data rate ACK = 0 01690 // Channel mask = 0 01691 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 ); 01692 macIndex += 3; // Skip over the remaining bytes of the request 01693 break; 01694 } 01695 adr.chMask = ( uint16_t )payload[macIndex++]; 01696 adr.chMask |= ( uint16_t )payload[macIndex++] << 8; 01697 01698 Redundancy = payload[macIndex++]; 01699 adr.chMaskCntl = ( Redundancy >> 4 ) & 0x07; 01700 if ((Redundancy & 0x0f) > 0) 01701 LoRaMacParams.NbTrans = Redundancy & 0x0f; 01702 01703 MACC_PRINTF("chMask:%04x chMaskCntl:%x nbTrans:%u ", adr.chMask, adr.chMaskCntl, LoRaMacParams.NbTrans ); 01704 01705 region_adr_request(&adr); 01706 01707 if( ValidateDatarate( adr.datarate, adr.channelsMask ) == false ) 01708 { 01709 MACC_PRINTF("badDr "); 01710 adr.status &= 0xFD; // Datarate KO 01711 } 01712 01713 // 01714 // Remark MaxTxPower = 0 and MinTxPower = 5 01715 // 01716 if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false ) 01717 { 01718 MACC_PRINTF("badPower(max:%d given:%d min:%d) ", LORAMAC_MAX_TX_POWER, txPower, LORAMAC_MIN_TX_POWER); 01719 adr.status &= 0xFB; // TxPower KO 01720 } 01721 MACC_PRINTF("status:%x (idx %u) ", adr.status, macIndex); 01722 if( ( adr.status & 0x07 ) == 0x07 ) 01723 { 01724 LoRaMacParams.ChannelsDatarate = adr.datarate; 01725 LoRaMacParams.ChannelsTxPower = txPower; 01726 01727 memcpy( ( uint8_t* )LoRaMacParams.ChannelsMask , ( uint8_t* )adr.channelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); 01728 LoRaMacParams.NbEnabledChannels = region_CountNbEnabledChannels(); 01729 01730 } 01731 AddMacCommand( MOTE_MAC_LINK_ADR_ANS, adr.status, 0 ); 01732 } 01733 break; 01734 case SRV_MAC_RX_PARAM_SETUP_REQ: 01735 { 01736 uint8_t status = 0x07; 01737 int8_t datarate = 0; 01738 int8_t drOffset = 0; 01739 uint32_t freq = 0; 01740 01741 drOffset = ( payload[macIndex] >> 4 ) & 0x07; 01742 datarate = payload[macIndex] & 0x0F; 01743 macIndex++; 01744 01745 freq = ( uint32_t )payload[macIndex++]; 01746 freq |= ( uint32_t )payload[macIndex++] << 8; 01747 freq |= ( uint32_t )payload[macIndex++] << 16; 01748 freq *= 100; 01749 MACC_PRINTF("RX_PARAM_SETUP_REQ %uhz drOffset:%u dr%u ", freq, drOffset, datarate); 01750 01751 if( Rx2FreqInRange( freq ) == false ) 01752 { 01753 status &= 0xFE; // Channel frequency KO 01754 } 01755 01756 if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false ) 01757 { 01758 status &= 0xFD; // Datarate KO 01759 } 01760 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) 01761 if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) || 01762 ( datarate > DR_13 ) ) 01763 { 01764 status &= 0xFD; // Datarate KO 01765 } 01766 #endif 01767 if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false ) 01768 { 01769 status &= 0xFB; // Rx1DrOffset range KO 01770 } 01771 01772 MACC_PRINTF("status:0x%02x ", status); 01773 if( ( status & 0x07 ) == 0x07 ) 01774 { 01775 LoRaMacParams.Rx2Channel .Datarate = datarate; 01776 LoRaMacParams.Rx2Channel .FrequencyHz = freq; 01777 LoRaMacParams.Rx1DrOffset = drOffset; 01778 } 01779 AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 ); 01780 } 01781 break; 01782 case SRV_MAC_DEV_STATUS_REQ: 01783 MACC_PRINTF("DEV_STATUS_REQ "); 01784 { 01785 uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE; 01786 if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) ) 01787 { 01788 batteryLevel = LoRaMacCallbacks->GetBatteryLevel( ); 01789 } 01790 AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr ); 01791 break; 01792 } 01793 case SRV_MAC_NEW_CHANNEL_REQ: 01794 { 01795 uint8_t status = 0x03; 01796 01797 #if defined( USE_BAND_470 ) || defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 01798 status &= 0xFC; // Channel frequency and datarate KO 01799 macIndex += 5; 01800 #else 01801 int8_t channelIndex = 0; 01802 ChannelParams_t chParam; 01803 01804 channelIndex = payload[macIndex++]; 01805 chParam.FreqHz = ( uint32_t )payload[macIndex++]; 01806 chParam.FreqHz |= ( uint32_t )payload[macIndex++] << 8; 01807 chParam.FreqHz |= ( uint32_t )payload[macIndex++] << 16; 01808 chParam.FreqHz *= 100; 01809 chParam.DrRange.Value = payload[macIndex++]; 01810 MACC_PRINTF("NEW_CHANNEL_REQ ch%u %uhz drRange:%02x ", channelIndex, chParam.Frequency, chParam.DrRange.Value); 01811 01812 if( chParam.FreqHz == 0 ) 01813 { 01814 if( channelIndex < 3 ) 01815 { 01816 status &= 0xFC; 01817 } 01818 else 01819 { 01820 if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK ) 01821 { 01822 status &= 0xFC; 01823 } 01824 } 01825 } 01826 else 01827 { 01828 switch( LoRaMacChannelAdd( channelIndex, chParam ) ) 01829 { 01830 case LORAMAC_STATUS_OK: 01831 { 01832 MACC_PRINTF("add-ok "); 01833 break; 01834 } 01835 case LORAMAC_STATUS_FREQUENCY_INVALID: 01836 { 01837 MACC_PRINTF("add-bad-freq "); 01838 status &= 0xFE; 01839 break; 01840 } 01841 case LORAMAC_STATUS_DATARATE_INVALID: 01842 { 01843 MACC_PRINTF("add-bad-dr "); 01844 status &= 0xFD; 01845 break; 01846 } 01847 case LORAMAC_STATUS_FREQ_AND_DR_INVALID: 01848 { 01849 MACC_PRINTF("add-bad-both "); 01850 status &= 0xFC; 01851 break; 01852 } 01853 default: 01854 { 01855 MACC_PRINTF("add-bad-? "); 01856 status &= 0xFC; 01857 break; 01858 } 01859 } 01860 } 01861 #endif 01862 MACC_PRINTF("status:%x ", status); 01863 AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 ); 01864 } 01865 break; 01866 case SRV_MAC_ADR_PARAM_SETUP_REQ: 01867 MACC_PRINTF("ADR_PARAM_SETUP_REQ"); 01868 { 01869 uint8_t exps = payload[macIndex++] & 0x0F; 01870 ADR_ACK_LIMIT = 1 << (exps >> 4); 01871 ADR_ACK_DELAY = 1 << (exps & 0x0f); 01872 } 01873 AddMacCommand(SRV_MAC_ADR_PARAM_SETUP_ANS, 0, 0); 01874 break; 01875 case SRV_MAC_RX_TIMING_SETUP_REQ: 01876 MACC_PRINTF("RX_TIMING_SETUP_REQ"); 01877 { 01878 uint8_t delay = payload[macIndex++] & 0x0F; 01879 01880 if( delay == 0 ) 01881 { 01882 delay++; 01883 } 01884 LoRaMacParams.ReceiveDelay1_us = delay * 1e6; 01885 LoRaMacParams.ReceiveDelay2_us = LoRaMacParams.ReceiveDelay1_us + 1e6; 01886 AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); 01887 } 01888 break; 01889 #ifdef LORAWAN_JOIN_EUI 01890 case SRV_MAC_REKEY_CONF: 01891 macIndex++; //TODO server_version = payload[macIndex++]; 01892 01893 flags.need_ReKeyConf = 0; 01894 break; 01895 case SRV_MAC_FORCE_REJOIN_REQ: 01896 { 01897 uint16_t cmd_payload = payload[macIndex++]; 01898 cmd_payload |= payload[macIndex++] << 8; 01899 rejoin.type = (cmd_payload >> 4) & 7; 01900 if (rejoin.type == 2) 01901 JoinReqType = 2; 01902 else { 01903 JoinReqType = 0; 01904 rejoin.type = 0; 01905 } 01906 01907 rejoin.dr = cmd_payload & 0x0f; 01908 LoRaMacParams.ChannelsDatarate = rejoin.dr; 01909 rejoin.retries = 1 + ((cmd_payload >> 8) & 7); 01910 MAC_PRINTF("FORCE_REJOIN 0x%04x dr%u type%u tries%u ", cmd_payload, LoRaMacParams.ChannelsDatarate , JoinReqType, rejoin.retries); 01911 01912 { 01913 rejoin.Period = (cmd_payload >> 11) & 7; 01914 /* first forced-rejoin attempt must be immediate */ 01915 rejoin.event.attach_us(_rejoin_retry, 50000); 01916 rejoin.forced = true; 01917 } 01918 } 01919 break; 01920 case SRV_MAC_REJOIN_PARAM_REQ: 01921 { 01922 uint8_t p = payload[macIndex++]; 01923 rejoin.type0.MaxTimeN = p >> 4; 01924 rejoin.type0.MaxCountN = p & 0xf; 01925 rejoin.type0.enabled = true; 01926 MACC_PRINTF("REJOIN_PARAM MaxTimeN%u MaxCountN%u ", rejoin.type0.MaxTimeN, rejoin.type0.MaxCountN); 01927 rejoin.type0.uplinks_since = 1 << (rejoin.type0.MaxCountN + 4); 01928 AddMacCommand(MOTE_MAC_REJOIN_PARAM_ANS, 0, 0); 01929 } 01930 break; 01931 #else 01932 case SRV_MAC_RESET_CONF: 01933 macIndex++; //TODO server_version = payload[macIndex++]; 01934 flags.need_ResetConf = 0; 01935 break; 01936 #endif /* !LORAWAN_JOIN_EUI */ 01937 case SRV_MAC_DEVICE_TIME_ANS: 01938 { 01939 uint32_t subusecs, secs; 01940 us_timestamp_t us_since_tx_done; 01941 secs = payload[macIndex++]; 01942 secs += payload[macIndex++] << 8; 01943 secs += payload[macIndex++] << 16; 01944 secs += payload[macIndex++] << 24; 01945 subusecs = payload[macIndex++] * 3906.5; 01946 01947 //MAC_PRINTF("secs:%u, subusecs:%u\r\n", secs, subusecs); 01948 deviceTimeClassB(secs, subusecs); 01949 01950 us_since_tx_done = Radio::lpt.read_us() - tx_done_at; 01951 MlmeConfirm.fields.time.uSeconds += us_since_tx_done; 01952 while (us_since_tx_done >= 1000000) { 01953 MlmeConfirm.fields.time.Seconds++; 01954 us_since_tx_done -= 1000000; 01955 } 01956 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 01957 MlmeConfirm.fields.time.Seconds = secs; 01958 MlmeConfirm.fields.time.uSeconds = subusecs; 01959 } 01960 break; 01961 default: 01962 --macIndex; 01963 if (ProcessMacCommandsClassB(payload, &macIndex)) { 01964 /* mac command was taken */ 01965 //MACC_PRINTF("B-cont\r\n"); 01966 } 01967 #ifdef DUTY_ENABLE 01968 else if (ProcessMacCommandsDuty(payload, &macIndex)) { 01969 /* mac command was taken */ 01970 } 01971 #endif /* DUTY_ENABLE */ 01972 else { 01973 ret = -1; 01974 MAC_PRINTF("[31munknown mac:0x%02x at %u[0m\r\n", payload[macIndex-1], macIndex-1); 01975 } 01976 break; 01977 } // ..switch(payload[macIndex++]) 01978 01979 MACC_PRINTF("\r\n"); 01980 01981 } // ..while( macIndex < commandsSize ) 01982 01983 return ret; 01984 } // ..ProcessMacCommands() 01985 01986 #define MAX_FCNT_GAP 0x4000 01987 /* return: true == send downlink ack */ 01988 static int 01989 rx_downlink(uint8_t pktHeaderLen, uint16_t rx_size, int8_t snr) 01990 { 01991 LoRaMacHeader_t macHdr; 01992 LoRaMacFrameCtrl_t fCtrl; 01993 uint32_t myFCntDwn32, rxFCnt32; 01994 uint8_t rxFPort; 01995 uint16_t rxFCnt16; 01996 uint32_t address; 01997 uint32_t mic, micRx; 01998 uint8_t appPayloadStartIndex = 0; 01999 bool skipIndication = false; 02000 uint8_t frameLen = 0; 02001 bool is_AFCntDown; 02002 block_t block; 02003 const uint8_t* rx_payload = Radio::radio.rx_buf; 02004 02005 macHdr.Value = rx_payload[0]; 02006 02007 address = rx_payload[pktHeaderLen++]; 02008 address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 8 ); 02009 address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 16 ); 02010 address |= ( (uint32_t)rx_payload[pktHeaderLen++] << 24 ); 02011 02012 fCtrl.Value = rx_payload[pktHeaderLen++]; 02013 02014 rxFCnt16 = ( uint16_t )rx_payload[pktHeaderLen++]; 02015 rxFCnt16 |= ( uint16_t )rx_payload[pktHeaderLen++] << 8; 02016 02017 is_AFCntDown = false; 02018 if (( ( rx_size - 4 ) - (8 + fCtrl.Bits.FOptsLen) ) > 0) { 02019 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen; 02020 rxFPort = rx_payload[appPayloadStartIndex++]; 02021 if (flags.OptNeg && rxFPort > 0) 02022 is_AFCntDown = true; 02023 } /* else no payload/fport present */ 02024 02025 myFCntDwn32 = get_fcntdwn(is_AFCntDown); 02026 02027 McpsIndication.expectedFCntDown = myFCntDwn32; 02028 McpsIndication.receivedFCntDown = rxFCnt16; 02029 02030 rxFCnt32 = (myFCntDwn32 & 0xffff0000) | rxFCnt16; 02031 DEBUG_MIC_DOWN(" rxFCnt32:%" PRIu32" ", rxFCnt32); 02032 02033 micRx = ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN]; 02034 micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 1] << 8 ); 02035 micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 2] << 16 ); 02036 micRx |= ( ( uint32_t )rx_payload[rx_size - LORAMAC_MFR_LEN + 3] << 24 ); 02037 02038 block.b.header = 0x49; 02039 if (flags.OptNeg) 02040 block.b.confFCnt = ConfFCntUp; 02041 else 02042 block.b.confFCnt = 0; 02043 block.b.dr = 0; 02044 block.b.ch = 0; 02045 block.b.dir = DOWN_LINK; 02046 block.b.DevAddr = address; 02047 block.b.FCnt = rxFCnt32; 02048 block.b.zero8 = 0; 02049 block.b.lenMsg = rx_size - LORAMAC_MFR_LEN; 02050 mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); 02051 if (micRx != mic) { 02052 bool ignore_rx = true; 02053 PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_MIC_FAIL); 02054 MAC_PRINTF("\e[31mmicFail"); 02055 if (flags.OptNeg) { 02056 block.b.confFCnt = ConfFCntUp - 1; 02057 mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); 02058 if (micRx == mic) 02059 ignore_rx = false; 02060 else { 02061 block.b.confFCnt = 0; 02062 mic = LoRaMacComputeMic(&block, rx_payload, keys.SNwkSIntKey); 02063 if (micRx == mic) 02064 ignore_rx = false; 02065 } 02066 } 02067 if (ignore_rx) { 02068 MAC_PRINTF("\e[0m\r\n"); 02069 return -1; 02070 } else { 02071 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; 02072 if (LoRaMacPrimitives->MacMcpsIndication != NULL) 02073 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); 02074 } 02075 } else { 02076 /* downlink with good MIC means previous confirmed uplink was receied */ 02077 ConfFCntUp = 0; 02078 if (McpsIndication.RxSlot == 1) { // no need for RX2 with good mic on rx1 02079 RxWindowEvent2.detach(); 02080 } 02081 } 02082 02083 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 02084 //McpsIndication.Multicast = 0;//multicast; 02085 McpsIndication.FramePending = fCtrl.Bits.FPending; 02086 McpsIndication.Buffer = NULL; 02087 McpsIndication.BufferSize = 0; 02088 02089 MacCommandsBufferToRepeatIndex = 0; 02090 02091 if (macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN) 02092 { 02093 flags.SrvAckRequested = true; 02094 McpsIndication.McpsIndication = MCPS_CONFIRMED; 02095 02096 #ifdef LORAWAN_JOIN_EUI 02097 if (flags.IsLoRaMacNetworkJoined) 02098 #endif /* LORAWAN_JOIN_EUI */ 02099 02100 if (flags.OptNeg) 02101 ConfFCntDown = rxFCnt16; 02102 } 02103 else 02104 { // FRAME_TYPE_DATA_UNCONFIRMED_DOWN: 02105 ConfFCntDown = 0; 02106 flags.SrvAckRequested = false; 02107 McpsIndication.McpsIndication = MCPS_UNCONFIRMED; 02108 } 02109 02110 if (fCtrl.Bits.FOptsLen > 0) 02111 { 02112 // Decode Options field MAC commands 02113 if (flags.OptNeg) { 02114 uint32_t FCnt32; 02115 bool fromStored; 02116 uint8_t macDecrypt[16]; 02117 DEBUG_CRYPT_BUF(keys.NwkSEncKey, 16, "NwkSEncKey", 0); 02118 if (appPayloadStartIndex > 0) { 02119 /* rx header has AFCntDown: not for use with FOpts */ 02120 FCnt32 = get_fcntdwn(false); 02121 fromStored = true; 02122 } else { 02123 /* NFCntDown received in rx header */ 02124 FCnt32 = (get_fcntdwn(false) & 0xffff0000) | rxFCnt16; 02125 fromStored = false; 02126 } 02127 DEBUG_CRYPT("FCnt32:%" PRIu32" ", FCnt32); 02128 DEBUG_CRYPT_BUF(rx_payload+8, fCtrl.Bits.FOptsLen, "FOpts-rx", 0); 02129 LoRaMacEncrypt(0, rx_payload+8, fCtrl.Bits.FOptsLen, keys.NwkSEncKey, LoRaMacDevAddr, DOWN_LINK, FCnt32, macDecrypt); 02130 DEBUG_CRYPT_BUF(macDecrypt, fCtrl.Bits.FOptsLen, "FOpts-decrypt", 0); 02131 if (ProcessMacCommands(macDecrypt, 0, fCtrl.Bits.FOptsLen, snr) < 0) { 02132 if (fromStored) { 02133 MAC_PRINTF("fromStored-"); 02134 } 02135 MAC_PRINTF("FCnt32:%lu ", FCnt32); 02136 } 02137 } else { 02138 MAC_PRINTF("ProcessMacCommands-FOpts "); 02139 ProcessMacCommands( rx_payload, 8, fCtrl.Bits.FOptsLen + 8, snr); 02140 } 02141 } 02142 02143 if (appPayloadStartIndex > 0) 02144 { 02145 frameLen = ( rx_size - 4 ) - appPayloadStartIndex; 02146 02147 McpsIndication.Port = rxFPort; 02148 02149 if (rxFPort == 0) 02150 { 02151 if( ( fCtrl.Bits.FOptsLen == 0 ) /*&& ( multicast == 0 )*/ ) 02152 { 02153 uint8_t macDecrypt[16]; 02154 LoRaMacPayloadDecrypt(rx_payload + appPayloadStartIndex, 02155 frameLen, 02156 keys.NwkSEncKey, 02157 address, 02158 DOWN_LINK, 02159 rxFCnt32, 02160 macDecrypt 02161 ); 02162 02163 // Decode frame payload MAC commands 02164 MAC_PRINTF("ProcessMacCommands-payload "); 02165 if (ProcessMacCommands( macDecrypt, 0, frameLen, snr) < 0) { 02166 MAC_PRINTF(" rxFCnt32:%" PRIu32 " ", rxFCnt32); 02167 } 02168 } 02169 else 02170 { 02171 skipIndication = true; 02172 } 02173 } 02174 else 02175 { /* rxFPort > 0 */ 02176 MAC_PRINTF("rxFCnt32:%" PRIu32" %08" PRIx32" ", rxFCnt32, address); 02177 MAC_PRINTF("FCntDown%" PRIu32 " ", rxFCnt32); 02178 DEBUG_CRYPT(" addr%" PRIx32" len%u\r\n", address, frameLen); 02179 DEBUG_CRYPT_BUF(rx_payload + appPayloadStartIndex, frameLen, "rxEncd", 0); 02180 DEBUG_CRYPT_BUF(keys.AppSKey, 16, "AppSKey", 0); 02181 LoRaMacPayloadDecrypt(rx_payload + appPayloadStartIndex, 02182 frameLen, 02183 keys.AppSKey, 02184 address, 02185 DOWN_LINK, 02186 rxFCnt32, 02187 rxFRMPayload 02188 ); 02189 02190 if( skipIndication == false ) 02191 { 02192 McpsIndication.Buffer = rxFRMPayload; 02193 McpsIndication.BufferSize = frameLen; 02194 McpsIndication.RxData = true; 02195 } 02196 } 02197 } // ..if have payload 02198 02199 if (!skipIndication) 02200 { 02201 McpsIndication.AckReceived = fCtrl.Bits.Ack; 02202 McpsConfirm.AckReceived = fCtrl.Bits.Ack; 02203 02204 if (LoRaMacPrimitives->MacMcpsIndication != NULL) 02205 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxDone 02206 } 02207 02208 if (McpsIndication.RxSlot == 1 || McpsIndication.RxSlot == 2) 02209 McpsIndication.ADR_ACK_CNT = 0; 02210 02211 /* set FCntDwn to next expected value, if last NbTrans */ 02212 #ifdef LORAWAN_JOIN_EUI 02213 if (flags.uplink_in_progress <= 1 && last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) { 02214 if (fCtrl.Bits.Ack) { 02215 FCntUp++; 02216 } else { 02217 MAC_PRINTF("\e[31mrx-!ack\e[0m\n"); 02218 } 02219 } 02220 02221 if (is_AFCntDown) { 02222 AFCntDown = rxFCnt32 + 1; 02223 } else { 02224 NFCntDown = rxFCnt32 + 1; 02225 } 02226 #else 02227 /* if last NbTrans confirmed uplink ack'd ok: increment FCntUp */ 02228 if (flags.uplink_in_progress <= 1 && fCtrl.Bits.Ack && last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) { 02229 eeprom_increment_value(EEPROM_FCNTUP); /* TODO handle ee-failure return */ 02230 } 02231 02232 if (is_AFCntDown) 02233 eeprom_write_word(EEPROM_AFCNTDWN, rxFCnt32 + 1); 02234 else 02235 eeprom_write_word(EEPROM_NFCNTDWN, rxFCnt32 + 1); 02236 #endif /* !LORAWAN_JOIN_EUI */ 02237 02238 return 0; 02239 } // ...rx_downlink() 02240 02241 02242 #ifdef LORAWAN_JOIN_EUI 02243 typedef union { 02244 struct { 02245 uint8_t mhdr; 02246 unsigned int joinNonce : 24; 02247 unsigned int Home_NetID : 24; 02248 uint32_t DevAddr; 02249 struct { 02250 uint8_t RX2dr : 4; // 0,1,2,3 02251 uint8_t RX1DRoffset : 3; // 4,5,6 02252 uint8_t OptNeg : 1; // 7 02253 } DLSettings; 02254 uint8_t RxDelay; 02255 } __attribute__((packed)) fields; 02256 uint8_t octets[13]; 02257 } joinAccept_t; 02258 #endif /* LORAWAN_JOIN_EUI */ 02259 02260 02261 #define JOIN_ACCEPT_MAX_SIZE 34 02262 static void 02263 //OnRadioRxDone(uint8_t *rx_payload, uint16_t rx_size, int16_t rssi, int8_t snr, us_timestamp_t us_rxDone_at) 02264 OnRadioRxDone(uint8_t rx_size, float rssi, float snr) 02265 { 02266 LoRaMacEventInfoStatus_t status = LORAMAC_EVENT_INFO_STATUS_UNKNOWN_MTYPE; 02267 LoRaMacHeader_t macHdr; 02268 #ifdef LORAWAN_JOIN_EUI 02269 uint8_t _jaDecrypted[JOIN_ACCEPT_MAX_SIZE]; 02270 uint32_t mic, micRx; 02271 const uint8_t* key; 02272 const joinAccept_t* ja; 02273 #endif /* LORAWAN_JOIN_EUI */ 02274 uint8_t pktHeaderLen = 0; 02275 02276 McpsConfirm.AckReceived = false; 02277 McpsIndication.Rssi = rssi; 02278 McpsIndication.Snr = snr; 02279 McpsIndication.Port = 0; 02280 //McpsIndication.Multicast = 0; 02281 McpsIndication.FramePending = 0; 02282 McpsIndication.Buffer = NULL; 02283 McpsIndication.BufferSize = 0; 02284 McpsIndication.RxData = false; 02285 McpsIndication.AckReceived = false; 02286 McpsIndication.McpsIndication = MCPS_UNCONFIRMED; 02287 02288 if (MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_SENDING) { 02289 /* when regular downlink is sent in response to rejoin request */ 02290 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; 02291 } 02292 02293 if (LoRaMacDeviceClass != CLASS_C) 02294 { 02295 Radio::Sleep(); 02296 } 02297 02298 MAC_PRINTF("OnRadioRxDone(%u) RxSlot%d ", rx_size, McpsIndication.RxSlot); 02299 if (beacon_rx_done_payload(rx_size)) 02300 return; 02301 02302 macHdr.Value = Radio::radio.rx_buf[pktHeaderLen++]; 02303 02304 MAC_PRINTF(" rx-"); 02305 print_mtype(macHdr.Bits.MType ); 02306 switch (macHdr.Bits.MType ) 02307 { 02308 #ifdef LORAWAN_JOIN_EUI 02309 case FRAME_TYPE_JOIN_ACCEPT: 02310 /* always permitting join accept because it might be due to rejoin */ 02311 if (rx_size >= JOIN_ACCEPT_MAX_SIZE) { 02312 MAC_PRINTF("joinAccept overSize %u\r\n", rx_size); 02313 return; 02314 } 02315 02316 DEBUG_CRYPT_BUF(Radio::radio.rx_buf, rx_size, "rxBuf", 0); 02317 MAC_PRINTF("JoinReqType:%02x ", JoinReqType); 02318 if (JoinReqType == 0xff) { 02319 DEBUG_CRYPT_BUF(RootNwkKey, 16, "NwkKey", 0); 02320 key = RootNwkKey; 02321 } else { 02322 key = JSEncKey; 02323 DEBUG_CRYPT_BUF(JSEncKey, 16, "JSEncKey", 0); 02324 } 02325 LoRaMacJoinDecrypt( Radio::radio.rx_buf + 1, rx_size - 1, key, &_jaDecrypted[1]); 02326 DEBUG_CRYPT_BUF(_jaDecrypted, rx_size, "macbuf", 0); 02327 02328 _jaDecrypted[0] = macHdr.Value ; 02329 ja = (joinAccept_t*)_jaDecrypted; 02330 flags.OptNeg = ja->fields.DLSettings.OptNeg; 02331 02332 if (flags.OptNeg) { 02333 uint8_t micBuf[40]; 02334 uint8_t* ptr = micBuf; 02335 if (RootAppKey == NULL) { 02336 MAC_PRINTF("OptNeg-without-AppKey "); 02337 PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_NO_APPKEY); 02338 return; 02339 } 02340 *ptr++ = JoinReqType; 02341 memcpyr(ptr, LoRaMacJoinEui, 8); 02342 ptr += 8; 02343 *ptr++ = LoRaMacDevNonce & 0xff; 02344 *ptr++ = LoRaMacDevNonce >> 8; 02345 memcpy(ptr, _jaDecrypted, rx_size - LORAMAC_MFR_LEN); 02346 ptr += rx_size - LORAMAC_MFR_LEN; 02347 DEBUG_MIC_BUF_DOWN(JSIntKey, 16, "JSIntKey", ROW_MIC); 02348 DEBUG_MIC_BUF_DOWN(micBuf, ptr - micBuf, "jaMic-in", ROW_MIC+1); 02349 if (LoRaMacJoinComputeMic(false, micBuf, ptr - micBuf, JSIntKey, &mic ) < 0) { 02350 MAC_PRINTF("cryptFail\r\n"); 02351 return; 02352 } 02353 } else { 02354 if (LoRaMacJoinComputeMic(false, _jaDecrypted, rx_size - LORAMAC_MFR_LEN, RootNwkKey, &mic ) < 0) { 02355 MAC_PRINTF("cryptFail\r\n"); 02356 return; 02357 } 02358 } 02359 02360 micRx = ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN]; 02361 micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 1] << 8 ); 02362 micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 2] << 16 ); 02363 micRx |= ( ( uint32_t )_jaDecrypted[rx_size - LORAMAC_MFR_LEN + 3] << 24 ); 02364 02365 MAC_PRINTF("JOIN_ACCEPT %u,OptNeg%" PRIu32" ", rx_size, flags.OptNeg); 02366 02367 if (micRx == mic) 02368 { 02369 if (McpsIndication.RxSlot == 1) { // no need for RX2 with good mic on rx1 02370 RxWindowEvent2.detach(); 02371 } 02372 02373 #ifdef LORAWAN_ROOT_APPKEY 02374 if (flags.OptNeg) { 02375 MlmeConfirm.fields.join.myJoinNonce = eeprom_read(EEPROM_JOINNONCE); 02376 MlmeConfirm.fields.join.rxJoinNonce = ja->fields.joinNonce; 02377 if (MlmeConfirm.fields.join.rxJoinNonce <= MlmeConfirm.fields.join.myJoinNonce) { 02378 /* replay attack */ 02379 PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_JOINNONCE); 02380 return; 02381 } 02382 flags.need_ReKeyConf = 1; 02383 LoRaMacJoinComputeSKeys_1v1( RootNwkKey, RootAppKey, _jaDecrypted+1, LoRaMacJoinEui, LoRaMacDevNonce, &keys); 02384 eeprom_write_word(EEPROM_JOINNONCE, MlmeConfirm.fields.join.rxJoinNonce); 02385 } else 02386 #endif /* LORAWAN_ROOT_APPKEY */ 02387 LoRaMacJoinComputeSKeys_1v0( RootNwkKey, _jaDecrypted+1, LoRaMacDevNonce, &keys); 02388 02389 DEBUG_CRYPT_BUF(keys.AppSKey , 16, "create-AppSKey", 0); 02390 02391 LoRaMacNetID = ja->fields.Home_NetID; 02392 LoRaMacDevAddr = ja->fields.DevAddr; 02393 02394 // DLSettings 02395 LoRaMacParams.Rx1DrOffset = ja->fields.DLSettings.RX1DRoffset; 02396 LoRaMacParams.Rx2Channel .Datarate = ja->fields.DLSettings.RX2dr; 02397 02398 // RxDelay 02399 LoRaMacParams.ReceiveDelay1_us = (ja->fields.RxDelay & 0x0f) * 1000000; 02400 if( LoRaMacParams.ReceiveDelay1_us == 0 ) 02401 { 02402 LoRaMacParams.ReceiveDelay1_us = 1000000; 02403 } 02404 LoRaMacParams.ReceiveDelay2_us = LoRaMacParams.ReceiveDelay1_us + 1000000; 02405 MAC_PRINTF("rx1droffset:%u, rx2dr%u rxDelays:%" PRIu32" %" PRIu32", devaddr:%08" PRIx32" ", 02406 LoRaMacParams.Rx1DrOffset , 02407 LoRaMacParams.Rx2Channel .Datarate, 02408 LoRaMacParams.ReceiveDelay1_us , 02409 LoRaMacParams.ReceiveDelay2_us , 02410 LoRaMacDevAddr 02411 ); 02412 02413 #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) // TODO 02414 //CFList 02415 if( ( rx_size - 1 ) > 16 ) 02416 { 02417 ChannelParams_t param; 02418 param.DrRange.Value = ( LORAMAC_TX_MAX_DATARATE << 4 ) | LORAMAC_TX_MIN_DATARATE; 02419 02420 for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 ) 02421 { 02422 param.FreqHz = ( ( uint32_t )_jaDecrypted[13 + j] | ( ( uint32_t )_jaDecrypted[14 + j] << 8 ) | ( ( uint32_t )_jaDecrypted[15 + j] << 16 ) ) * 100; 02423 if( param.FreqHz != 0 ) 02424 { 02425 LoRaMacChannelAdd( i, param ); 02426 } 02427 else 02428 { 02429 LoRaMacChannelRemove( i ); 02430 } 02431 } 02432 } 02433 #endif 02434 status = LORAMAC_EVENT_INFO_STATUS_OK; 02435 flags.IsLoRaMacNetworkJoined = true; 02436 LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate ; 02437 02438 MAC_PRINTF("JoinReqType%x\r\n", JoinReqType); 02439 FCntUp = 0; 02440 NFCntDown = 0; 02441 AFCntDown = 0; 02442 ConfFCntDown = 0; 02443 RJcount0 = 0; 02444 McpsIndication.ADR_ACK_CNT = 0; 02445 02446 rejoin.event.detach(); 02447 02448 // must always notify application layer 02449 MlmeConfirm.MlmeRequest = MLME_JOIN; 02450 region_session_start(LORAMAC_EVENT_INFO_STATUS_OK); 02451 } 02452 else 02453 { /* join-accept mic fail */ 02454 status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL; 02455 MAC_PRINTF("ja-mic-fail rx:%" PRIx32 " calc:%" PRIx32" size:%d\r\n", micRx, mic, rx_size); 02456 if (MlmeIndication.MlmeIndication != MLME_NONE) { 02457 MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; 02458 if (LoRaMacPrimitives->MacMlmeIndication != NULL) 02459 LoRaMacPrimitives->MacMlmeIndication(&MlmeIndication); 02460 } 02461 } 02462 break; 02463 #endif /* LORAWAN_JOIN_EUI */ 02464 case FRAME_TYPE_DATA_CONFIRMED_DOWN: 02465 case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: 02466 if (rx_downlink(pktHeaderLen, rx_size, snr) == 0) 02467 status = LORAMAC_EVENT_INFO_STATUS_OK; 02468 break; 02469 case FRAME_TYPE_PROPRIETARY: 02470 { 02471 McpsIndication.McpsIndication = MCPS_PROPRIETARY; 02472 McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; 02473 McpsIndication.Buffer = Radio::radio.rx_buf; 02474 McpsIndication.BufferSize = rx_size - pktHeaderLen; 02475 02476 if (LoRaMacPrimitives->MacMcpsIndication != NULL) 02477 LoRaMacPrimitives->MacMcpsIndication( &McpsIndication ); // RxDone 02478 break; 02479 } 02480 default: 02481 MAC_PRINTF("unknown frame type:%02x\r\n", macHdr.Value ); 02482 PrepareRxDoneAbort(LORAMAC_EVENT_INFO_STATUS_UNKNOWN_MTYPE); 02483 break; 02484 } // ..switch( macHdr.Bits.MType ) 02485 02486 if (LoRaMacDeviceClass == CLASS_C) { 02487 if (McpsIndication.RxSlot == 1) { 02488 RxWindow2Setup(); 02489 RxWindow2Start(); // immiediately to continuous rx2 reception 02490 } else if (McpsIndication.RxSlot == 2) { 02491 /* stop simulated rx timeout for classC rx2-continuous */ 02492 RxWindowEvent2.detach(); 02493 } 02494 } 02495 02496 { 02497 if (flags.uplink_in_progress > 0) 02498 finish_uplink(status); 02499 02500 mcps_confirm(status); // RxDone 02501 mlme_confirm(status); 02502 } 02503 02504 MAC_PRINTF("\r\n"); 02505 02506 flags.rxing = false; 02507 } // ..OnRadioRxDone() 02508 02509 __attribute__((weak)) bool 02510 beacon_rx_timeout() 02511 { 02512 return false; 02513 } 02514 02515 void OnRadioRxTimeout( void ) 02516 { 02517 MAC_PRINTF("OnRadioRxTimeout()%d ", McpsIndication.RxSlot); 02518 #ifdef LORAWAN_JOIN_EUI 02519 MAC_PRINTF(",%u ", flags.IsLoRaMacNetworkJoined); 02520 #endif /* LORAWAN_JOIN_EUI */ 02521 02522 if (beacon_rx_timeout()) 02523 return; 02524 02525 if (McpsIndication.RxSlot == 1) 02526 RxWindow2Setup(); 02527 02528 if (LoRaMacDeviceClass != CLASS_C) 02529 Radio::Sleep(); 02530 02531 if (McpsIndication.RxSlot == 2) 02532 { 02533 #ifdef LORAWAN_JOIN_EUI 02534 if (flags.IsLoRaMacNetworkJoined) { 02535 #endif /* LORAWAN_JOIN_EUI */ 02536 if (uplinkMHDR->Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP) { 02537 /* sent once, stoping now */ 02538 mcps_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); 02539 } 02540 02541 mlme_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); 02542 #ifdef LORAWAN_JOIN_EUI 02543 } else { 02544 if (++MlmeIndication.JoinRequestTrials < MaxJoinRequestTrials) { 02545 TxDelayedEvent.attach_us(OnTxDelayedIsr, 1000000); 02546 MAC_PRINTF("RxTImeout-join-tx-delay\r\n"); 02547 MAC_PRINTF("join-try%u of%u ", MlmeIndication.JoinRequestTrials, MaxJoinRequestTrials); 02548 02549 if (MlmeIndication.MlmeIndication != MLME_NONE) { 02550 MlmeIndication.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT; 02551 if (LoRaMacPrimitives->MacMlmeIndication) 02552 LoRaMacPrimitives->MacMlmeIndication(&MlmeIndication); 02553 } 02554 } else { 02555 mlme_confirm(LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL); 02556 } 02557 } 02558 #endif /* LORAWAN_JOIN_EUI */ 02559 02560 finish_uplink(LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT); 02561 } // ..if (McpsIndication.RxSlot == 2) 02562 02563 if (LoRaMacDeviceClass == CLASS_C) { 02564 if (McpsIndication.RxSlot != 2) { 02565 RxWindow2Start(); 02566 } 02567 } else 02568 flags.rxing = false; 02569 02570 MAC_PRINTF("\r\n"); 02571 02572 } // ..OnRadioRxTimeout() 02573 02574 __attribute__((weak)) void 02575 on_dio0_top_half(us_timestamp_t dio0_at) 02576 { 02577 } 02578 02579 static void OnRadioRxError( void ) 02580 { 02581 if( LoRaMacDeviceClass != CLASS_C ) 02582 { 02583 Radio::Sleep(); 02584 } 02585 else 02586 { 02587 RxWindow2Setup(); 02588 RxWindow2Start(); 02589 } 02590 02591 if (McpsIndication.RxSlot == 2) 02592 { 02593 flags.uplink_in_progress = 0; // TODO check 02594 mlme_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_ERROR); 02595 mcps_confirm(LORAMAC_EVENT_INFO_STATUS_RX2_ERROR); 02596 } 02597 } // ..OnRadioRxError 02598 02599 const RadioEvents_t rev = { 02600 /* Dio0_top_half */ on_dio0_top_half, 02601 /* TxDone_topHalf */ OnRadioTxDone, 02602 /* TxDone_botHalf */ NULL, 02603 /* TxTimeout */ OnRadioTxTimeout, 02604 /* RxDone */ OnRadioRxDone, 02605 /* RxTimeout */ OnRadioRxTimeout, 02606 /* RxError */ OnRadioRxError, 02607 /* FhssChangeChannel */NULL, 02608 /* CadDone */ NULL 02609 }; 02610 02611 LoRaMacStatus_t 02612 LoRaMacInitialization( const LoRaMacPrimitives_t *primitives, const LoRaMacCallback_t *callbacks ) 02613 { 02614 if( primitives == NULL ) 02615 { 02616 return LORAMAC_STATUS_PARAMETER_INVALID; 02617 } 02618 02619 if( ( primitives->MacMcpsConfirm == NULL ) || 02620 ( primitives->MacMcpsIndication == NULL ) || 02621 ( primitives->MacMlmeConfirm == NULL ) || 02622 ( primitives->MacMlmeIndication == NULL ) ) 02623 { 02624 return LORAMAC_STATUS_PARAMETER_INVALID; 02625 } 02626 02627 if (targetCheckLSE() < 0) 02628 return LORAMAC_STATUS_LSE; 02629 02630 LoRaMacPrimitives = primitives; 02631 LoRaMacCallbacks = callbacks; 02632 02633 LoRaMacDeviceClass = CLASS_A; 02634 02635 #ifdef DUTY_ENABLE 02636 DutyInit(); 02637 #endif /* DUTY_ENABLE */ 02638 02639 region_mac_init(); 02640 02641 ResetMacParameters( ); 02642 02643 // Initialize Radio driver 02644 02645 LoRaMacClassBInitialization(); 02646 Radio::Init( &rev ); 02647 02648 // Random seed initialization 02649 srand(Radio::Random()); 02650 02651 flags.PublicNetwork = true; 02652 Radio::SetPublicNetwork( flags.PublicNetwork ); 02653 Radio::Sleep(); 02654 02655 McpsIndication.RxSlot = -1; 02656 function_pending = NULL; 02657 02658 McpsConfirm.McpsRequest = MCPS_NONE; 02659 02660 #ifdef LORAWAN_JOIN_EUI 02661 MaxJoinRequestTrials = 1; 02662 #else 02663 flags.have_SNwkSIntKey = 0; 02664 flags.have_NwkSEncKey = 0; 02665 flags.OptNeg = 0; 02666 #endif /* !LORAWAN_JOIN_EUI */ 02667 02668 LoRaMacCryptoInit(); 02669 02670 MlmeIndication.MlmeIndication = MLME_NONE; 02671 02672 ADR_ACK_LIMIT = DEFAULT_ADR_ACK_LIMIT; 02673 ADR_ACK_DELAY = DEFAULT_ADR_ACK_DELAY; 02674 02675 return LORAMAC_STATUS_OK; 02676 } // ..LoRaMacInitialization() 02677 02678 void SendFrameOnChannel( uint8_t ch_num ) 02679 { 02680 int8_t txPowerIndex = 0; 02681 int8_t txPower = 0; 02682 uint8_t tx_len = tx_buf_len; 02683 uint32_t mic; 02684 02685 /* TODO: if beacon guard, defer until pingslot 0 */ 02686 02687 last_up_macHdr.Value = Radio::radio.tx_buf[0]; 02688 if (last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP || 02689 last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_UP) 02690 { 02691 LoRaMacFrameCtrl_t* fCtrl = (LoRaMacFrameCtrl_t*)&Radio::radio.tx_buf[5]; 02692 block_t block; 02693 uint32_t fcnt_up; 02694 #ifdef LORAWAN_JOIN_EUI 02695 fcnt_up = FCntUp; 02696 #else 02697 fcnt_up = eeprom_read(EEPROM_FCNTUP); 02698 #endif /* LORAWAN_JOIN_EUI */ 02699 02700 fCtrl->Bits.AdrAckReq = false; 02701 if (fCtrl->Bits.Adr) { 02702 if (McpsIndication.ADR_ACK_CNT >= ADR_ACK_LIMIT) { 02703 if (LoRaMacParamsDefaults.ChannelsDatarate > LORAMAC_TX_MIN_DATARATE || LoRaMacParams.ChannelsTxPower > LORAMAC_DEFAULT_TX_POWER || LoRaMacParams.NbEnabledChannels < LoRaMacParamsDefaults.NbEnabledChannels) 02704 fCtrl->Bits.AdrAckReq = true; 02705 02706 if (McpsIndication.ADR_ACK_CNT >= (ADR_ACK_LIMIT + ADR_ACK_DELAY)) { 02707 /* if tx power less than default: increase tx power, otherwise decrease datarate */ 02708 if (LoRaMacParams.ChannelsTxPower > LORAMAC_DEFAULT_TX_POWER) { 02709 LoRaMacParams.ChannelsTxPower --; 02710 } else if (LoRaMacParams.ChannelsDatarate > LORAMAC_TX_MIN_DATARATE) { 02711 LoRaMacParams.ChannelsDatarate --; 02712 McpsIndication.ADR_ACK_CNT -= ADR_ACK_DELAY; 02713 } else { 02714 memcpy(LoRaMacParams.ChannelsMask , LoRaMacParamsDefaults.ChannelsMask , sizeof(LoRaMacParams.ChannelsMask )); 02715 LoRaMacParams.NbEnabledChannels = LoRaMacParamsDefaults.NbEnabledChannels; 02716 } 02717 } 02718 } 02719 } // ..if (fCtrl->Bits.Adr) 02720 02721 Radio::radio.tx_buf[6] = fcnt_up & 0xFF; 02722 Radio::radio.tx_buf[7] = ( fcnt_up >> 8 ) & 0xFF; 02723 02724 block.b.header = 0x49; 02725 block.b.confFCnt = 0; 02726 block.b.dr = 0; 02727 block.b.ch = 0; 02728 block.b.dir = UP_LINK; 02729 block.b.DevAddr = LoRaMacDevAddr; 02730 block.b.FCnt = fcnt_up; 02731 block.b.zero8 = 0; 02732 block.b.lenMsg = tx_len; 02733 if (flags.OptNeg) { 02734 uint16_t cmacF, cmacS; 02735 cmacF = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.FNwkSIntKey); 02736 02737 block.b.confFCnt = ConfFCntDown; 02738 block.b.dr = LoRaMacParams.ChannelsDatarate ; 02739 block.b.ch = ch_num; 02740 cmacS = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.SNwkSIntKey) & 0xffff; 02741 mic = cmacS | (cmacF << 16); 02742 ConfFCntDown = 0; /* single use */ 02743 } else 02744 mic = LoRaMacComputeMic(&block, Radio::radio.tx_buf, keys.FNwkSIntKey); 02745 02746 Radio::radio.tx_buf[tx_buf_len + 0] = mic & 0xFF; 02747 Radio::radio.tx_buf[tx_buf_len + 1] = ( mic >> 8 ) & 0xFF; 02748 Radio::radio.tx_buf[tx_buf_len + 2] = ( mic >> 16 ) & 0xFF; 02749 Radio::radio.tx_buf[tx_buf_len + 3] = ( mic >> 24 ) & 0xFF; 02750 tx_len += LORAMAC_MFR_LEN; 02751 MAC_PRINTF("FCntUp%u ", fcnt_up); 02752 02753 #ifdef LORAWAN_JOIN_EUI 02754 McpsConfirm.UpLinkCounter = FCntUp; 02755 #else 02756 McpsConfirm.UpLinkCounter = eeprom_read(EEPROM_FCNTUP); 02757 #endif /* !LORAWAN_JOIN_EUI */ 02758 02759 if (flags.uplink_in_progress <= 1) 02760 McpsIndication.ADR_ACK_CNT++; 02761 02762 } // ..if sending (un)conf 02763 02764 txPowerIndex = region_LimitTxPower( LoRaMacParams.ChannelsTxPower ); 02765 txPower = TxPowers[txPowerIndex]; 02766 02767 if (MlmeConfirm.MlmeRequest != MLME_NONE) { 02768 MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_SENDING; 02769 } 02770 if (McpsConfirm.McpsRequest != MCPS_NONE) { 02771 McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_SENDING; 02772 McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate ; 02773 McpsConfirm.TxPower = txPowerIndex; 02774 McpsConfirm.UpLinkFreqHz = Channels[ch_num].FreqHz; 02775 } 02776 02777 Radio::SetChannel(Channels[ch_num].FreqHz); 02778 if (MlmeIndication.MlmeIndication != MLME_NONE) 02779 MlmeIndication.freqHz = Channels[ch_num].FreqHz; 02780 02781 region_tx_setup(txPower, tx_len); 02782 02783 // Store the time on air 02784 //McpsConfirm.TxTimeOnAir = TxTimeOnAir_us; 02785 //MlmeConfirm.TxTimeOnAir = TxTimeOnAir_us; 02786 02787 // Send now 02788 if (Radio::Send(tx_len, LoRaMacParams.MaxListenTime, REGION_LBT_CHANNEL_FREE_TIME_us, REGION_LBT_RSSI_THRESHOLD_DBM) < 0) { 02789 mcps_confirm(LORAMAC_EVENT_INFO_STATUS_CHANNEL_BUSY); // SendFrame fail 02790 return; 02791 } 02792 waitingFor = LORAMAC_STATUS_WAITING_FOR_TXDONE; 02793 MAC_PRINTF(" sfoc %u, %" PRIu32"hz\r\n", tx_len, Channels[ch_num].FreqHz); 02794 02795 /* if this is unconfirmed up, and last NbTrans */ 02796 if (last_up_macHdr.Bits.MType == FRAME_TYPE_DATA_UNCONFIRMED_UP && flags.uplink_in_progress <= 1) { 02797 #ifdef LORAWAN_JOIN_EUI 02798 FCntUp++; 02799 #else 02800 if (eeprom_increment_value(EEPROM_FCNTUP) < 0) { 02801 mcps_confirm(LORAMAC_EVENT_INFO_STATUS_INCR_FAIL); // SendFrame fail 02802 } 02803 #endif 02804 } 02805 } // ..SendFrameOnChannel() 02806 02807 uint8_t CountBits( uint16_t mask, uint8_t nbBits ) 02808 { 02809 uint8_t nbActiveBits = 0; 02810 02811 for( uint8_t j = 0; j < nbBits; j++ ) 02812 { 02813 if( ( mask & ( 1 << j ) ) == ( 1 << j ) ) 02814 { 02815 nbActiveBits++; 02816 } 02817 } 02818 return nbActiveBits; 02819 } 02820 02821 void LoRaMacPrintStatus() 02822 { 02823 #ifdef MAC_DEBUG 02824 switch (waitingFor) { 02825 case LORAMAC_STATUS_WAITING_FOR_TXSTART: MAC_PRINTF("wait-TXSTART "); break; 02826 case LORAMAC_STATUS_WAITING_FOR_TXDONE: MAC_PRINTF("wait-TXDONE "); break; 02827 case LORAMAC_STATUS_WAITING_FOR_RX1: MAC_PRINTF("wait-RX1 "); break; 02828 case LORAMAC_STATUS_WAITING_FOR_RX2: MAC_PRINTF("wait-RX2 "); break; 02829 default: break; 02830 } 02831 if (flags.uplink_in_progress > 0) 02832 MAC_PRINTF("uplink_in_progress:%u ", flags.uplink_in_progress); 02833 MAC_PRINTF("ConfFCntUp%u\r\n", ConfFCntUp); 02834 MAC_PRINTF("function_pending:%p\r\n", function_pending); 02835 MAC_PRINTF("rx delays:%u, %u, %u, %u\r\n", 02836 RxWindow1Delay_us, 02837 LoRaMacParams.ReceiveDelay1_us , 02838 RxWindow2Delay_us, 02839 LoRaMacParams.ReceiveDelay2_us 02840 ); 02841 if (flags.uplink_in_progress) { 02842 MAC_PRINTF("since txDone:%u\r\n", Radio::lpt.read_us() - tx_done_at); 02843 } 02844 02845 MAC_PRINTF("class-"); 02846 switch (LoRaMacDeviceClass) { 02847 case CLASS_A: MAC_PRINTF("A "); break; 02848 case CLASS_B: MAC_PRINTF("B "); break; 02849 case CLASS_C: MAC_PRINTF("C "); break; 02850 } 02851 MAC_PRINTF("\r\n"); 02852 02853 //Radio::PrintStatus(); 02854 #endif /* MAC_DEBUG */ 02855 } 02856 02857 us_timestamp_t LoRaMacReadTimer() 02858 { 02859 return Radio::lpt.read_us(); 02860 } 02861 02862 int8_t 02863 LoRaMacGetRxSlot() 02864 { 02865 return McpsIndication.RxSlot; 02866 } 02867 02868 void 02869 LoRaMacUserContext() 02870 { 02871 Radio::service(); 02872 02873 if (flags.OnTxDelayed) { 02874 OnTxDelayedTimerEvent(); 02875 flags.OnTxDelayed = false; 02876 } 02877 } 02878
Generated on Mon Jul 18 2022 19:16:49 by 1.7.2