xref: /btstack/chipset/sx128x/SMTC_Drivers/sx1280-driver-c/sx1280.c (revision d72e9d4b1d8cea3c48e9897368c446f554491bbf)
1 /*
2   ______                              _
3  / _____)             _              | |
4 ( (____  _____ ____ _| |_ _____  ____| |__
5  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
6  _____) ) ____| | | || |_| ____( (___| | | |
7 (______/|_____)_|_|_| \__)_____)\____)_| |_|
8     (C)2016 Semtech
9 
10 Description: Driver for SX1280 devices
11 
12 License: Revised BSD License, see LICENSE.TXT file include in the project
13 
14 Maintainer: Miguel Luis, Matthieu Verdy and Benjamin Boulet
15 */
16 #include <string.h>
17 #include "sx1280.h"
18 #include "sx1280-hal.h"
19 #include "RangingCorrection.h"
20 
21 // logging on
22 #include "SEGGER_RTT.h"
23 #define printf(format, ...) SEGGER_RTT_printf(0, format,  ## __VA_ARGS__)
24 
25 
26 /*!
27  * \brief Radio registers definition
28  *
29  */
30 typedef struct
31 {
32     uint16_t      Addr;                             //!< The address of the register
33     uint8_t       Value;                            //!< The value of the register
34 }RadioRegisters_t;
35 
36 /*!
37  * \brief Radio hardware registers initialization definition
38  */
39 // { Address, RegValue }
40 #define RADIO_INIT_REGISTERS_VALUE  { 0 }
41 
42 /*!
43  * \brief Radio hardware registers initialization
44  */
45 const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;
46 
47 /*!
48  * \brief Holds the internal operating mode of the radio
49  */
50 static RadioOperatingModes_t OperatingMode;
51 
52 /*!
53  * \brief Stores the current packet type set in the radio
54  */
55 static RadioPacketTypes_t PacketType;
56 
57 /*!
58  * \brief Stores the current LoRa bandwidth set in the radio
59  */
60 static RadioLoRaBandwidths_t LoRaBandwidth;
61 
62 /*!
63  * \brief Holds the polling state of the driver
64  */
65 static bool PollingMode;
66 
67 /*!
68  * Hardware DIO IRQ callback initialization
69  */
70 DioIrqHandler *DioIrq[] = { SX1280OnDioIrq };
71 
72 void SX1280OnDioIrq( void );
73 
74 /*!
75  * \brief Holds a flag raised on radio interrupt
76  */
77 static bool IrqState;
78 
79 static RadioCallbacks_t* RadioCallbacks;
80 
81 int32_t SX1280complement2( const uint32_t num, const uint8_t bitCnt )
82 {
83     int32_t retVal = ( int32_t )num;
84     if( num >= 2<<( bitCnt - 2 ) )
85     {
86         retVal -= 2<<( bitCnt - 1 );
87     }
88     return retVal;
89 }
90 
91 void SX1280Init( RadioCallbacks_t *callbacks )
92 {
93     RadioCallbacks = callbacks;
94 
95     SX1280HalInit( DioIrq );
96 }
97 
98 void SX1280SetRegistersDefault( void )
99 {
100     for( int16_t i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ )
101     {
102         SX1280HalWriteRegister( RadioRegsInit[i].Addr, RadioRegsInit[i].Value );
103     }
104 }
105 
106 uint16_t SX1280GetFirmwareVersion( void )
107 {
108     return( ( ( SX1280HalReadRegister( REG_LR_FIRMWARE_VERSION_MSB ) ) << 8 ) | ( SX1280HalReadRegister( REG_LR_FIRMWARE_VERSION_MSB + 1 ) ) );
109 }
110 
111 RadioStatus_t SX1280GetStatus( void )
112 {
113     uint8_t stat = 0;
114     RadioStatus_t status;
115 
116     SX1280HalReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 );
117     status.Value = stat;
118     return status;
119 }
120 
121 RadioOperatingModes_t SX1280GetOpMode( void )
122 {
123     return OperatingMode;
124 }
125 
126 void SX1280SetSleep( SleepParams_t sleepConfig )
127 {
128     uint8_t sleep = ( sleepConfig.WakeUpRTC << 3 ) |
129                     ( sleepConfig.InstructionRamRetention << 2 ) |
130                     ( sleepConfig.DataBufferRetention << 1 ) |
131                     ( sleepConfig.DataRamRetention );
132 
133     OperatingMode = MODE_SLEEP;
134     SX1280HalWriteCommand( RADIO_SET_SLEEP, &sleep, 1 );
135 }
136 
137 void SX1280SetStandby( RadioStandbyModes_t standbyConfig )
138 {
139     SX1280HalWriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 );
140     if( standbyConfig == STDBY_RC )
141     {
142         OperatingMode = MODE_STDBY_RC;
143     }
144     else
145     {
146         OperatingMode = MODE_STDBY_XOSC;
147     }
148 }
149 
150 void SX1280SetFs( void )
151 {
152     SX1280HalWriteCommand( RADIO_SET_FS, 0, 0 );
153     OperatingMode = MODE_FS;
154 }
155 
156 void SX1280SetTx( TickTime_t timeout )
157 {
158     uint8_t buf[3];
159     buf[0] = timeout.Step;
160     buf[1] = ( uint8_t )( ( timeout.NbSteps >> 8 ) & 0x00FF );
161     buf[2] = ( uint8_t )( timeout.NbSteps & 0x00FF );
162 
163 // BK BEGIN - skip clear IRQ, it is cleared in process irq
164 //   SX1280ClearIrqStatus( IRQ_RADIO_ALL );
165 // BK END
166 
167     // If the radio is doing ranging operations, then apply the specific calls
168     // prior to SetTx
169     if( SX1280GetPacketType( ) == PACKET_TYPE_RANGING )
170     {
171         SX1280SetRangingRole( RADIO_RANGING_ROLE_MASTER );
172     }
173     SX1280HalWriteCommand( RADIO_SET_TX, buf, 3 );
174     OperatingMode = MODE_TX;
175 }
176 
177 void SX1280SetRx( TickTime_t timeout )
178 {
179     uint8_t buf[3];
180     buf[0] = timeout.Step;
181     buf[1] = ( uint8_t )( ( timeout.NbSteps >> 8 ) & 0x00FF );
182     buf[2] = ( uint8_t )( timeout.NbSteps & 0x00FF );
183 
184 
185 // BK BEGIN - skip clear IRQ, it is cleared in process irq
186 //    SX1280ClearIrqStatus( IRQ_RADIO_ALL );
187 // BK END
188 
189     // If the radio is doing ranging operations, then apply the specific calls
190     // prior to SetRx
191     if( SX1280GetPacketType( ) == PACKET_TYPE_RANGING )
192     {
193         SX1280SetRangingRole( RADIO_RANGING_ROLE_SLAVE );
194     }
195     SX1280HalWriteCommand( RADIO_SET_RX, buf, 3 );
196     OperatingMode = MODE_RX;
197 }
198 
199 void SX1280SetRxDutyCycle( RadioTickSizes_t Step, uint16_t NbStepRx, uint16_t RxNbStepSleep )
200 {
201     uint8_t buf[5];
202 
203     buf[0] = Step;
204     buf[1] = ( uint8_t )( ( NbStepRx >> 8 ) & 0x00FF );
205     buf[2] = ( uint8_t )( NbStepRx & 0x00FF );
206     buf[3] = ( uint8_t )( ( RxNbStepSleep >> 8 ) & 0x00FF );
207     buf[4] = ( uint8_t )( RxNbStepSleep & 0x00FF );
208     SX1280HalWriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 5 );
209     OperatingMode = MODE_RX;
210 }
211 
212 void SX1280SetCad( void )
213 {
214     SX1280HalWriteCommand( RADIO_SET_CAD, 0, 0 );
215     OperatingMode = MODE_CAD;
216 }
217 
218 void SX1280SetTxContinuousWave( void )
219 {
220     SX1280HalWriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 );
221 }
222 
223 void SX1280SetTxContinuousPreamble( void )
224 {
225     SX1280HalWriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 );
226 }
227 
228 void SX1280SetPacketType( RadioPacketTypes_t packetType )
229 {
230     // Save packet type internally to avoid questioning the radio
231     PacketType = packetType;
232 
233     SX1280HalWriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 );
234 }
235 
236 RadioPacketTypes_t SX1280GetPacketType( void )
237 {
238     return PacketType;
239 }
240 
241 void SX1280SetRfFrequency( uint32_t frequency )
242 {
243     uint8_t buf[3];
244     uint32_t freq = 0;
245 
246     freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP );
247     buf[0] = ( uint8_t )( ( freq >> 16 ) & 0xFF );
248     buf[1] = ( uint8_t )( ( freq >> 8 ) & 0xFF );
249     buf[2] = ( uint8_t )( freq & 0xFF );
250     SX1280HalWriteCommand( RADIO_SET_RFFREQUENCY, buf, 3 );
251 }
252 
253 void SX1280SetTxParams( int8_t power, RadioRampTimes_t rampTime )
254 {
255     uint8_t buf[2];
256 
257     // The power value to send on SPI/UART is in the range [0..31] and the
258     // physical output power is in the range [-18..13]dBm
259     buf[0] = power + 18;
260     buf[1] = ( uint8_t )rampTime;
261     SX1280HalWriteCommand( RADIO_SET_TXPARAMS, buf, 2 );
262 }
263 
264 void SX1280SetCadParams( RadioLoRaCadSymbols_t cadSymbolNum )
265 {
266     SX1280HalWriteCommand( RADIO_SET_CADPARAMS, ( uint8_t* )&cadSymbolNum, 1 );
267     OperatingMode = MODE_CAD;
268 }
269 
270 void SX1280SetBufferBaseAddresses( uint8_t txBaseAddress, uint8_t rxBaseAddress )
271 {
272     uint8_t buf[2];
273 
274     buf[0] = txBaseAddress;
275     buf[1] = rxBaseAddress;
276     SX1280HalWriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 );
277 }
278 
279 void SX1280SetModulationParams( ModulationParams_t *modulationParams )
280 {
281     uint8_t buf[3];
282 
283     // Check if required configuration corresponds to the stored packet type
284     // If not, silently update radio packet type
285     if( PacketType != modulationParams->PacketType )
286     {
287         SX1280SetPacketType( modulationParams->PacketType );
288     }
289 
290     switch( modulationParams->PacketType )
291     {
292         case PACKET_TYPE_GFSK:
293             buf[0] = modulationParams->Params.Gfsk.BitrateBandwidth;
294             buf[1] = modulationParams->Params.Gfsk.ModulationIndex;
295             buf[2] = modulationParams->Params.Gfsk.ModulationShaping;
296             break;
297 
298         case PACKET_TYPE_LORA:
299         case PACKET_TYPE_RANGING:
300             buf[0] = modulationParams->Params.LoRa.SpreadingFactor;
301             buf[1] = modulationParams->Params.LoRa.Bandwidth;
302             buf[2] = modulationParams->Params.LoRa.CodingRate;
303             LoRaBandwidth = modulationParams->Params.LoRa.Bandwidth;
304             break;
305 
306         case PACKET_TYPE_FLRC:
307             buf[0] = modulationParams->Params.Flrc.BitrateBandwidth;
308             buf[1] = modulationParams->Params.Flrc.CodingRate;
309             buf[2] = modulationParams->Params.Flrc.ModulationShaping;
310             break;
311 
312         case PACKET_TYPE_BLE:
313             buf[0] = modulationParams->Params.Ble.BitrateBandwidth;
314             buf[1] = modulationParams->Params.Ble.ModulationIndex;
315             buf[2] = modulationParams->Params.Ble.ModulationShaping;
316             break;
317 
318         case PACKET_TYPE_NONE:
319             buf[0] = 0;
320             buf[1] = 0;
321             buf[2] = 0;
322             break;
323     }
324     SX1280HalWriteCommand( RADIO_SET_MODULATIONPARAMS, buf, 3 );
325 }
326 
327 void SX1280SetPacketParams( PacketParams_t *packetParams )
328 {
329     uint8_t buf[7];
330 
331     // Check if required configuration corresponds to the stored packet type
332     // If not, silently update radio packet type
333     if( PacketType != packetParams->PacketType )
334     {
335         SX1280SetPacketType( packetParams->PacketType );
336     }
337 
338     switch( packetParams->PacketType )
339     {
340         case PACKET_TYPE_GFSK:
341             buf[0] = packetParams->Params.Gfsk.PreambleLength;
342             buf[1] = packetParams->Params.Gfsk.SyncWordLength;
343             buf[2] = packetParams->Params.Gfsk.SyncWordMatch;
344             buf[3] = packetParams->Params.Gfsk.HeaderType;
345             buf[4] = packetParams->Params.Gfsk.PayloadLength;
346             buf[5] = packetParams->Params.Gfsk.CrcLength;
347             buf[6] = packetParams->Params.Gfsk.Whitening;
348             break;
349 
350         case PACKET_TYPE_LORA:
351         case PACKET_TYPE_RANGING:
352             buf[0] = packetParams->Params.LoRa.PreambleLength;
353             buf[1] = packetParams->Params.LoRa.HeaderType;
354             buf[2] = packetParams->Params.LoRa.PayloadLength;
355             buf[3] = packetParams->Params.LoRa.CrcMode;
356             buf[4] = packetParams->Params.LoRa.InvertIQ;
357             buf[5] = 0;
358             buf[6] = 0;
359             break;
360 
361         case PACKET_TYPE_FLRC:
362             buf[0] = packetParams->Params.Flrc.PreambleLength;
363             buf[1] = packetParams->Params.Flrc.SyncWordLength;
364             buf[2] = packetParams->Params.Flrc.SyncWordMatch;
365             buf[3] = packetParams->Params.Flrc.HeaderType;
366             buf[4] = packetParams->Params.Flrc.PayloadLength;
367             buf[5] = packetParams->Params.Flrc.CrcLength;
368             buf[6] = packetParams->Params.Flrc.Whitening;
369             break;
370 
371         case PACKET_TYPE_BLE:
372             buf[0] = packetParams->Params.Ble.ConnectionState;
373             buf[1] = packetParams->Params.Ble.CrcField;
374             buf[2] = packetParams->Params.Ble.BlePacketType;
375             buf[3] = packetParams->Params.Ble.Whitening;
376             buf[4] = 0;
377             buf[5] = 0;
378             buf[6] = 0;
379             break;
380 
381         case PACKET_TYPE_NONE:
382             buf[0] = 0;
383             buf[1] = 0;
384             buf[2] = 0;
385             buf[3] = 0;
386             buf[4] = 0;
387             buf[5] = 0;
388             buf[6] = 0;
389             break;
390     }
391     SX1280HalWriteCommand( RADIO_SET_PACKETPARAMS, buf, 7 );
392 }
393 
394 void SX1280GetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer )
395 {
396     uint8_t status[2];
397 
398     SX1280HalReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 );
399 
400     // In case of LORA fixed header, the payloadLength is obtained by reading
401     // the register REG_LR_PAYLOADLENGTH
402     if( ( SX1280GetPacketType( ) == PACKET_TYPE_LORA ) && ( SX1280HalReadRegister( REG_LR_PACKETPARAMS ) >> 7 == 1 ) )
403     {
404         *payloadLength = SX1280HalReadRegister( REG_LR_PAYLOADLENGTH );
405     }
406     else if( SX1280GetPacketType( ) == PACKET_TYPE_BLE )
407     {
408         // In the case of BLE, the size returned in status[0] do not include the 2-byte length PDU header
409         // so it is added there
410         *payloadLength = status[0] + 2;
411     }
412     else
413     {
414         *payloadLength = status[0];
415     }
416 
417     *rxStartBufferPointer = status[1];
418 }
419 
420 void SX1280GetPacketStatus( PacketStatus_t *pktStatus )
421 {
422     uint8_t status[5];
423 
424     SX1280HalReadCommand( RADIO_GET_PACKETSTATUS, status, 5 );
425 
426     pktStatus->packetType = SX1280GetPacketType( );
427     switch( pktStatus->packetType )
428     {
429         case PACKET_TYPE_GFSK:
430             pktStatus->Params.Gfsk.RssiAvg = -status[0] / 2;
431             pktStatus->Params.Gfsk.RssiSync = -status[1] / 2;
432 
433             pktStatus->Params.Gfsk.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
434             pktStatus->Params.Gfsk.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
435             pktStatus->Params.Gfsk.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
436             pktStatus->Params.Gfsk.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
437             pktStatus->Params.Gfsk.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
438             pktStatus->Params.Gfsk.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
439             pktStatus->Params.Gfsk.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
440 
441             pktStatus->Params.Gfsk.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
442             pktStatus->Params.Gfsk.TxRxStatus.PacketSent = status[3] & 0x01;
443 
444             pktStatus->Params.Gfsk.SyncAddrStatus = status[4] & 0x07;
445             break;
446 
447         case PACKET_TYPE_LORA:
448         case PACKET_TYPE_RANGING:
449             pktStatus->Params.LoRa.RssiPkt = -status[0] / 2;
450             ( status[1] < 128 ) ? ( pktStatus->Params.LoRa.SnrPkt = status[1] / 4 ) : ( pktStatus->Params.LoRa.SnrPkt = ( ( status[1] - 256 ) /4 ) );
451 
452             pktStatus->Params.LoRa.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
453             pktStatus->Params.LoRa.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
454             pktStatus->Params.LoRa.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
455             pktStatus->Params.LoRa.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
456             pktStatus->Params.LoRa.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
457             pktStatus->Params.LoRa.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
458             pktStatus->Params.LoRa.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
459 
460             pktStatus->Params.LoRa.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
461             pktStatus->Params.LoRa.TxRxStatus.PacketSent = status[3] & 0x01;
462 
463             pktStatus->Params.LoRa.SyncAddrStatus = status[4] & 0x07;
464             break;
465 
466         case PACKET_TYPE_FLRC:
467             pktStatus->Params.Flrc.RssiAvg = -status[0] / 2;
468             pktStatus->Params.Flrc.RssiSync = -status[1] / 2;
469 
470             pktStatus->Params.Flrc.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
471             pktStatus->Params.Flrc.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
472             pktStatus->Params.Flrc.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
473             pktStatus->Params.Flrc.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
474             pktStatus->Params.Flrc.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
475             pktStatus->Params.Flrc.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
476             pktStatus->Params.Flrc.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
477 
478             pktStatus->Params.Flrc.TxRxStatus.RxPid = ( status[3] >> 6 ) & 0x03;
479             pktStatus->Params.Flrc.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
480             pktStatus->Params.Flrc.TxRxStatus.RxPidErr = ( status[3] >> 4 ) & 0x01;
481             pktStatus->Params.Flrc.TxRxStatus.PacketSent = status[3] & 0x01;
482 
483             pktStatus->Params.Flrc.SyncAddrStatus = status[4] & 0x07;
484             break;
485 
486         case PACKET_TYPE_BLE:
487             pktStatus->Params.Ble.RssiAvg = -status[0] / 2;
488             pktStatus->Params.Ble.RssiSync = -status[1] / 2;
489 
490             pktStatus->Params.Ble.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
491             pktStatus->Params.Ble.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
492             pktStatus->Params.Ble.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
493             pktStatus->Params.Ble.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
494             pktStatus->Params.Ble.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
495             pktStatus->Params.Ble.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
496             pktStatus->Params.Ble.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
497 
498             pktStatus->Params.Ble.TxRxStatus.PacketSent = status[3] & 0x01;
499 
500             pktStatus->Params.Ble.SyncAddrStatus = status[4] & 0x07;
501             break;
502 
503         case PACKET_TYPE_NONE:
504             // In that specific case, we set everything in the pktStatus to zeros
505             // and reset the packet type accordingly
506             memset( pktStatus, 0, sizeof( PacketStatus_t ) );
507             pktStatus->packetType = PACKET_TYPE_NONE;
508             break;
509     }
510 }
511 
512 int8_t SX1280GetRssiInst( void )
513 {
514     uint8_t raw = 0;
515 
516     SX1280HalReadCommand( RADIO_GET_RSSIINST, &raw, 1 );
517 
518     return ( int8_t )( -raw / 2 );
519 }
520 
521 void SX1280SetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask )
522 {
523     uint8_t buf[8];
524 
525     buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF );
526     buf[1] = ( uint8_t )( irqMask & 0x00FF );
527     buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF );
528     buf[3] = ( uint8_t )( dio1Mask & 0x00FF );
529     buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF );
530     buf[5] = ( uint8_t )( dio2Mask & 0x00FF );
531     buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF );
532     buf[7] = ( uint8_t )( dio3Mask & 0x00FF );
533     SX1280HalWriteCommand( RADIO_SET_DIOIRQPARAMS, buf, 8 );
534 }
535 
536 uint16_t SX1280GetIrqStatus( void )
537 {
538     uint8_t irqStatus[2];
539 
540     SX1280HalReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 );
541 
542     return ( irqStatus[0] << 8 ) | irqStatus[1];
543 }
544 
545 void SX1280ClearIrqStatus( uint16_t irq )
546 {
547     uint8_t buf[2];
548 
549     buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF );
550     buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF );
551     SX1280HalWriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 );
552 }
553 
554 void SX1280Calibrate( CalibrationParams_t calibParam )
555 {
556     uint8_t cal = ( calibParam.ADCBulkPEnable << 5 ) |
557                   ( calibParam.ADCBulkNEnable << 4 ) |
558                   ( calibParam.ADCPulseEnable << 3 ) |
559                   ( calibParam.PLLEnable << 2 ) |
560                   ( calibParam.RC13MEnable << 1 ) |
561                   ( calibParam.RC64KEnable );
562 
563     SX1280HalWriteCommand( RADIO_CALIBRATE, &cal, 1 );
564 }
565 
566 void SX1280SetRegulatorMode( RadioRegulatorModes_t mode )
567 {
568     SX1280HalWriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 );
569 }
570 
571 void SX1280SetSaveContext( void )
572 {
573     SX1280HalWriteCommand( RADIO_SET_SAVECONTEXT, 0, 0 );
574 }
575 
576 void SX1280SetAutoTx( uint16_t time )
577 {
578     uint16_t compensatedTime = time - ( uint16_t )AUTO_RX_TX_OFFSET;
579     uint8_t buf[2];
580 
581     buf[0] = ( uint8_t )( ( compensatedTime >> 8 ) & 0x00FF );
582     buf[1] = ( uint8_t )( compensatedTime & 0x00FF );
583     SX1280HalWriteCommand( RADIO_SET_AUTOTX, buf, 2 );
584 }
585 
586 void SX1280StopAutoTx( void )
587 {
588     uint8_t buf[2] = {0x00, 0x00};
589     SX1280HalWriteCommand( RADIO_SET_AUTOTX, buf, 2 );
590 }
591 
592 void SX1280SetAutoFS( uint8_t enable )
593 {
594     SX1280HalWriteCommand( RADIO_SET_AUTOFS, &enable, 1 );
595 }
596 
597 void SX1280SetLongPreamble( uint8_t enable )
598 {
599     SX1280HalWriteCommand( RADIO_SET_LONGPREAMBLE, &enable, 1 );
600 }
601 
602 void SX1280SetPayload( uint8_t *buffer, uint8_t size )
603 {
604     SX1280HalWriteBuffer( 0x00, buffer, size );
605 }
606 
607 uint8_t SX1280GetPayload( uint8_t *buffer, uint8_t *size , uint8_t maxSize )
608 {
609     uint8_t offset;
610 
611     SX1280GetRxBufferStatus( size, &offset );
612     if( *size > maxSize )
613     {
614         return 1;
615     }
616     SX1280HalReadBuffer( offset, buffer, *size );
617     return 0;
618 }
619 
620 void SX1280SendPayload( uint8_t *payload, uint8_t size, TickTime_t timeout )
621 {
622     SX1280SetPayload( payload, size );
623     SX1280SetTx( timeout );
624 }
625 
626 uint8_t SX1280SetSyncWord( uint8_t syncWordIdx, uint8_t *syncWord )
627 {
628     uint16_t addr;
629     uint8_t syncwordSize = 0;
630 
631     switch( SX1280GetPacketType( ) )
632     {
633         case PACKET_TYPE_GFSK:
634             syncwordSize = 5;
635             switch( syncWordIdx )
636             {
637                 case 1:
638                     addr = REG_LR_SYNCWORDBASEADDRESS1;
639                     break;
640 
641                 case 2:
642                     addr = REG_LR_SYNCWORDBASEADDRESS2;
643                     break;
644 
645                 case 3:
646                     addr = REG_LR_SYNCWORDBASEADDRESS3;
647                     break;
648 
649                 default:
650                     return 1;
651             }
652             break;
653 
654         case PACKET_TYPE_FLRC:
655             // For FLRC packet type, the SyncWord is one byte shorter and
656             // the base address is shifted by one byte
657             syncwordSize = 4;
658             switch( syncWordIdx )
659             {
660                 case 1:
661                     addr = REG_LR_SYNCWORDBASEADDRESS1 + 1;
662                     break;
663 
664                 case 2:
665                     addr = REG_LR_SYNCWORDBASEADDRESS2 + 1;
666                     break;
667 
668                 case 3:
669                     addr = REG_LR_SYNCWORDBASEADDRESS3 + 1;
670                     break;
671 
672                 default:
673                     return 1;
674             }
675             break;
676 
677         case PACKET_TYPE_BLE:
678             // For Ble packet type, only the first SyncWord is used and its
679             // address is shifted by one byte
680             syncwordSize = 4;
681             switch( syncWordIdx )
682             {
683                 case 1:
684                     addr = REG_LR_SYNCWORDBASEADDRESS1 + 1;
685                     break;
686 
687                 default:
688                     return 1;
689             }
690             break;
691 
692         default:
693             return 1;
694     }
695     SX1280HalWriteRegisters( addr, syncWord, syncwordSize );
696     return 0;
697 }
698 
699 void SX1280SetSyncWordErrorTolerance( uint8_t ErrorBits )
700 {
701     ErrorBits = ( SX1280HalReadRegister( REG_LR_SYNCWORDTOLERANCE ) & 0xF0 ) | ( ErrorBits & 0x0F );
702     SX1280HalWriteRegister( REG_LR_SYNCWORDTOLERANCE, ErrorBits );
703 }
704 
705 void SX1280SetCrcSeed( uint16_t seed )
706 {
707     uint8_t val[2];
708 
709     val[0] = ( uint8_t )( seed >> 8 ) & 0xFF;
710     val[1] = ( uint8_t )( seed  & 0xFF );
711 
712     switch( SX1280GetPacketType( ) )
713     {
714         case PACKET_TYPE_GFSK:
715         case PACKET_TYPE_FLRC:
716             SX1280HalWriteRegisters( REG_LR_CRCSEEDBASEADDR, val, 2 );
717             break;
718 
719         default:
720             break;
721     }
722 }
723 
724 void SX1280SetBleAccessAddress( uint32_t accessAddress )
725 {
726     SX1280HalWriteRegister( REG_LR_BLE_ACCESS_ADDRESS, ( accessAddress >> 24 ) & 0x000000FF );
727     SX1280HalWriteRegister( REG_LR_BLE_ACCESS_ADDRESS + 1, ( accessAddress >> 16 ) & 0x000000FF );
728     SX1280HalWriteRegister( REG_LR_BLE_ACCESS_ADDRESS + 2, ( accessAddress >> 8 ) & 0x000000FF );
729     SX1280HalWriteRegister( REG_LR_BLE_ACCESS_ADDRESS + 3, accessAddress & 0x000000FF );
730 }
731 
732 void SX1280SetBleAdvertizerAccessAddress( void )
733 {
734     SX1280SetBleAccessAddress( BLE_ADVERTIZER_ACCESS_ADDRESS );
735 }
736 
737 void SX1280SetCrcPolynomial( uint16_t polynomial )
738 {
739     uint8_t val[2];
740 
741     val[0] = ( uint8_t )( polynomial >> 8 ) & 0xFF;
742     val[1] = ( uint8_t )( polynomial  & 0xFF );
743 
744     switch( SX1280GetPacketType( ) )
745     {
746         case PACKET_TYPE_GFSK:
747         case PACKET_TYPE_FLRC:
748             SX1280HalWriteRegisters( REG_LR_CRCPOLYBASEADDR, val, 2 );
749             break;
750 
751         default:
752             break;
753     }
754 }
755 
756 void SX1280SetWhiteningSeed( uint8_t seed )
757 {
758     switch( SX1280GetPacketType( ) )
759     {
760         case PACKET_TYPE_GFSK:
761         case PACKET_TYPE_FLRC:
762         case PACKET_TYPE_BLE:
763             SX1280HalWriteRegister( REG_LR_WHITSEEDBASEADDR, seed );
764             break;
765 
766         default:
767             break;
768     }
769 }
770 
771 void SX1280EnableManualGain( void )
772 {
773     SX1280HalWriteRegister( REG_ENABLE_MANUAL_GAIN_CONTROL, SX1280HalReadRegister( REG_ENABLE_MANUAL_GAIN_CONTROL ) | MASK_MANUAL_GAIN_CONTROL );
774     SX1280HalWriteRegister( REG_DEMOD_DETECTION, SX1280HalReadRegister( REG_DEMOD_DETECTION ) & MASK_DEMOD_DETECTION );
775 }
776 
777 void SX1280DisableManualGain( void )
778 {
779     SX1280HalWriteRegister( REG_ENABLE_MANUAL_GAIN_CONTROL, SX1280HalReadRegister( REG_ENABLE_MANUAL_GAIN_CONTROL ) & ~MASK_MANUAL_GAIN_CONTROL );
780     SX1280HalWriteRegister( REG_DEMOD_DETECTION, SX1280HalReadRegister( REG_DEMOD_DETECTION ) | ~MASK_DEMOD_DETECTION );
781 }
782 
783 void SX1280SetManualGainValue( uint8_t gain )
784 {
785     SX1280HalWriteRegister( REG_MANUAL_GAIN_VALUE, ( SX1280HalReadRegister( REG_MANUAL_GAIN_VALUE ) & MASK_MANUAL_GAIN_VALUE ) | gain );
786 }
787 
788 void SX1280SetLNAGainSetting( const RadioLnaSettings_t lnaSetting )
789 {
790     switch( lnaSetting )
791     {
792         case LNA_HIGH_SENSITIVITY_MODE:
793         {
794             SX1280HalWriteRegister( REG_LNA_REGIME, SX1280HalReadRegister( REG_LNA_REGIME ) | MASK_LNA_REGIME );
795             break;
796         }
797         case LNA_LOW_POWER_MODE:
798         {
799             SX1280HalWriteRegister( REG_LNA_REGIME, SX1280HalReadRegister( REG_LNA_REGIME ) & ~MASK_LNA_REGIME );
800             break;
801         }
802     }
803 }
804 
805 void SX1280SetRangingIdLength( RadioRangingIdCheckLengths_t length )
806 {
807     switch( SX1280GetPacketType( ) )
808     {
809         case PACKET_TYPE_RANGING:
810             SX1280HalWriteRegister( REG_LR_RANGINGIDCHECKLENGTH, ( ( ( ( uint8_t )length ) & 0x03 ) << 6 ) | ( SX1280HalReadRegister( REG_LR_RANGINGIDCHECKLENGTH ) & 0x3F ) );
811             break;
812 
813         default:
814             break;
815     }
816 }
817 
818 void SX1280SetDeviceRangingAddress( uint32_t address )
819 {
820     uint8_t addrArray[] = { address >> 24, address >> 16, address >> 8, address };
821 
822     switch( SX1280GetPacketType( ) )
823     {
824         case PACKET_TYPE_RANGING:
825             SX1280HalWriteRegisters( REG_LR_DEVICERANGINGADDR, addrArray, 4 );
826             break;
827 
828         default:
829             break;
830     }
831 }
832 
833 void SX1280SetRangingRequestAddress( uint32_t address )
834 {
835     uint8_t addrArray[] = { address >> 24, address >> 16, address >> 8, address };
836 
837     switch( SX1280GetPacketType( ) )
838     {
839         case PACKET_TYPE_RANGING:
840             SX1280HalWriteRegisters( REG_LR_REQUESTRANGINGADDR, addrArray, 4 );
841             break;
842 
843         default:
844             break;
845     }
846 }
847 
848 double SX1280GetRangingResult( RadioRangingResultTypes_t resultType )
849 {
850     uint32_t valLsb = 0;
851     double val = 0.0;
852 
853     switch( SX1280GetPacketType( ) )
854     {
855         case PACKET_TYPE_RANGING:
856             SX1280SetStandby( STDBY_XOSC );
857             SX1280HalWriteRegister( 0x97F, SX1280HalReadRegister( 0x97F ) | ( 1 << 1 ) ); // enable LORA modem clock
858             SX1280HalWriteRegister( REG_LR_RANGINGRESULTCONFIG, ( SX1280HalReadRegister( REG_LR_RANGINGRESULTCONFIG ) & MASK_RANGINGMUXSEL ) | ( ( ( ( uint8_t )resultType ) & 0x03 ) << 4 ) );
859             valLsb = ( ( SX1280HalReadRegister( REG_LR_RANGINGRESULTBASEADDR ) << 16 ) | ( SX1280HalReadRegister( REG_LR_RANGINGRESULTBASEADDR + 1 ) << 8 ) | ( SX1280HalReadRegister( REG_LR_RANGINGRESULTBASEADDR + 2 ) ) );
860             SX1280SetStandby( STDBY_RC );
861 
862             // Convertion from LSB to distance. For explanation on the formula, refer to Datasheet of SX1280
863             switch( resultType )
864             {
865                 case RANGING_RESULT_RAW:
866                     // Convert the ranging LSB to distance in meter
867                     val = ( double )SX1280complement2( valLsb, 24 ) / ( double )SX1280GetLoRaBandwidth( ) * 36621.09375;
868                     break;
869 
870                 case RANGING_RESULT_AVERAGED:
871                 case RANGING_RESULT_DEBIASED:
872                 case RANGING_RESULT_FILTERED:
873                     val = ( double )valLsb * 20.0 / 100.0;
874                     break;
875 
876                 default:
877                     val = 0.0;
878             }
879             break;
880 
881         default:
882             break;
883     }
884     return val;
885 }
886 
887 uint8_t SX1280GetRangingPowerDeltaThresholdIndicator( void )
888 {
889     SX1280SetStandby( STDBY_XOSC );
890     SX1280HalWriteRegister( 0x97F, SX1280HalReadRegister( 0x97F ) | ( 1 << 1 ) ); // enable LoRa modem clock
891     SX1280HalWriteRegister( REG_LR_RANGINGRESULTCONFIG, ( SX1280HalReadRegister( REG_LR_RANGINGRESULTCONFIG ) & MASK_RANGINGMUXSEL ) | ( ( ( ( uint8_t )RANGING_RESULT_RAW ) & 0x03 ) << 4 ) ); // Select raw results
892     return SX1280HalReadRegister( REG_RANGING_RSSI );
893 }
894 
895 void SX1280SetRangingCalibration( uint16_t cal )
896 {
897     switch( SX1280GetPacketType( ) )
898     {
899         case PACKET_TYPE_RANGING:
900             SX1280HalWriteRegister( REG_LR_RANGINGRERXTXDELAYCAL, ( uint8_t )( ( cal >> 8 ) & 0xFF ) );
901             SX1280HalWriteRegister( REG_LR_RANGINGRERXTXDELAYCAL + 1, ( uint8_t )( ( cal ) & 0xFF ) );
902             break;
903 
904         default:
905             break;
906     }
907 }
908 
909 void SX1280RangingClearFilterResult( void )
910 {
911     uint8_t regVal = SX1280HalReadRegister( REG_LR_RANGINGRESULTCLEARREG );
912 
913     // To clear result, set bit 5 to 1 then to 0
914     SX1280HalWriteRegister( REG_LR_RANGINGRESULTCLEARREG, regVal | ( 1 << 5 ) );
915     SX1280HalWriteRegister( REG_LR_RANGINGRESULTCLEARREG, regVal & ( ~( 1 << 5 ) ) );
916 }
917 
918 void SX1280RangingSetFilterNumSamples( uint8_t num )
919 {
920     // Silently set 8 as minimum value
921     SX1280HalWriteRegister( REG_LR_RANGINGFILTERWINDOWSIZE, ( num < DEFAULT_RANGING_FILTER_SIZE ) ? DEFAULT_RANGING_FILTER_SIZE : num );
922 }
923 
924 int8_t SX1280ParseHexFileLine( char* line )
925 {
926     uint16_t addr;
927     uint16_t n;
928     uint8_t code;
929     uint8_t bytes[256];
930 
931     if( SX1280GetHexFileLineFields( line, bytes, &addr, &n, &code ) != 0 )
932     {
933         if( code == 0 )
934         {
935             SX1280HalWriteRegisters( addr, bytes, n );
936         }
937         if( code == 1 )
938         { // end of file
939             //return 2;
940         }
941         if( code == 2 )
942         { // begin of file
943             //return 3;
944         }
945     }
946     else
947     {
948         return 0;
949     }
950     return 1;
951 }
952 
953 void SX1280SetRangingRole( RadioRangingRoles_t role )
954 {
955     uint8_t buf[1];
956 
957     buf[0] = role;
958     SX1280HalWriteCommand( RADIO_SET_RANGING_ROLE, &buf[0], 1 );
959 }
960 
961 int8_t SX1280GetHexFileLineFields( char* line, uint8_t *bytes, uint16_t *addr, uint16_t *num, uint8_t *code )
962 {
963     uint16_t sum, len, cksum;
964     char *ptr;
965 
966     *num = 0;
967     if( line[0] != ':' )
968     {
969         return 0;
970     }
971     if( strlen( line ) < 11 )
972     {
973         return 0;
974     }
975     ptr = line + 1;
976     if( !sscanf( ptr, "%02hx", &len ) )
977     {
978         return 0;
979     }
980     ptr += 2;
981     if( strlen( line ) < ( 11 + ( len * 2 ) ) )
982     {
983         return 0;
984     }
985     if( !sscanf( ptr, "%04hx", addr ) )
986     {
987         return 0;
988     }
989     ptr += 4;
990     if( !sscanf( ptr, "%02hhx", code ) )
991     {
992         return 0;
993     }
994     ptr += 2;
995     sum = ( len & 255 ) + ( ( *addr >> 8 ) & 255 ) + ( *addr & 255 ) + ( ( *code >> 8 ) & 255 ) + ( *code & 255 );
996     while( *num != len )
997     {
998         if( !sscanf( ptr, "%02hhx", &bytes[*num] ) )
999         {
1000             return 0;
1001         }
1002         ptr += 2;
1003         sum += bytes[*num] & 255;
1004         ( *num )++;
1005         if( *num >= 256 )
1006         {
1007             return 0;
1008         }
1009     }
1010     if( !sscanf( ptr, "%02hx", &cksum ) )
1011     {
1012         return 0;
1013     }
1014     if( ( ( sum & 255 ) + ( cksum & 255 ) ) & 255 )
1015     {
1016         return 0; // checksum error
1017     }
1018 
1019     return 1;
1020 }
1021 
1022 double SX1280GetFrequencyError( )
1023 {
1024     uint8_t efeRaw[3] = {0};
1025     uint32_t efe = 0;
1026     double efeHz = 0.0;
1027 
1028     switch( SX1280GetPacketType( ) )
1029     {
1030         case PACKET_TYPE_LORA:
1031         case PACKET_TYPE_RANGING:
1032             efeRaw[0] = SX1280HalReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB );
1033             efeRaw[1] = SX1280HalReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 1 );
1034             efeRaw[2] = SX1280HalReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 2 );
1035             efe = ( efeRaw[0]<<16 ) | ( efeRaw[1]<<8 ) | efeRaw[2];
1036             efe &= REG_LR_ESTIMATED_FREQUENCY_ERROR_MASK;
1037 
1038             efeHz = 1.55 * ( double )SX1280complement2( efe, 20 ) / ( 1600.0 / ( double )SX1280GetLoRaBandwidth( ) * 1000.0 );
1039             break;
1040 
1041         case PACKET_TYPE_NONE:
1042         case PACKET_TYPE_BLE:
1043         case PACKET_TYPE_FLRC:
1044         case PACKET_TYPE_GFSK:
1045             break;
1046     }
1047 
1048     return efeHz;
1049 }
1050 
1051 void SX1280SetPollingMode( void )
1052 {
1053     PollingMode = true;
1054 }
1055 
1056 int32_t SX1280GetLoRaBandwidth( )
1057 {
1058     int32_t bwValue = 0;
1059 
1060     switch( LoRaBandwidth )
1061     {
1062         case LORA_BW_0200:
1063             bwValue = 203125;
1064             break;
1065 
1066         case LORA_BW_0400:
1067             bwValue = 406250;
1068             break;
1069 
1070         case LORA_BW_0800:
1071             bwValue = 812500;
1072             break;
1073 
1074         case LORA_BW_1600:
1075             bwValue = 1625000;
1076             break;
1077 
1078         default:
1079             bwValue = 0;
1080     }
1081     return bwValue;
1082 }
1083 
1084 double SX1280GetRangingCorrectionPerSfBwGain( const RadioLoRaSpreadingFactors_t sf, const RadioLoRaBandwidths_t bw, const int8_t gain){
1085     uint8_t sf_index, bw_index;
1086 
1087     switch(sf){
1088         case LORA_SF5:
1089             sf_index = 0;
1090             break;
1091         case LORA_SF6:
1092             sf_index = 1;
1093             break;
1094         case LORA_SF7:
1095             sf_index = 2;
1096             break;
1097         case LORA_SF8:
1098             sf_index = 3;
1099             break;
1100         case LORA_SF9:
1101             sf_index = 4;
1102             break;
1103         case LORA_SF10:
1104             sf_index = 5;
1105             break;
1106 		case LORA_SF11:
1107 			sf_index = 6;
1108 			break;
1109 		case LORA_SF12:
1110             sf_index = 7;
1111             break;
1112     }
1113     switch(bw){
1114         case LORA_BW_0400:
1115             bw_index = 0;
1116             break;
1117         case LORA_BW_0800:
1118             bw_index = 1;
1119             break;
1120         case LORA_BW_1600:
1121             bw_index = 2;
1122             break;
1123     }
1124 
1125     double correction = RangingCorrectionPerSfBwGain[sf_index][bw_index][gain];
1126     return correction;
1127 }
1128 
1129 double SX1280ComputeRangingCorrectionPolynome(const RadioLoRaSpreadingFactors_t sf, const RadioLoRaBandwidths_t bw, const double median){
1130     uint8_t sf_index, bw_index;
1131 
1132     switch(sf){
1133         case LORA_SF5:
1134             sf_index = 0;
1135             break;
1136         case LORA_SF6:
1137             sf_index = 1;
1138             break;
1139         case LORA_SF7:
1140             sf_index = 2;
1141             break;
1142         case LORA_SF8:
1143             sf_index = 3;
1144             break;
1145         case LORA_SF9:
1146             sf_index = 4;
1147             break;
1148         case LORA_SF10:
1149             sf_index = 5;
1150             break;
1151 		case LORA_SF11:
1152 			sf_index = 6;
1153 			break;
1154 		case LORA_SF12:
1155             sf_index = 7;
1156             break;
1157     }
1158     switch(bw){
1159         case LORA_BW_0400:
1160             bw_index = 0;
1161             break;
1162         case LORA_BW_0800:
1163             bw_index = 1;
1164             break;
1165         case LORA_BW_1600:
1166             bw_index = 2;
1167             break;
1168     }
1169     const RangingCorrectionPolynomes_t *polynome = RangingCorrectionPolynomesPerSfBw[sf_index][bw_index];
1170     double correctedValue = 0.0;
1171     double correctionCoeff = 0;
1172     for(uint8_t order = 0; order < polynome->order; order++){
1173         correctionCoeff = polynome->coefficients[order] * pow(median, polynome->order - order - 1);
1174         correctedValue += correctionCoeff;
1175     }
1176     return correctedValue;
1177 }
1178 
1179 void SX1280SetInterruptMode( void )
1180 {
1181     PollingMode = false;
1182 }
1183 
1184 void SX1280OnDioIrq( void )
1185 {
1186     /*
1187      * When polling mode is activated, it is up to the application to call
1188      * ProcessIrqs( ). Otherwise, the driver automatically calls ProcessIrqs( )
1189      * on radio interrupt.
1190      */
1191     if( PollingMode == true )
1192     {
1193         IrqState = true;
1194     }
1195     else
1196     {
1197         SX1280ProcessIrqs( );
1198     }
1199 }
1200 
1201 void SX1280AutoTxWillStart( void ){
1202     OperatingMode = MODE_TX;
1203 }
1204 
1205 void SX1280ProcessIrqs( void )
1206 {
1207     RadioPacketTypes_t packetType = PACKET_TYPE_NONE;
1208 
1209     if( SX1280GetOpMode( ) == MODE_SLEEP )
1210     {
1211         return; // DIO glitch on V2b :-)
1212     }
1213 
1214     if( PollingMode == true )
1215     {
1216         if( IrqState == true )
1217         {
1218             __disable_irq( );
1219             IrqState = false;
1220             __enable_irq( );
1221         }
1222         else
1223         {
1224             return;
1225         }
1226     }
1227 
1228     packetType = SX1280GetPacketType( );
1229     uint16_t irqRegs = SX1280GetIrqStatus( );
1230     SX1280ClearIrqStatus( IRQ_RADIO_ALL );
1231 
1232     switch( packetType )
1233     {
1234         case PACKET_TYPE_GFSK:
1235         case PACKET_TYPE_FLRC:
1236         case PACKET_TYPE_BLE:
1237             switch( OperatingMode )
1238             {
1239                 case MODE_RX:
1240                     if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
1241                     {
1242                         if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
1243                         {
1244                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1245                             {
1246                                 RadioCallbacks->rxError( IRQ_CRC_ERROR_CODE );
1247                             }
1248                         }
1249                         else if( ( irqRegs & IRQ_SYNCWORD_ERROR ) == IRQ_SYNCWORD_ERROR )
1250                         {
1251                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1252                             {
1253                                 RadioCallbacks->rxError( IRQ_SYNCWORD_ERROR_CODE );
1254                             }
1255                         }
1256                         else
1257                         {
1258                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxDone != NULL ) )
1259                             {
1260                                 RadioCallbacks->rxDone( );
1261                             }
1262                         }
1263                     }
1264                     if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
1265                     {
1266                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxSyncWordDone != NULL ) )
1267                         {
1268                             RadioCallbacks->rxSyncWordDone( );
1269                         }
1270                     }
1271                     if( ( irqRegs & IRQ_SYNCWORD_ERROR ) == IRQ_SYNCWORD_ERROR )
1272                     {
1273                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1274                         {
1275                             RadioCallbacks->rxError( IRQ_SYNCWORD_ERROR_CODE );
1276                         }
1277                     }
1278                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1279                     {
1280                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxTimeout != NULL ) )
1281                         {
1282                             RadioCallbacks->rxTimeout( );
1283                         }
1284                     }
1285                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
1286                     {
1287                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txDone != NULL ) )
1288                         {
1289                             RadioCallbacks->txDone( );
1290                         }
1291                     }
1292                     break;
1293                 case MODE_TX:
1294                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
1295                     {
1296                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txDone != NULL ) )
1297                         {
1298                             RadioCallbacks->txDone( );
1299                         }
1300                     }
1301                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1302                     {
1303                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txTimeout != NULL ) )
1304                         {
1305                             RadioCallbacks->txTimeout( );
1306                         }
1307                     }
1308                     break;
1309                 default:
1310                     // Unexpected IRQ: silently returns
1311                     break;
1312             }
1313             break;
1314         case PACKET_TYPE_LORA:
1315             switch( OperatingMode )
1316             {
1317                 case MODE_RX:
1318                     if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
1319                     {
1320                         if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
1321                         {
1322                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1323                             {
1324                                 RadioCallbacks->rxError( IRQ_CRC_ERROR_CODE );
1325                             }
1326                         }
1327                         else
1328                         {
1329                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxDone != NULL ) )
1330                             {
1331                                 RadioCallbacks->rxDone( );
1332                             }
1333                         }
1334                     }
1335                     if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
1336                     {
1337                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxHeaderDone != NULL ) )
1338                         {
1339                             RadioCallbacks->rxHeaderDone( );
1340                         }
1341                     }
1342                     if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
1343                     {
1344                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1345                         {
1346                             RadioCallbacks->rxError( IRQ_HEADER_ERROR_CODE );
1347                         }
1348                     }
1349                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1350                     {
1351                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxTimeout != NULL ) )
1352                         {
1353                             RadioCallbacks->rxTimeout( );
1354                         }
1355                     }
1356                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_DISCARDED ) == IRQ_RANGING_SLAVE_REQUEST_DISCARDED )
1357                     {
1358                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1359                         {
1360                             RadioCallbacks->rxError( IRQ_RANGING_ON_LORA_ERROR_CODE );
1361                         }
1362                     }
1363                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
1364                     {
1365                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txDone != NULL ) )
1366                         {
1367                             RadioCallbacks->txDone( );
1368                         }
1369                     }
1370                     break;
1371                 case MODE_TX:
1372                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
1373                     {
1374                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txDone != NULL ) )
1375                         {
1376                             RadioCallbacks->txDone( );
1377                         }
1378                     }
1379                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1380                     {
1381                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->txTimeout != NULL ) )
1382                         {
1383                             RadioCallbacks->txTimeout( );
1384                         }
1385                     }
1386                     break;
1387                 case MODE_CAD:
1388                     if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
1389                     {
1390                         if( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED )
1391                         {
1392                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->cadDone != NULL ) )
1393                             {
1394                                 RadioCallbacks->cadDone( true );
1395                             }
1396                         }
1397                         else
1398                         {
1399                             if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->cadDone != NULL ) )
1400                             {
1401                                 RadioCallbacks->cadDone( false );
1402                             }
1403                         }
1404                     }
1405                     else if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1406                     {
1407                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxTimeout != NULL ) )
1408                         {
1409                             RadioCallbacks->rxTimeout( );
1410                         }
1411                     }
1412                     break;
1413                 default:
1414                     // Unexpected IRQ: silently returns
1415                     break;
1416             }
1417             break;
1418         case PACKET_TYPE_RANGING:
1419             switch( OperatingMode )
1420             {
1421                 // MODE_RX indicates an IRQ on the Slave side
1422                 case MODE_RX:
1423                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_DISCARDED ) == IRQ_RANGING_SLAVE_REQUEST_DISCARDED )
1424                     {
1425                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1426                         {
1427                             RadioCallbacks->rangingDone( IRQ_RANGING_SLAVE_ERROR_CODE );
1428                         }
1429                     }
1430                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_VALID ) == IRQ_RANGING_SLAVE_REQUEST_VALID )
1431                     {
1432                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1433                         {
1434                             RadioCallbacks->rangingDone( IRQ_RANGING_SLAVE_VALID_CODE );
1435                         }
1436                     }
1437                     if( ( irqRegs & IRQ_RANGING_SLAVE_RESPONSE_DONE ) == IRQ_RANGING_SLAVE_RESPONSE_DONE )
1438                     {
1439                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1440                         {
1441                             RadioCallbacks->rangingDone( IRQ_RANGING_SLAVE_VALID_CODE );
1442                         }
1443                     }
1444                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1445                     {
1446                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1447                         {
1448                             RadioCallbacks->rangingDone( IRQ_RANGING_SLAVE_ERROR_CODE );
1449                         }
1450                     }
1451                     if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
1452                     {
1453                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxHeaderDone != NULL ) )
1454                         {
1455                             RadioCallbacks->rxHeaderDone( );
1456                         }
1457                     }
1458                     if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
1459                     {
1460                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rxError != NULL ) )
1461                         {
1462                             RadioCallbacks->rxError( IRQ_HEADER_ERROR_CODE );
1463                         }
1464                     }
1465                     break;
1466                 // MODE_TX indicates an IRQ on the Master side
1467                 case MODE_TX:
1468                     if( ( irqRegs & IRQ_RANGING_MASTER_RESULT_TIMEOUT ) == IRQ_RANGING_MASTER_RESULT_TIMEOUT )
1469                     {
1470                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1471                         {
1472                             RadioCallbacks->rangingDone( IRQ_RANGING_MASTER_ERROR_CODE );
1473                         }
1474                     }
1475                     if( ( irqRegs & IRQ_RANGING_MASTER_RESULT_VALID ) == IRQ_RANGING_MASTER_RESULT_VALID )
1476                     {
1477                         if( ( RadioCallbacks != NULL ) && ( RadioCallbacks->rangingDone != NULL ) )
1478                         {
1479                             RadioCallbacks->rangingDone( IRQ_RANGING_MASTER_VALID_CODE );
1480                         }
1481                     }
1482                     break;
1483                 default:
1484                     // Unexpected IRQ: silently returns
1485                     break;
1486             }
1487             break;
1488         default:
1489             // Unexpected IRQ: silently returns
1490             break;
1491     }
1492 }
1493