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