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.
 
 
 
 
 
 

1385 lines
43 KiB

  1. /*!
  2. * \file radio.c
  3. *
  4. * \brief Radio driver API definition
  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. * \endcode
  18. *
  19. * \author Miguel Luis ( Semtech )
  20. *
  21. * \author Gregory Cristian ( Semtech )
  22. */
  23. #include <math.h>
  24. #include <string.h>
  25. #include "utilities.h"
  26. #include "timer.h"
  27. #include "delay.h"
  28. #include "radio.h"
  29. #include "sx126x.h"
  30. #include "sx126x-board.h"
  31. #include "board.h"
  32. /*!
  33. * \brief Initializes the radio
  34. *
  35. * \param [IN] events Structure containing the driver callback functions
  36. */
  37. void RadioInit( RadioEvents_t *events );
  38. /*!
  39. * Return current radio status
  40. *
  41. * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]
  42. */
  43. RadioState_t RadioGetStatus( void );
  44. /*!
  45. * \brief Configures the radio with the given modem
  46. *
  47. * \param [IN] modem Modem to be used [0: FSK, 1: LoRa]
  48. */
  49. void RadioSetModem( RadioModems_t modem );
  50. /*!
  51. * \brief Sets the channel frequency
  52. *
  53. * \param [IN] freq Channel RF frequency
  54. */
  55. void RadioSetChannel( uint32_t freq );
  56. /*!
  57. * \brief Checks if the channel is free for the given time
  58. *
  59. * \remark The FSK modem is always used for this task as we can select the Rx bandwidth at will.
  60. *
  61. * \param [IN] freq Channel RF frequency in Hertz
  62. * \param [IN] rxBandwidth Rx bandwidth in Hertz
  63. * \param [IN] rssiThresh RSSI threshold in dBm
  64. * \param [IN] maxCarrierSenseTime Max time in milliseconds while the RSSI is measured
  65. *
  66. * \retval isFree [true: Channel is free, false: Channel is not free]
  67. */
  68. bool RadioIsChannelFree( uint32_t freq, uint32_t rxBandwidth, int16_t rssiThresh, uint32_t maxCarrierSenseTime );
  69. /*!
  70. * \brief Generates a 32 bits random value based on the RSSI readings
  71. *
  72. * \remark This function sets the radio in LoRa modem mode and disables
  73. * all interrupts.
  74. * After calling this function either Radio.SetRxConfig or
  75. * Radio.SetTxConfig functions must be called.
  76. *
  77. * \retval randomValue 32 bits random value
  78. */
  79. uint32_t RadioRandom( void );
  80. /*!
  81. * \brief Sets the reception parameters
  82. *
  83. * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
  84. * \param [IN] bandwidth Sets the bandwidth
  85. * FSK : >= 2600 and <= 250000 Hz
  86. * LoRa: [0: 125 kHz, 1: 250 kHz,
  87. * 2: 500 kHz, 3: Reserved]
  88. * \param [IN] datarate Sets the Datarate
  89. * FSK : 600..300000 bits/s
  90. * LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
  91. * 10: 1024, 11: 2048, 12: 4096 chips]
  92. * \param [IN] coderate Sets the coding rate (LoRa only)
  93. * FSK : N/A ( set to 0 )
  94. * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
  95. * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)
  96. * FSK : >= 2600 and <= 250000 Hz
  97. * LoRa: N/A ( set to 0 )
  98. * \param [IN] preambleLen Sets the Preamble length
  99. * FSK : Number of bytes
  100. * LoRa: Length in symbols (the hardware adds 4 more symbols)
  101. * \param [IN] symbTimeout Sets the RxSingle timeout value
  102. * FSK : timeout in number of bytes
  103. * LoRa: timeout in symbols
  104. * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
  105. * \param [IN] payloadLen Sets payload length when fixed length is used
  106. * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
  107. * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping
  108. * FSK : N/A ( set to 0 )
  109. * LoRa: [0: OFF, 1: ON]
  110. * \param [IN] HopPeriod Number of symbols between each hop
  111. * FSK : N/A ( set to 0 )
  112. * LoRa: Number of symbols
  113. * \param [IN] iqInverted Inverts IQ signals (LoRa only)
  114. * FSK : N/A ( set to 0 )
  115. * LoRa: [0: not inverted, 1: inverted]
  116. * \param [IN] rxContinuous Sets the reception in continuous mode
  117. * [false: single mode, true: continuous mode]
  118. */
  119. void RadioSetRxConfig( RadioModems_t modem, uint32_t bandwidth,
  120. uint32_t datarate, uint8_t coderate,
  121. uint32_t bandwidthAfc, uint16_t preambleLen,
  122. uint16_t symbTimeout, bool fixLen,
  123. uint8_t payloadLen,
  124. bool crcOn, bool FreqHopOn, uint8_t HopPeriod,
  125. bool iqInverted, bool rxContinuous );
  126. /*!
  127. * \brief Sets the transmission parameters
  128. *
  129. * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
  130. * \param [IN] power Sets the output power [dBm]
  131. * \param [IN] fdev Sets the frequency deviation (FSK only)
  132. * FSK : [Hz]
  133. * LoRa: 0
  134. * \param [IN] bandwidth Sets the bandwidth (LoRa only)
  135. * FSK : 0
  136. * LoRa: [0: 125 kHz, 1: 250 kHz,
  137. * 2: 500 kHz, 3: Reserved]
  138. * \param [IN] datarate Sets the Datarate
  139. * FSK : 600..300000 bits/s
  140. * LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
  141. * 10: 1024, 11: 2048, 12: 4096 chips]
  142. * \param [IN] coderate Sets the coding rate (LoRa only)
  143. * FSK : N/A ( set to 0 )
  144. * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
  145. * \param [IN] preambleLen Sets the preamble length
  146. * FSK : Number of bytes
  147. * LoRa: Length in symbols (the hardware adds 4 more symbols)
  148. * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
  149. * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON]
  150. * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping
  151. * FSK : N/A ( set to 0 )
  152. * LoRa: [0: OFF, 1: ON]
  153. * \param [IN] HopPeriod Number of symbols between each hop
  154. * FSK : N/A ( set to 0 )
  155. * LoRa: Number of symbols
  156. * \param [IN] iqInverted Inverts IQ signals (LoRa only)
  157. * FSK : N/A ( set to 0 )
  158. * LoRa: [0: not inverted, 1: inverted]
  159. * \param [IN] timeout Transmission timeout [ms]
  160. */
  161. void RadioSetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
  162. uint32_t bandwidth, uint32_t datarate,
  163. uint8_t coderate, uint16_t preambleLen,
  164. bool fixLen, bool crcOn, bool FreqHopOn,
  165. uint8_t HopPeriod, bool iqInverted, uint32_t timeout );
  166. /*!
  167. * \brief Checks if the given RF frequency is supported by the hardware
  168. *
  169. * \param [IN] frequency RF frequency to be checked
  170. * \retval isSupported [true: supported, false: unsupported]
  171. */
  172. bool RadioCheckRfFrequency( uint32_t frequency );
  173. /*!
  174. * \brief Computes the packet time on air in ms for the given payload
  175. *
  176. * \Remark Can only be called once SetRxConfig or SetTxConfig have been called
  177. *
  178. * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
  179. * \param [IN] bandwidth Sets the bandwidth
  180. * FSK : >= 2600 and <= 250000 Hz
  181. * LoRa: [0: 125 kHz, 1: 250 kHz,
  182. * 2: 500 kHz, 3: Reserved]
  183. * \param [IN] datarate Sets the Datarate
  184. * FSK : 600..300000 bits/s
  185. * LoRa: [6: 64, 7: 128, 8: 256, 9: 512,
  186. * 10: 1024, 11: 2048, 12: 4096 chips]
  187. * \param [IN] coderate Sets the coding rate (LoRa only)
  188. * FSK : N/A ( set to 0 )
  189. * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
  190. * \param [IN] preambleLen Sets the Preamble length
  191. * FSK : Number of bytes
  192. * LoRa: Length in symbols (the hardware adds 4 more symbols)
  193. * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed]
  194. * \param [IN] payloadLen Sets payload length when fixed length is used
  195. * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON]
  196. *
  197. * \retval airTime Computed airTime (ms) for the given packet payload length
  198. */
  199. uint32_t RadioTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
  200. uint32_t datarate, uint8_t coderate,
  201. uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
  202. bool crcOn );
  203. /*!
  204. * \brief Sends the buffer of size. Prepares the packet to be sent and sets
  205. * the radio in transmission
  206. *
  207. * \param [IN]: buffer Buffer pointer
  208. * \param [IN]: size Buffer size
  209. */
  210. void RadioSend( uint8_t *buffer, uint8_t size );
  211. /*!
  212. * \brief Sets the radio in sleep mode
  213. */
  214. void RadioSleep( void );
  215. /*!
  216. * \brief Sets the radio in standby mode
  217. */
  218. void RadioStandby( void );
  219. /*!
  220. * \brief Sets the radio in reception mode for the given time
  221. * \param [IN] timeout Reception timeout [ms]
  222. * [0: continuous, others timeout]
  223. */
  224. void RadioRx( uint32_t timeout );
  225. /*!
  226. * \brief Start a Channel Activity Detection
  227. */
  228. void RadioStartCad( void );
  229. /*!
  230. * \brief Sets the radio in continuous wave transmission mode
  231. *
  232. * \param [IN]: freq Channel RF frequency
  233. * \param [IN]: power Sets the output power [dBm]
  234. * \param [IN]: time Transmission mode timeout [s]
  235. */
  236. void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time );
  237. /*!
  238. * \brief Reads the current RSSI value
  239. *
  240. * \retval rssiValue Current RSSI value in [dBm]
  241. */
  242. int16_t RadioRssi( RadioModems_t modem );
  243. /*!
  244. * \brief Writes the radio register at the specified address
  245. *
  246. * \param [IN]: addr Register address
  247. * \param [IN]: data New register value
  248. */
  249. void RadioWrite( uint32_t addr, uint8_t data );
  250. /*!
  251. * \brief Reads the radio register at the specified address
  252. *
  253. * \param [IN]: addr Register address
  254. * \retval data Register value
  255. */
  256. uint8_t RadioRead( uint32_t addr );
  257. /*!
  258. * \brief Writes multiple radio registers starting at address
  259. *
  260. * \param [IN] addr First Radio register address
  261. * \param [IN] buffer Buffer containing the new register's values
  262. * \param [IN] size Number of registers to be written
  263. */
  264. void RadioWriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
  265. /*!
  266. * \brief Reads multiple radio registers starting at address
  267. *
  268. * \param [IN] addr First Radio register address
  269. * \param [OUT] buffer Buffer where to copy the registers data
  270. * \param [IN] size Number of registers to be read
  271. */
  272. void RadioReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size );
  273. /*!
  274. * \brief Sets the maximum payload length.
  275. *
  276. * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa]
  277. * \param [IN] max Maximum payload length in bytes
  278. */
  279. void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max );
  280. /*!
  281. * \brief Sets the network to public or private. Updates the sync byte.
  282. *
  283. * \remark Applies to LoRa modem only
  284. *
  285. * \param [IN] enable if true, it enables a public network
  286. */
  287. void RadioSetPublicNetwork( bool enable );
  288. /*!
  289. * \brief Gets the time required for the board plus radio to get out of sleep.[ms]
  290. *
  291. * \retval time Radio plus board wakeup time in ms.
  292. */
  293. uint32_t RadioGetWakeupTime( void );
  294. /*!
  295. * \brief Process radio irq
  296. */
  297. void RadioIrqProcess( void );
  298. /*!
  299. * \brief Sets the radio in reception mode with Max LNA gain for the given time
  300. * \param [IN] timeout Reception timeout [ms]
  301. * [0: continuous, others timeout]
  302. */
  303. void RadioRxBoosted( uint32_t timeout );
  304. /*!
  305. * \brief Sets the Rx duty cycle management parameters
  306. *
  307. * \param [in] rxTime Structure describing reception timeout value
  308. * \param [in] sleepTime Structure describing sleep timeout value
  309. */
  310. void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime );
  311. /*!
  312. * \brief Add a register to the retention list
  313. *
  314. * \param [in] registerAddress The address of the register to be kept in retention
  315. */
  316. void RadioAddRegisterToRetentionList( uint16_t registerAddress );
  317. /*!
  318. * Radio driver structure initialization
  319. */
  320. const struct Radio_s Radio =
  321. {
  322. RadioInit,
  323. RadioGetStatus,
  324. RadioSetModem,
  325. RadioSetChannel,
  326. RadioIsChannelFree,
  327. RadioRandom,
  328. RadioSetRxConfig,
  329. RadioSetTxConfig,
  330. RadioCheckRfFrequency,
  331. RadioTimeOnAir,
  332. RadioSend,
  333. RadioSleep,
  334. RadioStandby,
  335. RadioRx,
  336. RadioStartCad,
  337. RadioSetTxContinuousWave,
  338. RadioRssi,
  339. RadioWrite,
  340. RadioRead,
  341. RadioWriteBuffer,
  342. RadioReadBuffer,
  343. RadioSetMaxPayloadLength,
  344. RadioSetPublicNetwork,
  345. RadioGetWakeupTime,
  346. RadioIrqProcess,
  347. // Available on SX126x only
  348. RadioRxBoosted,
  349. RadioSetRxDutyCycle
  350. };
  351. /*
  352. * Local types definition
  353. */
  354. /*!
  355. * FSK bandwidth definition
  356. */
  357. typedef struct
  358. {
  359. uint32_t bandwidth;
  360. uint8_t RegValue;
  361. }FskBandwidth_t;
  362. /*!
  363. * Precomputed FSK bandwidth registers values
  364. */
  365. const FskBandwidth_t FskBandwidths[] =
  366. {
  367. { 4800 , 0x1F },
  368. { 5800 , 0x17 },
  369. { 7300 , 0x0F },
  370. { 9700 , 0x1E },
  371. { 11700 , 0x16 },
  372. { 14600 , 0x0E },
  373. { 19500 , 0x1D },
  374. { 23400 , 0x15 },
  375. { 29300 , 0x0D },
  376. { 39000 , 0x1C },
  377. { 46900 , 0x14 },
  378. { 58600 , 0x0C },
  379. { 78200 , 0x1B },
  380. { 93800 , 0x13 },
  381. { 117300, 0x0B },
  382. { 156200, 0x1A },
  383. { 187200, 0x12 },
  384. { 234300, 0x0A },
  385. { 312000, 0x19 },
  386. { 373600, 0x11 },
  387. { 467000, 0x09 },
  388. { 500000, 0x00 }, // Invalid Bandwidth
  389. };
  390. const RadioLoRaBandwidths_t Bandwidths[] = { LORA_BW_125, LORA_BW_250, LORA_BW_500 };
  391. uint8_t MaxPayloadLength = 0xFF;
  392. uint32_t TxTimeout = 0;
  393. uint32_t RxTimeout = 0;
  394. bool RxContinuous = false;
  395. PacketStatus_t RadioPktStatus;
  396. uint8_t RadioRxPayload[255];
  397. bool IrqFired = false;
  398. /*
  399. * SX126x DIO IRQ callback functions prototype
  400. */
  401. /*!
  402. * \brief DIO 0 IRQ callback
  403. */
  404. void RadioOnDioIrq( void* context );
  405. /*!
  406. * \brief Tx timeout timer callback
  407. */
  408. void RadioOnTxTimeoutIrq( void* context );
  409. /*!
  410. * \brief Rx timeout timer callback
  411. */
  412. void RadioOnRxTimeoutIrq( void* context );
  413. /*
  414. * Private global variables
  415. */
  416. /*!
  417. * Holds the current network type for the radio
  418. */
  419. typedef struct
  420. {
  421. bool Previous;
  422. bool Current;
  423. }RadioPublicNetwork_t;
  424. static RadioPublicNetwork_t RadioPublicNetwork = { false };
  425. /*!
  426. * Radio callbacks variable
  427. */
  428. static RadioEvents_t* RadioEvents;
  429. /*
  430. * Public global variables
  431. */
  432. /*!
  433. * Radio hardware and global parameters
  434. */
  435. SX126x_t SX126x;
  436. /*!
  437. * Tx and Rx timers
  438. */
  439. TimerEvent_t TxTimeoutTimer;
  440. TimerEvent_t RxTimeoutTimer;
  441. /*!
  442. * Returns the known FSK bandwidth registers value
  443. *
  444. * \param [IN] bandwidth Bandwidth value in Hz
  445. * \retval regValue Bandwidth register value.
  446. */
  447. static uint8_t RadioGetFskBandwidthRegValue( uint32_t bandwidth )
  448. {
  449. uint8_t i;
  450. if( bandwidth == 0 )
  451. {
  452. return( 0x1F );
  453. }
  454. for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ )
  455. {
  456. if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) )
  457. {
  458. return FskBandwidths[i+1].RegValue;
  459. }
  460. }
  461. // ERROR: Value not found
  462. while( 1 );
  463. }
  464. void RadioInit( RadioEvents_t *events )
  465. {
  466. RadioEvents = events;
  467. SX126xInit( RadioOnDioIrq );
  468. SX126xSetStandby( STDBY_RC );
  469. SX126xSetRegulatorMode( USE_DCDC );
  470. SX126xSetBufferBaseAddress( 0x00, 0x00 );
  471. SX126xSetTxParams( 0, RADIO_RAMP_200_US );
  472. SX126xSetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  473. // Add registers to the retention list (4 is the maximum possible number)
  474. RadioAddRegisterToRetentionList( REG_RX_GAIN );
  475. RadioAddRegisterToRetentionList( REG_TX_MODULATION );
  476. // Initialize driver timeout timers
  477. TimerInit( &TxTimeoutTimer, RadioOnTxTimeoutIrq );
  478. TimerInit( &RxTimeoutTimer, RadioOnRxTimeoutIrq );
  479. IrqFired = false;
  480. }
  481. RadioState_t RadioGetStatus( void )
  482. {
  483. switch( SX126xGetOperatingMode( ) )
  484. {
  485. case MODE_TX:
  486. return RF_TX_RUNNING;
  487. case MODE_RX:
  488. return RF_RX_RUNNING;
  489. case MODE_CAD:
  490. return RF_CAD;
  491. default:
  492. return RF_IDLE;
  493. }
  494. }
  495. void RadioSetModem( RadioModems_t modem )
  496. {
  497. switch( modem )
  498. {
  499. default:
  500. case MODEM_FSK:
  501. SX126xSetPacketType( PACKET_TYPE_GFSK );
  502. // When switching to GFSK mode the LoRa SyncWord register value is reset
  503. // Thus, we also reset the RadioPublicNetwork variable
  504. RadioPublicNetwork.Current = false;
  505. break;
  506. case MODEM_LORA:
  507. SX126xSetPacketType( PACKET_TYPE_LORA );
  508. // Public/Private network register is reset when switching modems
  509. if( RadioPublicNetwork.Current != RadioPublicNetwork.Previous )
  510. {
  511. RadioPublicNetwork.Current = RadioPublicNetwork.Previous;
  512. RadioSetPublicNetwork( RadioPublicNetwork.Current );
  513. }
  514. break;
  515. }
  516. }
  517. void RadioSetChannel( uint32_t freq )
  518. {
  519. SX126xSetRfFrequency( freq );
  520. }
  521. bool RadioIsChannelFree( uint32_t freq, uint32_t rxBandwidth, int16_t rssiThresh, uint32_t maxCarrierSenseTime )
  522. {
  523. bool status = true;
  524. int16_t rssi = 0;
  525. uint32_t carrierSenseTime = 0;
  526. RadioSetModem( MODEM_FSK );
  527. RadioSetChannel( freq );
  528. // Set Rx bandwidth. Other parameters are not used.
  529. RadioSetRxConfig( MODEM_FSK, rxBandwidth, 600, 0, rxBandwidth, 3, 0, false,
  530. 0, false, 0, 0, false, true );
  531. RadioRx( 0 );
  532. DelayMs( 1 );
  533. carrierSenseTime = TimerGetCurrentTime( );
  534. // Perform carrier sense for maxCarrierSenseTime
  535. while( TimerGetElapsedTime( carrierSenseTime ) < maxCarrierSenseTime )
  536. {
  537. rssi = RadioRssi( MODEM_FSK );
  538. if( rssi > rssiThresh )
  539. {
  540. status = false;
  541. break;
  542. }
  543. }
  544. RadioSleep( );
  545. return status;
  546. }
  547. uint32_t RadioRandom( void )
  548. {
  549. uint32_t rnd = 0;
  550. /*
  551. * Radio setup for random number generation
  552. */
  553. // Set LoRa modem ON
  554. RadioSetModem( MODEM_LORA );
  555. // Disable LoRa modem interrupts
  556. SX126xSetDioIrqParams( IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  557. rnd = SX126xGetRandom( );
  558. return rnd;
  559. }
  560. void RadioSetRxConfig( RadioModems_t modem, uint32_t bandwidth,
  561. uint32_t datarate, uint8_t coderate,
  562. uint32_t bandwidthAfc, uint16_t preambleLen,
  563. uint16_t symbTimeout, bool fixLen,
  564. uint8_t payloadLen,
  565. bool crcOn, bool freqHopOn, uint8_t hopPeriod,
  566. bool iqInverted, bool rxContinuous )
  567. {
  568. RxContinuous = rxContinuous;
  569. if( rxContinuous == true )
  570. {
  571. symbTimeout = 0;
  572. }
  573. if( fixLen == true )
  574. {
  575. MaxPayloadLength = payloadLen;
  576. }
  577. else
  578. {
  579. MaxPayloadLength = 0xFF;
  580. }
  581. switch( modem )
  582. {
  583. case MODEM_FSK:
  584. SX126xSetStopRxTimerOnPreambleDetect( false );
  585. SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;
  586. SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;
  587. SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
  588. SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue( bandwidth << 1 ); // SX126x badwidth is double sided
  589. SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
  590. SX126x.PacketParams.Params.Gfsk.PreambleLength = ( preambleLen << 3 ); // convert byte into bit
  591. SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
  592. SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3; // convert byte into bit
  593. SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
  594. SX126x.PacketParams.Params.Gfsk.HeaderType = ( fixLen == true ) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
  595. SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength;
  596. if( crcOn == true )
  597. {
  598. SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
  599. }
  600. else
  601. {
  602. SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
  603. }
  604. SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;
  605. RadioStandby( );
  606. RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
  607. SX126xSetModulationParams( &SX126x.ModulationParams );
  608. SX126xSetPacketParams( &SX126x.PacketParams );
  609. SX126xSetSyncWord( ( uint8_t[] ){ 0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00 } );
  610. SX126xSetWhiteningSeed( 0x01FF );
  611. RxTimeout = ( uint32_t )symbTimeout * 8000UL / datarate;
  612. break;
  613. case MODEM_LORA:
  614. SX126xSetStopRxTimerOnPreambleDetect( false );
  615. SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
  616. SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t )datarate;
  617. SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
  618. SX126x.ModulationParams.Params.LoRa.CodingRate = ( RadioLoRaCodingRates_t )coderate;
  619. if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
  620. ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
  621. {
  622. SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
  623. }
  624. else
  625. {
  626. SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
  627. }
  628. SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;
  629. if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) ||
  630. ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) )
  631. {
  632. if( preambleLen < 12 )
  633. {
  634. SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
  635. }
  636. else
  637. {
  638. SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
  639. }
  640. }
  641. else
  642. {
  643. SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
  644. }
  645. SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen;
  646. SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
  647. SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn;
  648. SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted;
  649. RadioStandby( );
  650. RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
  651. SX126xSetModulationParams( &SX126x.ModulationParams );
  652. SX126xSetPacketParams( &SX126x.PacketParams );
  653. SX126xSetLoRaSymbNumTimeout( symbTimeout );
  654. // WORKAROUND - Optimizing the Inverted IQ Operation, see DS_SX1261-2_V1.2 datasheet chapter 15.4
  655. if( SX126x.PacketParams.Params.LoRa.InvertIQ == LORA_IQ_INVERTED )
  656. {
  657. SX126xWriteRegister( REG_IQ_POLARITY, SX126xReadRegister( REG_IQ_POLARITY ) & ~( 1 << 2 ) );
  658. }
  659. else
  660. {
  661. SX126xWriteRegister( REG_IQ_POLARITY, SX126xReadRegister( REG_IQ_POLARITY ) | ( 1 << 2 ) );
  662. }
  663. // WORKAROUND END
  664. // Timeout Max, Timeout handled directly in SetRx function
  665. RxTimeout = 0xFFFF;
  666. break;
  667. }
  668. }
  669. void RadioSetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
  670. uint32_t bandwidth, uint32_t datarate,
  671. uint8_t coderate, uint16_t preambleLen,
  672. bool fixLen, bool crcOn, bool freqHopOn,
  673. uint8_t hopPeriod, bool iqInverted, uint32_t timeout )
  674. {
  675. switch( modem )
  676. {
  677. case MODEM_FSK:
  678. SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;
  679. SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;
  680. SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
  681. SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue( bandwidth << 1 ); // SX126x badwidth is double sided
  682. SX126x.ModulationParams.Params.Gfsk.Fdev = fdev;
  683. SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
  684. SX126x.PacketParams.Params.Gfsk.PreambleLength = ( preambleLen << 3 ); // convert byte into bit
  685. SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
  686. SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3 ; // convert byte into bit
  687. SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
  688. SX126x.PacketParams.Params.Gfsk.HeaderType = ( fixLen == true ) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
  689. if( crcOn == true )
  690. {
  691. SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
  692. }
  693. else
  694. {
  695. SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
  696. }
  697. SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;
  698. RadioStandby( );
  699. RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
  700. SX126xSetModulationParams( &SX126x.ModulationParams );
  701. SX126xSetPacketParams( &SX126x.PacketParams );
  702. SX126xSetSyncWord( ( uint8_t[] ){ 0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00 } );
  703. SX126xSetWhiteningSeed( 0x01FF );
  704. break;
  705. case MODEM_LORA:
  706. SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
  707. SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) datarate;
  708. SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
  709. SX126x.ModulationParams.Params.LoRa.CodingRate= ( RadioLoRaCodingRates_t )coderate;
  710. if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
  711. ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
  712. {
  713. SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
  714. }
  715. else
  716. {
  717. SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
  718. }
  719. SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;
  720. if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) ||
  721. ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) )
  722. {
  723. if( preambleLen < 12 )
  724. {
  725. SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
  726. }
  727. else
  728. {
  729. SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
  730. }
  731. }
  732. else
  733. {
  734. SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
  735. }
  736. SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen;
  737. SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
  738. SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn;
  739. SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted;
  740. RadioStandby( );
  741. RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
  742. SX126xSetModulationParams( &SX126x.ModulationParams );
  743. SX126xSetPacketParams( &SX126x.PacketParams );
  744. break;
  745. }
  746. // WORKAROUND - Modulation Quality with 500 kHz LoRa Bandwidth, see DS_SX1261-2_V1.2 datasheet chapter 15.1
  747. if( ( modem == MODEM_LORA ) && ( SX126x.ModulationParams.Params.LoRa.Bandwidth == LORA_BW_500 ) )
  748. {
  749. SX126xWriteRegister( REG_TX_MODULATION, SX126xReadRegister( REG_TX_MODULATION ) & ~( 1 << 2 ) );
  750. }
  751. else
  752. {
  753. SX126xWriteRegister( REG_TX_MODULATION, SX126xReadRegister( REG_TX_MODULATION ) | ( 1 << 2 ) );
  754. }
  755. // WORKAROUND END
  756. SX126xSetRfTxPower( power );
  757. TxTimeout = timeout;
  758. }
  759. bool RadioCheckRfFrequency( uint32_t frequency )
  760. {
  761. return true;
  762. }
  763. static uint32_t RadioGetLoRaBandwidthInHz( RadioLoRaBandwidths_t bw )
  764. {
  765. uint32_t bandwidthInHz = 0;
  766. switch( bw )
  767. {
  768. case LORA_BW_007:
  769. bandwidthInHz = 7812UL;
  770. break;
  771. case LORA_BW_010:
  772. bandwidthInHz = 10417UL;
  773. break;
  774. case LORA_BW_015:
  775. bandwidthInHz = 15625UL;
  776. break;
  777. case LORA_BW_020:
  778. bandwidthInHz = 20833UL;
  779. break;
  780. case LORA_BW_031:
  781. bandwidthInHz = 31250UL;
  782. break;
  783. case LORA_BW_041:
  784. bandwidthInHz = 41667UL;
  785. break;
  786. case LORA_BW_062:
  787. bandwidthInHz = 62500UL;
  788. break;
  789. case LORA_BW_125:
  790. bandwidthInHz = 125000UL;
  791. break;
  792. case LORA_BW_250:
  793. bandwidthInHz = 250000UL;
  794. break;
  795. case LORA_BW_500:
  796. bandwidthInHz = 500000UL;
  797. break;
  798. }
  799. return bandwidthInHz;
  800. }
  801. static uint32_t RadioGetGfskTimeOnAirNumerator( uint32_t datarate, uint8_t coderate,
  802. uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
  803. bool crcOn )
  804. {
  805. const RadioAddressComp_t addrComp = RADIO_ADDRESSCOMP_FILT_OFF;
  806. const uint8_t syncWordLength = 3;
  807. return ( preambleLen << 3 ) +
  808. ( ( fixLen == false ) ? 8 : 0 ) +
  809. ( syncWordLength << 3 ) +
  810. ( ( payloadLen +
  811. ( addrComp == RADIO_ADDRESSCOMP_FILT_OFF ? 0 : 1 ) +
  812. ( ( crcOn == true ) ? 2 : 0 )
  813. ) << 3
  814. );
  815. }
  816. static uint32_t RadioGetLoRaTimeOnAirNumerator( uint32_t bandwidth,
  817. uint32_t datarate, uint8_t coderate,
  818. uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
  819. bool crcOn )
  820. {
  821. int32_t crDenom = coderate + 4;
  822. bool lowDatareOptimize = false;
  823. // Ensure that the preamble length is at least 12 symbols when using SF5 or
  824. // SF6
  825. if( ( datarate == 5 ) || ( datarate == 6 ) )
  826. {
  827. if( preambleLen < 12 )
  828. {
  829. preambleLen = 12;
  830. }
  831. }
  832. if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
  833. ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
  834. {
  835. lowDatareOptimize = true;
  836. }
  837. int32_t ceilDenominator;
  838. int32_t ceilNumerator = ( payloadLen << 3 ) +
  839. ( crcOn ? 16 : 0 ) -
  840. ( 4 * datarate ) +
  841. ( fixLen ? 0 : 20 );
  842. if( datarate <= 6 )
  843. {
  844. ceilDenominator = 4 * datarate;
  845. }
  846. else
  847. {
  848. ceilNumerator += 8;
  849. if( lowDatareOptimize == true )
  850. {
  851. ceilDenominator = 4 * ( datarate - 2 );
  852. }
  853. else
  854. {
  855. ceilDenominator = 4 * datarate;
  856. }
  857. }
  858. if( ceilNumerator < 0 )
  859. {
  860. ceilNumerator = 0;
  861. }
  862. // Perform integral ceil()
  863. int32_t intermediate =
  864. ( ( ceilNumerator + ceilDenominator - 1 ) / ceilDenominator ) * crDenom + preambleLen + 12;
  865. if( datarate <= 6 )
  866. {
  867. intermediate += 2;
  868. }
  869. return ( uint32_t )( ( 4 * intermediate + 1 ) * ( 1 << ( datarate - 2 ) ) );
  870. }
  871. uint32_t RadioTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
  872. uint32_t datarate, uint8_t coderate,
  873. uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
  874. bool crcOn )
  875. {
  876. uint32_t numerator = 0;
  877. uint32_t denominator = 1;
  878. switch( modem )
  879. {
  880. case MODEM_FSK:
  881. {
  882. numerator = 1000U * RadioGetGfskTimeOnAirNumerator( datarate, coderate,
  883. preambleLen, fixLen,
  884. payloadLen, crcOn );
  885. denominator = datarate;
  886. }
  887. break;
  888. case MODEM_LORA:
  889. {
  890. numerator = 1000U * RadioGetLoRaTimeOnAirNumerator( bandwidth, datarate,
  891. coderate, preambleLen,
  892. fixLen, payloadLen, crcOn );
  893. denominator = RadioGetLoRaBandwidthInHz( Bandwidths[bandwidth] );
  894. }
  895. break;
  896. }
  897. // Perform integral ceil()
  898. return ( numerator + denominator - 1 ) / denominator;
  899. }
  900. void RadioSend( uint8_t *buffer, uint8_t size )
  901. {
  902. SX126xSetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
  903. IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
  904. IRQ_RADIO_NONE,
  905. IRQ_RADIO_NONE );
  906. if( SX126xGetPacketType( ) == PACKET_TYPE_LORA )
  907. {
  908. SX126x.PacketParams.Params.LoRa.PayloadLength = size;
  909. }
  910. else
  911. {
  912. SX126x.PacketParams.Params.Gfsk.PayloadLength = size;
  913. }
  914. SX126xSetPacketParams( &SX126x.PacketParams );
  915. SX126xSendPayload( buffer, size, 0 );
  916. TimerSetValue( &TxTimeoutTimer, TxTimeout );
  917. TimerStart( &TxTimeoutTimer );
  918. }
  919. void RadioSleep( void )
  920. {
  921. SleepParams_t params = { 0 };
  922. params.Fields.WarmStart = 1;
  923. SX126xSetSleep( params );
  924. DelayMs( 2 );
  925. }
  926. void RadioStandby( void )
  927. {
  928. SX126xSetStandby( STDBY_RC );
  929. }
  930. void RadioRx( uint32_t timeout )
  931. {
  932. SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
  933. IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
  934. IRQ_RADIO_NONE,
  935. IRQ_RADIO_NONE );
  936. if( timeout != 0 )
  937. {
  938. TimerSetValue( &RxTimeoutTimer, timeout );
  939. TimerStart( &RxTimeoutTimer );
  940. }
  941. if( RxContinuous == true )
  942. {
  943. SX126xSetRx( 0xFFFFFF ); // Rx Continuous
  944. }
  945. else
  946. {
  947. SX126xSetRx( RxTimeout << 6 );
  948. }
  949. }
  950. void RadioRxBoosted( uint32_t timeout )
  951. {
  952. SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
  953. IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
  954. IRQ_RADIO_NONE,
  955. IRQ_RADIO_NONE );
  956. if( timeout != 0 )
  957. {
  958. TimerSetValue( &RxTimeoutTimer, timeout );
  959. TimerStart( &RxTimeoutTimer );
  960. }
  961. if( RxContinuous == true )
  962. {
  963. SX126xSetRxBoosted( 0xFFFFFF ); // Rx Continuous
  964. }
  965. else
  966. {
  967. SX126xSetRxBoosted( RxTimeout << 6 );
  968. }
  969. }
  970. void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime )
  971. {
  972. SX126xSetRxDutyCycle( rxTime, sleepTime );
  973. }
  974. void RadioAddRegisterToRetentionList( uint16_t registerAddress )
  975. {
  976. uint8_t buffer[9];
  977. // Read the address and registers already added to the list
  978. SX126xReadRegisters( REG_RETENTION_LIST_BASE_ADDRESS, buffer, 9 );
  979. const uint8_t nbOfRegisters = buffer[0];
  980. uint8_t* registerList = &buffer[1];
  981. // Check if the register given as parameter is already added to the list
  982. for( uint8_t i = 0; i < nbOfRegisters; i++ )
  983. {
  984. if( registerAddress == ( ( uint16_t ) registerList[2 * i] << 8 ) + registerList[2 * i + 1] )
  985. {
  986. return;
  987. }
  988. }
  989. if( nbOfRegisters < MAX_NB_REG_IN_RETENTION )
  990. {
  991. buffer[0] += 1;
  992. registerList[2 * nbOfRegisters] = ( uint8_t )( registerAddress >> 8 );
  993. registerList[2 * nbOfRegisters + 1] = ( uint8_t )( registerAddress >> 0 );
  994. // Update radio with modified list
  995. SX126xWriteRegisters( REG_RETENTION_LIST_BASE_ADDRESS, buffer, 9 );
  996. }
  997. }
  998. void RadioStartCad( void )
  999. {
  1000. SX126xSetDioIrqParams( IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  1001. SX126xSetCad( );
  1002. }
  1003. void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
  1004. {
  1005. uint32_t timeout = ( uint32_t )time * 1000;
  1006. SX126xSetRfFrequency( freq );
  1007. SX126xSetRfTxPower( power );
  1008. SX126xSetTxContinuousWave( );
  1009. TimerSetValue( &TxTimeoutTimer, timeout );
  1010. TimerStart( &TxTimeoutTimer );
  1011. }
  1012. int16_t RadioRssi( RadioModems_t modem )
  1013. {
  1014. return SX126xGetRssiInst( );
  1015. }
  1016. void RadioWrite( uint32_t addr, uint8_t data )
  1017. {
  1018. SX126xWriteRegister( addr, data );
  1019. }
  1020. uint8_t RadioRead( uint32_t addr )
  1021. {
  1022. return SX126xReadRegister( addr );
  1023. }
  1024. void RadioWriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
  1025. {
  1026. SX126xWriteRegisters( addr, buffer, size );
  1027. }
  1028. void RadioReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
  1029. {
  1030. SX126xReadRegisters( addr, buffer, size );
  1031. }
  1032. void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max )
  1033. {
  1034. if( modem == MODEM_LORA )
  1035. {
  1036. SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength = max;
  1037. SX126xSetPacketParams( &SX126x.PacketParams );
  1038. }
  1039. else
  1040. {
  1041. if( SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_VARIABLE_LENGTH )
  1042. {
  1043. SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength = max;
  1044. SX126xSetPacketParams( &SX126x.PacketParams );
  1045. }
  1046. }
  1047. }
  1048. void RadioSetPublicNetwork( bool enable )
  1049. {
  1050. RadioPublicNetwork.Current = RadioPublicNetwork.Previous = enable;
  1051. RadioSetModem( MODEM_LORA );
  1052. if( enable == true )
  1053. {
  1054. // Change LoRa modem SyncWord
  1055. SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF );
  1056. SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF );
  1057. }
  1058. else
  1059. {
  1060. // Change LoRa modem SyncWord
  1061. SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF );
  1062. SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF );
  1063. }
  1064. }
  1065. uint32_t RadioGetWakeupTime( void )
  1066. {
  1067. return SX126xGetBoardTcxoWakeupTime( ) + RADIO_WAKEUP_TIME;
  1068. }
  1069. void RadioOnTxTimeoutIrq( void* context )
  1070. {
  1071. if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) )
  1072. {
  1073. RadioEvents->TxTimeout( );
  1074. }
  1075. }
  1076. void RadioOnRxTimeoutIrq( void* context )
  1077. {
  1078. if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
  1079. {
  1080. RadioEvents->RxTimeout( );
  1081. }
  1082. }
  1083. void RadioOnDioIrq( void* context )
  1084. {
  1085. IrqFired = true;
  1086. }
  1087. void RadioIrqProcess( void )
  1088. {
  1089. CRITICAL_SECTION_BEGIN( );
  1090. // Clear IRQ flag
  1091. const bool isIrqFired = IrqFired;
  1092. IrqFired = false;
  1093. CRITICAL_SECTION_END( );
  1094. if( isIrqFired == true )
  1095. {
  1096. uint16_t irqRegs = SX126xGetIrqStatus( );
  1097. SX126xClearIrqStatus( irqRegs );
  1098. // Check if DIO1 pin is High. If it is the case revert IrqFired to true
  1099. CRITICAL_SECTION_BEGIN( );
  1100. if( SX126xGetDio1PinState( ) == 1 )
  1101. {
  1102. IrqFired = true;
  1103. }
  1104. CRITICAL_SECTION_END( );
  1105. if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
  1106. {
  1107. TimerStop( &TxTimeoutTimer );
  1108. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1109. SX126xSetOperatingMode( MODE_STDBY_RC );
  1110. if( ( RadioEvents != NULL ) && ( RadioEvents->TxDone != NULL ) )
  1111. {
  1112. RadioEvents->TxDone( );
  1113. }
  1114. }
  1115. if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
  1116. {
  1117. TimerStop( &RxTimeoutTimer );
  1118. if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
  1119. {
  1120. if( RxContinuous == false )
  1121. {
  1122. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1123. SX126xSetOperatingMode( MODE_STDBY_RC );
  1124. }
  1125. if( ( RadioEvents != NULL ) && ( RadioEvents->RxError ) )
  1126. {
  1127. RadioEvents->RxError( );
  1128. }
  1129. }
  1130. else
  1131. {
  1132. uint8_t size;
  1133. if( RxContinuous == false )
  1134. {
  1135. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1136. SX126xSetOperatingMode( MODE_STDBY_RC );
  1137. // WORKAROUND - Implicit Header Mode Timeout Behavior, see DS_SX1261-2_V1.2 datasheet chapter 15.3
  1138. SX126xWriteRegister( REG_RTC_CTRL, 0x00 );
  1139. SX126xWriteRegister( REG_EVT_CLR, SX126xReadRegister( REG_EVT_CLR ) | ( 1 << 1 ) );
  1140. // WORKAROUND END
  1141. }
  1142. SX126xGetPayload( RadioRxPayload, &size , 255 );
  1143. SX126xGetPacketStatus( &RadioPktStatus );
  1144. if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
  1145. {
  1146. RadioEvents->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt );
  1147. }
  1148. }
  1149. }
  1150. if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
  1151. {
  1152. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1153. SX126xSetOperatingMode( MODE_STDBY_RC );
  1154. if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) )
  1155. {
  1156. RadioEvents->CadDone( ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ) );
  1157. }
  1158. }
  1159. if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
  1160. {
  1161. if( SX126xGetOperatingMode( ) == MODE_TX )
  1162. {
  1163. TimerStop( &TxTimeoutTimer );
  1164. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1165. SX126xSetOperatingMode( MODE_STDBY_RC );
  1166. if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) )
  1167. {
  1168. RadioEvents->TxTimeout( );
  1169. }
  1170. }
  1171. else if( SX126xGetOperatingMode( ) == MODE_RX )
  1172. {
  1173. TimerStop( &RxTimeoutTimer );
  1174. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1175. SX126xSetOperatingMode( MODE_STDBY_RC );
  1176. if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
  1177. {
  1178. RadioEvents->RxTimeout( );
  1179. }
  1180. }
  1181. }
  1182. if( ( irqRegs & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED )
  1183. {
  1184. //__NOP( );
  1185. }
  1186. if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
  1187. {
  1188. //__NOP( );
  1189. }
  1190. if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
  1191. {
  1192. //__NOP( );
  1193. }
  1194. if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
  1195. {
  1196. TimerStop( &RxTimeoutTimer );
  1197. if( RxContinuous == false )
  1198. {
  1199. //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
  1200. SX126xSetOperatingMode( MODE_STDBY_RC );
  1201. }
  1202. if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
  1203. {
  1204. RadioEvents->RxTimeout( );
  1205. }
  1206. }
  1207. }
  1208. }