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