Simplified LoRaWAN library.
Fork of LoRaWAN-lib-v1_0_1 by
Diff: LoRaMac.cpp
- Revision:
- 7:c16969e0f70f
- Parent:
- 6:d7a34ded7c87
- Child:
- 8:26002607de9c
diff -r d7a34ded7c87 -r c16969e0f70f LoRaMac.cpp --- a/LoRaMac.cpp Wed May 18 11:19:24 2016 +0000 +++ b/LoRaMac.cpp Tue Jul 05 13:24:54 2016 +0000 @@ -186,10 +186,20 @@ static uint8_t MacCommandsBufferIndex = 0; /*! + * Contains the current MacCommandsBuffer index for MAC commands to repeat + */ +static uint8_t MacCommandsBufferToRepeatIndex = 0; + +/*! * Buffer containing the MAC layer commands */ static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; +/*! + * Buffer containing the MAC layer commands which must be repeated + */ +static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; + #if defined( USE_BAND_433 ) /*! * Data rates table definition @@ -324,28 +334,17 @@ { DR_12, DR_11, DR_10, DR_9 }, // DR_2 { DR_13, DR_12, DR_11, DR_10 }, // DR_3 { DR_13, DR_13, DR_12, DR_11 }, // DR_4 - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { DR_8 , DR_8 , DR_8 , DR_8 }, - { DR_9 , DR_8 , DR_8 , DR_8 }, - { DR_10, DR_9 , DR_8 , DR_8 }, - { DR_11, DR_10, DR_9 , DR_8 }, - { DR_12, DR_11, DR_10, DR_9 }, - { DR_13, DR_12, DR_11, DR_10 }, - { 0xFF , 0xFF , 0xFF , 0xFF }, - { 0xFF , 0xFF , 0xFF , 0xFF }, }; /*! * Maximum payload with respect to the datarate index. Cannot operate with repeater. */ -const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 129, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; +const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; /*! * Maximum payload with respect to the datarate index. Can operate with repeater. */ -const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 129, 242, 242, 0, 0, 0, 33, 103, 222, 222, 222, 222, 0, 0 }; +const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 }; /*! * Tx output powers table definition @@ -369,44 +368,35 @@ * Contains the channels which remain to be applied. */ static uint16_t ChannelsMaskRemaining[6]; + +/*! + * Defines the first channel for RX window 2 for US band + */ +#define LORAMAC_FIRST_RX2_CHANNEL ( (uint32_t) 923.3e6 ) + +/*! + * Defines the last channel for RX window 2 for US band + */ +#define LORAMAC_LAST_RX2_CHANNEL ( (uint32_t) 927.5e6 ) + +/*! + * Defines the step width of the channels for RX window 2 + */ +#define LORAMAC_STEPWIDTH_RX2_CHANNEL ( (uint32_t) 600e3 ) + #else #error "Please define a frequency band in the compiler options." #endif /*! - * LoRaMAC 2nd reception window settings - */ -static Rx2ChannelParams_t Rx2Channel = RX_WND_2_CHANNEL; - -/*! - * Datarate offset between uplink and downlink on first window + * LoRaMac parameters */ -static uint8_t Rx1DrOffset = 0; - -/*! - * Mask indicating which channels are enabled - */ -static uint16_t ChannelsMask[6]; +LoRaMacParams_t LoRaMacParams; /*! - * Channels Tx output power - */ -static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; - -/*! - * Channels datarate + * LoRaMac default parameters */ -static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; - -/*! - * Channels default datarate - */ -static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE; - -/*! - * Number of uplink messages repetitions [1:15] (unconfirmed messages only) - */ -static uint8_t ChannelsNbRep = 1; +LoRaMacParams_t LoRaMacParamsDefaults; /*! * Uplink messages repetitions counter @@ -436,6 +426,9 @@ */ static uint8_t Channel; +/*! + * Channel index of the last transmission + */ static uint8_t LastTxChannel; /*! @@ -490,14 +483,6 @@ static TimerEvent_t RxWindowTimer2; /*! - * LoRaMac reception windows delay from end of Tx - */ -static uint32_t ReceiveDelay1; -static uint32_t ReceiveDelay2; -static uint32_t JoinAcceptDelay1; -static uint32_t JoinAcceptDelay2; - -/*! * LoRaMac reception windows delay * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME @@ -506,11 +491,6 @@ static uint32_t RxWindow2Delay; /*! - * LoRaMac maximum time a reception window stays open - */ -static uint32_t MaxRxWindow; - -/*! * Acknowledge timeout timer. Used for packet retransmissions. */ static TimerEvent_t AckTimeoutTimer; @@ -536,6 +516,11 @@ TimerTime_t TxTimeOnAir = 0; /*! + * Number of trials for the Join Request + */ +static uint16_t JoinRequestTrials; + +/*! * Structure to hold an MCPS indication data. */ static McpsIndication_t McpsIndication; @@ -645,6 +630,15 @@ static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous ); /*! + * \brief Verifies if the RX window 2 frequency is in range + * + * \param [IN] freq window channel frequency + * + * \retval status Function status [1: OK, 0: Frequency not applicable] + */ +static bool Rx2FreqInRange( uint32_t freq ); + +/*! * \brief Adds a new MAC command to be sent. * * \Remark MAC layer internal function @@ -664,6 +658,20 @@ static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ); /*! + * \brief Parses the MAC commands which must be repeated. + * + * \Remark MAC layer internal function + * + * \param [IN] cmdBufIn Buffer which stores the MAC commands to send + * \param [IN] length Length of the input buffer to parse + * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be + * repeated. + * + * \retval Size of the MAC commands to repeat. + */ +static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ); + +/*! * \brief Validates if the payload fits into the frame, taking the datarate * into account. * @@ -804,12 +812,27 @@ static LoRaMacStatus_t ScheduleTx( void ); /* + * \brief Sets the duty cycle for retransmissions + * + * \retval Duty cycle + */ +static uint16_t RetransmissionDutyCylce( void ); + +/* * \brief Calculates the back-off time for the band of a channel. * * \param [IN] channel The last Tx channel index */ static void CalculateBackOff( uint8_t channel ); +/* + * \brief Alternates the datarate of the channel for the join request. + * + * \param [IN] nbTrials Number of performed join requests. + * \retval Datarate to apply + */ +static int8_t AlternateDatarate( uint16_t nbTrials ); + /*! * \brief LoRaMAC layer prepared frame buffer transmission with channel specification * @@ -821,7 +844,10 @@ */ LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel ); - +/*! + * \brief Resets MAC specific parameters to default + */ +static void ResetMacParameters( void ); static void OnRadioTxDone( void ) { @@ -980,26 +1006,26 @@ LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 ); // DLSettings - Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07; - Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F; + LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07; + LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F; #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) /* * WARNING: To be removed once Semtech server implementation * is corrected. */ - if( Rx2Channel.Datarate == DR_3 ) + if( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) { - Rx2Channel.Datarate = DR_8; + LoRaMacParams.Rx2Channel.Datarate = DR_8; } #endif // RxDelay - ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F ); - if( ReceiveDelay1 == 0 ) + LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F ); + if( LoRaMacParams.ReceiveDelay1 == 0 ) { - ReceiveDelay1 = 1; + LoRaMacParams.ReceiveDelay1 = 1; } - ReceiveDelay1 *= 1e6; - ReceiveDelay2 = ReceiveDelay1 + 1e6; + LoRaMacParams.ReceiveDelay1 *= 1e6; + LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6; #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) //CFList @@ -1019,7 +1045,7 @@ #endif MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; IsLoRaMacNetworkJoined = true; - ChannelsDatarate = ChannelsDefaultDatarate; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; } else { @@ -1122,6 +1148,7 @@ McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; AdrAckCounter = 0; + MacCommandsBufferToRepeatIndex = 0; // Update 32 bits downlink counter if( multicast == 1 ) @@ -1191,11 +1218,6 @@ } } - if( fCtrl.Bits.FOptsLen > 0 ) - { - // Decode Options field MAC commands - ProcessMacCommands( payload, 8, appPayloadStartIndex, snr ); - } if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 ) { port = payload[appPayloadStartIndex++]; @@ -1205,19 +1227,32 @@ if( port == 0 ) { - LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, - frameLen, - nwkSKey, - address, - DOWN_LINK, - downLinkCounter, - LoRaMacRxPayload ); - - // Decode frame payload MAC commands - ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr ); + if( fCtrl.Bits.FOptsLen == 0 ) + { + LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, + frameLen, + nwkSKey, + address, + DOWN_LINK, + downLinkCounter, + LoRaMacRxPayload ); + + // Decode frame payload MAC commands + ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr ); + } + else + { + skipIndication = true; + } } else { + if( fCtrl.Bits.FOptsLen > 0 ) + { + // Decode Options field MAC commands. Omit the fPort. + ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr ); + } + LoRaMacPayloadDecrypt( payload + appPayloadStartIndex, frameLen, appSKey, @@ -1234,6 +1269,15 @@ } } } + else + { + if( fCtrl.Bits.FOptsLen > 0 ) + { + // Decode Options field MAC commands + ProcessMacCommands( payload, 8, appPayloadStartIndex, snr ); + } + } + if( skipIndication == false ) { LoRaMacFlags.Bits.McpsInd = 1; @@ -1370,17 +1414,20 @@ { if( MlmeConfirm.MlmeRequest == MLME_JOIN ) { + // Retransmit only if the answer is not OK + ChannelsNbRepCounter = 0; + if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK ) { + // Stop retransmission + ChannelsNbRepCounter = LoRaMacParams.ChannelsNbRep; UpLinkCounter = 0; } - // Join messages aren't repeated automatically - ChannelsNbRepCounter = ChannelsNbRep; } } if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) ) { - if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) ) + if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) ) { ChannelsNbRepCounter = 0; @@ -1426,7 +1473,7 @@ if( ( AckTimeoutRetriesCounter % 2 ) == 1 ) { - ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE ); + LoRaMacParams.ChannelsDatarate = MAX( LoRaMacParams.ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE ); } LoRaMacFlags.Bits.MacDone = 0; // Sends the same frame again @@ -1436,18 +1483,18 @@ { #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); #elif defined( USE_BAND_915 ) // Re-enable default channels - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; + LoRaMacParams.ChannelsMask[0] = 0xFFFF; + LoRaMacParams.ChannelsMask[1] = 0xFFFF; + LoRaMacParams.ChannelsMask[2] = 0xFFFF; + LoRaMacParams.ChannelsMask[3] = 0xFFFF; + LoRaMacParams.ChannelsMask[4] = 0x00FF; + LoRaMacParams.ChannelsMask[5] = 0x0000; #elif defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ReenableChannels( ChannelsMask[4], ChannelsMask ); + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); #else #error "Please define a frequency band in the compiler options." #endif @@ -1500,9 +1547,26 @@ static void OnTxDelayedTimerEvent( void ) { + LoRaMacHeader_t macHdr; + LoRaMacFrameCtrl_t fCtrl; + TimerStop( &TxDelayedTimer ); LoRaMacState &= ~MAC_TX_DELAYED; + if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) ) + { + macHdr.Value = 0; + macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; + + fCtrl.Value = 0; + fCtrl.Bits.Adr = AdrCtrlOn; + + /* In case of a join request retransmission, the stack must prepare + * the frame again, because the network server keeps track of the random + * LoRaMacDevNonce values to prevent reply attacks. */ + PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 ); + } + ScheduleTx( ); } @@ -1521,7 +1585,7 @@ } #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) - datarate = ChannelsDatarate - Rx1DrOffset; + datarate = LoRaMacParams.ChannelsDatarate - LoRaMacParams.Rx1DrOffset; if( datarate < 0 ) { datarate = DR_0; @@ -1543,7 +1607,7 @@ } RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false ); #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) - datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset]; + datarate = datarateOffsets[LoRaMacParams.ChannelsDatarate][LoRaMacParams.Rx1DrOffset]; if( datarate < 0 ) { datarate = DR_0; @@ -1583,7 +1647,7 @@ {// LoRa 500 kHz bandwidth = 2; } - RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false ); + RxWindowSetup( LORAMAC_FIRST_RX2_CHANNEL + ( Channel % 8 ) * LORAMAC_STEPWIDTH_RX2_CHANNEL, datarate, bandwidth, symbTimeout, false ); #else #error "Please define a frequency band in the compiler options." #endif @@ -1599,22 +1663,22 @@ #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // For higher datarates, we increase the number of symbols generating a Rx Timeout - if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) ) + if( ( LoRaMacParams.Rx2Channel.Datarate == DR_3 ) || ( LoRaMacParams.Rx2Channel.Datarate == DR_4 ) ) { // DR_4, DR_3 symbTimeout = 8; } - else if( Rx2Channel.Datarate == DR_5 ) + else if( LoRaMacParams.Rx2Channel.Datarate == DR_5 ) { symbTimeout = 10; } - else if( Rx2Channel.Datarate == DR_6 ) + else if( LoRaMacParams.Rx2Channel.Datarate == DR_6 ) {// LoRa 250 kHz bandwidth = 1; symbTimeout = 14; } #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) // For higher datarates, we increase the number of symbols generating a Rx Timeout - switch( Rx2Channel.Datarate ) + switch( LoRaMacParams.Rx2Channel.Datarate ) { case DR_0: // SF10 - BW125 symbTimeout = 5; @@ -1644,7 +1708,7 @@ default: break; } - if( Rx2Channel.Datarate >= DR_4 ) + if( LoRaMacParams.Rx2Channel.Datarate >= DR_4 ) {// LoRa 500 kHz bandwidth = 2; } @@ -1653,11 +1717,11 @@ #endif if( LoRaMacDeviceClass != CLASS_C ) { - RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false ); + RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, false ); } else { - RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true ); + RxWindowSetup( LoRaMacParams.Rx2Channel.Frequency, LoRaMacParams.Rx2Channel.Datarate, bandwidth, symbTimeout, true ); } } @@ -1688,17 +1752,17 @@ #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 ) { // Restore default channels - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 ); + memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParams.ChannelsMask, 8 ); } - if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) ) + if( ( LoRaMacParams.ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) ) { // Make sure, that the channels are activated - ChannelsMaskRemaining[4] = ChannelsMask[4]; + ChannelsMaskRemaining[4] = LoRaMacParams.ChannelsMask[4]; } #else - if( CountBits( ChannelsMask[0], 16 ) == 0 ) + if( CountBits( LoRaMacParams.ChannelsMask[0], 16 ) == 0 ) { // Re-enable default channels, if no channel is enabled - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); } #endif @@ -1738,7 +1802,7 @@ #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 ) #else - if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 ) + if( ( LoRaMacParams.ChannelsMask[k] & ( 1 << j ) ) != 0 ) #endif { if( Channels[i + j].Frequency == 0 ) @@ -1754,8 +1818,8 @@ } } #endif - if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) && - ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false ) + if( ( ( Channels[i + j].DrRange.Fields.Min <= LoRaMacParams.ChannelsDatarate ) && + ( LoRaMacParams.ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false ) { // Check if the current channel selection supports the given datarate continue; } @@ -1856,7 +1920,7 @@ if( rxContinuous == false ) { - Radio.Rx( MaxRxWindow ); + Radio.Rx( LoRaMacParams.MaxRxWindow ); } else { @@ -1865,6 +1929,22 @@ } } +static bool Rx2FreqInRange( uint32_t freq ) +{ +#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) + if( Radio.CheckRfFrequency( freq ) == true ) +#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) + if( ( Radio.CheckRfFrequency( freq ) == true ) && + ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) && + ( freq <= LORAMAC_LAST_RX2_CHANNEL ) && + ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) ) +#endif + { + return true; + } + return false; +} + static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ) { uint16_t maxN = 0; @@ -1987,14 +2067,14 @@ { int8_t resultTxPower = txPower; #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( ChannelsDatarate == DR_4 ) || - ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) ) + if( ( LoRaMacParams.ChannelsDatarate == DR_4 ) || + ( ( LoRaMacParams.ChannelsDatarate >= DR_8 ) && ( LoRaMacParams.ChannelsDatarate <= DR_13 ) ) ) {// Limit tx power to max 26dBm resultTxPower = MAX( txPower, TX_POWER_26_DBM ); } else { - if( CountNbEnabled125kHzChannels( ChannelsMask ) < 50 ) + if( CountNbEnabled125kHzChannels( LoRaMacParams.ChannelsMask ) < 50 ) {// Limit tx power to max 21dBm resultTxPower = MAX( txPower, TX_POWER_20_DBM ); } @@ -2031,7 +2111,7 @@ static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut ) { bool adrAckReq = false; - int8_t datarate = ChannelsDatarate; + int8_t datarate = LoRaMacParams.ChannelsDatarate; if( adrEnabled == true ) { @@ -2052,7 +2132,7 @@ } if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) ) { - if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 ) + if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 ) { #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) if( datarate > LORAMAC_TX_MIN_DATARATE ) @@ -2063,9 +2143,8 @@ { if( updateChannelMask == true ) { - // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); } } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) @@ -2083,15 +2162,15 @@ { #if defined( USE_BAND_915 ) // Re-enable default channels - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; + LoRaMacParams.ChannelsMask[0] = 0xFFFF; + LoRaMacParams.ChannelsMask[1] = 0xFFFF; + LoRaMacParams.ChannelsMask[2] = 0xFFFF; + LoRaMacParams.ChannelsMask[3] = 0xFFFF; + LoRaMacParams.ChannelsMask[4] = 0x00FF; + LoRaMacParams.ChannelsMask[5] = 0x0000; #else // defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ReenableChannels( ChannelsMask[4], ChannelsMask ); + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); #endif } } @@ -2111,11 +2190,13 @@ static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 ) { LoRaMacStatus_t status = LORAMAC_STATUS_BUSY; + // The maximum buffer length must take MAC commands to re-send into account. + uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; switch( cmd ) { case MOTE_MAC_LINK_CHECK_REQ: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this command @@ -2123,7 +2204,7 @@ } break; case MOTE_MAC_LINK_ADR_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Margin @@ -2132,7 +2213,7 @@ } break; case MOTE_MAC_DUTY_CYCLE_ANS: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this answer @@ -2140,7 +2221,7 @@ } break; case MOTE_MAC_RX_PARAM_SETUP_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Status: Datarate ACK, Channel ACK @@ -2149,7 +2230,7 @@ } break; case MOTE_MAC_DEV_STATUS_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 2 ) ) + if( MacCommandsBufferIndex < ( bufLen - 2 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // 1st byte Battery @@ -2160,7 +2241,7 @@ } break; case MOTE_MAC_NEW_CHANNEL_ANS: - if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) ) + if( MacCommandsBufferIndex < ( bufLen - 1 ) ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // Status: Datarate range OK, Channel frequency OK @@ -2169,7 +2250,7 @@ } break; case MOTE_MAC_RX_TIMING_SETUP_ANS: - if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH ) + if( MacCommandsBufferIndex < bufLen ) { MacCommandsBuffer[MacCommandsBufferIndex++] = cmd; // No payload for this answer @@ -2186,6 +2267,40 @@ return status; } +static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut ) +{ + uint8_t i = 0; + uint8_t cmdCount = 0; + + if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) ) + { + return 0; + } + + for( i = 0; i < length; i++ ) + { + switch( cmdBufIn[i] ) + { + case MOTE_MAC_RX_PARAM_SETUP_ANS: + { + cmdBufOut[cmdCount++] = cmdBufIn[i++]; + cmdBufOut[cmdCount++] = cmdBufIn[i++]; + cmdBufOut[cmdCount++] = cmdBufIn[i]; + break; + } + case MOTE_MAC_RX_TIMING_SETUP_ANS: + { + cmdBufOut[cmdCount++] = cmdBufIn[i]; + break; + } + default: + break; + } + } + + return cmdCount; +} + static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr ) { while( macIndex < commandsSize ) @@ -2212,14 +2327,14 @@ // Initialize local copy of the channels mask array for( i = 0; i < 6; i++ ) { - channelsMask[i] = ChannelsMask[i]; + channelsMask[i] = LoRaMacParams.ChannelsMask[i]; } datarate = payload[macIndex++]; txPower = datarate & 0x0F; datarate = ( datarate >> 4 ) & 0x0F; if( ( AdrCtrlOn == false ) && - ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) ) + ( ( LoRaMacParams.ChannelsDatarate != datarate ) || ( LoRaMacParams.ChannelsTxPower != txPower ) ) ) { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower // Answer the server with fail status // Power ACK = 0 @@ -2341,17 +2456,17 @@ } if( ( status & 0x07 ) == 0x07 ) { - ChannelsDatarate = datarate; - ChannelsTxPower = txPower; - - ChannelsMask[0] = channelsMask[0]; - ChannelsMask[1] = channelsMask[1]; - ChannelsMask[2] = channelsMask[2]; - ChannelsMask[3] = channelsMask[3]; - ChannelsMask[4] = channelsMask[4]; - ChannelsMask[5] = channelsMask[5]; - - ChannelsNbRep = nbRep; + LoRaMacParams.ChannelsDatarate = datarate; + LoRaMacParams.ChannelsTxPower = txPower; + + LoRaMacParams.ChannelsMask[0] = channelsMask[0]; + LoRaMacParams.ChannelsMask[1] = channelsMask[1]; + LoRaMacParams.ChannelsMask[2] = channelsMask[2]; + LoRaMacParams.ChannelsMask[3] = channelsMask[3]; + LoRaMacParams.ChannelsMask[4] = channelsMask[4]; + LoRaMacParams.ChannelsMask[5] = channelsMask[5]; + + LoRaMacParams.ChannelsNbRep = nbRep; } AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 ); } @@ -2377,7 +2492,7 @@ freq |= ( uint32_t )payload[macIndex++] << 16; freq *= 100; - if( Radio.CheckRfFrequency( freq ) == false ) + if( Rx2FreqInRange( freq ) == false ) { status &= 0xFE; // Channel frequency KO } @@ -2400,9 +2515,9 @@ if( ( status & 0x07 ) == 0x07 ) { - Rx2Channel.Datarate = datarate; - Rx2Channel.Frequency = freq; - Rx1DrOffset = drOffset; + LoRaMacParams.Rx2Channel.Datarate = datarate; + LoRaMacParams.Rx2Channel.Frequency = freq; + LoRaMacParams.Rx1DrOffset = drOffset; } AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 ); } @@ -2493,8 +2608,8 @@ { delay++; } - ReceiveDelay1 = delay * 1e6; - ReceiveDelay2 = ReceiveDelay1 + 1e6; + LoRaMacParams.ReceiveDelay1 = delay * 1e6; + LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1e6; AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); } break; @@ -2556,11 +2671,11 @@ while( SetNextChannel( &dutyCycleTimeOff ) == false ) { // Set the default datarate - ChannelsDatarate = ChannelsDefaultDatarate; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) // Re-enable default channels LC1, LC2, LC3 - ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + LoRaMacParams.ChannelsMask[0] = LoRaMacParams.ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); #endif } @@ -2581,15 +2696,45 @@ } } +static uint16_t RetransmissionDutyCylce( void ) +{ + uint16_t dutyCycle = 0; + +#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) + TimerTime_t timeElapsed = TimerGetElapsedTime( 0 ); + + if( timeElapsed < 3600000000 ) + { + dutyCycle = BACKOFF_DC_1_HOUR; + } + else if( timeElapsed < ( 3600000000 + 36000000000 ) ) + { + dutyCycle = BACKOFF_DC_10_HOURS; + } + else + { + dutyCycle = BACKOFF_DC_24_HOURS; + } +#endif + return dutyCycle; +} + static void CalculateBackOff( uint8_t channel ) { uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle; + uint16_t joinDutyCycle = 0; + bool rndTimeOff = false; if( IsLoRaMacNetworkJoined == false ) { -#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) - dutyCycle = JOIN_DC; -#endif + joinDutyCycle = RetransmissionDutyCylce( ); + dutyCycle = MAX( dutyCycle, joinDutyCycle ); + + // Make sure to not apply the random back-off to the first TX + if( TxTimeOnAir > 0 ) + { + rndTimeOff = true; + } } // Update Band Time OFF @@ -2601,10 +2746,126 @@ { Bands[Channels[channel].Band].TimeOff = 0; } + + if( rndTimeOff == true ) + { + Bands[Channels[channel].Band].TimeOff = randr( Bands[Channels[channel].Band].TimeOff, + Bands[Channels[channel].Band].TimeOff + BACKOFF_RND_OFFSET ); + } + // Update Aggregated Time OFF AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir ); } +static int8_t AlternateDatarate( uint16_t nbTrials ) +{ + int8_t datarate = LORAMAC_TX_MIN_DATARATE; +#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) +#if defined( USE_BAND_915 ) + // Re-enable 500 kHz default channels + LoRaMacParams.ChannelsMask[4] = 0x00FF; +#else // defined( USE_BAND_915_HYBRID ) + // Re-enable 500 kHz default channels + ReenableChannels( LoRaMacParams.ChannelsMask[4], LoRaMacParams.ChannelsMask ); +#endif + + if( ( nbTrials & 0x01 ) == 0x01 ) + { + datarate = DR_4; + } + else + { + datarate = DR_1; + } +#else + if( ( nbTrials % 48 ) == 0 ) + { + datarate = DR_0; + } + else if( ( nbTrials % 32 ) == 0 ) + { + datarate = DR_1; + } + else if( ( nbTrials % 24 ) == 0 ) + { + datarate = DR_2; + } + else if( ( nbTrials % 16 ) == 0 ) + { + datarate = DR_3; + } + else if( ( nbTrials % 8 ) == 0 ) + { + datarate = DR_4; + } + else + { + datarate = DR_5; + } +#endif + return datarate; +} + +static void ResetMacParameters( void ) +{ + IsLoRaMacNetworkJoined = false; + + // Counters + UpLinkCounter = 1; + DownLinkCounter = 0; + AdrAckCounter = 0; + + ChannelsNbRepCounter = 0; + + AckTimeoutRetries = 1; + AckTimeoutRetriesCounter = 1; + AckTimeoutRetry = false; + + MaxDCycle = 0; + AggregatedDCycle = 1; + + MacCommandsBufferIndex = 0; + MacCommandsBufferToRepeatIndex = 0; + + IsRxWindowsEnabled = true; + + LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower; + LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate; + + LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow; + LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1; + LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2; + LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1; + LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2; + + LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset; + LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep; + + LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel; + + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); + +#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) LoRaMacParamsDefaults.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); +#endif + + + NodeAckRequested = false; + SrvAckRequested = false; + MacCommandsInNextTx = false; + + // Reset Multicast downlink counters + MulticastParams_t *cur = MulticastChannels; + while( cur != NULL ) + { + cur->DownLinkCounter = 0; + cur = cur->Next; + } + + // Initialize channel index. + Channel = LORA_MAX_NB_CHANNELS; +} + LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) { uint16_t i; @@ -2628,8 +2889,8 @@ switch( macHdr->Bits.MType ) { case FRAME_TYPE_JOIN_REQ: - RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME; - RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME; + RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 - RADIO_WAKEUP_TIME; LoRaMacBufferPktLen = pktHeaderLen; @@ -2660,15 +2921,15 @@ return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet } - fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate ); - - if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false ) + fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &LoRaMacParams.ChannelsDatarate ); + + if( ValidatePayloadLength( fBufferSize, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false ) { return LORAMAC_STATUS_LENGTH_ERROR; } - RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME; - RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME; + RxWindow1Delay = LoRaMacParams.ReceiveDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = LoRaMacParams.ReceiveDelay2 - RADIO_WAKEUP_TIME; if( SrvAckRequested == true ) { @@ -2686,6 +2947,10 @@ LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF; + // Copy the MAC commands which must be re-send into the MAC command buffer + memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex ); + MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; + if( ( payload != NULL ) && ( payloadSize > 0 ) ) { if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) ) @@ -2710,6 +2975,12 @@ } } MacCommandsInNextTx = false; + // Store MAC commands which must be re-send in case the device does not receive a downlink anymore + MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat ); + if( MacCommandsBufferToRepeatIndex > 0 ) + { + MacCommandsInNextTx = true; + } MacCommandsBufferIndex = 0; if( ( payload != NULL ) && ( payloadSize > 0 ) ) @@ -2754,29 +3025,29 @@ LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel ) { - int8_t datarate = Datarates[ChannelsDatarate]; + int8_t datarate = Datarates[LoRaMacParams.ChannelsDatarate]; int8_t txPowerIndex = 0; int8_t txPower = 0; - txPowerIndex = LimitTxPower( ChannelsTxPower ); + txPowerIndex = LimitTxPower( LoRaMacParams.ChannelsTxPower ); txPower = TxPowers[txPowerIndex]; MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; - McpsConfirm.Datarate = ChannelsDatarate; + McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate; McpsConfirm.TxPower = txPowerIndex; Radio.SetChannel( channel.Frequency ); #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) - if( ChannelsDatarate == DR_7 ) + if( LoRaMacParams.ChannelsDatarate == DR_7 ) { // High Speed FSK channel Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen ); Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 ); TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen ); } - else if( ChannelsDatarate == DR_6 ) + else if( LoRaMacParams.ChannelsDatarate == DR_6 ) { // High speed LoRa channel Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen ); Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 ); @@ -2790,7 +3061,7 @@ } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen ); - if( ChannelsDatarate >= DR_4 ) + if( LoRaMacParams.ChannelsDatarate >= DR_4 ) { // High speed LoRa channel BW500 kHz Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 ); TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen ); @@ -2840,40 +3111,64 @@ LoRaMacFlags.Value = 0; LoRaMacDeviceClass = CLASS_A; - - UpLinkCounter = 1; - DownLinkCounter = 0; - AdrAckCounter = 0; - + LoRaMacState = MAC_IDLE; + + JoinRequestTrials = 0; RepeaterSupport = false; - IsRxWindowsEnabled = true; - IsLoRaMacNetworkJoined = false; - LoRaMacState = MAC_IDLE; - + + // Reset duty cycle times + AggregatedLastTxDoneTime = 0; + AggregatedTimeOff = 0; + + // Duty cycle #if defined( USE_BAND_433 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = false; #elif defined( USE_BAND_780 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = false; #elif defined( USE_BAND_868 ) - ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); + DutyCycleOn = true; +#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) + DutyCycleOn = false; +#else + #error "Please define a frequency band in the compiler options." +#endif + + // Reset to defaults + LoRaMacParamsDefaults.ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; + LoRaMacParamsDefaults.ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; + + LoRaMacParamsDefaults.MaxRxWindow = MAX_RX_WINDOW; + LoRaMacParamsDefaults.ReceiveDelay1 = RECEIVE_DELAY1; + LoRaMacParamsDefaults.ReceiveDelay2 = RECEIVE_DELAY2; + LoRaMacParamsDefaults.JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1; + LoRaMacParamsDefaults.JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2; + + LoRaMacParamsDefaults.ChannelsNbRep = 1; + LoRaMacParamsDefaults.Rx1DrOffset = 0; + + LoRaMacParamsDefaults.Rx2Channel = ( Rx2ChannelParams_t )RX_WND_2_CHANNEL; + + // Channel mask +#if defined( USE_BAND_433 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); +#elif defined( USE_BAND_780 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); +#elif defined( USE_BAND_868 ) + LoRaMacParamsDefaults.ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 ); #elif defined( USE_BAND_915 ) - ChannelsMask[0] = 0xFFFF; - ChannelsMask[1] = 0xFFFF; - ChannelsMask[2] = 0xFFFF; - ChannelsMask[3] = 0xFFFF; - ChannelsMask[4] = 0x00FF; - ChannelsMask[5] = 0x0000; - - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) ); + LoRaMacParamsDefaults.ChannelsMask[0] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[1] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[2] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[3] = 0xFFFF; + LoRaMacParamsDefaults.ChannelsMask[4] = 0x00FF; + LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000; #elif defined( USE_BAND_915_HYBRID ) - ChannelsMask[0] = 0x00FF; - ChannelsMask[1] = 0x0000; - ChannelsMask[2] = 0x0000; - ChannelsMask[3] = 0x0000; - ChannelsMask[4] = 0x0001; - ChannelsMask[5] = 0x0000; - - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) ); + LoRaMacParamsDefaults.ChannelsMask[0] = 0x00FF; + LoRaMacParamsDefaults.ChannelsMask[1] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[2] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[3] = 0x0000; + LoRaMacParamsDefaults.ChannelsMask[4] = 0x0001; + LoRaMacParamsDefaults.ChannelsMask[5] = 0x0000; #else #error "Please define a frequency band in the compiler options." #endif @@ -2895,34 +3190,9 @@ } #endif - ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER; - ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE; - ChannelsNbRep = 1; - ChannelsNbRepCounter = 0; - - MaxDCycle = 0; - AggregatedDCycle = 1; - AggregatedLastTxDoneTime = 0; - AggregatedTimeOff = 0; - -#if defined( USE_BAND_433 ) - DutyCycleOn = false; -#elif defined( USE_BAND_780 ) - DutyCycleOn = false; -#elif defined( USE_BAND_868 ) - DutyCycleOn = true; -#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - DutyCycleOn = false; -#else - #error "Please define a frequency band in the compiler options." -#endif - - MaxRxWindow = MAX_RX_WINDOW; - ReceiveDelay1 = RECEIVE_DELAY1; - ReceiveDelay2 = RECEIVE_DELAY2; - JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1; - JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2; - + ResetMacParameters( ); + + // Initialize timers TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent ); TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT ); @@ -2942,9 +3212,6 @@ // Random seed initialization srand1( Radio.Random( ) ); - // Initialize channel index. - Channel = LORA_MAX_NB_CHANNELS; - PublicNetwork = true; SetPublicNetwork( PublicNetwork ); Radio.Sleep( ); @@ -2954,7 +3221,8 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo ) { - int8_t datarate = ChannelsDefaultDatarate; + int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate; + uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex; if( txInfo == NULL ) { @@ -2972,9 +3240,9 @@ txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate]; } - if( txInfo->CurrentPayloadSize >= MacCommandsBufferIndex ) + if( txInfo->CurrentPayloadSize >= fOptLen ) { - txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - MacCommandsBufferIndex; + txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen; } else { @@ -2986,7 +3254,7 @@ return LORAMAC_STATUS_LENGTH_ERROR; } - if( ValidatePayloadLength( size, datarate, MacCommandsBufferIndex ) == false ) + if( ValidatePayloadLength( size, datarate, fOptLen ) == false ) { return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR; } @@ -3057,57 +3325,57 @@ } case MIB_RX2_CHANNEL: { - mibGet->Param.Rx2Channel = Rx2Channel; + mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel; break; } case MIB_CHANNELS_MASK: { - mibGet->Param.ChannelsMask = ChannelsMask; + mibGet->Param.ChannelsMask = LoRaMacParams.ChannelsMask; break; } case MIB_CHANNELS_NB_REP: { - mibGet->Param.ChannelNbRep = ChannelsNbRep; + mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep; break; } case MIB_MAX_RX_WINDOW_DURATION: { - mibGet->Param.MaxRxWindow = MaxRxWindow; + mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow; break; } case MIB_RECEIVE_DELAY_1: { - mibGet->Param.ReceiveDelay1 = ReceiveDelay1; + mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1; break; } case MIB_RECEIVE_DELAY_2: { - mibGet->Param.ReceiveDelay2 = ReceiveDelay2; + mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2; break; } case MIB_JOIN_ACCEPT_DELAY_1: { - mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1; + mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1; break; } case MIB_JOIN_ACCEPT_DELAY_2: { - mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2; + mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2; break; } case MIB_CHANNELS_DEFAULT_DATARATE: { - mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate; + mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate; break; } case MIB_CHANNELS_DATARATE: { - mibGet->Param.ChannelsDatarate = ChannelsDatarate; + mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate; break; } case MIB_CHANNELS_TX_POWER: { - mibGet->Param.ChannelsTxPower = ChannelsTxPower; + mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower; break; } case MIB_UPLINK_COUNTER: @@ -3231,7 +3499,7 @@ } case MIB_RX2_CHANNEL: { - Rx2Channel = mibSet->Param.Rx2Channel; + LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel; break; } case MIB_CHANNELS_MASK: @@ -3253,12 +3521,12 @@ } else { - memcpy1( ( uint8_t* ) ChannelsMask, - ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) ); - for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ ) + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, + ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( LoRaMacParams.ChannelsMask ) ); + for ( uint8_t i = 0; i < sizeof( LoRaMacParams.ChannelsMask ) / 2; i++ ) { // Disable channels which are no longer available - ChannelsMaskRemaining[i] &= ChannelsMask[i]; + ChannelsMaskRemaining[i] &= LoRaMacParams.ChannelsMask[i]; } } } @@ -3267,7 +3535,7 @@ status = LORAMAC_STATUS_PARAMETER_INVALID; } #else - memcpy1( ( uint8_t* ) ChannelsMask, + memcpy1( ( uint8_t* ) LoRaMacParams.ChannelsMask, ( uint8_t* ) mibSet->Param.ChannelsMask, 2 ); #endif } @@ -3282,7 +3550,7 @@ if( ( mibSet->Param.ChannelNbRep >= 1 ) && ( mibSet->Param.ChannelNbRep <= 15 ) ) { - ChannelsNbRep = mibSet->Param.ChannelNbRep; + LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep; } else { @@ -3292,27 +3560,27 @@ } case MIB_MAX_RX_WINDOW_DURATION: { - MaxRxWindow = mibSet->Param.MaxRxWindow; + LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow; break; } case MIB_RECEIVE_DELAY_1: { - ReceiveDelay1 = mibSet->Param.ReceiveDelay1; + LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1; break; } case MIB_RECEIVE_DELAY_2: { - ReceiveDelay2 = mibSet->Param.ReceiveDelay2; + LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2; break; } case MIB_JOIN_ACCEPT_DELAY_1: { - JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1; + LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1; break; } case MIB_JOIN_ACCEPT_DELAY_2: { - JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2; + LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2; break; } case MIB_CHANNELS_DEFAULT_DATARATE: @@ -3320,7 +3588,7 @@ if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) { - ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate; + LoRaMacParamsDefaults.ChannelsDatarate = mibSet->Param.ChannelsDefaultDatarate; } else { @@ -3333,7 +3601,7 @@ if( ValueInRange( mibSet->Param.ChannelsDatarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) { - ChannelsDatarate = mibSet->Param.ChannelsDatarate; + LoRaMacParams.ChannelsDatarate = mibSet->Param.ChannelsDatarate; } else { @@ -3346,7 +3614,7 @@ if( ValueInRange( mibSet->Param.ChannelsTxPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) ) { - ChannelsTxPower = mibSet->Param.ChannelsTxPower; + LoRaMacParams.ChannelsTxPower = mibSet->Param.ChannelsTxPower; } else { @@ -3412,7 +3680,7 @@ frequencyInvalid = true; } - if( params.DrRange.Fields.Min > ChannelsDefaultDatarate ) + if( params.DrRange.Fields.Min > LoRaMacParamsDefaults.ChannelsDatarate ) { datarateInvalid = true; } @@ -3474,7 +3742,7 @@ // Every parameter is valid, activate the channel Channels[id] = params; Channels[id].Band = band; - ChannelsMask[0] |= ( 1 << id ); + LoRaMacParams.ChannelsMask[0] |= ( 1 << id ); return LORAMAC_STATUS_OK; #endif @@ -3501,7 +3769,7 @@ Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 }; // Disable the channel as it doesn't exist anymore - if( DisableChannelInMask( id, ChannelsMask ) == false ) + if( DisableChannelInMask( id, LoRaMacParams.ChannelsMask ) == false ) { return LORAMAC_STATUS_PARAMETER_INVALID; } @@ -3631,28 +3899,10 @@ macHdr.Value = 0; macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ; - IsLoRaMacNetworkJoined = false; - -#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) -#if defined( USE_BAND_915 ) - // Re-enable 500 kHz default channels - ChannelsMask[4] = 0x00FF; -#else // defined( USE_BAND_915_HYBRID ) - // Re-enable 500 kHz default channels - ChannelsMask[4] = 0x0001; -#endif - - static uint8_t drSwitch = 0; - - if( ( ++drSwitch & 0x01 ) == 0x01 ) - { - ChannelsDatarate = DR_0; - } - else - { - ChannelsDatarate = DR_4; - } -#endif + ResetMacParameters( ); + + JoinRequestTrials++; + LoRaMacParams.ChannelsDatarate = AlternateDatarate( JoinRequestTrials ); status = Send( &macHdr, 0, NULL, 0 ); break; @@ -3751,7 +4001,7 @@ { if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true ) { - ChannelsDatarate = datarate; + LoRaMacParams.ChannelsDatarate = datarate; } else {