1 /*!
2  * \file      RegionAS923.c
3  *
4  * \brief     Region implementation for AS923
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 "RegionAS923.h"
34 
35 // Definitions
36 #define CHANNELS_MASK_SIZE                1
37 
38 /*!
39  * RSSI threshold for a free channel [dBm]
40  */
41 #define AS923_RSSI_FREE_TH                          -80
42 
43 /*!
44  * Specifies the time the node performs a carrier sense
45  */
46 #define AS923_CARRIER_SENSE_TIME                    5
47 
48 /*!
49  * Specifies the reception bandwidth to be used while executing the LBT
50  * Max channel bandwidth is 200 kHz
51  */
52 #define AS923_LBT_RX_BANDWIDTH            200000
53 
54 #ifndef REGION_AS923_DEFAULT_CHANNEL_PLAN
55 #define REGION_AS923_DEFAULT_CHANNEL_PLAN CHANNEL_PLAN_GROUP_AS923_1
56 #endif
57 
58 #if( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1 )
59 
60 // Channel plan CHANNEL_PLAN_GROUP_AS923_1
61 
62 #define REGION_AS923_FREQ_OFFSET          0
63 
64 #define AS923_MIN_RF_FREQUENCY            915000000
65 #define AS923_MAX_RF_FREQUENCY            928000000
66 
67 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_2 )
68 
69 // Channel plan CHANNEL_PLAN_GROUP_AS923_2
70 // -1.8MHz
71 #define REGION_AS923_FREQ_OFFSET          ( ( ~( 0xFFFFB9B0 ) + 1 ) * 100 )
72 
73 #define AS923_MIN_RF_FREQUENCY            920000000
74 #define AS923_MAX_RF_FREQUENCY            923000000
75 
76 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_3 )
77 
78 // Channel plan CHANNEL_PLAN_GROUP_AS923_3
79 // -6.6MHz
80 #define REGION_AS923_FREQ_OFFSET          ( ( ~( 0xFFFEFE30 ) + 1 ) * 100 )
81 
82 #define AS923_MIN_RF_FREQUENCY            915000000
83 #define AS923_MAX_RF_FREQUENCY            921000000
84 
85 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_4 )
86 
87 // Channel plan CHANNEL_PLAN_GROUP_AS923_4
88 // -5.90MHz
89 #define REGION_AS923_FREQ_OFFSET          ( ( ~( 0xFFFF1988 ) + 1 ) * 100 )
90 
91 #define AS923_MIN_RF_FREQUENCY            917000000
92 #define AS923_MAX_RF_FREQUENCY            920000000
93 
94 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_LBT )
95 
96 // Channel plan CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_LBT
97 
98 #define REGION_AS923_FREQ_OFFSET          0
99 
100 /*!
101  * Restrict AS923 frequencies to channels 24 to 38
102  * Center frequencies 920.6 MHz to 923.4 MHz @ 200 kHz max bandwidth
103  */
104 #define AS923_MIN_RF_FREQUENCY            920600000
105 #define AS923_MAX_RF_FREQUENCY            923400000
106 
107 #undef AS923_TX_MAX_DATARATE
108 #define AS923_TX_MAX_DATARATE             DR_5
109 
110 #undef AS923_RX_MAX_DATARATE
111 #define AS923_RX_MAX_DATARATE             DR_5
112 
113 #undef AS923_DEFAULT_MAX_EIRP
114 #define AS923_DEFAULT_MAX_EIRP            13.0f
115 
116 /*!
117  * STD-T108 Ver1.4 does not require dwell-time enforcement when using LBT on channels 28 to 38
118  */
119 #undef AS923_DEFAULT_UPLINK_DWELL_TIME
120 #define AS923_DEFAULT_UPLINK_DWELL_TIME   0
121 
122 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_DC )
123 
124 /*
125  * STD-T108 Ver1.4 allows the use of channels 24 to 38 without LBT.
126  * However a duty cycle enforcement must be in place
127  */
128 
129 // Channel plan CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_DC
130 
131 #define REGION_AS923_FREQ_OFFSET          0
132 
133 /*!
134  * Restrict AS923 frequencies to channels 24 to 38
135  * Center frequencies 920.6 MHz to 923.4 MHz @ 200 kHz max bandwidth
136  */
137 #define AS923_MIN_RF_FREQUENCY            920600000
138 #define AS923_MAX_RF_FREQUENCY            923400000
139 
140 #undef AS923_TX_MAX_DATARATE
141 #define AS923_TX_MAX_DATARATE             DR_5
142 
143 #undef AS923_RX_MAX_DATARATE
144 #define AS923_RX_MAX_DATARATE             DR_5
145 
146 #undef AS923_DEFAULT_MAX_EIRP
147 #define AS923_DEFAULT_MAX_EIRP            13.0f
148 
149 /*!
150  * STD-T108 Ver1.4 does not require dwell-time enforcement when using DC on channels 28 to 38
151  */
152 #undef AS923_DEFAULT_UPLINK_DWELL_TIME
153 #define AS923_DEFAULT_UPLINK_DWELL_TIME   0
154 
155 /*!
156  * Enable duty cycle enforcement
157  */
158 #undef AS923_DUTY_CYCLE_ENABLED
159 #define AS923_DUTY_CYCLE_ENABLED          1
160 
161 #elif ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH37_CH61_LBT_DC )
162 
163 /*
164  * STD-T108 Ver1.4 allows the use of channels 37 to 61 with LBT and DC.
165  * However dwell time enforcement must be enabled
166  */
167 
168 // Channel plan CHANNEL_PLAN_GROUP_AS923_1_JP_CH37_CH61_LBT_DC
169 
170 #define REGION_AS923_FREQ_OFFSET          0
171 
172 /*!
173  * Restrict AS923 frequencies to channels 37 to 61
174  * Center frequencies 922.4 MHz to 928.0 MHz @ 200 kHz max bandwidth
175  */
176 #define AS923_MIN_RF_FREQUENCY            922400000
177 #define AS923_MAX_RF_FREQUENCY            928000000
178 
179 #undef AS923_TX_MAX_DATARATE
180 #define AS923_TX_MAX_DATARATE             DR_5
181 
182 #undef AS923_RX_MAX_DATARATE
183 #define AS923_RX_MAX_DATARATE             DR_5
184 
185 #undef AS923_DEFAULT_MAX_EIRP
186 #define AS923_DEFAULT_MAX_EIRP            13.0f
187 
188 /*!
189  * Enable duty cycle enforcement
190  */
191 #undef AS923_DUTY_CYCLE_ENABLED
192 #define AS923_DUTY_CYCLE_ENABLED          1
193 
194 /*!
195  * STD-T108 Ver1.4 requires a carrier sense time of at least 128 us on channels 37 to 61
196  */
197 #undef AS923_CARRIER_SENSE_TIME
198 #define AS923_CARRIER_SENSE_TIME          1
199 
200 #else
201 #error	"Wrong default channel plan selected. Please review compiler options."
202 #endif
203 
204 /*
205  * Non-volatile module context.
206  */
207 static RegionNvmDataGroup1_t* RegionNvmGroup1;
208 static RegionNvmDataGroup2_t* RegionNvmGroup2;
209 static Band_t* RegionBands;
210 
211 // Static functions
VerifyRfFreq(uint32_t freq)212 static bool VerifyRfFreq( uint32_t freq )
213 {
214     // Check radio driver support
215     if( Radio.CheckRfFrequency( freq ) == false )
216     {
217         return false;
218     }
219 
220     if( ( freq < AS923_MIN_RF_FREQUENCY ) || ( freq > AS923_MAX_RF_FREQUENCY ) )
221     {
222         return false;
223     }
224     return true;
225 }
226 
GetTimeOnAir(int8_t datarate,uint16_t pktLen)227 static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
228 {
229     int8_t phyDr = DataratesAS923[datarate];
230     uint32_t bandwidth = RegionCommonGetBandwidth( datarate, BandwidthsAS923 );
231     TimerTime_t timeOnAir = 0;
232 
233     if( datarate == DR_7 )
234     { // High Speed FSK channel
235         timeOnAir = Radio.TimeOnAir( MODEM_FSK, bandwidth, phyDr * 1000, 0, 5, false, pktLen, true );
236     }
237     else
238     {
239         timeOnAir = Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
240     }
241     return timeOnAir;
242 }
243 
RegionAS923GetPhyParam(GetPhyParams_t * getPhy)244 PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
245 {
246     PhyParam_t phyParam = { 0 };
247 
248     switch( getPhy->Attribute )
249     {
250         case PHY_MIN_RX_DR:
251         {
252             if( getPhy->DownlinkDwellTime == 0 )
253             {
254                 phyParam.Value = AS923_RX_MIN_DATARATE;
255             }
256             else
257             {
258                 phyParam.Value = AS923_DWELL_LIMIT_DATARATE;
259             }
260             break;
261         }
262         case PHY_MIN_TX_DR:
263         {
264             if( getPhy->UplinkDwellTime == 0 )
265             {
266                 phyParam.Value = AS923_TX_MIN_DATARATE;
267             }
268             else
269             {
270                 phyParam.Value = AS923_DWELL_LIMIT_DATARATE;
271             }
272             break;
273         }
274         case PHY_DEF_TX_DR:
275         {
276             phyParam.Value = AS923_DEFAULT_DATARATE;
277             break;
278         }
279         case PHY_NEXT_LOWER_TX_DR:
280         {
281             RegionCommonGetNextLowerTxDrParams_t nextLowerTxDrParams =
282             {
283                 .CurrentDr = getPhy->Datarate,
284                 .MaxDr = ( int8_t )AS923_TX_MAX_DATARATE,
285                 .MinDr = ( int8_t )( ( getPhy->UplinkDwellTime == 0 ) ? AS923_TX_MIN_DATARATE : AS923_DWELL_LIMIT_DATARATE ),
286                 .NbChannels = AS923_MAX_NB_CHANNELS,
287                 .ChannelsMask = RegionNvmGroup2->ChannelsMask,
288                 .Channels = RegionNvmGroup2->Channels,
289             };
290             phyParam.Value = RegionCommonGetNextLowerTxDr( &nextLowerTxDrParams );
291             break;
292         }
293         case PHY_MAX_TX_POWER:
294         {
295             phyParam.Value = AS923_MAX_TX_POWER;
296             break;
297         }
298         case PHY_DEF_TX_POWER:
299         {
300             phyParam.Value = AS923_DEFAULT_TX_POWER;
301             break;
302         }
303         case PHY_DEF_ADR_ACK_LIMIT:
304         {
305             phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_LIMIT;
306             break;
307         }
308         case PHY_DEF_ADR_ACK_DELAY:
309         {
310             phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_DELAY;
311             break;
312         }
313         case PHY_MAX_PAYLOAD:
314         {
315             if( getPhy->UplinkDwellTime == 0 )
316             {
317                 phyParam.Value = MaxPayloadOfDatarateDwell0AS923[getPhy->Datarate];
318             }
319             else
320             {
321                 phyParam.Value = MaxPayloadOfDatarateDwell1AS923[getPhy->Datarate];
322             }
323             break;
324         }
325         case PHY_DUTY_CYCLE:
326         {
327             phyParam.Value = AS923_DUTY_CYCLE_ENABLED;
328             break;
329         }
330         case PHY_MAX_RX_WINDOW:
331         {
332             phyParam.Value = AS923_MAX_RX_WINDOW;
333             break;
334         }
335         case PHY_RECEIVE_DELAY1:
336         {
337             phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY1;
338             break;
339         }
340         case PHY_RECEIVE_DELAY2:
341         {
342             phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY2;
343             break;
344         }
345         case PHY_JOIN_ACCEPT_DELAY1:
346         {
347             phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1;
348             break;
349         }
350         case PHY_JOIN_ACCEPT_DELAY2:
351         {
352             phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY2;
353             break;
354         }
355         case PHY_RETRANSMIT_TIMEOUT:
356         {
357             phyParam.Value = ( REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT + randr( -REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND, REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND ) );
358             break;
359         }
360         case PHY_DEF_DR1_OFFSET:
361         {
362             phyParam.Value = REGION_COMMON_DEFAULT_RX1_DR_OFFSET;
363             break;
364         }
365         case PHY_DEF_RX2_FREQUENCY:
366         {
367             phyParam.Value = AS923_RX_WND_2_FREQ - REGION_AS923_FREQ_OFFSET;
368             break;
369         }
370         case PHY_DEF_RX2_DR:
371         {
372             phyParam.Value = AS923_RX_WND_2_DR;
373             break;
374         }
375         case PHY_CHANNELS_MASK:
376         {
377             phyParam.ChannelsMask = RegionNvmGroup2->ChannelsMask;
378             break;
379         }
380         case PHY_CHANNELS_DEFAULT_MASK:
381         {
382             phyParam.ChannelsMask = RegionNvmGroup2->ChannelsDefaultMask;
383             break;
384         }
385         case PHY_MAX_NB_CHANNELS:
386         {
387             phyParam.Value = AS923_MAX_NB_CHANNELS;
388             break;
389         }
390         case PHY_CHANNELS:
391         {
392             phyParam.Channels = RegionNvmGroup2->Channels;
393             break;
394         }
395         case PHY_DEF_UPLINK_DWELL_TIME:
396         {
397             phyParam.Value = AS923_DEFAULT_UPLINK_DWELL_TIME;
398             break;
399         }
400         case PHY_DEF_DOWNLINK_DWELL_TIME:
401         {
402             phyParam.Value = REGION_COMMON_DEFAULT_DOWNLINK_DWELL_TIME;
403             break;
404         }
405         case PHY_DEF_MAX_EIRP:
406         {
407             phyParam.fValue = AS923_DEFAULT_MAX_EIRP;
408             break;
409         }
410         case PHY_DEF_ANTENNA_GAIN:
411         {
412             phyParam.fValue = AS923_DEFAULT_ANTENNA_GAIN;
413             break;
414         }
415         case PHY_BEACON_CHANNEL_FREQ:
416         {
417             phyParam.Value = AS923_BEACON_CHANNEL_FREQ - REGION_AS923_FREQ_OFFSET;
418             break;
419         }
420         case PHY_BEACON_FORMAT:
421         {
422             phyParam.BeaconFormat.BeaconSize = AS923_BEACON_SIZE;
423             phyParam.BeaconFormat.Rfu1Size = AS923_RFU1_SIZE;
424             phyParam.BeaconFormat.Rfu2Size = AS923_RFU2_SIZE;
425             break;
426         }
427         case PHY_BEACON_CHANNEL_DR:
428         {
429             phyParam.Value = AS923_BEACON_CHANNEL_DR;
430             break;
431         }
432         case PHY_PING_SLOT_CHANNEL_FREQ:
433         {
434             phyParam.Value = AS923_PING_SLOT_CHANNEL_FREQ - REGION_AS923_FREQ_OFFSET;
435             break;
436         }
437         case PHY_PING_SLOT_CHANNEL_DR:
438         {
439             phyParam.Value = AS923_PING_SLOT_CHANNEL_DR;
440             break;
441         }
442         case PHY_SF_FROM_DR:
443         {
444             phyParam.Value = DataratesAS923[getPhy->Datarate];
445             break;
446         }
447         case PHY_BW_FROM_DR:
448         {
449             phyParam.Value = RegionCommonGetBandwidth( getPhy->Datarate, BandwidthsAS923 );
450             break;
451         }
452         default:
453         {
454             break;
455         }
456     }
457 
458     return phyParam;
459 }
460 
RegionAS923SetBandTxDone(SetBandTxDoneParams_t * txDone)461 void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone )
462 {
463     RegionCommonSetBandTxDone( &RegionBands[RegionNvmGroup2->Channels[txDone->Channel].Band],
464                                txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
465 }
466 
RegionAS923InitDefaults(InitDefaultsParams_t * params)467 void RegionAS923InitDefaults( InitDefaultsParams_t* params )
468 {
469     Band_t bands[AS923_MAX_NB_BANDS] =
470     {
471         AS923_BAND0
472     };
473 
474     switch( params->Type )
475     {
476         case INIT_TYPE_DEFAULTS:
477         {
478             if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) )
479             {
480                 return;
481             }
482 
483             RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1;
484             RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2;
485             RegionBands = (Band_t*) params->Bands;
486 
487             // Default bands
488             memcpy1( ( uint8_t* )RegionBands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS );
489 
490             // Default channels
491             RegionNvmGroup2->Channels[0] = ( ChannelParams_t ) AS923_LC1;
492             RegionNvmGroup2->Channels[1] = ( ChannelParams_t ) AS923_LC2;
493 
494             // Apply frequency offset
495             RegionNvmGroup2->Channels[0].Frequency -= REGION_AS923_FREQ_OFFSET;
496             RegionNvmGroup2->Channels[1].Frequency -= REGION_AS923_FREQ_OFFSET;
497 
498             // Default ChannelsMask
499             RegionNvmGroup2->ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
500 
501             // Update the channels mask
502             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
503 
504 #if ( ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_LBT ) || \
505       ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH37_CH61_LBT_DC ) )
506             RegionNvmGroup2->RssiFreeThreshold = AS923_RSSI_FREE_TH;
507             RegionNvmGroup2->CarrierSenseTime = AS923_CARRIER_SENSE_TIME;
508 #endif
509             break;
510         }
511         case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS:
512         {
513             // Reset Channels Rx1Frequency to default 0
514             RegionNvmGroup2->Channels[0].Rx1Frequency = 0;
515             RegionNvmGroup2->Channels[1].Rx1Frequency = 0;
516             // Update the channels mask
517             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
518             break;
519         }
520         case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS:
521         {
522             // Activate channels default mask
523             RegionNvmGroup2->ChannelsMask[0] |= RegionNvmGroup2->ChannelsDefaultMask[0];
524             break;
525         }
526         default:
527         {
528             break;
529         }
530     }
531 }
532 
RegionAS923Verify(VerifyParams_t * verify,PhyAttribute_t phyAttribute)533 bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
534 {
535     switch( phyAttribute )
536     {
537         case PHY_FREQUENCY:
538         {
539             return VerifyRfFreq( verify->Frequency );
540         }
541         case PHY_TX_DR:
542         {
543             if( verify->DatarateParams.UplinkDwellTime == 0 )
544             {
545                 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AS923_TX_MIN_DATARATE, AS923_TX_MAX_DATARATE );
546             }
547             else
548             {
549                 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AS923_DWELL_LIMIT_DATARATE, AS923_TX_MAX_DATARATE );
550             }
551         }
552         case PHY_DEF_TX_DR:
553         {
554             return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
555         }
556         case PHY_RX_DR:
557         {
558             if( verify->DatarateParams.DownlinkDwellTime == 0 )
559             {
560                 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AS923_RX_MIN_DATARATE, AS923_RX_MAX_DATARATE );
561             }
562             else
563             {
564                 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AS923_DWELL_LIMIT_DATARATE, AS923_RX_MAX_DATARATE );
565             }
566         }
567         case PHY_DEF_TX_POWER:
568         case PHY_TX_POWER:
569         {
570             // Remark: switched min and max!
571             return RegionCommonValueInRange( verify->TxPower, AS923_MAX_TX_POWER, AS923_MIN_TX_POWER );
572         }
573         case PHY_DUTY_CYCLE:
574         {
575             return AS923_DUTY_CYCLE_ENABLED;
576         }
577         default:
578             return false;
579     }
580 }
581 
RegionAS923ApplyCFList(ApplyCFListParams_t * applyCFList)582 void RegionAS923ApplyCFList( ApplyCFListParams_t* applyCFList )
583 {
584     ChannelParams_t newChannel;
585     ChannelAddParams_t channelAdd;
586     ChannelRemoveParams_t channelRemove;
587 
588     // Setup default datarate range
589     newChannel.DrRange.Value = ( DR_5 << 4 ) | DR_0;
590 
591     // Size of the optional CF list
592     if( applyCFList->Size != 16 )
593     {
594         return;
595     }
596 
597     // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
598     if( applyCFList->Payload[15] != 0 )
599     {
600         return;
601     }
602 
603     // Last byte is RFU, don't take it into account
604     for( uint8_t i = 0, chanIdx = AS923_NUMB_DEFAULT_CHANNELS; chanIdx < AS923_MAX_NB_CHANNELS; i+=3, chanIdx++ )
605     {
606         if( chanIdx < ( AS923_NUMB_CHANNELS_CF_LIST + AS923_NUMB_DEFAULT_CHANNELS ) )
607         {
608             // Channel frequency
609             newChannel.Frequency = (uint32_t) applyCFList->Payload[i];
610             newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 1] << 8 );
611             newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 2] << 16 );
612             newChannel.Frequency *= 100;
613 
614             // Initialize alternative frequency to 0
615             newChannel.Rx1Frequency = 0;
616         }
617         else
618         {
619             newChannel.Frequency = 0;
620             newChannel.DrRange.Value = 0;
621             newChannel.Rx1Frequency = 0;
622         }
623 
624         if( newChannel.Frequency != 0 )
625         {
626             channelAdd.NewChannel = &newChannel;
627             channelAdd.ChannelId = chanIdx;
628 
629             // Try to add all channels
630             RegionAS923ChannelAdd( &channelAdd );
631         }
632         else
633         {
634             channelRemove.ChannelId = chanIdx;
635 
636             RegionAS923ChannelsRemove( &channelRemove );
637         }
638     }
639 }
640 
RegionAS923ChanMaskSet(ChanMaskSetParams_t * chanMaskSet)641 bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
642 {
643     switch( chanMaskSet->ChannelsMaskType )
644     {
645         case CHANNELS_MASK:
646         {
647             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
648             break;
649         }
650         case CHANNELS_DEFAULT_MASK:
651         {
652             RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
653             break;
654         }
655         default:
656             return false;
657     }
658     return true;
659 }
660 
RegionAS923ComputeRxWindowParameters(int8_t datarate,uint8_t minRxSymbols,uint32_t rxError,RxConfigParams_t * rxConfigParams)661 void RegionAS923ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
662 {
663     uint32_t tSymbolInUs = 0;
664 
665     // Get the datarate, perform a boundary check
666     rxConfigParams->Datarate = MIN( datarate, AS923_RX_MAX_DATARATE );
667     rxConfigParams->Bandwidth = RegionCommonGetBandwidth( rxConfigParams->Datarate, BandwidthsAS923 );
668 
669     if( rxConfigParams->Datarate == DR_7 )
670     { // FSK
671         tSymbolInUs = RegionCommonComputeSymbolTimeFsk( DataratesAS923[rxConfigParams->Datarate] );
672     }
673     else
674     { // LoRa
675         tSymbolInUs = RegionCommonComputeSymbolTimeLoRa( DataratesAS923[rxConfigParams->Datarate], BandwidthsAS923[rxConfigParams->Datarate] );
676     }
677 
678     RegionCommonComputeRxWindowParameters( tSymbolInUs, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
679 }
680 
RegionAS923RxConfig(RxConfigParams_t * rxConfig,int8_t * datarate)681 bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
682 {
683     RadioModems_t modem;
684     int8_t dr = rxConfig->Datarate;
685     int8_t phyDr = 0;
686     uint32_t frequency = rxConfig->Frequency;
687 
688     if( Radio.GetStatus( ) != RF_IDLE )
689     {
690         return false;
691     }
692 
693     if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
694     {
695         // Apply window 1 frequency
696         frequency = RegionNvmGroup2->Channels[rxConfig->Channel].Frequency;
697         // Apply the alternative RX 1 window frequency, if it is available
698         if( RegionNvmGroup2->Channels[rxConfig->Channel].Rx1Frequency != 0 )
699         {
700             frequency = RegionNvmGroup2->Channels[rxConfig->Channel].Rx1Frequency;
701         }
702     }
703 
704     // Read the physical datarate from the datarates table
705     phyDr = DataratesAS923[dr];
706 
707     Radio.SetChannel( frequency );
708 
709     // Radio configuration
710     if( dr == DR_7 )
711     {
712         modem = MODEM_FSK;
713         Radio.SetRxConfig( modem, 50000, phyDr * 1000, 0, 83333, 5, rxConfig->WindowTimeout, false, 0, true, 0, 0, false, rxConfig->RxContinuous );
714     }
715     else
716     {
717         modem = MODEM_LORA;
718         Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
719     }
720 
721     Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateDwell0AS923[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
722 
723     *datarate = (uint8_t) dr;
724     return true;
725 }
726 
RegionAS923TxConfig(TxConfigParams_t * txConfig,int8_t * txPower,TimerTime_t * txTimeOnAir)727 bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
728 {
729     RadioModems_t modem;
730     int8_t phyDr = DataratesAS923[txConfig->Datarate];
731     int8_t txPowerLimited = RegionCommonLimitTxPower( txConfig->TxPower, RegionBands[RegionNvmGroup2->Channels[txConfig->Channel].Band].TxMaxPower );
732     uint32_t bandwidth = RegionCommonGetBandwidth( txConfig->Datarate, BandwidthsAS923 );
733     int8_t phyTxPower = 0;
734 
735     // Calculate physical TX power
736     phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
737 
738     // Setup the radio frequency
739     Radio.SetChannel( RegionNvmGroup2->Channels[txConfig->Channel].Frequency );
740 
741     if( txConfig->Datarate == DR_7 )
742     { // High Speed FSK channel
743         modem = MODEM_FSK;
744         Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
745     }
746     else
747     {
748         modem = MODEM_LORA;
749         Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
750     }
751 
752     // Update time-on-air
753     *txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
754 
755     // Setup maximum payload lenght of the radio driver
756     Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
757 
758     *txPower = txPowerLimited;
759     return true;
760 }
761 
RegionAS923LinkAdrReq(LinkAdrReqParams_t * linkAdrReq,int8_t * drOut,int8_t * txPowOut,uint8_t * nbRepOut,uint8_t * nbBytesParsed)762 uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
763 {
764     uint8_t status = 0x07;
765     RegionCommonLinkAdrParams_t linkAdrParams = { 0 };
766     uint8_t nextIndex = 0;
767     uint8_t bytesProcessed = 0;
768     uint16_t chMask = 0;
769     GetPhyParams_t getPhy;
770     PhyParam_t phyParam;
771     RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
772 
773     while( bytesProcessed < linkAdrReq->PayloadSize )
774     {
775         // Get ADR request parameters
776         nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
777 
778         if( nextIndex == 0 )
779             break; // break loop, since no more request has been found
780 
781         // Update bytes processed
782         bytesProcessed += nextIndex;
783 
784         // Revert status, as we only check the last ADR request for the channel mask KO
785         status = 0x07;
786 
787         // Setup temporary channels mask
788         chMask = linkAdrParams.ChMask;
789 
790         // Verify channels mask
791         if( ( linkAdrParams.ChMaskCtrl == 0 ) && ( chMask == 0 ) )
792         {
793             status &= 0xFE; // Channel mask KO
794         }
795         else if( ( ( linkAdrParams.ChMaskCtrl >= 1 ) && ( linkAdrParams.ChMaskCtrl <= 5 )) ||
796                 ( linkAdrParams.ChMaskCtrl >= 7 ) )
797         {
798             // RFU
799             status &= 0xFE; // Channel mask KO
800         }
801         else
802         {
803             for( uint8_t i = 0; i < AS923_MAX_NB_CHANNELS; i++ )
804             {
805                 if( linkAdrParams.ChMaskCtrl == 6 )
806                 {
807                     if( RegionNvmGroup2->Channels[i].Frequency != 0 )
808                     {
809                         chMask |= 1 << i;
810                     }
811                 }
812                 else
813                 {
814                     if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
815                         ( RegionNvmGroup2->Channels[i].Frequency == 0 ) )
816                     {// Trying to enable an undefined channel
817                         status &= 0xFE; // Channel mask KO
818                     }
819                 }
820             }
821         }
822     }
823 
824     // Get the minimum possible datarate
825     getPhy.Attribute = PHY_MIN_TX_DR;
826     getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
827     phyParam = RegionAS923GetPhyParam( &getPhy );
828 
829     linkAdrVerifyParams.Status = status;
830     linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
831     linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
832     linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
833     linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
834     linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
835     linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
836     linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
837     linkAdrVerifyParams.NbChannels = AS923_MAX_NB_CHANNELS;
838     linkAdrVerifyParams.ChannelsMask = &chMask;
839     linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
840     linkAdrVerifyParams.MaxDatarate = AS923_TX_MAX_DATARATE;
841     linkAdrVerifyParams.Channels = RegionNvmGroup2->Channels;
842     linkAdrVerifyParams.MinTxPower = AS923_MIN_TX_POWER;
843     linkAdrVerifyParams.MaxTxPower = AS923_MAX_TX_POWER;
844     linkAdrVerifyParams.Version = linkAdrReq->Version;
845 
846     // Verify the parameters and update, if necessary
847     status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
848 
849     // Update channelsMask if everything is correct
850     if( status == 0x07 )
851     {
852         // Set the channels mask to a default value
853         memset1( ( uint8_t* ) RegionNvmGroup2->ChannelsMask, 0, sizeof( RegionNvmGroup2->ChannelsMask ) );
854         // Update the channels mask
855         RegionNvmGroup2->ChannelsMask[0] = chMask;
856     }
857 
858     // Update status variables
859     *drOut = linkAdrParams.Datarate;
860     *txPowOut = linkAdrParams.TxPower;
861     *nbRepOut = linkAdrParams.NbRep;
862     *nbBytesParsed = bytesProcessed;
863 
864     return status;
865 }
866 
RegionAS923RxParamSetupReq(RxParamSetupReqParams_t * rxParamSetupReq)867 uint8_t RegionAS923RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
868 {
869     uint8_t status = 0x07;
870 
871     // Verify radio frequency
872     if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
873     {
874         status &= 0xFE; // Channel frequency KO
875     }
876 
877     // Verify datarate
878     if( RegionCommonValueInRange( rxParamSetupReq->Datarate, AS923_RX_MIN_DATARATE, AS923_RX_MAX_DATARATE ) == false )
879     {
880         status &= 0xFD; // Datarate KO
881     }
882 
883     // Verify datarate offset
884     if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, AS923_MIN_RX1_DR_OFFSET, AS923_MAX_RX1_DR_OFFSET ) == false )
885     {
886         status &= 0xFB; // Rx1DrOffset range KO
887     }
888 
889     return status;
890 }
891 
RegionAS923NewChannelReq(NewChannelReqParams_t * newChannelReq)892 int8_t RegionAS923NewChannelReq( NewChannelReqParams_t* newChannelReq )
893 {
894     uint8_t status = 0x03;
895     ChannelAddParams_t channelAdd;
896     ChannelRemoveParams_t channelRemove;
897 
898     if( newChannelReq->NewChannel->Frequency == 0 )
899     {
900         channelRemove.ChannelId = newChannelReq->ChannelId;
901 
902         // Remove
903         if( RegionAS923ChannelsRemove( &channelRemove ) == false )
904         {
905             status &= 0xFC;
906         }
907     }
908     else
909     {
910         channelAdd.NewChannel = newChannelReq->NewChannel;
911         channelAdd.ChannelId = newChannelReq->ChannelId;
912 
913         switch( RegionAS923ChannelAdd( &channelAdd ) )
914         {
915             case LORAMAC_STATUS_OK:
916             {
917                 break;
918             }
919             case LORAMAC_STATUS_FREQUENCY_INVALID:
920             {
921                 status &= 0xFE;
922                 break;
923             }
924             case LORAMAC_STATUS_DATARATE_INVALID:
925             {
926                 status &= 0xFD;
927                 break;
928             }
929             case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
930             {
931                 status &= 0xFC;
932                 break;
933             }
934             default:
935             {
936                 status &= 0xFC;
937                 break;
938             }
939         }
940     }
941 
942     return status;
943 }
944 
RegionAS923TxParamSetupReq(TxParamSetupReqParams_t * txParamSetupReq)945 int8_t RegionAS923TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
946 {
947     // Accept the request
948     return 0;
949 }
950 
RegionAS923DlChannelReq(DlChannelReqParams_t * dlChannelReq)951 int8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq )
952 {
953     uint8_t status = 0x03;
954 
955     if( dlChannelReq->ChannelId >= ( CHANNELS_MASK_SIZE * 16 ) )
956     {
957         return 0;
958     }
959 
960     // Verify if the frequency is supported
961     if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
962     {
963         status &= 0xFE;
964     }
965 
966     // Verify if an uplink frequency exists
967     if( RegionNvmGroup2->Channels[dlChannelReq->ChannelId].Frequency == 0 )
968     {
969         status &= 0xFD;
970     }
971 
972     // Apply Rx1 frequency, if the status is OK
973     if( status == 0x03 )
974     {
975         RegionNvmGroup2->Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
976     }
977 
978     return status;
979 }
980 
RegionAS923AlternateDr(int8_t currentDr,AlternateDrType_t type)981 int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type )
982 {
983     // Only AS923_DWELL_LIMIT_DATARATE is supported
984     return AS923_DWELL_LIMIT_DATARATE;
985 }
986 
RegionAS923NextChannel(NextChanParams_t * nextChanParams,uint8_t * channel,TimerTime_t * time,TimerTime_t * aggregatedTimeOff)987 LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
988 {
989     uint8_t nbEnabledChannels = 0;
990     uint8_t nbRestrictedChannels = 0;
991     uint8_t enabledChannels[AS923_MAX_NB_CHANNELS] = { 0 };
992     RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
993     RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
994     LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
995     uint16_t joinChannels = AS923_JOIN_CHANNELS;
996 
997     if( RegionCommonCountChannels( RegionNvmGroup2->ChannelsMask, 0, 1 ) == 0 )
998     { // Reactivate default channels
999         RegionNvmGroup2->ChannelsMask[0] |= LC( 1 ) + LC( 2 );
1000     }
1001 
1002     // Search how many channels are enabled
1003     countChannelsParams.Joined = nextChanParams->Joined;
1004     countChannelsParams.Datarate = nextChanParams->Datarate;
1005     countChannelsParams.ChannelsMask = RegionNvmGroup2->ChannelsMask;
1006     countChannelsParams.Channels = RegionNvmGroup2->Channels;
1007     countChannelsParams.Bands = RegionBands;
1008     countChannelsParams.MaxNbChannels = AS923_MAX_NB_CHANNELS;
1009     countChannelsParams.JoinChannels = &joinChannels;
1010 
1011     identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
1012     identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
1013     identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
1014     identifyChannelsParam.MaxBands = AS923_MAX_NB_BANDS;
1015 
1016     identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
1017     identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
1018     identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
1019 
1020     identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
1021 
1022     status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
1023                                            &nbEnabledChannels, &nbRestrictedChannels, time );
1024 
1025     if( status == LORAMAC_STATUS_OK )
1026     {
1027 #if ( ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH24_CH38_LBT ) || \
1028       ( REGION_AS923_DEFAULT_CHANNEL_PLAN == CHANNEL_PLAN_GROUP_AS923_1_JP_CH37_CH61_LBT_DC ) )
1029         // Executes the LBT algorithm when operating in Japan
1030         uint8_t channelNext = 0;
1031 
1032         for( uint8_t  i = 0, j = randr( 0, nbEnabledChannels - 1 ); i < AS923_MAX_NB_CHANNELS; i++ )
1033         {
1034             channelNext = enabledChannels[j];
1035             j = ( j + 1 ) % nbEnabledChannels;
1036 
1037             // Perform carrier sense for AS923_CARRIER_SENSE_TIME
1038             // If the channel is free, we can stop the LBT mechanism
1039             if( Radio.IsChannelFree( RegionNvmGroup2->Channels[channelNext].Frequency, AS923_LBT_RX_BANDWIDTH, RegionNvmGroup2->RssiFreeThreshold, RegionNvmGroup2->CarrierSenseTime ) == true )
1040             {
1041                 // Free channel found
1042                 *channel = channelNext;
1043                 return LORAMAC_STATUS_OK;
1044             }
1045         }
1046         // Even if one or more channels are available according to the channel plan, no free channel
1047         // was found during the LBT procedure.
1048         status = LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
1049 #else
1050         // We found a valid channel
1051         *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
1052 #endif
1053     }
1054     else if( status == LORAMAC_STATUS_NO_CHANNEL_FOUND )
1055     {
1056         // Datarate not supported by any channel, restore defaults
1057         RegionNvmGroup2->ChannelsMask[0] |= LC( 1 ) + LC( 2 );
1058     }
1059     return status;
1060 }
1061 
RegionAS923ChannelAdd(ChannelAddParams_t * channelAdd)1062 LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )
1063 {
1064     bool drInvalid = false;
1065     bool freqInvalid = false;
1066     uint8_t id = channelAdd->ChannelId;
1067 
1068     if( id < AS923_NUMB_DEFAULT_CHANNELS )
1069     {
1070         return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
1071     }
1072 
1073     if( id >= AS923_MAX_NB_CHANNELS )
1074     {
1075         return LORAMAC_STATUS_PARAMETER_INVALID;
1076     }
1077 
1078     // Validate the datarate range
1079     if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, AS923_TX_MIN_DATARATE, AS923_TX_MAX_DATARATE ) == false )
1080     {
1081         drInvalid = true;
1082     }
1083     if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, AS923_TX_MIN_DATARATE, AS923_TX_MAX_DATARATE ) == false )
1084     {
1085         drInvalid = true;
1086     }
1087     if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
1088     {
1089         drInvalid = true;
1090     }
1091 
1092     // Check frequency
1093     if( freqInvalid == false )
1094     {
1095         if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
1096         {
1097             freqInvalid = true;
1098         }
1099     }
1100 
1101     // Check status
1102     if( ( drInvalid == true ) && ( freqInvalid == true ) )
1103     {
1104         return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
1105     }
1106     if( drInvalid == true )
1107     {
1108         return LORAMAC_STATUS_DATARATE_INVALID;
1109     }
1110     if( freqInvalid == true )
1111     {
1112         return LORAMAC_STATUS_FREQUENCY_INVALID;
1113     }
1114 
1115     memcpy1( ( uint8_t* ) &(RegionNvmGroup2->Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( RegionNvmGroup2->Channels[id] ) );
1116     RegionNvmGroup2->Channels[id].Band = 0;
1117     RegionNvmGroup2->ChannelsMask[0] |= ( 1 << id );
1118     return LORAMAC_STATUS_OK;
1119 }
1120 
RegionAS923ChannelsRemove(ChannelRemoveParams_t * channelRemove)1121 bool RegionAS923ChannelsRemove( ChannelRemoveParams_t* channelRemove  )
1122 {
1123     uint8_t id = channelRemove->ChannelId;
1124 
1125     if( id < AS923_NUMB_DEFAULT_CHANNELS )
1126     {
1127         return false;
1128     }
1129 
1130     // Remove the channel from the list of channels
1131     RegionNvmGroup2->Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
1132 
1133     return RegionCommonChanDisable( RegionNvmGroup2->ChannelsMask, id, AS923_MAX_NB_CHANNELS );
1134 }
1135 
RegionAS923ApplyDrOffset(uint8_t downlinkDwellTime,int8_t dr,int8_t drOffset)1136 uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
1137 {
1138     // Initialize minDr
1139     int8_t minDr;
1140 
1141     if( downlinkDwellTime == 0 )
1142     {
1143         // Update the minDR for a downlink dwell time configuration of 0
1144         minDr = EffectiveRx1DrOffsetDownlinkDwell0AS923[dr][drOffset];
1145     }
1146     else
1147     {
1148         // Update the minDR for a downlink dwell time configuration of 1
1149         minDr = EffectiveRx1DrOffsetDownlinkDwell1AS923[dr][drOffset];
1150     }
1151 
1152     return minDr;
1153 }
1154 
RegionAS923RxBeaconSetup(RxBeaconSetup_t * rxBeaconSetup,uint8_t * outDr)1155 void RegionAS923RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
1156 {
1157     RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
1158 
1159     regionCommonRxBeaconSetup.Datarates = DataratesAS923;
1160     regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
1161     regionCommonRxBeaconSetup.BeaconSize = AS923_BEACON_SIZE;
1162     regionCommonRxBeaconSetup.BeaconDatarate = AS923_BEACON_CHANNEL_DR;
1163     regionCommonRxBeaconSetup.BeaconChannelBW = AS923_BEACON_CHANNEL_BW;
1164     regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
1165     regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
1166 
1167     RegionCommonRxBeaconSetup( &regionCommonRxBeaconSetup );
1168 
1169     // Store downlink datarate
1170     *outDr = AS923_BEACON_CHANNEL_DR;
1171 }
1172