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( ®ionCommonRxBeaconSetup );
1168
1169 // Store downlink datarate
1170 *outDr = AS923_BEACON_CHANNEL_DR;
1171 }
1172