| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034 |
- /*!
- * \file RegionEU433.c
- *
- * \brief Region implementation for EU433
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013-2017 Semtech
- *
- * ___ _____ _ ___ _ _____ ___ ___ ___ ___
- * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
- * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- * embedded.connectivity.solutions===============
- *
- * \endcode
- *
- * \author Miguel Luis ( Semtech )
- *
- * \author Gregory Cristian ( Semtech )
- *
- * \author Daniel Jaeckle ( STACKFORCE )
- */
- #include "utilities.h"
- #include "RegionCommon.h"
- #include "RegionEU433.h"
- // Definitions
- #define CHANNELS_MASK_SIZE 1
- /*!
- * Region specific context
- */
- typedef struct sRegionEU433NvmCtx
- {
- /*!
- * LoRaMAC channels
- */
- ChannelParams_t Channels[ EU433_MAX_NB_CHANNELS ];
- /*!
- * LoRaMac bands
- */
- Band_t Bands[ EU433_MAX_NB_BANDS ];
- /*!
- * LoRaMac channels mask
- */
- uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
- /*!
- * LoRaMac channels default mask
- */
- uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
- }RegionEU433NvmCtx_t;
- /*
- * Non-volatile module context.
- */
- static RegionEU433NvmCtx_t NvmCtx;
- // Static functions
- static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
- {
- uint8_t nextLowerDr = 0;
- if( dr == minDr )
- {
- nextLowerDr = minDr;
- }
- else
- {
- nextLowerDr = dr - 1;
- }
- return nextLowerDr;
- }
- static uint32_t GetBandwidth( uint32_t drIndex )
- {
- switch( BandwidthsEU433[drIndex] )
- {
- default:
- case 125000:
- return 0;
- case 250000:
- return 1;
- case 500000:
- return 2;
- }
- }
- static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
- {
- int8_t txPowerResult = txPower;
- // Limit tx power to the band max
- txPowerResult = MAX( txPower, maxBandTxPower );
- return txPowerResult;
- }
- static bool VerifyRfFreq( uint32_t freq )
- {
- // Check radio driver support
- if( Radio.CheckRfFrequency( freq ) == false )
- {
- return false;
- }
- if( ( freq < 433175000 ) || ( freq > 434665000 ) )
- {
- return false;
- }
- return true;
- }
- static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
- {
- uint8_t nbEnabledChannels = 0;
- uint8_t delayTransmission = 0;
- for( uint8_t i = 0, k = 0; i < EU433_MAX_NB_CHANNELS; i += 16, k++ )
- {
- for( uint8_t j = 0; j < 16; j++ )
- {
- if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
- {
- if( channels[i + j].Frequency == 0 )
- { // Check if the channel is enabled
- continue;
- }
- if( joined == false )
- {
- if( ( EU433_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
- {
- continue;
- }
- }
- if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
- channels[i + j].DrRange.Fields.Max ) == false )
- { // Check if the current channel selection supports the given datarate
- continue;
- }
- if( bands[channels[i + j].Band].TimeOff > 0 )
- { // Check if the band is available for transmission
- delayTransmission++;
- continue;
- }
- enabledChannels[nbEnabledChannels++] = i + j;
- }
- }
- }
- *delayTx = delayTransmission;
- return nbEnabledChannels;
- }
- PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
- {
- PhyParam_t phyParam = { 0 };
- switch( getPhy->Attribute )
- {
- case PHY_MIN_RX_DR:
- {
- phyParam.Value = EU433_RX_MIN_DATARATE;
- break;
- }
- case PHY_MIN_TX_DR:
- {
- phyParam.Value = EU433_TX_MIN_DATARATE;
- break;
- }
- case PHY_DEF_TX_DR:
- {
- phyParam.Value = EU433_DEFAULT_DATARATE;
- break;
- }
- case PHY_NEXT_LOWER_TX_DR:
- {
- phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, EU433_TX_MIN_DATARATE );
- break;
- }
- case PHY_MAX_TX_POWER:
- {
- phyParam.Value = EU433_MAX_TX_POWER;
- break;
- }
- case PHY_DEF_TX_POWER:
- {
- phyParam.Value = EU433_DEFAULT_TX_POWER;
- break;
- }
- case PHY_DEF_ADR_ACK_LIMIT:
- {
- phyParam.Value = EU433_ADR_ACK_LIMIT;
- break;
- }
- case PHY_DEF_ADR_ACK_DELAY:
- {
- phyParam.Value = EU433_ADR_ACK_DELAY;
- break;
- }
- case PHY_MAX_PAYLOAD:
- {
- phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate];
- break;
- }
- case PHY_MAX_PAYLOAD_REPEATER:
- {
- phyParam.Value = MaxPayloadOfDatarateRepeaterEU433[getPhy->Datarate];
- break;
- }
- case PHY_DUTY_CYCLE:
- {
- phyParam.Value = EU433_DUTY_CYCLE_ENABLED;
- break;
- }
- case PHY_MAX_RX_WINDOW:
- {
- phyParam.Value = EU433_MAX_RX_WINDOW;
- break;
- }
- case PHY_RECEIVE_DELAY1:
- {
- phyParam.Value = EU433_RECEIVE_DELAY1;
- break;
- }
- case PHY_RECEIVE_DELAY2:
- {
- phyParam.Value = EU433_RECEIVE_DELAY2;
- break;
- }
- case PHY_JOIN_ACCEPT_DELAY1:
- {
- phyParam.Value = EU433_JOIN_ACCEPT_DELAY1;
- break;
- }
- case PHY_JOIN_ACCEPT_DELAY2:
- {
- phyParam.Value = EU433_JOIN_ACCEPT_DELAY2;
- break;
- }
- case PHY_MAX_FCNT_GAP:
- {
- phyParam.Value = EU433_MAX_FCNT_GAP;
- break;
- }
- case PHY_ACK_TIMEOUT:
- {
- phyParam.Value = ( EU433_ACKTIMEOUT + randr( -EU433_ACK_TIMEOUT_RND, EU433_ACK_TIMEOUT_RND ) );
- break;
- }
- case PHY_DEF_DR1_OFFSET:
- {
- phyParam.Value = EU433_DEFAULT_RX1_DR_OFFSET;
- break;
- }
- case PHY_DEF_RX2_FREQUENCY:
- {
- phyParam.Value = EU433_RX_WND_2_FREQ;
- break;
- }
- case PHY_DEF_RX2_DR:
- {
- phyParam.Value = EU433_RX_WND_2_DR;
- break;
- }
- case PHY_CHANNELS_MASK:
- {
- phyParam.ChannelsMask = NvmCtx.ChannelsMask;
- break;
- }
- case PHY_CHANNELS_DEFAULT_MASK:
- {
- phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
- break;
- }
- case PHY_MAX_NB_CHANNELS:
- {
- phyParam.Value = EU433_MAX_NB_CHANNELS;
- break;
- }
- case PHY_CHANNELS:
- {
- phyParam.Channels = NvmCtx.Channels;
- break;
- }
- case PHY_DEF_UPLINK_DWELL_TIME:
- case PHY_DEF_DOWNLINK_DWELL_TIME:
- {
- phyParam.Value = 0;
- break;
- }
- case PHY_DEF_MAX_EIRP:
- {
- phyParam.fValue = EU433_DEFAULT_MAX_EIRP;
- break;
- }
- case PHY_DEF_ANTENNA_GAIN:
- {
- phyParam.fValue = EU433_DEFAULT_ANTENNA_GAIN;
- break;
- }
- case PHY_BEACON_CHANNEL_FREQ:
- {
- phyParam.Value = EU433_BEACON_CHANNEL_FREQ;
- break;
- }
- case PHY_BEACON_FORMAT:
- {
- phyParam.BeaconFormat.BeaconSize = EU433_BEACON_SIZE;
- phyParam.BeaconFormat.Rfu1Size = EU433_RFU1_SIZE;
- phyParam.BeaconFormat.Rfu2Size = EU433_RFU2_SIZE;
- break;
- }
- case PHY_BEACON_CHANNEL_DR:
- {
- phyParam.Value = EU433_BEACON_CHANNEL_DR;
- break;
- }
- case PHY_PING_SLOT_CHANNEL_DR:
- {
- phyParam.Value = EU433_PING_SLOT_CHANNEL_DR;
- break;
- }
- default:
- {
- break;
- }
- }
- return phyParam;
- }
- void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone )
- {
- RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
- }
- void RegionEU433InitDefaults( InitDefaultsParams_t* params )
- {
- Band_t bands[EU433_MAX_NB_BANDS] =
- {
- EU433_BAND0
- };
- switch( params->Type )
- {
- case INIT_TYPE_INIT:
- {
- // Initialize bands
- memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS );
- // Channels
- NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
- NvmCtx.Channels[1] = ( ChannelParams_t ) EU433_LC2;
- NvmCtx.Channels[2] = ( ChannelParams_t ) EU433_LC3;
- // Initialize the channels default mask
- NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
- // Update the channels mask
- RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
- break;
- }
- case INIT_TYPE_RESTORE_CTX:
- {
- if( params->NvmCtx != 0 )
- {
- memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
- }
- break;
- }
- case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
- {
- // Restore channels default mask
- NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
- // Channels
- NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
- NvmCtx.Channels[1] = ( ChannelParams_t ) EU433_LC2;
- NvmCtx.Channels[2] = ( ChannelParams_t ) EU433_LC3;
- break;
- }
- default:
- {
- break;
- }
- }
- }
- void* RegionEU433GetNvmCtx( GetNvmCtxParams_t* params )
- {
- params->nvmCtxSize = sizeof( RegionEU433NvmCtx_t );
- return &NvmCtx;
- }
- bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
- {
- switch( phyAttribute )
- {
- case PHY_FREQUENCY:
- {
- return VerifyRfFreq( verify->Frequency );
- }
- case PHY_TX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE );
- }
- case PHY_DEF_TX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
- }
- case PHY_RX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_RX_MIN_DATARATE, EU433_RX_MAX_DATARATE );
- }
- case PHY_DEF_TX_POWER:
- case PHY_TX_POWER:
- {
- // Remark: switched min and max!
- return RegionCommonValueInRange( verify->TxPower, EU433_MAX_TX_POWER, EU433_MIN_TX_POWER );
- }
- case PHY_DUTY_CYCLE:
- {
- return EU433_DUTY_CYCLE_ENABLED;
- }
- default:
- return false;
- }
- }
- void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList )
- {
- ChannelParams_t newChannel;
- ChannelAddParams_t channelAdd;
- ChannelRemoveParams_t channelRemove;
- // Setup default datarate range
- newChannel.DrRange.Value = ( DR_5 << 4 ) | DR_0;
- // Size of the optional CF list
- if( applyCFList->Size != 16 )
- {
- return;
- }
- // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
- if( applyCFList->Payload[15] != 0 )
- {
- return;
- }
- // Last byte is RFU, don't take it into account
- for( uint8_t i = 0, chanIdx = EU433_NUMB_DEFAULT_CHANNELS; chanIdx < EU433_MAX_NB_CHANNELS; i+=3, chanIdx++ )
- {
- if( chanIdx < ( EU433_NUMB_CHANNELS_CF_LIST + EU433_NUMB_DEFAULT_CHANNELS ) )
- {
- // Channel frequency
- newChannel.Frequency = (uint32_t) applyCFList->Payload[i];
- newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 1] << 8 );
- newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 2] << 16 );
- newChannel.Frequency *= 100;
- // Initialize alternative frequency to 0
- newChannel.Rx1Frequency = 0;
- }
- else
- {
- newChannel.Frequency = 0;
- newChannel.DrRange.Value = 0;
- newChannel.Rx1Frequency = 0;
- }
- if( newChannel.Frequency != 0 )
- {
- channelAdd.NewChannel = &newChannel;
- channelAdd.ChannelId = chanIdx;
- // Try to add all channels
- RegionEU433ChannelAdd( &channelAdd );
- }
- else
- {
- channelRemove.ChannelId = chanIdx;
- RegionEU433ChannelsRemove( &channelRemove );
- }
- }
- }
- bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
- {
- switch( chanMaskSet->ChannelsMaskType )
- {
- case CHANNELS_MASK:
- {
- RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
- break;
- }
- case CHANNELS_DEFAULT_MASK:
- {
- RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
- break;
- }
- default:
- return false;
- }
- return true;
- }
- void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
- {
- double tSymbol = 0.0;
- // Get the datarate, perform a boundary check
- rxConfigParams->Datarate = MIN( datarate, EU433_RX_MAX_DATARATE );
- rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
- if( rxConfigParams->Datarate == DR_7 )
- { // FSK
- tSymbol = RegionCommonComputeSymbolTimeFsk( DataratesEU433[rxConfigParams->Datarate] );
- }
- else
- { // LoRa
- tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesEU433[rxConfigParams->Datarate], BandwidthsEU433[rxConfigParams->Datarate] );
- }
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
- }
- bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
- {
- RadioModems_t modem;
- int8_t dr = rxConfig->Datarate;
- uint8_t maxPayload = 0;
- int8_t phyDr = 0;
- uint32_t frequency = rxConfig->Frequency;
- if( Radio.GetStatus( ) != RF_IDLE )
- {
- return false;
- }
- if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
- {
- // Apply window 1 frequency
- frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
- // Apply the alternative RX 1 window frequency, if it is available
- if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
- {
- frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
- }
- }
- // Read the physical datarate from the datarates table
- phyDr = DataratesEU433[dr];
- Radio.SetChannel( frequency );
- // Radio configuration
- if( dr == DR_7 )
- {
- modem = MODEM_FSK;
- Radio.SetRxConfig( modem, 50000, phyDr * 1000, 0, 83333, 5, rxConfig->WindowTimeout, false, 0, true, 0, 0, false, rxConfig->RxContinuous );
- }
- else
- {
- modem = MODEM_LORA;
- Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
- }
- if( rxConfig->RepeaterSupport == true )
- {
- maxPayload = MaxPayloadOfDatarateRepeaterEU433[dr];
- }
- else
- {
- maxPayload = MaxPayloadOfDatarateEU433[dr];
- }
- Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
- *datarate = (uint8_t) dr;
- return true;
- }
- static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
- {
- int8_t phyDr = DataratesEU433[datarate];
- uint32_t bandwidth = GetBandwidth( datarate );
- return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
- }
- bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
- {
- RadioModems_t modem;
- int8_t phyDr = DataratesEU433[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
- uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
- int8_t phyTxPower = 0;
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
- // Setup the radio frequency
- Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
- if( txConfig->Datarate == DR_7 )
- { // High Speed FSK channel
- modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
- }
- else
- {
- modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
- }
- // Setup maximum payload lenght of the radio driver
- Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
- // Get the time-on-air of the next tx frame
- *txTimeOnAir = GetTimeOnAir( modem, txConfig->PktLen );
- *txPower = txPowerLimited;
- return true;
- }
- 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( NvmCtx.Channels[i].Frequency != 0 )
- {
- chMask |= 1 << i;
- }
- }
- else
- {
- if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( NvmCtx.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 = NvmCtx.Channels;
- linkAdrVerifyParams.MinTxPower = EU433_MIN_TX_POWER;
- linkAdrVerifyParams.MaxTxPower = EU433_MAX_TX_POWER;
- linkAdrVerifyParams.Version = linkAdrReq->Version;
- // 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
- memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
- // Update the channels mask
- NvmCtx.ChannelsMask[0] = chMask;
- }
- // Update status variables
- *drOut = linkAdrParams.Datarate;
- *txPowOut = linkAdrParams.TxPower;
- *nbRepOut = linkAdrParams.NbRep;
- *nbBytesParsed = bytesProcessed;
- return status;
- }
- uint8_t RegionEU433RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
- {
- uint8_t status = 0x07;
- // Verify radio frequency
- if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
- {
- status &= 0xFE; // Channel frequency KO
- }
- // Verify datarate
- if( RegionCommonValueInRange( rxParamSetupReq->Datarate, EU433_RX_MIN_DATARATE, EU433_RX_MAX_DATARATE ) == false )
- {
- status &= 0xFD; // Datarate KO
- }
- // Verify datarate offset
- if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, EU433_MIN_RX1_DR_OFFSET, EU433_MAX_RX1_DR_OFFSET ) == false )
- {
- status &= 0xFB; // Rx1DrOffset range KO
- }
- return status;
- }
- uint8_t RegionEU433NewChannelReq( NewChannelReqParams_t* newChannelReq )
- {
- uint8_t status = 0x03;
- ChannelAddParams_t channelAdd;
- ChannelRemoveParams_t channelRemove;
- if( newChannelReq->NewChannel->Frequency == 0 )
- {
- channelRemove.ChannelId = newChannelReq->ChannelId;
- // Remove
- if( RegionEU433ChannelsRemove( &channelRemove ) == false )
- {
- status &= 0xFC;
- }
- }
- else
- {
- channelAdd.NewChannel = newChannelReq->NewChannel;
- channelAdd.ChannelId = newChannelReq->ChannelId;
- switch( RegionEU433ChannelAdd( &channelAdd ) )
- {
- 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;
- }
- }
- }
- return status;
- }
- int8_t RegionEU433TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
- {
- return -1;
- }
- uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq )
- {
- uint8_t status = 0x03;
- // Verify if the frequency is supported
- if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
- {
- status &= 0xFE;
- }
- // Verify if an uplink frequency exists
- if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
- {
- status &= 0xFD;
- }
- // Apply Rx1 frequency, if the status is OK
- if( status == 0x03 )
- {
- NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
- }
- return status;
- }
- int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type )
- {
- return currentDr;
- }
- void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff )
- {
- RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = NvmCtx.Channels;
- calcBackOffParams.Bands = NvmCtx.Bands;
- calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
- calcBackOffParams.Joined = calcBackOff->Joined;
- calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
- calcBackOffParams.Channel = calcBackOff->Channel;
- calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
- calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
- RegionCommonCalcBackOff( &calcBackOffParams );
- }
- LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
- {
- uint8_t nbEnabledChannels = 0;
- uint8_t delayTx = 0;
- uint8_t enabledChannels[EU433_MAX_NB_CHANNELS] = { 0 };
- TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
- { // Reactivate default channels
- NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
- if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
- {
- // Reset Aggregated time off
- *aggregatedTimeOff = 0;
- // Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU433_MAX_NB_BANDS );
- // Search how many channels are enabled
- nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- NvmCtx.ChannelsMask, NvmCtx.Channels,
- NvmCtx.Bands, enabledChannels, &delayTx );
- }
- else
- {
- delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
- }
- if( nbEnabledChannels > 0 )
- {
- // We found a valid channel
- *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
- *time = 0;
- return LORAMAC_STATUS_OK;
- }
- else
- {
- if( delayTx > 0 )
- {
- // Delay transmission due to AggregatedTimeOff or to a band time off
- *time = nextTxDelay;
- return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
- }
- // Datarate not supported by any channel, restore defaults
- NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- *time = 0;
- return LORAMAC_STATUS_NO_CHANNEL_FOUND;
- }
- }
- LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
- {
- bool drInvalid = false;
- bool freqInvalid = false;
- uint8_t id = channelAdd->ChannelId;
- if( id < EU433_NUMB_DEFAULT_CHANNELS )
- {
- return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
- }
- if( id >= EU433_MAX_NB_CHANNELS )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- // Validate the datarate range
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
- {
- drInvalid = true;
- }
- // Check frequency
- if( freqInvalid == false )
- {
- if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
- {
- freqInvalid = true;
- }
- }
- // Check status
- if( ( drInvalid == true ) && ( freqInvalid == true ) )
- {
- return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
- }
- if( drInvalid == true )
- {
- return LORAMAC_STATUS_DATARATE_INVALID;
- }
- if( freqInvalid == true )
- {
- return LORAMAC_STATUS_FREQUENCY_INVALID;
- }
- memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
- NvmCtx.Channels[id].Band = 0;
- NvmCtx.ChannelsMask[0] |= ( 1 << id );
- return LORAMAC_STATUS_OK;
- }
- bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove )
- {
- uint8_t id = channelRemove->ChannelId;
- if( id < EU433_NUMB_DEFAULT_CHANNELS )
- {
- return false;
- }
- // Remove the channel from the list of channels
- NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
- return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, EU433_MAX_NB_CHANNELS );
- }
- void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave )
- {
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
- }
- uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
- {
- int8_t datarate = dr - drOffset;
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
- }
- void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
- {
- RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
- regionCommonRxBeaconSetup.Datarates = DataratesEU433;
- regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
- regionCommonRxBeaconSetup.BeaconSize = EU433_BEACON_SIZE;
- regionCommonRxBeaconSetup.BeaconDatarate = EU433_BEACON_CHANNEL_DR;
- regionCommonRxBeaconSetup.BeaconChannelBW = EU433_BEACON_CHANNEL_BW;
- regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
- regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
- RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
- // Store downlink datarate
- *outDr = EU433_BEACON_CHANNEL_DR;
- }
|