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( ®ionCommonRxBeaconSetup );
1056
1057 // Store downlink datarate
1058 *outDr = AS923_BEACON_CHANNEL_DR;
1059 }
1060