1 /*!
2  * \file      RegionEU433.c
3  *
4  * \brief     Region implementation for EU433
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
18  *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19  *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
20  *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21  *              embedded.connectivity.solutions===============
22  *
23  * \endcode
24  *
25  * \author    Miguel Luis ( Semtech )
26  *
27  * \author    Gregory Cristian ( Semtech )
28  *
29  * \author    Daniel Jaeckle ( STACKFORCE )
30 */
31 #include "radio.h"
32 #include "RegionCommon.h"
33 #include "RegionEU433.h"
34 
35 // Definitions
36 #define CHANNELS_MASK_SIZE              1
37 
38 /*
39  * Non-volatile module context.
40  */
41 static RegionNvmDataGroup1_t* RegionNvmGroup1;
42 static RegionNvmDataGroup2_t* RegionNvmGroup2;
43 static Band_t* RegionBands;
44 
45 // Static functions
VerifyRfFreq(uint32_t freq)46 static bool VerifyRfFreq( uint32_t freq )
47 {
48     // Check radio driver support
49     if( Radio.CheckRfFrequency( freq ) == false )
50     {
51         return false;
52     }
53 
54     if( ( freq < 433175000 ) || ( freq > 434665000 ) )
55     {
56         return false;
57     }
58     return true;
59 }
60 
GetTimeOnAir(int8_t datarate,uint16_t pktLen)61 static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
62 {
63     int8_t phyDr = DataratesEU433[datarate];
64     uint32_t bandwidth = RegionCommonGetBandwidth( datarate, BandwidthsEU433 );
65     TimerTime_t timeOnAir = 0;
66 
67     if( datarate == DR_7 )
68     { // High Speed FSK channel
69         timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
70     }
71     else
72     {
73         timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
74     }
75     return timeOnAir;
76 }
77 
RegionEU433GetPhyParam(GetPhyParams_t * getPhy)78 PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
79 {
80     PhyParam_t phyParam = { 0 };
81 
82     switch( getPhy->Attribute )
83     {
84         case PHY_MIN_RX_DR:
85         {
86             phyParam.Value = EU433_RX_MIN_DATARATE;
87             break;
88         }
89         case PHY_MIN_TX_DR:
90         {
91             phyParam.Value = EU433_TX_MIN_DATARATE;
92             break;
93         }
94         case PHY_DEF_TX_DR:
95         {
96             phyParam.Value = EU433_DEFAULT_DATARATE;
97             break;
98         }
99         case PHY_NEXT_LOWER_TX_DR:
100         {
101             RegionCommonGetNextLowerTxDrParams_t nextLowerTxDrParams =
102             {
103                 .CurrentDr = getPhy->Datarate,
104                 .MaxDr = ( int8_t )EU433_TX_MAX_DATARATE,
105                 .MinDr = ( int8_t )EU433_TX_MIN_DATARATE,
106                 .NbChannels = EU433_MAX_NB_CHANNELS,
107                 .ChannelsMask = RegionNvmGroup2->ChannelsMask,
108                 .Channels = RegionNvmGroup2->Channels,
109             };
110             phyParam.Value = RegionCommonGetNextLowerTxDr( &nextLowerTxDrParams );
111             break;
112         }
113         case PHY_MAX_TX_POWER:
114         {
115             phyParam.Value = EU433_MAX_TX_POWER;
116             break;
117         }
118         case PHY_DEF_TX_POWER:
119         {
120             phyParam.Value = EU433_DEFAULT_TX_POWER;
121             break;
122         }
123         case PHY_DEF_ADR_ACK_LIMIT:
124         {
125             phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_LIMIT;
126             break;
127         }
128         case PHY_DEF_ADR_ACK_DELAY:
129         {
130             phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_DELAY;
131             break;
132         }
133         case PHY_MAX_PAYLOAD:
134         {
135             phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate];
136             break;
137         }
138         case PHY_DUTY_CYCLE:
139         {
140             phyParam.Value = EU433_DUTY_CYCLE_ENABLED;
141             break;
142         }
143         case PHY_MAX_RX_WINDOW:
144         {
145             phyParam.Value = EU433_MAX_RX_WINDOW;
146             break;
147         }
148         case PHY_RECEIVE_DELAY1:
149         {
150             phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY1;
151             break;
152         }
153         case PHY_RECEIVE_DELAY2:
154         {
155             phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY2;
156             break;
157         }
158         case PHY_JOIN_ACCEPT_DELAY1:
159         {
160             phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1;
161             break;
162         }
163         case PHY_JOIN_ACCEPT_DELAY2:
164         {
165             phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY2;
166             break;
167         }
168         case PHY_RETRANSMIT_TIMEOUT:
169         {
170             phyParam.Value = ( REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT + randr( -REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND, REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND ) );
171             break;
172         }
173         case PHY_DEF_DR1_OFFSET:
174         {
175             phyParam.Value = REGION_COMMON_DEFAULT_RX1_DR_OFFSET;
176             break;
177         }
178         case PHY_DEF_RX2_FREQUENCY:
179         {
180             phyParam.Value = EU433_RX_WND_2_FREQ;
181             break;
182         }
183         case PHY_DEF_RX2_DR:
184         {
185             phyParam.Value = EU433_RX_WND_2_DR;
186             break;
187         }
188         case PHY_CHANNELS_MASK:
189         {
190             phyParam.ChannelsMask = RegionNvmGroup2->ChannelsMask;
191             break;
192         }
193         case PHY_CHANNELS_DEFAULT_MASK:
194         {
195             phyParam.ChannelsMask = RegionNvmGroup2->ChannelsDefaultMask;
196             break;
197         }
198         case PHY_MAX_NB_CHANNELS:
199         {
200             phyParam.Value = EU433_MAX_NB_CHANNELS;
201             break;
202         }
203         case PHY_CHANNELS:
204         {
205             phyParam.Channels = RegionNvmGroup2->Channels;
206             break;
207         }
208         case PHY_DEF_UPLINK_DWELL_TIME:
209         {
210             phyParam.Value = EU433_DEFAULT_UPLINK_DWELL_TIME;
211             break;
212         }
213         case PHY_DEF_DOWNLINK_DWELL_TIME:
214         {
215             phyParam.Value = REGION_COMMON_DEFAULT_DOWNLINK_DWELL_TIME;
216             break;
217         }
218         case PHY_DEF_MAX_EIRP:
219         {
220             phyParam.fValue = EU433_DEFAULT_MAX_EIRP;
221             break;
222         }
223         case PHY_DEF_ANTENNA_GAIN:
224         {
225             phyParam.fValue = EU433_DEFAULT_ANTENNA_GAIN;
226             break;
227         }
228         case PHY_BEACON_CHANNEL_FREQ:
229         {
230             phyParam.Value = EU433_BEACON_CHANNEL_FREQ;
231             break;
232         }
233         case PHY_BEACON_FORMAT:
234         {
235             phyParam.BeaconFormat.BeaconSize = EU433_BEACON_SIZE;
236             phyParam.BeaconFormat.Rfu1Size = EU433_RFU1_SIZE;
237             phyParam.BeaconFormat.Rfu2Size = EU433_RFU2_SIZE;
238             break;
239         }
240         case PHY_BEACON_CHANNEL_DR:
241         {
242             phyParam.Value = EU433_BEACON_CHANNEL_DR;
243             break;
244         }
245         case PHY_PING_SLOT_CHANNEL_FREQ:
246         {
247             phyParam.Value = EU433_PING_SLOT_CHANNEL_FREQ;
248             break;
249         }
250         case PHY_PING_SLOT_CHANNEL_DR:
251         {
252             phyParam.Value = EU433_PING_SLOT_CHANNEL_DR;
253             break;
254         }
255         case PHY_SF_FROM_DR:
256         {
257             phyParam.Value = DataratesEU433[getPhy->Datarate];
258             break;
259         }
260         case PHY_BW_FROM_DR:
261         {
262             phyParam.Value = RegionCommonGetBandwidth( getPhy->Datarate, BandwidthsEU433 );
263             break;
264         }
265         default:
266         {
267             break;
268         }
269     }
270 
271     return phyParam;
272 }
273 
RegionEU433SetBandTxDone(SetBandTxDoneParams_t * txDone)274 void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone )
275 {
276     RegionCommonSetBandTxDone( &RegionBands[RegionNvmGroup2->Channels[txDone->Channel].Band],
277                                txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
278 }
279 
RegionEU433InitDefaults(InitDefaultsParams_t * params)280 void RegionEU433InitDefaults( InitDefaultsParams_t* params )
281 {
282     Band_t bands[EU433_MAX_NB_BANDS] =
283     {
284         EU433_BAND0
285     };
286 
287     switch( params->Type )
288     {
289         case INIT_TYPE_DEFAULTS:
290         {
291             if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) )
292             {
293                 return;
294             }
295 
296             RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1;
297             RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2;
298             RegionBands = (Band_t*) params->Bands;
299 
300             // Default bands
301             memcpy1( ( uint8_t* )RegionBands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS );
302 
303             // Default channels
304             RegionNvmGroup2->Channels[0] = ( ChannelParams_t ) EU433_LC1;
305             RegionNvmGroup2->Channels[1] = ( ChannelParams_t ) EU433_LC2;
306             RegionNvmGroup2->Channels[2] = ( ChannelParams_t ) EU433_LC3;
307 
308             // Default ChannelsMask
309             RegionNvmGroup2->ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
310 
311             // Update the channels mask
312             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
313             break;
314         }
315         case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS:
316         {
317             // Reset Channels Rx1Frequency to default 0
318             RegionNvmGroup2->Channels[0].Rx1Frequency = 0;
319             RegionNvmGroup2->Channels[1].Rx1Frequency = 0;
320             RegionNvmGroup2->Channels[2].Rx1Frequency = 0;
321             // Update the channels mask
322             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
323             break;
324         }
325         case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS:
326         {
327             // Restore channels default mask
328             RegionNvmGroup2->ChannelsMask[0] |= RegionNvmGroup2->ChannelsDefaultMask[0];
329             break;
330         }
331         default:
332         {
333             break;
334         }
335     }
336 }
337 
RegionEU433Verify(VerifyParams_t * verify,PhyAttribute_t phyAttribute)338 bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
339 {
340     switch( phyAttribute )
341     {
342         case PHY_FREQUENCY:
343         {
344             return VerifyRfFreq( verify->Frequency );
345         }
346         case PHY_TX_DR:
347         {
348             return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE );
349         }
350         case PHY_DEF_TX_DR:
351         {
352             return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
353         }
354         case PHY_RX_DR:
355         {
356             return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_RX_MIN_DATARATE, EU433_RX_MAX_DATARATE );
357         }
358         case PHY_DEF_TX_POWER:
359         case PHY_TX_POWER:
360         {
361             // Remark: switched min and max!
362             return RegionCommonValueInRange( verify->TxPower, EU433_MAX_TX_POWER, EU433_MIN_TX_POWER );
363         }
364         case PHY_DUTY_CYCLE:
365         {
366             return EU433_DUTY_CYCLE_ENABLED;
367         }
368         default:
369             return false;
370     }
371 }
372 
RegionEU433ApplyCFList(ApplyCFListParams_t * applyCFList)373 void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList )
374 {
375     ChannelParams_t newChannel;
376     ChannelAddParams_t channelAdd;
377     ChannelRemoveParams_t channelRemove;
378 
379     // Setup default datarate range
380     newChannel.DrRange.Value = ( DR_5 << 4 ) | DR_0;
381 
382     // Size of the optional CF list
383     if( applyCFList->Size != 16 )
384     {
385         return;
386     }
387 
388     // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
389     if( applyCFList->Payload[15] != 0 )
390     {
391         return;
392     }
393 
394     // Last byte is RFU, don't take it into account
395     for( uint8_t i = 0, chanIdx = EU433_NUMB_DEFAULT_CHANNELS; chanIdx < EU433_MAX_NB_CHANNELS; i+=3, chanIdx++ )
396     {
397         if( chanIdx < ( EU433_NUMB_CHANNELS_CF_LIST + EU433_NUMB_DEFAULT_CHANNELS ) )
398         {
399             // Channel frequency
400             newChannel.Frequency = (uint32_t) applyCFList->Payload[i];
401             newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 1] << 8 );
402             newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 2] << 16 );
403             newChannel.Frequency *= 100;
404 
405             // Initialize alternative frequency to 0
406             newChannel.Rx1Frequency = 0;
407         }
408         else
409         {
410             newChannel.Frequency = 0;
411             newChannel.DrRange.Value = 0;
412             newChannel.Rx1Frequency = 0;
413         }
414 
415         if( newChannel.Frequency != 0 )
416         {
417             channelAdd.NewChannel = &newChannel;
418             channelAdd.ChannelId = chanIdx;
419 
420             // Try to add all channels
421             RegionEU433ChannelAdd( &channelAdd );
422         }
423         else
424         {
425             channelRemove.ChannelId = chanIdx;
426 
427             RegionEU433ChannelsRemove( &channelRemove );
428         }
429     }
430 }
431 
RegionEU433ChanMaskSet(ChanMaskSetParams_t * chanMaskSet)432 bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
433 {
434     switch( chanMaskSet->ChannelsMaskType )
435     {
436         case CHANNELS_MASK:
437         {
438             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
439             break;
440         }
441         case CHANNELS_DEFAULT_MASK:
442         {
443             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
444             break;
445         }
446         default:
447             return false;
448     }
449     return true;
450 }
451 
RegionEU433ComputeRxWindowParameters(int8_t datarate,uint8_t minRxSymbols,uint32_t rxError,RxConfigParams_t * rxConfigParams)452 void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
453 {
454     uint32_t tSymbolInUs = 0;
455 
456     // Get the datarate, perform a boundary check
457     rxConfigParams->Datarate = MIN( datarate, EU433_RX_MAX_DATARATE );
458     rxConfigParams->Bandwidth = RegionCommonGetBandwidth( rxConfigParams->Datarate, BandwidthsEU433 );
459 
460     if( rxConfigParams->Datarate == DR_7 )
461     { // FSK
462         tSymbolInUs = RegionCommonComputeSymbolTimeFsk( DataratesEU433[rxConfigParams->Datarate] );
463     }
464     else
465     { // LoRa
466         tSymbolInUs = RegionCommonComputeSymbolTimeLoRa( DataratesEU433[rxConfigParams->Datarate], BandwidthsEU433[rxConfigParams->Datarate] );
467     }
468 
469     RegionCommonComputeRxWindowParameters( tSymbolInUs, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
470 }
471 
RegionEU433RxConfig(RxConfigParams_t * rxConfig,int8_t * datarate)472 bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
473 {
474     RadioModems_t modem;
475     int8_t dr = rxConfig->Datarate;
476     int8_t phyDr = 0;
477     uint32_t frequency = rxConfig->Frequency;
478 
479     if( Radio.GetStatus( ) != RF_IDLE )
480     {
481         return false;
482     }
483 
484     if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
485     {
486         // Apply window 1 frequency
487         frequency = RegionNvmGroup2->Channels[rxConfig->Channel].Frequency;
488         // Apply the alternative RX 1 window frequency, if it is available
489         if( RegionNvmGroup2->Channels[rxConfig->Channel].Rx1Frequency != 0 )
490         {
491             frequency = RegionNvmGroup2->Channels[rxConfig->Channel].Rx1Frequency;
492         }
493     }
494 
495     // Read the physical datarate from the datarates table
496     phyDr = DataratesEU433[dr];
497 
498     Radio.SetChannel( frequency );
499 
500     // Radio configuration
501     if( dr == DR_7 )
502     {
503         modem = MODEM_FSK;
504         Radio.SetRxConfig( modem, 50000, phyDr * 1000, 0, 83333, 5, rxConfig->WindowTimeout, false, 0, true, 0, 0, false, rxConfig->RxContinuous );
505     }
506     else
507     {
508         modem = MODEM_LORA;
509         Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
510     }
511 
512     Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateEU433[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
513 
514     *datarate = (uint8_t) dr;
515     return true;
516 }
517 
RegionEU433TxConfig(TxConfigParams_t * txConfig,int8_t * txPower,TimerTime_t * txTimeOnAir)518 bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
519 {
520     RadioModems_t modem;
521     int8_t phyDr = DataratesEU433[txConfig->Datarate];
522     int8_t txPowerLimited = RegionCommonLimitTxPower( txConfig->TxPower, RegionBands[RegionNvmGroup2->Channels[txConfig->Channel].Band].TxMaxPower );
523     uint32_t bandwidth = RegionCommonGetBandwidth( txConfig->Datarate, BandwidthsEU433 );
524     int8_t phyTxPower = 0;
525 
526     // Calculate physical TX power
527     phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
528 
529     // Setup the radio frequency
530     Radio.SetChannel( RegionNvmGroup2->Channels[txConfig->Channel].Frequency );
531 
532     if( txConfig->Datarate == DR_7 )
533     { // High Speed FSK channel
534         modem = MODEM_FSK;
535         Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
536     }
537     else
538     {
539         modem = MODEM_LORA;
540         Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
541     }
542 
543     // Update time-on-air
544     *txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
545 
546     // Setup maximum payload lenght of the radio driver
547     Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
548 
549     *txPower = txPowerLimited;
550     return true;
551 }
552 
RegionEU433LinkAdrReq(LinkAdrReqParams_t * linkAdrReq,int8_t * drOut,int8_t * txPowOut,uint8_t * nbRepOut,uint8_t * nbBytesParsed)553 uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
554 {
555     uint8_t status = 0x07;
556     RegionCommonLinkAdrParams_t linkAdrParams = { 0 };
557     uint8_t nextIndex = 0;
558     uint8_t bytesProcessed = 0;
559     uint16_t chMask = 0;
560     GetPhyParams_t getPhy;
561     PhyParam_t phyParam;
562     RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
563 
564     while( bytesProcessed < linkAdrReq->PayloadSize )
565     {
566         // Get ADR request parameters
567         nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
568 
569         if( nextIndex == 0 )
570             break; // break loop, since no more request has been found
571 
572         // Update bytes processed
573         bytesProcessed += nextIndex;
574 
575         // Revert status, as we only check the last ADR request for the channel mask KO
576         status = 0x07;
577 
578         // Setup temporary channels mask
579         chMask = linkAdrParams.ChMask;
580 
581         // Verify channels mask
582         if( ( linkAdrParams.ChMaskCtrl == 0 ) && ( chMask == 0 ) )
583         {
584             status &= 0xFE; // Channel mask KO
585         }
586         else if( ( ( linkAdrParams.ChMaskCtrl >= 1 ) && ( linkAdrParams.ChMaskCtrl <= 5 )) ||
587                 ( linkAdrParams.ChMaskCtrl >= 7 ) )
588         {
589             // RFU
590             status &= 0xFE; // Channel mask KO
591         }
592         else
593         {
594             for( uint8_t i = 0; i < EU433_MAX_NB_CHANNELS; i++ )
595             {
596                 if( linkAdrParams.ChMaskCtrl == 6 )
597                 {
598                     if( RegionNvmGroup2->Channels[i].Frequency != 0 )
599                     {
600                         chMask |= 1 << i;
601                     }
602                 }
603                 else
604                 {
605                     if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
606                         ( RegionNvmGroup2->Channels[i].Frequency == 0 ) )
607                     {// Trying to enable an undefined channel
608                         status &= 0xFE; // Channel mask KO
609                     }
610                 }
611             }
612         }
613     }
614 
615         // Get the minimum possible datarate
616     getPhy.Attribute = PHY_MIN_TX_DR;
617     getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
618     phyParam = RegionEU433GetPhyParam( &getPhy );
619 
620     linkAdrVerifyParams.Status = status;
621     linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
622     linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
623     linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
624     linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
625     linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
626     linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
627     linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
628     linkAdrVerifyParams.NbChannels = EU433_MAX_NB_CHANNELS;
629     linkAdrVerifyParams.ChannelsMask = &chMask;
630     linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
631     linkAdrVerifyParams.MaxDatarate = EU433_TX_MAX_DATARATE;
632     linkAdrVerifyParams.Channels = RegionNvmGroup2->Channels;
633     linkAdrVerifyParams.MinTxPower = EU433_MIN_TX_POWER;
634     linkAdrVerifyParams.MaxTxPower = EU433_MAX_TX_POWER;
635     linkAdrVerifyParams.Version = linkAdrReq->Version;
636 
637     // Verify the parameters and update, if necessary
638     status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
639 
640     // Update channelsMask if everything is correct
641     if( status == 0x07 )
642     {
643         // Set the channels mask to a default value
644         memset1( ( uint8_t* ) RegionNvmGroup2->ChannelsMask, 0, sizeof( RegionNvmGroup2->ChannelsMask ) );
645         // Update the channels mask
646         RegionNvmGroup2->ChannelsMask[0] = chMask;
647     }
648 
649     // Update status variables
650     *drOut = linkAdrParams.Datarate;
651     *txPowOut = linkAdrParams.TxPower;
652     *nbRepOut = linkAdrParams.NbRep;
653     *nbBytesParsed = bytesProcessed;
654 
655     return status;
656 }
657 
RegionEU433RxParamSetupReq(RxParamSetupReqParams_t * rxParamSetupReq)658 uint8_t RegionEU433RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
659 {
660     uint8_t status = 0x07;
661 
662     // Verify radio frequency
663     if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
664     {
665         status &= 0xFE; // Channel frequency KO
666     }
667 
668     // Verify datarate
669     if( RegionCommonValueInRange( rxParamSetupReq->Datarate, EU433_RX_MIN_DATARATE, EU433_RX_MAX_DATARATE ) == false )
670     {
671         status &= 0xFD; // Datarate KO
672     }
673 
674     // Verify datarate offset
675     if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, EU433_MIN_RX1_DR_OFFSET, EU433_MAX_RX1_DR_OFFSET ) == false )
676     {
677         status &= 0xFB; // Rx1DrOffset range KO
678     }
679 
680     return status;
681 }
682 
RegionEU433NewChannelReq(NewChannelReqParams_t * newChannelReq)683 int8_t RegionEU433NewChannelReq( NewChannelReqParams_t* newChannelReq )
684 {
685     uint8_t status = 0x03;
686     ChannelAddParams_t channelAdd;
687     ChannelRemoveParams_t channelRemove;
688 
689     if( newChannelReq->NewChannel->Frequency == 0 )
690     {
691         channelRemove.ChannelId = newChannelReq->ChannelId;
692 
693         // Remove
694         if( RegionEU433ChannelsRemove( &channelRemove ) == false )
695         {
696             status &= 0xFC;
697         }
698     }
699     else
700     {
701         channelAdd.NewChannel = newChannelReq->NewChannel;
702         channelAdd.ChannelId = newChannelReq->ChannelId;
703 
704         switch( RegionEU433ChannelAdd( &channelAdd ) )
705         {
706             case LORAMAC_STATUS_OK:
707             {
708                 break;
709             }
710             case LORAMAC_STATUS_FREQUENCY_INVALID:
711             {
712                 status &= 0xFE;
713                 break;
714             }
715             case LORAMAC_STATUS_DATARATE_INVALID:
716             {
717                 status &= 0xFD;
718                 break;
719             }
720             case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
721             {
722                 status &= 0xFC;
723                 break;
724             }
725             default:
726             {
727                 status &= 0xFC;
728                 break;
729             }
730         }
731     }
732 
733     return status;
734 }
735 
RegionEU433TxParamSetupReq(TxParamSetupReqParams_t * txParamSetupReq)736 int8_t RegionEU433TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
737 {
738     // Do not accept the request
739     return -1;
740 }
741 
RegionEU433DlChannelReq(DlChannelReqParams_t * dlChannelReq)742 int8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq )
743 {
744     uint8_t status = 0x03;
745 
746     if( dlChannelReq->ChannelId >= ( CHANNELS_MASK_SIZE * 16 ) )
747     {
748         return 0;
749     }
750 
751     // Verify if the frequency is supported
752     if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
753     {
754         status &= 0xFE;
755     }
756 
757     // Verify if an uplink frequency exists
758     if( RegionNvmGroup2->Channels[dlChannelReq->ChannelId].Frequency == 0 )
759     {
760         status &= 0xFD;
761     }
762 
763     // Apply Rx1 frequency, if the status is OK
764     if( status == 0x03 )
765     {
766         RegionNvmGroup2->Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
767     }
768 
769     return status;
770 }
771 
RegionEU433AlternateDr(int8_t currentDr,AlternateDrType_t type)772 int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type )
773 {
774     return currentDr;
775 }
776 
RegionEU433NextChannel(NextChanParams_t * nextChanParams,uint8_t * channel,TimerTime_t * time,TimerTime_t * aggregatedTimeOff)777 LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
778 {
779     uint8_t nbEnabledChannels = 0;
780     uint8_t nbRestrictedChannels = 0;
781     uint8_t enabledChannels[EU433_MAX_NB_CHANNELS] = { 0 };
782     RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
783     RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
784     LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
785     uint16_t joinChannels = EU433_JOIN_CHANNELS;
786 
787     if( RegionCommonCountChannels( RegionNvmGroup2->ChannelsMask, 0, 1 ) == 0 )
788     { // Reactivate default channels
789         RegionNvmGroup2->ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
790     }
791 
792     // Search how many channels are enabled
793     countChannelsParams.Joined = nextChanParams->Joined;
794     countChannelsParams.Datarate = nextChanParams->Datarate;
795     countChannelsParams.ChannelsMask = RegionNvmGroup2->ChannelsMask;
796     countChannelsParams.Channels = RegionNvmGroup2->Channels;
797     countChannelsParams.Bands = RegionBands;
798     countChannelsParams.MaxNbChannels = EU433_MAX_NB_CHANNELS;
799     countChannelsParams.JoinChannels = &joinChannels;
800 
801     identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
802     identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
803     identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
804     identifyChannelsParam.MaxBands = EU433_MAX_NB_BANDS;
805 
806     identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
807     identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
808     identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
809 
810     identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
811 
812     status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
813                                            &nbEnabledChannels, &nbRestrictedChannels, time );
814 
815     if( status == LORAMAC_STATUS_OK )
816     {
817         // We found a valid channel
818         *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
819     }
820     else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
821     {
822         // Datarate not supported by any channel, restore defaults
823         RegionNvmGroup2->ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
824     }
825     return status;
826 }
827 
RegionEU433ChannelAdd(ChannelAddParams_t * channelAdd)828 LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
829 {
830     bool drInvalid = false;
831     bool freqInvalid = false;
832     uint8_t id = channelAdd->ChannelId;
833 
834     if( id < EU433_NUMB_DEFAULT_CHANNELS )
835     {
836         return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
837     }
838 
839     if( id >= EU433_MAX_NB_CHANNELS )
840     {
841         return LORAMAC_STATUS_PARAMETER_INVALID;
842     }
843 
844     // Validate the datarate range
845     if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE ) == false )
846     {
847         drInvalid = true;
848     }
849     if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE ) == false )
850     {
851         drInvalid = true;
852     }
853     if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
854     {
855         drInvalid = true;
856     }
857 
858     // Check frequency
859     if( freqInvalid == false )
860     {
861         if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
862         {
863             freqInvalid = true;
864         }
865     }
866 
867     // Check status
868     if( ( drInvalid == true ) && ( freqInvalid == true ) )
869     {
870         return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
871     }
872     if( drInvalid == true )
873     {
874         return LORAMAC_STATUS_DATARATE_INVALID;
875     }
876     if( freqInvalid == true )
877     {
878         return LORAMAC_STATUS_FREQUENCY_INVALID;
879     }
880 
881     memcpy1( ( uint8_t* ) &(RegionNvmGroup2->Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( RegionNvmGroup2->Channels[id] ) );
882     RegionNvmGroup2->Channels[id].Band = 0;
883     RegionNvmGroup2->ChannelsMask[0] |= ( 1 << id );
884     return LORAMAC_STATUS_OK;
885 }
886 
RegionEU433ChannelsRemove(ChannelRemoveParams_t * channelRemove)887 bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove  )
888 {
889     uint8_t id = channelRemove->ChannelId;
890 
891     if( id < EU433_NUMB_DEFAULT_CHANNELS )
892     {
893         return false;
894     }
895 
896     // Remove the channel from the list of channels
897     RegionNvmGroup2->Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
898 
899     return RegionCommonChanDisable( RegionNvmGroup2->ChannelsMask, id, EU433_MAX_NB_CHANNELS );
900 }
901 
RegionEU433ApplyDrOffset(uint8_t downlinkDwellTime,int8_t dr,int8_t drOffset)902 uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
903 {
904     int8_t datarate = dr - drOffset;
905 
906     if( datarate < 0 )
907     {
908         datarate = DR_0;
909     }
910     return datarate;
911 }
912 
RegionEU433RxBeaconSetup(RxBeaconSetup_t * rxBeaconSetup,uint8_t * outDr)913 void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
914 {
915     RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
916 
917     regionCommonRxBeaconSetup.Datarates = DataratesEU433;
918     regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
919     regionCommonRxBeaconSetup.BeaconSize = EU433_BEACON_SIZE;
920     regionCommonRxBeaconSetup.BeaconDatarate = EU433_BEACON_CHANNEL_DR;
921     regionCommonRxBeaconSetup.BeaconChannelBW = EU433_BEACON_CHANNEL_BW;
922    regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
923     regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
924 
925     RegionCommonRxBeaconSetup( &regionCommonRxBeaconSetup );
926 
927     // Store downlink datarate
928     *outDr = EU433_BEACON_CHANNEL_DR;
929 }
930