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