GCC Code Coverage Report


Directory: ../../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 52.9% 136 / 0 / 257
Functions: 75.0% 15 / 0 / 20
Branches: 25.0% 26 / 0 / 104

driver/lora/lora.c
Line Branch Exec Source
1 /*******************************************************************************
2 *
3 * FILE:
4 * lora.c
5 *
6 * DESCRIPTION:
7 * Contains API functions for transmating and receiving from the board's
8 * built-in LoRa module.
9 *
10 * COPYRIGHT:
11 * Copyright (c) 2025 Sun Devil Rocketry.
12 * All rights reserved.
13 *
14 * This software is licensed under terms that can be found in the LICENSE
15 * file in the root directory of this software component.
16 * If no LICENSE file comes with this software, it is covered under the
17 * BSD-3-Clause.
18 *
19 * https://opensource.org/license/bsd-3-clause
20 *
21 *******************************************************************************/
22
23
24 /*------------------------------------------------------------------------------
25 Standard Includes
26 ------------------------------------------------------------------------------*/
27 #include <string.h>
28
29 /*------------------------------------------------------------------------------
30 MCU Pins
31 ------------------------------------------------------------------------------*/
32 #if defined( FLIGHT_COMPUTER )
33 #include "sdr_pin_defines_A0002.h"
34 #include "led.h"
35 #elif defined( GROUND_STATION )
36 #include "sdr_pin_defines_A0005.h"
37 #include "led.h"
38 #elif defined( A0010 )
39 #include "sdr_pin_defines_A0010.h"
40 #include "led.h"
41 #endif
42
43 /*------------------------------------------------------------------------------
44 Project Inlcudes
45 ------------------------------------------------------------------------------*/
46 #include "lora.h"
47 #include "usb.h"
48 #include "main.h"
49
50 /*------------------------------------------------------------------------------
51 Global Variables
52 ------------------------------------------------------------------------------*/
53 static LORA_STATUS lora_rx_done = LORA_WAITING;
54 static bool is_lora_configured = false;
55
56 /*------------------------------------------------------------------------------
57 Internal function prototypes
58 ------------------------------------------------------------------------------*/
59 /*******************************************************************************
60 * *
61 * PROCEDURE: *
62 * LORA_SPI_Receive *
63 * *
64 * DESCRIPTION: *
65 * Wrapper function for HAL SPI transmit *
66 * *
67 *******************************************************************************/
68 12 static LORA_STATUS LORA_SPI_Receive
69 (
70 uint8_t* read_buffer_ptr
71 )
72 {
73 /*------------------------------------------------------------------------------
74 Local variables
75 ------------------------------------------------------------------------------*/
76 12 HAL_StatusTypeDef status;
77
78 /*------------------------------------------------------------------------------
79 Implementation
80 ------------------------------------------------------------------------------*/
81
82 /* Takes pointer to the read buffer. and puts output there */
83 12 status = HAL_SPI_Receive( &(LORA_SPI), read_buffer_ptr, 1, LORA_TIMEOUT );
84
85
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if ( status == HAL_OK )
86 {
87 /* Successful initializaiton */
88 12 return LORA_OK;
89 }
90
91 /* Failed initialization */
92 return LORA_FAIL;
93 }
94
95 12 static LORA_STATUS LORA_SPI_Transmit_Byte
96 (
97 uint8_t byte
98 )
99 {
100 /*------------------------------------------------------------------------------
101 Local Variables
102 ------------------------------------------------------------------------------*/
103 12 HAL_StatusTypeDef status;
104
105 /*------------------------------------------------------------------------------
106 Implementation
107 ------------------------------------------------------------------------------*/
108 /* Takes register and data to write (1 byte) and writes that register. */
109 12 status = HAL_SPI_Transmit( &(LORA_SPI), &byte, 1, LORA_TIMEOUT);
110
111
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (status == HAL_OK)
112 {
113 /* SPI transmpit successful */
114 12 return LORA_OK;
115 }
116
117 return LORA_FAIL;
118 }
119
120 /*******************************************************************************
121 * *
122 * PROCEDURE: *
123 * LORA_SPI_Transmit_Data *
124 * *
125 * DESCRIPTION: *
126 * Transmit data over SPI *
127 * *
128 *******************************************************************************/
129 18 static LORA_STATUS LORA_SPI_Transmit_Data
130 (
131 LORA_REGISTER_ADDR reg,
132 uint8_t data
133 )
134 {
135 18 HAL_StatusTypeDef status;
136
137 /* Takes register and data to write and writes that register. */
138 18 uint8_t transmitBuffer[2] = { reg, data };
139 18 status = HAL_SPI_Transmit( &(LORA_SPI), &transmitBuffer[0], 2, LORA_TIMEOUT);
140
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (status == HAL_OK){
142 return LORA_OK;
143 ✗ } else return LORA_FAIL;
144 }
145
146 /*******************************************************************************
147 * *
148 * PROCEDURE: *
149 * lora_read_register *
150 * *
151 * DESCRIPTION: *
152 * Read internal modem register *
153 * *
154 *******************************************************************************/
155 12 static LORA_STATUS lora_read_register
156 (
157 LORA_REGISTER_ADDR lora_register,
158 uint8_t* pRegData
159 )
160 {
161 12 LORA_STATUS transmit_status, receive_status;
162
163 12 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
164
165 12 transmit_status = LORA_SPI_Transmit_Byte( (lora_register & 0x7F) );
166 12 receive_status = LORA_SPI_Receive( pRegData );
167
168 12 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET );
169
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (transmit_status + receive_status == 0){
171 return LORA_OK;
172 } else {
173 ✗ return LORA_FAIL;
174 }
175 }
176
177 /*******************************************************************************
178 * *
179 * PROCEDURE: *
180 * lora_read_register_buffer *
181 * *
182 * DESCRIPTION: *
183 * Read buffer from internal modem register *
184 * *
185 *******************************************************************************/
186 ✗ static LORA_STATUS lora_read_register_buffer
187 (
188 LORA_REGISTER_ADDR lora_register,
189 uint8_t* pRegData,
190 uint8_t buffer_len
191 )
192 {
193 ✗ LORA_STATUS status;
194 ✗ HAL_StatusTypeDef hal_status;
195
196 ✗ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
197
198 ✗ status = LORA_SPI_Transmit_Byte( (lora_register & 0x7F) );
199 ✗ if( status != LORA_OK )
200 return LORA_FAIL;
201
202 ✗ hal_status = HAL_SPI_Receive( &(LORA_SPI), pRegData, buffer_len, LORA_TIMEOUT );
203 ✗ if( hal_status != HAL_OK )
204 return LORA_FAIL;
205
206 ✗ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET );
207
208 ✗ return LORA_OK;
209 }
210
211 /*******************************************************************************
212 * *
213 * PROCEDURE: *
214 * lora_write_register *
215 * *
216 * DESCRIPTION: *
217 * Write internal modem register *
218 * *
219 *******************************************************************************/
220 18 static LORA_STATUS lora_write_register
221 (
222 LORA_REGISTER_ADDR lora_register,
223 uint8_t data
224 )
225 {
226 18 LORA_STATUS status;
227
228 18 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
229
230 18 status = LORA_SPI_Transmit_Data( (lora_register | 0x80), data );
231
232 18 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET );
233
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ( status == LORA_OK )
235 return LORA_OK;
236 ✗ else return LORA_FAIL;
237 }
238
239 /*******************************************************************************
240 * *
241 * PROCEDURE: *
242 * lora_write_register_buffer *
243 * *
244 * DESCRIPTION: *
245 * Write internal modem register with data buffer *
246 * *
247 *******************************************************************************/
248 ✗ static LORA_STATUS lora_write_register_buffer
249 (
250 LORA_REGISTER_ADDR lora_register,
251 uint8_t* data,
252 uint8_t buffer_len
253 )
254 {
255 ✗ HAL_StatusTypeDef status;
256
257 ✗ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
258
259 // SPI write regester we are writing
260 ✗ uint8_t dest_reg = (lora_register | 0x80);
261 ✗ status = HAL_SPI_Transmit( &(LORA_SPI), &dest_reg, 1, LORA_TIMEOUT);
262 ✗ if ( status != HAL_OK )
263 return LORA_FAIL;
264
265 // Write desire buffer
266 ✗ status = HAL_SPI_Transmit( &(LORA_SPI), data, buffer_len, LORA_TIMEOUT);
267 ✗ if ( status != HAL_OK )
268 return LORA_FAIL;
269
270 ✗ HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET );
271
272
273 ✗ return LORA_OK;
274 }
275
276
277 /*******************************************************************************
278 * *
279 * PROCEDURE: *
280 * lora_is_lora_initialized *
281 * *
282 * DESCRIPTION: *
283 * Determine initialization state of LoRa modem. *
284 * *
285 *******************************************************************************/
286 1 bool lora_is_lora_initialized
287 (
288 void
289 )
290 {
291 1 return is_lora_configured;
292
293 } /* lora_is_lora_initialized */
294
295
296 /*******************************************************************************
297 * *
298 * PROCEDURE: *
299 * lora_cmd_execute *
300 * *
301 * DESCRIPTION: *
302 * Execute a LoRa terminal command. *
303 * *
304 *******************************************************************************/
305 1 LORA_STATUS lora_cmd_execute
306 (
307 uint8_t subcommand_code,
308 LORA_PRESET* lora_preset_buf
309 )
310 {
311
1/3
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (subcommand_code)
312 {
313 /*-------------------------------------------------------------
314 Upload Preset (to FC)
315 -------------------------------------------------------------*/
316 1 case LORA_PRESET_UPLOAD:
317 {
318 /* Recieve preset subcommand over USB */
319 1 uint8_t data_receive_buffer[sizeof( LORA_PRESET )];
320
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if (usb_receive( data_receive_buffer,
321 sizeof( LORA_PRESET ),
322 10 * HAL_DEFAULT_TIMEOUT ) == USB_OK)
323 {
324 /* Copy received data into preset data */
325 1 memcpy(lora_preset_buf, data_receive_buffer, sizeof( LORA_PRESET ) );
326 1 return LORA_OK;
327 }
328 else
329 {
330 /* lora presets remain untouched if usb receive fails */
331 return LORA_FAIL;
332 }
333 }
334 /*-------------------------------------------------------------
335 Download Preset (from FC)
336 -------------------------------------------------------------*/
337 ✗ case LORA_PRESET_DOWNLOAD:
338 {
339 /* tx straight from buffer (usb transmit does not modify the buffer) */
340 ✗ if( usb_transmit( lora_preset_buf, sizeof( LORA_PRESET ), 10 * HAL_DEFAULT_TIMEOUT ) == USB_OK )
341 {
342 return LORA_OK;
343 }
344 else
345 {
346 ✗ return LORA_FAIL;
347 }
348 }
349 /*-------------------------------------------------------------
350 Unrecognized command code
351 -------------------------------------------------------------*/
352 default:
353 {
354 return LORA_FAIL;
355 }
356 }
357
358 } /* lora_cmd_execute */
359
360
361 /*******************************************************************************
362 * *
363 * PROCEDURE: *
364 * lora_configure *
365 * *
366 * DESCRIPTION: *
367 * Configure and re-initialize the lora modem. *
368 * *
369 *******************************************************************************/
370 2 LORA_STATUS lora_configure
371 (
372 LORA_PRESET* preset
373 )
374 {
375 2 LORA_CONFIG lora_config;
376 2 LORA_STATUS lora_status = LORA_OK;
377
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 memset( &lora_config, 0, sizeof( lora_config ) );
378
379 /* Set app-dependent (non-configurable) parameters. */
380 // ETS TEMP: We may elect to change these later, but this
381 // is what we're using for now.
382 2 lora_config.lora_header_mode = LORA_EXPLICIT_HEADER;
383 2 lora_config.lora_mode = LORA_STANDBY_MODE;
384
385 /* Make sure presets are neither all 0xFF nor all 0x00 for validity */
386
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if( preset )
387 {
388 /* 00 buffer check */
389 2 uint8_t cmp_buf[sizeof(LORA_PRESET)];
390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 memset(cmp_buf, 0x00, sizeof(LORA_PRESET));
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!memcmp(cmp_buf, preset, sizeof(LORA_PRESET)))
392 {
393 ✗ preset = NULL;
394 }
395
396 /* FF buffer check */
397
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 memset(cmp_buf, 0xFF, sizeof(LORA_PRESET));
398
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (preset && !memcmp(cmp_buf, preset, sizeof(LORA_PRESET)))
399 {
400 ✗ preset = NULL;
401 }
402 }
403
404 /* Check if presets exist. If so, we'll use them. Else, prepare defaults. */
405 ✗ if( !preset )
406 {
407 /* drew's most frequently tested parameters. in particular, 915 will help us see that these are the defaults */
408 ✗ lora_config.lora_bandwidth = LORA_BANDWIDTH_125_KHZ;
409 ✗ lora_config.lora_ecr = LORA_ECR_4_5;
410 ✗ lora_config.lora_frequency = 915000;
411 ✗ lora_config.lora_spread = LORA_SPREAD_12;
412 ✗ lora_config.lora_pa_select = false;
413
414 ✗ lora_status = LORA_USING_DEFAULTS;
415 }
416 else
417 {
418 2 lora_config.lora_bandwidth = preset->lora_bandwidth;
419 2 lora_config.lora_ecr = preset->lora_ecr - 4;
420 2 lora_config.lora_frequency = preset->lora_frequency;
421 2 lora_config.lora_spread = preset->lora_spread;
422 2 lora_config.lora_pa_select = preset->high_power_mode;
423
424 2 lora_status = LORA_OK;
425 }
426
427 /* reset and re-initialize */
428 2 lora_reset();
429 2 HAL_Delay(10);
430
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (lora_init( &lora_config ) == LORA_OK)
431 {
432 2 is_lora_configured = true;
433 2 return lora_status;
434 }
435 else
436 {
437 return LORA_FAIL;
438 }
439
440 } /* lora_configure */
441
442 // Get the device chip ID
443 2 static LORA_STATUS lora_get_device_id
444 (
445 uint8_t* buffer_ptr
446 )
447 {
448 2 LORA_STATUS status;
449
450 2 status = lora_read_register( LORA_REG_ID_VERSION, buffer_ptr );
451
452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ( status == LORA_OK )
453 return LORA_OK;
454 ✗ else return LORA_FAIL;
455 }
456
457
458 /*------------------------------------------------------------------------------
459 Procedures
460 ------------------------------------------------------------------------------*/
461
462 /*******************************************************************************
463 * *
464 * PROCEDURE: *
465 * lora_read_register_IT *
466 * *
467 * DESCRIPTION: *
468 * Read internal modem register. *
469 * *
470 * NOTE: *
471 * A completion callback (HAL_SPI_TxRxCpltCallback) for this operation *
472 * MUST be registered for the LoRa SPI handle. The completion callback *
473 * must pull NSS high like so: *
474 * *
475 * HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET ); *
476 * *
477 *******************************************************************************/
478 992 LORA_STATUS lora_read_register_IT
479 (
480 uint8_t lora_register,
481 uint8_t* pRegData /* o: 2 byte array; first byte will be empty, second will have the data */
482 )
483 {
484 992 HAL_StatusTypeDef hal_status;
485 992 static uint8_t read_reg[2];
486 992 read_reg[0] = lora_register & 0x7F;
487 992 read_reg[1] = 0x00;
488
489 992 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
490 992 hal_status = HAL_SPI_TransmitReceive_IT( &(LORA_SPI), read_reg, pRegData, 2 );
491
492 /* NSS high is in the callback */
493
494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 992 times.
992 if ( hal_status == HAL_OK )
495 {
496 return LORA_OK;
497 }
498 else
499 {
500 ✗ return LORA_FAIL;
501 }
502
503 } /* lora_read_register_IT */
504
505
506 /*******************************************************************************
507 * *
508 * PROCEDURE: *
509 * lora_write_register_IT *
510 * *
511 * DESCRIPTION: *
512 * Write to modem (register write). *
513 * *
514 * NOTE: *
515 * A completion callback (HAL_SPI_TxCpltCallback) for this operation *
516 * MUST be registered for the LoRa SPI handle. The completion callback *
517 * must pull NSS high like so: *
518 * *
519 * HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET ); *
520 * *
521 *******************************************************************************/
522 992 LORA_STATUS lora_write_register_IT
523 (
524 uint8_t lora_register,
525 uint8_t data
526 )
527 {
528 992 static uint8_t write_reg[2]; /* statically scoped so it doesn't go out of scope during tx */
529 992 write_reg[0] = (lora_register | 0x80);
530 992 write_reg[1] = data;
531
532 992 return lora_write_IT(write_reg, 2);
533
534 } /* lora_write_register_IT */
535
536
537 /*******************************************************************************
538 * *
539 * PROCEDURE: *
540 * lora_write_IT *
541 * *
542 * DESCRIPTION: *
543 * Write to modem (burst write, also used for register write). *
544 * *
545 * NOTE: *
546 * A completion callback (HAL_SPI_TxCpltCallback) for this operation *
547 * MUST be registered for the LoRa SPI handle. The completion callback *
548 * must pull NSS high like so: *
549 * *
550 * HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_SET ); *
551 * *
552 *******************************************************************************/
553 1323 LORA_STATUS lora_write_IT
554 (
555 uint8_t* data,
556 size_t len
557 )
558 {
559 1323 HAL_StatusTypeDef hal_status;
560
561 1323 HAL_GPIO_WritePin( LORA_NSS_GPIO_PORT, LORA_NSS_PIN, GPIO_PIN_RESET );
562 1323 hal_status = HAL_SPI_Transmit_IT( &(LORA_SPI), data, len );
563
564 /* NSS high is in the callback */
565
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1323 times.
1323 if ( hal_status == HAL_OK )
567 {
568 return LORA_OK;
569 }
570 else
571 {
572 ✗ return LORA_FAIL;
573 }
574
575 } /* lora_write_IT */
576
577
578 /*******************************************************************************
579 * *
580 * PROCEDURE: *
581 * lora_set_chip_mode *
582 * *
583 * DESCRIPTION: *
584 * Set operation mode of LoRa modem *
585 * *
586 *******************************************************************************/
587 4 LORA_STATUS lora_set_chip_mode
588 (
589 LORA_CHIPMODE chip_mode
590 )
591 {
592 // Get initial value of the operation mode register
593 4 uint8_t operation_mode_register;
594 4 LORA_STATUS read_status = lora_read_register( LORA_REG_OPERATION_MODE, &operation_mode_register );
595
596
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (read_status != LORA_OK)
597 {
598 return LORA_FAIL;
599 }
600
601 // // Fail if not in LORA Mode
602 // if ( !( operation_mode_register & (1<<7) ) ){
603 // return LORA_FAIL;
604 // }
605
606 // Change the value of the chip register to set it to the suggested chip mode
607 4 uint8_t new_opmode_register = (operation_mode_register & ~(0x7));
608 4 new_opmode_register = (new_opmode_register | chip_mode);
609
610 // Write new byte
611 4 LORA_STATUS write_status = lora_write_register( LORA_REG_OPERATION_MODE, new_opmode_register );
612
613
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if ( write_status + read_status == 0 ){
614 return LORA_OK;
615 } else {
616 ✗ return LORA_FAIL;
617 }
618 }
619
620 /*******************************************************************************
621 * *
622 * PROCEDURE: *
623 * lora_init *
624 * *
625 * DESCRIPTION: *
626 * Initialize LoRa modem *
627 * *
628 *******************************************************************************/
629 2 LORA_STATUS lora_init
630 (
631 LORA_CONFIG *lora_config_ptr
632 )
633 {
634 // TODO add check for accurate chip ID (more than zero)
635 2 uint8_t device_id = 0;
636 2 lora_get_device_id( &device_id );
637
638
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if( device_id != 0x12 ) {
639 return LORA_FAIL;
640 }
641
642 // Check legality of frequency settings
643 // We do this first so that nothing gets set if we're on an illegal frequency.
644
645 // Get a version of our bandwidth for legality calculations
646 2 uint32_t bandwidth; // Calculations down in hz due to decimal bandwidths
647
1/11
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
2 switch( lora_config_ptr->lora_bandwidth ) {
648 case LORA_BANDWIDTH_7_8_KHZ:
649 bandwidth = 7800;
650 break;
651 ✗ case LORA_BANDWIDTH_10_4_KHZ:
652 ✗ bandwidth = 10400;
653 ✗ break;
654 ✗ case LORA_BANDWIDTH_15_6_KHZ:
655 ✗ bandwidth = 15600;
656 ✗ break;
657 ✗ case LORA_BANDWIDTH_20_8_KHZ:
658 ✗ bandwidth = 20800;
659 ✗ break;
660 ✗ case LORA_BANDWIDTH_31_25_KHZ:
661 ✗ bandwidth = 31250;
662 ✗ break;
663 ✗ case LORA_BANDWIDTH_41_7_KHZ:
664 ✗ bandwidth = 41700;
665 ✗ break;
666 ✗ case LORA_BANDWIDTH_62_5_KHZ:
667 ✗ bandwidth = 62500;
668 ✗ break;
669 ✗ case LORA_BANDWIDTH_125_KHZ:
670 ✗ bandwidth = 125000;
671 ✗ break;
672 2 case LORA_BANDWIDTH_250_KHZ:
673 2 bandwidth = 250000;
674 2 break;
675 ✗ case LORA_BANDWIDTH_500_KHZ:
676 ✗ bandwidth = 500000;
677 ✗ break;
678 default:
679 // Just in case, even though this is reading an enum
680 return LORA_FAIL;
681 }
682
683 // Check legal compliance of frequency:
684
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if( !( lora_config_ptr->lora_frequency * 1000 + ( bandwidth / 2 ) <= ISM_MAX_FREQ * 1000 &&
685
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 lora_config_ptr->lora_frequency * 1000 - ( bandwidth / 2 ) >= ISM_MIN_FREQ * 1000 )
686 ) {
687 return LORA_FAIL;
688 }
689
690 2 LORA_STATUS set_sleep_status = lora_set_chip_mode( LORA_SLEEP_MODE ); // Switch to sleep mode to enable LoRa bit (datasheeet page 102)
691 // Get initial value of the operation mode register
692 2 uint8_t operation_mode_register;
693 2 LORA_STATUS read_status1 = lora_read_register( LORA_REG_OPERATION_MODE, &operation_mode_register );
694
695 2 uint8_t new_opmode_register;
696 2 new_opmode_register = ( operation_mode_register | 0b10000000 ); // Toggle the LoRa bit
697
698 // Write new byte
699 2 LORA_STATUS write_status1 = lora_write_register( LORA_REG_OPERATION_MODE, new_opmode_register );
700
701 // Get initial value of config register 2
702 2 uint8_t modem_config2_register;
703 2 LORA_STATUS read_status2 = lora_read_register( LORA_REG_RX_HEADER_INFO, &modem_config2_register );
704
705 2 uint8_t new_config2_register = modem_config2_register & 0x0F; // Erase spread factor bits
706 2 new_config2_register = ( new_config2_register | ( lora_config_ptr->lora_spread << 4 ) ); // Set the spread factor
707 2 LORA_STATUS write_status2 = lora_write_register( LORA_REG_RX_HEADER_INFO, new_config2_register ); // Write new spread factor
708
709 // Get initial value of config register 1
710 2 uint8_t modem_config1_register;
711 2 LORA_STATUS read_status3 = lora_read_register( LORA_REG_NUM_RX_BYTES, &modem_config1_register );
712 2 uint8_t new_config1_register = ( (lora_config_ptr->lora_bandwidth << 4) | (lora_config_ptr->lora_ecr << 1) | lora_config_ptr->lora_header_mode ); //TODO: Check datasheet for that last bit
713
714 // Write new config1 register
715 2 LORA_STATUS write_status3 = lora_write_register( LORA_REG_NUM_RX_BYTES, new_config1_register );
716
717 // Determine register values for the frequency registers
718 2 uint32_t freq_mhz = lora_config_ptr->lora_frequency / 1000; // The megahertz component of our frequency.
719 2 uint32_t freq_khz = lora_config_ptr->lora_frequency - freq_mhz * 1000; // The kilohertz component of our frequency.
720 // The formula for converting khz to chip unit is fruqency * 524288 / ( 32 * 1000 )
721 // Straight up doing that causes an integer overflow, though, so I have to do it this way.
722 2 uint32_t frf_reg = ( freq_mhz * 524288 / 32 ) + ( freq_khz * 524288 / ( 32 * 1000 ) );
723
724 2 uint8_t lora_freq_reg1 = ( frf_reg << 8 ) >> 24;
725 2 uint8_t lora_freq_reg2 = ( frf_reg << 16 ) >> 24;
726 2 uint8_t lora_freq_reg3 = ( frf_reg << 24 ) >> 24;
727
728 // Write the frequency registers
729 2 LORA_STATUS write_status4 = lora_write_register( LORA_REG_FREQ_MSB, lora_freq_reg1 );
730 2 LORA_STATUS write_status5 = lora_write_register( LORA_REG_FREQ_MSD, lora_freq_reg2 );
731 2 LORA_STATUS write_status6 = lora_write_register( LORA_REG_FREQ_LSB, lora_freq_reg3 );
732
733 // Determine register values for the PA Config Register
734 2 uint8_t new_pa_select_reg;
735
736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if( lora_config_ptr->lora_pa_select )
737 {
738 new_pa_select_reg = 0b11111111; /* PA select, everything else maxed out */
739 }
740 else
741 {
742 ✗ new_pa_select_reg = 0b01111111; /* RFO select, everything else maxed out */
743 }
744
745 // Write the PA Config Register
746 2 LORA_STATUS write_status7 = lora_write_register( LORA_REG_PA_CONFIG, new_pa_select_reg );
747
748 2 LORA_STATUS standby_status = lora_set_chip_mode( lora_config_ptr->lora_mode ); // Switch it into standby mode, which is what's convenient.
749
750
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if( set_sleep_status + read_status1 + read_status2 + read_status3 + write_status1 + write_status2 + write_status3 + write_status4 + write_status5 + write_status6 + write_status7 + standby_status == 0 ) {
751 return LORA_OK;
752 } else {
753 ✗ return LORA_FAIL;
754 }
755 }
756
757 /*******************************************************************************
758 * *
759 * PROCEDURE: *
760 * lora_reset *
761 * *
762 * DESCRIPTION: *
763 * Reset LoRa modem (Initialization function needs to be called again) *
764 * *
765 *******************************************************************************/
766 2 void lora_reset
767 (
768 void
769 )
770 {
771 2 HAL_GPIO_WritePin(LORA_RST_GPIO_PORT, LORA_RST_PIN, GPIO_PIN_RESET); // Pull Low
772 2 HAL_Delay(10); // Hold reset low for 10 ms
773 2 HAL_GPIO_WritePin(LORA_RST_GPIO_PORT, LORA_RST_PIN, GPIO_PIN_SET); // Pull High
774 2 HAL_Delay(10); // Wait for SX1278 to stabilize
775 2 }
776
777 /*******************************************************************************
778 * *
779 * PROCEDURE: *
780 * lora_transmit *
781 * *
782 * DESCRIPTION: *
783 * transmit a buffer through lora fifo *
784 * *
785 *******************************************************************************/
786 ✗ LORA_STATUS lora_transmit
787 (
788 uint8_t* buffer_ptr,
789 uint8_t buffer_len
790 )
791 {
792 // Mode request STAND-BY
793 ✗ LORA_STATUS standby_status = lora_set_chip_mode(LORA_STANDBY_MODE);
794
795 // Write data to LoRA FIFO
796 ✗ uint8_t fifo_ptr_addr;
797 ✗ LORA_STATUS tx_base_status = lora_read_register(LORA_REG_FIFO_TX_BASE_ADDR, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer
798 ✗ if (tx_base_status + standby_status != LORA_OK){
799 // Error handler
800 // led_set_color(// led_RED);
801 return LORA_FAIL;
802 }
803 ✗ LORA_STATUS ptr_status = lora_write_register(LORA_REG_FIFO_SPI_POINTER, fifo_ptr_addr); // Set fifo data pointer to TX base address
804 ✗ if (ptr_status != LORA_OK){
805 // Error handler
806 // led_set_color(// led_RED);
807 return LORA_FAIL;
808 }
809
810 // Write buffer length to fifo_rw
811 ✗ LORA_STATUS fifo_status = lora_write_register(LORA_REG_SIGNAL_TO_NOISE, buffer_len);
812
813 // Send byte to byte to the fifo buffer
814 ✗ LORA_STATUS sendbyte_status = LORA_OK;
815
816 /*
817 // Old transmit buffer write code
818 // TODO don't remove until burst transmit is working
819 for (int i = 0; i<buffer_len; i++){
820 sendbyte_status = lora_write_register(LORA_REG_FIFO_RW, buffer_ptr[i]);
821 }
822 */
823
824 ✗ sendbyte_status = lora_write_register_buffer( LORA_REG_FIFO_RW, buffer_ptr, buffer_len );
825
826 ✗ LORA_STATUS tmode_status = lora_set_chip_mode(LORA_TRANSMIT_MODE);
827
828 ✗ uint8_t lora_op;
829 ✗ LORA_STATUS regop_status;
830 ✗ while (1){ // TODO Add a timeout here
831 ✗ regop_status = lora_read_register(LORA_REG_OPERATION_MODE, &lora_op);
832 ✗ if ((lora_op & 0b111) == LORA_STANDBY_MODE){
833 break;
834 }
835 }
836 ✗ if( fifo_status + tmode_status + regop_status + sendbyte_status == 0 ) {
837 return LORA_OK;
838 } else {
839 ✗ return LORA_FAIL;
840 }
841 }
842
843 /*******************************************************************************
844 * *
845 * PROCEDURE: *
846 * lora_receive_ready *
847 * *
848 * DESCRIPTION: *
849 * Check if new packt has been received *
850 * *
851 *******************************************************************************/
852 ✗ LORA_STATUS lora_receive_ready
853 (
854 void
855 )
856 {
857 ✗ uint8_t mode;
858
859 ✗ LORA_STATUS mode_check = lora_read_register( LORA_REG_OPERATION_MODE, &mode );
860 ✗ mode = mode & 0x07;
861
862 ✗ if( mode_check == LORA_OK && mode == LORA_RX_CONTINUOUS_MODE ) {
863 ✗ uint8_t irq_flag;
864
865 ✗ LORA_STATUS irq_check = lora_read_register(LORA_REG_IRQ_FLAGS, &irq_flag);
866
867 ✗ if( irq_check == LORA_OK ) {
868 ✗ lora_write_register( LORA_REG_IRQ_FLAGS, irq_flag );
869 ✗ uint8_t rx_done = ( irq_flag & 0x40 ) == 0x40;
870
871 ✗ if( rx_done ) {
872 ✗ lora_rx_done = LORA_READY;
873 ✗ return LORA_READY;
874 } else {
875 ✗ lora_rx_done = LORA_WAITING;
876 ✗ return LORA_WAITING;
877 }
878 } else {
879 return LORA_FAIL;
880 }
881 } else {
882 return LORA_FAIL;
883 }
884 }
885
886 /*******************************************************************************
887 * *
888 * PROCEDURE: *
889 * lora_receive *
890 * *
891 * DESCRIPTION: *
892 * lora_receive: receive a buffer from lora fifo with continuous mode *
893 * *
894 *******************************************************************************/
895 ✗ LORA_STATUS lora_receive
896 (
897 uint8_t* buffer_ptr,
898 uint8_t buffer_len,
899 uint8_t* num_bytes_received
900 )
901 {
902 ✗ if ( lora_rx_done == LORA_READY ){
903 // Write IRQ flags
904 ✗ uint8_t irq_flag;
905
906 ✗ LORA_STATUS irq_status2 = lora_read_register(LORA_REG_IRQ_FLAGS, &irq_flag);
907 ✗ if( irq_status2 != LORA_OK )
908 {
909 return LORA_FAIL;
910 }
911 ✗ uint8_t crc_err = ( irq_flag & 0x20 ) == 0x20;
912
913 ✗ if (!crc_err){ // TODO make a fail happen for a CRC error
914 // Read received number of bytes
915 ✗ uint8_t num_bytes;
916 ✗ LORA_STATUS fifo2_status = lora_read_register(LORA_REG_FIFO_RX_NUM_BYTES, &num_bytes);
917
918 // In case SPI operation fials
919 ✗ if( fifo2_status != LORA_OK ) {
920 return LORA_FAIL;
921 }
922
923 ✗ if (num_bytes > buffer_len)
924 {
925 return LORA_BUFFER_UNDERSIZED;
926 }
927
928 // Set lora fifo pointer to the RX base current address
929 ✗ uint8_t fifo_ptr_addr;
930 ✗ LORA_STATUS base_adr_status = lora_read_register(LORA_REG_FIFO_RX_BASE_CUR_ADDR, &fifo_ptr_addr); // Access LoRA FIFO data buffer pointer
931 ✗ if (base_adr_status != LORA_OK){
932 // Error handler
933 return LORA_FAIL;
934 }
935 ✗ LORA_STATUS ptr2_status = lora_write_register(LORA_REG_FIFO_SPI_POINTER, fifo_ptr_addr); // Set fifo data pointer to TX base address
936 ✗ if (ptr2_status != LORA_OK){
937 // Error handler
938 return LORA_FAIL;
939 }
940 // Begin extracting payload
941 ✗ LORA_STATUS pld_xtr_status = LORA_OK;
942
943 /*
944 // Old Rx buffer read code
945 // TODO don't remove until burst read is confirmed working
946 for (int i = 0; i < num_bytes; i++){
947 uint8_t packet;
948 pld_xtr_status = lora_read_register(LORA_REG_FIFO_RW, &packet); // Access LoRA FIFO data buffer pointer
949 buffer_ptr[i] = packet;
950 } */
951
952 ✗ lora_read_register_buffer( LORA_REG_FIFO_RW, buffer_ptr, num_bytes);
953
954 ✗ *num_bytes_received = num_bytes;
955 ✗ if (pld_xtr_status == LORA_OK ) {
956 ✗ return LORA_OK;
957 } else {
958 return LORA_FAIL;
959 }
960 }
961 return LORA_OK;
962 ✗ } else if( lora_rx_done == LORA_WAITING ) {
963 ✗ return LORA_WAITING;
964 }
965 return LORA_FAIL;
966 }
967
968 /*------------------------------------------------------------------------------
969 Internal procedures
970 ------------------------------------------------------------------------------*/
971