uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed ) { uint8_t status = 0x07; LinkAdrParams_t linkAdrParams; uint8_t nextIndex = 0; uint8_t bytesProcessed = 0; uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 }; // Initialize local copy of channels mask RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 ); while( bytesProcessed < linkAdrReq->PayloadSize ) { 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; if( linkAdrParams.ChMaskCtrl == 6 ) { // Enable all 125 kHz channels channelsMask[0] = 0xFFFF; channelsMask[1] = 0xFFFF; channelsMask[2] = 0xFFFF; channelsMask[3] = 0xFFFF; // Apply chMask to channels 64 to 71 channelsMask[4] = linkAdrParams.ChMask; } else if( linkAdrParams.ChMaskCtrl == 7 ) { // Disable all 125 kHz channels channelsMask[0] = 0x0000; channelsMask[1] = 0x0000; channelsMask[2] = 0x0000; channelsMask[3] = 0x0000; // Apply chMask to channels 64 to 71 channelsMask[4] = linkAdrParams.ChMask; } else if( linkAdrParams.ChMaskCtrl == 5 ) { // RFU status &= 0xFE; // Channel mask KO } else { channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask; } } // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) ) { status &= 0xFE; // Channel mask KO } // Verify datarate if( RegionCommonChanVerifyDr( AU915_MAX_NB_CHANNELS, channelsMask, linkAdrParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE, Channels ) == false ) { status &= 0xFD; // Datarate KO } // Verify tx power if( RegionCommonValueInRange( linkAdrParams.TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER ) == 0 ) { // Verify if the maximum TX power is exceeded if( AU915_MAX_TX_POWER > linkAdrParams.TxPower ) { // Apply maximum TX power. Accept TX power. linkAdrParams.TxPower = AU915_MAX_TX_POWER; } else { status &= 0xFB; // TxPower KO } } // Update channelsMask if everything is correct if( status == 0x07 ) { if( linkAdrParams.NbRep == 0 ) { // Value of 0 is not allowed, revert to default. linkAdrParams.NbRep = 1; } // Copy Mask RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 ); ChannelsMaskRemaining[0] &= ChannelsMask[0]; ChannelsMaskRemaining[1] &= ChannelsMask[1]; ChannelsMaskRemaining[2] &= ChannelsMask[2]; ChannelsMaskRemaining[3] &= ChannelsMask[3]; ChannelsMaskRemaining[4] = ChannelsMask[4]; ChannelsMaskRemaining[5] = ChannelsMask[5]; } // Update status variables *drOut = linkAdrParams.Datarate; *txPowOut = linkAdrParams.TxPower; *nbRepOut = linkAdrParams.NbRep; *nbBytesParsed = bytesProcessed; return status; }
uint8_t RegionCN470ALinkAdrReq( LinkAdrReqParams_t *linkAdrReq, int8_t *drOut, int8_t *txPowOut, uint8_t *nbRepOut, uint8_t *nbBytesParsed ) { uint8_t status = 0x07; LinkAdrParams_t linkAdrParams; uint8_t nextIndex = 0; uint8_t bytesProcessed = 0; uint16_t chMask = 0; 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 < CN470A_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 } } } } } // Verify datarate if ( RegionCommonChanVerifyDr( CN470A_MAX_NB_CHANNELS, &chMask, linkAdrParams.Datarate, CN470A_TX_MIN_DATARATE, CN470A_TX_MAX_DATARATE, Channels ) == false ) { status &= 0xFD; // Datarate KO } // Verify tx power if ( RegionCommonValueInRange( linkAdrParams.TxPower, CN470A_MAX_TX_POWER, CN470A_MIN_TX_POWER ) == 0 ) { // Verify if the maximum TX power is exceeded if ( CN470A_MAX_TX_POWER > linkAdrParams.TxPower ) { // Apply maximum TX power. Accept TX power. linkAdrParams.TxPower = CN470A_MAX_TX_POWER; } else { status &= 0xFB; // TxPower KO } } // Update channelsMask if everything is correct if ( status == 0x07 ) { if ( linkAdrParams.NbRep == 0 ) { // Value of 0 is not allowed, revert to default. linkAdrParams.NbRep = 1; } // 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; }
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; }