Simplified LoRaWAN library.
Fork of LoRaWAN-lib-v1_0_1 by
Diff: LoRaMac.cpp
- Revision:
- 3:b9d87593a8ae
- Parent:
- 2:14a5d6ad92d5
- Child:
- 4:37c12dbc8dc7
diff -r 14a5d6ad92d5 -r b9d87593a8ae LoRaMac.cpp --- a/LoRaMac.cpp Tue Jan 05 16:41:54 2016 +0000 +++ b/LoRaMac.cpp Mon Mar 14 09:09:54 2016 +0000 @@ -300,12 +300,6 @@ LC1, LC2, LC3, - LC4, - LC5, - LC6, - LC7, - LC8, - LC9, }; #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) /*! @@ -447,6 +441,7 @@ MAC_ACK_REQ = 0x00000004, MAC_ACK_RETRY = 0x00000008, MAC_TX_DELAYED = 0x00000010, + MAC_TX_CONFIG = 0x00000020, }; /*! @@ -562,6 +557,12 @@ static void OnRadioTxDone( void ); /*! + * \brief This function prepares the MAC to abort the execution of function + * OnRadioRxDone in case of a reception error. + */ +static void PrepareRxDoneAbort( void ); + +/*! * \brief Function to be executed on Radio Rx Done event */ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); @@ -609,9 +610,13 @@ /*! * \brief Searches and set the next random available channel * - * \retval status Function status [0: OK, 1: Unable to find a free channel] + * \param [OUT] Time to wait for the next transmission according to the duty + * cycle. + * + * \retval status Function status [1: OK, 0: Unable to find a channel on the + * current datarate] */ -static TimerTime_t SetNextChannel( void ); +static bool SetNextChannel( TimerTime_t* time ); /*! * \brief Sets the network to public or private. Updates the sync byte. @@ -833,6 +838,28 @@ } } +static void PrepareRxDoneAbort( void ) +{ + LoRaMacState &= ~MAC_TX_RUNNING; + + if( NodeAckRequested ) + { + OnAckTimeoutTimerEvent( ); + } + + if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) ) + { + OnRxWindow2TimerEvent( ); + } + + LoRaMacFlags.Bits.McpsInd = 1; + LoRaMacFlags.Bits.MacDone = 1; + + // Trig OnMacCheckTimerEvent call as soon as possible + TimerSetValue( &MacStateCheckTimer, 1000 ); + TimerStart( &MacStateCheckTimer ); +} + static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { LoRaMacHeader_t macHdr; @@ -941,11 +968,13 @@ ChannelParams_t param; param.DrRange.Value = ( DR_5 << 4 ) | DR_0; + LoRaMacState |= MAC_TX_CONFIG; for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 ) { param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100; LoRaMacChannelAdd( i, param ); } + LoRaMacState &= ~MAC_TX_CONFIG; } #endif MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK; @@ -960,8 +989,6 @@ case FRAME_TYPE_DATA_CONFIRMED_DOWN: case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: { - LoRaMacFlags.Bits.McpsInd = 1; - address = payload[pktHeaderLen++]; address |= ( (uint32_t)payload[pktHeaderLen++] << 8 ); address |= ( (uint32_t)payload[pktHeaderLen++] << 16 ); @@ -985,13 +1012,8 @@ if( multicast == 0 ) { // We are not the destination of this frame. - LoRaMacFlags.Bits.MacDone = 1; McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL; - LoRaMacState &= ~MAC_TX_RUNNING; - if( NodeAckRequested ) - { - OnAckTimeoutTimerEvent( ); - } + PrepareRxDoneAbort( ); return; } } @@ -1003,12 +1025,6 @@ downLinkCounter = DownLinkCounter; } - if( LoRaMacDeviceClass != CLASS_A ) - { - LoRaMacState |= MAC_RX; - // Starts the MAC layer status check timer - TimerStart( &MacStateCheckTimer ); - } fCtrl.Value = payload[pktHeaderLen++]; sequenceCounter = ( uint16_t )payload[pktHeaderLen++]; @@ -1066,14 +1082,9 @@ if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) && ( curMulticastParams->DownLinkCounter != 0 ) ) { - LoRaMacFlags.Bits.MacDone = 1; McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; McpsIndication.DownLinkCounter = downLinkCounter; - LoRaMacState &= ~MAC_TX_RUNNING; - if( NodeAckRequested == true ) - { - OnAckTimeoutTimerEvent( ); - } + PrepareRxDoneAbort( ); return; } curMulticastParams->DownLinkCounter = downLinkCounter; @@ -1082,36 +1093,25 @@ { if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) { + SrvAckRequested = true; McpsIndication.McpsIndication = MCPS_CONFIRMED; } else { + SrvAckRequested = false; McpsIndication.McpsIndication = MCPS_UNCONFIRMED; } if( ( DownLinkCounter == downLinkCounter ) && ( DownLinkCounter != 0 ) ) { - LoRaMacFlags.Bits.MacDone = 1; McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED; McpsIndication.DownLinkCounter = downLinkCounter; - LoRaMacState &= ~MAC_TX_RUNNING; - if( NodeAckRequested == true ) - { - OnAckTimeoutTimerEvent( ); - } + PrepareRxDoneAbort( ); return; } DownLinkCounter = downLinkCounter; } - if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) - { - SrvAckRequested = true; - } - else - { - SrvAckRequested = false; - } // Check if the frame is an acknowledgement if( fCtrl.Bits.Ack == 1 ) { @@ -1174,34 +1174,32 @@ McpsIndication.RxData = true; } } + LoRaMacFlags.Bits.McpsInd = 1; } else { McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL; - LoRaMacState &= ~MAC_TX_RUNNING; - if( NodeAckRequested == true ) - { - OnAckTimeoutTimerEvent( ); - } + + PrepareRxDoneAbort( ); + return; } } break; case FRAME_TYPE_PROPRIETARY: { - LoRaMacFlags.Bits.McpsInd = 1; - memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size ); McpsIndication.McpsIndication = MCPS_PROPRIETARY; McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK; McpsIndication.Buffer = LoRaMacRxPayload; McpsIndication.BufferSize = size - pktHeaderLen; + + LoRaMacFlags.Bits.McpsInd = 1; break; } default: - LoRaMacFlags.Bits.McpsInd = 1; McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR; - LoRaMacState &= ~MAC_TX_RUNNING; + PrepareRxDoneAbort( ); break; } @@ -1209,8 +1207,11 @@ { OnRxWindow2TimerEvent( ); } - LoRaMacFlags.Bits.MacDone = 1; + + // Trig OnMacCheckTimerEvent call as soon as possible + TimerSetValue( &MacStateCheckTimer, 1000 ); + TimerStart( &MacStateCheckTimer ); } static void OnRadioTxTimeout( void ) @@ -1336,6 +1337,7 @@ if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) ) { AckTimeoutRetry = false; + NodeAckRequested = false; if( IsUpLinkCounterFixed == false ) { UpLinkCounter++; @@ -1387,6 +1389,7 @@ #endif LoRaMacState &= ~MAC_TX_RUNNING; + NodeAckRequested = false; McpsConfirm.AckReceived = false; McpsConfirm.NbRetries = AckTimeoutRetriesCounter; if( IsUpLinkCounterFixed == false ) @@ -1420,6 +1423,7 @@ else { // Operation not finished restart timer + TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT ); TimerStart( &MacStateCheckTimer ); } @@ -1546,9 +1550,10 @@ } } -static TimerTime_t SetNextChannel( void ) +static bool SetNextChannel( TimerTime_t* time ) { 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 ); @@ -1556,11 +1561,28 @@ memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS ); #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) + - ( ChannelsMaskRemaining[4] & 0x00FF ) ) == 0 ) + if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 ) + { // Restore default channels + memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 ); + } + if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) ) + { // Make sure, that the channels are activated + ChannelsMaskRemaining[4] = ChannelsMask[4]; + } +#else + uint8_t chanCnt = 0; + for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ ) { - memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, - sizeof( ChannelsMask ) ); + if( ChannelsMask[k] != 0 ) + { + chanCnt++; + break; + } + } + if( chanCnt == 0 ) + { + // Re-enable default channels, if no channel is enabled + ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); } #endif @@ -1605,21 +1627,16 @@ { if( Channels[i + j].Frequency == 0 ) { // Check if the channel is enabled -#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - DisableChannelInMask( i + j, ChannelsMaskRemaining ); -#endif continue; } 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 -#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - DisableChannelInMask( i + j, ChannelsMaskRemaining ); -#endif continue; } if( Bands[Channels[i + j].Band].TimeOff > 0 ) { // Check if the band is available for transmission + delayTx++; continue; } enabledChannels[nbEnabledChannels++] = i + j; @@ -1629,6 +1646,7 @@ } else { + delayTx++; nextTxDelay = AggregatedTimeOff - ( curTime - AggregatedLastTxDoneTime ); } @@ -1636,14 +1654,25 @@ { Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )]; #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - DisableChannelInMask( Channel, ChannelsMaskRemaining ); + if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) ) + { + DisableChannelInMask( Channel, ChannelsMaskRemaining ); + } #endif - return 0; + *time = 0; + return true; } else { - // Protect the function of returning the initialization value of nextTxDelay - return ( nextTxDelay == ( TimerTime_t )( -1 ) ) ? 0 : nextTxDelay; + if( delayTx > 0 ) + { + // Delay transmission due to AggregatedTimeOff or to a band time off + *time = nextTxDelay; + return true; + } + // Datarate not supported by any channel + *time = 0; + return false; } } @@ -1813,38 +1842,10 @@ { AdrAckCounter = 0; adrAckReq = false; - - if( updateChannelMask == true ) - { -#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 ) ); -#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) -#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; -#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; -#endif -#else -#error "Please define a frequency band in the compiler options." -#endif - } } else { - if( AdrAckCounter > ADR_ACK_LIMIT ) + if( AdrAckCounter >= ADR_ACK_LIMIT ) { adrAckReq = true; } @@ -1852,26 +1853,60 @@ { adrAckReq = false; } - if( AdrAckCounter > ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) ) + if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) ) { - AdrAckCounter = 0; + 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 ) - { - datarate--; - } + if( datarate > LORAMAC_MIN_DATARATE ) + { + datarate--; + } + if( datarate == LORAMAC_MIN_DATARATE ) + { + if( updateChannelMask == true ) + { + + // Re-enable default channels LC1, LC2, LC3 + ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) ); + } + } #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) - if( ( datarate > LORAMAC_MIN_DATARATE ) && ( datarate == DR_8 ) ) - { - datarate = DR_4; - } - else if( datarate > LORAMAC_MIN_DATARATE ) - { - datarate--; - } + if( ( datarate > LORAMAC_MIN_DATARATE ) && ( datarate == DR_8 ) ) + { + datarate = DR_4; + } + else if( datarate > LORAMAC_MIN_DATARATE ) + { + datarate--; + } + if( datarate == LORAMAC_MIN_DATARATE ) + { + if( updateChannelMask == true ) + { +#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; +#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; +#endif + } + } #else #error "Please define a frequency band in the compiler options." #endif + } } } } @@ -2193,8 +2228,10 @@ case SRV_MAC_NEW_CHANNEL_REQ: { uint8_t status = 0x03; + #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) - status &= 0xFE; // Channel frequency KO + status &= 0xFC; // Channel frequency and datarate KO + macIndex += 5; #else int8_t channelIndex = 0; ChannelParams_t chParam; @@ -2206,21 +2243,52 @@ chParam.Frequency *= 100; chParam.DrRange.Value = payload[macIndex++]; - if( ValueInRange( channelIndex, 3, LORA_MAX_NB_CHANNELS - 1 ) == false ) - + LoRaMacState |= MAC_TX_CONFIG; + if( chParam.Frequency == 0 ) { - status &= 0xFE; // Channel frequency KO + if( channelIndex < 3 ) + { + status &= 0xFC; + } + else + { + if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK ) + { + status &= 0xFC; + } + } } - - if( Radio.CheckRfFrequency( chParam.Frequency ) == false ) + else { - status &= 0xFE; // Channel frequency KO + switch( LoRaMacChannelAdd( channelIndex, chParam ) ) + { + case LORAMAC_STATUS_OK: + { + break; + } + case LORAMAC_STATUS_FREQUENCY_INVALID: + { + status &= 0xFE; + break; + } + case LORAMAC_STATUS_DATARATE_INVALID: + { + status &= 0xFD; + break; + } + case LORAMAC_STATUS_FREQ_AND_DR_INVALID: + { + status &= 0xFC; + break; + } + default: + { + status &= 0xFC; + break; + } + } } - - if( LoRaMacChannelAdd( channelIndex, chParam ) != LORAMAC_STATUS_OK ) - { - status &= 0xFD; // Datarate range KO - } + LoRaMacState &= ~MAC_TX_CONFIG; #endif AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 ); } @@ -2291,7 +2359,16 @@ } // Select channel - dutyCycleTimeOff = SetNextChannel( ); + while( SetNextChannel( &dutyCycleTimeOff ) == false ) + { + // Set the default datarate + ChannelsDatarate = ChannelsDefaultDatarate; + +#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 ) ); +#endif + } // Schedule transmission of frame if( dutyCycleTimeOff == 0 ) @@ -2365,6 +2442,8 @@ 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 ) { return LORAMAC_STATUS_LENGTH_ERROR; @@ -2379,8 +2458,6 @@ fCtrl->Bits.Ack = 1; } - fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate ); - LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF; LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF; @@ -2513,6 +2590,7 @@ MlmeConfirm.TxTimeOnAir = TxTimeOnAir; // Starts the MAC layer status check timer + TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT ); TimerStart( &MacStateCheckTimer ); // Send now @@ -3048,117 +3126,142 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params ) { +#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) + return LORAMAC_STATUS_PARAMETER_INVALID; +#else + bool datarateInvalid = false; + bool frequencyInvalid = false; + uint8_t band = 0; + + // The id must not exceed LORA_MAX_NB_CHANNELS if( id >= LORA_MAX_NB_CHANNELS ) { return LORAMAC_STATUS_PARAMETER_INVALID; } + // Validate if the MAC is in a correct state if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) { - return LORAMAC_STATUS_BUSY; + if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG ) + { + return LORAMAC_STATUS_BUSY; + } } + // 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 ) ) { - return LORAMAC_STATUS_PARAMETER_INVALID; + datarateInvalid = true; } - params.Band = 0; - -#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) - return LORAMAC_STATUS_PARAMETER_INVALID; -#else -#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) - Channels[id] = params; - Channels[id].Band = 0; // No duty cycle on EU433 and CN470 bands -#elif defined( USE_BAND_868 ) - Channels[id] = params; - if( ( Channels[id].Frequency >= 865000000 ) && ( Channels[id].Frequency <= 868000000 ) ) +#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) + if( id < 3 ) { - if( Channels[id].Band != BAND_G1_0 ) + if( params.Frequency != Channels[id].Frequency ) { - Channels[id].Band = BAND_G1_0; + frequencyInvalid = true; + } + + if( params.DrRange.Fields.Min > LORAMAC_DEFAULT_DATARATE ) + { + datarateInvalid = true; + } + if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_MAX_DATARATE ) == false ) + { + datarateInvalid = true; } } - else if( ( Channels[id].Frequency > 868000000 ) && ( Channels[id].Frequency <= 868600000 ) ) +#endif + + // Validate the frequency + if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) ) { - if( Channels[id].Band != BAND_G1_1 ) +#if defined( USE_BAND_868 ) + if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) ) { - Channels[id].Band = BAND_G1_1; + band = BAND_G1_0; } - } - else if( ( Channels[id].Frequency >= 868700000 ) && ( Channels[id].Frequency <= 869200000 ) ) - { - if( Channels[id].Band != BAND_G1_2 ) + else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) ) { - Channels[id].Band = BAND_G1_2; + band = BAND_G1_1; } - } - else if( ( Channels[id].Frequency >= 869400000 ) && ( Channels[id].Frequency <= 869650000 ) ) - { - if( Channels[id].Band != BAND_G1_3 ) + else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) ) { - Channels[id].Band = BAND_G1_3; + band = BAND_G1_2; + } + else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) ) + { + band = BAND_G1_3; } - } - else if( ( Channels[id].Frequency >= 869700000 ) && ( Channels[id].Frequency <= 870000000 ) ) - { - if( Channels[id].Band != BAND_G1_4 ) + else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) ) { - Channels[id].Band = BAND_G1_4; + band = BAND_G1_4; } + else + { + frequencyInvalid = true; + } +#endif } else { - Channels[id].Frequency = 0; - Channels[id].DrRange.Value = 0; + frequencyInvalid = true; + } + + if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) ) + { + return LORAMAC_STATUS_FREQ_AND_DR_INVALID; } -#else - #error "Please define a frequency band in the compiler options." -#endif - // Check if it is a valid channel - if( Channels[id].Frequency > 0 ) + if( datarateInvalid == true ) + { + return LORAMAC_STATUS_DATARATE_INVALID; + } + if( frequencyInvalid == true ) { - // Activate the newly created channel - if( id < 16 ) - { - ChannelsMask[0] |= 1 << id; - } + return LORAMAC_STATUS_FREQUENCY_INVALID; } + // Every parameter is valid, activate the channel + Channels[id] = params; + Channels[id].Band = band; + ChannelsMask[0] |= ( 1 << id ); + return LORAMAC_STATUS_OK; #endif } LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id ) { +#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) { - return LORAMAC_STATUS_BUSY; + if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG ) + { + return LORAMAC_STATUS_BUSY; + } } -#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) - if( id < 64 ) + + if( id < 3 ) { - if( CountNbEnabled125kHzChannels( ChannelsMask ) <= 6 ) + return LORAMAC_STATUS_PARAMETER_INVALID; + } + else + { + // 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 ) { return LORAMAC_STATUS_PARAMETER_INVALID; } } -#else - if( id < 3 ) - { - return LORAMAC_STATUS_PARAMETER_INVALID; - } + return LORAMAC_STATUS_OK; +#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) ) + return LORAMAC_STATUS_PARAMETER_INVALID; #endif - - if( DisableChannelInMask( id, ChannelsMask ) == false ) - { - return LORAMAC_STATUS_PARAMETER_INVALID; - } - - return LORAMAC_STATUS_OK; } LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam ) @@ -3283,6 +3386,14 @@ 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 ) @@ -3362,7 +3473,7 @@ { readyToSend = true; AckTimeoutRetriesCounter = 1; - AckTimeoutRetries = mcpsRequest->Req.Confirmed.nbRetries; + AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials; macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP; fPort = mcpsRequest->Req.Confirmed.fPort;