Compare commits

..

205 commits

Author SHA1 Message Date
6ea0884898 Merge pull request '17.0.3' (#2) from 17.0.3 into master
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Cppcheck / Perform static code check (push) Has been cancelled
Doxygen / doxygen (push) Has been cancelled
CI / CubeCell:CubeCell:CubeCell-Board (push) Has been cancelled
CI / MegaCore:avr:1281 (push) Has been cancelled
CI / MegaCoreX:megaavr:4809 (push) Has been cancelled
CI / STMicroelectronics:stm32:GenF3 (push) Has been cancelled
CI / STMicroelectronics:stm32:Nucleo_64 (push) Has been cancelled
CI / SiliconLabs:silabs:xg24explorerkit (push) Has been cancelled
CI / adafruit:nrf52:feather52832 (push) Has been cancelled
CI / adafruit:samd:adafruit_feather_m0 (push) Has been cancelled
CI / arduino:avr:mega (push) Has been cancelled
CI / arduino:mbed:envie_m4 (push) Has been cancelled
CI / arduino:mbed:nano33ble (push) Has been cancelled
CI / arduino:mbed_rp2040:pico (push) Has been cancelled
CI / arduino:megaavr:uno2018 (push) Has been cancelled
CI / arduino:renesas_uno:minima (push) Has been cancelled
CI / arduino:sam:arduino_due_x (push) Has been cancelled
CI / arduino:samd:arduino_zero_native (push) Has been cancelled
CI / esp32:esp32:esp32 (push) Has been cancelled
CI / esp8266:esp8266:generic (push) Has been cancelled
CI / rp2040:rp2040:rpipico (push) Has been cancelled
CI / stm32duino:STM32F1:mapleMini (push) Has been cancelled
CI / teensy:avr:teensy41 (push) Has been cancelled
CI / metrics (push) Has been cancelled
CI / esp-build (push) Has been cancelled
CI / tock-build (push) Has been cancelled
CI / rpi-build (push) Has been cancelled
CI / rpi-test (push) Has been cancelled
CI / rpi-pico-build (push) Has been cancelled
Reviewed-on: #2
2025-04-02 00:56:25 +02:00
6488c1e20e 17.0.3
Some checks failed
CI / esp32:esp32:esp32 (pull_request) Has been cancelled
CI / esp8266:esp8266:generic (pull_request) Has been cancelled
CI / rp2040:rp2040:rpipico (pull_request) Has been cancelled
CI / stm32duino:STM32F1:mapleMini (pull_request) Has been cancelled
CI / teensy:avr:teensy41 (pull_request) Has been cancelled
Unit test / Build and run unit test (pull_request) Has been cancelled
CodeQL / Analyze (pull_request) Has been cancelled
Cppcheck / Perform static code check (pull_request) Has been cancelled
CI / CubeCell:CubeCell:CubeCell-Board (pull_request) Has been cancelled
CI / MegaCore:avr:1281 (pull_request) Has been cancelled
CI / MegaCoreX:megaavr:4809 (pull_request) Has been cancelled
CI / STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC (pull_request) Has been cancelled
CI / STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1 (pull_request) Has been cancelled
CI / SiliconLabs:silabs:xg24explorerkit (pull_request) Has been cancelled
CI / adafruit:nrf52:feather52832 (pull_request) Has been cancelled
CI / adafruit:samd:adafruit_feather_m0 (pull_request) Has been cancelled
CI / arduino:avr:mega (pull_request) Has been cancelled
CI / arduino:mbed:envie_m4 (pull_request) Has been cancelled
CI / arduino:mbed:nano33ble (pull_request) Has been cancelled
CI / arduino:mbed_rp2040:pico (pull_request) Has been cancelled
CI / arduino:megaavr:uno2018 (pull_request) Has been cancelled
CI / arduino:renesas_uno:minima (pull_request) Has been cancelled
CI / arduino:sam:arduino_due_x (pull_request) Has been cancelled
CI / arduino:samd:arduino_zero_native (pull_request) Has been cancelled
CI / metrics (pull_request) Has been cancelled
CI / esp-build (pull_request) Has been cancelled
CI / tock-build (pull_request) Has been cancelled
CI / rpi-build (pull_request) Has been cancelled
CI / rpi-test (pull_request) Has been cancelled
CI / rpi-pico-build (pull_request) Has been cancelled
2025-04-02 00:55:54 +02:00
82bb7ac946 fix
Some checks failed
CI / adafruit:nrf52:feather52832 (pull_request) Has been cancelled
CI / adafruit:samd:adafruit_feather_m0 (pull_request) Has been cancelled
CI / arduino:avr:mega (pull_request) Has been cancelled
CI / arduino:mbed:envie_m4 (pull_request) Has been cancelled
CI / arduino:mbed:nano33ble (pull_request) Has been cancelled
CI / arduino:mbed_rp2040:pico (pull_request) Has been cancelled
CI / arduino:megaavr:uno2018 (pull_request) Has been cancelled
CI / arduino:renesas_uno:minima (pull_request) Has been cancelled
CI / arduino:sam:arduino_due_x (pull_request) Has been cancelled
CI / arduino:samd:arduino_zero_native (pull_request) Has been cancelled
CI / esp32:esp32:esp32 (pull_request) Has been cancelled
CI / esp8266:esp8266:generic (pull_request) Has been cancelled
CI / rp2040:rp2040:rpipico (pull_request) Has been cancelled
CI / stm32duino:STM32F1:mapleMini (pull_request) Has been cancelled
CI / teensy:avr:teensy41 (pull_request) Has been cancelled
CI / metrics (pull_request) Has been cancelled
CodeQL / Analyze (pull_request) Has been cancelled
Cppcheck / Perform static code check (pull_request) Has been cancelled
CI / CubeCell:CubeCell:CubeCell-Board (pull_request) Has been cancelled
CI / MegaCore:avr:1281 (pull_request) Has been cancelled
CI / MegaCoreX:megaavr:4809 (pull_request) Has been cancelled
CI / STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC (pull_request) Has been cancelled
CI / STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1 (pull_request) Has been cancelled
CI / SiliconLabs:silabs:xg24explorerkit (pull_request) Has been cancelled
CI / esp-build (pull_request) Has been cancelled
CI / tock-build (pull_request) Has been cancelled
CI / rpi-build (pull_request) Has been cancelled
CI / rpi-test (pull_request) Has been cancelled
CI / rpi-pico-build (pull_request) Has been cancelled
Unit test / Build and run unit test (pull_request) Has been cancelled
2025-04-02 00:48:45 +02:00
4548b9ffc4 update 2025-04-02 00:46:28 +02:00
a6e737a055 adjusted radiolib.h 2025-04-02 00:41:20 +02:00
jgromes
ec785005aa [SX126x] Zero-initialize version string
Some checks failed
Cppcheck / Perform static code check (push) Waiting to run
Doxygen / doxygen (push) Waiting to run
CI / teensy:avr:teensy41 (push) Waiting to run
CI / rpi-pico-build (push) Waiting to run
CI / STMicroelectronics:stm32:GenF3 (push) Waiting to run
CI / STMicroelectronics:stm32:Nucleo_64 (push) Waiting to run
CI / SiliconLabs:silabs:xg24explorerkit (push) Waiting to run
CI / adafruit:nrf52:feather52832 (push) Waiting to run
CI / adafruit:samd:adafruit_feather_m0 (push) Waiting to run
CI / arduino:avr:mega (push) Waiting to run
CI / arduino:mbed:envie_m4 (push) Waiting to run
CI / arduino:mbed:nano33ble (push) Waiting to run
CI / arduino:mbed_rp2040:pico (push) Waiting to run
CI / arduino:megaavr:uno2018 (push) Waiting to run
CI / arduino:renesas_uno:minima (push) Waiting to run
CI / arduino:sam:arduino_due_x (push) Waiting to run
CI / arduino:samd:arduino_zero_native (push) Waiting to run
CI / esp32:esp32:esp32 (push) Waiting to run
CI / esp8266:esp8266:generic (push) Waiting to run
CI / rp2040:rp2040:rpipico (push) Waiting to run
CI / stm32duino:STM32F1:mapleMini (push) Waiting to run
CI / CubeCell:CubeCell:CubeCell-Board (push) Waiting to run
CI / MegaCore:avr:1281 (push) Waiting to run
CI / MegaCoreX:megaavr:4809 (push) Waiting to run
CI / metrics (push) Blocked by required conditions
CI / esp-build (push) Waiting to run
CI / tock-build (push) Waiting to run
CI / rpi-build (push) Waiting to run
CI / rpi-test (push) Blocked by required conditions
Unit test / Build and run unit test (push) Failing after 2s
2025-03-23 21:47:20 +01:00
jgromes
f0e686eaa9 [Si443x] Add CRC configuration (#1430) 2025-03-14 20:14:52 +01:00
jgromes
416f52d92a [Si443x] Fix CRC error IRQ (#1430) 2025-03-14 20:14:23 +01:00
jgromes
d526ac3091 [RF69] Remove redundant sync word length caching 2025-03-08 13:09:54 +01:00
Jan Gromeš
1b62bc3208
[RF69] Merge pull request #1452 from lyusupov/master
[RF69] further fix for sync word length
2025-03-08 13:09:09 +01:00
Linar Yusupov
77db225396
[RF69] further fix for sync word length 2025-03-08 13:02:05 +03:00
Jan Gromeš
15745bbd1d
[LoRaWAN] Merge pull request #1450 from jgromes/fix-cn470
Fix for CN470 (formerly CN500) (#1447)
2025-03-06 21:03:14 +01:00
StevenCellist
7577ae413f Fix for CN470 (formerly CN500) 2025-03-06 18:31:20 +01:00
Linar Yusupov
c88cf551cc
[SX128x] fix for improper GFSK syncword setting with length other than 5 bytes (#1446)
* [SX128x] fix for improper GFSK syncword setting with length other than 5 bytes

* [SX128x] misc. rework
2025-03-06 17:47:59 +01:00
Linar Yusupov
6bf0c3f735
[RF69] a fix for invalid sync word length setting (#1448)
* [RF69] a fix for invalid sync word length setting

* [RF69] fix maxErrBits width
2025-03-06 07:09:01 +01:00
jgromes
d605bc2058 [SX128x] Add missing const cast 2025-03-04 08:10:09 +01:00
jgromes
08e0c0e613 [SX128x] Simplify sync word configuration 2025-03-03 08:36:03 +01:00
Linar Yusupov
d142928e9f
[SX128x] fix for invalid GSFK sync words order (#1444) 2025-03-03 08:34:26 +01:00
Linar Yusupov
01d1bdae2c
[SX128x] Add support for GFSK fixed packet length mode (#1441)
* [SX1280] add support for GFSK fixed packet length mode

* [SX1280] meet cpp check

* [SX1280] cleanup
2025-03-02 20:26:16 +01:00
Jan Gromeš
56729041b3
[MOD] Add debug timestamps (#1440) 2025-03-02 09:37:55 +01:00
jgromes
b203323ff9 Merge branch 'master' of https://github.com/jgromes/RadioLib 2025-03-02 08:31:49 +01:00
jgromes
07792dc90f [MOD] Return debug information even after post-transfer GPIO timeout (#1434) 2025-03-02 08:31:47 +01:00
jgromes
c9690a7955 [EXT] Remove redundant null check (#1436) 2025-02-27 18:16:30 +01:00
Crsarmv7l
cf776230a4
Slightly increase timeout while waiting for MARC state to be ready for TX (#1429) 2025-02-19 19:44:01 +01:00
jgromes
648ecbed3b [SX127x] Fix typo in doxygen comment 2025-02-18 07:20:42 +01:00
jgromes
6a96d44b2b [SX127x] Fix automated RFO selection (#1412) 2025-02-17 21:19:18 +01:00
jgromes
ae65265268 [LR11x0] Fix rest of latitude/longitude conversion (#1379) 2025-02-17 18:36:36 +01:00
jgromes
9c82d1bdc2 [LR11x0] Fix latitude/longitude for negative values (#1379) 2025-02-17 17:42:20 +01:00
jgromes
4a557f5162 [PHY] Add missing member variable init 2025-02-15 14:57:36 +01:00
jgromes
5f1303aaba [SX128x] Use public frequency step and max packet length variables 2025-02-15 14:49:01 +01:00
jgromes
24c7166170 [SX127x] Use public frequency step and max packet length variables 2025-02-15 14:48:55 +01:00
jgromes
699f025581 [SX126x] Use public frequency step and max packet length variables 2025-02-15 14:48:51 +01:00
jgromes
c420d69193 [Si443x] Use public frequency step and max packet length variables 2025-02-15 14:48:45 +01:00
jgromes
558e60b18d [RF69] Use public frequency step and max packet length variables 2025-02-15 14:48:33 +01:00
jgromes
e4daea6251 [nRF24] Use public frequency step and max packet length variables 2025-02-15 14:48:23 +01:00
jgromes
78e2991459 [LR11x0] Use public frequency step and max packet length variables 2025-02-15 14:48:16 +01:00
jgromes
8286e2d770 [CC1101] Use public frequency step and max packet length variables 2025-02-15 14:48:08 +01:00
jgromes
2fd2926c9f [PHY] Make frequency step and max packet length public variables 2025-02-15 14:47:45 +01:00
jgromes
35059a86ff [SX126x] Remove node address methods from header (#1422) 2025-02-14 22:03:10 +01:00
jgromes
977b2c28c8 [nRF24] Add public LNA control method (#1392) 2025-02-13 18:57:44 +01:00
Crsarmv7l
b9c214db95
[CC1101] FIFO Refills to transmit packets up to 255 bytes (#1404)
* Update CC1101.h

Add Max packet size for FIFO Refills

* Define FIFO Size, Max packet Length for FIFO refills

* FIFO REFILL

- Go through FSTXON State
- Check MARCSTATE to ensure ready to tx
- Initial FIFO fill
- Check FIFO bytes twice in accordance with errata
- Refill FIFO
- Check MARCSTATE is idle before returning

* Fix typos

* Fix another typo

* min -> std::min per build check

* Revert std::min back to min

* Use RADIOLIB_MIN Macro instead of min

* Move MARC State check for Idle to finishTransmit function

Change allows startTransmit to stop blocking once the last bytes are added to the FIFO

* Add timeouts for both MARC state checks

* Fix typo

* No interrupt for packets bigger than 64 bytes

* Initialize state as RADIOLIB_ERR_NONE if avoiding ISR

* Update example with packet size and discussion link

* Update example with new packet size and discussion link

* Update example, clarify blocking on greater than 64 bytes link discussion

* Update doxygen comments for 255 byte limit, limitations and discussion link
2025-02-13 17:20:56 +01:00
jgromes
bcbf2a12e1 [CI] Allow code coverage report deploy only from master 2025-02-11 20:18:32 +01:00
jgromes
584f547954 Fix debug info macro (#1398) 2025-02-11 15:22:32 +01:00
jgromes
2e35481fc2 Fix script argument check 2025-02-11 15:21:30 +01:00
jgromes
e087449c0b Use configurable line feed for debug output (#1398) 2025-02-11 14:28:31 +01:00
Jan Gromeš
e86fb27649
[CI] Measure code coverage after unit test (#1417)
* [CI] Measure code coverage after unit test

* [CI] Update workflow

* [CI] Fix indentation

* [CI] Ignore geninfo errors

* [CI] Force gcov 11

* [CI] Install gcc 11

* [CI] Revert gcc-11

* Use ubuntu 22.04 as unit test runner

* Deploy coverage report to github pages

* Add coverage link

---------

Co-authored-by: jgromes <jan.gromes>
2025-02-10 08:35:52 +01:00
Jan Gromeš
8c2c7b6cb5
[LoRaWAN] Add methods to allow user-provided sleep function (#1410)
* [LoRaWAN] Add methods to allow user-provided sleep function

* Add example sleep function

* [LoRaWAN] Switch all delay calls to sleepDelay

* [LoRaWAN] Remove unused variable

---------

Co-authored-by: StevenCellist <steven@boonstoppel.nu>
2025-02-06 07:00:03 +01:00
Jan Gromeš
45de7978dc
Merge pull request #1416 from lyusupov/master
a fix for build with Arduino Core over Zephyr OS for Nano 33 BLE and Portenta H7 targets
2025-02-05 22:53:02 +01:00
Jan Gromeš
2550fae4cb
[PHY] Staged modes (#1414)
* [PHY] Add PHY support for staged modes

* [SX126x] Add support for staged Rx/Tx

* [PHY] Add missing virtual specifiers

* [SX126x] Add missing overrides

* [LoRaWAN] Use new stageMode and launchMode, reduce scanGuard

* [LoRaWAN] A-synchronize transmissions (#1410)

* [PHY] Pass mode config by reference

* [PHY] Add default implementation of start transmit/receive

* [SX126x] Implement staged modes

* [SX128x] Implement staged modes

* [SX127x] Implement staged modes

* [LR11x0] Implement staged modes

* [SX127x] Remove unused method from header

* [SX126x] Make array const

* Add new methods to keywords

---------

Co-authored-by: StevenCellist <steven@boonstoppel.nu>
2025-02-05 20:41:43 +01:00
Linar Yusupov
3563e7257a
a fix for build with Arduino Core for Zephyr OS for Nano 33 BLE and Portenta H7 targets 2025-02-05 13:23:36 +03:00
jgromes
9e832526a5 [SX127x] Fix lower power range of RFO (#1412) 2025-02-02 10:10:13 +01:00
jgromes
33fd649288 Ensure output dir of spectrum scan always exists 2025-02-02 09:33:16 +01:00
jgromes
f2461edaec [SX127x] Fix mistake in doxygen comment (#1411) 2025-02-01 21:05:58 +01:00
jgromes
4deec953e8 [LLCC68] Add missing override specifiers 2025-01-31 18:25:57 +01:00
jgromes
8ab989ab53 [CI] Add helper script to cppcheck single path 2025-01-31 18:25:38 +01:00
jgromes
b634c9c711 [SX126x] Add missing virtual specifier (#1405) 2025-01-31 18:09:52 +01:00
jgromes
8c304a89c1 [LLCC68] Add override begin FSK and LR-FHSS methods (#1405) 2025-01-31 17:59:47 +01:00
StevenCellist
27653e1cf7 [LoRaWAN] Allow support for misc MAC commands 2025-01-30 20:58:53 +01:00
jgromes
5eb90ea17a [SX126x] Add LR-FHSS interrupt transmit example 2025-01-29 21:14:36 +01:00
jgromes
779e0aa4dd [SX126x] Rename LR-FHSS modem example to transmit 2025-01-29 20:45:41 +01:00
jgromes
c187960cc1 [SX126x] Add public method to handle LR-FHSS hopping 2025-01-29 17:51:20 +00:00
jgromes
fc6ff698b9 [RF69] Fix sync word length not set correctly (#1400) 2025-01-27 18:44:49 +01:00
jgromes
c6096ad3b8 [CI] Fix steps order 2025-01-23 19:04:06 +01:00
jgromes
d0cfd5a461 [CI] Only push metrics from master 2025-01-23 18:41:16 +01:00
Jan Gromeš
73b6a7d5e9
[SX123x] Merge pull request #1397 from lyusupov/master
add chip revision number for Semtech SX123xH
2025-01-23 18:34:53 +01:00
Linar Yusupov
5979a2a7be add chip revision number for SX123xH 2025-01-23 15:35:09 +03:00
jgromes
bedab1a66d [CI] Add unit test for SPIsetRegValue 2025-01-19 21:48:39 +01:00
jgromes
c4ac0ac68b [CI] Add artificial delay to unit test emulated SPI 2025-01-19 21:46:00 +01:00
jgromes
3e146c891e [CI] Fix SPI log wipe 2025-01-19 21:45:32 +01:00
jgromes
4733fdd9d1 Fix debug prints 2025-01-19 18:30:02 +01:00
jgromes
8126e6f508 Suppress double promotion warning for debug 2025-01-19 18:29:56 +01:00
jgromes
650d00b3e3 Added no-tag debug macro to protocol level 2025-01-19 13:27:14 +00:00
jgromes
21a77a6389 [Morse] Fix debug output 2025-01-19 13:26:51 +00:00
jgromes
cbb8126442 [LoRaWAN] Fix possible integer overflow 2025-01-18 21:23:01 +01:00
jgromes
269eb2fe38 [LoRaWAN] Fix typecast 2025-01-18 21:22:17 +01:00
jgromes
0cd69b2e6f [CI] Use v4 artifact download 2025-01-18 18:34:33 +01:00
jgromes
64f0f5028b [LoRaWAN] Cppcheck fixes 2025-01-18 18:14:56 +01:00
jgromes
1324b53f7b [Print] Fix duplicate methods 2025-01-18 18:14:34 +01:00
jgromes
ff24e2b2ae [LoRaWAN] Cppcheck fixes 2025-01-18 17:51:57 +01:00
jgromes
aab3e05386 [Crypto] Cppcheck fixes 2025-01-18 17:51:30 +01:00
jgromes
cc9ce359b6 [OPT] Cppcheck fixes 2025-01-18 17:51:11 +01:00
jgromes
de33ce4d6a [PHY] Cppcheck fixes 2025-01-18 17:50:53 +01:00
jgromes
d685534154 [Print] Cppcheck fixes 2025-01-18 17:50:09 +01:00
jgromes
bf1933a0c4 [Pager] Cppcheck fixes 2025-01-18 17:49:51 +01:00
jgromes
208f4f8ad4 [Morse] Cppcheck fixes 2025-01-18 17:49:37 +01:00
jgromes
1357d672c7 [Hell] Cppcheck fixes 2025-01-18 17:49:24 +01:00
jgromes
9b8b9c2802 [FSK4] Cppcheck fixes 2025-01-18 17:49:10 +01:00
jgromes
dab2c3497c [AX.25] Cppcheck fixes 2025-01-18 17:48:57 +01:00
jgromes
d4d98d37ce [APRS] Cppcheck fixes 2025-01-18 17:48:41 +01:00
jgromes
80a44a3232 [SX128x] Cppcheck fixes 2025-01-18 17:48:25 +01:00
jgromes
06b3049e38 [SX127x] Cppcheck fixes 2025-01-18 17:48:19 +01:00
jgromes
ddd4b23e65 [SX126x] Cppcheck fixes 2025-01-18 17:48:09 +01:00
jgromes
aaa48ba4d8 [Si443x] Cppcheck fixes 2025-01-18 17:47:54 +01:00
jgromes
5e7be10364 [nRF24] Cppcheck fixes 2025-01-18 17:47:34 +01:00
jgromes
d23983bc1f [CI] Suppress missing includes in cppcheck 2025-01-18 16:39:17 +01:00
jgromes
d3d16433bf [SX126x] Cppcheck fixes 2025-01-18 15:43:14 +01:00
jgromes
beb6689287 [RF69] Cppcheck fixes 2025-01-18 15:25:48 +01:00
jgromes
77dad34c05 [LR11x0] Cppcheck fixes 2025-01-18 15:21:40 +01:00
jgromes
3354cd89df [SX126x] MAke LLCC68-shared methods virtual 2025-01-17 22:31:20 +01:00
jgromes
21b8e5a364 [LLCC68] Cppcheck fixes 2025-01-17 22:30:49 +01:00
jgromes
af34dd9691 [CC1101] Cppcheck fixes 2025-01-17 22:30:37 +01:00
jgromes
6733847186 [CI] Suppress unused variable warnings for unimplemented functions 2025-01-17 20:24:10 +01:00
jgromes
5efdfb342a [CI] Always test from clean 2025-01-17 20:00:59 +01:00
jgromes
4088db2cf2 [MOD] Fix issues reported by new cppcheck 2025-01-17 20:00:26 +01:00
jgromes
7c464a0632 Add double-promotion and pedantic warnings to CMake 2025-01-17 19:59:50 +01:00
jgromes
c538cac769 [Morse] Fix possible overflow 2025-01-17 19:59:25 +01:00
jgromes
10c38164f2 [LoRaWAN] Remove range expression in switch 2025-01-17 19:59:10 +01:00
Jan Gromeš
6fb3c0968a
Merge pull request #1387 from MatejFranceskin/pr-fix-warnings
fix implicit conversion from float to double warnings
2025-01-17 19:54:59 +01:00
jgromes
cad09196de [CI] Use v4 artifact action 2025-01-16 18:30:51 +01:00
jgromes
a5011914c5 [CI] Disable self hosted runner actions 2025-01-16 18:27:52 +01:00
Matej Frančeškin
f3276c2e66 fix implicit conversion from float to double warnings 2025-01-15 16:06:47 +01:00
Yegor Shytikov
4f1d367c93
[LR11x0] Skip frequency range verification (#1388)
* Update LR1120.cpp

LR1120 can set the frequency of the documented range. So, allowing another frequency was tested with the LR1121 Lyligo board, which works. Thanks!

* Update LR1120.h

* add RADIOLIB_CHECK_PARAMS

* remove  skipRfValidation parameter

* Fix formating
2025-01-14 20:56:03 +01:00
petrel
04b96873a3
[CC1101]Add sleep function (#1389) 2025-01-14 08:03:43 +01:00
jgromes
9a8affde8e Fix default debug port on non-Arduino platforms (#1380) 2025-01-11 09:32:12 +01:00
jgromes
2ca2ddf968 [CI] Fix passing STM32 part numbers 2025-01-06 18:03:18 +01:00
jgromes
d26b1ff38e Bump version to 7.1.2 2025-01-05 20:20:04 +01:00
jgromes
49f21cc707 [CI] Fix skipping for STM32 2025-01-05 18:28:40 +01:00
jgromes
06f416935f [SX128x] Added explicit typecast 2025-01-05 17:46:42 +01:00
jgromes
5ea881c595 [SX126x] Added explicit typecast 2025-01-05 17:46:36 +01:00
jgromes
92c08c1ebf [LR11x0] Added explicit typecast 2025-01-05 17:46:30 +01:00
Jan Gromeš
cbb8d419d1
[CI] Unit test (#1373)
* [CI] Add basic unit testing

* [CI] Add gitignore

* [CI] Install libfmt

---------

Co-authored-by: jgromes <jan.gromes>
2025-01-05 17:23:13 +01:00
jgromes
a63ca70558 [Pager] Fix debug parameter type 2025-01-05 09:59:55 +01:00
StevenCellist
33b65344c4 [LoRaWAN] Fix ADR backoff difference between 1.0.4 and 1.1 2025-01-04 23:27:18 +01:00
StevenCellist
f346dd3687 [LoRaWAN] Improve handling of invalid MAC commands 2025-01-04 23:18:37 +01:00
StevenCellist
a3782b432c [LoRaWAN] Accept MAC channel mask if ADR is disabled 2025-01-04 16:20:42 +01:00
StevenCellist
283bfb43fe [LoRaWAN] Revert change in dwell time arguments 2025-01-04 16:04:05 +01:00
StevenCellist
5952106e93
[LoRaWAN] Update reference example 2025-01-04 15:05:36 +01:00
StevenCellist
617d759ea5 [LoRaWAN] Fix some MAC commands not being resent 2025-01-04 14:48:25 +01:00
StevenCellist
6ab358c292 [LoRaWAN] Improve dwell time handling under ADR 2025-01-04 14:43:20 +01:00
StevenCellist
92d2dc0f09 [LoRaWAN] Remove unused space in session buffer 2025-01-04 14:27:10 +01:00
jgromes
01e7fa0731 [Pager] Fix sync words in long messages (#1112) 2025-01-04 11:23:07 +01:00
jgromes
b5d36f11e5 [Pager] Minor formatting fixes 2025-01-04 11:22:28 +01:00
Jan Gromeš
7141d261be
[CI] Use SSH deploy key for metrics push (#1371)
Co-authored-by: jgromes <jan.gromes>
2025-01-03 19:27:13 +01:00
CrispyAlice2
680e88c739
Fix frequency issue on SX127x (#1368) (#1369)
* Fix frequency issue on SX127x (#1368)

* Add force option to SPIsetRegValue

* Fix indent
2025-01-03 19:11:29 +01:00
Jan Gromeš
bd4ede2fb7
[CI] Add size metrics (#1367)
* [CI] Add CI scripts, save metrics on build

* Fix token name

* Fix path

* Pass size files via artifacts

* Fix path to artifacts

* Fix git hash in artifact filename

* Fix git hash

* Fix artifact name

* Fix artifact path

* Avoid filenames with colons

* Fix artifact paths

* Remove incorrect cd

* Add missing cd

* Fix paths in second repo

* More path fixing

* Fix artifacts repo name

* Remove path from example filename in output

* Add hash to commit message

* Fix typo

* Fix artifact commit message

* Move git hash

* Use GITHUB_SHA variable

* Drop markdown format

---------

Co-authored-by: jgromes <jan.gromes>
2025-01-01 14:14:08 +01:00
jgromes
92b687821f [MOD] Remove getCs method (#1364) 2024-12-29 10:03:42 +01:00
jgromes
60a093775a [CC1101] Use Module SPI transfer stream 2024-12-29 10:03:13 +01:00
jgromes
c7fb065310 [CC1101] Simplify reset sequence 2024-12-29 09:46:38 +01:00
jgromes
8e35b14fae [nRF24] Use Module SPI transfer stream 2024-12-29 09:33:53 +01:00
jgromes
422dc867e0 Merge branch 'master' of https://github.com/jgromes/RadioLib 2024-12-27 20:41:39 +01:00
jgromes
af6de6a0e0 [CI] Fix library name in release CI 2024-12-27 20:41:37 +01:00
jgromes
b2b4c9e0f7 [SX126x] Use dummy SPI transfer for wakeup (#1364) 2024-12-27 16:26:24 +00:00
jgromes
ff387e93ad [SX128x] Use dummy SPI transfer for wakeup 2024-12-27 16:25:59 +00:00
jgromes
9bff1582bd [LR11x0] Use dummy SPI transfer for wakeup 2024-12-27 16:25:52 +00:00
jgromes
c37015ef94 [CI] Fix typo 2024-12-20 13:53:26 +01:00
jgromes
afa5da7fd6 [CI] Add release workflow 2024-12-20 13:52:09 +01:00
jgromes
6622a0ac99 Bump version to 7.1.1 2024-12-19 14:18:20 +01:00
StevenCellist
c2b44d2552
Add FSK to supported LoRaWAN modulations 2024-12-18 22:48:03 +01:00
jgromes
02fe9f3119 Remove dev files 2024-12-18 08:28:06 +01:00
jgromes
89424a3025 [LoRaWAN] Remove unused parameter 2024-12-18 07:22:06 +00:00
jgromes
661b36cc4c [SX126x] Suppress unused variable warning 2024-12-17 21:05:50 +00:00
jgromes
8c0e8a6586 [SX126x] Remove address filtering from examples (#1268) 2024-12-17 20:27:17 +00:00
jgromes
6e3b870317 [SX126x] Drop support for FSK address filtering (#1268) 2024-12-17 20:12:19 +00:00
jgromes
67547615af [SX126x] Added notes about preamble detector to Doxygen (#1350) 2024-12-16 19:01:30 +00:00
jgromes
eeff547aa4 [SX126x] Fix preamble detector configuration (#1350) 2024-12-16 18:49:18 +00:00
jgromes
5a8ba0003b [SX126x] Fix broken FSK packet params calls (#1350) (#1338) 2024-12-16 08:19:15 +00:00
jgromes
75f087b5c2 [SX126x] Use length from startReceive in implicit header mode 2024-12-15 15:53:13 +01:00
jgromes
ded508cc25 [SX128x] Use length from startReceive in implicit header mode 2024-12-15 15:53:06 +01:00
jgromes
0cc72c8310 [SX127x] Use length from startReceive in implicit header mode (#1345) 2024-12-15 15:48:05 +01:00
jgromes
111de250ec [CC1101] Clarify maximum packet length (#1347) 2024-12-14 14:49:23 +01:00
jgromes
f2a8a894d9 [CI] Add Silicon Labs board to supported platforms 2024-12-14 14:30:56 +01:00
Jan Gromeš
933981e97d
Merge pull request #1343 from lyusupov/master
fix build with Arduino Core for Silicon Labs EFR32 Series 2
2024-12-14 14:27:12 +01:00
StevenCellist
957a533089 [LoRaWAN] Do not reject first JoinAccept for 1.0.4 on Chirpstack 2024-12-14 12:39:27 +01:00
Linar Yusupov
67e5c6ee7b
fix build with Arduino Core for Silicon Labs EFR32 Series 2 2024-12-11 13:57:59 +03:00
jgromes
577a0761ac [SX126x] Make Tx timeout at least 5 ms (#1338) 2024-12-08 10:15:22 +01:00
jgromes
116d60deb2 [SX128x] Make Tx timeout at least 5 ms 2024-12-08 10:14:26 +01:00
jgromes
a692b72347 Move ESP-IDF HAL back to examples (#1322) 2024-11-30 21:53:48 +01:00
StevenCellist
5d6ca6251f [LoRaWAN] Code style fixes 2024-11-26 23:03:09 +01:00
StevenCellist
5e063e7ad8 [LoRaWAN] Update revision naming / RP revision B 2024-11-26 22:27:18 +01:00
StevenCellist
3e634ffb88 [LoRaWAN] Simplify JoinRequest datarate handling 2024-11-26 22:26:12 +01:00
jgromes
855a64c053 [SX126x] Allow SX1261 version string for LLCC68 devices (#1329) 2024-11-26 19:46:43 +01:00
jgromes
24f1535088 [SX126x] Fix upper power range in doxygen 2024-11-24 10:38:35 +01:00
jgromes
0bd5bdc896 [SX126x] Allow 15 dBm on SX1261 (#1329) 2024-11-24 09:29:58 +01:00
jgromes
35f18b049b [LLCC68] Added note about different configuration 2024-11-22 17:16:27 +01:00
jgromes
53e7a309a0 [LLCC68] Added LLCC68 examples 2024-11-22 17:14:59 +01:00
jgromes
ef16e431af [LR11x0] Disable DIO11 for GNSS only (#1275) 2024-11-21 20:09:05 +01:00
jgromes
8d119fc242 [SX128x] Fixed order of ISR functions in examples 2024-11-19 18:52:27 +01:00
jgromes
17bcfcd0bb [SX127x] Fixed order of ISR functions in examples 2024-11-19 18:52:21 +01:00
jgromes
a579eed780 [SX126x] Fixed order of ISR functions in examples 2024-11-19 18:52:16 +01:00
jgromes
0a6d6a26e1 [STM32WLx] Fixed order of ISR functions in examples 2024-11-19 18:52:10 +01:00
jgromes
12d81e6d0f [Si443x] Fixed order of ISR functions in examples 2024-11-19 18:52:02 +01:00
jgromes
1fa7d479ad [RF69] Fixed order of ISR functions in examples 2024-11-19 18:51:57 +01:00
jgromes
f95de45be7 [nRF24] Fixed order of ISR functions in examples 2024-11-19 18:51:49 +01:00
jgromes
2dd69398e3 [LR11x0] Fixed order of ISR functions in examples 2024-11-19 18:51:42 +01:00
jgromes
b33647adc3 [CC1101] Fixed order of ISR functions in examples 2024-11-19 18:51:30 +01:00
Jan Gromeš
b3efc8445c
[STM32WLx] Merge pull request #1326 from radiohound/master
Change order of setFlag function
2024-11-19 18:03:29 +01:00
Walter Dunckel
8eb6f0cf24
Change order of setFlag function
The change allows the code to compile. The same issue exists with a few other examples too.
2024-11-19 06:30:10 -08:00
jgromes
c467b005c2 [SX127x] Add missing state initialization (#1321) 2024-11-18 18:24:12 +01:00
jgromes
c7d6ad3e95 Remove an outdated comment 2024-11-17 19:43:40 +01:00
Alistair Francis
9d9d480a48
hal: Tock: Namespace HAL, update timer implementation and update libtock-c (#1313)
* tock: use native time getter, remove globals

Tock has direct support for querying time. The prior `millis()`
method here replicated the same functionality, but missed some
corner case concerns around overflow/wrapping. Instead, just use
the native Tock time getter method. This also removes unneeded
global variables and methods.

* NonArduino/Tock: Update to latest libtock-c

Update to the latest libtock-c commit. libtock-c now includes a
libtockHal.h, so we can use that instead of the version here.

Signed-off-by: Alistair Francis <alistair@alistair23.me>

---------

Signed-off-by: Alistair Francis <alistair@alistair23.me>
Co-authored-by: Pat Pannuto <pat.pannuto@gmail.com>
2024-11-14 18:51:00 +01:00
jgromes
f3a8c6dc2d Add link to online debug decoder 2024-11-10 17:47:15 +01:00
jgromes
9ac8bb9a7e Drop debug decoder 2024-11-10 17:45:24 +01:00
jgromes
29ede2c354 [MOD] Optimize SPI register writing 2024-11-10 17:43:28 +01:00
jgromes
fe52311371 [SX127x] Added parameter doc and keyword 2024-11-03 18:27:51 +01:00
SzczepanLeon
cb45f4fe5e
[SX127x/RF69] Added setFifoThreshold (#1309)
* [SX127x] Added setFifoThreshold

* [SX127x] Added setFifoThreshold

* Add setFifoThreshold to RF69 class.

* Documentation update, about setFifoThreshold.
2024-11-03 18:25:44 +01:00
jgromes
49868938d6 Update links to status decoder 2024-11-03 12:57:19 +01:00
jgromes
f15de1e7dd Added missing links to doxygen mainpage 2024-11-03 11:16:26 +01:00
jgromes
72ecc275af Added links to status code decoder to issue templates 2024-11-02 17:38:41 +01:00
Alistair Francis
b1d8850d92
hal: Tock: Re-enable pin after detaching interrupt (#1308)
The Tock libtock_lora_phy_gpio_disable_interrupt() syscall will disable
interrupts for the pin, but also put the pin into a disabled low power
state. This isn't what RadioLib expects and casues subsequent LoRaWAN
transfers to fail [1].

So after we disable interrupts and send the pin to low power let's
re-enable inputs as RadioLib expects.

1: https://github.com/jgromes/RadioLib/discussions/1303

Signed-off-by: Alistair Francis <alistair@alistair23.me>
2024-11-02 12:38:43 +01:00
jgromes
e9dd3dc843 Added quick links to readme 2024-11-02 11:01:43 +01:00
Victor Barpp Gomes
a608075fc1
[LoRaWAN] Accept const uint8_t* on public API (#1302) 2024-11-01 17:47:02 +01:00
jgromes
4564d87721 [PHY] Use less generic modem names (#1294) 2024-10-29 17:14:04 +00:00
jgromes
0096c11f99 [CC1101] Added support for 4-FSK (#823) 2024-10-28 21:32:20 +01:00
jgromes
8f3a5c7430 [LR11x0] Use array as LR-FHSS sync word 2024-10-28 18:52:07 +00:00
jgromes
15a751a543 [SX126x] Fix LR-FHSS sync word 2024-10-28 18:51:43 +00:00
160 changed files with 4211 additions and 3032 deletions

View file

@ -7,8 +7,8 @@ assignees: ''
---
**IMPORTANT: Check the wiki**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
**IMPORTANT: Check the docs**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). If you are seeing an error code, we have [online status code decoder](https://radiolib-org.github.io/status_decoder/decode.html).
**Describe the bug**
A clear and concise description of what the bug is. When applicable, please include [debug mode output](https://github.com/jgromes/RadioLib/wiki/Debug-mode) **using the appropriate debug mode**.

View file

@ -7,8 +7,8 @@ assignees: ''
---
**IMPORTANT: Check the wiki**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
**IMPORTANT: Check the docs**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). If you are seeing an error code, we have [online status code decoder](https://radiolib-org.github.io/status_decoder/decode.html).
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

View file

@ -9,7 +9,7 @@ assignees: ''
**IMPORTANT: Before submitting an issue, please check the following:**
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). If you are seeing an error code, we have [online status code decoder](https://radiolib-org.github.io/status_decoder/decode.html).
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).

View file

@ -9,7 +9,7 @@ assignees: ''
**IMPORTANT: Before submitting an issue, please check the following:**
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). If you are seeing an error code, we have [online status code decoder](https://radiolib-org.github.io/status_decoder/decode.html).
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).

View file

@ -36,6 +36,7 @@ on:
- MegaCore:avr:1281
- teensy:avr:teensy41
- arduino:renesas_uno:minima
- SiliconLabs:silabs:xg24explorerkit
jobs:
build:
@ -82,14 +83,16 @@ jobs:
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
echo "options=':xtal=80,ResetMethod=ck,CrystalFreq=26,FlashFreq=40,FlashMode=qio,eesz=512K'" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls http://arduino.esp8266.com/stable/package_esp8266com_index.json" >> $GITHUB_OUTPUT
- id: STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
- id: STMicroelectronics:stm32:GenF3
run: |
echo "options=':pnum=BLACKPILL_F303CC'" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
- id: STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
- id: STMicroelectronics:stm32:Nucleo_64
run: |
echo "options=':pnum=NUCLEO_WL55JC1'" >> $GITHUB_OUTPUT
# Do *not* skip STM32WL examples
echo "skip-pattern='LR11x0_Firmware_Update'" >> $GITHUB_OUTPUT
echo "skip-pattern=(LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
- id: stm32duino:STM32F1:mapleMini
run: |
@ -118,6 +121,9 @@ jobs:
- id: arduino:renesas_uno:minima
run: |
echo "skip-pattern=(STM32WL|LoRaWAN|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
- id: SiliconLabs:silabs:xg24explorerkit
run: |
echo "index-url=--additional-urls https://siliconlabs.github.io/arduino/package_arduinosilabs_index.json" >> $GITHUB_OUTPUT
runs-on: ubuntu-latest
name: ${{ matrix.id }}
@ -176,28 +182,64 @@ jobs:
if: ${{ env.run-build == 'true' }}
run:
|
for example in $(find $PWD/examples -name '*.ino' | sort); do
# check whether to skip this sketch
if [ ! -z '${{ steps.prep.outputs.skip-pattern }}' ] && [[ ${example} =~ ${{ steps.prep.outputs.skip-pattern }} ]]; then
# skip sketch
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with ${{ steps.prep.outputs.skip-pattern }})\033[0m";
else
# apply special flags for LoRaWAN
if [[ ${example} =~ "LoRaWAN" ]]; then
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
fi
cd $PWD/extras/test/ci
./build_examples.sh ${{ matrix.id }} "${{ steps.prep.outputs.skip-pattern }}" ${{ steps.prep.outputs.options }}
- name: Extract short commit hash
id: short-hash
run: echo "::set-output name=short_sha::$(git rev-parse --short HEAD)"
- name: Parse sizes
if: ${{ env.run-build == 'true' }}
run:
|
cd $PWD/extras/test/ci
./parse_size.sh ${{ matrix.id }}
cat size_${{ steps.short-hash.outputs.short_sha }}_${{ steps.split.outputs._0 }}-${{ steps.split.outputs._1 }}-${{ steps.split.outputs._2 }}.csv
- name: Upload size report as artifact
uses: actions/upload-artifact@v4
with:
name: size-file-${{ steps.split.outputs._0 }}-${{ steps.split.outputs._1 }}-${{ steps.split.outputs._2 }}
path: extras/test/ci/size_${{ steps.short-hash.outputs.short_sha }}_${{ steps.split.outputs._0 }}-${{ steps.split.outputs._1 }}-${{ steps.split.outputs._2 }}.csv
# build sketch
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn ${{ matrix.id }}${{ steps.prep.outputs.options }} --build-property compiler.cpp.extra_flags="$flags" $example --warnings=${{ steps.prep.outputs.warnings }}
if [ $? -ne 0 ]; then
echo -e "\033[1;31m${example##*/} build FAILED\033[0m\n";
exit 1;
else
echo -e "\033[1;32m${example##*/} build PASSED\033[0m\n";
fi
fi
done
metrics:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/master'
steps:
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ACTIONS_METRICS_DEPLOY_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
- name: Clone artifact repo
run:
|
cd $PWD/..
git clone git@github.com:radiolib-org/artifacts.git
cd artifacts
git config --global user.name "${{ github.actor }}"
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
- name: Download size artifacts
uses: actions/download-artifact@v4
with:
path: aggregated-sizes
- name: Push size files
run:
|
ls -R aggregated-sizes
mkdir -p $PWD/../artifacts/radiolib-ci/l0
cp aggregated-sizes/*/size_*.csv $PWD/../artifacts/radiolib-ci/l0/.
cd $PWD/../artifacts/radiolib-ci
git add .
COMMIT_URL="https://github.com/jgromes/RadioLib/commit/$GITHUB_SHA"
git commit -m "Push artifacts from $COMMIT_URL"
git push origin main
esp-build:
runs-on: ubuntu-latest
@ -247,10 +289,11 @@ jobs:
run: |
cd $PWD/examples/NonArduino/Tock
git clone https://github.com/tock/libtock-c.git
cd libtock-c; git checkout dbee65a56d74b4bad166317f199e80b959f7c82c; cd ../
cd libtock-c; git checkout c0202f9ab78da4a6e95f136cf5250701e3778f63; cd ../
LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
rpi-build:
if: false # self-hosted runner temporarily disabled
runs-on: [self-hosted, ARM64]
steps:
- name: Checkout repository
@ -282,6 +325,7 @@ jobs:
./build.sh
rpi-test:
if: false # self-hosted runner temporarily disabled
needs: rpi-build
runs-on: [self-hosted, ARM64]
steps:

37
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: "Release"
on: workflow_dispatch
jobs:
release:
name: Release RadioLib update
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Checkout latest tag
run: git checkout $(git describe --tags $(git rev-list --tags --max-count=1))
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install PlatformIO and ESP-IDF
run: |
pip install --upgrade platformio
pip install --upgrade idf-component-manager
- name: PlatformIO publish
env:
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
run: pio pkg publish --no-interactive
- name: ESP-IDF publish
env:
IDF_COMPONENT_API_TOKEN: ${{ secrets.IDF_COMPONENT_API_TOKEN }}
run: compote component upload --name RadioLib --namespace jgromes

48
.github/workflows/unit-test.yml vendored Normal file
View file

@ -0,0 +1,48 @@
name: "Unit test"
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
unit-test:
name: Build and run unit test
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libboost-all-dev libfmt-dev lcov
- name: Run unit test
run: |
cd extras/test/unit
./test.sh
- name: Measure test coverage
run: |
cd extras/test/unit
./coverage.sh
- name: Upload coverage report as artifact
uses: actions/upload-artifact@v4
with:
name: coverage_report
path: extras/test/unit/lcov.report
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/master'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: gh-pages
publish_dir: extras/test/unit/lcov.report
destination_dir: coverage
keep_files: true

7
.gitignore vendored
View file

@ -11,13 +11,6 @@
# Jetbrain IDEs
.idea
# Debug decoder
extras/decoder/log.txt
extras/decoder/out.txt
# Spectrum scan
extras/SX126x_Spectrum_Scan/out/*
# PlatformIO
.pio*

View file

@ -36,7 +36,7 @@ target_include_directories(RadioLib
set_property(TARGET RadioLib PROPERTY CXX_STANDARD 20)
# enable most warnings
target_compile_options(RadioLib PRIVATE -Wall -Wextra)
target_compile_options(RadioLib PRIVATE -Wall -Wextra -Wpedantic -Wdouble-promotion)
include(GNUInstallDirs)

View file

@ -4,8 +4,6 @@
## Universal wireless communication library for embedded devices
## See the [Wiki](https://github.com/jgromes/RadioLib/wiki) and [FAQ](https://github.com/jgromes/RadioLib/wiki/Frequently-Asked-Questions) for further information. See the [GitHub Pages](https://jgromes.github.io/RadioLib) for detailed and up-to-date API reference.
RadioLib allows its users to integrate all sorts of different wireless communication modules, protocols and even digital modes into a single consistent system.
Want to add a Bluetooth interface to your LoRa network? Sure thing! Do you just want to go really old-school and play around with radio teletype, slow-scan TV, or even Hellschreiber using nothing but a cheap radio module? Why not!
@ -13,6 +11,13 @@ RadioLib natively supports Arduino, but can run in non-Arduino environments as w
RadioLib was originally created as a driver for [__RadioShield__](https://github.com/jgromes/RadioShield), but it can be used to control as many different wireless modules as you like - or at least as many as your microcontroller can handle!
### Quick links:
* [__Wiki__](https://github.com/jgromes/RadioLib/wiki) - contains useful general information on using this library
* [__FAQ__](https://github.com/jgromes/RadioLib/wiki/Frequently-Asked-Questions) - frequently asked questions, and answers
* [__API Reference__](https://jgromes.github.io/RadioLib) - full API reference, automatically generated from the source code
* [__Status Code Decoder__](https://radiolib-org.github.io/status_decoder/decode.html) - decoder for status codes returned by RadioLib methods
* [__Debug Log Decoder__](https://radiolib-org.github.io/debug_decoder/decode.html) - decoder for RadioLib SPI debug logs
### Supported modules:
* __CC1101__ FSK radio module
* __LLCC68__ LoRa module
@ -43,7 +48,7 @@ SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
* [__POCSAG__](https://www.sigidwiki.com/wiki/POCSAG) using 2-FSK for modules:
SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
* [__LoRaWAN__](https://lora-alliance.org/) using LoRa for modules:
* [__LoRaWAN__](https://lora-alliance.org/) using LoRa and FSK for modules:
SX127x, RFM9x, SX126x, LR11x0 and SX128x
### Supported Arduino platforms:
@ -89,4 +94,7 @@ SX127x, RFM9x, SX126x, LR11x0 and SX128x
* __PJRC__
* [__Teensy__](https://github.com/PaulStoffregen/cores) - Teensy 2.x, 3.x and 4.x boards
* __Silicon Labs__
* [__EFR32__](https://github.com/SiliconLabs/arduino) - Silicon Labs xG24, xG27 and other boards
The list above is by no means exhaustive - RadioLib code is independent of the used platform! Compilation of all examples is tested for all platforms officially supported prior to releasing new version. In addition, RadioLib includes an internal hardware abstraction layer, which allows it to be easily ported even to non-Arduino environments.

View file

@ -37,6 +37,21 @@ CC1101 radio = new Module(10, 2, RADIOLIB_NC, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -76,21 +91,6 @@ void setup() {
// radio.readData();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -82,10 +82,11 @@ void setup() {
void loop() {
Serial.print(F("[CC1101] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to 63 characters long
// you can transmit C-string or Arduino string up to 255 characters long
int state = radio.transmit("Hello World!");
// you can also transmit byte array up to 63 bytes long
// you can also transmit byte array up to 255 bytes long
// With some limitations see here: https://github.com/jgromes/RadioLib/discussions/1138
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);

View file

@ -2,7 +2,7 @@
RadioLib CC1101 Blocking Transmit Example
This example transmits packets using CC1101 FSK radio module.
Each packet contains up to 64 bytes of data, in the form of:
Each packet contains up to 255 bytes of data with some limitations (https://github.com/jgromes/RadioLib/discussions/1138), in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
@ -57,11 +57,11 @@ int count = 0;
void loop() {
Serial.print(F("[CC1101] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to 63 characters long
// you can transmit C-string or Arduino string up to 255 characters long
String str = "Hello World! #" + String(count++);
int state = radio.transmit(str);
// you can also transmit byte array up to 63 bytes long
// you can also transmit byte array up to 255 bytes long with some limitations; https://github.com/jgromes/RadioLib/discussions/1138
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);
@ -72,7 +72,7 @@ void loop() {
Serial.println(F("success!"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 64 bytes
// the supplied packet was longer than 255 bytes
Serial.println(F("too long!"));
} else {

View file

@ -3,7 +3,7 @@
This example transmits packets using CC1101 FSK radio module.
Once a packet is transmitted, an interrupt is triggered.
Each packet contains up to 64 bytes of data, in the form of:
Each packet contains up to 255 bytes of data with some limitations (https://github.com/jgromes/RadioLib/discussions/1138), in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
@ -36,6 +36,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -58,10 +73,12 @@ void setup() {
Serial.print(F("[CC1101] Sending first packet ... "));
// you can transmit C-string or Arduino string up to
// 64 characters long
// 255 characters long
transmissionState = radio.startTransmit("Hello World!");
// you can also transmit byte array up to 64 bytes long
// you can also transmit byte array up to 255 bytes long
// When transmitting more than 64 bytes startTransmit blocks to refill the FIFO.
// Blocking ceases once the last bytes have been placed in the FIFO
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x56,
0x78, 0xAB, 0xCD, 0xEF};
@ -69,21 +86,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;
@ -119,11 +121,11 @@ void loop() {
Serial.print(F("[CC1101] Sending another packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
// 255 characters long
String str = "Hello World! #" + String(count++);
transmissionState = radio.startTransmit(str);
// you can also transmit byte array up to 256 bytes long
// you can also transmit byte array up to 255 bytes long with limitations https://github.com/jgromes/RadioLib/discussions/1138
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};

View file

@ -57,6 +57,21 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
END_OF_MODE_TABLE,
};
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -89,21 +104,6 @@ void setup() {
}
}
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -62,7 +62,8 @@ void setup() {
3, // header count
0x13A); // hopping sequence seed
state = radio.setOutputPower(10.0);
state = radio.setSyncWord(0x12345678);
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67};
state = radio.setSyncWord(syncWord, 4);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Unable to set configuration, code "));
Serial.println(state);

View file

@ -63,6 +63,21 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
END_OF_MODE_TABLE,
};
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -105,21 +120,6 @@ void setup() {
// radio.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -62,6 +62,21 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -98,21 +113,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -60,6 +60,20 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
END_OF_MODE_TABLE,
};
// flag to indicate that a scan was completed
volatile bool scanFlag = false;
// this function is called when a scan is completed
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// scan is complete, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -92,20 +106,6 @@ void setup() {
}
}
// flag to indicate that a scan was completed
volatile bool scanFlag = false;
// this function is called when a scan is completed
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// scan is complete, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -41,9 +41,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
const LoRaWANBand_t Region = EU868;
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
const uint8_t subBand = 0;
// ============================================================================
// Below is to support the sketch - only make changes if the notes say so ...

View file

@ -48,6 +48,9 @@ void setup() {
// Override the default join rate
uint8_t joinDR = 4;
// Optionally provide a custom sleep function - see config.h
//node.setSleepFunction(customDelay);
// Setup the OTAA session information
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
@ -68,7 +71,7 @@ void setup() {
// Manages uplink intervals to the TTN Fair Use Policy
node.setDutyCycle(true, 1250);
// Enable the dwell time limits - 400ms is the limit for the US
// Update dwell time limits - 400ms is the limit for the US
node.setDwellTime(true, 400);
Serial.println(F("Ready!\n"));

View file

@ -37,9 +37,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
const LoRaWANBand_t Region = EU868;
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
const uint8_t subBand = 0;
// ============================================================================
// Below is to support the sketch - only make changes if the notes say so ...
@ -142,4 +144,19 @@ void arrayDump(uint8_t *buffer, uint16_t len) {
Serial.println();
}
// Custom delay function:
// Communication over LoRaWAN includes a lot of delays.
// By default, RadioLib will use the Arduino delay() function,
// which will waste a lot of power. However, you can put your
// microcontroller to sleep instead by customizing the function below,
// and providing it to RadioLib via "node.setSleepFunction".
// NOTE: You ahve to ensure that this function is timed precisely, and
// does actually wait for the amount of time specified!
// Failure to do so will result in missed downlinks or failed join!
void customDelay(RadioLibTime_t ms) {
// this is just an example, so we use the Arduino delay() function,
// but you can put your microcontroller to sleep here
::delay(ms);
}
#endif

View file

@ -37,9 +37,11 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN500
// regional choices: EU868, US915, AU915, AS923, AS923_2, AS923_3, AS923_4, IN865, KR920, CN470
const LoRaWANBand_t Region = EU868;
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
// subband choice: for US915/AU915 set to 2, for CN470 set to 1, otherwise leave on 0
const uint8_t subBand = 0;
// ============================================================================
// Below is to support the sketch - only make changes if the notes say so ...

View file

@ -52,7 +52,7 @@ You are making your own device using a third party LoRaWAN stack so there will n
Choose the Frequency plan appropriate for your region. Consider that almost all countries have laws relating to what frequencies you use so don't get creative. For Europe please use the recommended option. For other regions use the entry marked 'used by TTN'.
Choose LoRaWAN 1.1.0 - the last one in the list - the latest specfication. RadioLib uses RP001 Regional Parameters 1.1 revision A.
Choose LoRaWAN 1.1.0 - the last one in the list - the latest specfication. RadioLib uses RP001 Regional Parameters 1.1 revision B.
At this point you will be asked for your JoinEUI. As this is a DIY device and we are using RadioLib, you can use all zero's as recommended by The LoRa Alliance TR007 Technical Recommendations document. Once you've put in all zeros and clicked confirm you will be asked for a DevEUI, AppKey and NwkKey. It is preferable to have the console generate them so they are properly formatted.

View file

@ -6,17 +6,17 @@ RadioLib LoRaWAN examples.
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA (but why?), this example shows how you can do this using RadioLib.
## LoRaWAN versions & regional parameters
RadioLib implements both LoRaWAN v1.1 and v1.0.4. Confusingly, v1.0.4 is newer than v1.1, but v1.1 includes more security checks and as such **LoRaWAN v1.1 is preferred**.
The catch is in the Regional Parameters: as v1.0.4 is newer, it is more up to date regarding local laws & regulations. Therefore, RadioLib implements 1.0.4 as baseline and 1.1 as fallback, but **Regional Parameters v1.0.4 is preferred**.
_Note: the CN500 band is implemented as specified in RP v1.1, as the RP v1.0.4 version is much too complex._
RadioLib implements both LoRaWAN Specification 1.1 and 1.0.4. Confusingly, 1.0.4 is newer than 1.1, but 1.1 includes more security checks and as such **LoRaWAN 1.1 is preferred**.
The catch is in the Regional Parameters: as RP002 1.0.4 is newer than RP001 1.1, it is more up to date regarding local laws & regulations. Therefore, RadioLib implements 1.0.4 as baseline and 1.1 (revision B) as fallback, and as such **RP002 Regional Parameters 1.0.4 is preferred**.
_Note: the CN470 band is implemented as specified in RP001 1.1 revision B, as the RP002 1.0.4 version is much too complex._
To activate a LoRaWAN v1.1 session, supply all the required keys:
To activate a LoRaWAN 1.1 session, supply all the required keys:
```cpp
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey);
```
To activate a LoRaWAN v1.0.4 session, set the keys that are not available to `NULL`:
To activate a LoRaWAN 1.0.4 session, set the keys that are not available to `NULL`:
```cpp
node.beginOTAA(joinEUI, devEUI, NULL, appKey);
node.beginABP(devAddr, NULL, NULL, nwkSEncKey, appSKey);
@ -26,9 +26,9 @@ The device doesn't need to know the Regional Parameters version - that is of imp
## LoRaWAN persistence
> [!WARNING]
> These examples do not actually comply with LoRaWAN v1.0.4/v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
> These examples do not actually comply with LoRaWAN 1.0.4/1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN v1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN 1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
Currently, examples are available for the following platforms:
* [LoRaWAN for ESP32](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP32)

View file

@ -7,7 +7,7 @@
// this example only works on ESP32 and is unlikely to work on ESP32S2/S3 etc.
// if you need high portability, you should probably use Arduino anyway ...
#if CONFIG_IDF_TARGET_ESP32 == 0
#error Target is not ESP32!
#error This example HAL only supports ESP32 targets. Support for ESP32S2/S3 etc. can be added by adjusting this file to user needs.
#endif
// include all the dependencies

View file

@ -17,7 +17,7 @@
#include <RadioLib.h>
// include the hardware abstraction layer
#include "hal/ESP-IDF/EspHal.h"
#include "EspHal.h"
// create a new instance of the HAL class
EspHal* hal = new EspHal(5, 19, 27);

View file

@ -50,7 +50,21 @@ add_executable(${PROJECT_NAME} main.cpp)
# The build system for libtock-c is a bit odd and the version of libraries
# built changes based on compiler version.
if (RISCV_BUILD)
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0")
target_link_libraries(${PROJECT_NAME} PUBLIC
RadioLib
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/rv32imc/libtocksync.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0/riscv/lib/gcc/riscv64-unknown-elf/14.1.0/rv32i/ilp32/libgcc.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libstdc++.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.4.0.20231231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.4.0.20231231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libm.a
)
target_include_directories(RadioLib AFTER PUBLIC
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/include/
)
elseif(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
target_link_libraries(${PROJECT_NAME} PUBLIC
RadioLib
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
@ -80,7 +94,17 @@ if (RISCV_BUILD)
)
endif()
else()
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
if (EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0")
target_link_libraries(${PROJECT_NAME} PUBLIC
RadioLib
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/cortex-m4/libtocksync.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0/arm/lib/gcc/arm-none-eabi/14.1.0/libgcc.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-14.1.0/arm/arm-none-eabi/lib/libstdc++.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.4.0.20231231/arm/arm-none-eabi/lib/libc.a
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.4.0.20231231/arm/arm-none-eabi/lib/libm.a
)
elseif(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
target_link_libraries(${PROJECT_NAME} PUBLIC
RadioLib
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a

View file

@ -23,7 +23,7 @@ The RadioLib example can be built with:
$ git clone https://github.com/jgromes/RadioLib.git
$ cd RadioLib/examples/NonArduino/Tock/
$ git clone https://github.com/tock/libtock-c.git
$ cd libtock-c; git checkout dbee65a56d74b4bad166317f199e80b959f7c82c; cd ../
$ cd libtock-c; git checkout c0202f9ab78da4a6e95f136cf5250701e3778f63; cd ../
$ LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
```

View file

@ -3,9 +3,9 @@ set -e
rm -rf ./build-*
cd libtock-c/examples/cxx_hello
pushd ${LIBTOCK_C_DIRECTORY}/examples/cxx_hello
make -j4
cd ../../../
popd
mkdir -p build-arm
cd build-arm

View file

@ -28,14 +28,14 @@
#include <RadioLib.h>
// include the hardware abstraction layer
#include "hal/Tock/libtockHal.h"
#include "RadioLib/libtockHal.h"
// the entry point for the program
int main(void) {
printf("[SX1261] Initialising Radio ... \r\n");
// create a new instance of the HAL class
TockHal* hal = new TockHal();
TockRadioLibHal* hal = new TockRadioLibHal();
// now we can create the radio module
// pinout corresponds to the SparkFun LoRa Thing Plus - expLoRaBLE
@ -43,7 +43,7 @@ int main(void) {
// DIO1 pin: 2
// NRST pin: 4
// BUSY pin: 1
Module* tock_module = new Module(hal, RADIO_NSS, RADIO_DIO_1, RADIO_RESET, RADIO_BUSY);
Module* tock_module = new Module(hal, RADIOLIB_RADIO_NSS, RADIOLIB_RADIO_DIO_1, RADIOLIB_RADIO_RESET, RADIOLIB_RADIO_BUSY);
SX1262* radio = new SX1262(tock_module);
// Setup the radio

View file

@ -29,6 +29,21 @@ RF69 radio = new Module(10, 2, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -68,21 +83,6 @@ void setup() {
// radio.readData();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -35,6 +35,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -85,21 +100,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -33,6 +33,18 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
END_OF_MODE_TABLE,
};
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -66,18 +78,6 @@ void setup() {
}
}
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -43,6 +43,18 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
END_OF_MODE_TABLE,
};
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -97,18 +109,6 @@ void setup() {
// radio.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -38,6 +38,18 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -85,18 +97,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -33,6 +33,21 @@ SX1262 radio = new Module(10, 2, 3, 9);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -62,21 +77,6 @@ void setup() {
}
}
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -35,6 +35,24 @@ SX1262 radio = new Module(10, 2, 3, 9);
Radio radio = new RadioModule();
*/
// whether we are receiving, or scanning
bool receiving = false;
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -64,23 +82,6 @@ void setup() {
}
}
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
bool receiving = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -126,33 +126,4 @@ void loop() {
Serial.println(F("[SX1262] Failed to receive packet, code "));
Serial.println(state);
}
// FSK modem has built-in address filtering system
// it can be enabled by setting node address, broadcast
// address, or both
//
// to transmit packet to a particular address,
// use the following methods:
//
// radio.transmit("Hello World!", address);
// radio.startTransmit("Hello World!", address);
// set node address to 0x02
state = radio.setNodeAddress(0x02);
// set broadcast address to 0xFF
state = radio.setBroadcastAddress(0xFF);
if (state != RADIOLIB_ERR_NONE) {
Serial.println(F("[SX1262] Unable to set address filter, code "));
Serial.println(state);
}
// address filtering can also be disabled
// NOTE: calling this method will also erase previously set
// node and broadcast address
/*
state = radio.disableAddressFiltering();
if (state != RADIOLIB_ERR_NONE) {
Serial.println(F("Unable to remove address filter, code "));
}
*/
}

View file

@ -1,95 +0,0 @@
/*
RadioLib SX126x LR-FHSS Modem Example
This example shows how to use LR-FHSS modem in SX126x chips.
This modem can only transmit data, and is not able to receive.
NOTE: The sketch below is just a guide on how to use
LR-FHSS modem, so this code should not be run directly!
Instead, modify the other examples to use LR-FHSS
modem and use the appropriate configuration
methods.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1262 has the following connections:
// NSS pin: 10
// IRQ pin: 2
// NRST pin: 3
// BUSY pin: 9
SX1262 radio = new Module(10, 2, 3, 9);
// or detect the pinout automatically using RadioBoards
// https://github.com/radiolib-org/RadioBoards
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
int state = radio.beginLRFHSS();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true) { delay(10); }
}
// if needed, you can switch between any of the modems
//
// radio.begin() start LoRa modem (and disable LR-FHSS)
// radio.beginLRFHSS() start LR-FHSS modem (and disable LoRa)
// the following settings can also
// be modified at run-time
state = radio.setFrequency(433.5);
state = radio.setLrFhssConfig(RADIOLIB_SX126X_LR_FHSS_BW_1523_4, // bandwidth
RADIOLIB_SX126X_LR_FHSS_CR_1_2, // coding rate
3, // header count
0x13A); // hopping sequence seed
state = radio.setOutputPower(10.0);
state = radio.setSyncWord(0x12345678);
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Unable to set configuration, code "));
Serial.println(state);
while (true) { delay(10); }
}
#warning "This sketch is just an API guide! Read the note at line 6."
}
void loop() {
// LR-FHSS modem can only transmit!
// transmit LR-FHSS packet
int state = radio.transmit("Hello World!");
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);
*/
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("[SX1262] Packet transmitted successfully!"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
Serial.println(F("[SX1262] Packet too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
Serial.println(F("[SX1262] Timed out while transmitting!"));
} else {
Serial.println(F("[SX1262] Failed to transmit packet, code "));
Serial.println(state);
}
}

View file

@ -0,0 +1,113 @@
/*
RadioLib SX126x LR-FHSS Modem Example
This example shows how to use LR-FHSS modem in SX126x chips.
This modem can only transmit data, and is not able to receive.
This example transmits packets using SX1262 LoRa radio module.
Each packet contains up to 256 bytes of data, in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
Other modules from SX126x family can also be used.
Using blocking transmit is not recommended, as it will lead
to inefficient use of processor time!
Instead, interrupt transmit is recommended.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1262 has the following connections:
// NSS pin: 10
// IRQ pin: 2
// NRST pin: 3
// BUSY pin: 9
SX1262 radio = new Module(10, 2, 3, 9);
// or detect the pinout automatically using RadioBoards
// https://github.com/radiolib-org/RadioBoards
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
int state = radio.beginLRFHSS();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true) { delay(10); }
}
// some modules have an external RF switch
// controlled via two pins (RX enable, TX enable)
// to enable automatic control of the switch,
// call the following method
// RX enable: 4
// TX enable: 5
/*
radio.setRfSwitchPins(4, 5);
*/
}
// counter to keep track of transmitted packets
int count = 0;
void loop() {
// LR-FHSS modem can only transmit!
Serial.print(F("[SX1262] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
String str = "Hello World! #" + String(count++);
int state = radio.transmit(str);
// you can also transmit byte array up to 256 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);
*/
if (state == RADIOLIB_ERR_NONE) {
// the packet was successfully transmitted
Serial.println(F("success!"));
// print measured data rate
Serial.print(F("[SX1262] Datarate:\t"));
Serial.print(radio.getDataRate());
Serial.println(F(" bps"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
// the supplied packet was longer than 256 bytes
Serial.println(F("too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
// timeout occurred while transmitting packet
Serial.println(F("timeout!"));
} else {
// some other error occurred
Serial.print(F("failed, code "));
Serial.println(state);
}
// wait for a second before transmitting again
delay(1000);
}

View file

@ -0,0 +1,151 @@
/*
RadioLib SX126x LR-FHSS Transmit with Interrupts Example
This example shows how to use LR-FHSS modem in SX126x chips.
This modem can only transmit data, and is not able to receive.
This example transmits packets using SX1262 LoRa radio module.
Each packet contains up to 256 bytes of data, in the form of:
- Arduino String
- null-terminated char array (C-string)
- arbitrary binary data (byte array)
Other modules from SX126x family can also be used.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lr-fhss-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1262 has the following connections:
// NSS pin: 10
// IRQ pin: 2
// NRST pin: 3
// BUSY pin: 9
SX1262 radio = new Module(10, 2, 3, 9);
// or detect the pinout automatically using RadioBoards
// https://github.com/radiolib-org/RadioBoards
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
// or a frequency hop is needed
volatile bool flag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet or need to hop, set the flag
flag = true;
}
void setup() {
Serial.begin(9600);
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
int state = radio.beginLRFHSS();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true) { delay(10); }
}
// set the function that will be called
// when packet transmission is finished
radio.setPacketSentAction(setFlag);
// start transmitting the first packet
Serial.print(F("[SX1262] Sending first packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
transmissionState = radio.startTransmit("Hello World!");
// you can also transmit byte array up to 256 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
state = radio.startTransmit(byteArr, 8);
*/
}
// counter to keep track of transmitted packets
int count = 0;
void loop() {
// LR-FHSS modem can only transmit!
// check if the previous transmission finished
if(flag) {
// reset flag
flag = false;
// check if this was caused by hopping or transmission finished
if(radio.getIrqFlags() & RADIOLIB_SX126X_IRQ_LR_FHSS_HOP) {
radio.hopLRFHSS();
} else {
if (transmissionState == RADIOLIB_ERR_NONE) {
// packet was successfully sent
Serial.println(F("transmission finished!"));
// NOTE: when using interrupt-driven transmit method,
// it is not possible to automatically measure
// transmission data rate using getDataRate()
} else {
Serial.print(F("failed, code "));
Serial.println(transmissionState);
}
// clean up after transmission is finished
// this will ensure transmitter is disabled,
// RF switch is powered down etc.
radio.finishTransmit();
// wait a second before transmitting again
delay(1000);
// send another one
Serial.print(F("[SX1262] Sending another packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
String str = "Hello World! #" + String(count++);
transmissionState = radio.startTransmit(str);
// you can also transmit byte array up to 256 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};
transmissionState = radio.startTransmit(byteArr, 8);
*/
}
}
}

View file

@ -39,6 +39,21 @@ SX1262 radio = new Module(10, 2, 3, 9);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -78,21 +93,6 @@ void setup() {
// radio.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -38,6 +38,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -71,21 +86,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -34,6 +34,36 @@ SX1278 radio = new Module(10, 2, 9, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a preamble was not detected
volatile bool timeoutFlag = false;
// flag to indicate that a preamble was detected
volatile bool detectedFlag = false;
// this function is called when no preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagTimeout(void) {
// we timed out, set the flag
timeoutFlag = true;
}
// this function is called when LoRa preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagDetected(void) {
// we got a preamble, set the flag
detectedFlag = true;
}
void setup() {
// Serial port speed must be high enough for this example
Serial.begin(115200);
@ -68,36 +98,6 @@ void setup() {
}
}
// flag to indicate that a preamble was not detected
volatile bool timeoutFlag = false;
// flag to indicate that a preamble was detected
volatile bool detectedFlag = false;
// this function is called when no preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagTimeout(void) {
// we timed out, set the flag
timeoutFlag = true;
}
// this function is called when LoRa preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagDetected(void) {
// we got a preamble, set the flag
detectedFlag = true;
}
void loop() {
// check if we need to restart channel activity detection
if(detectedFlag || timeoutFlag) {

View file

@ -39,6 +39,39 @@ SX1278 radio = new Module(10, 2, 9, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a preamble was not detected
volatile bool timeoutFlag = false;
// flag to indicate that a preamble was detected
volatile bool detectedFlag = false;
// flag to indicate if we are currently receiving
bool receiving = false;
// this function is called when no preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagTimeout(void) {
// we timed out, set the flag
timeoutFlag = true;
}
// this function is called when LoRa preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagDetected(void) {
// we got a preamble, set the flag
detectedFlag = true;
}
void setup() {
// Serial port speed must be high enough for this example
Serial.begin(115200);
@ -74,39 +107,6 @@ void setup() {
}
}
// flag to indicate that a preamble was not detected
volatile bool timeoutFlag = false;
// flag to indicate that a preamble was detected
volatile bool detectedFlag = false;
// flag to indicate if we are currently receiving
bool receiving = false;
// this function is called when no preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagTimeout(void) {
// we timed out, set the flag
timeoutFlag = true;
}
// this function is called when LoRa preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlagDetected(void) {
// we got a preamble, set the flag
detectedFlag = true;
}
void loop() {
// check if we need to restart channel activity detection
if(detectedFlag || timeoutFlag) {

View file

@ -32,6 +32,12 @@ const int pin = 5;
Radio radio = new RadioModule();
*/
// this function is called when a new bit is received
void readBit(void) {
// read the data bit
radio.readBit(pin);
}
void setup() {
Serial.begin(9600);
@ -59,12 +65,6 @@ void setup() {
radio.receiveDirect();
}
// this function is called when a new bit is received
void readBit(void) {
// read the data bit
radio.readBit(pin);
}
void loop() {
// we expect the packet to contain the string "Hello World!",
// a length byte and 2 CRC bytes, that's 15 bytes in total

View file

@ -39,6 +39,21 @@ SX1278 radio = new Module(10, 2, 9, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -78,21 +93,6 @@ void setup() {
// radio.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -38,6 +38,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -71,21 +86,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -31,6 +31,21 @@ SX1280 radio = new Module(10, 2, 3, 9);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void setup() {
Serial.begin(9600);
@ -60,21 +75,6 @@ void setup() {
}
}
// flag to indicate that a packet was detected or CAD timed out
volatile bool scanFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// something happened, set the flag
scanFlag = true;
}
void loop() {
// check if the flag is set
if(scanFlag) {

View file

@ -39,6 +39,21 @@ SX1280 radio = new Module(10, 2, 3, 9);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -79,21 +94,6 @@ void setup() {
// radio.scanChannel();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -38,6 +38,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -71,21 +86,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -31,6 +31,21 @@ Si4432 radio = new Module(10, 2, 9);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -70,21 +85,6 @@ void setup() {
// radio.readData();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -36,6 +36,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -69,21 +84,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -34,6 +34,21 @@ nRF24 radio = new Module(10, 2, 3);
Radio radio = new RadioModule();
*/
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -88,21 +103,6 @@ void setup() {
// radio.readData();
}
// flag to indicate that a packet was received
volatile bool receivedFlag = false;
// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we got a packet, set the flag
receivedFlag = true;
}
void loop() {
// check if the flag is set
if(receivedFlag) {

View file

@ -36,6 +36,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -84,21 +99,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;

View file

@ -0,0 +1,2 @@
# all output pictures
*.png

18
extras/cppcheck/check_file.sh Executable file
View file

@ -0,0 +1,18 @@
#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <path to check>"
exit 1
fi
path=$1
cppcheck --version
cppcheck $path --enable=all \
--force \
--inline-suppr \
--suppress=ConfigurationNotChecked \
--suppress=unusedFunction \
--suppress=missingIncludeSystem \
--suppress=missingInclude \
--quiet

View file

@ -2,7 +2,14 @@
file=cppcheck.txt
cppcheck --version
cppcheck src --enable=all --force --inline-suppr --suppress=ConfigurationNotChecked --suppress=unusedFunction --quiet >> $file 2>&1
cppcheck src --enable=all \
--force \
--inline-suppr \
--suppress=ConfigurationNotChecked \
--suppress=unusedFunction \
--suppress=missingIncludeSystem \
--suppress=missingInclude \
--quiet >> $file 2>&1
echo "Cppcheck finished with exit code $?"
error=$(grep ": error:" $file | wc -l)

View file

@ -1,111 +0,0 @@
import re, sys, argparse
from pathlib import Path
from argparse import RawTextHelpFormatter
'''
TODO list:
1. Parse macro values (the names of bits in all registers in header file)
2. Failed SPI write handling
3. SX126x/SX128x handling
'''
def get_macro_name(value, macros):
for macro in macros:
if macro[1] == value:
return macro[0]
return 'UNKNOWN_VALUE'
def get_macro_value(value):
return ' 0x{0:02X}\n'.format(int(value, 16))
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
RadioLib debug output decoder script. Turns RadioLib Serial dumps into readable text.
Step-by-step guid on how to use the decoder:
1. Uncomment lines 312 (#define RADIOLIB_DEBUG) and 313 (#define RADIOLIB_VERBOSE) in RadioLib/src/BuildOpt.h
2. Recompile and upload the failing Arduino sketch
3. Open Arduino IDE Serial Monitor and enable timestamps
4. Copy the Serial output and save it into a .txt file
5. Run this script
Output will be saved in the file specified by --out and printed to the terminal
''')
parser.add_argument('file', metavar='file', type=str, help='Text file of the debug output')
parser.add_argument('--out', metavar='out', default='./out.txt', type=str, help='Where to save the decoded file (defaults to ./out.txt)')
args = parser.parse_args()
# open the log file
log = open(args.file, 'r').readlines()
# find modules that are in use
used_modules = []
pattern_module = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?M\t')
for entry in log:
m = pattern_module.search(entry)
if m != None:
used_modules.append(entry[m.end():].rstrip())
# get paths to all relevant header files
header_files = []
for path in Path('../../src').rglob('*.h'):
for module in used_modules:
if module in path.name:
header_files.append(path)
# extract names of address macros from the header files
macro_addresses = []
pattern_define = re.compile('#define \w* +\w*(\n| +\/\/){1}')
for path in header_files:
file = open(path, 'r').readlines()
for line in file:
m = pattern_define.search(line)
if m != None:
s = re.split(' +', m.group().rstrip())
if (s.__len__() > 1) and ('_REG' in s[1]):
macro_addresses.append([s[1], int(s[2], 0)])
'''
# extract names of value macros for each adddress macro
macro_values = []
for path in header_files:
file = open(path, 'r').readlines()
for line in file:
for module in used_modules:
pattern_addr_macro = re.compile('\/\/ SI443X_REG_\w+'.format(module.capitalize()))
'''
# parse every line in the log file
out = []
pattern_debug = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?[RWM]\t.+')
for entry in log:
m = pattern_debug.search(entry)
if m != None:
s = re.split('( |\t)+', entry.rstrip())
cmd_len = int((s.__len__() - 7)/2)
new_entry = s[0] + s[1] + s[2] + s[3]
if s[4] == 'W':
macro_address = int(s[6], 16)
new_entry += 'write {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
for i in range(cmd_len):
new_entry += get_macro_value(s[8 + 2*i]);
elif s[4] == 'R':
macro_address = int(s[6], 16)
new_entry += 'read {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
for i in range(cmd_len):
new_entry += get_macro_value(s[8 + 2*i]);
elif s[4] == 'M':
new_entry += 'module {}\n'.format(s[6])
out.append(new_entry)
else:
out.append(entry)
# write the output file
out_file = open(args.out, 'w')
for line in out:
print(line, end='')
out_file.write(line)
out_file.close()

13
extras/test/ci/build_arduino.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
board=$1
sketch=$2
flags=$3
warnings="all"
arduino-cli compile \
--libraries ../../../../ \
--fqbn $board \
--build-property compiler.cpp.extra_flags="$flags" \
--warnings=$warnings \
$sketch --export-binaries

View file

@ -0,0 +1,41 @@
#!/bin/bash
#board=arduino:avr:mega
board="$1"
#skip="(STM32WL|LR11x0_Firmware_Update|NonArduino)"
skip="$2"
#options=""
options="$3"
# file for saving the compiled binary size reports
size_file="size_$board.txt"
rm -f $size_file
path="../../../examples"
for example in $(find $path -name '*.ino' | sort); do
# check whether to skip this sketch
if [ ! -z '$skip' ] && [[ ${example} =~ ${skip} ]]; then
# skip sketch
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with $skip)\033[0m";
else
# apply special flags for LoRaWAN
if [[ ${example} =~ "LoRaWAN" ]]; then
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
fi
# build sketch
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
board_opts=$board$options
./build_arduino.sh $board_opts $example "$flags"
if [ $? -ne 0 ]; then
echo -e "\033[1;31m${example##*/} build FAILED\033[0m\n";
exit 1;
else
echo -e "\033[1;32m${example##*/} build PASSED\033[0m\n";
dir="$(dirname -- "$example")"
file="$(basename -- "$example")"
size="$(size $dir/build/*/$file.elf)"
echo $size >> $size_file
fi
fi
done

24
extras/test/ci/parse_size.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
board=$1
hash=$(git rev-parse --short HEAD)
in_file="size_$board.txt"
out_file="size_${hash}_${board//:/-}.csv"
rm -f $out_file
# write the header
echo "text,data,bss,dec,hex,filename" > "$out_file"
# convert to CSV
awk 'NR > 1 {
split($12, path_parts, "/");
filename_with_ext = path_parts[length(path_parts)];
split(filename_with_ext, filename_parts, ".");
filename = filename_parts[1];
print $7 "," $8 "," $9 "," $10 "," $11 "," filename
}' "$in_file" >> "$out_file"
# remove input file
rm -f $in_file

2
extras/test/unit/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
build/
lcov*

View file

@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.13)
project(radiolib-unittest)
# add RadioLib sources
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CURRENT_BINARY_DIR}/RadioLib")
# add test sources
file(GLOB_RECURSE TEST_SOURCES
"tests/main.cpp"
"tests/TestModule.cpp"
)
# create the executable
add_executable(${PROJECT_NAME} ${TEST_SOURCES})
# include directories
target_include_directories(${PROJECT_NAME} PUBLIC include)
# link RadioLib
target_link_libraries(${PROJECT_NAME} RadioLib fmt gcov)
# set target properties and options
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
set(BUILD_FLAGS -Wall -Wextra -fprofile-arcs -ftest-coverage -O0)
target_compile_options(${PROJECT_NAME} PRIVATE ${BUILD_FLAGS})
target_compile_options(RadioLib PRIVATE ${BUILD_FLAGS})
# set RadioLib debug
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_BASIC RADIOLIB_DEBUG_SPI RADIOLIB_DEBUG_PROTOCOL)

12
extras/test/unit/coverage.sh Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash
set -e
filename="lcov"
rm -rf $filename.*
lcov --capture --directory build --output-file "${filename}.info"
# filter out boost and C++ standard library
lcov --remove "${filename}.info" "/usr/*/boost/*" "/usr/include/c++/*" --output-file "${filename}.info"
# generate HTML
genhtml "${filename}.info" --output-directory "${filename}.report"

View file

@ -0,0 +1,71 @@
#ifndef HARDWARE_EMULATION_HPP
#define HARDWARE_EMULATION_HPP
#include <stdint.h>
// value that is returned by the emualted radio class when performing SPI transfer to it
#define EMULATED_RADIO_SPI_RETURN (0xFF)
// pin indexes
#define EMULATED_RADIO_NSS_PIN (1)
#define EMULATED_RADIO_IRQ_PIN (2)
#define EMULATED_RADIO_RST_PIN (3)
#define EMULATED_RADIO_GPIO_PIN (4)
enum PinFunction_t {
PIN_UNASSIGNED = 0,
PIN_CS,
PIN_IRQ,
PIN_RST,
PIN_GPIO,
};
// structure for emulating GPIO pins
struct EmulatedPin_t {
uint32_t mode;
uint32_t value;
bool event;
PinFunction_t func;
};
// structure for emulating SPI registers
struct EmulatedRegister_t {
uint8_t value;
uint8_t readOnlyBitFlags;
bool bufferAccess;
};
// base class for emulated radio modules (SX126x etc.)
class EmulatedRadio {
public:
void connect(EmulatedPin_t* csPin, EmulatedPin_t* irqPin, EmulatedPin_t* rstPin, EmulatedPin_t* gpioPin) {
this->cs = csPin;
this->cs->func = PIN_CS;
this->irq = irqPin;
this->irq->func = PIN_IRQ;
this->rst = rstPin;
this->rst->func = PIN_RST;
this->gpio = gpioPin;
this->gpio->func = PIN_GPIO;
}
virtual uint8_t HandleSPI(uint8_t b) {
(void)b;
// handle the SPI input and generate output here
return(EMULATED_RADIO_SPI_RETURN);
}
virtual void HandleGPIO() {
// handle discrete GPIO signals here (e.g. reset state machine on NSS falling edge)
}
protected:
// pointers to emulated GPIO pins
// this is done via pointers so that the same GPIO entity is shared, like with a real hardware
EmulatedPin_t* cs;
EmulatedPin_t* irq;
EmulatedPin_t* rst;
EmulatedPin_t* gpio;
};
#endif

View file

@ -0,0 +1,269 @@
#ifndef TEST_HAL_HPP
#define TEST_HAL_HPP
#include <chrono>
#include <thread>
#include <fmt/format.h>
#include <RadioLib.h>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#if defined(TEST_HAL_LOG)
#define HAL_LOG(...) BOOST_TEST_MESSAGE(__VA_ARGS__)
#else
#define HAL_LOG(...) {}
#endif
#include "HardwareEmulation.hpp"
#define TEST_HAL_INPUT (0)
#define TEST_HAL_OUTPUT (1)
#define TEST_HAL_LOW (0)
#define TEST_HAL_HIGH (1)
#define TEST_HAL_RISING (0)
#define TEST_HAL_FALLING (1)
// number of emulated GPIO pins
#define TEST_HAL_NUM_GPIO_PINS (32)
#define TEST_HAL_SPI_LOG_LENGTH (512)
class TestHal : public RadioLibHal {
public:
TestHal() : RadioLibHal(TEST_HAL_INPUT, TEST_HAL_OUTPUT, TEST_HAL_LOW, TEST_HAL_HIGH, TEST_HAL_RISING, TEST_HAL_FALLING) { }
void init() override {
HAL_LOG("TestHal::init()");
// save program start timestamp
start = std::chrono::high_resolution_clock::now();
// init emulated GPIO
for(int i = 0; i < TEST_HAL_NUM_GPIO_PINS; i++) {
this->gpio[i].mode = 0;
this->gpio[i].value = 0;
this->gpio[i].event = false;
this->gpio[i].func = PIN_UNASSIGNED;
}
// wipe history log
this->spiLogWipe();
}
void term() override {
HAL_LOG("TestHal::term()");
}
void pinMode(uint32_t pin, uint32_t mode) override {
HAL_LOG("TestHal::pinMode(pin=" << pin << ", mode=" << mode << " [" << ((mode == TEST_HAL_INPUT) ? "INPUT" : "OUTPUT") << "])");
// check the range
BOOST_ASSERT_MSG(pin < TEST_HAL_NUM_GPIO_PINS, "Pin number out of range");
// check known modes
BOOST_ASSERT_MSG(((mode == TEST_HAL_INPUT) || (mode == TEST_HAL_OUTPUT)), "Invalid pin mode");
// set mode
this->gpio[pin].mode = mode;
}
void digitalWrite(uint32_t pin, uint32_t value) override {
HAL_LOG("TestHal::digitalWrite(pin=" << pin << ", value=" << value << " [" << ((value == TEST_HAL_LOW) ? "LOW" : "HIGH") << "])");
// check the range
BOOST_ASSERT_MSG(pin < TEST_HAL_NUM_GPIO_PINS, "Pin number out of range");
// check it is output
BOOST_ASSERT_MSG(this->gpio[pin].mode == TEST_HAL_OUTPUT, "GPIO is not output!");
// check known values
BOOST_ASSERT_MSG(((value == TEST_HAL_LOW) || (value == TEST_HAL_HIGH)), "Invalid output value");
// set value
this->gpio[pin].value = value;
this->gpio[pin].event = true;
if(radio) {
this->radio->HandleGPIO();
}
this->gpio[pin].event = false;
}
uint32_t digitalRead(uint32_t pin) override {
HAL_LOG("TestHal::digitalRead(pin=" << pin << ")");
// check the range
BOOST_ASSERT_MSG(pin < TEST_HAL_NUM_GPIO_PINS, "Pin number out of range");
// check it is input
BOOST_ASSERT_MSG(this->gpio[pin].mode == TEST_HAL_INPUT, "GPIO is not input");
// read the value
uint32_t value = this->gpio[pin].value;
HAL_LOG("TestHal::digitalRead(pin=" << pin << ")=" << value << " [" << ((value == TEST_HAL_LOW) ? "LOW" : "HIGH") << "]");
return(value);
}
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override {
HAL_LOG("TestHal::attachInterrupt(interruptNum=" << interruptNum << ", interruptCb=" << interruptCb << ", mode=" << mode << ")");
// TODO implement
(void)interruptNum;
(void)interruptCb;
(void)mode;
}
void detachInterrupt(uint32_t interruptNum) override {
HAL_LOG("TestHal::detachInterrupt(interruptNum=" << interruptNum << ")");
// TODO implement
(void)interruptNum;
}
void delay(unsigned long ms) override {
HAL_LOG("TestHal::delay(ms=" << ms << ")");
const auto start = std::chrono::high_resolution_clock::now();
// sleep_for is sufficient for ms-precision sleep
std::this_thread::sleep_for(std::chrono::duration<unsigned long, std::milli>(ms));
// measure and print
const auto end = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double, std::milli> elapsed = end - start;
HAL_LOG("TestHal::delay(ms=" << ms << ")=" << elapsed.count() << "ms");
}
void delayMicroseconds(unsigned long us) override {
HAL_LOG("TestHal::delayMicroseconds(us=" << us << ")");
const auto start = std::chrono::high_resolution_clock::now();
// busy wait is needed for microseconds precision
const auto len = std::chrono::microseconds(us);
while(std::chrono::high_resolution_clock::now() - start < len);
// measure and print
const auto end = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double, std::micro> elapsed = end - start;
HAL_LOG("TestHal::delayMicroseconds(us=" << us << ")=" << elapsed.count() << "us");
}
void yield() override {
HAL_LOG("TestHal::yield()");
}
unsigned long millis() override {
HAL_LOG("TestHal::millis()");
std::chrono::time_point now = std::chrono::high_resolution_clock::now();
auto res = std::chrono::duration_cast<std::chrono::milliseconds>(now - this->start);
HAL_LOG("TestHal::millis()=" << res.count());
return(res.count());
}
unsigned long micros() override {
HAL_LOG("TestHal::micros()");
std::chrono::time_point now = std::chrono::high_resolution_clock::now();
auto res = std::chrono::duration_cast<std::chrono::microseconds>(now - this->start);
HAL_LOG("TestHal::micros()=" << res.count());
return(res.count());
}
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
HAL_LOG("TestHal::pulseIn(pin=" << pin << ", state=" << state << ", timeout=" << timeout << ")");
// TODO implement
(void)pin;
(void)state;
(void)timeout;
return(0);
}
void spiBegin() {
HAL_LOG("TestHal::spiBegin()");
}
void spiBeginTransaction() {
HAL_LOG("TestHal::spiBeginTransaction()");
}
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
HAL_LOG("TestHal::spiTransfer(len=" << len << ")");
for(size_t i = 0; i < len; i++) {
// append to log
(*this->spiLogPtr++) = out[i];
// process the SPI byte
in[i] = this->radio->HandleSPI(out[i]);
// artificial delay to emulate SPI running at a finite speed
// this is added because timeouts are based on time duration,
// so we need to make sure some time actually elapses
this->delayMicroseconds(100);
// output debug
HAL_LOG(fmt::format("out={:#02x}, in={:#02x}", out[i], in[i]));
}
}
void spiEndTransaction() {
HAL_LOG("TestHal::spiEndTransaction()");
}
void spiEnd() {
HAL_LOG("TestHal::spiEnd()");
}
void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) {
HAL_LOG("TestHal::tone(pin=" << pin << ", frequency=" << frequency << ", duration=" << duration << ")");
// TODO implement
(void)pin;
(void)frequency;
(void)duration;
}
void noTone(uint32_t pin) {
HAL_LOG("TestHal::noTone(pin=" << pin << ")");
// TODO implement
(void)pin;
}
// method to compare buffer to the internal SPI log, for verifying SPI transactions
int spiLogMemcmp(const void* in, size_t n) {
int ret = memcmp(this->spiLog, in, n);
this->spiLogWipe();
return(ret);
}
void spiLogWipe() {
memset(this->spiLog, 0x00, TEST_HAL_SPI_LOG_LENGTH);
this->spiLogPtr = this->spiLog;
}
// method that "connects" the emualted radio hardware to this HAL
void connectRadio(EmulatedRadio* r) {
this->radio = r;
this->radio->connect(&this->gpio[EMULATED_RADIO_NSS_PIN],
&this->gpio[EMULATED_RADIO_IRQ_PIN],
&this->gpio[EMULATED_RADIO_RST_PIN],
&this->gpio[EMULATED_RADIO_GPIO_PIN]);
}
private:
// array of emulated GPIO pins
EmulatedPin_t gpio[TEST_HAL_NUM_GPIO_PINS];
// start time point
std::chrono::time_point<std::chrono::high_resolution_clock> start;
// emulated radio hardware
EmulatedRadio* radio;
// SPI history log
uint8_t spiLog[TEST_HAL_SPI_LOG_LENGTH];
uint8_t* spiLogPtr;
};
#endif

14
extras/test/unit/test.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
set -e
# build the test binary
rm -rf build
mkdir build
cd build
cmake -G "CodeBlocks - Unix Makefiles" ..
make -j4
# run it
cd ..
./build/radiolib-unittest --log_level=message

View file

@ -0,0 +1,229 @@
// boost test header
#include <boost/test/unit_test.hpp>
// mock HAL
#include "TestHal.hpp"
// testing fixture
struct ModuleFixture {
TestHal* hal = nullptr;
Module* mod = nullptr;
EmulatedRadio* radioHardware = nullptr;
ModuleFixture() {
BOOST_TEST_MESSAGE("--- Module fixture setup ---");
hal = new TestHal();
radioHardware = new EmulatedRadio();
hal->connectRadio(radioHardware);
mod = new Module(hal, EMULATED_RADIO_NSS_PIN, EMULATED_RADIO_IRQ_PIN, EMULATED_RADIO_RST_PIN, EMULATED_RADIO_GPIO_PIN);
mod->init();
}
~ModuleFixture() {
BOOST_TEST_MESSAGE("--- Module fixture teardown ---");
mod->term();
delete[] mod;
delete[] hal;
}
};
BOOST_FIXTURE_TEST_SUITE(suite_Module, ModuleFixture)
BOOST_FIXTURE_TEST_CASE(Module_SPIgetRegValue_reg, ModuleFixture)
{
BOOST_TEST_MESSAGE("--- Test Module::SPIgetRegValue register access ---");
int16_t ret;
// basic register read with default config
const uint8_t address = 0x12;
const uint8_t spiTxn[] = { address, 0x00 };
ret = mod->SPIgetRegValue(address);
// check return code, value and history log
BOOST_TEST(ret >= RADIOLIB_ERR_NONE);
BOOST_TEST(ret == EMULATED_RADIO_SPI_RETURN);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// register read masking test
const uint8_t msb = 5;
const uint8_t lsb = 1;
const uint8_t maskedValue = 0x3E;
ret = mod->SPIgetRegValue(address, msb, lsb);
BOOST_TEST(ret == maskedValue);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIgetRegValue(address, lsb, msb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIgetRegValue(address, 10, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIgetRegValue(address, msb, 10);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
}
BOOST_FIXTURE_TEST_CASE(Module_SPIsetRegValue_reg, ModuleFixture)
{
BOOST_TEST_MESSAGE("--- Test Module::SPIsetRegValue register access ---");
int16_t ret;
// basic register write with default config
const uint8_t address = 0x12;
const uint8_t value = 0xAB;
const uint8_t spiTxn[] = { address, 0x00, 0x80 | address, value };
ret = mod->SPIsetRegValue(address, value);
// check return code and history log
// this will return write error because the bare emulated radio has no internal logic
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// register write masking test
const uint8_t msb = 5;
const uint8_t lsb = 1;
const uint8_t maskedValue = 0xEB;
const uint8_t spiTxn2[] = { address, 0x00, 0x80 | address, maskedValue };
ret = mod->SPIsetRegValue(address, value, msb, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn2, sizeof(spiTxn2)) == 0);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIsetRegValue(address, value, lsb, msb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIsetRegValue(address, value, 10, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIsetRegValue(address, value, msb, 10);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
// check interval test
const uint8_t interval = 200;
const unsigned long start = hal->micros();
ret = mod->SPIsetRegValue(address, value, 7, 0, interval);
const unsigned long stop = hal->micros();
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
const unsigned long elapsed = stop - start;
BOOST_TEST(elapsed >= (unsigned long)interval*1000UL);
// disabled check mask test
ret = mod->SPIsetRegValue(address, value, 7, 0, 2, 0);
BOOST_TEST(ret == RADIOLIB_ERR_NONE);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// forced write test
ret = mod->SPIsetRegValue(address, value, 7, 0, 2, 0xFF, true);
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
}
BOOST_FIXTURE_TEST_CASE(Module_SPIgetRegValue_stream, ModuleFixture)
{
BOOST_TEST_MESSAGE("--- Test Module::SPIgetRegValue stream access ---");
int16_t ret;
// change settings to stream type
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
mod->spiConfig.statusPos = 1;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS;
mod->spiConfig.stream = true;
// basic register read
const uint8_t address = 0x12;
const uint8_t spiTxn[] = { RADIOLIB_SX126X_CMD_READ_REGISTER, 0x00, address, 0x00, 0x00 };
ret = mod->SPIgetRegValue(address);
// check return code, value and history log
BOOST_TEST(ret >= RADIOLIB_ERR_NONE);
BOOST_TEST(ret == EMULATED_RADIO_SPI_RETURN);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// register read masking test
const uint8_t msb = 5;
const uint8_t lsb = 1;
const uint8_t maskedValue = 0x3E;
ret = mod->SPIgetRegValue(address, msb, lsb);
BOOST_TEST(ret == maskedValue);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIgetRegValue(address, lsb, msb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIgetRegValue(address, 10, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIgetRegValue(address, msb, 10);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
}
BOOST_FIXTURE_TEST_CASE(Module_SPIsetRegValue_stream, ModuleFixture)
{
BOOST_TEST_MESSAGE("--- Test Module::SPIsetRegValue stream access ---");
int16_t ret;
// change settings to stream type
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
mod->spiConfig.statusPos = 1;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP;
mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS;
mod->spiConfig.stream = true;
// basic register write with default config
const uint8_t address = 0x12;
const uint8_t value = 0xAB;
const uint8_t spiTxn[] = {
RADIOLIB_SX126X_CMD_READ_REGISTER, 0x00, address, 0x00, 0x00,
RADIOLIB_SX126X_CMD_WRITE_REGISTER, 0x00, address, value,
};
ret = mod->SPIsetRegValue(address, value);
// check return code and history log
// this will return write error because the bare emulated radio has no internal logic
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// register write masking test
const uint8_t msb = 5;
const uint8_t lsb = 1;
const uint8_t maskedValue = 0xEB;
const uint8_t spiTxn2[] = {
RADIOLIB_SX126X_CMD_READ_REGISTER, 0x00, address, 0x00, 0x00,
RADIOLIB_SX126X_CMD_WRITE_REGISTER, 0x00, address, maskedValue,
};
ret = mod->SPIsetRegValue(address, value, msb, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn2, sizeof(spiTxn2)) == 0);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIsetRegValue(address, value, lsb, msb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIsetRegValue(address, value, 10, lsb);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
ret = mod->SPIsetRegValue(address, value, msb, 10);
BOOST_TEST(ret == RADIOLIB_ERR_INVALID_BIT_RANGE);
// check interval test
const uint8_t interval = 200;
const unsigned long start = hal->micros();
ret = mod->SPIsetRegValue(address, value, 7, 0, interval);
const unsigned long stop = hal->micros();
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
const unsigned long elapsed = stop - start;
BOOST_TEST(elapsed >= (unsigned long)interval*1000UL);
// disabled check mask test
ret = mod->SPIsetRegValue(address, value, 7, 0, 2, 0);
BOOST_TEST(ret == RADIOLIB_ERR_NONE);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
// forced write test
ret = mod->SPIsetRegValue(address, value, 7, 0, 2, 0xFF, true);
BOOST_TEST(ret == RADIOLIB_ERR_SPI_WRITE_FAILED);
BOOST_TEST(hal->spiLogMemcmp(spiTxn, sizeof(spiTxn)) == 0);
}
BOOST_AUTO_TEST_SUITE_END()

View file

@ -0,0 +1,5 @@
#define BOOST_TEST_MODULE "RadioLib Unit test"
#include <boost/test/included/unit_test.hpp>
// intentionally left blank, boost.test creates its own entrypoint

View file

@ -1,4 +1,4 @@
version: "7.1.0"
version: "17.0.3"
description: "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN)."
tags:
- radio
@ -33,8 +33,8 @@ tags:
- lr1110
- lr1120
- lr1121
url: "https://github.com/jgromes/RadioLib"
repository: "https://github.com/jgromes/RadioLib.git"
url: "https://git.cheetah.cat/forks/RadioLibSmol"
repository: "https://git.cheetah.cat/forks/RadioLibSmol.git"
license: "MIT"
dependencies:
# Required IDF version

View file

@ -86,7 +86,7 @@ EU868 KEYWORD1
US915 KEYWORD1
EU433 KEYWORD1
AU915 KEYWORD1
CN500 KEYWORD1
CN470 KEYWORD1
AS923 KEYWORD1
AS923_2 KEYWORD1
AS923_3 KEYWORD1
@ -197,6 +197,7 @@ randomByte KEYWORD2
getPacketLength KEYWORD2
setFifoEmptyAction KEYWORD2
clearFifoEmptyAction KEYWORD2
setFifoThreshold KEYWORD2
setFifoFullAction KEYWORD2
clearFifoFullAction KEYWORD2
fifoAdd KEYWORD2
@ -221,6 +222,7 @@ setGdo2Action KEYWORD2
clearGdo0Action KEYWORD2
clearGdo2Action KEYWORD2
setCrcFiltering KEYWORD2
beginFSK4 KEYWORD2
# SX126x-specific
setTCXO KEYWORD2
@ -244,6 +246,7 @@ spectralScanAbort KEYWORD2
spectralScanGetStatus KEYWORD2
spectralScanGetResult KEYWORD2
setPaRampTime KEYWORD2
hopLRFHSS KEYWORD2
# nRF24
setIrqAction KEYWORD2
@ -340,6 +343,8 @@ setDataRate KEYWORD2
checkDataRate KEYWORD2
setModem KEYWORD2
getModem KEYWORD2
stageMode KEYWORD2
launchMode KEYWORD2
# LoRaWAN
getBufferNonces KEYWORD2
@ -374,6 +379,7 @@ getLastToA KEYWORD2
dutyCycleInterval KEYWORD2
timeUntilUplink KEYWORD2
getMaxPayloadLen KEYWORD2
setSleepFunction KEYWORD2
#######################################
# Constants (LITERAL1)

View file

@ -1,13 +1,13 @@
{
"name": "RadioLib",
"version": "7.1.0",
"version": "17.0.3",
"description": "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).",
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rf69, sx1231, rfm96, rfm98, sstv, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan, lr1110, lr1120, lr1121",
"homepage": "https://github.com/jgromes/RadioLib",
"repository":
{
"type": "git",
"url": "https://github.com/jgromes/RadioLib.git"
"url": "https://git.cheetah.cat/forks/RadioLibSmol.git"
},
"authors":
{

View file

@ -1,10 +1,10 @@
name=RadioLib
version=7.1.0
version=17.0.3
author=Jan Gromes <gromes.jan@gmail.com>
maintainer=Jan Gromes <gromes.jan@gmail.com>
sentence=Universal wireless communication library
paragraph=User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, LR1110 and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).
category=Communication
url=https://github.com/jgromes/RadioLib
url=https://git.cheetah.cat/forks/RadioLibSmol
architectures=*
includes=RadioLib.h

View file

@ -29,7 +29,11 @@
// set which output port should be used for debug output
// may be Serial port (on Arduino) or file like stdout or stderr (on generic platforms)
#if !defined(RADIOLIB_DEBUG_PORT)
#define RADIOLIB_DEBUG_PORT Serial
#if ARDUINO >= 100
#define RADIOLIB_DEBUG_PORT Serial
#else
#define RADIOLIB_DEBUG_PORT stdout
#endif
#endif
/*
@ -114,6 +118,10 @@
//#define RADIOLIB_CLOCK_DRIFT_MS (0)
#endif
#if !defined(RADIOLIB_LINE_FEED)
#define RADIOLIB_LINE_FEED "\r\n"
#endif
#if ARDUINO >= 100
// Arduino build
#include "Arduino.h"
@ -133,11 +141,9 @@
* RADIOLIB_DEFAULT_SPI - default SPIClass instance to use.
* RADIOLIB_NONVOLATILE - macro to place variable into program storage (usually Flash).
* RADIOLIB_NONVOLATILE_READ_BYTE - function/macro to read variables saved in program storage (usually Flash).
* RADIOLIB_TYPE_ALIAS - construct to create an alias for a type, usually vai the `using` keyword.
* RADIOLIB_TYPE_ALIAS - construct to create an alias for a type, usually via the `using` keyword.
* RADIOLIB_TONE_UNSUPPORTED - some platforms do not have tone()/noTone(), which is required for AFSK.
*
* In addition, some platforms may require RadioLib to disable specific drivers (such as ESP8266).
*
* Users may also specify their own configuration by uncommenting the RADIOLIB_CUSTOM_ARDUINO,
* and then specifying all platform parameters in the section below. This will override automatic
* platform detection.
@ -262,20 +268,24 @@
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#if defined(ARDUINO_ARCH_MBED)
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
#define RADIOLIB_TONE_UNSUPPORTED
#define RADIOLIB_MBED_TONE_OVERRIDE
#endif
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4)
#elif defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_PORTENTA_H7)
// Arduino Portenta H7
#define RADIOLIB_PLATFORM "Portenta H7"
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#if defined(ARDUINO_ARCH_MBED)
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
#define RADIOLIB_TONE_UNSUPPORTED
#define RADIOLIB_MBED_TONE_OVERRIDE
#endif
#elif defined(__STM32F4__) || defined(__STM32F1__)
// Arduino STM32 core by Roger Clark (https://github.com/rogerclarkmelbourne/Arduino_STM32)
@ -365,6 +375,13 @@
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#elif defined(ARDUINO_ARCH_SILABS)
// Silicon Labs Arduino
#define RADIOLIB_PLATFORM "Arduino Silicon Labs"
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#else
// other Arduino platforms not covered by the above list - this may or may not work
#define RADIOLIB_PLATFORM "Unknown Arduino"
@ -424,14 +441,10 @@
#define RADIOLIB_NC (0xFFFFFFFF)
#define RADIOLIB_NONVOLATILE
#define RADIOLIB_NONVOLATILE_READ_BYTE(addr) (*((uint8_t *)(void *)(addr)))
#define RADIOLIB_NONVOLATILE_READ_DWORD(addr) (*((uint32_t *)(void *)(addr)))
#define RADIOLIB_NONVOLATILE_READ_BYTE(addr) (*(reinterpret_cast<uint8_t *>(reinterpret_cast<void *>(addr))))
#define RADIOLIB_NONVOLATILE_READ_DWORD(addr) (*(reinterpret_cast<uint32_t *>(reinterpret_cast<void *>(addr))))
#define RADIOLIB_TYPE_ALIAS(type, alias) using alias = type;
#if !defined(RADIOLIB_DEBUG_PORT)
#define RADIOLIB_DEBUG_PORT stdout
#endif
#define DEC 10
#define HEX 16
#define OCT 8
@ -460,23 +473,20 @@
#endif
#if RADIOLIB_DEBUG
#if defined(RADIOLIB_BUILD_ARDUINO)
#define RADIOLIB_DEBUG_PRINT(...) rlb_printf(__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN(M, ...) rlb_printf(M "\n", ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) rlb_printf(LEVEL "" M, ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) rlb_printf(LEVEL "" M "\n", ##__VA_ARGS__)
#if !defined(RADIOLIB_DEBUG_PRINT)
#define RADIOLIB_DEBUG_PRINT(M, ...) rlb_printf(false, M, ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) rlb_printf(true, LEVEL "" M, ##__VA_ARGS__)
#endif
// some platforms do not support printf("%f"), so it has to be done this way
#if !defined(RADIOLIB_DEBUG_PRINTLN)
#define RADIOLIB_DEBUG_PRINTLN(M, ...) rlb_printf(false, M RADIOLIB_LINE_FEED, ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) rlb_printf(true, LEVEL "" M RADIOLIB_LINE_FEED, ##__VA_ARGS__)
#endif
// some Arduino platforms do not support printf("%f"), so it has to be done this way
#if defined(RADIOLIB_BUILD_ARDUINO)
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL); RADIOLIB_DEBUG_PORT.print(VAL, DECIMALS)
#else
#if !defined(RADIOLIB_DEBUG_PRINT)
#define RADIOLIB_DEBUG_PRINT(...) fprintf(RADIOLIB_DEBUG_PORT, __VA_ARGS__)
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) fprintf(RADIOLIB_DEBUG_PORT, LEVEL "" M, ##__VA_ARGS__)
#endif
#if !defined(RADIOLIB_DEBUG_PRINTLN)
#define RADIOLIB_DEBUG_PRINTLN(M, ...) fprintf(RADIOLIB_DEBUG_PORT, M "\n", ##__VA_ARGS__)
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) fprintf(RADIOLIB_DEBUG_PORT, LEVEL "" M "\n", ##__VA_ARGS__)
#endif
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL "%.3f", VAL)
#endif
@ -484,63 +494,74 @@
#else
#define RADIOLIB_DEBUG_PRINT(...) {}
#define RADIOLIB_DEBUG_PRINTLN(...) {}
#define RADIOLIB_DEBUG_PRINT_FLOAT(VAL, DECIMALS) {}
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) {}
#define RADIOLIB_DEBUG_HEXDUMP(...) {}
#endif
#define RADIOLIB_DEBUG_TAG ": "
#define RADIOLIB_DEBUG_TAG_BASIC "RLB_DBG" RADIOLIB_DEBUG_TAG
#define RADIOLIB_DEBUG_TAG_PROTOCOL "RLB_PRO" RADIOLIB_DEBUG_TAG
#define RADIOLIB_DEBUG_TAG_SPI "RLB_SPI" RADIOLIB_DEBUG_TAG
#if RADIOLIB_DEBUG_BASIC
#define RADIOLIB_DEBUG_BASIC_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL("RLB_DBG: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINT_NOTAG(...) RADIOLIB_DEBUG_PRINT_LVL("", __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL("RLB_DBG: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT("RLB_DBG: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_BASIC_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP("RLB_DBG: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_BASIC_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL(RADIOLIB_DEBUG_TAG_BASIC, __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL(RADIOLIB_DEBUG_TAG_BASIC, __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP(RADIOLIB_DEBUG_TAG_BASIC, __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT(RADIOLIB_DEBUG_TAG_BASIC, __VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINT_NOTAG(...) RADIOLIB_DEBUG_PRINT(__VA_ARGS__)
#define RADIOLIB_DEBUG_BASIC_PRINTLN_NOTAG(...) RADIOLIB_DEBUG_PRINTLN(__VA_ARGS__)
#else
#define RADIOLIB_DEBUG_BASIC_PRINT(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINT_NOTAG(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINTLN(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_BASIC_HEXDUMP(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINT_NOTAG(...) {}
#define RADIOLIB_DEBUG_BASIC_PRINTLN_NOTAG(...) {}
#endif
#if RADIOLIB_DEBUG_PROTOCOL
#define RADIOLIB_DEBUG_PROTOCOL_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL("RLB_PRO: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL("RLB_PRO: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT("RLB_PRO: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP("RLB_PRO: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_PROTOCOL_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL(RADIOLIB_DEBUG_TAG_PROTOCOL, __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL(RADIOLIB_DEBUG_TAG_PROTOCOL, __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP(RADIOLIB_DEBUG_TAG_PROTOCOL, __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT(RADIOLIB_DEBUG_TAG_PROTOCOL, __VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_NOTAG(...) RADIOLIB_DEBUG_PRINT(__VA_ARGS__)
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN_NOTAG(...) RADIOLIB_DEBUG_PRINTLN(__VA_ARGS__)
#else
#define RADIOLIB_DEBUG_PROTOCOL_PRINT(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_NOTAG(...) {}
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN_NOTAG(...) {}
#endif
#if RADIOLIB_DEBUG_SPI
#define RADIOLIB_DEBUG_SPI_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL("RLB_SPI: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINT_NOTAG(...) RADIOLIB_DEBUG_PRINT_LVL("", __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL("RLB_SPI: ", __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG(...) RADIOLIB_DEBUG_PRINTLN_LVL("", __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT("RLB_SPI: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_SPI_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP("RLB_SPI: ", __VA_ARGS__);
#define RADIOLIB_DEBUG_SPI_PRINT(...) RADIOLIB_DEBUG_PRINT_LVL(RADIOLIB_DEBUG_TAG_SPI, __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN_LVL(RADIOLIB_DEBUG_TAG_SPI, __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_HEXDUMP(...) RADIOLIB_DEBUG_HEXDUMP(RADIOLIB_DEBUG_TAG_SPI, __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINT_FLOAT(...) RADIOLIB_DEBUG_PRINT_FLOAT(RADIOLIB_DEBUG_TAG_SPI, __VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINT_NOTAG(...) RADIOLIB_DEBUG_PRINT(__VA_ARGS__)
#define RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG(...) RADIOLIB_DEBUG_PRINTLN(__VA_ARGS__)
#else
#define RADIOLIB_DEBUG_SPI_PRINT(...) {}
#define RADIOLIB_DEBUG_SPI_PRINT_NOTAG(...) {}
#define RADIOLIB_DEBUG_SPI_PRINTLN(...) {}
#define RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG(...) {}
#define RADIOLIB_DEBUG_SPI_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_SPI_HEXDUMP(...) {}
#define RADIOLIB_DEBUG_SPI_PRINT_FLOAT(...) {}
#define RADIOLIB_DEBUG_SPI_PRINT_NOTAG(...) {}
#define RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG(...) {}
#endif
// debug info strings
#define RADIOLIB_VALUE_TO_STRING(x) #x
#define RADIOLIB_VALUE(x) RADIOLIB_VALUE_TO_STRING(x)
#define RADIOLIB_INFO "\nRadioLib Info\nVersion: \"" \
#define RADIOLIB_INFO "\r\nRadioLib Info\nVersion: \"" \
RADIOLIB_VALUE(RADIOLIB_VERSION_MAJOR) "." \
RADIOLIB_VALUE(RADIOLIB_VERSION_MINOR) "." \
RADIOLIB_VALUE(RADIOLIB_VERSION_PATCH) "." \
RADIOLIB_VALUE(RADIOLIB_VERSION_EXTRA) "\"\n" \
"Platform: " RADIOLIB_VALUE(RADIOLIB_PLATFORM) "\n" \
"Compiled: " RADIOLIB_VALUE(__DATE__) " " RADIOLIB_VALUE(__TIME__)
RADIOLIB_VALUE(RADIOLIB_VERSION_EXTRA) "\"\r\n" \
"Platform: " RADIOLIB_VALUE(RADIOLIB_PLATFORM) "\r\n" \
RADIOLIB_VALUE(__DATE__) " " RADIOLIB_VALUE(__TIME__)
/*!
\brief A simple assert macro, will return on error.
@ -578,7 +599,7 @@
// version definitions
#define RADIOLIB_VERSION_MAJOR 7
#define RADIOLIB_VERSION_MINOR 1
#define RADIOLIB_VERSION_PATCH 0
#define RADIOLIB_VERSION_PATCH 2
#define RADIOLIB_VERSION_EXTRA 0
#define RADIOLIB_VERSION (((RADIOLIB_VERSION_MAJOR) << 24) | ((RADIOLIB_VERSION_MINOR) << 16) | ((RADIOLIB_VERSION_PATCH) << 8) | (RADIOLIB_VERSION_EXTRA))

View file

@ -1,12 +1,18 @@
#include "Hal.h"
static RadioLibHal* rlb_timestamp_hal = nullptr;
RadioLibHal::RadioLibHal(const uint32_t input, const uint32_t output, const uint32_t low, const uint32_t high, const uint32_t rising, const uint32_t falling)
: GpioModeInput(input),
GpioModeOutput(output),
GpioLevelLow(low),
GpioLevelHigh(high),
GpioInterruptRising(rising),
GpioInterruptFalling(falling) {}
GpioInterruptFalling(falling) {
if(!rlb_timestamp_hal) {
rlb_timestamp_hal = this;
}
}
void RadioLibHal::init() {
@ -33,3 +39,7 @@ void RadioLibHal::yield() {
uint32_t RadioLibHal::pinToInterrupt(uint32_t pin) {
return(pin);
}
RadioLibTime_t rlb_time_us() {
return(rlb_timestamp_hal == nullptr ? 0 : rlb_timestamp_hal->micros());
}

View file

@ -6,6 +6,9 @@
#include "BuildOpt.h"
/*! \brief Global-scope function that returns timestamp since start (in microseconds). */
RadioLibTime_t rlb_time_us();
/*!
\class RadioLibHal
\brief Hardware abstraction library base interface.

View file

@ -25,7 +25,7 @@ Module::Module(const Module& mod) {
}
Module& Module::operator=(const Module& mod) {
memcpy((void*)&mod.spiConfig, &this->spiConfig, sizeof(SPIConfig_t));
memcpy(reinterpret_cast<void*>(&(const_cast<Module&>(mod)).spiConfig), &this->spiConfig, sizeof(SPIConfig_t));
this->csPin = mod.csPin;
this->irqPin = mod.irqPin;
this->rstPin = mod.rstPin;
@ -56,13 +56,21 @@ int16_t Module::SPIgetRegValue(uint32_t reg, uint8_t msb, uint8_t lsb) {
return(maskedValue);
}
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask, bool force) {
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
}
// read the current value
uint8_t currentValue = SPIreadRegister(reg);
uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
// check if we actually need to update the register
if((currentValue & mask) == (value & mask) && !force) {
return(RADIOLIB_ERR_NONE);
}
// update the register
uint8_t newValue = (currentValue & ~mask) | (value & mask);
SPIwriteRegister(reg, newValue);
@ -134,7 +142,7 @@ uint8_t Module::SPIreadRegister(uint32_t reg) {
return(resp);
}
void Module::SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes) {
void Module::SPIwriteRegisterBurst(uint32_t reg, const uint8_t* data, size_t numBytes) {
if(!spiConfig.stream) {
SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, data, NULL, numBytes);
} else {
@ -166,7 +174,7 @@ void Module::SPIwriteRegister(uint32_t reg, uint8_t data) {
}
}
void Module::SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
void Module::SPItransfer(uint16_t cmd, uint32_t reg, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
// prepare the buffers
size_t buffLen = this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8 + numBytes;
#if RADIOLIB_STATIC_ONLY
@ -208,7 +216,7 @@ void Module::SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t*
// print debug information
#if RADIOLIB_DEBUG_SPI
uint8_t* debugBuffPtr = NULL;
const uint8_t* debugBuffPtr = NULL;
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
RADIOLIB_DEBUG_SPI_PRINT("W\t%X\t", reg);
debugBuffPtr = &buffOut[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
@ -219,7 +227,7 @@ void Module::SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t*
for(size_t n = 0; n < numBytes; n++) {
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", debugBuffPtr[n]);
}
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
#endif
#if !RADIOLIB_STATIC_ONLY
@ -237,7 +245,7 @@ int16_t Module::SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool
return(this->SPIreadStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
}
int16_t Module::SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
int16_t Module::SPIreadStream(const uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
// send the command
int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio);
RADIOLIB_ASSERT(state);
@ -256,7 +264,7 @@ int16_t Module::SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_
#endif
}
int16_t Module::SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
int16_t Module::SPIwriteStream(uint16_t cmd, const uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
uint8_t cmdBuf[2];
uint8_t* cmdPtr = cmdBuf;
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
@ -265,7 +273,7 @@ int16_t Module::SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, boo
return(this->SPIwriteStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
}
int16_t Module::SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
int16_t Module::SPIwriteStream(const uint8_t* cmd, uint8_t cmdLen, const uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
// send the command
int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio);
RADIOLIB_ASSERT(state);
@ -307,8 +315,9 @@ int16_t Module::SPIcheckStream() {
return(state);
}
int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio) {
int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio) {
// prepare the output buffer
int16_t state = RADIOLIB_ERR_NONE;
size_t buffLen = cmdLen + numBytes;
if(!write) {
buffLen += (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8);
@ -340,6 +349,9 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
RadioLibTime_t start = this->hal->millis();
while(this->hal->digitalRead(this->gpioPin)) {
this->hal->yield();
// this timeout check triggers a false positive from cppcheck
// cppcheck-suppress unsignedLessThanZero
if(this->hal->millis() - start >= this->spiConfig.timeout) {
RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO pre-transfer timeout, is it connected?");
#if !RADIOLIB_STATIC_ONLY
@ -347,6 +359,7 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
#endif
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
}
}
}
}
@ -374,21 +387,23 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
RadioLibTime_t start = this->hal->millis();
while(this->hal->digitalRead(this->gpioPin)) {
this->hal->yield();
// this timeout check triggers a false positive from cppcheck
// cppcheck-suppress unsignedLessThanZero
if(this->hal->millis() - start >= this->spiConfig.timeout) {
RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO post-transfer timeout, is it connected?");
#if !RADIOLIB_STATIC_ONLY
delete[] buffOut;
delete[] buffIn;
#endif
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
// do not return yet to display the debug output
state = RADIOLIB_ERR_SPI_CMD_TIMEOUT;
break;
}
}
}
}
// parse status
int16_t state = RADIOLIB_ERR_NONE;
if((this->spiConfig.parseStatusCb != nullptr) && (numBytes > 0)) {
// parse status (only if GPIO did not timeout)
if((state == RADIOLIB_ERR_NONE) && (this->spiConfig.parseStatusCb != nullptr) && (numBytes > 0)) {
state = this->spiConfig.parseStatusCb(buffIn[this->spiConfig.statusPos]);
}
@ -411,7 +426,7 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
for(; n < cmdLen; n++) {
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", cmd[n]);
}
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
// print data bytes
RADIOLIB_DEBUG_SPI_PRINT("SI\t");
@ -421,12 +436,12 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
for(; n < buffLen; n++) {
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", buffOut[n]);
}
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
RADIOLIB_DEBUG_SPI_PRINT("SO\t");
for(n = 0; n < buffLen; n++) {
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", buffIn[n]);
}
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG("");
#endif
#if !RADIOLIB_STATIC_ONLY

View file

@ -272,9 +272,10 @@ class Module {
\param lsb Least significant bit of the register variable. Bits below this one will not be affected by the write operation.
\param checkInterval Number of milliseconds between register writing and verification reading. Some registers need up to 10ms to process the change.
\param checkMask Mask of bits to check, only bits set to 1 will be verified.
\param force Write new value even if the old value is the same.
\returns \ref status_codes
*/
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF, bool force = false);
/*!
\brief SPI burst read method.
@ -297,7 +298,7 @@ class Module {
\param data Pointer to array that holds the data that will be written.
\param numBytes Number of bytes that will be written.
*/
void SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes);
void SPIwriteRegisterBurst(uint32_t reg, const uint8_t* data, size_t numBytes);
/*!
\brief SPI basic write method. Use of this method is reserved for special cases, SPIsetRegValue should be used instead.
@ -314,7 +315,7 @@ class Module {
\param dataIn Data that was transferred from slave to master.
\param numBytes Number of bytes to transfer.
*/
void SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
void SPItransfer(uint16_t cmd, uint32_t reg, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
/*!
\brief Method to check the result of last SPI stream transfer.
@ -343,7 +344,7 @@ class Module {
\param verify Whether to verify the result of the transaction after it is finished.
\returns \ref status_codes
*/
int16_t SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
int16_t SPIreadStream(const uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
/*!
\brief Method to perform a write transaction with SPI stream.
@ -354,7 +355,7 @@ class Module {
\param verify Whether to verify the result of the transaction after it is finished.
\returns \ref status_codes
*/
int16_t SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
int16_t SPIwriteStream(uint16_t cmd, const uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
/*!
\brief Method to perform a write transaction with SPI stream.
@ -366,7 +367,7 @@ class Module {
\param verify Whether to verify the result of the transaction after it is finished.
\returns \ref status_codes
*/
int16_t SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
int16_t SPIwriteStream(const uint8_t* cmd, uint8_t cmdLen, const uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
/*!
\brief SPI single transfer method for modules with stream-type SPI interface (SX126x, SX128x etc.).
@ -379,15 +380,12 @@ class Module {
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
\returns \ref status_codes
*/
int16_t SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio);
int16_t SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, const uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio);
// pin number access methods
/*!
\brief Access method to get the pin number of SPI chip select.
\returns Pin number of SPI chip select configured in the constructor.
*/
uint32_t getCs() const { return(csPin); }
// getCs is omitted on purpose, as it can interfere when accessing the SPI in a concurrent environment
// so it is considered to be part of the SPI pins and hence not accessible from outside
// see https://github.com/jgromes/RadioLib/discussions/1364
/*!
\brief Access method to get the pin number of interrupt/GPIO.

View file

@ -4,24 +4,15 @@
/*!
\mainpage RadioLib Documentation
Universal wireless communication library for Arduino.
Universal wireless communication library for embedded devices.
\par Currently Supported Wireless Modules and Protocols
- CC1101 FSK module
- RF69 FSK module
- Si443x FSK module
- SX126x LoRa/FSK module
- SX127x LoRa/FSK module
- SX128x LoRa/GFSK/BLE/FLRC module
- SX1231 FSK module
- PhysicalLayer protocols
- RTTY (RTTYClient)
- Morse Code (MorseClient)
- AX.25 (AX25Client)
- SSTV (SSTVClient)
- Hellschreiber (HellClient)
- 4-FSK (FSK4Client)
- APRS (APRSClient)
- POCSAG (PagerClient)
\par Quick Links
Documentation for most common methods can be found in its reference page (see the list above).\n
@ -31,6 +22,7 @@
- PhysicalLayer - FSK and LoRa radio modules
\see https://github.com/jgromes/RadioLib
\see https://jgromes.github.io/RadioLib/coverage/src/index.html
\copyright Copyright (c) 2019 Jan Gromes
*/
@ -66,18 +58,7 @@
#warning "Low-end platform detected, stability issues are likely!"
#endif
#include "modules/CC1101/CC1101.h"
#include "modules/LLCC68/LLCC68.h"
#include "modules/LR11x0/LR1110.h"
#include "modules/LR11x0/LR1120.h"
#include "modules/LR11x0/LR1121.h"
#include "modules/nRF24/nRF24.h"
#include "modules/RF69/RF69.h"
#include "modules/RFM2x/RFM22.h"
#include "modules/RFM2x/RFM23.h"
#include "modules/Si443x/Si4430.h"
#include "modules/Si443x/Si4431.h"
#include "modules/Si443x/Si4432.h"
#include "modules/SX123x/SX1231.h"
#include "modules/SX123x/SX1233.h"
#include "modules/SX126x/SX1261.h"
@ -96,19 +77,7 @@
// physical layer protocols
#include "protocols/PhysicalLayer/PhysicalLayer.h"
#include "protocols/AFSK/AFSK.h"
#include "protocols/AX25/AX25.h"
#include "protocols/Hellschreiber/Hellschreiber.h"
#include "protocols/Morse/Morse.h"
#include "protocols/Pager/Pager.h"
#include "protocols/RTTY/RTTY.h"
#include "protocols/SSTV/SSTV.h"
#include "protocols/FSK4/FSK4.h"
#include "protocols/APRS/APRS.h"
#include "protocols/ExternalRadio/ExternalRadio.h"
#include "protocols/Print/Print.h"
#include "protocols/BellModem/BellModem.h"
#include "protocols/LoRaWAN/LoRaWAN.h"
// utilities
#include "utils/CRC.h"

View file

@ -1,225 +0,0 @@
/*
RadioLib Non-Arduino Tock Library helper functions
Licensed under the MIT License
Copyright (c) 2023 Alistair Francis <alistair@alistair23.me>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef TOCK_HAL_H
#define TOCK_HAL_H
// include RadioLib
#include <RadioLib.h>
// include all the dependencies
#include "libtock/net/lora_phy.h"
#include "libtock/net/syscalls/lora_phy_syscalls.h"
#include "libtock-sync/net/lora_phy.h"
#include "libtock/peripherals/gpio.h"
#include "libtock-sync/services/alarm.h"
#include "libtock/kernel/read_only_state.h"
#define RADIO_BUSY 1
#define RADIO_DIO_1 2
#define RADIO_DIO_3 3
#define RADIO_RESET 4
// Skip the chips select as Tock handles this for us
#define RADIO_NSS RADIOLIB_NC
// define Arduino-style macros
#define PIN_LOW (0x0)
#define PIN_HIGH (0x1)
#define PIN_INPUT (0x01)
#define PIN_OUTPUT (0x03)
#define PIN_RISING (0x01)
#define PIN_FALLING (0x02)
typedef void (*gpioIrqFn)(void);
gpioIrqFn gpio_funcs[4] = { NULL, NULL, NULL, NULL};
uint32_t frequency = 0;
/*
* Get the the timer frequency in Hz.
*/
int alarm_internal_frequency(uint32_t* frequency) {
syscall_return_t rval = command(0x0, 1, 0, 0);
return tock_command_return_u32_to_returncode(rval, frequency);
}
int alarm_internal_read(uint32_t* time) {
syscall_return_t rval = command(0x0, 2, 0, 0);
return tock_command_return_u32_to_returncode(rval, time);
}
static void lora_phy_gpio_Callback (int gpioPin,
__attribute__ ((unused)) int arg2,
__attribute__ ((unused)) int arg3,
void* userdata)
{
gpioIrqFn fn = gpio_funcs[gpioPin - 1];
if (fn != NULL ) {
fn();
}
}
class TockHal : public RadioLibHal {
public:
// default constructor - initializes the base HAL and any needed private members
TockHal()
: RadioLibHal(PIN_INPUT, PIN_OUTPUT, PIN_LOW, PIN_HIGH, PIN_RISING, PIN_FALLING) {
}
void init() override {
}
void term() override {
}
// GPIO-related methods (pinMode, digitalWrite etc.) should check
// RADIOLIB_NC as an alias for non-connected pins
void pinMode(uint32_t pin, uint32_t mode) override {
if(pin == RADIOLIB_NC) {
return;
}
if (mode == PIN_OUTPUT) {
libtock_lora_phy_gpio_enable_output(pin);
} else if (mode == PIN_INPUT) {
libtock_lora_phy_gpio_enable_input(pin, libtock_pull_down);
}
}
void digitalWrite(uint32_t pin, uint32_t value) override {
if(pin == RADIOLIB_NC) {
return;
}
if (value) {
libtock_lora_phy_gpio_set(pin);
} else {
libtock_lora_phy_gpio_clear(pin);
}
}
uint32_t digitalRead(uint32_t pin) override {
int value;
if(pin == RADIOLIB_NC) {
return 0;
}
libtock_lora_phy_gpio_read(pin, &value);
return value;
}
void attachInterrupt(uint32_t interruptNum, gpioIrqFn interruptCb, uint32_t mode) override {
if(interruptNum == RADIOLIB_NC) {
return;
}
gpio_funcs[interruptNum - 1] = interruptCb;
libtock_lora_phy_gpio_command_interrupt_callback(lora_phy_gpio_Callback, NULL);
// set GPIO as input and enable interrupts on it
libtock_lora_phy_gpio_enable_input(interruptNum, libtock_pull_down);
libtock_lora_phy_gpio_enable_interrupt(interruptNum, libtock_change);
}
void detachInterrupt(uint32_t interruptNum) override {
if(interruptNum == RADIOLIB_NC) {
return;
}
gpio_funcs[interruptNum - 1] = NULL;
libtock_lora_phy_gpio_disable_interrupt(interruptNum);
}
void delay(unsigned long ms) override {
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
libtocksync_alarm_delay_ms(ms);
#else
libtocksync_alarm_delay_ms(ms * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS));
#endif
}
void delayMicroseconds(unsigned long us) override {
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
libtocksync_alarm_delay_ms(us / 1000);
#else
libtocksync_alarm_delay_ms((us * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS)) / 1000);
#endif
}
unsigned long millis() override {
uint32_t now;
unsigned long ms;
if (frequency == 0) {
alarm_internal_frequency(&frequency);
}
alarm_internal_read(&now);
ms = now / (frequency / 1000);
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
return ms;
#else
return ms * 1000 / (1000 + RADIOLIB_CLOCK_DRIFT_MS);
#endif
}
unsigned long micros() override {
return millis() / 1000;
}
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
return 0;
}
void spiBegin() {
}
void spiBeginTransaction() {
}
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
libtocksync_lora_phy_read_write(out, in, len);
}
void spiEndTransaction() {
}
void spiEnd() {
}
void yield() {
::yield_no_wait();
}
private:
};
#endif

View file

@ -2,99 +2,26 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_CC1101
CC1101::CC1101(Module* module) : PhysicalLayer(RADIOLIB_CC1101_FREQUENCY_STEP_SIZE, RADIOLIB_CC1101_MAX_PACKET_LENGTH) {
CC1101::CC1101(Module* module) : PhysicalLayer() {
this->freqStep = RADIOLIB_CC1101_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_CC1101_MAX_PACKET_LENGTH;
this->mod = module;
}
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set module properties
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
// set the modulation and execute the common part
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_2_FSK;
return(this->beginCommon(freq, br, freqDev, rxBw, pwr, preambleLength));
}
// try to find the CC1101 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
flagFound = true;
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
this->mod->hal->delay(10);
i++;
}
}
if(!flagFound) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No CC1101 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tCC1101");
}
// configure settings not accessible by API
int16_t state = config();
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
// configure bitrate
state = setBitRate(br);
RADIOLIB_ASSERT(state);
// configure default RX bandwidth
state = setRxBandwidth(rxBw);
RADIOLIB_ASSERT(state);
// configure default frequency deviation
state = setFrequencyDeviation(freqDev);
RADIOLIB_ASSERT(state);
// configure default TX output power
state = setOutputPower(pwr);
RADIOLIB_ASSERT(state);
// set default packet length mode
state = variablePacketLengthMode();
RADIOLIB_ASSERT(state);
// configure default preamble length
state = setPreambleLength(preambleLength, preambleLength - 4);
RADIOLIB_ASSERT(state);
// set default data shaping
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
// set default encoding
state = setEncoding(RADIOLIB_ENCODING_NRZ);
RADIOLIB_ASSERT(state);
// set default sync word
uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
state = setSyncWord(sw[0], sw[1], 0, false);
RADIOLIB_ASSERT(state);
// flush FIFOs
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
return(state);
int16_t CC1101::beginFSK4(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set the modulation and execute the common part
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_4_FSK;
return(this->beginCommon(freq, br, freqDev, rxBw, pwr, preambleLength));
}
void CC1101::reset() {
// this is the manual power-on-reset sequence
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delayMicroseconds(5);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
this->mod->hal->delayMicroseconds(40);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delay(10);
// just send the command, the reset sequence as described in datasheet seems unnecessary in our usage
SPIsendCommand(RADIOLIB_CC1101_CMD_RESET);
}
@ -133,7 +60,7 @@ int16_t CC1101::transmit(const uint8_t* data, size_t len, uint8_t addr) {
int16_t CC1101::receive(uint8_t* data, size_t len) {
// calculate timeout (500 ms + 400 full max-length packets at current bit rate)
RadioLibTime_t timeout = 500 + (1.0/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0f);
// start reception
int16_t state = startReceive();
@ -191,6 +118,12 @@ int16_t CC1101::standby(uint8_t mode) {
return(standby());
}
int16_t CC1101::sleep() {
int16_t state =standby();
SPIsendCommand(RADIOLIB_CC1101_CMD_POWER_DOWN);
return(state);
}
int16_t CC1101::transmitDirect(uint32_t frf) {
return transmitDirect(true, frf);
}
@ -305,23 +238,50 @@ int16_t CC1101::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// flush Tx FIFO
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
// set GDO0 mapping
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_PKT_RECEIVED, 5, 0);
RADIOLIB_ASSERT(state);
// Turn on freq oscilator
SPIsendCommand(RADIOLIB_CC1101_CMD_FSTXON);
// Check MARCSTATE and wait until ready to tx
// 724us is the longest time for calibrate per datasheet
// Needs a bit more time for reliability
RadioLibTime_t start = this->mod->hal->micros();
while(SPIgetRegValue(RADIOLIB_CC1101_REG_MARCSTATE, 4, 0) != 0x12) {
if(this->mod->hal->micros() - start > 800) {
standby();
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
// set GDO0 mapping only if we aren't refilling the FIFO
int16_t state = RADIOLIB_ERR_NONE;
if(len <= RADIOLIB_CC1101_FIFO_SIZE) {
state = SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SYNC_WORD_SENT_OR_PKT_RECEIVED, 5, 0);
RADIOLIB_ASSERT(state);
}
// data put on FIFO
uint8_t dataSent = 0;
// optionally write packet length
if(this->packetLengthConfig == RADIOLIB_CC1101_LENGTH_CONFIG_VARIABLE) {
if (len > RADIOLIB_CC1101_MAX_PACKET_LENGTH - 1) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
SPIwriteRegister(RADIOLIB_CC1101_REG_FIFO, len);
dataSent+= 1;
}
// check address filtering
uint8_t filter = SPIgetRegValue(RADIOLIB_CC1101_REG_PKTCTRL1, 1, 0);
if(filter != RADIOLIB_CC1101_ADR_CHK_NONE) {
SPIwriteRegister(RADIOLIB_CC1101_REG_FIFO, addr);
dataSent += 1;
}
// fill the FIFO
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, const_cast<uint8_t*>(data), len);
uint8_t initialWrite = RADIOLIB_MIN((uint8_t)len, (uint8_t)(RADIOLIB_CC1101_FIFO_SIZE - dataSent));
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, const_cast<uint8_t*>(data), initialWrite);
dataSent += initialWrite;
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
@ -329,11 +289,40 @@ int16_t CC1101::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// set mode to transmit
SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
// Keep feeding the FIFO until the packet is done
while (dataSent < len) {
uint8_t fifoBytes = 0;
uint8_t prevFifobytes = 0;
// Check number of bytes on FIFO twice due to the CC1101 errata. Block until two reads are equal.
do{
fifoBytes = SPIgetRegValue(RADIOLIB_CC1101_REG_TXBYTES, 6, 0);
prevFifobytes = SPIgetRegValue(RADIOLIB_CC1101_REG_TXBYTES, 6, 0);
} while (fifoBytes != prevFifobytes);
//If there is room add more data to the FIFO
if (fifoBytes < RADIOLIB_CC1101_FIFO_SIZE) {
uint8_t bytesToWrite = RADIOLIB_MIN((uint8_t)(RADIOLIB_CC1101_FIFO_SIZE - fifoBytes), (uint8_t)(len - dataSent));
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_FIFO, const_cast<uint8_t*>(&data[dataSent]), bytesToWrite);
dataSent += bytesToWrite;
}
}
return(state);
}
int16_t CC1101::finishTransmit() {
// set mode to standby to disable transmitter/RF switch
// Check MARCSTATE for Idle to let anything in the FIFO empty
// Timeout is 2x FIFO transmit time
RadioLibTime_t timeout = (1.0f/(this->bitRate))*(RADIOLIB_CC1101_FIFO_SIZE*2.0f);
RadioLibTime_t start = this->mod->hal->millis();
while(SPIgetRegValue(RADIOLIB_CC1101_REG_MARCSTATE, 4, 0) != 0x01) {
if(this->mod->hal->millis() - start > timeout) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
int16_t state = standby();
RADIOLIB_ASSERT(state);
@ -429,9 +418,9 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
int16_t CC1101::setFrequency(float freq) {
// check allowed frequency range
#if RADIOLIB_CHECK_PARAMS
if(!(((freq >= 300.0) && (freq <= 348.0)) ||
((freq >= 387.0) && (freq <= 464.0)) ||
((freq >= 779.0) && (freq <= 928.0)))) {
if(!(((freq >= 300.0f) && (freq <= 348.0f)) ||
((freq >= 387.0f) && (freq <= 464.0f)) ||
((freq >= 779.0f) && (freq <= 928.0f)))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY);
}
#endif
@ -441,7 +430,7 @@ int16_t CC1101::setFrequency(float freq) {
//set carrier frequency
uint32_t base = 1;
uint32_t FRF = (freq * (base << 16)) / 26.0;
uint32_t FRF = (freq * (base << 16)) / 26.0f;
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_FREQ2, (FRF & 0xFF0000) >> 16, 7, 0);
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_FREQ1, (FRF & 0x00FF00) >> 8, 7, 0);
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_FREQ0, FRF & 0x0000FF, 7, 0);
@ -455,7 +444,7 @@ int16_t CC1101::setFrequency(float freq) {
}
int16_t CC1101::setBitRate(float br) {
RADIOLIB_CHECK_RANGE(br, 0.025, 600.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(br, 0.025f, 600.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
// set mode to standby
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
@ -463,7 +452,7 @@ int16_t CC1101::setBitRate(float br) {
// calculate exponent and mantissa values
uint8_t e = 0;
uint8_t m = 0;
getExpMant(br * 1000.0, 256, 28, 14, e, m);
getExpMant(br * 1000.0f, 256, 28, 14, e, m);
// set bit rate value
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG4, e, 3, 0);
@ -484,7 +473,7 @@ int16_t CC1101::setBitRateTolerance(uint8_t brt) {
}
int16_t CC1101::setRxBandwidth(float rxBw) {
RADIOLIB_CHECK_RANGE(rxBw, 58.0, 812.0, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
RADIOLIB_CHECK_RANGE(rxBw, 58.0f, 812.0f, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
// set mode to standby
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
@ -492,8 +481,8 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
// calculate exponent and mantissa values
for(int8_t e = 3; e >= 0; e--) {
for(int8_t m = 3; m >= 0; m --) {
float point = (RADIOLIB_CC1101_CRYSTAL_FREQ * 1000000.0)/(8 * (m + 4) * ((uint32_t)1 << e));
if(fabs((rxBw * 1000.0) - point) <= 1000) {
float point = (RADIOLIB_CC1101_CRYSTAL_FREQ * 1000000.0f)/(8 * (m + 4) * ((uint32_t)1 << e));
if(fabs((rxBw * 1000.0f - point) <= 1000.0f)) {
// set Rx channel filter bandwidth
return(SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG4, (e << 6) | (m << 4), 7, 4));
}
@ -505,33 +494,33 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
}
int16_t CC1101::autoSetRxBandwidth() {
// Uncertainty ~ +/- 40ppm for a cheap CC1101
// Uncertainty * 2 for both transmitter and receiver
float uncertainty = ((this->frequency) * 40 * 2);
uncertainty = (uncertainty/1000); //Since bitrate is in kBit
float minbw = ((this->bitRate) + uncertainty);
int possibles[16] = {58, 68, 81, 102, 116, 135, 162, 203, 232, 270, 325, 406, 464, 541, 650, 812};
for (int i = 0; i < 16; i++) {
if (possibles[i] > minbw) {
int16_t state = setRxBandwidth(possibles[i]);
return(state);
}
// Uncertainty ~ +/- 40ppm for a cheap CC1101
// Uncertainty * 2 for both transmitter and receiver
float uncertainty = ((this->frequency) * 40 * 2);
uncertainty = (uncertainty/1000); //Since bitrate is in kBit
float minbw = ((this->bitRate) + uncertainty);
const int options[16] = { 58, 68, 81, 102, 116, 135, 162, 203, 232, 270, 325, 406, 464, 541, 650, 812 };
for(int i = 0; i < 16; i++) {
if(options[i] > minbw) {
return(setRxBandwidth(options[i]));
}
return(RADIOLIB_ERR_UNKNOWN);
}
return(RADIOLIB_ERR_UNKNOWN);
}
int16_t CC1101::setFrequencyDeviation(float freqDev) {
// set frequency deviation to lowest available setting (required for digimodes)
float newFreqDev = freqDev;
if(freqDev < 0.0) {
newFreqDev = 1.587;
if(freqDev < 0.0f) {
newFreqDev = 1.587f;
}
// check range unless 0 (special value)
if (freqDev != 0) {
RADIOLIB_CHECK_RANGE(newFreqDev, 1.587, 380.8, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
RADIOLIB_CHECK_RANGE(newFreqDev, 1.587f, 380.8f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
// set mode to standby
@ -540,7 +529,7 @@ int16_t CC1101::setFrequencyDeviation(float freqDev) {
// calculate exponent and mantissa values
uint8_t e = 0;
uint8_t m = 0;
getExpMant(newFreqDev * 1000.0, 8, 17, 7, e, m);
getExpMant(newFreqDev * 1000.0f, 8, 17, 7, e, m);
// set frequency deviation value
int16_t state = SPIsetRegValue(RADIOLIB_CC1101_REG_DEVIATN, (e << 4), 6, 4);
@ -569,7 +558,7 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
//
// freqDev = (fXosc / 2^17) * (8 + m) * 2^e
//
*freqDev = (1000.0 / (uint32_t(1) << 17)) - (8 + m) * (uint32_t(1) << e);
*freqDev = (1000.0f / (uint32_t(1) << 17)) - (8 + m) * (uint32_t(1) << e);
return(RADIOLIB_ERR_NONE);
}
@ -588,7 +577,7 @@ int16_t CC1101::setOutputPower(int8_t pwr) {
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)
uint8_t paValues[2] = {0x00, powerRaw};
const uint8_t paValues[2] = { 0x00, powerRaw };
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
return(RADIOLIB_ERR_NONE);
@ -633,13 +622,13 @@ int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
// round to the known frequency settings
uint8_t f;
if(this->frequency < 374.0) {
if(this->frequency < 374.0f) {
// 315 MHz
f = 0;
} else if(this->frequency < 650.5) {
} else if(this->frequency < 650.5f) {
// 434 MHz
f = 1;
} else if(this->frequency < 891.5) {
} else if(this->frequency < 891.5f) {
// 868 MHz
f = 2;
} else {
@ -667,7 +656,7 @@ int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
}
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
int16_t CC1101::setSyncWord(const uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
if((maxErrBits > 1) || (len != 2)) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
@ -792,9 +781,9 @@ float CC1101::getRSSI() {
if(!this->directModeEnabled) {
if(this->rawRSSI >= 128) {
rssi = (((float)this->rawRSSI - 256.0)/2.0) - 74.0;
rssi = (((float)this->rawRSSI - 256.0f)/2.0f) - 74.0f;
} else {
rssi = (((float)this->rawRSSI)/2.0) - 74.0;
rssi = (((float)this->rawRSSI)/2.0f) - 74.0f;
}
} else {
uint8_t rawRssi = SPIreadRegister(RADIOLIB_CC1101_REG_RSSI);
@ -922,7 +911,7 @@ int16_t CC1101::setDataShaping(uint8_t sh) {
// set data shaping
switch(sh) {
case RADIOLIB_SHAPING_NONE:
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, RADIOLIB_CC1101_MOD_FORMAT_2_FSK, 6, 4);
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, this->modulation, 6, 4);
break;
case RADIOLIB_SHAPING_0_5:
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, RADIOLIB_CC1101_MOD_FORMAT_GFSK, 6, 4);
@ -1006,6 +995,87 @@ int16_t CC1101::setDIOMapping(uint32_t pin, uint32_t value) {
return(SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0 - pin, value));
}
int16_t CC1101::beginCommon(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set module properties
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
// try to find the CC1101 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
flagFound = true;
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
this->mod->hal->delay(10);
i++;
}
}
if(!flagFound) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No CC1101 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tCC1101");
}
// configure settings not accessible by API
int16_t state = config();
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
// configure bitrate
state = setBitRate(br);
RADIOLIB_ASSERT(state);
// configure default RX bandwidth
state = setRxBandwidth(rxBw);
RADIOLIB_ASSERT(state);
// configure default frequency deviation
state = setFrequencyDeviation(freqDev);
RADIOLIB_ASSERT(state);
// configure default TX output power
state = setOutputPower(pwr);
RADIOLIB_ASSERT(state);
// set default packet length mode
state = variablePacketLengthMode();
RADIOLIB_ASSERT(state);
// configure default preamble length
state = setPreambleLength(preambleLength, preambleLength - 4);
RADIOLIB_ASSERT(state);
// set default data shaping
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
// set default encoding
state = setEncoding(RADIOLIB_ENCODING_NRZ);
RADIOLIB_ASSERT(state);
// set default sync word
const uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
state = setSyncWord(sw[0], sw[1], 0, false);
RADIOLIB_ASSERT(state);
// flush FIFOs
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
return(state);
}
int16_t CC1101::config() {
// Reset the radio. Registers may be dirty from previous usage.
reset();
@ -1058,7 +1128,7 @@ int16_t CC1101::directMode(bool sync) {
void CC1101::getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8_t expMax, uint8_t& exp, uint8_t& mant) {
// get table origin point (exp = 0, mant = 0)
float origin = (mantOffset * RADIOLIB_CC1101_CRYSTAL_FREQ * 1000000.0)/((uint32_t)1 << divExp);
float origin = (mantOffset * RADIOLIB_CC1101_CRYSTAL_FREQ * 1000000.0f)/((uint32_t)1 << divExp);
// iterate over possible exponent values
for(int8_t e = expMax; e >= 0; e--) {
@ -1149,26 +1219,12 @@ void CC1101::SPIwriteRegister(uint8_t reg, uint8_t data) {
return(this->mod->SPIwriteRegister(reg, data));
}
void CC1101::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len) {
void CC1101::SPIwriteRegisterBurst(uint8_t reg, const uint8_t* data, size_t len) {
this->mod->SPIwriteRegisterBurst(reg | RADIOLIB_CC1101_CMD_BURST, data, len);
}
void CC1101::SPIsendCommand(uint8_t cmd) {
// pull NSS low
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
// start transfer
this->mod->hal->spiBeginTransaction();
// send the command byte
uint8_t status = 0;
this->mod->hal->spiTransfer(&cmd, 1, &status);
// stop transfer
this->mod->hal->spiEndTransaction();
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
RADIOLIB_DEBUG_SPI_PRINTLN("CMD\tW\t%02X\t%02X", cmd, status);
(void)status;
this->mod->SPItransferStream(&cmd, 1, true, NULL, NULL, 0, false);
}
#endif

View file

@ -8,8 +8,9 @@
// CC1101 physical layer properties
#define RADIOLIB_CC1101_FREQUENCY_STEP_SIZE 396.7285156
#define RADIOLIB_CC1101_MAX_PACKET_LENGTH 63
#define RADIOLIB_CC1101_CRYSTAL_FREQ 26.0
#define RADIOLIB_CC1101_MAX_PACKET_LENGTH 255
#define RADIOLIB_CC1101_FIFO_SIZE 64
#define RADIOLIB_CC1101_CRYSTAL_FREQ 26.0f
#define RADIOLIB_CC1101_DIV_EXPONENT 16
// CC1101 SPI commands
@ -191,9 +192,6 @@
// RADIOLIB_CC1101_REG_SYNC0
#define RADIOLIB_CC1101_SYNC_WORD_LSB 0x91 // 7 0 sync word LSB
// RADIOLIB_CC1101_REG_PKTLEN
#define RADIOLIB_CC1101_PACKET_LENGTH 0xFF // 7 0 packet length in bytes
// RADIOLIB_CC1101_REG_PKTCTRL1
#define RADIOLIB_CC1101_PQT 0x00 // 7 5 preamble quality threshold
#define RADIOLIB_CC1101_CRC_AUTOFLUSH_OFF 0b00000000 // 3 3 automatic Rx FIFO flush on CRC check fail: disabled (default)
@ -562,6 +560,24 @@ class CC1101: public PhysicalLayer {
int8_t pwr = RADIOLIB_CC1101_DEFAULT_POWER,
uint8_t preambleLength = RADIOLIB_CC1101_DEFAULT_PREAMBLELEN);
/*!
\brief Initialization method for 4-FSK modulation.
\param freq Carrier frequency in MHz. Defaults to 434 MHz.
\param br Bit rate to be used in kbps. Defaults to 4.8 kbps.
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 5.0 kHz.
\param rxBw Receiver bandwidth in kHz. Defaults to 135.0 kHz.
\param pwr Output power in dBm. Defaults to 10 dBm.
\param preambleLength Preamble Length in bits. Defaults to 16 bits.
\returns \ref status_codes
*/
int16_t beginFSK4(
float freq = RADIOLIB_CC1101_DEFAULT_FREQ,
float br = RADIOLIB_CC1101_DEFAULT_BR,
float freqDev = RADIOLIB_CC1101_DEFAULT_FREQDEV,
float rxBw = RADIOLIB_CC1101_DEFAULT_RXBW,
int8_t pwr = RADIOLIB_CC1101_DEFAULT_POWER,
uint8_t preambleLength = RADIOLIB_CC1101_DEFAULT_PREAMBLELEN);
/*!
\brief Reset method - resets the chip using manual reset sequence (without RESET pin).
*/
@ -599,6 +615,12 @@ class CC1101: public PhysicalLayer {
*/
int16_t standby(uint8_t mode) override;
/*!
\brief Sets the module to sleep mode.
\returns \ref status_codes
*/
int16_t sleep() override;
/*!
\brief Starts synchronous direct mode transmission.
\param frf Raw RF frequency value. Defaults to 0, required for quick frequency shifts in RTTY.
@ -680,7 +702,10 @@ class CC1101: public PhysicalLayer {
void clearPacketSentAction() override;
/*!
\brief Interrupt-driven binary transmit method.
\brief Interrupt-driven binary transmit method for packets less than 64 bytes.
Method blocks for packets longer than 64 bytes up to a 255 byte limit, until
the last bytes are placed in the FIFO. Some limitations and issues apply; see discussion:
https://github.com/jgromes/RadioLib/discussions/1138
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
@ -818,7 +843,7 @@ class CC1101: public PhysicalLayer {
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
\returns \ref status_codes
*/
int16_t setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0, bool requireCarrierSense = false);
int16_t setSyncWord(const uint8_t* syncWord, uint8_t len, uint8_t maxErrBits = 0, bool requireCarrierSense = false);
/*!
\brief Sets preamble length.
@ -988,7 +1013,7 @@ class CC1101: public PhysicalLayer {
int16_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2);
void SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
uint8_t SPIreadRegister(uint8_t reg);
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len);
void SPIwriteRegisterBurst(uint8_t reg, const uint8_t* data, size_t len);
void SPIwriteRegister(uint8_t reg, uint8_t data);
void SPIsendCommand(uint8_t cmd);
@ -1014,6 +1039,7 @@ class CC1101: public PhysicalLayer {
int8_t power = RADIOLIB_CC1101_DEFAULT_POWER;
int16_t beginCommon(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength);
int16_t config();
int16_t transmitDirect(bool sync, uint32_t frf);
int16_t receiveDirect(bool sync);

View file

@ -9,6 +9,13 @@ LLCC68::LLCC68(Module* mod) : SX1262(mod) {
int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t pwr, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
// execute common part
int16_t state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
// bit of a hack, but some LLCC68 chips report as "SX1261", try that
// for full discussion, see https://github.com/jgromes/RadioLib/issues/1329
chipType = RADIOLIB_SX1261_CHIP_TYPE;
state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
RADIOLIB_DEBUG_PRINTLN("LLCC68 version string not found, using SX1261 instead");
}
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
@ -30,8 +37,58 @@ int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
return(state);
}
int16_t LLCC68::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
// execute common part
int16_t state = SX126x::beginFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage, useRegulatorLDO);
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
// bit of a hack, but some LLCC68 chips report as "SX1261", try that
// for full discussion, see https://github.com/jgromes/RadioLib/issues/1329
chipType = RADIOLIB_SX1261_CHIP_TYPE;
state = SX126x::beginFSK(br, freqDev, rxBw, preambleLength, tcxoVoltage, useRegulatorLDO);
RADIOLIB_DEBUG_PRINTLN("LLCC68 version string not found, using SX1261 instead");
}
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
state = SX126x::fixPaClamping();
RADIOLIB_ASSERT(state);
state = setOutputPower(power);
RADIOLIB_ASSERT(state);
return(state);
}
int16_t LLCC68::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, bool narrowGrid, int8_t power, float tcxoVoltage, bool useRegulatorLDO) {
// execute common part
int16_t state = SX126x::beginLRFHSS(bw, cr, narrowGrid, tcxoVoltage, useRegulatorLDO);
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
// bit of a hack, but some LLCC68 chips report as "SX1261", try that
// for full discussion, see https://github.com/jgromes/RadioLib/issues/1329
chipType = RADIOLIB_SX1261_CHIP_TYPE;
state = SX126x::beginLRFHSS(bw, cr, narrowGrid, tcxoVoltage, useRegulatorLDO);
RADIOLIB_DEBUG_PRINTLN("LLCC68 version string not found, using SX1261 instead");
}
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
state = SX126x::fixPaClamping();
RADIOLIB_ASSERT(state);
state = setOutputPower(power);
RADIOLIB_ASSERT(state);
return(state);
}
int16_t LLCC68::setBandwidth(float bw) {
RADIOLIB_CHECK_RANGE(bw, 100.0, 510.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(bw, 100.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
return(SX1262::setBandwidth(bw));
}
@ -88,14 +145,14 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) {
// select interpretation based on active modem
uint8_t modem = this->getPacketType();
if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.6, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 0.6, 200.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.6f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 100.0, 510.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 100.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 5, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
uint8_t bw_div2 = dr.lora.bandwidth / 2 + 0.01;
uint8_t bw_div2 = dr.lora.bandwidth / 2 + 0.01f;
switch (bw_div2) {
case 62: // 125.0:
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 5, 9, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
@ -118,13 +175,13 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) {
int16_t LLCC68::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
default:

View file

@ -7,6 +7,7 @@
#include "../../Module.h"
#include "../SX126x/SX1262.h"
#include "../SX126x/SX1261.h"
//RADIOLIB_SX126X_REG_VERSION_STRING
#define RADIOLIB_LLCC68_CHIP_TYPE "LLCC68"
@ -38,8 +39,39 @@ class LLCC68: public SX1262 {
\param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false.
\returns \ref status_codes
*/
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t pwr = 10, uint16_t preambleLength = 8, float tcxoVoltage = 0, bool useRegulatorLDO = false);
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 0, bool useRegulatorLDO = false) override;
/*!
\brief Initialization method for FSK modem.
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
\param br FSK bit rate in kbps. Defaults to 4.8 kbps.
\param freqDev Frequency deviation from carrier frequency in kHz. Defaults to 5.0 kHz.
\param rxBw Receiver bandwidth in kHz. Defaults to 156.2 kHz.
\param power Output power in dBm. Defaults to 10 dBm.
\param preambleLength FSK preamble length in bits. Defaults to 16 bits.
\param tcxoVoltage TCXO reference voltage to be set on DIO3. Defaults to 0 V (XTAL).
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
To use XTAL, either set this value to 0, or set SX126x::XTAL to true.
\param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false.
\returns \ref status_codes
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 0, bool useRegulatorLDO = false) override;
/*!
\brief Initialization method for LR-FHSS modem. This modem only supports transmission!
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
\param bw LR-FHSS bandwidth, one of RADIOLIB_SX126X_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
\param cr LR-FHSS coding rate, one of RADIOLIB_SX126X_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
\param narrowGrid Whether to use narrow (3.9 kHz) or wide (25.39 kHz) grid spacing. Defaults to true (narrow/non-FCC) grid.
\param power Output power in dBm. Defaults to 10 dBm.
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 0 V (XTAL).
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
To use XTAL, either set this value to 0, or set SX126x::XTAL to true.
\param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false.
\returns \ref status_codes
*/
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_SX126X_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_SX126X_LR_FHSS_CR_2_3, bool narrowGrid = true, int8_t power = 10, float tcxoVoltage = 0, bool useRegulatorLDO = false) override;
// configuration methods
/*!
@ -47,14 +79,14 @@ class LLCC68: public SX1262 {
\param bw LoRa bandwidth to be set in kHz.
\returns \ref status_codes
*/
int16_t setBandwidth(float bw);
int16_t setBandwidth(float bw) override;
/*!
\brief Sets LoRa spreading factor. Allowed values range from 5 to 11, depending on currently set spreading factor.
\param sf LoRa spreading factor to be set.
\returns \ref status_codes
*/
int16_t setSpreadingFactor(uint8_t sf);
int16_t setSpreadingFactor(uint8_t sf) override;
/*!
\brief Set data.

View file

@ -51,7 +51,7 @@ int16_t LR1110::setFrequency(float freq) {
}
int16_t LR1110::setFrequency(float freq, bool skipCalibration, float band) {
RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 150.0f, 960.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// check if we need to recalibrate image
int16_t state;
@ -113,13 +113,13 @@ int16_t LR1110::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo
int16_t LR1110::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginGFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
}

View file

@ -9,7 +9,7 @@ LR1120::LR1120(Module* mod) : LR11x0(mod) {
int16_t LR1120::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
// execute common part
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, preambleLength, tcxoVoltage, freq > 1000.0);
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, preambleLength, tcxoVoltage, freq > 1000.0f);
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
@ -51,11 +51,13 @@ int16_t LR1120::setFrequency(float freq) {
}
int16_t LR1120::setFrequency(float freq, bool skipCalibration, float band) {
if(!(((freq >= 150.0) && (freq <= 960.0)) ||
((freq >= 1900.0) && (freq <= 2200.0)) ||
((freq >= 2400.0) && (freq <= 2500.0)))) {
#if RADIOLIB_CHECK_PARAMS
if(!(((freq >= 150.0f) && (freq <= 960.0f)) ||
((freq >= 1900.0f) && (freq <= 2200.0f)) ||
((freq >= 2400.0f) && (freq <= 2500.0f)))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY);
}
#endif
// check if we need to recalibrate image
int16_t state;
@ -68,7 +70,7 @@ int16_t LR1120::setFrequency(float freq, bool skipCalibration, float band) {
state = LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f));
RADIOLIB_ASSERT(state);
this->freqMHz = freq;
this->highFreq = (freq > 1000.0);
this->highFreq = (freq > 1000.0f);
return(RADIOLIB_ERR_NONE);
}
@ -133,17 +135,17 @@ int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo
int16_t LR1120::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginGFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
}
return(RADIOLIB_ERR_WRONG_MODEM);
}
#endif
#endif

View file

@ -8,7 +8,9 @@
#if !RADIOLIB_EXCLUDE_LR11X0
LR11x0::LR11x0(Module* mod) : PhysicalLayer(RADIOLIB_LR11X0_FREQUENCY_STEP_SIZE, RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
LR11x0::LR11x0(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_LR11X0_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_LR11X0_MAX_PACKET_LENGTH;
this->mod = mod;
this->XTAL = false;
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_LR11X0_IRQ_TX_DONE;
@ -110,7 +112,8 @@ int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, bool narrowGrid, float tcxoV
state = setLrFhssConfig(bw, cr);
RADIOLIB_ASSERT(state);
state = setSyncWord(0x12AD101B);
uint8_t syncWord[] = { 0x12, 0xAD, 0x10, 0x1B };
state = setSyncWord(syncWord, 4);
RADIOLIB_ASSERT(state);
state = setRegulatorLDO();
@ -128,6 +131,8 @@ int16_t LR11x0::beginGNSS(uint8_t constellations, float tcxoVoltage) {
state = this->clearErrors();
RADIOLIB_ASSERT(state);
// set GNSS flag to reserve DIO11 for LF clock
this->gnss = true;
state = this->configLfClock(RADIOLIB_LR11X0_LF_BUSY_RELEASE_DISABLED | RADIOLIB_LR11X0_LF_CLK_XOSC);
RADIOLIB_ASSERT(state);
@ -216,7 +221,7 @@ int16_t LR11x0::transmit(const uint8_t* data, size_t len, uint8_t addr) {
RadioLibTime_t elapsed = this->mod->hal->micros() - start;
// update data rate
this->dataRateMeasured = (len*8.0)/((float)elapsed/1000000.0);
this->dataRateMeasured = (len*8.0f)/((float)elapsed/1000000.0f);
return(finishTransmit());
}
@ -235,7 +240,7 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
// calculate timeout (100 LoRa symbols, the default for SX127x series)
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
timeout = (RadioLibTime_t)(symbolLength * 100.0);
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
// calculate timeout (500 % of expected time-one-air)
@ -243,8 +248,8 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
if(len == 0) {
maxLen = 0xFF;
}
float brBps = ((float)(RADIOLIB_LR11X0_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0);
float brBps = ((float)(RADIOLIB_LR11X0_CRYSTAL_FREQ) * 1000000.0f * 32.0f) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// this modem cannot receive
@ -258,7 +263,7 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
// start reception
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0) / 30.52);
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0f) / 30.52f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -284,7 +289,7 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) {
// check whether this was a timeout or not
if((getIrqStatus() & RADIOLIB_LR11X0_IRQ_TIMEOUT) || softTimeout) {
standby();
clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
return(RADIOLIB_ERR_RX_TIMEOUT);
}
@ -353,10 +358,9 @@ int16_t LR11x0::standby(uint8_t mode, bool wakeup) {
this->mod->setRfSwitchState(Module::MODE_IDLE);
if(wakeup) {
// pull NSS low for a while to wake up
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delay(1);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
// send a NOP command - this pulls the NSS low to exit the sleep mode,
// while preventing interference with possible other SPI transactions
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_LR11X0_CMD_NOP, NULL, 0, false, false);
}
uint8_t buff[] = { mode };
@ -412,76 +416,9 @@ void LR11x0::clearPacketSentAction() {
this->clearIrqAction();
}
int16_t LR11x0::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// suppress unused variable warning
(void)addr;
// check packet length
if(len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((this->addrComp != RADIOLIB_LR11X0_GFSK_ADDR_FILTER_DISABLED) && (len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcTypeLoRa, this->invertIQEnabled);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, len, this->crcTypeGFSK, this->whitening);
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// in LR-FHSS mode, the packet is built by the device
// TODO add configurable device offset
state = lrFhssBuildFrame(this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
} else {
// write packet to buffer
state = writeBuffer8(const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
}
// clear interrupt flags
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state = setTx(RADIOLIB_LR11X0_TX_TIMEOUT_NONE);
RADIOLIB_ASSERT(state);
// wait for BUSY to go low (= PA ramp up done)
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
this->mod->hal->yield();
}
return(state);
}
int16_t LR11x0::finishTransmit() {
// clear interrupt flags
clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
// set mode to standby to disable transmitter/RF switch
return(standby());
@ -491,46 +428,6 @@ int16_t LR11x0::startReceive() {
return(this->startReceive(RADIOLIB_LR11X0_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t LR11x0::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
(void)len;
// check active modem
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
uint32_t irq = irqMask;
if(timeout != RADIOLIB_LR11X0_RX_TIMEOUT_INF) {
irq |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(irqFlags & irq));
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->implicitLen, this->crcTypeLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
state = setRx(timeout);
return(state);
}
uint32_t LR11x0::getIrqStatus() {
// there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes
uint8_t buff[6] = { 0 };
@ -578,7 +475,7 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) {
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
// check if CRC failed - this is done after reading data to give user the option to keep them
RADIOLIB_ASSERT(crcState);
@ -624,7 +521,7 @@ int16_t LR11x0::startChannelScan(const ChannelScanConfig_t &config) {
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set mode to CAD
@ -665,22 +562,22 @@ int16_t LR11x0::setBandwidth(float bw, bool high) {
// ensure byte conversion doesn't overflow
if (high) {
RADIOLIB_CHECK_RANGE(bw, 203.125, 815.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(bw, 203.125f, 815.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
if(fabsf(bw - 203.125) <= 0.001) {
if(fabsf(bw - 203.125f) <= 0.001f) {
this->bandwidth = RADIOLIB_LR11X0_LORA_BW_203_125;
} else if(fabsf(bw - 406.25) <= 0.001) {
} else if(fabsf(bw - 406.25f) <= 0.001f) {
this->bandwidth = RADIOLIB_LR11X0_LORA_BW_406_25;
} else if(fabsf(bw - 812.5) <= 0.001) {
} else if(fabsf(bw - 812.5f) <= 0.001f) {
this->bandwidth = RADIOLIB_LR11X0_LORA_BW_812_50;
} else {
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
}
} else {
RADIOLIB_CHECK_RANGE(bw, 0.0, 510.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(bw, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
// check allowed bandwidth values
uint8_t bw_div2 = bw / 2 + 0.01;
uint8_t bw_div2 = bw / 2 + 0.01f;
switch (bw_div2) {
case 31: // 62.5:
this->bandwidth = RADIOLIB_LR11X0_LORA_BW_62_5;
@ -758,24 +655,20 @@ int16_t LR11x0::setCodingRate(uint8_t cr, bool longInterleave) {
return(setModulationParamsLoRa(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
}
int16_t LR11x0::setSyncWord(uint32_t syncWord) {
int16_t LR11x0::setSyncWord(uint8_t syncWord) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
return(setLoRaSyncWord(syncWord & 0xFF));
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(lrFhssSetSyncWord(syncWord));
if(type != RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
return(RADIOLIB_ERR_WRONG_MODEM);
return(setLoRaSyncWord(syncWord));
}
int16_t LR11x0::setBitRate(float br) {
RADIOLIB_CHECK_RANGE(br, 0.6, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(br, 0.6f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
@ -787,7 +680,7 @@ int16_t LR11x0::setBitRate(float br) {
// set bit rate value
// TODO implement fractional bit rate configuration
this->bitRate = br * 1000.0;
this->bitRate = br * 1000.0f;
return(setModulationParamsGFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev));
}
@ -802,12 +695,12 @@ int16_t LR11x0::setFrequencyDeviation(float freqDev) {
// set frequency deviation to lowest available setting (required for digimodes)
float newFreqDev = freqDev;
if(freqDev < 0.0) {
newFreqDev = 0.6;
if(freqDev < 0.0f) {
newFreqDev = 0.6f;
}
RADIOLIB_CHECK_RANGE(newFreqDev, 0.6, 200.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
this->frequencyDev = newFreqDev * 1000.0;
RADIOLIB_CHECK_RANGE(newFreqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
this->frequencyDev = newFreqDev * 1000.0f;
return(setModulationParamsGFSK(this->bitRate, this->pulseShape, this->rxBandwidth, this->frequencyDev));
}
@ -826,47 +719,47 @@ int16_t LR11x0::setRxBandwidth(float rxBw) {
}*/
// check allowed receiver bandwidth values
if(fabsf(rxBw - 4.8) <= 0.001) {
if(fabsf(rxBw - 4.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_4_8;
} else if(fabsf(rxBw - 5.8) <= 0.001) {
} else if(fabsf(rxBw - 5.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_5_8;
} else if(fabsf(rxBw - 7.3) <= 0.001) {
} else if(fabsf(rxBw - 7.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_7_3;
} else if(fabsf(rxBw - 9.7) <= 0.001) {
} else if(fabsf(rxBw - 9.7f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_9_7;
} else if(fabsf(rxBw - 11.7) <= 0.001) {
} else if(fabsf(rxBw - 11.7f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_11_7;
} else if(fabsf(rxBw - 14.6) <= 0.001) {
} else if(fabsf(rxBw - 14.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_14_6;
} else if(fabsf(rxBw - 19.5) <= 0.001) {
} else if(fabsf(rxBw - 19.5f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_19_5;
} else if(fabsf(rxBw - 23.4) <= 0.001) {
} else if(fabsf(rxBw - 23.4f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_23_4;
} else if(fabsf(rxBw - 29.3) <= 0.001) {
} else if(fabsf(rxBw - 29.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_29_3;
} else if(fabsf(rxBw - 39.0) <= 0.001) {
} else if(fabsf(rxBw - 39.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_39_0;
} else if(fabsf(rxBw - 46.9) <= 0.001) {
} else if(fabsf(rxBw - 46.9f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_46_9;
} else if(fabsf(rxBw - 58.6) <= 0.001) {
} else if(fabsf(rxBw - 58.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_58_6;
} else if(fabsf(rxBw - 78.2) <= 0.001) {
} else if(fabsf(rxBw - 78.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_78_2;
} else if(fabsf(rxBw - 93.8) <= 0.001) {
} else if(fabsf(rxBw - 93.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_93_8;
} else if(fabsf(rxBw - 117.3) <= 0.001) {
} else if(fabsf(rxBw - 117.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_117_3;
} else if(fabsf(rxBw - 156.2) <= 0.001) {
} else if(fabsf(rxBw - 156.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_156_2;
} else if(fabsf(rxBw - 187.2) <= 0.001) {
} else if(fabsf(rxBw - 187.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_187_2;
} else if(fabsf(rxBw - 234.3) <= 0.001) {
} else if(fabsf(rxBw - 234.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_234_3;
} else if(fabsf(rxBw - 312.0) <= 0.001) {
} else if(fabsf(rxBw - 312.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_312_0;
} else if(fabsf(rxBw - 373.6) <= 0.001) {
} else if(fabsf(rxBw - 373.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_373_6;
} else if(fabsf(rxBw - 467.0) <= 0.001) {
} else if(fabsf(rxBw - 467.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_LR11X0_GFSK_RX_BW_467_0;
} else {
return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
@ -885,27 +778,36 @@ int16_t LR11x0::setSyncWord(uint8_t* syncWord, size_t len) {
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
// update sync word length
this->syncWordLength = len*8;
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, RADIOLIB_LR11X0_MAX_PACKET_LENGTH, this->crcTypeGFSK, this->whitening);
RADIOLIB_ASSERT(state);
// sync word is passed most-significant byte first
uint8_t fullSyncWord[RADIOLIB_LR11X0_GFSK_SYNC_WORD_LEN] = { 0 };
memcpy(fullSyncWord, syncWord, len);
return(setGfskSyncWord(fullSyncWord));
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
// with length set to 1 and LoRa modem active, assume it is the LoRa sync word
if(len > 1) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
return(setSyncWord(syncWord[0]));
} else if(type != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// with length set to 4 and LR-FHSS modem active, assume it is the LR-FHSS sync word
if(len != sizeof(uint32_t)) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
uint32_t sync = 0;
memcpy(&sync, syncWord, sizeof(uint32_t));
return(lrFhssSetSyncWord(sync));
}
// update sync word length
this->syncWordLength = len*8;
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, RADIOLIB_LR11X0_MAX_PACKET_LENGTH, this->crcTypeGFSK, this->whitening);
RADIOLIB_ASSERT(state);
// sync word is passed most-significant byte first
uint8_t fullSyncWord[RADIOLIB_LR11X0_GFSK_SYNC_WORD_LEN] = { 0 };
memcpy(fullSyncWord, syncWord, len);
return(setGfskSyncWord(fullSyncWord));
return(RADIOLIB_ERR_WRONG_MODEM);
}
int16_t LR11x0::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
@ -1097,13 +999,13 @@ int16_t LR11x0::checkDataRate(DataRate_t dr) {
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.6, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 0.6, 200.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.6f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(dr.fsk.freqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
return(RADIOLIB_ERR_NONE);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 5, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 0.0, 510.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(dr.lora.bandwidth, 0.0f, 510.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(dr.lora.codingRate, 5, 8, RADIOLIB_ERR_INVALID_CODING_RATE);
return(RADIOLIB_ERR_NONE);
@ -1151,28 +1053,28 @@ int16_t LR11x0::setTCXO(float voltage, uint32_t delay) {
}
// check 0 V disable
if(fabsf(voltage - 0.0) <= 0.001) {
if(fabsf(voltage - 0.0f) <= 0.001f) {
setTcxoMode(0, 0);
return(reset());
}
// check allowed voltage values
uint8_t tune = 0;
if(fabsf(voltage - 1.6) <= 0.001) {
if(fabsf(voltage - 1.6f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_1_6;
} else if(fabsf(voltage - 1.7) <= 0.001) {
} else if(fabsf(voltage - 1.7f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_1_7;
} else if(fabsf(voltage - 1.8) <= 0.001) {
} else if(fabsf(voltage - 1.8f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_1_8;
} else if(fabsf(voltage - 2.2) <= 0.001) {
} else if(fabsf(voltage - 2.2f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_2_2;
} else if(fabsf(voltage - 2.4) <= 0.001) {
} else if(fabsf(voltage - 2.4f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_2_4;
} else if(fabsf(voltage - 2.7) <= 0.001) {
} else if(fabsf(voltage - 2.7f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_2_7;
} else if(fabsf(voltage - 3.0) <= 0.001) {
} else if(fabsf(voltage - 3.0f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_3_0;
} else if(fabsf(voltage - 3.3) <= 0.001) {
} else if(fabsf(voltage - 3.3f) <= 0.001f) {
tune = RADIOLIB_LR11X0_TCXO_VOLTAGE_3_3;
} else {
return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE);
@ -1346,7 +1248,7 @@ RadioLibTime_t LR11x0::getTimeOnAir(size_t len) {
uint32_t N_symbolPreamble = (this->preambleLengthLoRa & 0x0F) * (uint32_t(1) << ((this->preambleLengthLoRa & 0xF0) >> 4));
// calculate the number of symbols
N_symbol = (float)N_symbolPreamble + coeff1 + 8.0 + ceilf((float)RADIOLIB_MAX((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * (float)(this->codingRate + 4);
N_symbol = (float)N_symbolPreamble + coeff1 + 8.0f + ceilf((float)RADIOLIB_MAX((int16_t)(8 * len + N_bitCRC - coeff2 + N_symbolHeader), (int16_t)0) / (float)coeff3) * (float)(this->codingRate + 4);
} else {
// long interleaving - abandon hope all ye who enter here
@ -1355,7 +1257,7 @@ RadioLibTime_t LR11x0::getTimeOnAir(size_t len) {
}
// get time-on-air in us
return(((uint32_t(1) << this->spreadingFactor) / this->bandwidthKhz) * N_symbol * 1000.0);
return(((uint32_t(1) << this->spreadingFactor) / this->bandwidthKhz) * N_symbol * 1000.0f);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
return(((uint32_t)len * 8 * 1000000UL) / this->bitRate);
@ -1412,7 +1314,7 @@ int16_t LR11x0::setIrqFlags(uint32_t irq) {
}
int16_t LR11x0::clearIrqFlags(uint32_t irq) {
return(this->clearIrq(irq));
return(this->clearIrqState(irq));
}
uint8_t LR11x0::randomByte() {
@ -1587,7 +1489,7 @@ void LR11x0::clearWiFiScanAction() {
int16_t LR11x0::getWifiScanResultsCount(uint8_t* count) {
// clear IRQ first, as this is likely to be called right after scan has finished
int16_t state = clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
int16_t state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
uint8_t buff[1] = { 0 };
@ -1758,7 +1660,7 @@ int16_t LR11x0::updateFirmware(const uint32_t* image, size_t size, bool nonvolat
uint32_t offset = i * maxLen;
uint32_t len = (i == (numWrites - 1)) ? rem : maxLen;
RADIOLIB_DEBUG_BASIC_PRINTLN("Writing chunk %d at offset %08lx (%u words)", (int)i, (unsigned long)offset, (unsigned int)len);
this->bootWriteFlashEncrypted(offset*sizeof(uint32_t), (uint32_t*)&image[offset], len, nonvolatile);
this->bootWriteFlashEncrypted(offset*sizeof(uint32_t), const_cast<uint32_t*>(&image[offset]), len, nonvolatile);
}
// kick the device from bootloader
@ -1804,7 +1706,7 @@ int16_t LR11x0::isGnssScanCapable() {
size_t len = sz > 32 ? 32 : sz/sizeof(uint32_t);
state = this->readRegMem32(addr, buff, len);
RADIOLIB_ASSERT(state);
RADIOLIB_DEBUG_HEXDUMP(NULL, (uint8_t*)buff, len*sizeof(uint32_t), addr);
RADIOLIB_DEBUG_HEXDUMP(NULL, reinterpret_cast<uint8_t*>(buff), len*sizeof(uint32_t), addr);
addr += len*sizeof(uint32_t);
sz -= len*sizeof(uint32_t);
}
@ -1863,7 +1765,7 @@ int16_t LR11x0::gnssScan(LR11x0GnssResult_t* res) {
// distinguish between GNSS-done and GNSS-abort outcomes and clear the flags
uint32_t irq = this->getIrqStatus();
this->clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
this->clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
if(irq & RADIOLIB_LR11X0_IRQ_GNSS_ABORT) {
return(RADIOLIB_ERR_RX_TIMEOUT);
}
@ -1975,7 +1877,7 @@ int16_t LR11x0::updateGnssAlmanac(uint8_t constellation) {
// distinguish between GNSS-done and GNSS-abort outcomes and clear the flags
uint32_t irq = this->getIrqStatus();
this->clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
this->clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
if(irq & RADIOLIB_LR11X0_IRQ_GNSS_ABORT) {
state = RADIOLIB_ERR_RX_TIMEOUT;
}
@ -2026,25 +1928,143 @@ int16_t LR11x0::getGnssSatellites(LR11x0GnssSatellite_t* sats, uint8_t numSats)
int16_t LR11x0::getModem(ModemType_t* modem) {
RADIOLIB_ASSERT_PTR(modem);
uint8_t packetType = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&packetType);
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
switch(packetType) {
switch(type) {
case(RADIOLIB_LR11X0_PACKET_TYPE_LORA):
*modem = ModemType_t::LoRa;
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_LR11X0_PACKET_TYPE_GFSK):
*modem = ModemType_t::FSK;
*modem = ModemType_t::RADIOLIB_MODEM_FSK;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS):
*modem = ModemType_t::LRFHSS;
*modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
return(RADIOLIB_ERR_NONE);
}
return(RADIOLIB_ERR_WRONG_MODEM);
}
int16_t LR11x0::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
// check active modem
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) &&
(modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(cfg->receive.timeout != RADIOLIB_LR11X0_RX_TIMEOUT_INF) {
cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(cfg->receive.irqFlags & cfg->receive.irqMask));
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_LR11X0_LORA_HEADER_IMPLICIT) && (modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->implicitLen, this->crcTypeLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
this->rxTimeout = cfg->receive.timeout;
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// check packet length
if(cfg->transmit.len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((this->addrComp != RADIOLIB_LR11X0_GFSK_ADDR_FILTER_DISABLED) && (cfg->transmit.len > RADIOLIB_LR11X0_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
state = RADIOLIB_ERR_NONE;
uint8_t modem = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
state = getPacketType(&modem);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcTypeLoRa, this->invertIQEnabled);
} else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, cfg->transmit.len, this->crcTypeGFSK, this->whitening);
} else if(modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
state = setDioIrqParams(RADIOLIB_LR11X0_IRQ_TX_DONE | RADIOLIB_LR11X0_IRQ_TIMEOUT);
RADIOLIB_ASSERT(state);
if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// in LR-FHSS mode, the packet is built by the device
// TODO add configurable device offset
state = lrFhssBuildFrame(this->lrFhssHdrCount, this->lrFhssCr, this->lrFhssGrid, true, this->lrFhssBw, this->lrFhssHopSeq, 0, cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
} else {
// write packet to buffer
state = writeBuffer8(cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
}
// clear interrupt flags
state = clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t LR11x0::launchMode() {
int16_t state;
switch(this->stagedMode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->mod->setRfSwitchState(Module::MODE_RX);
state = setRx(this->rxTimeout);
} break;
case(RADIOLIB_RADIO_MODE_TX): {
this->mod->setRfSwitchState(Module::MODE_TX);
state = setTx(RADIOLIB_LR11X0_TX_TIMEOUT_NONE);
RADIOLIB_ASSERT(state);
// wait for BUSY to go low (= PA ramp up done)
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
this->mod->hal->yield();
}
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
return(state);
}
int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
@ -2060,6 +2080,7 @@ int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->spiConfig.stream = true;
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
this->gnss = false;
// try to find the LR11x0 chip - this will also reset the module at least once
if(!LR11x0::findChip(this->chipType)) {
@ -2074,7 +2095,7 @@ int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
RADIOLIB_ASSERT(state);
// set TCXO control, if requested
if(!this->XTAL && tcxoVoltage > 0.0) {
if(!this->XTAL && tcxoVoltage > 0.0f) {
state = setTCXO(tcxoVoltage);
RADIOLIB_ASSERT(state);
}
@ -2106,7 +2127,7 @@ int16_t LR11x0::SPIcheckStatus(Module* mod) {
return(LR11x0::SPIparseStatus(buff[0]));
}
int16_t LR11x0::SPIcommand(uint16_t cmd, bool write, uint8_t* data, size_t len, uint8_t* out, size_t outLen) {
int16_t LR11x0::SPIcommand(uint16_t cmd, bool write, uint8_t* data, size_t len, const uint8_t* out, size_t outLen) {
int16_t state = RADIOLIB_ERR_UNKNOWN;
if(!write) {
// the SPI interface of LR11x0 requires two separate transactions for reading
@ -2167,7 +2188,7 @@ int16_t LR11x0::config(uint8_t modem) {
RADIOLIB_ASSERT(state);
// clear IRQ
state = this->clearIrq(RADIOLIB_LR11X0_IRQ_ALL);
state = this->clearIrqState(RADIOLIB_LR11X0_IRQ_ALL);
state |= this->setDioIrqParams(RADIOLIB_LR11X0_IRQ_NONE);
RADIOLIB_ASSERT(state);
@ -2281,7 +2302,7 @@ Module* LR11x0::getMod() {
return(this->mod);
}
int16_t LR11x0::writeRegMem32(uint32_t addr, uint32_t* data, size_t len) {
int16_t LR11x0::writeRegMem32(uint32_t addr, const uint32_t* data, size_t len) {
// check maximum size
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
@ -2326,12 +2347,12 @@ int16_t LR11x0::readRegMem32(uint32_t addr, uint32_t* data, size_t len) {
return(state);
}
int16_t LR11x0::writeBuffer8(uint8_t* data, size_t len) {
int16_t LR11x0::writeBuffer8(const uint8_t* data, size_t len) {
// check maximum size
if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
}
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_BUFFER, true, data, len));
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_WRITE_BUFFER, true, const_cast<uint8_t*>(data), len));
}
int16_t LR11x0::readBuffer8(uint8_t* data, size_t len, size_t offset) {
@ -2446,10 +2467,10 @@ int16_t LR11x0::setDioIrqParams(uint32_t irq1, uint32_t irq2) {
}
int16_t LR11x0::setDioIrqParams(uint32_t irq) {
return(setDioIrqParams(irq, 0));
return(setDioIrqParams(irq, this->gnss ? 0 : irq));
}
int16_t LR11x0::clearIrq(uint32_t irq) {
int16_t LR11x0::clearIrqState(uint32_t irq) {
uint8_t buff[4] = {
(uint8_t)((irq >> 24) & 0xFF), (uint8_t)((irq >> 16) & 0xFF), (uint8_t)((irq >> 8) & 0xFF), (uint8_t)(irq & 0xFF),
};
@ -2457,7 +2478,7 @@ int16_t LR11x0::clearIrq(uint32_t irq) {
}
int16_t LR11x0::configLfClock(uint8_t setup) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK, true, &setup, 1));
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK, true, &setup, 1));
}
int16_t LR11x0::setTcxoMode(uint8_t tune, uint32_t delay) {
@ -2751,7 +2772,7 @@ int16_t LR11x0::setModulationParamsLoRa(uint8_t sf, uint8_t bw, uint8_t cr, uint
// calculate symbol length and enable low data rate optimization, if auto-configuration is enabled
if(this->ldroAuto) {
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
if(symbolLength >= 16.0) {
if(symbolLength >= 16.0f) {
this->ldrOptimize = RADIOLIB_LR11X0_LORA_LDRO_ENABLED;
} else {
this->ldrOptimize = RADIOLIB_LR11X0_LORA_LDRO_DISABLED;
@ -2950,7 +2971,7 @@ int16_t LR11x0::setLoRaSyncWord(uint8_t sync) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_LORA_SYNC_WORD, true, buff, sizeof(buff)));
}
int16_t LR11x0::lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, uint8_t* payload, size_t len) {
int16_t LR11x0::lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, const uint8_t* payload, size_t len) {
// check maximum size
const uint8_t maxLen[4][4] = {
{ 189, 178, 167, 155, },
@ -2997,7 +3018,7 @@ int16_t LR11x0::lrFhssSetSyncWord(uint32_t sync) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_LR_FHSS_SET_SYNC_WORD, true, buff, sizeof(buff)));
}
int16_t LR11x0::configBleBeacon(uint8_t chan, uint8_t* payload, size_t len) {
int16_t LR11x0::configBleBeacon(uint8_t chan, const uint8_t* payload, size_t len) {
return(this->bleBeaconCommon(RADIOLIB_LR11X0_CMD_CONFIG_BLE_BEACON, chan, payload, len));
}
@ -3011,11 +3032,11 @@ int16_t LR11x0::getLoRaRxHeaderInfos(uint8_t* info) {
return(state);
}
int16_t LR11x0::bleBeaconSend(uint8_t chan, uint8_t* payload, size_t len) {
int16_t LR11x0::bleBeaconSend(uint8_t chan, const uint8_t* payload, size_t len) {
return(this->bleBeaconCommon(RADIOLIB_LR11X0_CMD_BLE_BEACON_SEND, chan, payload, len));
}
int16_t LR11x0::bleBeaconCommon(uint16_t cmd, uint8_t chan, uint8_t* payload, size_t len) {
int16_t LR11x0::bleBeaconCommon(uint16_t cmd, uint8_t chan, const uint8_t* payload, size_t len) {
// check maximum size
// TODO what is the actual maximum?
if(len > RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN) {
@ -3233,8 +3254,8 @@ int16_t LR11x0::gnssAssisted(uint32_t gpsTime, uint8_t effort, uint8_t resMask,
}
int16_t LR11x0::gnssSetAssistancePosition(float lat, float lon) {
uint16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
uint16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
int16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
int16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
uint8_t buff[4] = {
(uint8_t)((latRaw >> 8) & 0xFF), (uint8_t)(latRaw & 0xFF),
(uint8_t)((lonRaw >> 8) & 0xFF), (uint8_t)(lonRaw & 0xFF),
@ -3248,11 +3269,11 @@ int16_t LR11x0::gnssReadAssistancePosition(float* lat, float* lon) {
// pass the replies
if(lat) {
uint16_t latRaw = ((uint16_t)(buff[0]) << 8) | (uint16_t)(buff[1]);
int16_t latRaw = ((int16_t)(buff[0]) << 8) | (int16_t)(buff[1]);
*lat = ((float)latRaw*90.0f)/2048.0f;
}
if(lon) {
uint16_t lonRaw = ((uint16_t)(buff[2]) << 8) | (uint16_t)(buff[3]);
int16_t lonRaw = ((int16_t)(buff[2]) << 8) | (int16_t)(buff[3]);
*lon = ((float)lonRaw*180.0f)/2048.0f;
}
@ -3358,7 +3379,7 @@ int16_t LR11x0::gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac) {
int16_t LR11x0::gnssAlmanacFullUpdateSV(uint8_t svn, const uint8_t* svnAlmanac) {
uint8_t buff[RADIOLIB_LR11X0_GNSS_ALMANAC_BLOCK_SIZE] = { svn };
memcpy(&buff[1], svnAlmanac, RADIOLIB_LR11X0_GNSS_ALMANAC_BLOCK_SIZE - 1);
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE, true, buff, sizeof(buff)));
@ -3382,8 +3403,8 @@ int16_t LR11x0::gnssAlmanacReadSV(uint8_t svId, uint8_t* almanac) {
}
int16_t LR11x0::gnssGetNbSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv) {
uint16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
uint16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
int16_t latRaw = (lat*2048.0f)/90.0f + 0.5f;
int16_t lonRaw = (lon*2048.0f)/180.0f + 0.5f;
uint8_t reqBuff[9] = {
(uint8_t)((time >> 24) & 0xFF), (uint8_t)((time >> 16) & 0xFF),
(uint8_t)((time >> 8) & 0xFF), (uint8_t)(time & 0xFF),
@ -3520,21 +3541,21 @@ int16_t LR11x0::gnssReadDopplerSolverRes(uint8_t* error, uint8_t* nbSvUsed, floa
if(error) { *error = buff[0]; }
if(nbSvUsed) { *nbSvUsed = buff[1]; }
if(lat) {
uint16_t latRaw = ((uint16_t)(buff[2]) << 8) | (uint16_t)buff[3];
int16_t latRaw = ((int16_t)(buff[2]) << 8) | (int16_t)buff[3];
*lat = ((float)latRaw * 90.0f)/2048.0f;
}
if(lon) {
uint16_t lonRaw = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5];
int16_t lonRaw = ((int16_t)(buff[4]) << 8) | (int16_t)buff[5];
*lon = ((float)lonRaw * 180.0f)/2048.0f;
}
if(accuracy) { *accuracy = ((uint16_t)(buff[6]) << 8) | (uint16_t)buff[7]; }
if(xtal) { *xtal = ((uint16_t)(buff[8]) << 8) | (uint16_t)buff[9]; }
if(latFilt) {
uint16_t latRaw = ((uint16_t)(buff[10]) << 8) | (uint16_t)buff[11];
int16_t latRaw = ((int16_t)(buff[10]) << 8) | (int16_t)buff[11];
*latFilt = ((float)latRaw * 90.0f)/2048.0f;
}
if(lonFilt) {
uint16_t lonRaw = ((uint16_t)(buff[12]) << 8) | (uint16_t)buff[13];
int16_t lonRaw = ((int16_t)(buff[12]) << 8) | (int16_t)buff[13];
*lonFilt = ((float)lonRaw * 180.0f)/2048.0f;
}
if(accuracyFilt) { *accuracyFilt = ((uint16_t)(buff[14]) << 8) | (uint16_t)buff[15]; }
@ -3632,7 +3653,7 @@ void LR11x0::gnssAbort() {
// send the abort signal (single NOP)
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
// we need to call the most basic overload of the SPI write method otherwise the call will be ambiguous
uint8_t cmd[2] = { 0, 0 };
const uint8_t cmd[2] = { 0, 0 };
this->mod->SPIwriteStream(cmd, 2, NULL, 0, false, false);
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_16;
@ -3640,7 +3661,7 @@ void LR11x0::gnssAbort() {
this->mod->hal->delay(3000);
}
int16_t LR11x0::cryptoSetKey(uint8_t keyId, uint8_t* key) {
int16_t LR11x0::cryptoSetKey(uint8_t keyId, const uint8_t* key) {
RADIOLIB_ASSERT_PTR(key);
uint8_t buff[1 + RADIOLIB_AES128_KEY_SIZE] = { 0 };
buff[0] = keyId;
@ -3648,7 +3669,7 @@ int16_t LR11x0::cryptoSetKey(uint8_t keyId, uint8_t* key) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CRYPTO_SET_KEY, false, buff, sizeof(buff)));
}
int16_t LR11x0::cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, uint8_t* key) {
int16_t LR11x0::cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, const uint8_t* key) {
RADIOLIB_ASSERT_PTR(key);
uint8_t buff[2 + RADIOLIB_AES128_KEY_SIZE] = { 0 };
buff[0] = srcKeyId;
@ -3657,7 +3678,7 @@ int16_t LR11x0::cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, uint8_t* key
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CRYPTO_DERIVE_KEY, false, buff, sizeof(buff)));
}
int16_t LR11x0::cryptoProcessJoinAccept(uint8_t decKeyId, uint8_t verKeyId, uint8_t lwVer, uint8_t* header, uint8_t* dataIn, size_t len, uint8_t* dataOut) {
int16_t LR11x0::cryptoProcessJoinAccept(uint8_t decKeyId, uint8_t verKeyId, uint8_t lwVer, const uint8_t* header, const uint8_t* dataIn, size_t len, uint8_t* dataOut) {
// calculate buffer sizes
size_t headerLen = 1;
if(lwVer) {
@ -3710,7 +3731,7 @@ int16_t LR11x0::cryptoProcessJoinAccept(uint8_t decKeyId, uint8_t verKeyId, uint
return(state);
}
int16_t LR11x0::cryptoComputeAesCmac(uint8_t keyId, uint8_t* data, size_t len, uint32_t* mic) {
int16_t LR11x0::cryptoComputeAesCmac(uint8_t keyId, const uint8_t* data, size_t len, uint32_t* mic) {
size_t reqLen = sizeof(uint8_t) + len;
#if RADIOLIB_STATIC_ONLY
uint8_t reqBuff[sizeof(uint8_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
@ -3737,7 +3758,7 @@ int16_t LR11x0::cryptoComputeAesCmac(uint8_t keyId, uint8_t* data, size_t len, u
return(state);
}
int16_t LR11x0::cryptoVerifyAesCmac(uint8_t keyId, uint32_t micExp, uint8_t* data, size_t len, bool* result) {
int16_t LR11x0::cryptoVerifyAesCmac(uint8_t keyId, uint32_t micExp, const uint8_t* data, size_t len, bool* result) {
size_t reqLen = sizeof(uint8_t) + sizeof(uint32_t) + len;
#if RADIOLIB_STATIC_ONLY
uint8_t reqBuff[sizeof(uint8_t) + sizeof(uint32_t) + RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];
@ -3768,15 +3789,15 @@ int16_t LR11x0::cryptoVerifyAesCmac(uint8_t keyId, uint32_t micExp, uint8_t* dat
return(state);
}
int16_t LR11x0::cryptoAesEncrypt01(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut) {
int16_t LR11x0::cryptoAesEncrypt01(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut) {
return(this->cryptoCommon(RADIOLIB_LR11X0_CMD_CRYPTO_AES_ENCRYPT_01, keyId, dataIn, len, dataOut));
}
int16_t LR11x0::cryptoAesEncrypt(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut) {
int16_t LR11x0::cryptoAesEncrypt(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut) {
return(this->cryptoCommon(RADIOLIB_LR11X0_CMD_CRYPTO_AES_ENCRYPT, keyId, dataIn, len, dataOut));
}
int16_t LR11x0::cryptoAesDecrypt(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut) {
int16_t LR11x0::cryptoAesDecrypt(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut) {
return(this->cryptoCommon(RADIOLIB_LR11X0_CMD_CRYPTO_AES_DECRYPT, keyId, dataIn, len, dataOut));
}
@ -3806,7 +3827,7 @@ int16_t LR11x0::cryptoGetParam(uint8_t id, uint32_t* value) {
return(state);
}
int16_t LR11x0::cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile) {
int16_t LR11x0::cryptoCheckEncryptedFirmwareImage(uint32_t offset, const uint32_t* data, size_t len, bool nonvolatile) {
// check maximum size
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
@ -3833,7 +3854,7 @@ int16_t LR11x0::bootEraseFlash(void) {
return(state);
}
int16_t LR11x0::bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile) {
int16_t LR11x0::bootWriteFlashEncrypted(uint32_t offset, const uint32_t* data, size_t len, bool nonvolatile) {
// check maximum size
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
@ -3881,7 +3902,8 @@ int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* d
for(size_t i = 0; i < len; i++) {
uint32_t bin = 0;
if(nonvolatile) {
bin = RADIOLIB_NONVOLATILE_READ_DWORD(data + i);
uint32_t* ptr = const_cast<uint32_t*>(data) + i;
bin = RADIOLIB_NONVOLATILE_READ_DWORD(ptr);
} else {
bin = data[i];
}
@ -3898,7 +3920,7 @@ int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* d
return(state);
}
int16_t LR11x0::cryptoCommon(uint16_t cmd, uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut) {
int16_t LR11x0::cryptoCommon(uint16_t cmd, uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut) {
// build buffers
#if RADIOLIB_STATIC_ONLY
uint8_t reqBuff[RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN];

View file

@ -33,7 +33,7 @@
#define RADIOLIB_LR11X0_CMD_SET_DIO_AS_RF_SWITCH (0x0112)
#define RADIOLIB_LR11X0_CMD_SET_DIO_IRQ_PARAMS (0x0113)
#define RADIOLIB_LR11X0_CMD_CLEAR_IRQ (0x0114)
#define RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK (0x0116)
#define RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK (0x0116)
#define RADIOLIB_LR11X0_CMD_SET_TCXO_MODE (0x0117)
#define RADIOLIB_LR11X0_CMD_REBOOT (0x0118)
#define RADIOLIB_LR11X0_CMD_GET_VBAT (0x0119)
@ -233,7 +233,7 @@
#define RADIOLIB_LR11X0_CALIBRATE_HF_RC (0x01UL << 1) // 1 1 high frequency RC
#define RADIOLIB_LR11X0_CALIBRATE_LF_RC (0x01UL << 0) // 0 0 low frequency RC
#define RADIOLIB_LR11X0_CALIBRATE_ALL (0x3FUL << 0) // 5 0 everything
#define RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ (20.0)
#define RADIOLIB_LR11X0_CAL_IMG_FREQ_TRIG_MHZ (20.0f)
// RADIOLIB_LR11X0_CMD_SET_REG_MODE
#define RADIOLIB_LR11X0_REG_MODE_LDO (0x00UL << 0) // 0 0 regulator mode: LDO in all modes
@ -281,7 +281,7 @@
#define RADIOLIB_LR11X0_IRQ_ALL (0x1BF80FFCUL) // 31 0 all interrupts
#define RADIOLIB_LR11X0_IRQ_NONE (0x00UL << 0) // 31 0 no interrupts
// RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK
// RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK
#define RADIOLIB_LR11X0_LF_CLK_RC (0x00UL << 0) // 1 0 32.768 kHz source: RC oscillator
#define RADIOLIB_LR11X0_LF_CLK_XOSC (0x01UL << 0) // 1 0 crystal oscillator
#define RADIOLIB_LR11X0_LF_CLK_EXT (0x02UL << 0) // 1 0 external signal on DIO11
@ -409,7 +409,7 @@
#define RADIOLIB_LR11X0_GFSK_RX_BW_312_0 (0x19UL << 0) // 7 0 312.0 kHz
#define RADIOLIB_LR11X0_GFSK_RX_BW_373_6 (0x11UL << 0) // 7 0 373.6 kHz
#define RADIOLIB_LR11X0_GFSK_RX_BW_467_0 (0x09UL << 0) // 7 0 467.0 kHz
#define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE (488.28215) // 31 0 LR FHSS bit rate: 488.28215 bps
#define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE (488.28215f) // 31 0 LR FHSS bit rate: 488.28215 bps
#define RADIOLIB_LR11X0_LR_FHSS_BIT_RATE_RAW (0x8001E848UL) // 31 0 488.28215 bps in raw
#define RADIOLIB_LR11X0_LR_FHSS_SHAPING_GAUSSIAN_BT_1_0 (0x0BUL << 0) // 7 0 shaping filter: Gaussian, BT = 1.0
#define RADIOLIB_LR11X0_SIGFOX_SHAPING_GAUSSIAN_BT_0_7 (0x16UL << 0) // 7 0 shaping filter: Gaussian, BT = 0.7
@ -877,6 +877,7 @@ class LR11x0: public PhysicalLayer {
using PhysicalLayer::transmit;
using PhysicalLayer::receive;
using PhysicalLayer::startTransmit;
using PhysicalLayer::startReceive;
using PhysicalLayer::readData;
/*!
@ -1073,16 +1074,6 @@ class LR11x0: public PhysicalLayer {
*/
void clearPacketSentAction() override;
/*!
\brief Interrupt-driven binary transmit method.
Overloads for string-based transmissions are implemented in PhysicalLayer.
\param data Binary data to be sent.
\param len Number of bytes to send.
\param addr Address to send the data to. Will only be added if address filtering was enabled.
\returns \ref status_codes
*/
int16_t startTransmit(const uint8_t* data, size_t len, uint8_t addr = 0) override;
/*!
\brief Clean up after transmission is done.
\returns \ref status_codes
@ -1097,20 +1088,6 @@ class LR11x0: public PhysicalLayer {
*/
int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. IRQ1 will be activated when full packet is received.
\param timeout Raw timeout value, expressed as multiples of 1/32.768 kHz (approximately 30.52 us).
Defaults to RADIOLIB_LR11X0_RX_TIMEOUT_INF for infinite timeout (Rx continuous mode),
set to RADIOLIB_LR11X0_RX_TIMEOUT_NONE for no timeout (Rx single mode).
If timeout other than infinite is set, signal will be generated on IRQ1.
\param irqFlags Sets the IRQ flags that will trigger IRQ1, defaults to RADIOLIB_LR11X0_IRQ_RX_DONE.
\param irqMask Only for PhysicalLayer compatibility, not used.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, uint32_t irqFlags = RADIOLIB_LR11X0_IRQ_RX_DONE, uint32_t irqMask = 0, size_t len = 0);
/*!
\brief Reads the current IRQ status.
\returns IRQ status bits
@ -1176,11 +1153,11 @@ class LR11x0: public PhysicalLayer {
int16_t setCodingRate(uint8_t cr, bool longInterleave = false);
/*!
\brief Sets LoRa or LR-FHSS sync word.
\param syncWord LoRa or LR-FHSS sync word to be set. For LoRa, only 8 least significant bits will be used
\brief Sets LoRa sync word.
\param syncWord LoRa sync word to be set.
\returns \ref status_codes
*/
int16_t setSyncWord(uint32_t syncWord);
int16_t setSyncWord(uint8_t syncWord);
/*!
\brief Sets GFSK bit rate. Allowed values range from 0.6 to 300.0 kbps.
@ -1622,15 +1599,21 @@ class LR11x0: public PhysicalLayer {
*/
int16_t calibrateImageRejection(float freqMin, float freqMax);
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected:
#endif
Module* getMod() override;
// LR11x0 SPI command implementations
int16_t writeRegMem32(uint32_t addr, uint32_t* data, size_t len);
int16_t writeRegMem32(uint32_t addr, const uint32_t* data, size_t len);
int16_t readRegMem32(uint32_t addr, uint32_t* data, size_t len);
int16_t writeBuffer8(uint8_t* data, size_t len);
int16_t writeBuffer8(const uint8_t* data, size_t len);
int16_t readBuffer8(uint8_t* data, size_t len, size_t offset);
int16_t clearRxBuffer(void);
int16_t writeRegMemMask32(uint32_t addr, uint32_t mask, uint32_t data);
@ -1644,7 +1627,7 @@ class LR11x0: public PhysicalLayer {
int16_t setDioAsRfSwitch(uint8_t en, uint8_t stbyCfg, uint8_t rxCfg, uint8_t txCfg, uint8_t txHpCfg, uint8_t txHfCfg, uint8_t gnssCfg, uint8_t wifiCfg);
int16_t setDioIrqParams(uint32_t irq1, uint32_t irq2);
int16_t setDioIrqParams(uint32_t irq);
int16_t clearIrq(uint32_t irq);
int16_t clearIrqState(uint32_t irq);
int16_t configLfClock(uint8_t setup);
int16_t setTcxoMode(uint8_t tune, uint32_t delay);
int16_t reboot(bool stay);
@ -1702,11 +1685,11 @@ class LR11x0: public PhysicalLayer {
int16_t setRangingParameter(uint8_t symbolNum);
int16_t setRssiCalibration(const int8_t* tune, int16_t gainOffset);
int16_t setLoRaSyncWord(uint8_t sync);
int16_t lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, uint8_t* payload, size_t len);
int16_t lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, const uint8_t* payload, size_t len);
int16_t lrFhssSetSyncWord(uint32_t sync);
int16_t configBleBeacon(uint8_t chan, uint8_t* payload, size_t len);
int16_t configBleBeacon(uint8_t chan, const uint8_t* payload, size_t len);
int16_t getLoRaRxHeaderInfos(uint8_t* info);
int16_t bleBeaconSend(uint8_t chan, uint8_t* payload, size_t len);
int16_t bleBeaconSend(uint8_t chan, const uint8_t* payload, size_t len);
int16_t wifiScan(uint8_t type, uint16_t mask, uint8_t acqMode, uint8_t nbMaxRes, uint8_t nbScanPerChan, uint16_t timeout, uint8_t abortOnTimeout);
int16_t wifiScanTimeLimit(uint8_t type, uint16_t mask, uint8_t acqMode, uint8_t nbMaxRes, uint16_t timePerChan, uint16_t timeout);
@ -1744,7 +1727,7 @@ class LR11x0: public PhysicalLayer {
int16_t gnssGetResultSize(uint16_t* size);
int16_t gnssReadResults(uint8_t* result, uint16_t size);
int16_t gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc);
int16_t gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac);
int16_t gnssAlmanacFullUpdateSV(uint8_t svn, const uint8_t* svnAlmanac);
int16_t gnssAlmanacReadAddrSize(uint32_t* addr, uint16_t* size);
int16_t gnssAlmanacReadSV(uint8_t svId, uint8_t* almanac);
int16_t gnssGetNbSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv);
@ -1773,29 +1756,29 @@ class LR11x0: public PhysicalLayer {
int16_t gnssWriteBitMaskSatActivated(uint8_t bitMask, uint32_t* bitMaskActivated0, uint32_t* bitMaskActivated1);
void gnssAbort();
int16_t cryptoSetKey(uint8_t keyId, uint8_t* key);
int16_t cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, uint8_t* key);
int16_t cryptoProcessJoinAccept(uint8_t decKeyId, uint8_t verKeyId, uint8_t lwVer, uint8_t* header, uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoComputeAesCmac(uint8_t keyId, uint8_t* data, size_t len, uint32_t* mic);
int16_t cryptoVerifyAesCmac(uint8_t keyId, uint32_t micExp, uint8_t* data, size_t len, bool* result);
int16_t cryptoAesEncrypt01(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoAesEncrypt(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoAesDecrypt(uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoSetKey(uint8_t keyId, const uint8_t* key);
int16_t cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, const uint8_t* key);
int16_t cryptoProcessJoinAccept(uint8_t decKeyId, uint8_t verKeyId, uint8_t lwVer, const uint8_t* header, const uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoComputeAesCmac(uint8_t keyId, const uint8_t* data, size_t len, uint32_t* mic);
int16_t cryptoVerifyAesCmac(uint8_t keyId, uint32_t micExp, const uint8_t* data, size_t len, bool* result);
int16_t cryptoAesEncrypt01(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoAesEncrypt(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoAesDecrypt(uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoStoreToFlash(void);
int16_t cryptoRestoreFromFlash(void);
int16_t cryptoSetParam(uint8_t id, uint32_t value);
int16_t cryptoGetParam(uint8_t id, uint32_t* value);
int16_t cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile);
int16_t cryptoCheckEncryptedFirmwareImage(uint32_t offset, const uint32_t* data, size_t len, bool nonvolatile);
int16_t cryptoCheckEncryptedFirmwareImageResult(bool* result);
int16_t bootEraseFlash(void);
int16_t bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile);
int16_t bootWriteFlashEncrypted(uint32_t offset, const uint32_t* data, size_t len, bool nonvolatile);
int16_t bootReboot(bool stay);
int16_t bootGetPin(uint8_t* pin);
int16_t bootGetChipEui(uint8_t* eui);
int16_t bootGetJoinEui(uint8_t* eui);
int16_t SPIcommand(uint16_t cmd, bool write, uint8_t* data, size_t len, uint8_t* out = NULL, size_t outLen = 0);
int16_t SPIcommand(uint16_t cmd, bool write, uint8_t* data, size_t len, const uint8_t* out = NULL, size_t outLen = 0);
#if !RADIOLIB_GODMODE
protected:
@ -1828,6 +1811,8 @@ class LR11x0: public PhysicalLayer {
float dataRateMeasured = 0;
uint8_t wifiScanMode = 0;
bool gnss = false;
uint32_t rxTimeout = 0;
int16_t modSetup(float tcxoVoltage, uint8_t modem);
static int16_t SPIparseStatus(uint8_t in);
@ -1839,9 +1824,9 @@ class LR11x0: public PhysicalLayer {
int16_t setHeaderType(uint8_t hdrType, size_t len = 0xFF);
// common methods to avoid some copy-paste
int16_t bleBeaconCommon(uint16_t cmd, uint8_t chan, uint8_t* payload, size_t len);
int16_t bleBeaconCommon(uint16_t cmd, uint8_t chan, const uint8_t* payload, size_t len);
int16_t writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len, bool nonvolatile);
int16_t cryptoCommon(uint16_t cmd, uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut);
int16_t cryptoCommon(uint16_t cmd, uint8_t keyId, const uint8_t* dataIn, size_t len, uint8_t* dataOut);
};
#endif

View file

@ -2,7 +2,9 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_RF69
RF69::RF69(Module* module) : PhysicalLayer(RADIOLIB_RF69_FREQUENCY_STEP_SIZE, RADIOLIB_RF69_MAX_PACKET_LENGTH) {
RF69::RF69(Module* module) : PhysicalLayer() {
this->freqStep = RADIOLIB_RF69_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_RF69_MAX_PACKET_LENGTH;
this->mod = module;
}
@ -122,7 +124,7 @@ int16_t RF69::transmit(const uint8_t* data, size_t len, uint8_t addr) {
int16_t RF69::receive(uint8_t* data, size_t len) {
// calculate timeout (500 ms + 400 full 64-byte packets at current bit rate)
RadioLibTime_t timeout = 500 + (1.0/(this->bitRate))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0);
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0f);
// start reception
int16_t state = startReceive();
@ -219,7 +221,7 @@ int16_t RF69::packetMode() {
return(this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_DATA_MODUL, RADIOLIB_RF69_PACKET_MODE, 6, 5));
}
void RF69::setAESKey(uint8_t* key) {
void RF69::setAESKey(const uint8_t* key) {
this->mod->SPIwriteRegisterBurst(RADIOLIB_RF69_REG_AES_KEY_1, key, 16);
}
@ -321,6 +323,10 @@ void RF69::clearFifoEmptyAction() {
clearDio1Action();
}
void RF69::setFifoThreshold(uint8_t threshold) {
this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_FIFO_THRESH, threshold, 6, 0);
}
void RF69::setFifoFullAction(void (*func)(void)) {
// set the interrupt
this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_FIFO_THRESH, RADIOLIB_RF69_FIFO_THRESH, 6, 0);
@ -360,7 +366,7 @@ bool RF69::fifoAdd(uint8_t* data, int totalLen, int* remLen) {
bool RF69::fifoGet(volatile uint8_t* data, int totalLen, volatile int* rcvLen) {
// get pointer to the correct position in data buffer
uint8_t* dataPtr = (uint8_t*)&data[*rcvLen];
uint8_t* dataPtr = const_cast<uint8_t*>(&data[*rcvLen]);
// check how much data are we still expecting
uint8_t len = RADIOLIB_RF69_FIFO_THRESH - 1;
@ -519,9 +525,9 @@ int16_t RF69::setOokPeakThresholdDecrement(uint8_t value) {
int16_t RF69::setFrequency(float freq) {
// check allowed frequency range
if(!(((freq > 290.0) && (freq < 340.0)) ||
((freq > 431.0) && (freq < 510.0)) ||
((freq > 862.0) && (freq < 1020.0)))) {
if(!(((freq > 290.0f) && (freq < 340.0f)) ||
((freq > 431.0f) && (freq < 510.0f)) ||
((freq > 862.0f) && (freq < 1020.0f)))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY);
}
@ -555,7 +561,7 @@ int16_t RF69::getFrequency(float *freq) {
int16_t RF69::setBitRate(float br) {
// datasheet says 1.2 kbps should be the smallest possible, but 0.512 works fine
RADIOLIB_CHECK_RANGE(br, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(br, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
// check bitrate-bandwidth ratio
if(!(br < 2000 * this->rxBandwidth)) {
@ -588,8 +594,8 @@ int16_t RF69::setRxBandwidth(float rxBw) {
// calculate exponent and mantissa values for receiver bandwidth
for(int8_t e = 7; e >= 0; e--) {
for(int8_t m = 2; m >= 0; m--) {
float point = (RADIOLIB_RF69_CRYSTAL_FREQ * 1000000.0)/(((4 * m) + 16) * ((uint32_t)1 << (e + (this->ookEnabled ? 3 : 2))));
if(fabsf(rxBw - (point / 1000.0)) <= 0.1) {
float point = (RADIOLIB_RF69_CRYSTAL_FREQ * 1000000.0f)/(((4 * m) + 16) * ((uint32_t)1 << (e + (this->ookEnabled ? 3 : 2))));
if(fabsf(rxBw - (point / 1000.0f)) <= 0.1f) {
// set Rx bandwidth
state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_RX_BW, (m << 3) | e, 4, 0);
if(state == RADIOLIB_ERR_NONE) {
@ -606,8 +612,8 @@ int16_t RF69::setRxBandwidth(float rxBw) {
int16_t RF69::setFrequencyDeviation(float freqDev) {
// set frequency deviation to lowest available setting (required for digimodes)
float newFreqDev = freqDev;
if(freqDev < 0.0) {
newFreqDev = 0.6;
if(freqDev < 0.0f) {
newFreqDev = 0.6f;
}
// check frequency deviation range
@ -644,7 +650,7 @@ int16_t RF69::getFrequencyDeviation(float *freqDev) {
// calculate frequency deviation from raw value obtained from register
// Fdev = Fstep * Fdev(13:0) (pag. 20 of datasheet)
*freqDev = (1000.0 * fdev * RADIOLIB_RF69_CRYSTAL_FREQ) /
*freqDev = (1000.0f * fdev * RADIOLIB_RF69_CRYSTAL_FREQ) /
(uint32_t(1) << RADIOLIB_RF69_DIV_EXPONENT);
return(RADIOLIB_ERR_NONE);
@ -688,9 +694,9 @@ int16_t RF69::setOutputPower(int8_t pwr, bool highPower) {
return(state);
}
int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
int16_t RF69::setSyncWord(const uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
// check constraints
if((maxErrBits > 7) || (len > 8)) {
if((maxErrBits > 7) || (len == 0) || (len > 8)) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
@ -701,16 +707,15 @@ int16_t RF69::setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits) {
}
}
// enable filtering
int16_t state = enableSyncWordFiltering(maxErrBits);
RADIOLIB_ASSERT(state);
// set the length
state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_SYNC_CONFIG, (len-1)<<3, 5, 3);
// set sync word register
this->mod->SPIwriteRegisterBurst(RADIOLIB_RF69_REG_SYNC_VALUE_1, syncWord, len);
if(state == RADIOLIB_ERR_NONE) {
this->syncWordLength = len;
}
return(state);
}
@ -801,7 +806,11 @@ int16_t RF69::variablePacketLengthMode(uint8_t maxLen) {
int16_t RF69::enableSyncWordFiltering(uint8_t maxErrBits) {
// enable sync word recognition
return(this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_SYNC_CONFIG, RADIOLIB_RF69_SYNC_ON | RADIOLIB_RF69_FIFO_FILL_CONDITION_SYNC | (this->syncWordLength - 1) << 3 | maxErrBits, 7, 0));
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_SYNC_CONFIG, RADIOLIB_RF69_SYNC_ON | RADIOLIB_RF69_FIFO_FILL_CONDITION_SYNC, 7, 6);
RADIOLIB_ASSERT(state);
// set maximum error bits
return(this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_SYNC_CONFIG, maxErrBits, 2, 0));
}
int16_t RF69::disableSyncWordFiltering() {
@ -924,9 +933,9 @@ float RF69::getRSSI() {
}
int16_t RF69::setRSSIThreshold(float dbm) {
RADIOLIB_CHECK_RANGE(dbm, -127.5, 0, RADIOLIB_ERR_INVALID_RSSI_THRESHOLD);
RADIOLIB_CHECK_RANGE(dbm, -127.5f, 0.0f, RADIOLIB_ERR_INVALID_RSSI_THRESHOLD);
return this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_RSSI_THRESH, (uint8_t)(-2.0 * dbm), 7, 0);
return this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_RSSI_THRESH, (uint8_t)(-2.0f * dbm), 7, 0);
}
void RF69::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {

View file

@ -12,7 +12,7 @@
// RF69 physical layer properties
#define RADIOLIB_RF69_FREQUENCY_STEP_SIZE 61.03515625
#define RADIOLIB_RF69_MAX_PACKET_LENGTH 64
#define RADIOLIB_RF69_CRYSTAL_FREQ 32.0
#define RADIOLIB_RF69_CRYSTAL_FREQ 32.0f
#define RADIOLIB_RF69_DIV_EXPONENT 19
// RF69 register map
@ -577,7 +577,7 @@ class RF69: public PhysicalLayer {
\brief Sets AES key.
\param key Key to be used for AES encryption. Must be exactly 16 bytes long.
*/
void setAESKey(uint8_t* key);
void setAESKey(const uint8_t* key);
/*!
\brief Enables AES encryption.
@ -648,6 +648,14 @@ class RF69: public PhysicalLayer {
*/
void clearFifoEmptyAction();
/*!
\brief Set FIFO threshold level.
Be aware that threshold is also set in setFifoFullAction method.
setFifoThreshold method must be called AFTER calling setFifoFullAction!
\param threshold Threshold level in bytes.
*/
void setFifoThreshold(uint8_t threshold);
/*!
\brief Set interrupt service routine function to call when FIFO is full.
\param func Pointer to interrupt service routine.
@ -781,7 +789,7 @@ class RF69: public PhysicalLayer {
\param len Sync word length in bytes.
\param maxErrBits Maximum allowed number of bit errors in received sync word. Defaults to 0.
*/
int16_t setSyncWord(uint8_t* syncWord, size_t len, uint8_t maxErrBits = 0);
int16_t setSyncWord(const uint8_t* syncWord, size_t len, uint8_t maxErrBits = 0);
/*!
\brief Sets preamble length.
@ -1023,8 +1031,6 @@ class RF69: public PhysicalLayer {
bool promiscuous = false;
uint8_t syncWordLength = RADIOLIB_RF69_DEFAULT_SW_LEN;
bool bitSync = true;
int16_t directMode();

View file

@ -17,7 +17,10 @@ int16_t SX1231::begin(float freq, float br, float freqDev, float rxBw, int8_t po
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_SX123X_CHIP_REVISION_2_A) || (version == RADIOLIB_SX123X_CHIP_REVISION_2_B) || (version == RADIOLIB_SX123X_CHIP_REVISION_2_C)) {
if((version == RADIOLIB_SX123X_CHIP_REVISION_2_A) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_B) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_C) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_D)) {
flagFound = true;
this->chipRevision = version;
} else {

View file

@ -11,6 +11,7 @@
#define RADIOLIB_SX123X_CHIP_REVISION_2_A 0x21
#define RADIOLIB_SX123X_CHIP_REVISION_2_B 0x22
#define RADIOLIB_SX123X_CHIP_REVISION_2_C 0x23
#define RADIOLIB_SX123X_CHIP_REVISION_2_D 0x24
// RADIOLIB_SX1231 specific register map
#define RADIOLIB_SX1231_REG_TEST_OOK 0x6E
@ -108,7 +109,7 @@ class SX1231: public RF69 {
\param preambleLen Preamble Length in bits. Defaults to 16 bits.
\returns \ref status_codes
*/
int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16);
virtual int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16);
#if !RADIOLIB_GODMODE
protected:

View file

@ -18,7 +18,10 @@ int16_t SX1233::begin(float freq, float br, float freqDev, float rxBw, int8_t po
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_SX123X_CHIP_REVISION_2_A) || (version == RADIOLIB_SX123X_CHIP_REVISION_2_B) || (version == RADIOLIB_SX123X_CHIP_REVISION_2_C)) {
if((version == RADIOLIB_SX123X_CHIP_REVISION_2_A) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_B) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_C) ||
(version == RADIOLIB_SX123X_CHIP_REVISION_2_D)) {
flagFound = true;
this->chipRevision = version;
} else {
@ -93,11 +96,11 @@ int16_t SX1233::begin(float freq, float br, float freqDev, float rxBw, int8_t po
int16_t SX1233::setBitRate(float br) {
// check high bit-rate operation
uint8_t pllBandwidth = RADIOLIB_SX1233_PLL_BW_LOW_BIT_RATE;
if((fabsf(br - 500.0f) < 0.1) || (fabsf(br - 600.0f) < 0.1)) {
if((fabsf(br - 500.0f) < 0.1f) || (fabsf(br - 600.0f) < 0.1f)) {
pllBandwidth = RADIOLIB_SX1233_PLL_BW_HIGH_BIT_RATE;
} else {
// datasheet says 1.2 kbps should be the smallest possible, but 0.512 works fine
RADIOLIB_CHECK_RANGE(br, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(br, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
}

View file

@ -38,7 +38,7 @@ class SX1233: public SX1231 {
\param preambleLen Preamble Length in bits. Defaults to 16 bits.
\returns \ref status_codes
*/
int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16);
int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16) override;
/*!
\brief Sets bit rate. Allowed values range from 0.5 to 300.0 kbps.

View file

@ -45,7 +45,7 @@ int16_t STM32WLx::setOutputPower(int8_t power) {
RADIOLIB_ASSERT(state);
// check the user did not request power output that is not possible
Module* mod = this->getMod();
const Module* mod = this->getMod();
bool hp_supported = mod->findRfSwitchMode(MODE_TX_HP);
bool lp_supported = mod->findRfSwitchMode(MODE_TX_LP);
if((!lp_supported && (power < -9)) || (!hp_supported && (power > 14))) {

View file

@ -66,12 +66,12 @@ class STM32WLx : public SX1262 {
/*!
\copydoc SX1262::begin
*/
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false) override;
/*!
\copydoc SX1262::beginFSK
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6, bool useRegulatorLDO = false) override;
// configuration methods
@ -113,12 +113,12 @@ class STM32WLx : public SX1262 {
\brief Sets interrupt service routine to call when DIO1/2/3 activates.
\param func ISR to call.
*/
void setDio1Action(void (*func)(void));
void setDio1Action(void (*func)(void)) override;
/*!
\brief Clears interrupt service routine to call when DIO1/2/3 activates.
*/
void clearDio1Action();
void clearDio1Action() override;
/*!
\brief Sets interrupt service routine to call when a packet is received.

View file

@ -16,11 +16,19 @@ int16_t SX1261::setOutputPower(int8_t power) {
RADIOLIB_ASSERT(state);
// set PA config
state = SX126x::setPaConfig(0x04, RADIOLIB_SX126X_PA_CONFIG_SX1261, 0x00);
uint8_t paDutyCycle = 0x04;
int8_t txPwr = power;
if(power == 15) {
// for 15 dBm, increase the duty cycle and lowe the power to set
// SX1261/2 datasheet, DS.SX1261-2.W.APP Rev. 2.1 page 78
paDutyCycle = 0x06;
txPwr--;
}
state = SX126x::setPaConfig(paDutyCycle, RADIOLIB_SX126X_PA_CONFIG_SX1261, 0x00);
RADIOLIB_ASSERT(state);
// set output power with default 200us ramp
state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
state = SX126x::setTxParams(txPwr, RADIOLIB_SX126X_PA_RAMP_200U);
RADIOLIB_ASSERT(state);
// restore OCP configuration
@ -29,9 +37,9 @@ int16_t SX1261::setOutputPower(int8_t power) {
int16_t SX1261::checkOutputPower(int8_t power, int8_t* clipped) {
if(clipped) {
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(15, power));
}
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
RADIOLIB_CHECK_RANGE(power, -17, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
return(RADIOLIB_ERR_NONE);
}

View file

@ -28,7 +28,7 @@ class SX1261 : public SX1262 {
SX1261(Module* mod); // cppcheck-suppress noExplicitConstructor
/*!
\brief Sets output power. Allowed values are in range from -17 to 14 dBm.
\brief Sets output power. Allowed values are in range from -17 to 15 dBm.
\param power Output power to be set in dBm.
\returns \ref status_codes
*/

Some files were not shown because too many files have changed in this diff Show more