bool RegionEU433AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter ) { bool adrAckReq = false; int8_t datarate = adrNext->Datarate; int8_t txPower = adrNext->TxPower; GetPhyParams_t getPhy; PhyParam_t phyParam; // Report back the adr ack counter *adrAckCounter = adrNext->AdrAckCounter; if( adrNext->AdrEnabled == true ) { if( datarate == EU433_TX_MIN_DATARATE ) { *adrAckCounter = 0; adrAckReq = false; } else { if( adrNext->AdrAckCounter >= EU433_ADR_ACK_LIMIT ) { adrAckReq = true; txPower = EU433_MAX_TX_POWER; } else { adrAckReq = false; } if( adrNext->AdrAckCounter >= ( EU433_ADR_ACK_LIMIT + EU433_ADR_ACK_DELAY ) ) { if( ( adrNext->AdrAckCounter % EU433_ADR_ACK_DELAY ) == 1 ) { // Decrease the datarate getPhy.Attribute = PHY_NEXT_LOWER_TX_DR; getPhy.Datarate = datarate; getPhy.UplinkDwellTime = adrNext->UplinkDwellTime; phyParam = RegionEU433GetPhyParam( &getPhy ); datarate = phyParam.Value; if( datarate == EU433_TX_MIN_DATARATE ) { // We must set adrAckReq to false as soon as we reach the lowest datarate adrAckReq = false; if( adrNext->UpdateChanMask == true ) { // Re-enable default channels ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 ); } } } } } } *drOut = datarate; *txPowOut = txPower; return adrAckReq; }
uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed ) { uint8_t status = 0x07; RegionCommonLinkAdrParams_t linkAdrParams; uint8_t nextIndex = 0; uint8_t bytesProcessed = 0; uint16_t chMask = 0; GetPhyParams_t getPhy; PhyParam_t phyParam; RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams; while( bytesProcessed < linkAdrReq->PayloadSize ) { // Get ADR request parameters nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams ); if( nextIndex == 0 ) break; // break loop, since no more request has been found // Update bytes processed bytesProcessed += nextIndex; // Revert status, as we only check the last ADR request for the channel mask KO status = 0x07; // Setup temporary channels mask chMask = linkAdrParams.ChMask; // Verify channels mask if( ( linkAdrParams.ChMaskCtrl == 0 ) && ( chMask == 0 ) ) { status &= 0xFE; // Channel mask KO } else if( ( ( linkAdrParams.ChMaskCtrl >= 1 ) && ( linkAdrParams.ChMaskCtrl <= 5 )) || ( linkAdrParams.ChMaskCtrl >= 7 ) ) { // RFU status &= 0xFE; // Channel mask KO } else { for( uint8_t i = 0; i < EU433_MAX_NB_CHANNELS; i++ ) { if( linkAdrParams.ChMaskCtrl == 6 ) { if( Channels[i].Frequency != 0 ) { chMask |= 1 << i; } } else { if( ( ( chMask & ( 1 << i ) ) != 0 ) && ( Channels[i].Frequency == 0 ) ) {// Trying to enable an undefined channel status &= 0xFE; // Channel mask KO } } } } } // Get the minimum possible datarate getPhy.Attribute = PHY_MIN_TX_DR; getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime; phyParam = RegionEU433GetPhyParam( &getPhy ); linkAdrVerifyParams.Status = status; linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled; linkAdrVerifyParams.Datarate = linkAdrParams.Datarate; linkAdrVerifyParams.TxPower = linkAdrParams.TxPower; linkAdrVerifyParams.NbRep = linkAdrParams.NbRep; linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate; linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower; linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep; linkAdrVerifyParams.NbChannels = EU433_MAX_NB_CHANNELS; linkAdrVerifyParams.ChannelsMask = &chMask; linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value; linkAdrVerifyParams.MaxDatarate = EU433_TX_MAX_DATARATE; linkAdrVerifyParams.Channels = Channels; linkAdrVerifyParams.MinTxPower = EU433_MIN_TX_POWER; linkAdrVerifyParams.MaxTxPower = EU433_MAX_TX_POWER; // Verify the parameters and update, if necessary status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep ); // Update channelsMask if everything is correct if( status == 0x07 ) { // Set the channels mask to a default value memset( ChannelsMask, 0, sizeof( ChannelsMask ) ); // Update the channels mask ChannelsMask[0] = chMask; } // Update status variables *drOut = linkAdrParams.Datarate; *txPowOut = linkAdrParams.TxPower; *nbRepOut = linkAdrParams.NbRep; *nbBytesParsed = bytesProcessed; return status; }