Update LoRaWAN MAC
Dependents: LoRaWAN-SX1272-Application-crash LoRaWAN-SX1272-Application-24-31-9sec Canada-SX1272-LoRaWAN-EEPROM Training-Aug2018-SX1272-X-NUCLEO-IKS01A2_Natalia
Fork of LoRaWAN-lib by
Diff: LoRaMac.cpp
- Revision:
- 4:37c12dbc8dc7
- Parent:
- 3:b9d87593a8ae
- Child:
- 5:2477c924494a
--- a/LoRaMac.cpp Mon Mar 14 09:09:54 2016 +0000 +++ b/LoRaMac.cpp Fri May 13 14:51:50 2016 +0000 @@ -34,6 +34,13 @@ #define LORA_MAC_COMMAND_MAX_LENGTH 15 /*! + * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength + * in RxWindowSetup function. + * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD + */ +#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4) + +/*! * Device IEEE EUI */ static uint8_t *LoRaMacDevEui; @@ -362,7 +369,6 @@ * Contains the channels which remain to be applied. */ static uint16_t ChannelsMaskRemaining[6]; - #else #error "Please define a frequency band in the compiler options." #endif @@ -430,6 +436,8 @@ */ static uint8_t Channel; +static uint8_t LastTxChannel; + /*! * LoRaMac internal states */ @@ -442,6 +450,7 @@ MAC_ACK_RETRY = 0x00000008, MAC_TX_DELAYED = 0x00000010, MAC_TX_CONFIG = 0x00000020, + MAC_RX_ABORT = 0x00000040, }; /*! @@ -672,16 +681,46 @@ */ static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ); +/*! + * \brief Counts the number of bits in a mask. + * + * \param [IN] mask A mask from which the function counts the active bits. + * \param [IN] nbBits The number of bits to check. + * + * \retval Number of enabled bits in the mask. + */ +static uint8_t CountBits( uint16_t mask, uint8_t nbBits ); + #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) /*! * \brief Counts the number of enabled 125 kHz channels in the channel mask. * This function can only be applied to US915 band. * - * \param channelsMask Pointer to the first element of the channel mask + * \param [IN] channelsMask Pointer to the first element of the channel mask * * \retval Number of enabled channels in the channel mask */ static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask ); + +#if defined( USE_BAND_915_HYBRID ) +/*! + * \brief Validates the correctness of the channel mask for US915, hybrid mode. + * + * \param [IN] mask Block definition to set. + * \param [OUT] channelsMask Pointer to the first element of the channel mask + */ +static void ReenableChannels( uint16_t mask, uint16_t* channelMask ); + +/*! + * \brief Validates the correctness of the channel mask for US915, hybrid mode. + * + * \param [IN] channelsMask Pointer to the first element of the channel mask + * + * \retval [true: channel mask correct, false: channel mask not correct] + */ +static bool ValidateChannelMask( uint16_t* channelMask ); +#endif + #endif /*! @@ -764,6 +803,13 @@ */ static LoRaMacStatus_t ScheduleTx( 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 LoRaMAC layer prepared frame buffer transmission with channel specification * @@ -789,19 +835,12 @@ OnRxWindow2TimerEvent( ); } - // Update Band Time OFF - Bands[Channels[Channel].Band].LastTxDoneTime = curTime; - if( DutyCycleOn == true ) - { - Bands[Channels[Channel].Band].TimeOff = TxTimeOnAir * Bands[Channels[Channel].Band].DCycle - TxTimeOnAir; - } - else - { - Bands[Channels[Channel].Band].TimeOff = 0; - } - // Update Aggregated Time OFF + // Store last Tx channel + LastTxChannel = Channel; + // Update last tx done time for the current channel + Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime; + // Update Aggregated last tx done time AggregatedLastTxDoneTime = curTime; - AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir ); if( IsRxWindowsEnabled == true ) { @@ -840,7 +879,7 @@ static void PrepareRxDoneAbort( void ) { - LoRaMacState &= ~MAC_TX_RUNNING; + LoRaMacState |= MAC_RX_ABORT; if( NodeAckRequested ) { @@ -864,6 +903,7 @@ { LoRaMacHeader_t macHdr; LoRaMacFrameCtrl_t fCtrl; + bool skipIndication = false; uint8_t pktHeaderLen = 0; uint32_t address = 0; @@ -1061,6 +1101,15 @@ } } + // Check for a the maximum allowed counter difference + if( sequenceCounterDiff >= MAX_FCNT_GAP ) + { + McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS; + McpsIndication.DownLinkCounter = downLinkCounter; + PrepareRxDoneAbort( ); + return; + } + if( isMicOk == true ) { McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; @@ -1095,19 +1144,27 @@ { SrvAckRequested = true; McpsIndication.McpsIndication = MCPS_CONFIRMED; + + if( ( DownLinkCounter == downLinkCounter ) && + ( DownLinkCounter != 0 ) ) + { + // Duplicated confirmed downlink. Skip indication. + skipIndication = true; + } } else { SrvAckRequested = false; McpsIndication.McpsIndication = MCPS_UNCONFIRMED; - } - if( ( DownLinkCounter == downLinkCounter ) && - ( DownLinkCounter != 0 ) ) - { - McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; - McpsIndication.DownLinkCounter = downLinkCounter; - PrepareRxDoneAbort( ); - return; + + if( ( DownLinkCounter == downLinkCounter ) && + ( DownLinkCounter != 0 ) ) + { + McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; + McpsIndication.DownLinkCounter = downLinkCounter; + PrepareRxDoneAbort( ); + return; + } } DownLinkCounter = downLinkCounter; } @@ -1169,12 +1226,18 @@ downLinkCounter, LoRaMacRxPayload ); - McpsIndication.Buffer = LoRaMacRxPayload; - McpsIndication.BufferSize = frameLen; - McpsIndication.RxData = true; + if( skipIndication == false ) + { + McpsIndication.Buffer = LoRaMacRxPayload; + McpsIndication.BufferSize = frameLen; + McpsIndication.RxData = true; + } } } - LoRaMacFlags.Bits.McpsInd = 1; + if( skipIndication == false ) + { + LoRaMacFlags.Bits.McpsInd = 1; + } } else { @@ -1281,6 +1344,12 @@ if( LoRaMacFlags.Bits.MacDone == 1 ) { + if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT ) + { + LoRaMacState &= ~MAC_RX_ABORT; + LoRaMacState &= ~MAC_TX_RUNNING; + } + if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) ) { if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) || @@ -1357,7 +1426,7 @@ if( ( AckTimeoutRetriesCounter % 2 ) == 1 ) { - ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_MIN_DATARATE ); + ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE ); } LoRaMacFlags.Bits.MacDone = 0; // Sends the same frame again @@ -1378,12 +1447,7 @@ ChannelsMask[5] = 0x0000; #elif defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ChannelsMask[0] = 0x00FF; - ChannelsMask[1] = 0x0000; - ChannelsMask[2] = 0x0000; - ChannelsMask[3] = 0x0000; - ChannelsMask[4] = 0x0001; - ChannelsMask[5] = 0x0000; + ReenableChannels( ChannelsMask[4], ChannelsMask ); #else #error "Please define a frequency band in the compiler options." #endif @@ -1464,13 +1528,18 @@ } // For higher datarates, we increase the number of symbols generating a Rx Timeout - if( datarate >= DR_3 ) - { // DR_6, DR_5, DR_4, DR_3 + if( ( datarate == DR_3 ) || ( datarate == DR_4 ) ) + { // DR_4, DR_3 symbTimeout = 8; } - if( datarate == DR_6 ) + else if( datarate == DR_5 ) + { + symbTimeout = 10; + } + else if( datarate == DR_6 ) {// LoRa 250 kHz bandwidth = 1; + symbTimeout = 14; } RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false ); #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) @@ -1480,9 +1549,35 @@ datarate = DR_0; } // For higher datarates, we increase the number of symbols generating a Rx Timeout - if( datarate > DR_0 ) - { // DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13 - symbTimeout = 8; + switch( datarate ) + { + case DR_0: // SF10 - BW125 + symbTimeout = 5; + break; + + case DR_1: // SF9 - BW125 + case DR_2: // SF8 - BW125 + case DR_8: // SF12 - BW500 + case DR_9: // SF11 - BW500 + case DR_10: // SF10 - BW500 + symbTimeout = 8; + break; + + case DR_3: // SF7 - BW125 + case DR_11: // SF9 - BW500 + symbTimeout = 10; + break; + + case DR_4: // SF8 - BW500 + case DR_12: // SF8 - BW500 + symbTimeout = 14; + break; + + case DR_13: // SF7 - BW500 + symbTimeout = 16; + break; + default: + break; } if( datarate >= DR_4 ) {// LoRa 500 kHz @@ -1504,19 +1599,50 @@ #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 ) - { // DR_6, DR_5, DR_4, DR_3 + if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) ) + { // DR_4, DR_3 symbTimeout = 8; } - if( Rx2Channel.Datarate == DR_6 ) + else if( Rx2Channel.Datarate == DR_5 ) + { + symbTimeout = 10; + } + else if( 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 - if( Rx2Channel.Datarate > DR_0 ) - { // DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13 - symbTimeout = 8; + switch( Rx2Channel.Datarate ) + { + case DR_0: // SF10 - BW125 + symbTimeout = 5; + break; + + case DR_1: // SF9 - BW125 + case DR_2: // SF8 - BW125 + case DR_8: // SF12 - BW500 + case DR_9: // SF11 - BW500 + case DR_10: // SF10 - BW500 + symbTimeout = 8; + break; + + case DR_3: // SF7 - BW125 + case DR_11: // SF9 - BW500 + symbTimeout = 10; + break; + + case DR_4: // SF8 - BW500 + case DR_12: // SF8 - BW500 + symbTimeout = 14; + break; + + case DR_13: // SF7 - BW500 + symbTimeout = 16; + break; + default: + break; } if( Rx2Channel.Datarate >= DR_4 ) {// LoRa 500 kHz @@ -1555,7 +1681,6 @@ uint8_t nbEnabledChannels = 0; uint8_t delayTx = 0; uint8_t enabledChannels[LORA_MAX_NB_CHANNELS]; - TimerTime_t curTime = TimerGetCurrentTime( ); TimerTime_t nextTxDelay = ( TimerTime_t )( -1 ); memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS ); @@ -1570,16 +1695,7 @@ ChannelsMaskRemaining[4] = ChannelsMask[4]; } #else - uint8_t chanCnt = 0; - for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ ) - { - if( ChannelsMask[k] != 0 ) - { - chanCnt++; - break; - } - } - if( chanCnt == 0 ) + if( CountBits( ChannelsMask[0], 16 ) == 0 ) { // Re-enable default channels, if no channel is enabled ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); @@ -1587,7 +1703,7 @@ #endif // Update Aggregated duty cycle - if( AggregatedTimeOff < ( curTime - AggregatedLastTxDoneTime ) ) + if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) ) { AggregatedTimeOff = 0; @@ -1596,14 +1712,14 @@ { if( DutyCycleOn == true ) { - if( Bands[i].TimeOff < ( curTime - Bands[i].LastTxDoneTime ) ) + if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) ) { Bands[i].TimeOff = 0; } if( Bands[i].TimeOff != 0 ) { nextTxDelay = MIN( Bands[i].TimeOff - - ( curTime - Bands[i].LastTxDoneTime ), + TimerGetElapsedTime( Bands[i].LastTxDoneTime ), nextTxDelay ); } } @@ -1629,6 +1745,15 @@ { // Check if the channel is enabled continue; } +#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) + if( IsLoRaMacNetworkJoined == false ) + { + if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 ) + { + continue; + } + } +#endif if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) && ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false ) { // Check if the current channel selection supports the given datarate @@ -1647,7 +1772,7 @@ else { delayTx++; - nextTxDelay = AggregatedTimeOff - ( curTime - AggregatedLastTxDoneTime ); + nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime ); } if( nbEnabledChannels > 0 ) @@ -1722,11 +1847,11 @@ if( RepeaterSupport == true ) { - Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] ); + Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD ); } else { - Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] ); + Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD ); } if( rxContinuous == false ) @@ -1766,6 +1891,20 @@ return false; } +static uint8_t CountBits( uint16_t mask, uint8_t nbBits ) +{ + uint8_t nbActiveBits = 0; + + for( uint8_t j = 0; j < nbBits; j++ ) + { + if( ( mask & ( 1 << j ) ) == ( 1 << j ) ) + { + nbActiveBits++; + } + } + return nbActiveBits; +} + #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask ) { @@ -1773,17 +1912,75 @@ for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ ) { - for( uint8_t j = 0; j < 16; j++ ) - {// Verify if the channel is active - if( ( channelsMask[k] & ( 1 << j ) ) == ( 1 << j ) ) - { - nb125kHzChannels++; - } - } + nb125kHzChannels += CountBits( channelsMask[k], 16 ); } return nb125kHzChannels; } + +#if defined( USE_BAND_915_HYBRID ) +static void ReenableChannels( uint16_t mask, uint16_t* channelMask ) +{ + uint16_t blockMask = mask; + + for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 ) + { + channelMask[i] = 0; + if( ( blockMask & ( 1 << j ) ) != 0 ) + { + channelMask[i] |= 0x00FF; + } + if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 ) + { + channelMask[i] |= 0xFF00; + } + } + channelMask[4] = blockMask; + channelMask[5] = 0x0000; +} + +static bool ValidateChannelMask( uint16_t* channelMask ) +{ + bool chanMaskState = false; + uint16_t block1 = 0; + uint16_t block2 = 0; + uint8_t index = 0; + + for( uint8_t i = 0; i < 4; i++ ) + { + block1 = channelMask[i] & 0x00FF; + block2 = channelMask[i] & 0xFF00; + + if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) ) + { + channelMask[i] &= block1; + channelMask[4] = 1 << ( i * 2 ); + chanMaskState = true; + index = i; + } + else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) ) + { + channelMask[i] &= block2; + channelMask[4] = 1 << ( i * 2 + 1 ); + chanMaskState = true; + index = i; + } + } + + // Do only change the channel mask, if we have found a valid block. + if( chanMaskState == true ) + { + for( uint8_t i = 0; i < 4; i++ ) + { + if( i != index ) + { + channelMask[i] = 0; + } + } + } + return chanMaskState; +} +#endif #endif static int8_t LimitTxPower( int8_t txPower ) @@ -1838,7 +2035,7 @@ if( adrEnabled == true ) { - if( datarate == LORAMAC_MIN_DATARATE ) + if( datarate == LORAMAC_TX_MIN_DATARATE ) { AdrAckCounter = 0; adrAckReq = false; @@ -1858,11 +2055,11 @@ if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 ) { #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) - if( datarate > LORAMAC_MIN_DATARATE ) + if( datarate > LORAMAC_TX_MIN_DATARATE ) { datarate--; } - if( datarate == LORAMAC_MIN_DATARATE ) + if( datarate == LORAMAC_TX_MIN_DATARATE ) { if( updateChannelMask == true ) { @@ -1872,15 +2069,15 @@ } } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( datarate > LORAMAC_MIN_DATARATE ) && ( datarate == DR_8 ) ) + if( ( datarate > LORAMAC_TX_MIN_DATARATE ) && ( datarate == DR_8 ) ) { datarate = DR_4; } - else if( datarate > LORAMAC_MIN_DATARATE ) + else if( datarate > LORAMAC_TX_MIN_DATARATE ) { datarate--; } - if( datarate == LORAMAC_MIN_DATARATE ) + if( datarate == LORAMAC_TX_MIN_DATARATE ) { if( updateChannelMask == true ) { @@ -1894,12 +2091,7 @@ ChannelsMask[5] = 0x0000; #else // defined( USE_BAND_915_HYBRID ) // Re-enable default channels - ChannelsMask[0] = 0x00FF; - ChannelsMask[1] = 0x0000; - ChannelsMask[2] = 0x0000; - ChannelsMask[3] = 0x0000; - ChannelsMask[4] = 0x0001; - ChannelsMask[5] = 0x0000; + ReenableChannels( ChannelsMask[4], ChannelsMask ); #endif } } @@ -2124,11 +2316,18 @@ { status &= 0xFE; // Channel mask KO } + +#if defined( USE_BAND_915_HYBRID ) + if( ValidateChannelMask( channelsMask ) == false ) + { + status &= 0xFE; // Channel mask KO + } +#endif } #else #error "Please define a frequency band in the compiler options." #endif - if( ValueInRange( datarate, LORAMAC_MIN_DATARATE, LORAMAC_MAX_DATARATE ) == false ) + if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false ) { status &= 0xFD; // Datarate KO } @@ -2144,21 +2343,14 @@ { ChannelsDatarate = datarate; ChannelsTxPower = txPower; -#if defined( USE_BAND_915_HYBRID ) - ChannelsMask[0] = channelsMask[0] & 0x00FF; - ChannelsMask[1] = channelsMask[1] & 0x0000; - ChannelsMask[2] = channelsMask[2] & 0x0000; - ChannelsMask[3] = channelsMask[3] & 0x0000; - ChannelsMask[4] = channelsMask[4] & 0x0001; - ChannelsMask[5] = channelsMask[5] & 0x0000; -#else + ChannelsMask[0] = channelsMask[0]; ChannelsMask[1] = channelsMask[1]; ChannelsMask[2] = channelsMask[2]; ChannelsMask[3] = channelsMask[3]; ChannelsMask[4] = channelsMask[4]; ChannelsMask[5] = channelsMask[5]; -#endif + ChannelsNbRep = nbRep; } AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 ); @@ -2190,7 +2382,7 @@ status &= 0xFE; // Channel frequency KO } - if( ValueInRange( datarate, LORAMAC_MIN_DATARATE, LORAMAC_MAX_DATARATE ) == false ) + if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false ) { status &= 0xFD; // Datarate KO } @@ -2358,6 +2550,8 @@ AggregatedTimeOff = 0; } + CalculateBackOff( LastTxChannel ); + // Select channel while( SetNextChannel( &dutyCycleTimeOff ) == false ) { @@ -2387,6 +2581,30 @@ } } +static void CalculateBackOff( uint8_t channel ) +{ + uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle; + + if( IsLoRaMacNetworkJoined == false ) + { +#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 ) + dutyCycle = JOIN_DC; +#endif + } + + // Update Band Time OFF + if( DutyCycleOn == true ) + { + Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir; + } + else + { + Bands[Channels[channel].Band].TimeOff = 0; + } + // Update Aggregated Time OFF + AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir ); +} + LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ) { uint16_t i; @@ -2537,15 +2755,16 @@ LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel ) { int8_t datarate = Datarates[ChannelsDatarate]; + int8_t txPowerIndex = 0; int8_t txPower = 0; - ChannelsTxPower = LimitTxPower( ChannelsTxPower ); - txPower = TxPowers[ChannelsTxPower]; + txPowerIndex = LimitTxPower( ChannelsTxPower ); + txPower = TxPowers[txPowerIndex]; MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; McpsConfirm.Datarate = ChannelsDatarate; - McpsConfirm.TxPower = ChannelsTxPower; + McpsConfirm.TxPower = txPowerIndex; Radio.SetChannel( channel.Frequency ); @@ -2876,6 +3095,11 @@ mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2; break; } + case MIB_CHANNELS_DEFAULT_DATARATE: + { + mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate; + break; + } case MIB_CHANNELS_DATARATE: { mibGet->Param.ChannelsDatarate = ChannelsDatarate; @@ -3015,19 +3239,32 @@ if( mibSet->Param.ChannelsMask ) { #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 6 ) && - ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) ) + bool chanMaskState = true; + +#if defined( USE_BAND_915_HYBRID ) + chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask ); +#endif + if( chanMaskState == true ) { - status = LORAMAC_STATUS_PARAMETER_INVALID; + if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < 6 ) && + ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) ) + { + status = LORAMAC_STATUS_PARAMETER_INVALID; + } + else + { + memcpy1( ( uint8_t* ) ChannelsMask, + ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) ); + for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ ) + { + // Disable channels which are no longer available + ChannelsMaskRemaining[i] &= ChannelsMask[i]; + } + } } else { - memcpy1( ( uint8_t* ) ChannelsMask, - ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) ); - for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ ) - { - ChannelsMaskRemaining[i] &= ChannelsMask[i]; - } + status = LORAMAC_STATUS_PARAMETER_INVALID; } #else memcpy1( ( uint8_t* ) ChannelsMask, @@ -3078,10 +3315,23 @@ JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2; break; } + case MIB_CHANNELS_DEFAULT_DATARATE: + { + if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate, + LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) + { + ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate; + } + else + { + status = LORAMAC_STATUS_PARAMETER_INVALID; + } + break; + } case MIB_CHANNELS_DATARATE: { if( ValueInRange( mibSet->Param.ChannelsDatarate, - LORAMAC_MIN_DATARATE, LORAMAC_MAX_DATARATE ) ) + LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) ) { ChannelsDatarate = mibSet->Param.ChannelsDatarate; } @@ -3116,6 +3366,16 @@ } break; } + case MIB_UPLINK_COUNTER: + { + UpLinkCounter = mibSet->Param.UpLinkCounter; + break; + } + case MIB_DOWNLINK_COUNTER: + { + DownLinkCounter = mibSet->Param.DownLinkCounter; + break; + } default: status = LORAMAC_STATUS_SERVICE_UNKNOWN; break; @@ -3148,10 +3408,10 @@ } // Validate the datarate if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) || - ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_MIN_DATARATE, - LORAMAC_MAX_DATARATE ) == false ) || - ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_MIN_DATARATE, - LORAMAC_MAX_DATARATE ) == false ) ) + ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE, + LORAMAC_TX_MAX_DATARATE ) == false ) || + ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE, + LORAMAC_TX_MAX_DATARATE ) == false ) ) { datarateInvalid = true; } @@ -3164,11 +3424,11 @@ frequencyInvalid = true; } - if( params.DrRange.Fields.Min > LORAMAC_DEFAULT_DATARATE ) + if( params.DrRange.Fields.Min > ChannelsDefaultDatarate ) { datarateInvalid = true; } - if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_MAX_DATARATE ) == false ) + if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false ) { datarateInvalid = true; } @@ -3243,7 +3503,7 @@ } } - if( id < 3 ) + if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) ) { return LORAMAC_STATUS_PARAMETER_INVALID; } @@ -3251,7 +3511,7 @@ { // Remove the channel from the list of channels Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 }; - + // Disable the channel as it doesn't exist anymore if( DisableChannelInMask( id, ChannelsMask ) == false ) { @@ -3501,7 +3761,7 @@ { if( AdrCtrlOn == false ) { - if( ValueInRange( datarate, LORAMAC_MIN_DATARATE, LORAMAC_MAX_DATARATE ) == true ) + if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true ) { ChannelsDatarate = datarate; }