Implement a secure ICS protocol targeting LoRa Node151 microcontroller for controlling irrigation.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

959 lines
29 KiB

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