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