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.
 
 
 
 
 
 

940 lines
32 KiB

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