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