1 /*!
2 * \file radio.c
3 *
4 * \brief Radio driver API definition
5 *
6 * \copyright Revised BSD License, see section \ref LICENSE.
7 *
8 * \code
9 * ______ _
10 * / _____) _ | |
11 * ( (____ _____ ____ _| |_ _____ ____| |__
12 * \____ \| ___ | (_ _) ___ |/ ___) _ \
13 * _____) ) ____| | | || |_| ____( (___| | | |
14 * (______/|_____)_|_|_| \__)_____)\____)_| |_|
15 * (C)2013-2017 Semtech
16 *
17 * \endcode
18 *
19 * \author Miguel Luis ( Semtech )
20 *
21 * \author Gregory Cristian ( Semtech )
22 */
23 #include <math.h>
24 #include <string.h>
25 #include "utilities.h"
26 #include "timer.h"
27 #include "delay.h"
28 #include "radio.h"
29 #include "sx126x.h"
30 #include "sx126x-board.h"
31 #include "board.h"
32
33 /*!
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 * \brief Add a register to the retention list
341 *
342 * \param [in] registerAddress The address of the register to be kept in retention
343 */
344 void RadioAddRegisterToRetentionList( uint16_t registerAddress );
345
346 /*!
347 * Radio driver structure initialization
348 */
349 const struct Radio_s Radio =
350 {
351 RadioInit,
352 RadioGetStatus,
353 RadioSetModem,
354 RadioSetChannel,
355 RadioIsChannelFree,
356 RadioRandom,
357 RadioSetRxConfig,
358 RadioSetTxConfig,
359 RadioCheckRfFrequency,
360 RadioTimeOnAir,
361 RadioSend,
362 RadioSleep,
363 RadioStandby,
364 RadioRx,
365 RadioStartCad,
366 RadioSetTxContinuousWave,
367 RadioRssi,
368 RadioWrite,
369 RadioRead,
370 RadioWriteBuffer,
371 RadioReadBuffer,
372 RadioSetMaxPayloadLength,
373 RadioSetPublicNetwork,
374 RadioGetWakeupTime,
375 RadioIrqProcess,
376 // Available on SX126x only
377 RadioRxBoosted,
378 RadioSetRxDutyCycle
379 };
380
381 /*
382 * Local types definition
383 */
384
385
386 /*!
387 * FSK bandwidth definition
388 */
389 typedef struct
390 {
391 uint32_t bandwidth;
392 uint8_t RegValue;
393 }FskBandwidth_t;
394
395 /*!
396 * Precomputed FSK bandwidth registers values
397 */
398 const FskBandwidth_t FskBandwidths[] =
399 {
400 { 4800 , 0x1F },
401 { 5800 , 0x17 },
402 { 7300 , 0x0F },
403 { 9700 , 0x1E },
404 { 11700 , 0x16 },
405 { 14600 , 0x0E },
406 { 19500 , 0x1D },
407 { 23400 , 0x15 },
408 { 29300 , 0x0D },
409 { 39000 , 0x1C },
410 { 46900 , 0x14 },
411 { 58600 , 0x0C },
412 { 78200 , 0x1B },
413 { 93800 , 0x13 },
414 { 117300, 0x0B },
415 { 156200, 0x1A },
416 { 187200, 0x12 },
417 { 234300, 0x0A },
418 { 312000, 0x19 },
419 { 373600, 0x11 },
420 { 467000, 0x09 },
421 { 500000, 0x00 }, // Invalid Bandwidth
422 };
423
424 const RadioLoRaBandwidths_t Bandwidths[] = { LORA_BW_125, LORA_BW_250, LORA_BW_500 };
425
426 uint8_t MaxPayloadLength = 0xFF;
427
428 uint32_t TxTimeout = 0;
429 uint32_t RxTimeout = 0;
430
431 bool RxContinuous = false;
432
433
434 PacketStatus_t RadioPktStatus;
435 uint8_t RadioRxPayload[255];
436
437 bool IrqFired = false;
438
439 /*
440 * SX126x DIO IRQ callback functions prototype
441 */
442
443 /*!
444 * \brief DIO 0 IRQ callback
445 */
446 void RadioOnDioIrq( void* context );
447
448 /*!
449 * \brief Tx timeout timer callback
450 */
451 void RadioOnTxTimeoutIrq( void* context );
452
453 /*!
454 * \brief Rx timeout timer callback
455 */
456 void RadioOnRxTimeoutIrq( void* context );
457
458 /*
459 * Private global variables
460 */
461
462
463 /*!
464 * Holds the current network type for the radio
465 */
466 typedef struct
467 {
468 bool Previous;
469 bool Current;
470 }RadioPublicNetwork_t;
471
472 static RadioPublicNetwork_t RadioPublicNetwork = { false };
473
474 /*!
475 * Radio callbacks variable
476 */
477 static RadioEvents_t* RadioEvents;
478
479 /*
480 * Public global variables
481 */
482
483 /*!
484 * Radio hardware and global parameters
485 */
486 SX126x_t SX126x;
487
488 /*!
489 * Tx and Rx timers
490 */
491 TimerEvent_t TxTimeoutTimer;
492 TimerEvent_t RxTimeoutTimer;
493
494 /*!
495 * Returns the known FSK bandwidth registers value
496 *
497 * \param [IN] bandwidth Bandwidth value in Hz
498 * \retval regValue Bandwidth register value.
499 */
RadioGetFskBandwidthRegValue(uint32_t bandwidth)500 static uint8_t RadioGetFskBandwidthRegValue( uint32_t bandwidth )
501 {
502 uint8_t i;
503
504 if( bandwidth == 0 )
505 {
506 return( 0x1F );
507 }
508
509 for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ )
510 {
511 if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) )
512 {
513 return FskBandwidths[i+1].RegValue;
514 }
515 }
516 // ERROR: Value not found
517 while( 1 );
518 }
519
RadioInit(RadioEvents_t * events)520 void RadioInit( RadioEvents_t *events )
521 {
522 RadioEvents = events;
523
524 SX126xInit( RadioOnDioIrq );
525 SX126xSetStandby( STDBY_RC );
526 SX126xSetRegulatorMode( USE_DCDC );
527
528 SX126xSetBufferBaseAddress( 0x00, 0x00 );
529 SX126xSetTxParams( 0, RADIO_RAMP_200_US );
530 SX126xSetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
531
532 // Add registers to the retention list (4 is the maximum possible number)
533 RadioAddRegisterToRetentionList( REG_RX_GAIN );
534 RadioAddRegisterToRetentionList( REG_TX_MODULATION );
535
536 // Initialize driver timeout timers
537 TimerInit( &TxTimeoutTimer, RadioOnTxTimeoutIrq );
538 TimerInit( &RxTimeoutTimer, RadioOnRxTimeoutIrq );
539
540 IrqFired = false;
541 }
542
RadioGetStatus(void)543 RadioState_t RadioGetStatus( void )
544 {
545 switch( SX126xGetOperatingMode( ) )
546 {
547 case MODE_TX:
548 return RF_TX_RUNNING;
549 case MODE_RX:
550 return RF_RX_RUNNING;
551 case MODE_CAD:
552 return RF_CAD;
553 default:
554 return RF_IDLE;
555 }
556 }
557
RadioSetModem(RadioModems_t modem)558 void RadioSetModem( RadioModems_t modem )
559 {
560 switch( modem )
561 {
562 default:
563 case MODEM_FSK:
564 SX126xSetPacketType( PACKET_TYPE_GFSK );
565 // When switching to GFSK mode the LoRa SyncWord register value is reset
566 // Thus, we also reset the RadioPublicNetwork variable
567 RadioPublicNetwork.Current = false;
568 break;
569 case MODEM_LORA:
570 SX126xSetPacketType( PACKET_TYPE_LORA );
571 // Public/Private network register is reset when switching modems
572 if( RadioPublicNetwork.Current != RadioPublicNetwork.Previous )
573 {
574 RadioPublicNetwork.Current = RadioPublicNetwork.Previous;
575 RadioSetPublicNetwork( RadioPublicNetwork.Current );
576 }
577 break;
578 }
579 }
580
RadioSetChannel(uint32_t freq)581 void RadioSetChannel( uint32_t freq )
582 {
583 SX126xSetRfFrequency( freq );
584 }
585
RadioIsChannelFree(uint32_t freq,uint32_t rxBandwidth,int16_t rssiThresh,uint32_t maxCarrierSenseTime)586 bool RadioIsChannelFree( uint32_t freq, uint32_t rxBandwidth, int16_t rssiThresh, uint32_t maxCarrierSenseTime )
587 {
588 bool status = true;
589 int16_t rssi = 0;
590 uint32_t carrierSenseTime = 0;
591
592 RadioSetModem( MODEM_FSK );
593
594 RadioSetChannel( freq );
595
596 // Set Rx bandwidth. Other parameters are not used.
597 RadioSetRxConfig( MODEM_FSK, rxBandwidth, 600, 0, rxBandwidth, 3, 0, false,
598 0, false, 0, 0, false, true );
599 RadioRx( 0 );
600
601 DelayMs( 1 );
602
603 carrierSenseTime = TimerGetCurrentTime( );
604
605 // Perform carrier sense for maxCarrierSenseTime
606 while( TimerGetElapsedTime( carrierSenseTime ) < maxCarrierSenseTime )
607 {
608 rssi = RadioRssi( MODEM_FSK );
609
610 if( rssi > rssiThresh )
611 {
612 status = false;
613 break;
614 }
615 }
616 RadioSleep( );
617 return status;
618 }
619
RadioRandom(void)620 uint32_t RadioRandom( void )
621 {
622 uint32_t rnd = 0;
623
624 /*
625 * Radio setup for random number generation
626 */
627 // Set LoRa modem ON
628 RadioSetModem( MODEM_LORA );
629
630 // Disable LoRa modem interrupts
631 SX126xSetDioIrqParams( IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
632
633 rnd = SX126xGetRandom( );
634
635 return rnd;
636 }
637
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)638 void RadioSetRxConfig( RadioModems_t modem, uint32_t bandwidth,
639 uint32_t datarate, uint8_t coderate,
640 uint32_t bandwidthAfc, uint16_t preambleLen,
641 uint16_t symbTimeout, bool fixLen,
642 uint8_t payloadLen,
643 bool crcOn, bool freqHopOn, uint8_t hopPeriod,
644 bool iqInverted, bool rxContinuous )
645 {
646
647 RxContinuous = rxContinuous;
648 if( rxContinuous == true )
649 {
650 symbTimeout = 0;
651 }
652 if( fixLen == true )
653 {
654 MaxPayloadLength = payloadLen;
655 }
656 else
657 {
658 MaxPayloadLength = 0xFF;
659 }
660
661 switch( modem )
662 {
663 case MODEM_FSK:
664 SX126xSetStopRxTimerOnPreambleDetect( false );
665 SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;
666
667 SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;
668 SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
669 SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue( bandwidth << 1 ); // SX126x badwidth is double sided
670
671 SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
672 SX126x.PacketParams.Params.Gfsk.PreambleLength = ( preambleLen << 3 ); // convert byte into bit
673 SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
674 SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3; // convert byte into bit
675 SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
676 SX126x.PacketParams.Params.Gfsk.HeaderType = ( fixLen == true ) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
677 SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength;
678 if( crcOn == true )
679 {
680 SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
681 }
682 else
683 {
684 SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
685 }
686 SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;
687
688 RadioStandby( );
689 RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
690 SX126xSetModulationParams( &SX126x.ModulationParams );
691 SX126xSetPacketParams( &SX126x.PacketParams );
692 SX126xSetSyncWord( ( uint8_t[] ){ 0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00 } );
693 SX126xSetWhiteningSeed( 0x01FF );
694
695 RxTimeout = ( uint32_t )symbTimeout * 8000UL / datarate;
696 break;
697
698 case MODEM_LORA:
699 SX126xSetStopRxTimerOnPreambleDetect( false );
700 SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
701 SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t )datarate;
702 SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
703 SX126x.ModulationParams.Params.LoRa.CodingRate = ( RadioLoRaCodingRates_t )coderate;
704
705 if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
706 ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
707 {
708 SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
709 }
710 else
711 {
712 SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
713 }
714
715 SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;
716
717 if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) ||
718 ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) )
719 {
720 if( preambleLen < 12 )
721 {
722 SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
723 }
724 else
725 {
726 SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
727 }
728 }
729 else
730 {
731 SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
732 }
733
734 SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen;
735
736 SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
737 SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn;
738 SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted;
739
740 RadioStandby( );
741 RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
742 SX126xSetModulationParams( &SX126x.ModulationParams );
743 SX126xSetPacketParams( &SX126x.PacketParams );
744 SX126xSetLoRaSymbNumTimeout( symbTimeout );
745
746 // WORKAROUND - Optimizing the Inverted IQ Operation, see DS_SX1261-2_V1.2 datasheet chapter 15.4
747 if( SX126x.PacketParams.Params.LoRa.InvertIQ == LORA_IQ_INVERTED )
748 {
749 SX126xWriteRegister( REG_IQ_POLARITY, SX126xReadRegister( REG_IQ_POLARITY ) & ~( 1 << 2 ) );
750 }
751 else
752 {
753 SX126xWriteRegister( REG_IQ_POLARITY, SX126xReadRegister( REG_IQ_POLARITY ) | ( 1 << 2 ) );
754 }
755 // WORKAROUND END
756
757 // Timeout Max, Timeout handled directly in SetRx function
758 RxTimeout = 0xFFFF;
759
760 break;
761 }
762 }
763
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)764 void RadioSetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
765 uint32_t bandwidth, uint32_t datarate,
766 uint8_t coderate, uint16_t preambleLen,
767 bool fixLen, bool crcOn, bool freqHopOn,
768 uint8_t hopPeriod, bool iqInverted, uint32_t timeout )
769 {
770
771 switch( modem )
772 {
773 case MODEM_FSK:
774 SX126x.ModulationParams.PacketType = PACKET_TYPE_GFSK;
775 SX126x.ModulationParams.Params.Gfsk.BitRate = datarate;
776
777 SX126x.ModulationParams.Params.Gfsk.ModulationShaping = MOD_SHAPING_G_BT_1;
778 SX126x.ModulationParams.Params.Gfsk.Bandwidth = RadioGetFskBandwidthRegValue( bandwidth << 1 ); // SX126x badwidth is double sided
779 SX126x.ModulationParams.Params.Gfsk.Fdev = fdev;
780
781 SX126x.PacketParams.PacketType = PACKET_TYPE_GFSK;
782 SX126x.PacketParams.Params.Gfsk.PreambleLength = ( preambleLen << 3 ); // convert byte into bit
783 SX126x.PacketParams.Params.Gfsk.PreambleMinDetect = RADIO_PREAMBLE_DETECTOR_08_BITS;
784 SX126x.PacketParams.Params.Gfsk.SyncWordLength = 3 << 3 ; // convert byte into bit
785 SX126x.PacketParams.Params.Gfsk.AddrComp = RADIO_ADDRESSCOMP_FILT_OFF;
786 SX126x.PacketParams.Params.Gfsk.HeaderType = ( fixLen == true ) ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
787
788 if( crcOn == true )
789 {
790 SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_2_BYTES_CCIT;
791 }
792 else
793 {
794 SX126x.PacketParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
795 }
796 SX126x.PacketParams.Params.Gfsk.DcFree = RADIO_DC_FREEWHITENING;
797
798 RadioStandby( );
799 RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
800 SX126xSetModulationParams( &SX126x.ModulationParams );
801 SX126xSetPacketParams( &SX126x.PacketParams );
802 SX126xSetSyncWord( ( uint8_t[] ){ 0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00 } );
803 SX126xSetWhiteningSeed( 0x01FF );
804 break;
805
806 case MODEM_LORA:
807 SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA;
808 SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) datarate;
809 SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth];
810 SX126x.ModulationParams.Params.LoRa.CodingRate= ( RadioLoRaCodingRates_t )coderate;
811
812 if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
813 ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
814 {
815 SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01;
816 }
817 else
818 {
819 SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00;
820 }
821
822 SX126x.PacketParams.PacketType = PACKET_TYPE_LORA;
823
824 if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) ||
825 ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) )
826 {
827 if( preambleLen < 12 )
828 {
829 SX126x.PacketParams.Params.LoRa.PreambleLength = 12;
830 }
831 else
832 {
833 SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
834 }
835 }
836 else
837 {
838 SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen;
839 }
840
841 SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen;
842 SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength;
843 SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn;
844 SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted;
845
846 RadioStandby( );
847 RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA );
848 SX126xSetModulationParams( &SX126x.ModulationParams );
849 SX126xSetPacketParams( &SX126x.PacketParams );
850 break;
851 }
852
853 // WORKAROUND - Modulation Quality with 500 kHz LoRa Bandwidth, see DS_SX1261-2_V1.2 datasheet chapter 15.1
854 if( ( modem == MODEM_LORA ) && ( SX126x.ModulationParams.Params.LoRa.Bandwidth == LORA_BW_500 ) )
855 {
856 SX126xWriteRegister( REG_TX_MODULATION, SX126xReadRegister( REG_TX_MODULATION ) & ~( 1 << 2 ) );
857 }
858 else
859 {
860 SX126xWriteRegister( REG_TX_MODULATION, SX126xReadRegister( REG_TX_MODULATION ) | ( 1 << 2 ) );
861 }
862 // WORKAROUND END
863
864 SX126xSetRfTxPower( power );
865 TxTimeout = timeout;
866 }
867
RadioCheckRfFrequency(uint32_t frequency)868 bool RadioCheckRfFrequency( uint32_t frequency )
869 {
870 return true;
871 }
872
RadioGetLoRaBandwidthInHz(RadioLoRaBandwidths_t bw)873 static uint32_t RadioGetLoRaBandwidthInHz( RadioLoRaBandwidths_t bw )
874 {
875 uint32_t bandwidthInHz = 0;
876
877 switch( bw )
878 {
879 case LORA_BW_007:
880 bandwidthInHz = 7812UL;
881 break;
882 case LORA_BW_010:
883 bandwidthInHz = 10417UL;
884 break;
885 case LORA_BW_015:
886 bandwidthInHz = 15625UL;
887 break;
888 case LORA_BW_020:
889 bandwidthInHz = 20833UL;
890 break;
891 case LORA_BW_031:
892 bandwidthInHz = 31250UL;
893 break;
894 case LORA_BW_041:
895 bandwidthInHz = 41667UL;
896 break;
897 case LORA_BW_062:
898 bandwidthInHz = 62500UL;
899 break;
900 case LORA_BW_125:
901 bandwidthInHz = 125000UL;
902 break;
903 case LORA_BW_250:
904 bandwidthInHz = 250000UL;
905 break;
906 case LORA_BW_500:
907 bandwidthInHz = 500000UL;
908 break;
909 }
910
911 return bandwidthInHz;
912 }
913
RadioGetGfskTimeOnAirNumerator(uint32_t datarate,uint8_t coderate,uint16_t preambleLen,bool fixLen,uint8_t payloadLen,bool crcOn)914 static uint32_t RadioGetGfskTimeOnAirNumerator( uint32_t datarate, uint8_t coderate,
915 uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
916 bool crcOn )
917 {
918 const RadioAddressComp_t addrComp = RADIO_ADDRESSCOMP_FILT_OFF;
919 const uint8_t syncWordLength = 3;
920
921 return ( preambleLen << 3 ) +
922 ( ( fixLen == false ) ? 8 : 0 ) +
923 ( syncWordLength << 3 ) +
924 ( ( payloadLen +
925 ( addrComp == RADIO_ADDRESSCOMP_FILT_OFF ? 0 : 1 ) +
926 ( ( crcOn == true ) ? 2 : 0 )
927 ) << 3
928 );
929 }
930
RadioGetLoRaTimeOnAirNumerator(uint32_t bandwidth,uint32_t datarate,uint8_t coderate,uint16_t preambleLen,bool fixLen,uint8_t payloadLen,bool crcOn)931 static uint32_t RadioGetLoRaTimeOnAirNumerator( uint32_t bandwidth,
932 uint32_t datarate, uint8_t coderate,
933 uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
934 bool crcOn )
935 {
936 int32_t crDenom = coderate + 4;
937 bool lowDatareOptimize = false;
938
939 // Ensure that the preamble length is at least 12 symbols when using SF5 or
940 // SF6
941 if( ( datarate == 5 ) || ( datarate == 6 ) )
942 {
943 if( preambleLen < 12 )
944 {
945 preambleLen = 12;
946 }
947 }
948
949 if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) ||
950 ( ( bandwidth == 1 ) && ( datarate == 12 ) ) )
951 {
952 lowDatareOptimize = true;
953 }
954
955 int32_t ceilDenominator;
956 int32_t ceilNumerator = ( payloadLen << 3 ) +
957 ( crcOn ? 16 : 0 ) -
958 ( 4 * datarate ) +
959 ( fixLen ? 0 : 20 );
960
961 if( datarate <= 6 )
962 {
963 ceilDenominator = 4 * datarate;
964 }
965 else
966 {
967 ceilNumerator += 8;
968
969 if( lowDatareOptimize == true )
970 {
971 ceilDenominator = 4 * ( datarate - 2 );
972 }
973 else
974 {
975 ceilDenominator = 4 * datarate;
976 }
977 }
978
979 if( ceilNumerator < 0 )
980 {
981 ceilNumerator = 0;
982 }
983
984 // Perform integral ceil()
985 int32_t intermediate =
986 ( ( ceilNumerator + ceilDenominator - 1 ) / ceilDenominator ) * crDenom + preambleLen + 12;
987
988 if( datarate <= 6 )
989 {
990 intermediate += 2;
991 }
992
993 return ( uint32_t )( ( 4 * intermediate + 1 ) * ( 1 << ( datarate - 2 ) ) );
994 }
995
RadioTimeOnAir(RadioModems_t modem,uint32_t bandwidth,uint32_t datarate,uint8_t coderate,uint16_t preambleLen,bool fixLen,uint8_t payloadLen,bool crcOn)996 uint32_t RadioTimeOnAir( RadioModems_t modem, uint32_t bandwidth,
997 uint32_t datarate, uint8_t coderate,
998 uint16_t preambleLen, bool fixLen, uint8_t payloadLen,
999 bool crcOn )
1000 {
1001 uint32_t numerator = 0;
1002 uint32_t denominator = 1;
1003
1004 switch( modem )
1005 {
1006 case MODEM_FSK:
1007 {
1008 numerator = 1000U * RadioGetGfskTimeOnAirNumerator( datarate, coderate,
1009 preambleLen, fixLen,
1010 payloadLen, crcOn );
1011 denominator = datarate;
1012 }
1013 break;
1014 case MODEM_LORA:
1015 {
1016 numerator = 1000U * RadioGetLoRaTimeOnAirNumerator( bandwidth, datarate,
1017 coderate, preambleLen,
1018 fixLen, payloadLen, crcOn );
1019 denominator = RadioGetLoRaBandwidthInHz( Bandwidths[bandwidth] );
1020 }
1021 break;
1022 }
1023 // Perform integral ceil()
1024 return ( numerator + denominator - 1 ) / denominator;
1025 }
1026
RadioSend(uint8_t * buffer,uint8_t size)1027 void RadioSend( uint8_t *buffer, uint8_t size )
1028 {
1029 SX126xSetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
1030 IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
1031 IRQ_RADIO_NONE,
1032 IRQ_RADIO_NONE );
1033
1034 if( SX126xGetPacketType( ) == PACKET_TYPE_LORA )
1035 {
1036 SX126x.PacketParams.Params.LoRa.PayloadLength = size;
1037 }
1038 else
1039 {
1040 SX126x.PacketParams.Params.Gfsk.PayloadLength = size;
1041 }
1042 SX126xSetPacketParams( &SX126x.PacketParams );
1043
1044 SX126xSendPayload( buffer, size, 0 );
1045 TimerSetValue( &TxTimeoutTimer, TxTimeout );
1046 TimerStart( &TxTimeoutTimer );
1047 }
1048
RadioSleep(void)1049 void RadioSleep( void )
1050 {
1051 SleepParams_t params = { 0 };
1052
1053 params.Fields.WarmStart = 1;
1054 SX126xSetSleep( params );
1055
1056 DelayMs( 2 );
1057 }
1058
RadioStandby(void)1059 void RadioStandby( void )
1060 {
1061 SX126xSetStandby( STDBY_RC );
1062 }
1063
RadioRx(uint32_t timeout)1064 void RadioRx( uint32_t timeout )
1065 {
1066 SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
1067 IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
1068 IRQ_RADIO_NONE,
1069 IRQ_RADIO_NONE );
1070
1071 if( timeout != 0 )
1072 {
1073 TimerSetValue( &RxTimeoutTimer, timeout );
1074 TimerStart( &RxTimeoutTimer );
1075 }
1076
1077 if( RxContinuous == true )
1078 {
1079 SX126xSetRx( 0xFFFFFF ); // Rx Continuous
1080 }
1081 else
1082 {
1083 SX126xSetRx( RxTimeout << 6 );
1084 }
1085 }
1086
RadioRxBoosted(uint32_t timeout)1087 void RadioRxBoosted( uint32_t timeout )
1088 {
1089 SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
1090 IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
1091 IRQ_RADIO_NONE,
1092 IRQ_RADIO_NONE );
1093
1094 if( timeout != 0 )
1095 {
1096 TimerSetValue( &RxTimeoutTimer, timeout );
1097 TimerStart( &RxTimeoutTimer );
1098 }
1099
1100 if( RxContinuous == true )
1101 {
1102 SX126xSetRxBoosted( 0xFFFFFF ); // Rx Continuous
1103 }
1104 else
1105 {
1106 SX126xSetRxBoosted( RxTimeout << 6 );
1107 }
1108 }
1109
RadioSetRxDutyCycle(uint32_t rxTime,uint32_t sleepTime)1110 void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime )
1111 {
1112 SX126xSetRxDutyCycle( rxTime, sleepTime );
1113 }
1114
RadioAddRegisterToRetentionList(uint16_t registerAddress)1115 void RadioAddRegisterToRetentionList( uint16_t registerAddress )
1116 {
1117 uint8_t buffer[9];
1118
1119 // Read the address and registers already added to the list
1120 SX126xReadRegisters( REG_RETENTION_LIST_BASE_ADDRESS, buffer, 9 );
1121
1122 const uint8_t nbOfRegisters = buffer[0];
1123 uint8_t* registerList = &buffer[1];
1124
1125 // Check if the register given as parameter is already added to the list
1126 for( uint8_t i = 0; i < nbOfRegisters; i++ )
1127 {
1128 if( registerAddress == ( ( uint16_t ) registerList[2 * i] << 8 ) + registerList[2 * i + 1] )
1129 {
1130 return;
1131 }
1132 }
1133
1134 if( nbOfRegisters < MAX_NB_REG_IN_RETENTION )
1135 {
1136 buffer[0] += 1;
1137 registerList[2 * nbOfRegisters] = ( uint8_t )( registerAddress >> 8 );
1138 registerList[2 * nbOfRegisters + 1] = ( uint8_t )( registerAddress >> 0 );
1139
1140 // Update radio with modified list
1141 SX126xWriteRegisters( REG_RETENTION_LIST_BASE_ADDRESS, buffer, 9 );
1142 }
1143 }
1144
RadioStartCad(void)1145 void RadioStartCad( void )
1146 {
1147 SX126xSetDioIrqParams( IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_CAD_DONE | IRQ_CAD_ACTIVITY_DETECTED, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
1148 SX126xSetCad( );
1149 }
1150
RadioSetTxContinuousWave(uint32_t freq,int8_t power,uint16_t time)1151 void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
1152 {
1153 uint32_t timeout = ( uint32_t )time * 1000;
1154
1155 SX126xSetRfFrequency( freq );
1156 SX126xSetRfTxPower( power );
1157 SX126xSetTxContinuousWave( );
1158
1159 TimerSetValue( &TxTimeoutTimer, timeout );
1160 TimerStart( &TxTimeoutTimer );
1161 }
1162
RadioRssi(RadioModems_t modem)1163 int16_t RadioRssi( RadioModems_t modem )
1164 {
1165 return SX126xGetRssiInst( );
1166 }
1167
RadioWrite(uint32_t addr,uint8_t data)1168 void RadioWrite( uint32_t addr, uint8_t data )
1169 {
1170 SX126xWriteRegister( addr, data );
1171 }
1172
RadioRead(uint32_t addr)1173 uint8_t RadioRead( uint32_t addr )
1174 {
1175 return SX126xReadRegister( addr );
1176 }
1177
RadioWriteBuffer(uint32_t addr,uint8_t * buffer,uint8_t size)1178 void RadioWriteBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
1179 {
1180 SX126xWriteRegisters( addr, buffer, size );
1181 }
1182
RadioReadBuffer(uint32_t addr,uint8_t * buffer,uint8_t size)1183 void RadioReadBuffer( uint32_t addr, uint8_t *buffer, uint8_t size )
1184 {
1185 SX126xReadRegisters( addr, buffer, size );
1186 }
1187
RadioSetMaxPayloadLength(RadioModems_t modem,uint8_t max)1188 void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max )
1189 {
1190 if( modem == MODEM_LORA )
1191 {
1192 SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength = max;
1193 SX126xSetPacketParams( &SX126x.PacketParams );
1194 }
1195 else
1196 {
1197 if( SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_VARIABLE_LENGTH )
1198 {
1199 SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength = max;
1200 SX126xSetPacketParams( &SX126x.PacketParams );
1201 }
1202 }
1203 }
1204
RadioSetPublicNetwork(bool enable)1205 void RadioSetPublicNetwork( bool enable )
1206 {
1207 RadioPublicNetwork.Current = RadioPublicNetwork.Previous = enable;
1208
1209 RadioSetModem( MODEM_LORA );
1210 if( enable == true )
1211 {
1212 // Change LoRa modem SyncWord
1213 SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF );
1214 SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF );
1215 }
1216 else
1217 {
1218 // Change LoRa modem SyncWord
1219 SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF );
1220 SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF );
1221 }
1222 }
1223
RadioGetWakeupTime(void)1224 uint32_t RadioGetWakeupTime( void )
1225 {
1226 return SX126xGetBoardTcxoWakeupTime( ) + RADIO_WAKEUP_TIME;
1227 }
1228
RadioOnTxTimeoutIrq(void * context)1229 void RadioOnTxTimeoutIrq( void* context )
1230 {
1231 if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) )
1232 {
1233 RadioEvents->TxTimeout( );
1234 }
1235 }
1236
RadioOnRxTimeoutIrq(void * context)1237 void RadioOnRxTimeoutIrq( void* context )
1238 {
1239 if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
1240 {
1241 RadioEvents->RxTimeout( );
1242 }
1243 }
1244
RadioOnDioIrq(void * context)1245 void RadioOnDioIrq( void* context )
1246 {
1247 IrqFired = true;
1248 }
1249
RadioIrqProcess(void)1250 void RadioIrqProcess( void )
1251 {
1252 CRITICAL_SECTION_BEGIN( );
1253 // Clear IRQ flag
1254 const bool isIrqFired = IrqFired;
1255 IrqFired = false;
1256 CRITICAL_SECTION_END( );
1257
1258 if( isIrqFired == true )
1259 {
1260 uint16_t irqRegs = SX126xGetIrqStatus( );
1261 SX126xClearIrqStatus( irqRegs );
1262
1263 // Check if DIO1 pin is High. If it is the case revert IrqFired to true
1264 CRITICAL_SECTION_BEGIN_REPEAT( );
1265 if( SX126xGetDio1PinState( ) == 1 )
1266 {
1267 IrqFired = true;
1268 }
1269 CRITICAL_SECTION_END( );
1270
1271 if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
1272 {
1273 TimerStop( &TxTimeoutTimer );
1274 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1275 SX126xSetOperatingMode( MODE_STDBY_RC );
1276 if( ( RadioEvents != NULL ) && ( RadioEvents->TxDone != NULL ) )
1277 {
1278 RadioEvents->TxDone( );
1279 }
1280 }
1281
1282 if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
1283 {
1284 TimerStop( &RxTimeoutTimer );
1285
1286 if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
1287 {
1288 if( RxContinuous == false )
1289 {
1290 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1291 SX126xSetOperatingMode( MODE_STDBY_RC );
1292 }
1293 if( ( RadioEvents != NULL ) && ( RadioEvents->RxError ) )
1294 {
1295 RadioEvents->RxError( );
1296 }
1297 }
1298 else
1299 {
1300 uint8_t size;
1301
1302 if( RxContinuous == false )
1303 {
1304 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1305 SX126xSetOperatingMode( MODE_STDBY_RC );
1306
1307 // WORKAROUND - Implicit Header Mode Timeout Behavior, see DS_SX1261-2_V1.2 datasheet chapter 15.3
1308 SX126xWriteRegister( REG_RTC_CTRL, 0x00 );
1309 SX126xWriteRegister( REG_EVT_CLR, SX126xReadRegister( REG_EVT_CLR ) | ( 1 << 1 ) );
1310 // WORKAROUND END
1311 }
1312 SX126xGetPayload( RadioRxPayload, &size , 255 );
1313 SX126xGetPacketStatus( &RadioPktStatus );
1314 if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
1315 {
1316 RadioEvents->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt );
1317 }
1318 }
1319 }
1320
1321 if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
1322 {
1323 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1324 SX126xSetOperatingMode( MODE_STDBY_RC );
1325 if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) )
1326 {
1327 RadioEvents->CadDone( ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ) );
1328 }
1329 }
1330
1331 if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
1332 {
1333 if( SX126xGetOperatingMode( ) == MODE_TX )
1334 {
1335 TimerStop( &TxTimeoutTimer );
1336 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1337 SX126xSetOperatingMode( MODE_STDBY_RC );
1338 if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) )
1339 {
1340 RadioEvents->TxTimeout( );
1341 }
1342 }
1343 else if( SX126xGetOperatingMode( ) == MODE_RX )
1344 {
1345 TimerStop( &RxTimeoutTimer );
1346 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1347 SX126xSetOperatingMode( MODE_STDBY_RC );
1348 if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
1349 {
1350 RadioEvents->RxTimeout( );
1351 }
1352 }
1353 }
1354
1355 if( ( irqRegs & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED )
1356 {
1357 //__NOP( );
1358 }
1359
1360 if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
1361 {
1362 //__NOP( );
1363 }
1364
1365 if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
1366 {
1367 //__NOP( );
1368 }
1369
1370 if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
1371 {
1372 TimerStop( &RxTimeoutTimer );
1373 if( RxContinuous == false )
1374 {
1375 //!< Update operating mode state to a value lower than \ref MODE_STDBY_XOSC
1376 SX126xSetOperatingMode( MODE_STDBY_RC );
1377 }
1378 if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
1379 {
1380 RadioEvents->RxTimeout( );
1381 }
1382 }
1383 }
1384 }
1385