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