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