1 /*!
2 * \file RegionAU915.c
3 *
4 * \brief Region implementation for AU915
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 "RegionAU915.h"
34 #include "RegionBaseUS.h"
35
36 // Definitions
37 #define CHANNELS_MASK_SIZE 6
38
39 // A mask to select only valid 500KHz channels
40 #define CHANNELS_MASK_500KHZ_MASK 0x00FF
41
42 /*
43 * Non-volatile module context.
44 */
45 static RegionNvmDataGroup1_t* RegionNvmGroup1;
46 static RegionNvmDataGroup2_t* RegionNvmGroup2;
47 static Band_t* RegionBands;
48
VerifyRfFreq(uint32_t freq)49 static bool VerifyRfFreq( uint32_t freq )
50 {
51 // Check radio driver support
52 if( Radio.CheckRfFrequency( freq ) == false )
53 {
54 return false;
55 }
56
57 // Rx frequencies
58 if( ( freq < AU915_FIRST_RX1_CHANNEL ) ||
59 ( freq > AU915_LAST_RX1_CHANNEL ) ||
60 ( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
61 {
62 return false;
63 }
64
65 // Tx frequencies for 125kHz
66 // Also includes the range for 500kHz channels
67 if( ( freq < 915200000 ) || ( freq > 927800000 ) )
68 {
69 return false;
70 }
71 return true;
72 }
73
GetTimeOnAir(int8_t datarate,uint16_t pktLen)74 static TimerTime_t GetTimeOnAir( int8_t datarate, uint16_t pktLen )
75 {
76 int8_t phyDr = DataratesAU915[datarate];
77 uint32_t bandwidth = RegionCommonGetBandwidth( datarate, BandwidthsAU915 );
78
79 return Radio.TimeOnAir( MODEM_LORA, bandwidth, phyDr, 1, 8, false, pktLen, true );
80 }
81
RegionAU915GetPhyParam(GetPhyParams_t * getPhy)82 PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
83 {
84 PhyParam_t phyParam = { 0 };
85
86 switch( getPhy->Attribute )
87 {
88 case PHY_MIN_RX_DR:
89 {
90 if( getPhy->DownlinkDwellTime == 0)
91 {
92 phyParam.Value = AU915_RX_MIN_DATARATE;
93 }
94 else
95 {
96 phyParam.Value = AU915_DWELL_LIMIT_DATARATE;
97 }
98 break;
99 }
100 case PHY_MIN_TX_DR:
101 {
102 if( getPhy->UplinkDwellTime == 0)
103 {
104 phyParam.Value = AU915_TX_MIN_DATARATE;
105 }
106 else
107 {
108 phyParam.Value = AU915_DWELL_LIMIT_DATARATE;
109 }
110 break;
111 }
112 case PHY_DEF_TX_DR:
113 {
114 phyParam.Value = AU915_DEFAULT_DATARATE;
115 break;
116 }
117 case PHY_NEXT_LOWER_TX_DR:
118 {
119 RegionCommonGetNextLowerTxDrParams_t nextLowerTxDrParams =
120 {
121 .CurrentDr = getPhy->Datarate,
122 .MaxDr = ( int8_t )AU915_TX_MAX_DATARATE,
123 .MinDr = ( int8_t )( ( getPhy->UplinkDwellTime == 0 ) ? AU915_TX_MIN_DATARATE : AU915_DWELL_LIMIT_DATARATE ),
124 .NbChannels = AU915_MAX_NB_CHANNELS,
125 .ChannelsMask = RegionNvmGroup2->ChannelsMask,
126 .Channels = RegionNvmGroup2->Channels,
127 };
128 phyParam.Value = RegionCommonGetNextLowerTxDr( &nextLowerTxDrParams );
129 break;
130 }
131 case PHY_MAX_TX_POWER:
132 {
133 phyParam.Value = AU915_MAX_TX_POWER;
134 break;
135 }
136 case PHY_DEF_TX_POWER:
137 {
138 phyParam.Value = AU915_DEFAULT_TX_POWER;
139 break;
140 }
141 case PHY_DEF_ADR_ACK_LIMIT:
142 {
143 phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_LIMIT;
144 break;
145 }
146 case PHY_DEF_ADR_ACK_DELAY:
147 {
148 phyParam.Value = REGION_COMMON_DEFAULT_ADR_ACK_DELAY;
149 break;
150 }
151 case PHY_MAX_PAYLOAD:
152 {
153 if( getPhy->UplinkDwellTime == 0 )
154 {
155 phyParam.Value = MaxPayloadOfDatarateDwell0AU915[getPhy->Datarate];
156 }
157 else
158 {
159 phyParam.Value = MaxPayloadOfDatarateDwell1AU915[getPhy->Datarate];
160 }
161 break;
162 }
163 case PHY_DUTY_CYCLE:
164 {
165 phyParam.Value = AU915_DUTY_CYCLE_ENABLED;
166 break;
167 }
168 case PHY_MAX_RX_WINDOW:
169 {
170 phyParam.Value = AU915_MAX_RX_WINDOW;
171 break;
172 }
173 case PHY_RECEIVE_DELAY1:
174 {
175 phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY1;
176 break;
177 }
178 case PHY_RECEIVE_DELAY2:
179 {
180 phyParam.Value = REGION_COMMON_DEFAULT_RECEIVE_DELAY2;
181 break;
182 }
183 case PHY_JOIN_ACCEPT_DELAY1:
184 {
185 phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY1;
186 break;
187 }
188 case PHY_JOIN_ACCEPT_DELAY2:
189 {
190 phyParam.Value = REGION_COMMON_DEFAULT_JOIN_ACCEPT_DELAY2;
191 break;
192 }
193 case PHY_RETRANSMIT_TIMEOUT:
194 {
195 phyParam.Value = ( REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT + randr( -REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND, REGION_COMMON_DEFAULT_RETRANSMIT_TIMEOUT_RND ) );
196 break;
197 }
198 case PHY_DEF_DR1_OFFSET:
199 {
200 phyParam.Value = REGION_COMMON_DEFAULT_RX1_DR_OFFSET;
201 break;
202 }
203 case PHY_DEF_RX2_FREQUENCY:
204 {
205 phyParam.Value = AU915_RX_WND_2_FREQ;
206 break;
207 }
208 case PHY_DEF_RX2_DR:
209 {
210 phyParam.Value = AU915_RX_WND_2_DR;
211 break;
212 }
213 case PHY_CHANNELS_MASK:
214 {
215 phyParam.ChannelsMask = RegionNvmGroup2->ChannelsMask;
216 break;
217 }
218 case PHY_CHANNELS_DEFAULT_MASK:
219 {
220 phyParam.ChannelsMask = RegionNvmGroup2->ChannelsDefaultMask;
221 break;
222 }
223 case PHY_MAX_NB_CHANNELS:
224 {
225 phyParam.Value = AU915_MAX_NB_CHANNELS;
226 break;
227 }
228 case PHY_CHANNELS:
229 {
230 phyParam.Channels = RegionNvmGroup2->Channels;
231 break;
232 }
233 case PHY_DEF_UPLINK_DWELL_TIME:
234 {
235 phyParam.Value = AU915_DEFAULT_UPLINK_DWELL_TIME;
236 break;
237 }
238 case PHY_DEF_DOWNLINK_DWELL_TIME:
239 {
240 phyParam.Value = REGION_COMMON_DEFAULT_DOWNLINK_DWELL_TIME;
241 break;
242 }
243 case PHY_DEF_MAX_EIRP:
244 {
245 phyParam.fValue = AU915_DEFAULT_MAX_EIRP;
246 break;
247 }
248 case PHY_DEF_ANTENNA_GAIN:
249 {
250 phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
251 break;
252 }
253 case PHY_BEACON_CHANNEL_FREQ:
254 {
255 phyParam.Value = RegionBaseUSCalcDownlinkFrequency( getPhy->Channel,
256 AU915_BEACON_CHANNEL_FREQ,
257 AU915_BEACON_CHANNEL_STEPWIDTH );
258 break;
259 }
260 case PHY_BEACON_FORMAT:
261 {
262 phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;
263 phyParam.BeaconFormat.Rfu1Size = AU915_RFU1_SIZE;
264 phyParam.BeaconFormat.Rfu2Size = AU915_RFU2_SIZE;
265 break;
266 }
267 case PHY_BEACON_CHANNEL_DR:
268 {
269 phyParam.Value = AU915_BEACON_CHANNEL_DR;
270 break;
271 }
272 case PHY_BEACON_NB_CHANNELS:
273 {
274 phyParam.Value = AU915_BEACON_NB_CHANNELS;
275 break;
276 }
277 case PHY_PING_SLOT_CHANNEL_FREQ:
278 {
279 phyParam.Value = RegionBaseUSCalcDownlinkFrequency( getPhy->Channel,
280 AU915_PING_SLOT_CHANNEL_FREQ,
281 AU915_BEACON_CHANNEL_STEPWIDTH );
282 break;
283 }
284 case PHY_PING_SLOT_CHANNEL_DR:
285 {
286 phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;
287 break;
288 }
289 case PHY_PING_SLOT_NB_CHANNELS:
290 {
291 phyParam.Value = AU915_BEACON_NB_CHANNELS;
292 break;
293 }
294 case PHY_SF_FROM_DR:
295 {
296 phyParam.Value = DataratesAU915[getPhy->Datarate];
297 break;
298 }
299 case PHY_BW_FROM_DR:
300 {
301 phyParam.Value = RegionCommonGetBandwidth( getPhy->Datarate, BandwidthsAU915 );
302 break;
303 }
304 default:
305 {
306 break;
307 }
308 }
309
310 return phyParam;
311 }
312
RegionAU915SetBandTxDone(SetBandTxDoneParams_t * txDone)313 void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
314 {
315 RegionCommonSetBandTxDone( &RegionBands[RegionNvmGroup2->Channels[txDone->Channel].Band],
316 txDone->LastTxAirTime, txDone->Joined, txDone->ElapsedTimeSinceStartUp );
317 }
318
RegionAU915InitDefaults(InitDefaultsParams_t * params)319 void RegionAU915InitDefaults( InitDefaultsParams_t* params )
320 {
321 Band_t bands[AU915_MAX_NB_BANDS] =
322 {
323 AU915_BAND0
324 };
325
326 switch( params->Type )
327 {
328 case INIT_TYPE_DEFAULTS:
329 {
330 if( ( params->NvmGroup1 == NULL ) || ( params->NvmGroup2 == NULL ) )
331 {
332 return;
333 }
334
335 RegionNvmGroup1 = (RegionNvmDataGroup1_t*) params->NvmGroup1;
336 RegionNvmGroup2 = (RegionNvmDataGroup2_t*) params->NvmGroup2;
337 RegionBands = (Band_t*) params->Bands;
338
339 // Initialize 8 bit channel groups index
340 RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0;
341
342 // Initialize the join trials counter
343 RegionNvmGroup1->JoinTrialsCounter = 0;
344
345 // Default bands
346 memcpy1( ( uint8_t* )RegionBands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );
347
348 // Channels
349 for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
350 {
351 // 125 kHz channels
352 RegionNvmGroup2->Channels[i].Frequency = 915200000 + i * 200000;
353 RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
354 RegionNvmGroup2->Channels[i].Band = 0;
355 }
356 for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ )
357 {
358 // 500 kHz channels
359 RegionNvmGroup2->Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
360 RegionNvmGroup2->Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
361 RegionNvmGroup2->Channels[i].Band = 0;
362 }
363
364 // Initialize channels default mask
365 RegionNvmGroup2->ChannelsDefaultMask[0] = 0xFFFF;
366 RegionNvmGroup2->ChannelsDefaultMask[1] = 0xFFFF;
367 RegionNvmGroup2->ChannelsDefaultMask[2] = 0xFFFF;
368 RegionNvmGroup2->ChannelsDefaultMask[3] = 0xFFFF;
369 RegionNvmGroup2->ChannelsDefaultMask[4] = 0x00FF;
370 RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;
371
372 // Copy channels default mask
373 RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
374
375 // Copy into channels mask remaining
376 RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, CHANNELS_MASK_SIZE );
377 break;
378 }
379 case INIT_TYPE_RESET_TO_DEFAULT_CHANNELS:
380 {
381 // Intentional fallthrough
382 }
383 case INIT_TYPE_ACTIVATE_DEFAULT_CHANNELS:
384 {
385 // Copy channels default mask
386 RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, RegionNvmGroup2->ChannelsDefaultMask, CHANNELS_MASK_SIZE );
387
388 for( uint8_t i = 0; i < CHANNELS_MASK_SIZE; i++ )
389 { // Copy-And the channels mask
390 RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i];
391 }
392 break;
393 }
394 default:
395 {
396 break;
397 }
398 }
399 }
400
RegionAU915Verify(VerifyParams_t * verify,PhyAttribute_t phyAttribute)401 bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
402 {
403 switch( phyAttribute )
404 {
405 case PHY_FREQUENCY:
406 {
407 return VerifyRfFreq( verify->Frequency );
408 }
409 case PHY_TX_DR:
410 case PHY_DEF_TX_DR:
411 {
412 if( verify->DatarateParams.UplinkDwellTime == 0 )
413 {
414 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );
415 }
416 else
417 {
418 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_TX_MAX_DATARATE );
419 }
420 }
421 case PHY_RX_DR:
422 {
423 if( verify->DatarateParams.UplinkDwellTime == 0 )
424 {
425 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );
426 }
427 else
428 {
429 return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_RX_MAX_DATARATE );
430 }
431 }
432 case PHY_DEF_TX_POWER:
433 case PHY_TX_POWER:
434 {
435 // Remark: switched min and max!
436 return RegionCommonValueInRange( verify->TxPower, AU915_MAX_TX_POWER, AU915_MIN_TX_POWER );
437 }
438 case PHY_DUTY_CYCLE:
439 {
440 return AU915_DUTY_CYCLE_ENABLED;
441 }
442 default:
443 return false;
444 }
445 }
446
RegionAU915ApplyCFList(ApplyCFListParams_t * applyCFList)447 void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList )
448 {
449 // Size of the optional CF list must be 16 byte
450 if( applyCFList->Size != 16 )
451 {
452 return;
453 }
454
455 // Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
456 if( applyCFList->Payload[15] != 0x01 )
457 {
458 return;
459 }
460
461 // ChMask0 - ChMask4 must be set (every ChMask has 16 bit)
462 for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 4; chMaskItr++, cntPayload+=2 )
463 {
464 RegionNvmGroup2->ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
465 RegionNvmGroup2->ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
466 if( chMaskItr == 4 )
467 {
468 RegionNvmGroup2->ChannelsMask[chMaskItr] = RegionNvmGroup2->ChannelsMask[chMaskItr] & CHANNELS_MASK_500KHZ_MASK;
469 }
470 // Set the channel mask to the remaining
471 RegionNvmGroup1->ChannelsMaskRemaining[chMaskItr] &= RegionNvmGroup2->ChannelsMask[chMaskItr];
472 }
473 }
474
RegionAU915ChanMaskSet(ChanMaskSetParams_t * chanMaskSet)475 bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
476 {
477 switch( chanMaskSet->ChannelsMaskType )
478 {
479 case CHANNELS_MASK:
480 {
481 RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );
482
483 RegionNvmGroup2->ChannelsDefaultMask[4] = RegionNvmGroup2->ChannelsDefaultMask[4] & CHANNELS_MASK_500KHZ_MASK;
484 RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000;
485
486 for( uint8_t i = 0; i < 6; i++ )
487 { // Copy-And the channels mask
488 RegionNvmGroup1->ChannelsMaskRemaining[i] &= RegionNvmGroup2->ChannelsMask[i];
489 }
490 break;
491 }
492 case CHANNELS_DEFAULT_MASK:
493 {
494 RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );
495 break;
496 }
497 default:
498 return false;
499 }
500 return true;
501 }
502
RegionAU915ComputeRxWindowParameters(int8_t datarate,uint8_t minRxSymbols,uint32_t rxError,RxConfigParams_t * rxConfigParams)503 void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
504 {
505 uint32_t tSymbolInUs = 0;
506
507 // Get the datarate, perform a boundary check
508 rxConfigParams->Datarate = MIN( datarate, AU915_RX_MAX_DATARATE );
509 rxConfigParams->Bandwidth = RegionCommonGetBandwidth( rxConfigParams->Datarate, BandwidthsAU915 );
510
511 tSymbolInUs = RegionCommonComputeSymbolTimeLoRa( DataratesAU915[rxConfigParams->Datarate], BandwidthsAU915[rxConfigParams->Datarate] );
512
513 RegionCommonComputeRxWindowParameters( tSymbolInUs, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
514 }
515
RegionAU915RxConfig(RxConfigParams_t * rxConfig,int8_t * datarate)516 bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
517 {
518 int8_t dr = rxConfig->Datarate;
519 int8_t phyDr = 0;
520 uint32_t frequency = rxConfig->Frequency;
521
522 if( Radio.GetStatus( ) != RF_IDLE )
523 {
524 return false;
525 }
526
527 if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
528 {
529 // Apply window 1 frequency
530 frequency = AU915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * AU915_STEPWIDTH_RX1_CHANNEL;
531 }
532
533 // Read the physical datarate from the datarates table
534 phyDr = DataratesAU915[dr];
535
536 Radio.SetChannel( frequency );
537
538 // Radio configuration
539 Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
540
541 Radio.SetMaxPayloadLength( MODEM_LORA, MaxPayloadOfDatarateDwell0AU915[dr] + LORAMAC_FRAME_PAYLOAD_OVERHEAD_SIZE );
542
543 *datarate = (uint8_t) dr;
544 return true;
545 }
546
RegionAU915TxConfig(TxConfigParams_t * txConfig,int8_t * txPower,TimerTime_t * txTimeOnAir)547 bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
548 {
549 int8_t phyDr = DataratesAU915[txConfig->Datarate];
550 int8_t txPowerLimited = RegionCommonLimitTxPower( txConfig->TxPower, RegionBands[RegionNvmGroup2->Channels[txConfig->Channel].Band].TxMaxPower );
551 uint32_t bandwidth = RegionCommonGetBandwidth( txConfig->Datarate, BandwidthsAU915 );
552 int8_t phyTxPower = 0;
553
554 // Calculate physical TX power
555 phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
556
557 // Setup the radio frequency
558 Radio.SetChannel( RegionNvmGroup2->Channels[txConfig->Channel].Frequency );
559
560 Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
561
562 // Setup maximum payload lenght of the radio driver
563 Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
564 // Update time-on-air
565 *txTimeOnAir = GetTimeOnAir( txConfig->Datarate, txConfig->PktLen );
566
567 *txPower = txPowerLimited;
568 return true;
569 }
570
RegionAU915LinkAdrReq(LinkAdrReqParams_t * linkAdrReq,int8_t * drOut,int8_t * txPowOut,uint8_t * nbRepOut,uint8_t * nbBytesParsed)571 uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
572 {
573 uint8_t status = 0x07;
574 RegionCommonLinkAdrParams_t linkAdrParams = { 0 };
575 uint8_t nextIndex = 0;
576 uint8_t bytesProcessed = 0;
577 uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
578 GetPhyParams_t getPhy;
579 PhyParam_t phyParam;
580 RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
581
582 // Initialize local copy of channels mask
583 RegionCommonChanMaskCopy( channelsMask, RegionNvmGroup2->ChannelsMask, 6 );
584
585 while( bytesProcessed < linkAdrReq->PayloadSize )
586 {
587 nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
588
589 if( nextIndex == 0 )
590 break; // break loop, since no more request has been found
591
592 // Update bytes processed
593 bytesProcessed += nextIndex;
594
595 // Revert status, as we only check the last ADR request for the channel mask KO
596 status = 0x07;
597
598 if( linkAdrParams.ChMaskCtrl == 6 )
599 {
600 // Enable all 125 kHz channels
601 channelsMask[0] = 0xFFFF;
602 channelsMask[1] = 0xFFFF;
603 channelsMask[2] = 0xFFFF;
604 channelsMask[3] = 0xFFFF;
605 // Apply chMask to channels 64 to 71
606 channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
607 }
608 else if( linkAdrParams.ChMaskCtrl == 7 )
609 {
610 // Disable all 125 kHz channels
611 channelsMask[0] = 0x0000;
612 channelsMask[1] = 0x0000;
613 channelsMask[2] = 0x0000;
614 channelsMask[3] = 0x0000;
615 // Apply chMask to channels 64 to 71
616 channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
617 }
618 else if( linkAdrParams.ChMaskCtrl == 5 )
619 {
620 // Start value for comparision
621 uint8_t bitMask = 1;
622
623 // cntChannelMask for channelsMask[0] until channelsMask[3]
624 uint8_t cntChannelMask = 0;
625
626 // i will be 1, 2, 3, ..., 7
627 for( uint8_t i = 0; i <= 7; i++ )
628 {
629 // 8 MSBs of ChMask are RFU
630 // Checking if the ChMask is set, then true
631 if( ( ( linkAdrParams.ChMask & 0x00FF ) & ( bitMask << i ) ) != 0 )
632 {
633 if( ( i % 2 ) == 0 )
634 {
635 // Enable a bank of 8 125kHz channels, 8 LSBs
636 channelsMask[cntChannelMask] |= 0x00FF;
637 // Enable the corresponding 500kHz channel
638 channelsMask[4] |= ( bitMask << i );
639 }
640 else
641 {
642 // Enable a bank of 8 125kHz channels, 8 MSBs
643 channelsMask[cntChannelMask] |= 0xFF00;
644 // Enable the corresponding 500kHz channel
645 channelsMask[4] |= ( bitMask << i );
646 // cntChannelMask increment for uneven i
647 cntChannelMask++;
648 }
649 }
650 // ChMask is not set
651 else
652 {
653 if( ( i % 2 ) == 0 )
654 {
655 // Disable a bank of 8 125kHz channels, 8 LSBs
656 channelsMask[cntChannelMask] &= 0xFF00;
657 // Disable the corresponding 500kHz channel
658 channelsMask[4] &= ~( bitMask << i );
659 }
660 else
661 {
662 // Enable a bank of 8 125kHz channels, 8 MSBs
663 channelsMask[cntChannelMask] &= 0x00FF;
664 // Disable the corresponding 500kHz channel
665 channelsMask[4] &= ~( bitMask << i );
666 // cntChannelMask increment for uneven i
667 cntChannelMask++;
668 }
669 }
670 }
671 }
672 else
673 {
674 channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
675 }
676 }
677
678 // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
679 if( ( linkAdrParams.Datarate < DR_6 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
680 {
681 status &= 0xFE; // Channel mask KO
682 }
683
684 // Get the minimum possible datarate
685 getPhy.Attribute = PHY_MIN_TX_DR;
686 getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
687 phyParam = RegionAU915GetPhyParam( &getPhy );
688
689 linkAdrVerifyParams.Status = status;
690 linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
691 linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
692 linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
693 linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
694 linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
695 linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
696 linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
697 linkAdrVerifyParams.NbChannels = AU915_MAX_NB_CHANNELS;
698 linkAdrVerifyParams.ChannelsMask = channelsMask;
699 linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
700 linkAdrVerifyParams.MaxDatarate = AU915_TX_MAX_DATARATE;
701 linkAdrVerifyParams.Channels = RegionNvmGroup2->Channels;
702 linkAdrVerifyParams.MinTxPower = AU915_MIN_TX_POWER;
703 linkAdrVerifyParams.MaxTxPower = AU915_MAX_TX_POWER;
704 linkAdrVerifyParams.Version = linkAdrReq->Version;
705
706 // Verify the parameters and update, if necessary
707 status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
708
709 // Update channelsMask if everything is correct
710 if( status == 0x07 )
711 {
712 // Copy Mask
713 RegionCommonChanMaskCopy( RegionNvmGroup2->ChannelsMask, channelsMask, 6 );
714
715 RegionNvmGroup1->ChannelsMaskRemaining[0] &= RegionNvmGroup2->ChannelsMask[0];
716 RegionNvmGroup1->ChannelsMaskRemaining[1] &= RegionNvmGroup2->ChannelsMask[1];
717 RegionNvmGroup1->ChannelsMaskRemaining[2] &= RegionNvmGroup2->ChannelsMask[2];
718 RegionNvmGroup1->ChannelsMaskRemaining[3] &= RegionNvmGroup2->ChannelsMask[3];
719 RegionNvmGroup1->ChannelsMaskRemaining[4] = RegionNvmGroup2->ChannelsMask[4];
720 RegionNvmGroup1->ChannelsMaskRemaining[5] = RegionNvmGroup2->ChannelsMask[5];
721 }
722
723 // Update status variables
724 *drOut = linkAdrParams.Datarate;
725 *txPowOut = linkAdrParams.TxPower;
726 *nbRepOut = linkAdrParams.NbRep;
727 *nbBytesParsed = bytesProcessed;
728
729 return status;
730 }
731
RegionAU915RxParamSetupReq(RxParamSetupReqParams_t * rxParamSetupReq)732 uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
733 {
734 uint8_t status = 0x07;
735
736 // Verify radio frequency
737 if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
738 {
739 status &= 0xFE; // Channel frequency KO
740 }
741
742 // Verify datarate
743 if( RegionCommonValueInRange( rxParamSetupReq->Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE ) == false )
744 {
745 status &= 0xFD; // Datarate KO
746 }
747 if( ( rxParamSetupReq->Datarate == DR_7 ) ||
748 ( rxParamSetupReq->Datarate > DR_13 ) )
749 {
750 status &= 0xFD; // Datarate KO
751 }
752
753 // Verify datarate offset
754 if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, AU915_MIN_RX1_DR_OFFSET, AU915_MAX_RX1_DR_OFFSET ) == false )
755 {
756 status &= 0xFB; // Rx1DrOffset range KO
757 }
758
759 return status;
760 }
761
RegionAU915NewChannelReq(NewChannelReqParams_t * newChannelReq)762 int8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq )
763 {
764 // Do not accept the request
765 return -1;
766 }
767
RegionAU915TxParamSetupReq(TxParamSetupReqParams_t * txParamSetupReq)768 int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
769 {
770 // Accept the request
771 return 0;
772 }
773
RegionAU915DlChannelReq(DlChannelReqParams_t * dlChannelReq)774 int8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
775 {
776 // Do not accept the request
777 return -1;
778 }
779
RegionAU915AlternateDr(int8_t currentDr,AlternateDrType_t type)780 int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )
781 {
782 // Alternates the data rate according to the channel sequence:
783 // Eight times a 125kHz DR_2 and then one 500kHz DR_6 channel
784 if( type == ALTERNATE_DR )
785 {
786 RegionNvmGroup1->JoinTrialsCounter++;
787 }
788 else
789 {
790 RegionNvmGroup1->JoinTrialsCounter--;
791 }
792
793 if( RegionNvmGroup1->JoinTrialsCounter % 9 == 0 )
794 {
795 // Use DR_6 every 9th times.
796 currentDr = DR_6;
797 }
798 else
799 {
800 currentDr = DR_2;
801 }
802 return currentDr;
803 }
804
RegionAU915NextChannel(NextChanParams_t * nextChanParams,uint8_t * channel,TimerTime_t * time,TimerTime_t * aggregatedTimeOff)805 LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
806 {
807 uint8_t nbEnabledChannels = 0;
808 uint8_t nbRestrictedChannels = 0;
809 uint8_t enabledChannels[AU915_MAX_NB_CHANNELS] = { 0 };
810 RegionCommonIdentifyChannelsParam_t identifyChannelsParam;
811 RegionCommonCountNbOfEnabledChannelsParams_t countChannelsParams;
812 LoRaMacStatus_t status = LORAMAC_STATUS_NO_CHANNEL_FOUND;
813
814 // Count 125kHz channels
815 if( RegionCommonCountChannels( RegionNvmGroup1->ChannelsMaskRemaining, 0, 4 ) == 0 )
816 { // Reactivate default channels
817 RegionCommonChanMaskCopy( RegionNvmGroup1->ChannelsMaskRemaining, RegionNvmGroup2->ChannelsMask, 4 );
818
819 RegionNvmGroup1->JoinChannelGroupsCurrentIndex = 0;
820 }
821 // Check other channels
822 if( nextChanParams->Datarate >= DR_6 )
823 {
824 if( ( RegionNvmGroup1->ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) == 0 )
825 {
826 RegionNvmGroup1->ChannelsMaskRemaining[4] = RegionNvmGroup2->ChannelsMask[4];
827 }
828 }
829
830 // Search how many channels are enabled
831 countChannelsParams.Joined = nextChanParams->Joined;
832 countChannelsParams.Datarate = nextChanParams->Datarate;
833 countChannelsParams.ChannelsMask = RegionNvmGroup1->ChannelsMaskRemaining;
834 countChannelsParams.Channels = RegionNvmGroup2->Channels;
835 countChannelsParams.Bands = RegionBands;
836 countChannelsParams.MaxNbChannels = AU915_MAX_NB_CHANNELS;
837 countChannelsParams.JoinChannels = NULL;
838
839 identifyChannelsParam.AggrTimeOff = nextChanParams->AggrTimeOff;
840 identifyChannelsParam.LastAggrTx = nextChanParams->LastAggrTx;
841 identifyChannelsParam.DutyCycleEnabled = nextChanParams->DutyCycleEnabled;
842 identifyChannelsParam.MaxBands = AU915_MAX_NB_BANDS;
843
844 identifyChannelsParam.ElapsedTimeSinceStartUp = nextChanParams->ElapsedTimeSinceStartUp;
845 identifyChannelsParam.LastTxIsJoinRequest = nextChanParams->LastTxIsJoinRequest;
846 identifyChannelsParam.ExpectedTimeOnAir = GetTimeOnAir( nextChanParams->Datarate, nextChanParams->PktLen );
847
848 identifyChannelsParam.CountNbOfEnabledChannelsParam = &countChannelsParams;
849
850 status = RegionCommonIdentifyChannels( &identifyChannelsParam, aggregatedTimeOff, enabledChannels,
851 &nbEnabledChannels, &nbRestrictedChannels, time );
852
853 if( status == LORAMAC_STATUS_OK )
854 {
855 if( nextChanParams->Joined == true )
856 {
857 // Choose randomly on of the remaining channels
858 *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
859 }
860 else
861 {
862 // For rapid network acquisition in mixed gateway channel plan environments, the device
863 // follow a random channel selection sequence. It probes alternating one out of a
864 // group of eight 125 kHz channels followed by probing one 500 kHz channel each pass.
865 // Each time a 125 kHz channel will be selected from another group.
866
867 // 125kHz Channels (0 - 63) DR2
868 if( nextChanParams->Datarate == DR_2 )
869 {
870 if( RegionBaseUSComputeNext125kHzJoinChannel( ( uint16_t* ) RegionNvmGroup1->ChannelsMaskRemaining,
871 &RegionNvmGroup1->JoinChannelGroupsCurrentIndex, channel ) == LORAMAC_STATUS_PARAMETER_INVALID )
872 {
873 return LORAMAC_STATUS_PARAMETER_INVALID;
874 }
875 }
876 // 500kHz Channels (64 - 71) DR6
877 else
878 {
879 // Choose the next available channel
880 uint8_t i = 0;
881 while( ( ( RegionNvmGroup1->ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) & ( 1 << i ) ) == 0 )
882 {
883 i++;
884 }
885 *channel = 64 + i;
886 }
887 }
888
889 // Disable the channel in the mask
890 RegionCommonChanDisable( RegionNvmGroup1->ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS );
891 }
892 return status;
893 }
894
RegionAU915ChannelAdd(ChannelAddParams_t * channelAdd)895 LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )
896 {
897 return LORAMAC_STATUS_PARAMETER_INVALID;
898 }
899
RegionAU915ChannelsRemove(ChannelRemoveParams_t * channelRemove)900 bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
901 {
902 return LORAMAC_STATUS_PARAMETER_INVALID;
903 }
904
RegionAU915ApplyDrOffset(uint8_t downlinkDwellTime,int8_t dr,int8_t drOffset)905 uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
906 {
907 int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
908
909 if( datarate < 0 )
910 {
911 if( downlinkDwellTime == 0 )
912 {
913 datarate = AU915_TX_MIN_DATARATE;
914 }
915 else
916 {
917 datarate = AU915_DWELL_LIMIT_DATARATE;
918 }
919 }
920 return datarate;
921 }
922
RegionAU915RxBeaconSetup(RxBeaconSetup_t * rxBeaconSetup,uint8_t * outDr)923 void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
924 {
925 RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
926
927 regionCommonRxBeaconSetup.Datarates = DataratesAU915;
928 regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
929 regionCommonRxBeaconSetup.BeaconSize = AU915_BEACON_SIZE;
930 regionCommonRxBeaconSetup.BeaconDatarate = AU915_BEACON_CHANNEL_DR;
931 regionCommonRxBeaconSetup.BeaconChannelBW = AU915_BEACON_CHANNEL_BW;
932 regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
933 regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
934
935 RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
936
937 // Store downlink datarate
938 *outDr = AU915_BEACON_CHANNEL_DR;
939 }
940