Compare commits

..

111 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
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
107 changed files with 2587 additions and 1630 deletions

View file

@ -83,12 +83,14 @@ 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 "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
@ -183,19 +185,20 @@ jobs:
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 }}
- name: Extract short commit hash
id: short-hash
run: echo "::set-output name=short_sha::$(git rev-parse --short HEAD)"
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@v3
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
@ -203,6 +206,7 @@ jobs:
metrics:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/master'
steps:
- name: Set up SSH
run: |
@ -221,7 +225,7 @@ jobs:
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
- name: Download size artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
path: aggregated-sizes
@ -289,6 +293,7 @@ jobs:
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
@ -320,6 +325,7 @@ jobs:
./build.sh
rpi-test:
if: false # self-hosted runner temporarily disabled
needs: rpi-build
runs-on: [self-hosted, ARM64]
steps:

View file

@ -10,7 +10,7 @@ on:
jobs:
unit-test:
name: Build and run unit test
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
@ -19,9 +19,30 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libboost-all-dev libfmt-dev
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

3
.gitignore vendored
View file

@ -11,9 +11,6 @@
# Jetbrain IDEs
.idea
# 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

@ -82,10 +82,11 @@ void setup() {
void loop() {
Serial.print(F("[CC1101] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to 64 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 64 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 64 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 64 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)
@ -73,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};
@ -119,11 +121,11 @@ void loop() {
Serial.print(F("[CC1101] Sending another packet ... "));
// you can transmit C-string or Arduino string up to
// 64 characters long
// 255 characters long
String str = "Hello World! #" + String(count++);
transmissionState = radio.startTransmit(str);
// you can also transmit byte array up to 64 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

@ -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);

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

@ -8,7 +8,7 @@ RadioLib LoRaWAN examples.
## LoRaWAN versions & regional parameters
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 CN500 band is implemented as specified in RP001 1.1 revision B, as the RP002 1.0.4 version is much too complex._
_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 1.1 session, supply all the required keys:
```cpp

View file

@ -1,96 +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);
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);
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

@ -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 +1,2 @@
build/
lcov*

View file

@ -18,12 +18,13 @@ add_executable(${PROJECT_NAME} ${TEST_SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC include)
# link RadioLib
target_link_libraries(${PROJECT_NAME} RadioLib fmt)
target_link_libraries(${PROJECT_NAME} RadioLib fmt gcov)
# set target properties and options
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra)
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)
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_PORT=stdout)
#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

@ -47,6 +47,9 @@ class TestHal : public RadioLibHal {
this->gpio[i].event = false;
this->gpio[i].func = PIN_UNASSIGNED;
}
// wipe history log
this->spiLogWipe();
}
void term() override {
@ -104,10 +107,18 @@ class TestHal : public RadioLibHal {
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 {
@ -159,6 +170,11 @@ class TestHal : public RadioLibHal {
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);
}
@ -168,10 +184,6 @@ class TestHal : public RadioLibHal {
void spiBeginTransaction() {
HAL_LOG("TestHal::spiBeginTransaction()");
// wipe history log
memset(this->spiLog, 0x00, TEST_HAL_SPI_LOG_LENGTH);
this->spiLogPtr = this->spiLog;
}
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
@ -184,7 +196,12 @@ class TestHal : public RadioLibHal {
// process the SPI byte
in[i] = this->radio->HandleSPI(out[i]);
// outpu debug
// 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]));
}
}
@ -199,15 +216,30 @@ class TestHal : public RadioLibHal {
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) {
return(memcmp(this->spiLog, in, 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

View file

@ -3,7 +3,8 @@
set -e
# build the test binary
mkdir -p build
rm -rf build
mkdir build
cd build
cmake -G "CodeBlocks - Unix Makefiles" ..
make -j4

View file

@ -48,8 +48,9 @@ BOOST_FIXTURE_TEST_SUITE(suite_Module, ModuleFixture)
// 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 == 0x3E);
BOOST_TEST(ret == maskedValue);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIgetRegValue(address, lsb, msb);
@ -60,6 +61,60 @@ BOOST_FIXTURE_TEST_SUITE(suite_Module, ModuleFixture)
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 ---");
@ -88,8 +143,9 @@ BOOST_FIXTURE_TEST_SUITE(suite_Module, ModuleFixture)
// 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 == 0x3E);
BOOST_TEST(ret == maskedValue);
// invalid mask tests (swapped MSB and LSB, out of range bit masks)
ret = mod->SPIgetRegValue(address, lsb, msb);
@ -100,4 +156,74 @@ BOOST_FIXTURE_TEST_SUITE(suite_Module, ModuleFixture)
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

@ -86,7 +86,7 @@ EU868 KEYWORD1
US915 KEYWORD1
EU433 KEYWORD1
AU915 KEYWORD1
CN500 KEYWORD1
CN470 KEYWORD1
AS923 KEYWORD1
AS923_2 KEYWORD1
AS923_3 KEYWORD1
@ -246,6 +246,7 @@ spectralScanAbort KEYWORD2
spectralScanGetStatus KEYWORD2
spectralScanGetResult KEYWORD2
setPaRampTime KEYWORD2
hopLRFHSS KEYWORD2
# nRF24
setIrqAction KEYWORD2
@ -342,6 +343,8 @@ setDataRate KEYWORD2
checkDataRate KEYWORD2
setModem KEYWORD2
getModem KEYWORD2
stageMode KEYWORD2
launchMode KEYWORD2
# LoRaWAN
getBufferNonces KEYWORD2
@ -376,6 +379,7 @@ getLastToA KEYWORD2
dutyCycleInterval KEYWORD2
timeUntilUplink KEYWORD2
getMaxPayloadLen KEYWORD2
setSleepFunction KEYWORD2
#######################################
# Constants (LITERAL1)

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"
@ -260,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)
@ -429,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
@ -465,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
@ -489,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.

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;
@ -142,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 {
@ -174,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
@ -216,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];
@ -227,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
@ -245,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);
@ -264,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--) {
@ -273,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);
@ -315,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);
@ -348,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
@ -355,6 +359,7 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
#endif
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
}
}
}
}
@ -382,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]);
}
@ -419,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");
@ -429,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

@ -298,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.
@ -315,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.
@ -344,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.
@ -355,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.
@ -367,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.).
@ -380,7 +380,7 @@ 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
// getCs is omitted on purpose, as it can interfere when accessing the SPI in a concurrent environment

View file

@ -22,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
*/

View file

@ -2,7 +2,9 @@
#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;
}
@ -58,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();
@ -116,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);
}
@ -230,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);
@ -254,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);
@ -354,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
@ -366,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);
@ -380,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);
@ -388,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);
@ -409,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);
@ -417,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));
}
@ -430,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
@ -465,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);
@ -494,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);
}
@ -513,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);
@ -558,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 {
@ -592,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);
}
@ -717,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);
@ -1001,7 +1065,7 @@ int16_t CC1101::beginCommon(float freq, float br, float freqDev, float rxBw, int
RADIOLIB_ASSERT(state);
// set default sync word
uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
const uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
state = setSyncWord(sw[0], sw[1], 0, false);
RADIOLIB_ASSERT(state);
@ -1064,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--) {
@ -1155,7 +1219,7 @@ 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);
}

View file

@ -8,8 +8,9 @@
// CC1101 physical layer properties
#define RADIOLIB_CC1101_FREQUENCY_STEP_SIZE 396.7285156
#define RADIOLIB_CC1101_MAX_PACKET_LENGTH 64
#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
@ -614,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.
@ -695,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.
@ -833,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.
@ -1003,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);

View file

@ -37,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));
}
@ -95,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);

View file

@ -39,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
/*!
@ -48,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;

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);
}
@ -146,4 +148,4 @@ int16_t LR1120::setModem(ModemType_t modem) {
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;
@ -219,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());
}
@ -238,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)
@ -246,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
@ -261,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);
@ -287,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);
}
@ -414,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());
@ -493,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 };
@ -580,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);
@ -626,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
@ -667,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;
@ -773,7 +668,7 @@ int16_t LR11x0::setSyncWord(uint8_t 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;
@ -785,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));
}
@ -800,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));
}
@ -824,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);
@ -1104,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);
@ -1158,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);
@ -1353,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
@ -1362,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);
@ -1419,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() {
@ -1594,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 };
@ -1765,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
@ -1811,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);
}
@ -1870,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);
}
@ -1982,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;
}
@ -2033,11 +1928,11 @@ 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::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
@ -2052,6 +1947,124 @@ int16_t LR11x0::getModem(ModemType_t* modem) {
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);
@ -2082,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);
}
@ -2114,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
@ -2175,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);
@ -2289,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);
@ -2334,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) {
@ -2457,7 +2470,7 @@ int16_t LR11x0::setDioIrqParams(uint32_t irq) {
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),
};
@ -2759,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;
@ -2958,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, },
@ -3005,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));
}
@ -3019,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) {
@ -3241,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),
@ -3256,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;
}
@ -3366,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)));
@ -3390,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),
@ -3528,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]; }
@ -3640,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;
@ -3648,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;
@ -3656,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;
@ -3665,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) {
@ -3718,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];
@ -3745,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];
@ -3776,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));
}
@ -3814,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);
@ -3841,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);
@ -3889,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];
}
@ -3906,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

@ -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
@ -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
@ -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:
@ -1829,6 +1812,7 @@ class LR11x0: public PhysicalLayer {
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);
@ -1840,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);
}
@ -364,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;
@ -523,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);
}
@ -559,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)) {
@ -592,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) {
@ -610,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
@ -648,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);
@ -692,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);
}
@ -705,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);
}
@ -805,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() {
@ -928,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.
@ -789,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.
@ -1031,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

@ -72,7 +72,7 @@ int16_t SX1262::setFrequency(float freq) {
}
int16_t SX1262::setFrequency(float freq, bool skipCalibration) {
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
if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) {

View file

@ -44,7 +44,7 @@ class SX1262: public SX126x {
\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 power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
virtual 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);
/*!
\brief Initialization method for FSK modem.
@ -60,7 +60,7 @@ class SX1262: public SX126x {
\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 = 1.6, bool useRegulatorLDO = false);
virtual 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);
/*!
\brief Initialization method for LR-FHSS modem. This modem only supports transmission!
@ -75,7 +75,7 @@ class SX1262: public SX126x {
\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 = 1.6, bool useRegulatorLDO = false);
virtual 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 = 1.6, bool useRegulatorLDO = false);
// configuration methods

View file

@ -73,7 +73,7 @@ int16_t SX1268::setFrequency(float freq) {
/// \todo integers only (all modules - frequency, data rate, bandwidth etc.)
int16_t SX1268::setFrequency(float freq, bool skipCalibration) {
RADIOLIB_CHECK_RANGE(freq, 410.0, 810.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 410.0f, 810.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// check if we need to recalibrate image
if(!skipCalibration && (fabsf(freq - this->freqMHz) >= RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ)) {

View file

@ -3,7 +3,9 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_SX126X
SX126x::SX126x(Module* mod) : PhysicalLayer(RADIOLIB_SX126X_FREQUENCY_STEP_SIZE, RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
SX126x::SX126x(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_SX126X_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_SX126X_MAX_PACKET_LENGTH;
this->mod = mod;
this->XTAL = false;
this->standbyXOSC = false;
@ -235,15 +237,14 @@ int16_t SX126x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
break;
} else {
// handle frequency hop
this->setLRFHSSHop(this->lrFhssHopNum % 16);
clearIrqStatus();
this->hopLRFHSS();
}
}
}
// update data rate
RadioLibTime_t elapsed = this->mod->hal->millis() - start;
this->dataRateMeasured = (len*8.0)/((float)elapsed/1000.0);
this->dataRateMeasured = (len*8.0f)/((float)elapsed/1000.0f);
return(finishTransmit());
}
@ -260,7 +261,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
if(modem == RADIOLIB_SX126X_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_SX126X_PACKET_TYPE_GFSK) {
// calculate timeout (500 % of expected time-one-air)
@ -268,8 +269,8 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
if(len == 0) {
maxLen = 0xFF;
}
float brBps = ((float)(RADIOLIB_SX126X_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0);
float brBps = (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (float)this->bitRate;
timeout = (RadioLibTime_t)(((maxLen * 8.0f) / brBps) * 1000.0f * 5.0f);
} else {
return(RADIOLIB_ERR_UNKNOWN);
@ -279,7 +280,7 @@ int16_t SX126x::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) / 15.625);
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0f) / 15.625f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -331,7 +332,7 @@ int16_t SX126x::transmitDirect(uint32_t frf) {
RADIOLIB_ASSERT(state);
// direct mode activation intentionally skipped here, as it seems to lead to much worse results
uint8_t data[] = { RADIOLIB_SX126X_CMD_NOP };
const uint8_t data[] = { RADIOLIB_SX126X_CMD_NOP };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_TX_CONTINUOUS_WAVE, data, 1));
}
@ -473,10 +474,20 @@ int16_t SX126x::standby(uint8_t mode, bool wakeup) {
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_SX126X_CMD_NOP, NULL, 0, false, false);
}
uint8_t data[] = { mode };
const uint8_t data[] = { mode };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_STANDBY, data, 1));
}
int16_t SX126x::hopLRFHSS() {
if(!(this->getIrqFlags() & RADIOLIB_SX126X_IRQ_LR_FHSS_HOP)) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
int16_t state = this->setLRFHSSHop(this->lrFhssHopNum % 16);
RADIOLIB_ASSERT(state);
return(clearIrqStatus());
}
void SX126x::setDio1Action(void (*func)(void)) {
this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, this->mod->hal->GpioInterruptRising);
}
@ -509,115 +520,6 @@ void SX126x::clearChannelScanAction() {
this->clearDio1Action();
}
int16_t SX126x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
(void)addr;
// check packet length
if(len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, len, this->headerType, this->invertIQEnabled);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType, len);
} else if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT, RADIOLIB_SX126X_IRQ_TX_DONE);
} else {
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP, RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP);
}
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
state = writeBuffer(const_cast<uint8_t*>(data), len);
} else {
// first, reset the LR-FHSS state machine
state = resetLRFHSS();
RADIOLIB_ASSERT(state);
// skip hopping for the first 4 - lrFhssHdrCount blocks
for(int i = 0; i < 4 - this->lrFhssHdrCount; ++i ) {
stepLRFHSS();
}
// in LR-FHSS mode, we need to build the entire packet manually
uint8_t frame[RADIOLIB_SX126X_MAX_PACKET_LENGTH] = { 0 };
size_t frameLen = 0;
this->lrFhssFrameBitsRem = 0;
this->lrFhssFrameHopsRem = 0;
this->lrFhssHopNum = 0;
state = buildLRFHSSPacket(const_cast<uint8_t*>(data), len, frame, &frameLen, &this->lrFhssFrameBitsRem, &this->lrFhssFrameHopsRem);
RADIOLIB_ASSERT(state);
// FIXME check max len for FHSS
state = writeBuffer(frame, frameLen);
RADIOLIB_ASSERT(state);
// activate hopping
uint8_t hopCfg[] = { RADIOLIB_SX126X_HOPPING_ENABLED, (uint8_t)frameLen, (uint8_t)this->lrFhssFrameHopsRem };
state = writeRegister(RADIOLIB_SX126X_REG_HOPPING_ENABLE, hopCfg, 3);
RADIOLIB_ASSERT(state);
// write the initial hopping table
uint8_t initHops = this->lrFhssFrameHopsRem;
if(initHops > 16) {
initHops = 16;
};
for(size_t i = 0; i < initHops; i++) {
// set the hop frequency and symbols
state = this->setLRFHSSHop(i);
RADIOLIB_ASSERT(state);
}
}
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// fix sensitivity
state = fixSensitivity();
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(this->txMode);
// start transmission
state = setTx(RADIOLIB_SX126X_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 SX126x::finishTransmit() {
// clear interrupt flags
int16_t state = clearIrqStatus();
@ -631,25 +533,6 @@ int16_t SX126x::startReceive() {
return(this->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX126x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (len != 0)) {
this->implicitLen = len;
}
int16_t state = startReceiveCommon(timeout, irqFlags, irqMask);
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
state = setRx(timeout);
return(state);
}
int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask) {
// datasheet claims time to go to sleep is ~500us, same to wake up, compensate for that with 1 ms + TCXO delay
uint32_t transitionTime = this->tcxoDelay + 1000;
@ -672,7 +555,7 @@ int16_t SX126x::startReceiveDutyCycle(uint32_t rxPeriod, uint32_t sleepPeriod, R
int16_t state = startReceiveCommon(RADIOLIB_SX126X_RX_TIMEOUT_INF, irqFlags, irqMask);
RADIOLIB_ASSERT(state);
uint8_t data[6] = {(uint8_t)((rxPeriodRaw >> 16) & 0xFF), (uint8_t)((rxPeriodRaw >> 8) & 0xFF), (uint8_t)(rxPeriodRaw & 0xFF),
const uint8_t data[6] = {(uint8_t)((rxPeriodRaw >> 16) & 0xFF), (uint8_t)((rxPeriodRaw >> 8) & 0xFF), (uint8_t)(rxPeriodRaw & 0xFF),
(uint8_t)((sleepPeriodRaw >> 16) & 0xFF), (uint8_t)((sleepPeriodRaw >> 8) & 0xFF), (uint8_t)(sleepPeriodRaw & 0xFF)};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_DUTY_CYCLE, data, 6));
}
@ -854,10 +737,10 @@ int16_t SX126x::setBandwidth(float bw) {
}
// ensure byte conversion doesn't overflow
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 3: // 7.8:
this->bandwidth = RADIOLIB_SX126X_LORA_BW_7_8;
@ -931,7 +814,7 @@ int16_t SX126x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
}
// update register
uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
const uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
return(writeRegister(RADIOLIB_SX126X_REG_LORA_SYNC_WORD_MSB, data, 2));
}
@ -942,7 +825,7 @@ int16_t SX126x::setCurrentLimit(float currentLimit) {
}
// calculate raw value
uint8_t rawLimit = (uint8_t)(currentLimit / 2.5);
uint8_t rawLimit = (uint8_t)(currentLimit / 2.5f);
// update register
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &rawLimit, 1));
@ -954,7 +837,7 @@ float SX126x::getCurrentLimit() {
readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
// return the actual value
return((float)ocp * 2.5);
return((float)ocp * 2.5f);
}
int16_t SX126x::setPreambleLength(size_t preambleLength) {
@ -986,14 +869,14 @@ int16_t SX126x::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);
RADIOLIB_CHECK_RANGE(newFreqDev, 0.6f, 200.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
// calculate raw frequency deviation value
uint32_t freqDevRaw = (uint32_t)(((newFreqDev * 1000.0) * (float)((uint32_t)(1) << 25)) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0));
uint32_t freqDevRaw = (uint32_t)(((newFreqDev * 1000.0f) * (float)((uint32_t)(1) << 25)) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f));
// check modulation parameters
this->frequencyDev = freqDevRaw;
@ -1010,11 +893,11 @@ int16_t SX126x::setBitRate(float br) {
}
if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
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);
}
// calculate raw bit rate value
uint32_t brRaw = (uint32_t)((RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0 * 32.0) / (br * 1000.0));
uint32_t brRaw = (uint32_t)((RADIOLIB_SX126X_CRYSTAL_FREQ * 1000000.0f * 32.0f) / (br * 1000.0f));
// check modulation parameters
this->bitRate = brRaw;
@ -1067,13 +950,13 @@ int16_t SX126x::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.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);
@ -1095,47 +978,47 @@ int16_t SX126x::setRxBandwidth(float rxBw) {
this->rxBandwidthKhz = rxBw;
// check allowed receiver bandwidth values
if(fabsf(rxBw - 4.8) <= 0.001) {
if(fabsf(rxBw - 4.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_4_8;
} else if(fabsf(rxBw - 5.8) <= 0.001) {
} else if(fabsf(rxBw - 5.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_5_8;
} else if(fabsf(rxBw - 7.3) <= 0.001) {
} else if(fabsf(rxBw - 7.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_7_3;
} else if(fabsf(rxBw - 9.7) <= 0.001) {
} else if(fabsf(rxBw - 9.7f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_9_7;
} else if(fabsf(rxBw - 11.7) <= 0.001) {
} else if(fabsf(rxBw - 11.7f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_11_7;
} else if(fabsf(rxBw - 14.6) <= 0.001) {
} else if(fabsf(rxBw - 14.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_14_6;
} else if(fabsf(rxBw - 19.5) <= 0.001) {
} else if(fabsf(rxBw - 19.5f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_19_5;
} else if(fabsf(rxBw - 23.4) <= 0.001) {
} else if(fabsf(rxBw - 23.4f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_23_4;
} else if(fabsf(rxBw - 29.3) <= 0.001) {
} else if(fabsf(rxBw - 29.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_29_3;
} else if(fabsf(rxBw - 39.0) <= 0.001) {
} else if(fabsf(rxBw - 39.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_39_0;
} else if(fabsf(rxBw - 46.9) <= 0.001) {
} else if(fabsf(rxBw - 46.9f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_46_9;
} else if(fabsf(rxBw - 58.6) <= 0.001) {
} else if(fabsf(rxBw - 58.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_58_6;
} else if(fabsf(rxBw - 78.2) <= 0.001) {
} else if(fabsf(rxBw - 78.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_78_2;
} else if(fabsf(rxBw - 93.8) <= 0.001) {
} else if(fabsf(rxBw - 93.8f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_93_8;
} else if(fabsf(rxBw - 117.3) <= 0.001) {
} else if(fabsf(rxBw - 117.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_117_3;
} else if(fabsf(rxBw - 156.2) <= 0.001) {
} else if(fabsf(rxBw - 156.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_156_2;
} else if(fabsf(rxBw - 187.2) <= 0.001) {
} else if(fabsf(rxBw - 187.2f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_187_2;
} else if(fabsf(rxBw - 234.3) <= 0.001) {
} else if(fabsf(rxBw - 234.3f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_234_3;
} else if(fabsf(rxBw - 312.0) <= 0.001) {
} else if(fabsf(rxBw - 312.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_312_0;
} else if(fabsf(rxBw - 373.6) <= 0.001) {
} else if(fabsf(rxBw - 373.6f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_373_6;
} else if(fabsf(rxBw - 467.0) <= 0.001) {
} else if(fabsf(rxBw - 467.0f) <= 0.001f) {
this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_467_0;
} else {
return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
@ -1154,7 +1037,7 @@ int16_t SX126x::setRxBoostedGainMode(bool rxbgm, bool persist) {
// add Rx Gain register to retention memory if requested
if(persist) {
// values and registers below are specified in SX126x datasheet v2.1 section 9.6, just below table 9-3
uint8_t data[] = { 0x01, (uint8_t)((RADIOLIB_SX126X_REG_RX_GAIN >> 8) & 0xFF), (uint8_t)(RADIOLIB_SX126X_REG_RX_GAIN & 0xFF) };
const uint8_t data[] = { 0x01, (uint8_t)((RADIOLIB_SX126X_REG_RX_GAIN >> 8) & 0xFF), (uint8_t)(RADIOLIB_SX126X_REG_RX_GAIN & 0xFF) };
state = writeRegister(RADIOLIB_SX126X_REG_RX_GAIN_RETENTION_0, data, 3);
}
@ -1373,7 +1256,7 @@ float SX126x::getRSSI(bool packet) {
// get instantaneous RSSI value
uint8_t rssiRaw = 0;
this->mod->SPIreadStream(RADIOLIB_SX126X_CMD_GET_RSSI_INST, &rssiRaw, 1);
return((float)rssiRaw / (-2.0));
return((float)rssiRaw / (-2.0f));
}
}
@ -1418,9 +1301,9 @@ float SX126x::getFrequencyError() {
// frequency error is negative
efe |= (uint32_t) 0xFFF00000;
efe = ~efe + 1;
error = 1.55 * (float) efe / (1600.0 / (float) this->bandwidthKhz) * -1.0;
error = 1.55f * (float) efe / (1600.0f / (float) this->bandwidthKhz) * -1.0f;
} else {
error = 1.55 * (float) efe / (1600.0 / (float) this->bandwidthKhz);
error = 1.55f * (float) efe / (1600.0f / (float) this->bandwidthKhz);
}
return(error);
@ -1528,7 +1411,7 @@ RadioLibTime_t SX126x::getTimeOnAir(size_t len) {
RadioLibTime_t SX126x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
// the timeout value is given in units of 15.625 microseconds
// the calling function should provide some extra width, as this number of units is truncated to integer
RadioLibTime_t timeout = timeoutUs / 15.625;
RadioLibTime_t timeout = timeoutUs / 15.625f;
return(timeout);
}
@ -1641,8 +1524,8 @@ int16_t SX126x::invertIQ(bool enable) {
int16_t SX126x::getModem(ModemType_t* modem) {
RADIOLIB_ASSERT_PTR(modem);
uint8_t packetType = getPacketType();
switch(packetType) {
uint8_t type = getPacketType();
switch(type) {
case(RADIOLIB_SX126X_PACKET_TYPE_LORA):
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
@ -1657,6 +1540,152 @@ int16_t SX126x::getModem(ModemType_t* modem) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
int16_t SX126x::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (cfg->receive.len != 0)) {
this->implicitLen = cfg->receive.len;
}
state = startReceiveCommon(cfg->receive.timeout, cfg->receive.irqFlags, cfg->receive.irqMask);
RADIOLIB_ASSERT(state);
this->rxTimeout = cfg->receive.timeout;
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// check packet length
if(cfg->transmit.len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) &&
(cfg->transmit.len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
state = RADIOLIB_ERR_NONE;
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, cfg->transmit.len, this->headerType, this->invertIQEnabled);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType, cfg->transmit.len);
} else if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
}
RADIOLIB_ASSERT(state);
// set DIO mapping
if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT, RADIOLIB_SX126X_IRQ_TX_DONE);
} else {
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP, RADIOLIB_SX126X_IRQ_TX_DONE | RADIOLIB_SX126X_IRQ_LR_FHSS_HOP);
}
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
state = writeBuffer(cfg->transmit.data, cfg->transmit.len);
} else {
// first, reset the LR-FHSS state machine
state = resetLRFHSS();
RADIOLIB_ASSERT(state);
// skip hopping for the first 4 - lrFhssHdrCount blocks
for(int i = 0; i < 4 - this->lrFhssHdrCount; ++i ) {
stepLRFHSS();
}
// in LR-FHSS mode, we need to build the entire packet manually
uint8_t frame[RADIOLIB_SX126X_MAX_PACKET_LENGTH] = { 0 };
size_t frameLen = 0;
this->lrFhssFrameBitsRem = 0;
this->lrFhssFrameHopsRem = 0;
this->lrFhssHopNum = 0;
state = buildLRFHSSPacket(cfg->transmit.data, cfg->transmit.len, frame, &frameLen, &this->lrFhssFrameBitsRem, &this->lrFhssFrameHopsRem);
RADIOLIB_ASSERT(state);
// FIXME check max len for FHSS
state = writeBuffer(frame, frameLen);
RADIOLIB_ASSERT(state);
// activate hopping
const uint8_t hopCfg[] = { RADIOLIB_SX126X_HOPPING_ENABLED, (uint8_t)frameLen, (uint8_t)this->lrFhssFrameHopsRem };
state = writeRegister(RADIOLIB_SX126X_REG_HOPPING_ENABLE, hopCfg, 3);
RADIOLIB_ASSERT(state);
// write the initial hopping table
uint8_t initHops = this->lrFhssFrameHopsRem;
if(initHops > 16) {
initHops = 16;
};
for(size_t i = 0; i < initHops; i++) {
// set the hop frequency and symbols
state = this->setLRFHSSHop(i);
RADIOLIB_ASSERT(state);
}
}
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// fix sensitivity
state = fixSensitivity();
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t SX126x::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(this->txMode);
state = setTx(RADIOLIB_SX126X_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);
}
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void SX126x::setDirectAction(void (*func)(void)) {
setDio1Action(func);
@ -1687,7 +1716,8 @@ int16_t SX126x::uploadPatch(const uint32_t* patch, size_t len, bool nonvolatile)
for(uint32_t i = 0; i < len / sizeof(uint32_t); i++) {
uint32_t bin = 0;
if(nonvolatile) {
bin = RADIOLIB_NONVOLATILE_READ_DWORD(patch + i);
uint32_t* ptr = const_cast<uint32_t*>(patch) + i;
bin = RADIOLIB_NONVOLATILE_READ_DWORD(ptr);
} else {
bin = patch[i];
}
@ -1726,7 +1756,7 @@ int16_t SX126x::spectralScanStart(uint16_t numSamples, uint8_t window, uint8_t i
RADIOLIB_ASSERT(state);
// now set the actual spectral scan parameters
uint8_t data[3] = { (uint8_t)((numSamples >> 8) & 0xFF), (uint8_t)(numSamples & 0xFF), interval };
const uint8_t data[3] = { (uint8_t)((numSamples >> 8) & 0xFF), (uint8_t)(numSamples & 0xFF), interval };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_SPECTR_SCAN_PARAMS, data, 3));
}
@ -1769,34 +1799,34 @@ int16_t SX126x::setTCXO(float voltage, uint32_t delay) {
}
// check 0 V disable
if(fabsf(voltage - 0.0) <= 0.001) {
if(fabsf(voltage - 0.0f) <= 0.001f) {
return(reset(true));
}
// check alowed voltage values
uint8_t data[4];
if(fabsf(voltage - 1.6) <= 0.001) {
if(fabsf(voltage - 1.6f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_6;
} else if(fabsf(voltage - 1.7) <= 0.001) {
} else if(fabsf(voltage - 1.7f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_7;
} else if(fabsf(voltage - 1.8) <= 0.001) {
} else if(fabsf(voltage - 1.8f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_1_8;
} else if(fabsf(voltage - 2.2) <= 0.001) {
} else if(fabsf(voltage - 2.2f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_2;
} else if(fabsf(voltage - 2.4) <= 0.001) {
} else if(fabsf(voltage - 2.4f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_4;
} else if(fabsf(voltage - 2.7) <= 0.001) {
} else if(fabsf(voltage - 2.7f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_2_7;
} else if(fabsf(voltage - 3.0) <= 0.001) {
} else if(fabsf(voltage - 3.0f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_0;
} else if(fabsf(voltage - 3.3) <= 0.001) {
} else if(fabsf(voltage - 3.3f) <= 0.001f) {
data[0] = RADIOLIB_SX126X_DIO3_OUTPUT_3_3;
} else {
return(RADIOLIB_ERR_INVALID_TCXO_VOLTAGE);
}
// calculate delay
uint32_t delayValue = (float)delay / 15.625;
uint32_t delayValue = (float)delay / 15.625f;
data[1] = (uint8_t)((delayValue >> 16) & 0xFF);
data[2] = (uint8_t)((delayValue >> 8) & 0xFF);
data[3] = (uint8_t)(delayValue & 0xFF);
@ -1822,12 +1852,12 @@ int16_t SX126x::setFs() {
}
int16_t SX126x::setTx(uint32_t timeout) {
uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF)} ;
const uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF)} ;
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_TX, data, 3));
}
int16_t SX126x::setRx(uint32_t timeout) {
uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF) };
const uint8_t data[] = { (uint8_t)((timeout >> 16) & 0xFF), (uint8_t)((timeout >> 8) & 0xFF), (uint8_t)(timeout & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX, data, 3, true, false));
}
@ -1879,11 +1909,11 @@ int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8
}
int16_t SX126x::setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMax, uint8_t paLut) {
uint8_t data[] = { paDutyCycle, hpMax, deviceSel, paLut };
const uint8_t data[] = { paDutyCycle, hpMax, deviceSel, paLut };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_PA_CONFIG, data, 4));
}
int16_t SX126x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
int16_t SX126x::writeRegister(uint16_t addr, const uint8_t* data, uint8_t numBytes) {
this->mod->SPIwriteRegisterBurst(addr, data, numBytes);
return(RADIOLIB_ERR_NONE);
}
@ -1897,18 +1927,18 @@ int16_t SX126x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
return(state);
}
int16_t SX126x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
uint8_t cmd[] = { RADIOLIB_SX126X_CMD_WRITE_BUFFER, offset };
int16_t SX126x::writeBuffer(const uint8_t* data, uint8_t numBytes, uint8_t offset) {
const uint8_t cmd[] = { RADIOLIB_SX126X_CMD_WRITE_BUFFER, offset };
return(this->mod->SPIwriteStream(cmd, 2, data, numBytes));
}
int16_t SX126x::readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
uint8_t cmd[] = { RADIOLIB_SX126X_CMD_READ_BUFFER, offset };
const uint8_t cmd[] = { RADIOLIB_SX126X_CMD_READ_BUFFER, offset };
return(this->mod->SPIreadStream(cmd, 2, data, numBytes));
}
int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
const uint8_t data[8] = {(uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
(uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
(uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
(uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF)};
@ -1916,12 +1946,12 @@ int16_t SX126x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t di
}
int16_t SX126x::clearIrqStatus(uint16_t clearIrqParams) {
uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
const uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CLEAR_IRQ_STATUS, data, 2));
}
int16_t SX126x::setRfFrequency(uint32_t frf) {
uint8_t data[] = { (uint8_t)((frf >> 24) & 0xFF), (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) };
const uint8_t data[] = { (uint8_t)((frf >> 24) & 0xFF), (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RF_FREQUENCY, data, 4));
}
@ -1974,7 +2004,7 @@ int16_t SX126x::setPaRampTime(uint8_t rampTime) {
return(this->setTxParams(this->pwr, rampTime));
}
int16_t SX126x::calibrateImage(uint8_t* data) {
int16_t SX126x::calibrateImage(const uint8_t* data) {
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE, data, 2);
// if something failed, show the device errors
@ -1996,7 +2026,7 @@ uint8_t SX126x::getPacketType() {
}
int16_t SX126x::setTxParams(uint8_t pwr, uint8_t rampTime) {
uint8_t data[] = { pwr, rampTime };
const uint8_t data[] = { pwr, rampTime };
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_TX_PARAMS, data, 2);
if(state == RADIOLIB_ERR_NONE) {
this->pwr = pwr;
@ -2040,7 +2070,7 @@ int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t
// 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_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON;
} else {
this->ldrOptimize = RADIOLIB_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF;
@ -2050,12 +2080,12 @@ int16_t SX126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t
}
// 500/9/8 - 0x09 0x04 0x03 0x00 - SF9, BW125, 4/8
// 500/11/8 - 0x0B 0x04 0x03 0x00 - SF11 BW125, 4/7
uint8_t data[4] = {sf, bw, cr, this->ldrOptimize};
const uint8_t data[4] = {sf, bw, cr, this->ldrOptimize};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS, data, 4));
}
int16_t SX126x::setModulationParamsFSK(uint32_t br, uint8_t sh, uint8_t rxBw, uint32_t freqDev) {
uint8_t data[8] = {(uint8_t)((br >> 16) & 0xFF), (uint8_t)((br >> 8) & 0xFF), (uint8_t)(br & 0xFF),
const uint8_t data[8] = {(uint8_t)((br >> 16) & 0xFF), (uint8_t)((br >> 8) & 0xFF), (uint8_t)(br & 0xFF),
sh, rxBw,
(uint8_t)((freqDev >> 16) & 0xFF), (uint8_t)((freqDev >> 8) & 0xFF), (uint8_t)(freqDev & 0xFF)};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_MODULATION_PARAMS, data, 8));
@ -2064,24 +2094,24 @@ int16_t SX126x::setModulationParamsFSK(uint32_t br, uint8_t sh, uint8_t rxBw, ui
int16_t SX126x::setPacketParams(uint16_t preambleLen, uint8_t crcType, uint8_t payloadLen, uint8_t hdrType, uint8_t invertIQ) {
int16_t state = fixInvertedIQ(invertIQ);
RADIOLIB_ASSERT(state);
uint8_t data[6] = {(uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF), hdrType, payloadLen, crcType, invertIQ};
const uint8_t data[6] = {(uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF), hdrType, payloadLen, crcType, invertIQ};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS, data, 6));
}
int16_t SX126x::setPacketParamsFSK(uint16_t preambleLen, uint8_t preambleDetectorLen, uint8_t crcType, uint8_t syncWordLen, uint8_t addrCmp, uint8_t whiten, uint8_t packType, uint8_t payloadLen) {
uint8_t data[9] = {(uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF),
const uint8_t data[9] = {(uint8_t)((preambleLen >> 8) & 0xFF), (uint8_t)(preambleLen & 0xFF),
preambleDetectorLen, syncWordLen, addrCmp,
packType, payloadLen, crcType, whiten};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_PACKET_PARAMS, data, 9));
}
int16_t SX126x::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) {
uint8_t data[2] = {txBaseAddress, rxBaseAddress};
const uint8_t data[2] = {txBaseAddress, rxBaseAddress};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_BUFFER_BASE_ADDRESS, data, 2));
}
int16_t SX126x::setRegulatorMode(uint8_t mode) {
uint8_t data[1] = {mode};
const uint8_t data[1] = {mode};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_REGULATOR_MODE, data, 1));
}
@ -2105,7 +2135,7 @@ uint16_t SX126x::getDeviceErrors() {
}
int16_t SX126x::clearDeviceErrors() {
uint8_t data[2] = {RADIOLIB_SX126X_CMD_NOP, RADIOLIB_SX126X_CMD_NOP};
const uint8_t data[2] = {RADIOLIB_SX126X_CMD_NOP, RADIOLIB_SX126X_CMD_NOP};
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CLEAR_DEVICE_ERRORS, data, 2));
}
@ -2126,7 +2156,7 @@ int16_t SX126x::fixSensitivity() {
RADIOLIB_ASSERT(state);
// fix the value for LoRa with 500 kHz bandwidth
if((getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA) && (fabsf(this->bandwidthKhz - 500.0) <= 0.001)) {
if((getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA) && (fabsf(this->bandwidthKhz - 500.0f) <= 0.001f)) {
sensitivityConfig &= 0xFB;
} else {
sensitivityConfig |= 0x04;
@ -2232,7 +2262,7 @@ int16_t SX126x::modSetup(float tcxoVoltage, bool useRegulatorLDO, 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);
}
@ -2329,7 +2359,7 @@ bool SX126x::findChip(const char* verStr) {
reset();
// read the version string
char version[16];
char version[16] = { 0 };
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, reinterpret_cast<uint8_t*>(version));
// check version register

View file

@ -14,7 +14,7 @@
// SX126X physical layer properties
#define RADIOLIB_SX126X_FREQUENCY_STEP_SIZE 0.9536743164
#define RADIOLIB_SX126X_MAX_PACKET_LENGTH 255
#define RADIOLIB_SX126X_CRYSTAL_FREQ 32.0
#define RADIOLIB_SX126X_CRYSTAL_FREQ 32.0f
#define RADIOLIB_SX126X_DIV_EXPONENT 25
// SX126X SPI commands
@ -201,7 +201,7 @@
#define RADIOLIB_SX126X_CAL_IMG_863_MHZ_2 0xDB
#define RADIOLIB_SX126X_CAL_IMG_902_MHZ_1 0xE1
#define RADIOLIB_SX126X_CAL_IMG_902_MHZ_2 0xE9
#define RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ (20.0)
#define RADIOLIB_SX126X_CAL_IMG_FREQ_TRIG_MHZ (20.0f)
//RADIOLIB_SX126X_CMD_SET_PA_CONFIG
#define RADIOLIB_SX126X_PA_CONFIG_HP_MAX 0x07
@ -478,6 +478,7 @@ class SX126x: public PhysicalLayer {
using PhysicalLayer::transmit;
using PhysicalLayer::receive;
using PhysicalLayer::startTransmit;
using PhysicalLayer::startReceive;
using PhysicalLayer::readData;
/*!
@ -628,18 +629,25 @@ class SX126x: public PhysicalLayer {
*/
int16_t standby(uint8_t mode, bool wakeup = true);
/*!
\brief Handle LR-FHSS hop.
When using LR-FHSS in interrupt-driven mode, this method MUST be called each time an interrupt is triggered!
\returns \ref status_codes
*/
int16_t hopLRFHSS();
// interrupt methods
/*!
\brief Sets interrupt service routine to call when DIO1 activates.
\param func ISR to call.
*/
void setDio1Action(void (*func)(void));
virtual void setDio1Action(void (*func)(void));
/*!
\brief Clears interrupt service routine to call when DIO1 activates.
*/
void clearDio1Action();
virtual void clearDio1Action();
/*!
\brief Sets interrupt service routine to call when a packet is received.
@ -674,16 +682,6 @@ class SX126x: public PhysicalLayer {
*/
void clearChannelScanAction() 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
@ -698,23 +696,6 @@ class SX126x: public PhysicalLayer {
*/
int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. DIO1 will be activated when full packet is received.
\param timeout Receive mode type and/or raw timeout value, expressed as multiples of 15.625 us.
When set to RADIOLIB_SX126X_RX_TIMEOUT_INF, the timeout will be infinite and the device will remain
in Rx mode until explicitly commanded to stop (Rx continuous mode).
When set to RADIOLIB_SX126X_RX_TIMEOUT_NONE, there will be no timeout and the device will return
to standby when a packet is received (Rx single mode).
For any other value, timeout will be applied and signal will be generated on DIO1 for conditions
defined by irqFlags and irqMask.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*!
\brief Interrupt-driven receive method where the device mostly sleeps and periodically wakes to listen.
Note that this function assumes the unit will take 500us + TCXO_delay to change state.
@ -783,14 +764,14 @@ class SX126x: public PhysicalLayer {
\param bw LoRa bandwidth to be set in kHz.
\returns \ref status_codes
*/
int16_t setBandwidth(float bw);
virtual int16_t setBandwidth(float bw);
/*!
\brief Sets LoRa spreading factor. Allowed values range from 5 to 12.
\param sf LoRa spreading factor to be set.
\returns \ref status_codes
*/
int16_t setSpreadingFactor(uint8_t sf);
virtual int16_t setSpreadingFactor(uint8_t sf);
/*!
\brief Sets LoRa coding rate denominator. Allowed values range from 5 to 8.
@ -908,27 +889,6 @@ class SX126x: public PhysicalLayer {
*/
int16_t setSyncBits(uint8_t *syncWord, uint8_t bitsLen);
/*!
\brief Sets node address. Calling this method will also enable address filtering for node address only.
\param addr Node address to be set.
\returns \ref status_codes
*/
int16_t setNodeAddress(uint8_t addr);
/*!
\brief Sets broadcast address. Calling this method will also enable address
filtering for node and broadcast address.
\param broadAddr Node address to be set.
\returns \ref status_codes
*/
int16_t setBroadcastAddress(uint8_t broadAddr);
/*!
\brief Disables address filtering. Calling this method will also erase previously set addresses.
\returns \ref status_codes
*/
int16_t disableAddressFiltering();
/*!
\brief Sets CRC configuration.
\param len CRC length in bytes, Allowed values are 1 or 2, set to 0 to disable CRC.
@ -1138,6 +1098,12 @@ class SX126x: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t getModem(ModemType_t* modem) override;
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
/*!
@ -1238,14 +1204,14 @@ class SX126x: public PhysicalLayer {
int16_t setTx(uint32_t timeout = 0);
int16_t setRx(uint32_t timeout);
int16_t setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin, uint8_t exitMode, RadioLibTime_t timeout);
int16_t writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t writeRegister(uint16_t addr, const uint8_t* data, uint8_t numBytes);
int16_t readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t writeBuffer(const uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX126X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX126X_IRQ_NONE);
virtual int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
int16_t setRfFrequency(uint32_t frf);
int16_t calibrateImage(uint8_t* data);
int16_t calibrateImage(const uint8_t* data);
uint8_t getPacketType();
int16_t setTxParams(uint8_t power, uint8_t rampTime);
int16_t setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro);
@ -1297,6 +1263,7 @@ class SX126x: public PhysicalLayer {
size_t implicitLen = 0;
uint8_t invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD;
uint32_t rxTimeout = 0;
// LR-FHSS stuff - there's a lot of it because all the encoding happens in software
uint8_t lrFhssCr = RADIOLIB_SX126X_LR_FHSS_CR_2_3;

View file

@ -87,7 +87,7 @@ int16_t SX126x::buildLRFHSSPacket(const uint8_t* in, size_t in_len, uint8_t* out
// for rates other than the 1/3 base, puncture the code
if(this->lrFhssCr != RADIOLIB_SX126X_LR_FHSS_CR_1_3) {
uint32_t matrix_index = 0;
uint8_t matrix[15] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 };
const uint8_t matrix[15] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 };
uint8_t matrix_len = 0;
switch(this->lrFhssCr) {
case RADIOLIB_SX126X_LR_FHSS_CR_5_6:
@ -364,7 +364,7 @@ int16_t SX126x::setLRFHSSHop(uint8_t index) {
}
}
uint8_t frq[4] = { (uint8_t)((freq_raw >> 24) & 0xFF), (uint8_t)((freq_raw >> 16) & 0xFF), (uint8_t)((freq_raw >> 8) & 0xFF), (uint8_t)(freq_raw & 0xFF) };
const uint8_t frq[4] = { (uint8_t)((freq_raw >> 24) & 0xFF), (uint8_t)((freq_raw >> 16) & 0xFF), (uint8_t)((freq_raw >> 8) & 0xFF), (uint8_t)(freq_raw & 0xFF) };
int16_t state = writeRegister(RADIOLIB_SX126X_REG_LR_FHSS_FREQX_0(index), frq, sizeof(freq_raw));
RADIOLIB_ASSERT(state);
@ -380,7 +380,7 @@ int16_t SX126x::setLRFHSSHop(uint8_t index) {
}
// write hop length in symbols
uint8_t sym[2] = { (uint8_t)((numSymbols >> 8) & 0xFF), (uint8_t)(numSymbols & 0xFF) };
const uint8_t sym[2] = { (uint8_t)((numSymbols >> 8) & 0xFF), (uint8_t)(numSymbols & 0xFF) };
state = writeRegister(RADIOLIB_SX126X_REG_LR_FHSS_NUM_SYMBOLS_FREQX_MSB(index), sym, sizeof(uint16_t));
RADIOLIB_ASSERT(state);

View file

@ -83,7 +83,7 @@ void SX1272::reset() {
}
int16_t SX1272::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 860.0, 1020.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 860.0f, 1020.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);
@ -102,11 +102,11 @@ int16_t SX1272::setBandwidth(float bw) {
uint8_t newBandwidth;
// check allowed bandwidth values
if(fabsf(bw - 125.0) <= 0.001) {
if(fabsf(bw - 125.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1272_BW_125_00_KHZ;
} else if(fabsf(bw - 250.0) <= 0.001) {
} else if(fabsf(bw - 250.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1272_BW_250_00_KHZ;
} else if(fabsf(bw - 500.0) <= 0.001) {
} else if(fabsf(bw - 500.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1272_BW_500_00_KHZ;
} else {
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
@ -121,7 +121,7 @@ int16_t SX1272::setBandwidth(float bw) {
if(this->ldroAuto) {
float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
Module* mod = this->getMod();
if(symbolLength >= 16.0) {
if(symbolLength >= 16.0f) {
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else {
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);
@ -175,7 +175,7 @@ int16_t SX1272::setSpreadingFactor(uint8_t sf) {
if(this->ldroAuto) {
float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
Module* mod = this->getMod();
if(symbolLength >= 16.0) {
if(symbolLength >= 16.0f) {
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_ON, 0, 0);
} else {
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_LOW_DATA_RATE_OPT_OFF, 0, 0);
@ -258,15 +258,15 @@ int16_t SX1272::checkDataRate(DataRate_t dr) {
// select interpretation based on active modem
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_FSK_OOK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0 <= 250.0) && (dr.fsk.freqDev <= 200.0))) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX127X_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 12, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
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);
return(RADIOLIB_ERR_NONE);
@ -279,8 +279,9 @@ int16_t SX1272::setOutputPower(int8_t power) {
return(this->setOutputPower(power, false));
}
int16_t SX1272::setOutputPower(int8_t power, bool useRfo) {
int16_t SX1272::setOutputPower(int8_t power, bool forceRfo) {
// check if power value is configurable
bool useRfo = (power < 2) || forceRfo;
int16_t state = checkOutputPower(power, NULL, useRfo);
RADIOLIB_ASSERT(state);

View file

@ -118,7 +118,7 @@ class SX1272: public SX127x {
Set to 0 to enable automatic gain control (recommended).
\returns \ref status_codes
*/
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
virtual int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
/*!
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
@ -160,7 +160,7 @@ class SX1272: public SX127x {
\param sf %LoRa link spreading factor to be set.
\returns \ref status_codes
*/
int16_t setSpreadingFactor(uint8_t sf);
virtual int16_t setSpreadingFactor(uint8_t sf);
/*!
\brief Sets %LoRa link coding rate denominator. Allowed values range from 5 to 8. Only available in %LoRa mode.
@ -201,10 +201,11 @@ class SX1272: public SX127x {
/*!
\brief Sets transmission output power. Allowed values range from -1 to 14 dBm (RFO pin) or +2 to +20 dBm (PA_BOOST pin).
\param power Transmission output power in dBm.
\param useRfo Whether to use the RFO (true) or the PA_BOOST (false) pin for the RF output.
\param forceRfo Whether to force using the RFO pin for the RF output (true)
or to leave the selection up to user (false) based on power output.
\returns \ref status_codes
*/
int16_t setOutputPower(int8_t power, bool useRfo);
int16_t setOutputPower(int8_t power, bool forceRfo);
/*!
\brief Check if output power is configurable.
@ -317,7 +318,7 @@ class SX1272: public SX127x {
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t configFSK();
int16_t configFSK() override;
void errataFix(bool rx) override;
#if !RADIOLIB_GODMODE

View file

@ -98,15 +98,15 @@ int16_t SX1273::checkDataRate(DataRate_t dr) {
// select interpretation based on active modem
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_FSK_OOK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0 <= 250.0) && (dr.fsk.freqDev <= 200.0))) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX127X_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 9, RADIOLIB_ERR_INVALID_SPREADING_FACTOR);
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);
return(RADIOLIB_ERR_NONE);

View file

@ -38,7 +38,7 @@ class SX1273: public SX1272 {
Set to 0 to enable automatic gain control (recommended).
\returns \ref status_codes
*/
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
int16_t begin(float freq = 915.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0) override;
// configuration methods
@ -47,7 +47,7 @@ class SX1273: public SX1272 {
\param sf %LoRa link 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

@ -7,7 +7,7 @@ SX1276::SX1276(Module* mod) : SX1278(mod) {
int16_t SX1276::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
RADIOLIB_ASSERT(state);
@ -39,7 +39,7 @@ int16_t SX1276::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
int16_t SX1276::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
RADIOLIB_ASSERT(state);
@ -69,7 +69,7 @@ int16_t SX1276::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
}
int16_t SX1276::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 137.0, 1020.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 137.0f, 1020.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);

View file

@ -27,7 +27,7 @@ class SX1276: public SX1278 {
/*!
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
@ -38,7 +38,7 @@ class SX1276: public SX1278 {
Set to 0 to enable automatic gain control (recommended).
\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_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0) override;
/*!
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
@ -52,7 +52,7 @@ class SX1276: public SX1278 {
\param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false) override;
// configuration methods

View file

@ -7,7 +7,7 @@ SX1277::SX1277(Module* mod) : SX1278(mod) {
int16_t SX1277::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
RADIOLIB_ASSERT(state);
@ -39,7 +39,7 @@ int16_t SX1277::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
int16_t SX1277::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
RADIOLIB_ASSERT(state);
@ -69,7 +69,7 @@ int16_t SX1277::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
}
int16_t SX1277::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 137.0, 1020.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 137.0f, 1020.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);
@ -140,15 +140,15 @@ int16_t SX1277::checkDataRate(DataRate_t dr) {
// select interpretation based on active modem
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_FSK_OOK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0 <= 250.0) && (dr.fsk.freqDev <= 200.0))) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX127X_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 9, 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);

View file

@ -27,7 +27,7 @@ class SX1277: public SX1278 {
/*!
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param sf %LoRa link spreading factor. Allowed values range from 6 to 9.
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
@ -38,7 +38,7 @@ class SX1277: public SX1278 {
Set to 0 to enable automatic gain control (recommended).
\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_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0) override;
/*!
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
@ -52,7 +52,7 @@ class SX1277: public SX1278 {
\param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false) override;
// configuration methods
@ -68,7 +68,7 @@ class SX1277: public SX1278 {
\param sf %LoRa link 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

@ -8,7 +8,7 @@ SX1278::SX1278(Module* mod) : SX127x(mod) {
int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
RADIOLIB_ASSERT(state);
@ -40,7 +40,7 @@ int16_t SX1278::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
int16_t SX1278::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
RADIOLIB_ASSERT(state);
@ -83,7 +83,7 @@ void SX1278::reset() {
}
int16_t SX1278::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 137.0, 525.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 137.0f, 525.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);
@ -102,25 +102,25 @@ int16_t SX1278::setBandwidth(float bw) {
uint8_t newBandwidth;
// check allowed bandwidth values
if(fabsf(bw - 7.8) <= 0.001) {
if(fabsf(bw - 7.8f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_7_80_KHZ;
} else if(fabsf(bw - 10.4) <= 0.001) {
} else if(fabsf(bw - 10.4f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_10_40_KHZ;
} else if(fabsf(bw - 15.6) <= 0.001) {
} else if(fabsf(bw - 15.6f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_15_60_KHZ;
} else if(fabsf(bw - 20.8) <= 0.001) {
} else if(fabsf(bw - 20.8f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_20_80_KHZ;
} else if(fabsf(bw - 31.25) <= 0.001) {
} else if(fabsf(bw - 31.25f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_31_25_KHZ;
} else if(fabsf(bw - 41.7) <= 0.001) {
} else if(fabsf(bw - 41.7f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_41_70_KHZ;
} else if(fabsf(bw - 62.5) <= 0.001) {
} else if(fabsf(bw - 62.5f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_62_50_KHZ;
} else if(fabsf(bw - 125.0) <= 0.001) {
} else if(fabsf(bw - 125.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_125_00_KHZ;
} else if(fabsf(bw - 250.0) <= 0.001) {
} else if(fabsf(bw - 250.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_250_00_KHZ;
} else if(fabsf(bw - 500.0) <= 0.001) {
} else if(fabsf(bw - 500.0f) <= 0.001f) {
newBandwidth = RADIOLIB_SX1278_BW_500_00_KHZ;
} else {
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
@ -135,7 +135,7 @@ int16_t SX1278::setBandwidth(float bw) {
if(this->ldroAuto) {
float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
Module* mod = this->getMod();
if(symbolLength >= 16.0) {
if(symbolLength >= 16.0f) {
state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
} else {
state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
@ -189,7 +189,7 @@ int16_t SX1278::setSpreadingFactor(uint8_t sf) {
if(this->ldroAuto) {
float symbolLength = (float)(uint32_t(1) << SX127x::spreadingFactor) / (float)SX127x::bandwidth;
Module* mod = this->getMod();
if(symbolLength >= 16.0) {
if(symbolLength >= 16.0f) {
state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_ON, 3, 3);
} else {
state = mod->SPIsetRegValue(RADIOLIB_SX1278_REG_MODEM_CONFIG_3, RADIOLIB_SX1278_LOW_DATA_RATE_OPT_OFF, 3, 3);
@ -272,15 +272,15 @@ int16_t SX1278::checkDataRate(DataRate_t dr) {
// select interpretation based on active modem
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_FSK_OOK) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5, 300.0, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0 <= 250.0) && (dr.fsk.freqDev <= 200.0))) {
RADIOLIB_CHECK_RANGE(dr.fsk.bitRate, 0.5f, 300.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
if(!((dr.fsk.freqDev + dr.fsk.bitRate/2.0f <= 250.0f) && (dr.fsk.freqDev <= 200.0f))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
return(RADIOLIB_ERR_NONE);
} else if(modem == RADIOLIB_SX127X_LORA) {
RADIOLIB_CHECK_RANGE(dr.lora.spreadingFactor, 6, 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);
@ -293,8 +293,9 @@ int16_t SX1278::setOutputPower(int8_t power) {
return(this->setOutputPower(power, false));
}
int16_t SX1278::setOutputPower(int8_t power, bool useRfo) {
int16_t SX1278::setOutputPower(int8_t power, bool forceRfo) {
// check if power value is configurable
bool useRfo = (power < 2) || forceRfo;
int16_t state = checkOutputPower(power, NULL, useRfo);
RADIOLIB_ASSERT(state);
@ -344,9 +345,9 @@ int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped, bool useRfo) {
if(useRfo) {
// RFO output
if(clipped) {
*clipped = RADIOLIB_MAX(-3, RADIOLIB_MIN(15, power));
*clipped = RADIOLIB_MAX(-4, RADIOLIB_MIN(15, power));
}
RADIOLIB_CHECK_RANGE(power, -3, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
RADIOLIB_CHECK_RANGE(power, -4, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
} else {
// PA_BOOST output, check high-power operation
if(clipped) {
@ -476,7 +477,7 @@ float SX1278::getRSSI() {
float SX1278::getRSSI(bool packet, bool skipReceive) {
int16_t offset = -157;
if(frequency < 868.0) {
if(frequency < 868.0f) {
offset = -164;
}
return(SX127x::getRSSI(packet, skipReceive, offset));
@ -606,11 +607,11 @@ void SX1278::errataFix(bool rx) {
// sensitivity optimization for 500kHz bandwidth
// see SX1276/77/78 Errata, section 2.1 for details
Module* mod = this->getMod();
if(fabsf(SX127x::bandwidth - 500.0) <= 0.001) {
if((frequency >= 862.0) && (frequency <= 1020.0)) {
if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
if((frequency >= 862.0f) && (frequency <= 1020.0f)) {
mod->SPIwriteRegister(0x36, 0x02);
mod->SPIwriteRegister(0x3a, 0x64);
} else if((frequency >= 410.0) && (frequency <= 525.0)) {
} else if((frequency >= 410.0f) && (frequency <= 525.0f)) {
mod->SPIwriteRegister(0x36, 0x02);
mod->SPIwriteRegister(0x3a, 0x7F);
}
@ -622,49 +623,49 @@ void SX1278::errataFix(bool rx) {
// figure out what we need to set
uint8_t fixedRegs[3] = { 0x00, 0x00, 0x00 };
float rxFreq = frequency;
if(fabsf(SX127x::bandwidth - 7.8) <= 0.001) {
if(fabsf(SX127x::bandwidth - 7.8f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x48;
fixedRegs[2] = 0x00;
rxFreq += 0.00781;
} else if(fabsf(SX127x::bandwidth - 10.4) <= 0.001) {
rxFreq += 0.00781f;
} else if(fabsf(SX127x::bandwidth - 10.4f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x44;
fixedRegs[2] = 0x00;
rxFreq += 0.01042;
} else if(fabsf(SX127x::bandwidth - 15.6) <= 0.001) {
rxFreq += 0.01042f;
} else if(fabsf(SX127x::bandwidth - 15.6f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x44;
fixedRegs[2] = 0x00;
rxFreq += 0.01562;
} else if(fabsf(SX127x::bandwidth - 20.8) <= 0.001) {
rxFreq += 0.01562f;
} else if(fabsf(SX127x::bandwidth - 20.8f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x44;
fixedRegs[2] = 0x00;
rxFreq += 0.02083;
} else if(fabsf(SX127x::bandwidth - 31.25) <= 0.001) {
rxFreq += 0.02083f;
} else if(fabsf(SX127x::bandwidth - 31.25f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x44;
fixedRegs[2] = 0x00;
rxFreq += 0.03125;
} else if(fabsf(SX127x::bandwidth - 41.7) <= 0.001) {
rxFreq += 0.03125f;
} else if(fabsf(SX127x::bandwidth - 41.7f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x44;
fixedRegs[2] = 0x00;
rxFreq += 0.04167;
} else if(fabsf(SX127x::bandwidth - 62.5) <= 0.001) {
rxFreq += 0.04167f;
} else if(fabsf(SX127x::bandwidth - 62.5f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x40;
fixedRegs[2] = 0x00;
} else if(fabsf(SX127x::bandwidth - 125.0) <= 0.001) {
} else if(fabsf(SX127x::bandwidth - 125.0f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x40;
fixedRegs[2] = 0x00;
} else if(fabsf(SX127x::bandwidth - 250.0) <= 0.001) {
} else if(fabsf(SX127x::bandwidth - 250.0f) <= 0.001f) {
fixedRegs[0] = 0b00000000;
fixedRegs[1] = 0x40;
fixedRegs[2] = 0x00;
} else if(fabsf(SX127x::bandwidth - 500.0) <= 0.001) {
} else if(fabsf(SX127x::bandwidth - 500.0f) <= 0.001f) {
fixedRegs[0] = 0b10000000;
fixedRegs[1] = mod->SPIreadRegister(0x2F);
fixedRegs[2] = mod->SPIreadRegister(0x30);

View file

@ -118,7 +118,7 @@ class SX1278: public SX127x {
/*!
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 525.0 MHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
@ -129,7 +129,7 @@ class SX1278: public SX127x {
Set to 0 to enable automatic gain control (recommended).
\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_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
virtual int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
/*!
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
@ -143,7 +143,7 @@ class SX1278: public SX127x {
\param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
virtual int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
/*!
\brief Reset method. Will reset the chip to the default state using RST pin.
@ -160,7 +160,7 @@ class SX1278: public SX127x {
int16_t setFrequency(float freq) override;
/*!
\brief Sets %LoRa link bandwidth. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz. Only available in %LoRa mode.
\brief Sets %LoRa link bandwidth. Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz. Only available in %LoRa mode.
\param bw %LoRa link bandwidth to be set in kHz.
\returns \ref status_codes
*/
@ -171,7 +171,7 @@ class SX1278: public SX127x {
\param sf %LoRa link spreading factor to be set.
\returns \ref status_codes
*/
int16_t setSpreadingFactor(uint8_t sf);
virtual int16_t setSpreadingFactor(uint8_t sf);
/*!
\brief Sets %LoRa link coding rate denominator. Allowed values range from 5 to 8. Only available in %LoRa mode.
@ -202,7 +202,7 @@ class SX1278: public SX127x {
int16_t checkDataRate(DataRate_t dr) override;
/*!
\brief Sets transmission output power. Allowed values range from -3 to 15 dBm (RFO pin) or +2 to +17 dBm (PA_BOOST pin).
\brief Sets transmission output power. Allowed values range from -4 to 15 dBm (RFO pin) or +2 to +17 dBm (PA_BOOST pin).
High power +20 dBm operation is also supported, on the PA_BOOST pin. Defaults to PA_BOOST.
\param power Transmission output power in dBm.
\returns \ref status_codes
@ -210,13 +210,14 @@ class SX1278: public SX127x {
int16_t setOutputPower(int8_t power) override;
/*!
\brief Sets transmission output power. Allowed values range from -3 to 15 dBm (RFO pin) or +2 to +17 dBm (PA_BOOST pin).
\brief Sets transmission output power. Allowed values range from -4 to 15 dBm (RFO pin) or +2 to +17 dBm (PA_BOOST pin).
High power +20 dBm operation is also supported, on the PA_BOOST pin.
\param power Transmission output power in dBm.
\param useRfo Whether to use the RFO (true) or the PA_BOOST (false) pin for the RF output.
\param forceRfo Whether to force using the RFO pin for the RF output (true)
or to leave the selection up to user (false) based on power output.
\returns \ref status_codes
*/
int16_t setOutputPower(int8_t power, bool useRfo);
int16_t setOutputPower(int8_t power, bool forceRfo);
/*!
\brief Check if output power is configurable.
@ -329,7 +330,7 @@ class SX1278: public SX127x {
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t configFSK();
int16_t configFSK() override;
void errataFix(bool rx) override;
#if !RADIOLIB_GODMODE

View file

@ -7,7 +7,7 @@ SX1279::SX1279(Module* mod) : SX1278(mod) {
int16_t SX1279::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, uint8_t gain) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::begin(versions, 3, syncWord, preambleLength);
RADIOLIB_ASSERT(state);
@ -39,7 +39,7 @@ int16_t SX1279::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
int16_t SX1279::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, bool enableOOK) {
// execute common part
uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
const uint8_t versions[] = { RADIOLIB_SX1278_CHIP_VERSION, RADIOLIB_SX1278_CHIP_VERSION_ALT, RADIOLIB_SX1278_CHIP_VERSION_RFM9X };
int16_t state = SX127x::beginFSK(versions, 3, freqDev, rxBw, preambleLength, enableOOK);
RADIOLIB_ASSERT(state);
@ -69,7 +69,7 @@ int16_t SX1279::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
}
int16_t SX1279::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 137.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 137.0f, 960.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency and if successful, save the new setting
int16_t state = SX127x::setFrequencyRaw(freq);

View file

@ -27,7 +27,7 @@ class SX1279: public SX1278 {
/*!
\brief %LoRa modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
\param freq Carrier frequency in MHz. Allowed values range from 137.0 MHz to 960.0 MHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param bw %LoRa link bandwidth in kHz. Allowed values are 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
@ -38,7 +38,7 @@ class SX1279: public SX1278 {
Set to 0 to enable automatic gain control (recommended).
\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_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0);
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX127X_SYNC_WORD, int8_t power = 10, uint16_t preambleLength = 8, uint8_t gain = 0) override;
/*!
\brief FSK modem initialization method. Must be called at least once from Arduino sketch to initialize the module.
@ -52,7 +52,7 @@ class SX1279: public SX1278 {
\param enableOOK Use OOK modulation instead of FSK.
\returns \ref status_codes
*/
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false);
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint16_t preambleLength = 16, bool enableOOK = false) override;
// configuration methods

View file

@ -2,11 +2,13 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_SX127X
SX127x::SX127x(Module* mod) : PhysicalLayer(RADIOLIB_SX127X_FREQUENCY_STEP_SIZE, RADIOLIB_SX127X_MAX_PACKET_LENGTH) {
SX127x::SX127x(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_SX127X_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_SX127X_MAX_PACKET_LENGTH;
this->mod = mod;
}
int16_t SX127x::begin(uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWord, uint16_t preambleLength) {
int16_t SX127x::begin(const uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWord, uint16_t preambleLength) {
// set module properties
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
@ -69,7 +71,7 @@ int16_t SX127x::begin(uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWo
return(state);
}
int16_t SX127x::beginFSK(uint8_t* chipVersions, uint8_t numVersions, float freqDev, float rxBw, uint16_t preambleLength, bool enableOOK) {
int16_t SX127x::beginFSK(const uint8_t* chipVersions, uint8_t numVersions, float freqDev, float rxBw, uint16_t preambleLength, bool enableOOK) {
// set module properties
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
@ -204,7 +206,7 @@ int16_t SX127x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
// update data rate
RadioLibTime_t elapsed = this->mod->hal->millis() - start;
this->dataRate = (len*8.0)/((float)elapsed/1000.0);
this->dataRate = (len*8.0f)/((float)elapsed/1000.0f);
return(finishTransmit());
}
@ -224,7 +226,7 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
RadioLibTime_t timeout = 0;
if(this->mod->getGpio() == RADIOLIB_NC) {
float symbolLength = (float) (uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
timeout = (RadioLibTime_t)(symbolLength * 100.0);
timeout = (RadioLibTime_t)(symbolLength * 100.0f);
}
// wait for packet reception or timeout
@ -389,67 +391,6 @@ int16_t SX127x::startReceive() {
return(this->startReceive(0, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX127x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
uint8_t mode = RADIOLIB_SX127X_RXCONTINUOUS;
// set mode to standby
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = this->setIrqFlags(getIrqMapped(irqFlags & irqMask));
RADIOLIB_ASSERT(state);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
if(timeout != 0) {
// for non-zero timeout value, change mode to Rx single and set the timeout
mode = RADIOLIB_SX127X_RXSINGLE;
uint8_t msb_sym = (timeout > 0x3FF) ? 0x3 : (uint8_t)(timeout >> 8);
uint8_t lsb_sym = (timeout > 0x3FF) ? 0xFF : (uint8_t)(timeout & 0xFF);
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, msb_sym, 1, 0);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_SYMB_TIMEOUT_LSB, lsb_sym);
RADIOLIB_ASSERT(state);
}
// in FHSS mode, enable channel change interrupt
if(this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) {
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 5, 4);
}
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->implicitHdr) && (len != 0)) {
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
this->packetLength = len;
}
// apply fixes to errata
RADIOLIB_ERRATA_SX127X(true);
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set FIFO pointers
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_RX_BASE_ADDR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_ADDR_PTR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
RADIOLIB_ASSERT(state);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// FSK modem does not distinguish between Rx single and continuous
mode = RADIOLIB_SX127X_RX;
}
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
return(setMode(mode));
}
void SX127x::setDio0Action(void (*func)(void), uint32_t dir) {
this->mod->hal->attachInterrupt(this->mod->hal->pinToInterrupt(this->mod->getIrq()), func, dir);
}
@ -548,7 +489,7 @@ bool SX127x::fifoAdd(uint8_t* data, int totalLen, int* remLen) {
bool SX127x::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_SX127X_FIFO_THRESH - 1;
@ -568,80 +509,6 @@ bool SX127x::fifoGet(volatile uint8_t* data, int totalLen, volatile int* rcvLen)
return(false);
}
int16_t SX127x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// set mode to standby
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// check packet length
if(len > RADIOLIB_SX127X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set DIO mapping
if(this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_TX_DONE | RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 7, 4);
} else {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_TX_DONE, 7, 6);
}
// apply fixes to errata
RADIOLIB_ERRATA_SX127X(false);
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set packet length
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
// set FIFO pointers
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_TX_BASE_ADDR, RADIOLIB_SX127X_FIFO_TX_BASE_ADDR_MAX);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_ADDR_PTR, RADIOLIB_SX127X_FIFO_TX_BASE_ADDR_MAX);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set DIO mapping
if(len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK) {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_PACK_FIFO_EMPTY, 5, 4);
} else {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6);
}
// set packet length - increased by 1 when address filter is enabled
uint8_t filter = this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, 2, 1);
if(this->packetLengthConfig == RADIOLIB_SX127X_PACKET_VARIABLE) {
if((filter == RADIOLIB_SX127X_ADDRESS_FILTERING_NODE) || (filter == RADIOLIB_SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, len + 1);
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, addr);
} else {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, len);
}
}
}
// write packet to FIFO
size_t packetLen = len;
if((modem == RADIOLIB_SX127X_FSK_OOK) && (len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK)) {
packetLen = RADIOLIB_SX127X_FIFO_THRESH - 1;
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_THRESH, RADIOLIB_SX127X_TX_START_FIFO_NOT_EMPTY, 7, 7);
}
this->mod->SPIwriteRegisterBurst(RADIOLIB_SX127X_REG_FIFO, const_cast<uint8_t*>(data), packetLen);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state |= setMode(RADIOLIB_SX127X_TX);
RADIOLIB_ASSERT(state);
return(RADIOLIB_ERR_NONE);
}
int16_t SX127x::finishTransmit() {
// wait for at least 1 bit at the lowest possible bit rate before clearing IRQ flags
// not doing this and clearing RADIOLIB_SX127X_FLAG_FIFO_OVERRUN will dump the FIFO,
@ -844,14 +711,14 @@ float SX127x::getFrequencyError(bool autoCorrect) {
// frequency error is negative
raw |= (uint32_t)0xFFF00000;
raw = ~raw + 1;
error = (((float)raw * (float)base)/32000000.0) * (this->bandwidth/500.0) * -1.0;
error = (((float)raw * (float)base)/32000000.0f) * (this->bandwidth/500.0f) * -1.0f;
} else {
error = (((float)raw * (float)base)/32000000.0) * (this->bandwidth/500.0);
error = (((float)raw * (float)base)/32000000.0f) * (this->bandwidth/500.0f);
}
if(autoCorrect) {
// adjust LoRa modem data rate
float ppmOffset = 0.95 * (error/32.0);
float ppmOffset = 0.95f * (error/32.0f);
this->mod->SPIwriteRegister(0x27, (uint8_t)ppmOffset);
}
@ -870,9 +737,9 @@ float SX127x::getFrequencyError(bool autoCorrect) {
// frequency error is negative
raw |= (uint32_t)0xFFF00000;
raw = ~raw + 1;
error = (float)raw * (32000000.0 / (float)(base << 19)) * -1.0;
error = (float)raw * (32000000.0f / (float)(base << 19)) * -1.0f;
} else {
error = (float)raw * (32000000.0 / (float)(base << 19));
error = (float)raw * (32000000.0f / (float)(base << 19));
}
return(error);
@ -894,7 +761,7 @@ float SX127x::getAFCError()
raw |= this->mod->SPIreadRegister(RADIOLIB_SX127X_REG_AFC_LSB);
uint32_t base = 1;
return raw * (32000000.0 / (float)(base << 19));
return raw * (32000000.0f / (float)(base << 19));
}
float SX127x::getSNR() {
@ -921,9 +788,9 @@ int16_t SX127x::setBitRateCommon(float br, uint8_t fracRegAddr) {
// check allowed bit rate
// datasheet says 1.2 kbps should be the smallest possible, but 0.512 works fine
if(ookEnabled) {
RADIOLIB_CHECK_RANGE(br, 0.5, 32.768002, RADIOLIB_ERR_INVALID_BIT_RATE); // Found that 32.768 is 32.768002
RADIOLIB_CHECK_RANGE(br, 0.5f, 32.768002f, RADIOLIB_ERR_INVALID_BIT_RATE); // Found that 32.768 is 32.768002
} else {
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);
}
// set mode to STANDBY
@ -931,13 +798,13 @@ int16_t SX127x::setBitRateCommon(float br, uint8_t fracRegAddr) {
RADIOLIB_ASSERT(state);
// set bit rate
uint16_t bitRateRaw = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / br;
uint16_t bitRateRaw = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0f) / br;
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_MSB, (bitRateRaw & 0xFF00) >> 8, 7, 0);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_LSB, bitRateRaw & 0x00FF, 7, 0);
// set fractional part of bit rate
if(!ookEnabled) {
float bitRateRem = ((RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / (float)br) - (float)bitRateRaw;
float bitRateRem = ((RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0f) / br) - (float)bitRateRaw;
uint8_t bitRateFrac = bitRateRem * 16;
state |= this->mod->SPIsetRegValue(fracRegAddr, bitRateFrac, 7, 0);
}
@ -956,12 +823,12 @@ int16_t SX127x::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
if(!((newFreqDev + this->bitRate/2.0 <= 250.0) && (freqDev <= 200.0))) {
if(!((newFreqDev + this->bitRate/2.0f <= 250.0f) && (freqDev <= 200.0f))) {
return(RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
}
@ -981,8 +848,8 @@ uint8_t SX127x::calculateBWManExp(float bandwidth)
{
for(uint8_t e = 7; e >= 1; e--) {
for(int8_t m = 2; m >= 0; m--) {
float point = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000000.0)/(((4 * m) + 16) * ((uint32_t)1 << (e + 2)));
if(fabsf(bandwidth - ((point / 1000.0) + 0.05)) <= 0.5) {
float point = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000000.0f)/(((4 * m) + 16) * ((uint32_t)1 << (e + 2)));
if(fabsf(bandwidth - ((point / 1000.0f) + 0.05f)) <= 0.5f) {
return((m << 3) | e);
}
}
@ -996,7 +863,7 @@ int16_t SX127x::setRxBandwidth(float rxBw) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_CHECK_RANGE(rxBw, 2.6, 250.0, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
RADIOLIB_CHECK_RANGE(rxBw, 2.6f, 250.0f, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
// set mode to STANDBY
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
@ -1012,7 +879,7 @@ int16_t SX127x::setAFCBandwidth(float rxBw) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_CHECK_RANGE(rxBw, 2.6, 250.0, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
RADIOLIB_CHECK_RANGE(rxBw, 2.6f, 250.0f, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
// set mode to STANDBY
int16_t state = setMode(RADIOLIB_SX127X_STANDBY);
@ -1251,7 +1118,7 @@ float SX127x::getNumSymbols(size_t len) {
// get Low Data Rate optimization flag
float de = 0;
if (symbolLength >= 16.0) {
if (symbolLength >= 16.0f) {
de = 1;
}
@ -1265,7 +1132,7 @@ float SX127x::getNumSymbols(size_t len) {
float n_pre = (float) ((this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PREAMBLE_MSB) << 8) | this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PREAMBLE_LSB));
// get number of payload symbols
float n_pay = 8.0 + RADIOLIB_MAX(ceilf((8.0 * (float) len - 4.0 * (float) this->spreadingFactor + 28.0 + 16.0 * crc - 20.0 * ih) / (4.0 * (float) this->spreadingFactor - 8.0 * de)) * (float) this->codingRate, 0.0);
float n_pay = 8.0f + RADIOLIB_MAX(ceilf((8.0f * (float) len - 4.0f * (float) this->spreadingFactor + 28.0f + 16.0f * crc - 20.0f * ih) / (4.0f * (float) this->spreadingFactor - 8.0f * de)) * (float) this->codingRate, 0.0f);
// add 4.25 symbols for the sync
return(n_pre + n_pay + 4.25f);
@ -1301,7 +1168,7 @@ RadioLibTime_t SX127x::getTimeOnAir(size_t len) {
}
// calculate time-on-air in us {[(length in bytes) * (8 bits / 1 byte)] / [(Bit Rate in kbps) * (1000 bps / 1 kbps)]} * (1000000 us in 1 sec)
return((uint32_t) (((crc + n_syncWord + n_pre + (float) (len * 8)) / (this->bitRate * 1000.0)) * 1000000.0));
return((uint32_t) (((crc + n_syncWord + n_pre + (float) (len * 8)) / (this->bitRate * 1000.0f)) * 1000000.0f));
}
return(RADIOLIB_ERR_UNKNOWN);
@ -1448,9 +1315,9 @@ int16_t SX127x::setCrcFiltering(bool enable) {
}
int16_t SX127x::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_SX127X_REG_RSSI_THRESH, (uint8_t)(-2.0 * dbm), 7, 0);
return this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RSSI_THRESH, (uint8_t)(-2.0f * dbm), 7, 0);
}
int16_t SX127x::setRSSIConfig(uint8_t smoothingSamples, int8_t offset) {
@ -1776,6 +1643,161 @@ int16_t SX127x::getModem(ModemType_t* modem) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
int16_t SX127x::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->rxMode = RADIOLIB_SX127X_RXCONTINUOUS;
// set mode to standby
state = setMode(RADIOLIB_SX127X_STANDBY);
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = this->setIrqFlags(getIrqMapped(cfg->receive.irqFlags & cfg->receive.irqMask));
RADIOLIB_ASSERT(state);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
if(cfg->receive.timeout != 0) {
// for non-zero timeout value, change mode to Rx single and set the timeout
this->rxMode = RADIOLIB_SX127X_RXSINGLE;
uint8_t msb_sym = (cfg->receive.timeout > 0x3FF) ? 0x3 : (uint8_t)(cfg->receive.timeout >> 8);
uint8_t lsb_sym = (cfg->receive.timeout > 0x3FF) ? 0xFF : (uint8_t)(cfg->receive.timeout & 0xFF);
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, msb_sym, 1, 0);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_SYMB_TIMEOUT_LSB, lsb_sym);
RADIOLIB_ASSERT(state);
}
// in FHSS mode, enable channel change interrupt
if(this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) {
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 5, 4);
}
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->implicitHdr) && (cfg->receive.len != 0)) {
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, cfg->receive.len);
this->packetLength = cfg->receive.len;
}
// apply fixes to errata
RADIOLIB_ERRATA_SX127X(true);
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set FIFO pointers
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_RX_BASE_ADDR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_ADDR_PTR, RADIOLIB_SX127X_FIFO_RX_BASE_ADDR_MAX);
RADIOLIB_ASSERT(state);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// FSK modem does not distinguish between Rx single and continuous
this->rxMode = RADIOLIB_SX127X_RX;
}
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// set mode to standby
state = setMode(RADIOLIB_SX127X_STANDBY);
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
// check packet length
if(cfg->transmit.len > RADIOLIB_SX127X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set DIO mapping
if(this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_HOP_PERIOD) > RADIOLIB_SX127X_HOP_PERIOD_OFF) {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_TX_DONE | RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 7, 4);
} else {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_LORA_TX_DONE, 7, 6);
}
// apply fixes to errata
RADIOLIB_ERRATA_SX127X(false);
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set packet length
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, cfg->transmit.len);
// set FIFO pointers
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_TX_BASE_ADDR, RADIOLIB_SX127X_FIFO_TX_BASE_ADDR_MAX);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_ADDR_PTR, RADIOLIB_SX127X_FIFO_TX_BASE_ADDR_MAX);
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
// clear interrupt flags
clearIrqFlags(RADIOLIB_SX127X_FLAGS_ALL);
// set DIO mapping
if(cfg->transmit.len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK) {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_PACK_FIFO_EMPTY, 5, 4);
} else {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO0_PACK_PACKET_SENT, 7, 6);
}
// set packet length - increased by 1 when address filter is enabled
uint8_t filter = this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, 2, 1);
if(this->packetLengthConfig == RADIOLIB_SX127X_PACKET_VARIABLE) {
if((filter == RADIOLIB_SX127X_ADDRESS_FILTERING_NODE) || (filter == RADIOLIB_SX127X_ADDRESS_FILTERING_NODE_BROADCAST)) {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, cfg->transmit.len + 1);
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, cfg->transmit.addr);
} else {
this->mod->SPIwriteRegister(RADIOLIB_SX127X_REG_FIFO, cfg->transmit.len);
}
}
}
// write packet to FIFO
size_t packetLen = cfg->transmit.len;
if((modem == RADIOLIB_SX127X_FSK_OOK) && (cfg->transmit.len > RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK)) {
packetLen = RADIOLIB_SX127X_FIFO_THRESH - 1;
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_THRESH, RADIOLIB_SX127X_TX_START_FIFO_NOT_EMPTY, 7, 7);
}
this->mod->SPIwriteRegisterBurst(RADIOLIB_SX127X_REG_FIFO, cfg->transmit.data, packetLen);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t SX127x::launchMode() {
int16_t state;
switch(this->stagedMode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->mod->setRfSwitchState(Module::MODE_RX);
state = setMode(this->rxMode);
RADIOLIB_ASSERT(state);
} break;
case(RADIOLIB_RADIO_MODE_TX): {
this->mod->setRfSwitchState(Module::MODE_TX);
state = setMode(RADIOLIB_SX127X_TX);
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = RADIOLIB_RADIO_MODE_NONE;
return(state);
}
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void SX127x::setDirectAction(void (*func)(void)) {
setDio1Action(func, this->mod->hal->GpioInterruptRising);
@ -1830,7 +1852,7 @@ float SX127x::getRSSI(bool packet, bool skipReceive, int16_t offset) {
// spread-spectrum modulation signal can be received below noise floor
// check last packet SNR and if it's less than 0, add it to reported RSSI to get the correct value
float lastPacketSNR = SX127x::getSNR();
if(lastPacketSNR < 0.0) {
if(lastPacketSNR < 0.0f) {
lastPacketRSSI += lastPacketSNR;
}
return(lastPacketRSSI);
@ -1850,7 +1872,7 @@ float SX127x::getRSSI(bool packet, bool skipReceive, int16_t offset) {
}
// read the value for FSK
float rssi = (float)this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_RSSI_VALUE_FSK) / -2.0;
float rssi = (float)this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_RSSI_VALUE_FSK) / -2.0f;
// set mode back to standby
if(!skipReceive) {
@ -1869,12 +1891,11 @@ int16_t SX127x::setHeaderType(uint8_t headerType, uint8_t bitIndex, size_t len)
}
// set requested packet mode
Module* mod = this->getMod();
int16_t state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, bitIndex, bitIndex);
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, bitIndex, bitIndex);
RADIOLIB_ASSERT(state);
// set length to register
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
RADIOLIB_ASSERT(state);
// update cached value

View file

@ -13,7 +13,7 @@
#define RADIOLIB_SX127X_FREQUENCY_STEP_SIZE 61.03515625
#define RADIOLIB_SX127X_MAX_PACKET_LENGTH 255
#define RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK 64
#define RADIOLIB_SX127X_CRYSTAL_FREQ 32.0
#define RADIOLIB_SX127X_CRYSTAL_FREQ 32.0f
#define RADIOLIB_SX127X_DIV_EXPONENT 19
// SX127x series common LoRa registers
@ -586,6 +586,7 @@ class SX127x: public PhysicalLayer {
using PhysicalLayer::transmit;
using PhysicalLayer::receive;
using PhysicalLayer::startTransmit;
using PhysicalLayer::startReceive;
using PhysicalLayer::readData;
// constructor
@ -606,7 +607,7 @@ class SX127x: public PhysicalLayer {
\param preambleLength Length of %LoRa transmission preamble in symbols.
\returns \ref status_codes
*/
int16_t begin(uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWord, uint16_t preambleLength);
int16_t begin(const uint8_t* chipVersions, uint8_t numVersions, uint8_t syncWord, uint16_t preambleLength);
/*!
\brief Reset method. Will reset the chip to the default state using RST pin. Declared pure virtual since SX1272 and SX1278 implementations differ.
@ -623,7 +624,7 @@ class SX127x: public PhysicalLayer {
\param enableOOK Flag to specify OOK mode. This modulation is similar to FSK.
\returns \ref status_codes
*/
int16_t beginFSK(uint8_t* chipVersions, uint8_t numVersions, float freqDev, float rxBw, uint16_t preambleLength, bool enableOOK);
int16_t beginFSK(const uint8_t* chipVersions, uint8_t numVersions, float freqDev, float rxBw, uint16_t preambleLength, bool enableOOK);
/*!
\brief Binary transmit method. Will transmit arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
@ -798,15 +799,6 @@ class SX127x: public PhysicalLayer {
*/
bool fifoGet(volatile uint8_t* data, int totalLen, volatile int* rcvLen);
/*!
\brief Interrupt-driven binary transmit method. Will start transmitting arbitrary binary data up to 255 bytes long using %LoRa or up to 63 bytes using FSK modem.
\param data Binary data that will be transmitted.
\param len Length of binary data to transmit (in bytes).
\param addr Node address to transmit the packet to. Only used in FSK mode.
\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
@ -820,19 +812,6 @@ class SX127x: public PhysicalLayer {
*/
int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method, implemented for compatibility with PhysicalLayer.
\param timeout Receive mode type and/or raw timeout value in symbols.
When set to 0, the timeout will be infinite and the device will remain
in Rx mode until explicitly commanded to stop (Rx continuous mode).
When non-zero (maximum 1023), the device will be set to Rx single mode and timeout will be set.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Expected length of packet to be received. Required for LoRa spreading factor 6.
\returns \ref status_codes
*/
int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0) override;
/*!
\brief Reads data that was received after calling startReceive method. When the packet length is not known in advance,
getPacketLength method must be called BEFORE calling readData!
@ -1163,6 +1142,12 @@ class SX127x: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t getModem(ModemType_t* modem) override;
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
/*!
@ -1251,7 +1236,7 @@ class SX127x: public PhysicalLayer {
bool ookEnabled = false;
bool implicitHdr = false;
int16_t configFSK();
virtual int16_t configFSK();
int16_t getActiveModem();
int16_t setFrequencyRaw(float newFreq);
int16_t setBitRateCommon(float br, uint8_t fracRegAddr);
@ -1268,6 +1253,7 @@ class SX127x: public PhysicalLayer {
float dataRate = 0;
bool packetLengthQueried = false; // FSK packet length is the first byte in FIFO, length can only be queried once
uint8_t packetLengthConfig = RADIOLIB_SX127X_PACKET_VARIABLE;
uint8_t rxMode = RADIOLIB_SX127X_RXCONTINUOUS;
int16_t config();
int16_t directMode();

View file

@ -33,7 +33,7 @@ int16_t SX1280::range(bool master, uint32_t addr, uint16_t calTable[3][6]) {
return(state);
}
int16_t SX1280::startRanging(bool master, uint32_t addr, uint16_t calTable[3][6]) {
int16_t SX1280::startRanging(bool master, uint32_t addr, const uint16_t calTable[3][6]) {
// check active modem
uint8_t modem = getPacketType();
if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING))) {
@ -80,7 +80,7 @@ int16_t SX1280::startRanging(bool master, uint32_t addr, uint16_t calTable[3][6]
}
// set ranging address
uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
const uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
state = writeRegister(addrReg, addrBuff, 4);
RADIOLIB_ASSERT(state);
@ -116,7 +116,7 @@ int16_t SX1280::startRanging(bool master, uint32_t addr, uint16_t calTable[3][6]
default:
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
}
uint8_t calBuff[] = { (uint8_t)((val >> 8) & 0xFF), (uint8_t)(val & 0xFF) };
const uint8_t calBuff[] = { (uint8_t)((val >> 8) & 0xFF), (uint8_t)(val & 0xFF) };
state = writeRegister(RADIOLIB_SX128X_REG_RANGING_CALIBRATION_MSB, calBuff, 2);
RADIOLIB_ASSERT(state);
@ -178,7 +178,7 @@ float SX1280::getRangingResult() {
// calculate the real result
uint32_t uraw = ((uint32_t)data[0] << 16) | ((uint32_t)data[1] << 8) | data[2];
int32_t raw = (uraw & ((1UL << 23) - 1)) | (uraw >> 23 << 31);
return((float)raw * 150.0 / (4.096 * this->bandwidthKhz));
return((float)raw * 150.0f / (4.096f * this->bandwidthKhz));
}
#endif

View file

@ -37,7 +37,7 @@ class SX1280: public SX1281 {
\param calTable Ranging calibration table - set to NULL to use the default.
\returns \ref status_codes
*/
int16_t startRanging(bool master, uint32_t addr, uint16_t calTable[3][6] = NULL);
int16_t startRanging(bool master, uint32_t addr, const uint16_t calTable[3][6] = NULL);
/*!
\brief Gets ranging result of the last ranging exchange.

View file

@ -2,7 +2,9 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_SX128X
SX128x::SX128x(Module* mod) : PhysicalLayer(RADIOLIB_SX128X_FREQUENCY_STEP_SIZE, RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
SX128x::SX128x(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_SX128X_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_SX128X_MAX_PACKET_LENGTH;
this->mod = mod;
this->irqMap[RADIOLIB_IRQ_TX_DONE] = RADIOLIB_SX128X_IRQ_TX_DONE;
this->irqMap[RADIOLIB_IRQ_RX_DONE] = RADIOLIB_SX128X_IRQ_RX_DONE;
@ -364,7 +366,7 @@ int16_t SX128x::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 / 15.625);
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625f);
state = startReceive(timeoutValue);
RADIOLIB_ASSERT(state);
@ -485,7 +487,7 @@ int16_t SX128x::standby(uint8_t mode, bool wakeup) {
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_SX128X_CMD_NOP, NULL, 0, false, false);
}
uint8_t data[] = { mode };
const uint8_t data[] = { mode };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_STANDBY, data, 1));
}
@ -513,70 +515,6 @@ void SX128x::clearPacketSentAction() {
this->clearDio1Action();
}
int16_t SX128x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
// suppress unused variable warning
(void)addr;
// check packet length
if(len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
int16_t state = RADIOLIB_ERR_NONE;
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, len, this->crcLoRa, this->invertIQEnabled);
} else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, len);
} else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
} else {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_ASSERT(state);
// update output power
state = setTxParams(this->power);
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
// first 2 bytes of BLE payload are PDU header
state = writeBuffer(const_cast<uint8_t*>(data), len, 2);
RADIOLIB_ASSERT(state);
} else {
state = writeBuffer(const_cast<uint8_t*>(data), len);
RADIOLIB_ASSERT(state);
}
// set DIO mapping
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE);
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state = setTx(RADIOLIB_SX128X_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 SX128x::finishTransmit() {
// clear interrupt flags
clearIrqStatus();
@ -589,49 +527,6 @@ int16_t SX128x::startReceive() {
return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0));
}
int16_t SX128x::startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (len != 0)) {
this->payloadLen = len;
}
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
int16_t state = setDioIrqParams(getIrqMapped(irqFlags), getIrqMapped(irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, 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);
}
int16_t SX128x::readData(uint8_t* data, size_t len) {
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
@ -745,7 +640,7 @@ int16_t SX128x::getChannelScanResult() {
}
int16_t SX128x::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 2400.0, 2500.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 2400.0f, 2500.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// calculate raw value
uint32_t frf = (freq * (uint32_t(1) << RADIOLIB_SX128X_DIV_EXPONENT)) / RADIOLIB_SX128X_CRYSTAL_FREQ;
@ -757,21 +652,21 @@ int16_t SX128x::setBandwidth(float bw) {
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
// check range for LoRa
RADIOLIB_CHECK_RANGE(bw, 203.125, 1625.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(bw, 203.125f, 1625.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
} else if(modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
// check range for ranging
RADIOLIB_CHECK_RANGE(bw, 406.25, 1625.0, RADIOLIB_ERR_INVALID_BANDWIDTH);
RADIOLIB_CHECK_RANGE(bw, 406.25f, 1625.0f, RADIOLIB_ERR_INVALID_BANDWIDTH);
} else {
return(RADIOLIB_ERR_WRONG_MODEM);
}
if(fabsf(bw - 203.125) <= 0.001) {
if(fabsf(bw - 203.125f) <= 0.001f) {
this->bandwidth = RADIOLIB_SX128X_LORA_BW_203_125;
} else if(fabsf(bw - 406.25) <= 0.001) {
} else if(fabsf(bw - 406.25f) <= 0.001f) {
this->bandwidth = RADIOLIB_SX128X_LORA_BW_406_25;
} else if(fabsf(bw - 812.5) <= 0.001) {
} else if(fabsf(bw - 812.5f) <= 0.001f) {
this->bandwidth = RADIOLIB_SX128X_LORA_BW_812_50;
} else if(fabsf(bw - 1625.0) <= 0.001) {
} else if(fabsf(bw - 1625.0f) <= 0.001f) {
this->bandwidth = RADIOLIB_SX128X_LORA_BW_1625_00;
} else {
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
@ -877,8 +772,7 @@ int16_t SX128x::setModem(ModemType_t modem) {
int16_t SX128x::getModem(ModemType_t* modem) {
RADIOLIB_ASSERT_PTR(modem);
uint8_t packetType = getPacketType();
switch(packetType) {
switch(getPacketType()) {
case(RADIOLIB_SX128X_PACKET_TYPE_LORA):
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
@ -932,7 +826,7 @@ int16_t SX128x::setPreambleLength(uint32_t preambleLength) {
// update packet parameters
this->preambleLengthGFSK = ((preambleLength / 4) - 1) << 4;
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening));
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
}
return(RADIOLIB_ERR_WRONG_MODEM);
@ -1020,21 +914,21 @@ int16_t SX128x::setFrequencyDeviation(float freqDev) {
// set frequency deviation to lowest available setting (required for digimodes)
float newFreqDev = freqDev;
if(freqDev < 0.0) {
newFreqDev = 62.5;
if(freqDev < 0.0f) {
newFreqDev = 62.5f;
}
RADIOLIB_CHECK_RANGE(newFreqDev, 62.5, 1000.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
RADIOLIB_CHECK_RANGE(newFreqDev, 62.5f, 1000.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
// override for the lowest possible frequency deviation - required for some PhysicalLayer protocols
if(newFreqDev == 0.0) {
if(newFreqDev == 0.0f) {
this->modIndex = RADIOLIB_SX128X_BLE_GFSK_MOD_IND_0_35;
this->bitRate = RADIOLIB_SX128X_BLE_GFSK_BR_0_125_BW_0_3;
return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
}
// update modulation parameters
uint8_t modInd = (uint8_t)((8.0 * (newFreqDev / (float)this->bitRateKbps)) - 1.0);
uint8_t modInd = (uint8_t)((8.0f * (newFreqDev / (float)this->bitRateKbps)) - 1.0f);
if(modInd > RADIOLIB_SX128X_BLE_GFSK_MOD_IND_4_00) {
return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS);
}
@ -1102,14 +996,8 @@ int16_t SX128x::setSyncWord(const uint8_t* syncWord, uint8_t len) {
this->syncWordLen = len;
}
// reverse sync word byte order
uint8_t syncWordBuff[] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
for(uint8_t i = 0; i < len; i++) {
syncWordBuff[4 - i] = syncWord[i];
}
// update sync word
int16_t state = SX128x::writeRegister(RADIOLIB_SX128X_REG_SYNC_WORD_1_BYTE_4, syncWordBuff, 5);
int16_t state = SX128x::writeRegister(RADIOLIB_SX128X_REG_SYNC_WORD_1_BYTE_4 + (5 - len), const_cast<uint8_t*>(syncWord), len);
RADIOLIB_ASSERT(state);
// update packet parameters
@ -1119,7 +1007,7 @@ int16_t SX128x::setSyncWord(const uint8_t* syncWord, uint8_t len) {
/// \todo add support for multiple sync words
this->syncWordMatch = RADIOLIB_SX128X_GFSK_FLRC_SYNC_WORD_1;
}
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening));
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
}
int16_t SX128x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
@ -1129,7 +1017,7 @@ int16_t SX128x::setSyncWord(uint8_t syncWord, uint8_t controlBits) {
}
// update register
uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
const uint8_t data[2] = {(uint8_t)((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), (uint8_t)(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))};
return(writeRegister(RADIOLIB_SX128X_REG_LORA_SYNC_WORD_MSB, data, 2));
}
@ -1150,7 +1038,7 @@ int16_t SX128x::setCRC(uint8_t len, uint32_t initial, uint16_t polynomial) {
}
}
this->crcGFSK = len << 4;
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening);
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
// set initial CRC value
@ -1177,7 +1065,7 @@ int16_t SX128x::setCRC(uint8_t len, uint32_t initial, uint16_t polynomial) {
RADIOLIB_ASSERT(state);
// set initial CRC value
uint8_t data[] = { (uint8_t)((initial >> 16) & 0xFF), (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) };
const uint8_t data[] = { (uint8_t)((initial >> 16) & 0xFF), (uint8_t)((initial >> 8) & 0xFF), (uint8_t)(initial & 0xFF) };
state = writeRegister(RADIOLIB_SX128X_REG_BLE_CRC_INITIAL_MSB, data, 3);
return(state);
@ -1212,7 +1100,7 @@ int16_t SX128x::setWhitening(bool enabled) {
}
if(modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening));
return(setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType));
}
return(setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening));
}
@ -1224,7 +1112,7 @@ int16_t SX128x::setAccessAddress(uint32_t addr) {
}
// set the address
uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
const uint8_t addrBuff[] = { (uint8_t)((addr >> 24) & 0xFF), (uint8_t)((addr >> 16) & 0xFF), (uint8_t)((addr >> 8) & 0xFF), (uint8_t)(addr & 0xFF) };
return(SX128x::writeRegister(RADIOLIB_SX128X_REG_ACCESS_ADDRESS_BYTE_3, addrBuff, 4));
}
@ -1293,7 +1181,7 @@ float SX128x::getRSSI() {
uint8_t rssiSync = packetStatus[0];
float rssiMeasured = -1.0 * rssiSync/2.0;
float snr = getSNR();
if(snr <= 0.0) {
if(snr <= 0.0f) {
return(rssiMeasured - snr);
} else {
return(rssiMeasured);
@ -1310,7 +1198,7 @@ float SX128x::getRSSI(bool packet) {
// get instantaneous RSSI value
uint8_t data[3] = {0, 0, 0}; // RssiInst, Status, RFU
this->mod->SPIreadStream(RADIOLIB_SX128X_CMD_GET_RSSI_INST, data, 3);
return ((float)data[0] / (-2.0));
return ((float)data[0] / (-2.0f));
} else {
return this->getRSSI();
}
@ -1332,7 +1220,7 @@ float SX128x::getSNR() {
if(snr < 128) {
return(snr/4.0);
} else {
return((snr - 256)/4.0);
return((snr - 256)/4.0f);
}
}
@ -1361,9 +1249,9 @@ float SX128x::getFrequencyError() {
// frequency error is negative
efe |= (uint32_t) 0xFFF00000;
efe = ~efe + 1;
error = 1.55 * (float) efe / (1600.0 / (float) this->bandwidthKhz) * -1.0;
error = 1.55f * (float) efe / (1600.0f / this->bandwidthKhz) * -1.0f;
} else {
error = 1.55 * (float) efe / (1600.0 / (float) this->bandwidthKhz);
error = 1.55f * (float) efe / (1600.0f / this->bandwidthKhz);
}
return(error);
@ -1389,6 +1277,14 @@ size_t SX128x::getPacketLength(bool update, uint8_t* offset) {
return((size_t)rxBufStatus[0]);
}
int16_t SX128x::fixedPacketLengthMode(uint8_t len) {
return(setPacketMode(RADIOLIB_SX128X_GFSK_FLRC_PACKET_FIXED, len));
}
int16_t SX128x::variablePacketLengthMode(uint8_t maxLen) {
return(setPacketMode(RADIOLIB_SX128X_GFSK_FLRC_PACKET_VARIABLE, maxLen));
}
RadioLibTime_t SX128x::getTimeOnAir(size_t len) {
// check active modem
uint8_t modem = getPacketType();
@ -1436,7 +1332,7 @@ RadioLibTime_t SX128x::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->codingRateLoRa + 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->codingRateLoRa + 4);
} else {
// long interleaving - abandon hope all ye who enter here
@ -1445,7 +1341,7 @@ RadioLibTime_t SX128x::getTimeOnAir(size_t len) {
}
// get time-on-air in us
return(((uint32_t(1) << sf) / this->bandwidthKhz) * N_symbol * 1000.0);
return(((uint32_t(1) << sf) / this->bandwidthKhz) * N_symbol * 1000.0f);
} else {
return(((uint32_t)len * 8 * 1000) / this->bitRateKbps);
@ -1493,6 +1389,128 @@ int16_t SX128x::invertIQ(bool enable) {
return(setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled));
}
int16_t SX128x::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
int16_t state;
switch(mode) {
case(RADIOLIB_RADIO_MODE_RX): {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (cfg->receive.len != 0)) {
this->payloadLen = cfg->receive.len;
}
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set DIO mapping
if(cfg->receive.timeout != RADIOLIB_SX128X_RX_TIMEOUT_INF) {
cfg->receive.irqMask |= (1UL << RADIOLIB_IRQ_TIMEOUT);
}
state = setDioIrqParams(getIrqMapped(cfg->receive.irqFlags), getIrqMapped(cfg->receive.irqMask));
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// set implicit mode and expected len if applicable
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_LORA)) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, this->payloadLen, this->crcLoRa, this->invertIQEnabled);
RADIOLIB_ASSERT(state);
}
this->rxTimeout = cfg->receive.timeout;
} break;
case(RADIOLIB_RADIO_MODE_TX): {
// check packet length
if(cfg->transmit.len > RADIOLIB_SX128X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// set packet Length
uint8_t modem = getPacketType();
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
state = setPacketParamsLoRa(this->preambleLengthLoRa, this->headerType, cfg->transmit.len, this->crcLoRa, this->invertIQEnabled);
} else if((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC)) {
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, this->packetType, cfg->transmit.len);
} else if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
state = setPacketParamsBLE(this->connectionState, this->crcBLE, this->bleTestPayload, this->whitening);
} else {
return(RADIOLIB_ERR_WRONG_MODEM);
}
RADIOLIB_ASSERT(state);
// update output power
state = setTxParams(this->power);
RADIOLIB_ASSERT(state);
// set buffer pointers
state = setBufferBaseAddress();
RADIOLIB_ASSERT(state);
// write packet to buffer
if(modem == RADIOLIB_SX128X_PACKET_TYPE_BLE) {
// first 2 bytes of BLE payload are PDU header
state = writeBuffer(cfg->transmit.data, cfg->transmit.len, 2);
RADIOLIB_ASSERT(state);
} else {
state = writeBuffer(cfg->transmit.data, cfg->transmit.len);
RADIOLIB_ASSERT(state);
}
// set DIO mapping
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_TX_DONE | RADIOLIB_SX128X_IRQ_RX_TX_TIMEOUT, RADIOLIB_SX128X_IRQ_TX_DONE);
RADIOLIB_ASSERT(state);
// clear interrupt flags
state = clearIrqStatus();
RADIOLIB_ASSERT(state);
} break;
default:
return(RADIOLIB_ERR_UNSUPPORTED);
}
this->stagedMode = mode;
return(state);
}
int16_t SX128x::launchMode() {
int16_t state;
switch(this->stagedMode) {
case(RADIOLIB_RADIO_MODE_RX): {
this->mod->setRfSwitchState(Module::MODE_RX);
state = setRx(this->rxTimeout);
RADIOLIB_ASSERT(state);
} break;
case(RADIOLIB_RADIO_MODE_TX): {
this->mod->setRfSwitchState(Module::MODE_TX);
state = setTx(RADIOLIB_SX128X_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);
}
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void SX128x::setDirectAction(void (*func)(void)) {
// SX128x is unable to perform direct mode reception
@ -1517,7 +1535,7 @@ uint8_t SX128x::getStatus() {
return(data);
}
int16_t SX128x::writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
int16_t SX128x::writeRegister(uint16_t addr, const uint8_t* data, uint8_t numBytes) {
this->mod->SPIwriteRegisterBurst(addr, data, numBytes);
return(RADIOLIB_ERR_NONE);
}
@ -1531,23 +1549,23 @@ int16_t SX128x::readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes) {
return(state);
}
int16_t SX128x::writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
uint8_t cmd[] = { RADIOLIB_SX128X_CMD_WRITE_BUFFER, offset };
int16_t SX128x::writeBuffer(const uint8_t* data, uint8_t numBytes, uint8_t offset) {
const uint8_t cmd[] = { RADIOLIB_SX128X_CMD_WRITE_BUFFER, offset };
return(this->mod->SPIwriteStream(cmd, 2, data, numBytes));
}
int16_t SX128x::readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset) {
uint8_t cmd[] = { RADIOLIB_SX128X_CMD_READ_BUFFER, offset };
const uint8_t cmd[] = { RADIOLIB_SX128X_CMD_READ_BUFFER, offset };
return(this->mod->SPIreadStream(cmd, 2, data, numBytes));
}
int16_t SX128x::setTx(uint16_t periodBaseCount, uint8_t periodBase) {
uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
const uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_TX, data, 3));
}
int16_t SX128x::setRx(uint16_t periodBaseCount, uint8_t periodBase) {
uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
const uint8_t data[] = { periodBase, (uint8_t)((periodBaseCount >> 8) & 0xFF), (uint8_t)(periodBaseCount & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RX, data, 3));
}
@ -1567,42 +1585,42 @@ uint8_t SX128x::getPacketType() {
}
int16_t SX128x::setRfFrequency(uint32_t frf) {
uint8_t data[] = { (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) };
const uint8_t data[] = { (uint8_t)((frf >> 16) & 0xFF), (uint8_t)((frf >> 8) & 0xFF), (uint8_t)(frf & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RF_FREQUENCY, data, 3));
}
int16_t SX128x::setTxParams(uint8_t pwr, uint8_t rampTime) {
uint8_t data[] = { pwr, rampTime };
const uint8_t data[] = { pwr, rampTime };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_TX_PARAMS, data, 2));
}
int16_t SX128x::setBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress) {
uint8_t data[] = { txBaseAddress, rxBaseAddress };
const uint8_t data[] = { txBaseAddress, rxBaseAddress };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_BUFFER_BASE_ADDRESS, data, 2));
}
int16_t SX128x::setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3) {
uint8_t data[] = { modParam1, modParam2, modParam3 };
const uint8_t data[] = { modParam1, modParam2, modParam3 };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_MODULATION_PARAMS, data, 3));
}
int16_t SX128x::setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncLen, uint8_t syncMatch, uint8_t crcLen, uint8_t whiten, uint8_t payLen, uint8_t hdrType) {
uint8_t data[] = { preambleLen, syncLen, syncMatch, hdrType, payLen, crcLen, whiten };
int16_t SX128x::setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncLen, uint8_t syncMatch, uint8_t crcLen, uint8_t whiten, uint8_t hdrType, uint8_t payLen) {
const uint8_t data[] = { preambleLen, syncLen, syncMatch, hdrType, payLen, crcLen, whiten };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
}
int16_t SX128x::setPacketParamsBLE(uint8_t connState, uint8_t crcLen, uint8_t bleTest, uint8_t whiten) {
uint8_t data[] = { connState, crcLen, bleTest, whiten, 0x00, 0x00, 0x00 };
const uint8_t data[] = { connState, crcLen, bleTest, whiten, 0x00, 0x00, 0x00 };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
}
int16_t SX128x::setPacketParamsLoRa(uint8_t preambleLen, uint8_t hdrType, uint8_t payLen, uint8_t crc, uint8_t invIQ) {
uint8_t data[] = { preambleLen, hdrType, payLen, crc, invIQ, 0x00, 0x00 };
const uint8_t data[] = { preambleLen, hdrType, payLen, crc, invIQ, 0x00, 0x00 };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_PARAMS, data, 7));
}
int16_t SX128x::setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask) {
uint8_t data[] = { (uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
const uint8_t data[] = { (uint8_t)((irqMask >> 8) & 0xFF), (uint8_t)(irqMask & 0xFF),
(uint8_t)((dio1Mask >> 8) & 0xFF), (uint8_t)(dio1Mask & 0xFF),
(uint8_t)((dio2Mask >> 8) & 0xFF), (uint8_t)(dio2Mask & 0xFF),
(uint8_t)((dio3Mask >> 8) & 0xFF), (uint8_t)(dio3Mask & 0xFF) };
@ -1616,20 +1634,35 @@ uint16_t SX128x::getIrqStatus() {
}
int16_t SX128x::clearIrqStatus(uint16_t clearIrqParams) {
uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
const uint8_t data[] = { (uint8_t)((clearIrqParams >> 8) & 0xFF), (uint8_t)(clearIrqParams & 0xFF) };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_CLEAR_IRQ_STATUS, data, 2));
}
int16_t SX128x::setRangingRole(uint8_t role) {
uint8_t data[] = { role };
const uint8_t data[] = { role };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_RANGING_ROLE, data, 1));
}
int16_t SX128x::setPacketType(uint8_t type) {
uint8_t data[] = { type };
const uint8_t data[] = { type };
return(this->mod->SPIwriteStream(RADIOLIB_SX128X_CMD_SET_PACKET_TYPE, data, 1));
}
int16_t SX128x::setPacketMode(uint8_t mode, uint8_t len) {
// check active modem
if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set requested packet mode
int16_t state = setPacketParamsGFSK(this->preambleLengthGFSK, this->syncWordLen, this->syncWordMatch, this->crcGFSK, this->whitening, mode, len);
RADIOLIB_ASSERT(state);
// update cached value
this->packetType = mode;
return(state);
}
int16_t SX128x::setHeaderType(uint8_t hdrType, size_t len) {
// check active modem
uint8_t modem = getPacketType();

View file

@ -12,7 +12,7 @@
// SX128X physical layer properties
#define RADIOLIB_SX128X_FREQUENCY_STEP_SIZE 198.3642578
#define RADIOLIB_SX128X_MAX_PACKET_LENGTH 255
#define RADIOLIB_SX128X_CRYSTAL_FREQ 52.0
#define RADIOLIB_SX128X_CRYSTAL_FREQ 52.0f
#define RADIOLIB_SX128X_DIV_EXPONENT 18
// SX128X SPI commands
@ -354,6 +354,7 @@ class SX128x: public PhysicalLayer {
using PhysicalLayer::transmit;
using PhysicalLayer::receive;
using PhysicalLayer::startTransmit;
using PhysicalLayer::startReceive;
using PhysicalLayer::readData;
/*!
@ -530,16 +531,6 @@ class SX128x: 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. Unsupported, compatibility only.
\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
@ -554,20 +545,6 @@ class SX128x: public PhysicalLayer {
*/
int16_t startReceive() override;
/*!
\brief Interrupt-driven receive method. DIO1 will be activated when full packet is received.
\param timeout Raw timeout value, expressed as multiples of 15.625 us. Defaults to
RADIOLIB_SX128X_RX_TIMEOUT_INF for infinite timeout (Rx continuous mode),
set to RADIOLIB_SX128X_RX_TIMEOUT_NONE for no timeout (Rx single mode).
If timeout other than infinite is set, signal will be generated on DIO1.
\param irqFlags Sets the IRQ flags, defaults to RX done, RX timeout, CRC error and header error.
\param irqMask Sets the mask of IRQ flags that will trigger DIO1, defaults to RX done.
\param len Only for PhysicalLayer compatibility, not used.
\returns \ref status_codes
*/
int16_t startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*!
\brief Reads the current IRQ status.
\returns IRQ status bits
@ -818,6 +795,20 @@ class SX128x: public PhysicalLayer {
*/
size_t getPacketLength(bool update, uint8_t* offset);
/*!
\brief Set modem in fixed packet length mode. Available in GFSK mode only.
\param len Packet length.
\returns \ref status_codes
*/
int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SX128X_MAX_PACKET_LENGTH);
/*!
\brief Set modem in variable packet length mode. Available in GFSK mode only.
\param maxLen Maximum packet length.
\returns \ref status_codes
*/
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SX128X_MAX_PACKET_LENGTH);
/*!
\brief Get expected time-on-air for a given size of payload.
\param len Payload length in bytes.
@ -863,6 +854,12 @@ class SX128x: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t invertIQ(bool enable) override;
/*! \copydoc PhysicalLayer::stageMode */
int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) override;
/*! \copydoc PhysicalLayer::launchMode */
int16_t launchMode() override;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
/*!
@ -890,9 +887,9 @@ class SX128x: public PhysicalLayer {
// SX128x SPI command implementations
uint8_t getStatus();
int16_t writeRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t writeRegister(uint16_t addr, const uint8_t* data, uint8_t numBytes);
int16_t readRegister(uint16_t addr, uint8_t* data, uint8_t numBytes);
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t writeBuffer(const uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t readBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
int16_t setTx(uint16_t periodBaseCount = RADIOLIB_SX128X_TX_TIMEOUT_NONE, uint8_t periodBase = RADIOLIB_SX128X_PERIOD_BASE_15_625_US);
int16_t setRx(uint16_t periodBaseCount, uint8_t periodBase = RADIOLIB_SX128X_PERIOD_BASE_15_625_US);
@ -902,7 +899,7 @@ class SX128x: public PhysicalLayer {
int16_t setTxParams(uint8_t pwr, uint8_t rampTime = RADIOLIB_SX128X_PA_RAMP_10_US);
int16_t setBufferBaseAddress(uint8_t txBaseAddress = 0x00, uint8_t rxBaseAddress = 0x00);
int16_t setModulationParams(uint8_t modParam1, uint8_t modParam2, uint8_t modParam3);
int16_t setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncLen, uint8_t syncMatch, uint8_t crcLen, uint8_t whiten, uint8_t payLen = 0xFF, uint8_t hdrType = RADIOLIB_SX128X_GFSK_FLRC_PACKET_VARIABLE);
int16_t setPacketParamsGFSK(uint8_t preambleLen, uint8_t syncLen, uint8_t syncMatch, uint8_t crcLen, uint8_t whiten, uint8_t hdrType, uint8_t payLen = 0xFF);
int16_t setPacketParamsBLE(uint8_t connState, uint8_t crcLen, uint8_t bleTest, uint8_t whiten);
int16_t setPacketParamsLoRa(uint8_t preambleLen, uint8_t hdrType, uint8_t payLen, uint8_t crc, uint8_t invIQ = RADIOLIB_SX128X_LORA_IQ_STANDARD);
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX128X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX128X_IRQ_NONE);
@ -920,6 +917,7 @@ class SX128x: public PhysicalLayer {
// common parameters
uint8_t power = 0;
uint32_t rxTimeout = 0;
// cached LoRa parameters
uint8_t invertIQEnabled = RADIOLIB_SX128X_LORA_IQ_STANDARD;
@ -929,6 +927,7 @@ class SX128x: public PhysicalLayer {
uint16_t bitRateKbps = 0;
uint8_t bitRate = 0, modIndex = 0, shaping = 0;
uint8_t preambleLengthGFSK = 0, syncWordLen = 0, syncWordMatch = 0, crcGFSK = 0, whitening = 0;
uint8_t packetType = RADIOLIB_SX128X_GFSK_FLRC_PACKET_VARIABLE;
// cached FLRC parameters
uint8_t codingRateFLRC = 0;
@ -937,6 +936,7 @@ class SX128x: public PhysicalLayer {
uint8_t connectionState = 0, crcBLE = 0, bleTestPayload = 0;
int16_t config(uint8_t modem);
int16_t setPacketMode(uint8_t mode, uint8_t len);
int16_t setHeaderType(uint8_t hdrType, size_t len = 0xFF);
};

View file

@ -22,7 +22,7 @@ int16_t Si4430::begin(float freq, float br, float freqDev, float rxBw, int8_t po
}
int16_t Si4430::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 900.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 900.0f, 960.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency
return(Si443x::setFrequencyRaw(freq));

View file

@ -35,7 +35,7 @@ class Si4430: public Si4432 {
\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 = 181.1, 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 = 181.1, int8_t power = 10, uint8_t preambleLen = 16) override;
// configuration methods

View file

@ -35,7 +35,7 @@ class Si4431: public Si4432 {
\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 = 181.1, 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 = 181.1, int8_t power = 10, uint8_t preambleLen = 16) override;
// configuration methods

View file

@ -22,7 +22,7 @@ int16_t Si4432::begin(float freq, float br, float freqDev, float rxBw, int8_t po
}
int16_t Si4432::setFrequency(float freq) {
RADIOLIB_CHECK_RANGE(freq, 240.0, 930.0, RADIOLIB_ERR_INVALID_FREQUENCY);
RADIOLIB_CHECK_RANGE(freq, 240.0f, 930.0f, RADIOLIB_ERR_INVALID_FREQUENCY);
// set frequency
return(Si443x::setFrequencyRaw(freq));

View file

@ -35,7 +35,7 @@ class Si4432: public Si443x {
\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 = 181.1, 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 = 181.1, int8_t power = 10, uint8_t preambleLen = 16);
// configuration methods

View file

@ -2,7 +2,9 @@
#include <math.h>
#if !RADIOLIB_EXCLUDE_SI443X
Si443x::Si443x(Module* mod) : PhysicalLayer(RADIOLIB_SI443X_FREQUENCY_STEP_SIZE, RADIOLIB_SI443X_MAX_PACKET_LENGTH) {
Si443x::Si443x(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_SI443X_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_SI443X_MAX_PACKET_LENGTH;
this->mod = mod;
}
@ -26,7 +28,7 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen)
this->mod->SPIwriteRegister(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_SOFTWARE_RESET);
// clear POR interrupt
clearIRQFlags();
clearIrqStatus();
// configure settings not accessible by API
int16_t state = config();
@ -52,10 +54,13 @@ int16_t Si443x::begin(float br, float freqDev, float rxBw, uint8_t preambleLen)
state = packetMode();
RADIOLIB_ASSERT(state);
state = setDataShaping(0);
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
state = setEncoding(0);
state = setEncoding(RADIOLIB_ENCODING_NRZ);
RADIOLIB_ASSERT(state);
state = setCRC(true);
RADIOLIB_ASSERT(state);
state = variablePacketLengthMode();
@ -94,7 +99,7 @@ int16_t Si443x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
int16_t Si443x::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_SI443X_MAX_PACKET_LENGTH*400.0);
RadioLibTime_t timeout = 500 + (1.0f/(this->bitRate))*(RADIOLIB_SI443X_MAX_PACKET_LENGTH*400.0f);
// start reception
int16_t state = startReceive();
@ -105,7 +110,7 @@ int16_t Si443x::receive(uint8_t* data, size_t len) {
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
if(this->mod->hal->millis() - start > timeout) {
standby();
clearIRQFlags();
clearIrqStatus();
return(RADIOLIB_ERR_RX_TIMEOUT);
}
}
@ -153,7 +158,7 @@ int16_t Si443x::transmitDirect(uint32_t frf) {
// check high/low band
uint8_t bandSelect = RADIOLIB_SI443X_BAND_SELECT_LOW;
uint8_t freqBand = (newFreq / 10) - 24;
if(newFreq >= 480.0) {
if(newFreq >= 480.0f) {
bandSelect = RADIOLIB_SI443X_BAND_SELECT_HIGH;
freqBand = (newFreq / 20) - 24;
}
@ -241,7 +246,7 @@ int16_t Si443x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_2, RADIOLIB_SI443X_TX_FIFO_CLEAR, 0, 0);
// clear interrupt flags
clearIRQFlags();
clearIrqStatus();
// set packet length
if (this->packetLengthConfig == RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF) {
@ -269,7 +274,7 @@ int16_t Si443x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
int16_t Si443x::finishTransmit() {
// clear interrupt flags
clearIRQFlags();
clearIrqStatus();
// set mode to standby to disable transmitter/RF switch
return(standby());
@ -285,13 +290,14 @@ int16_t Si443x::startReceive() {
this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_2, RADIOLIB_SI443X_RX_FIFO_CLEAR, 1, 1);
// clear interrupt flags
clearIRQFlags();
clearIrqStatus();
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_RX);
// set interrupt mapping
this->mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_VALID_PACKET_RECEIVED_ENABLED | RADIOLIB_SI443X_CRC_ERROR_ENABLED);
uint8_t irq = this->crcEnabled ? (RADIOLIB_SI443X_VALID_PACKET_RECEIVED_ENABLED | RADIOLIB_SI443X_CRC_ERROR_ENABLED) : RADIOLIB_SI443X_VALID_PACKET_RECEIVED_ENABLED;
this->mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, irq);
this->mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_2, 0x00);
// set mode to receive
@ -309,8 +315,15 @@ int16_t Si443x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMa
}
int16_t Si443x::readData(uint8_t* data, size_t len) {
// clear interrupt flags
clearIRQFlags();
// read interrupt flags
uint32_t irq = getIrqFlags();
// check integrity CRC
// Si443x does not have the option to keep the data after CRC failed
// reading the FIFO will just repeat the first byte (see https://github.com/jgromes/RadioLib/issues/1430)
if(irq & RADIOLIB_SI443X_CRC_ERROR_INTERRUPT) {
return(RADIOLIB_ERR_CRC_MISMATCH);
}
// get packet length
size_t length = getPacketLength();
@ -337,25 +350,25 @@ int16_t Si443x::readData(uint8_t* data, size_t len) {
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIRQFlags();
clearIrqStatus();
return(RADIOLIB_ERR_NONE);
}
int16_t Si443x::setBitRate(float br) {
RADIOLIB_CHECK_RANGE(br, 0.123, 256.0, RADIOLIB_ERR_INVALID_BIT_RATE);
RADIOLIB_CHECK_RANGE(br, 0.123f, 256.0f, RADIOLIB_ERR_INVALID_BIT_RATE);
// check high data rate
uint8_t dataRateMode = RADIOLIB_SI443X_LOW_DATA_RATE_MODE;
uint8_t exp = 21;
if(br >= 30.0) {
if(br >= 30.0f) {
// bit rate above 30 kbps
dataRateMode = RADIOLIB_SI443X_HIGH_DATA_RATE_MODE;
exp = 16;
}
// calculate raw data rate value
uint16_t txDr = (br * ((uint32_t)1 << exp)) / 1000.0;
uint16_t txDr = (br * ((uint32_t)1 << exp)) / 1000.0f;
// update registers
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_MODULATION_MODE_CONTROL_1, dataRateMode, 5, 5);
@ -376,14 +389,14 @@ int16_t Si443x::setBitRate(float br) {
int16_t Si443x::setFrequencyDeviation(float freqDev) {
// set frequency deviation to lowest available setting (required for digimodes)
float newFreqDev = freqDev;
if(freqDev < 0.0) {
newFreqDev = 0.625;
if(freqDev < 0.0f) {
newFreqDev = 0.625f;
}
RADIOLIB_CHECK_RANGE(newFreqDev, 0.625, 320.0, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
RADIOLIB_CHECK_RANGE(newFreqDev, 0.625f, 320.0f, RADIOLIB_ERR_INVALID_FREQUENCY_DEVIATION);
// calculate raw frequency deviation value
uint16_t fdev = (uint16_t)(newFreqDev / 0.625);
uint16_t fdev = (uint16_t)(newFreqDev / 0.625f);
// update registers
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_MODULATION_MODE_CONTROL_2, (uint8_t)((fdev & 0x0100) >> 6), 2, 2);
@ -397,7 +410,7 @@ int16_t Si443x::setFrequencyDeviation(float freqDev) {
}
int16_t Si443x::setRxBandwidth(float rxBw) {
RADIOLIB_CHECK_RANGE(rxBw, 2.6, 620.7, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
RADIOLIB_CHECK_RANGE(rxBw, 2.6f, 620.7f, RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
// decide which approximation to use for decimation rate and filter tap calculation
uint8_t bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_OFF;
@ -405,84 +418,84 @@ int16_t Si443x::setRxBandwidth(float rxBw) {
uint8_t filterSet = RADIOLIB_SI443X_IF_FILTER_COEFF_SET;
// this is the "well-behaved" section - can be linearly approximated
if((rxBw >= 2.6) && (rxBw <= 4.5)) {
if((rxBw >= 2.6f) && (rxBw <= 4.5f)) {
decRate = 5;
filterSet = ((rxBw - 2.1429)/0.3250 + 0.5);
} else if((rxBw > 4.5) && (rxBw <= 8.8)) {
filterSet = ((rxBw - 2.1429f)/0.3250f + 0.5f);
} else if((rxBw > 4.5f) && (rxBw <= 8.8f)) {
decRate = 4;
filterSet = ((rxBw - 3.9857)/0.6643 + 0.5);
} else if((rxBw > 8.8) && (rxBw <= 17.5)) {
filterSet = ((rxBw - 3.9857f)/0.6643f + 0.5f);
} else if((rxBw > 8.8f) && (rxBw <= 17.5f)) {
decRate = 3;
filterSet = ((rxBw - 7.6714)/1.3536 + 0.5);
} else if((rxBw > 17.5) && (rxBw <= 34.7)) {
filterSet = ((rxBw - 7.6714f)/1.3536f + 0.5f);
} else if((rxBw > 17.5f) && (rxBw <= 34.7f)) {
decRate = 2;
filterSet = ((rxBw - 15.2000)/2.6893 + 0.5);
} else if((rxBw > 34.7) && (rxBw <= 69.2)) {
filterSet = ((rxBw - 15.2000f)/2.6893f + 0.5f);
} else if((rxBw > 34.7f) && (rxBw <= 69.2f)) {
decRate = 1;
filterSet = ((rxBw - 30.2430)/5.3679 + 0.5);
} else if((rxBw > 69.2) && (rxBw <= 137.9)) {
filterSet = ((rxBw - 30.2430f)/5.3679f + 0.5f);
} else if((rxBw > 69.2f) && (rxBw <= 137.9f)) {
decRate = 0;
filterSet = ((rxBw - 60.286)/10.7000 + 0.5);
filterSet = ((rxBw - 60.286f)/10.7000f + 0.5f);
// this is the "Lord help thee who tread 'ere" section - no way to approximate this mess
/// \todo float tolerance equality as macro?
} else if(fabsf(rxBw - 142.8) <= 0.001) {
} else if(fabsf(rxBw - 142.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 1;
filterSet = 4;
} else if(fabsf(rxBw - 167.8) <= 0.001) {
} else if(fabsf(rxBw - 167.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 1;
filterSet = 5;
} else if(fabsf(rxBw - 181.1) <= 0.001) {
} else if(fabsf(rxBw - 181.1f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 1;
filterSet = 6;
} else if(fabsf(rxBw - 191.5) <= 0.001) {
} else if(fabsf(rxBw - 191.5f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 15;
} else if(fabsf(rxBw - 225.1) <= 0.001) {
} else if(fabsf(rxBw - 225.1f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 1;
} else if(fabsf(rxBw - 248.8) <= 0.001) {
} else if(fabsf(rxBw - 248.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 2;
} else if(fabsf(rxBw - 269.3) <= 0.001) {
} else if(fabsf(rxBw - 269.3f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 3;
} else if(fabsf(rxBw - 284.8) <= 0.001) {
} else if(fabsf(rxBw - 284.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 4;
} else if(fabsf(rxBw -335.5) <= 0.001) {
} else if(fabsf(rxBw -335.5f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 8;
} else if(fabsf(rxBw - 391.8) <= 0.001) {
} else if(fabsf(rxBw - 391.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 9;
} else if(fabsf(rxBw - 420.2) <= 0.001) {
} else if(fabsf(rxBw - 420.2f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 10;
} else if(fabsf(rxBw - 468.4) <= 0.001) {
} else if(fabsf(rxBw - 468.4f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 11;
} else if(fabsf(rxBw - 518.8) <= 0.001) {
} else if(fabsf(rxBw - 518.8f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 12;
} else if(fabsf(rxBw - 577.0) <= 0.001) {
} else if(fabsf(rxBw - 577.0f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 13;
} else if(fabsf(rxBw - 620.7) <= 0.001) {
} else if(fabsf(rxBw - 620.7f) <= 0.001f) {
bypass = RADIOLIB_SI443X_BYPASS_DEC_BY_3_ON;
decRate = 0;
filterSet = 14;
@ -633,6 +646,25 @@ int16_t Si443x::variablePacketLengthMode(uint8_t maxLen) {
return(Si443x::setPacketMode(RADIOLIB_SI443X_FIXED_PACKET_LENGTH_OFF, maxLen));
}
uint32_t Si443x::getIrqFlags() {
uint8_t data[] = { 0x00, 0x00 };
this->mod->SPIreadRegisterBurst(RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1, 2, data);
return(((uint32_t)(data[0]) << 8) | data[1]);
}
int16_t Si443x::clearIrqFlags(uint32_t irq) {
(void)irq;
(void)getIrqFlags();
return(RADIOLIB_ERR_NONE);
}
int16_t Si443x::setCRC(bool enable, bool mode) {
this->crcEnabled = enable;
uint8_t crcEn = enable ? RADIOLIB_SI443X_CRC_ON : RADIOLIB_SI443X_CRC_OFF;
uint8_t crcCfg = mode ? RADIOLIB_SI443X_CRC_IBM_CRC16 : RADIOLIB_SI443X_CRC_CCITT;
return(this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_DATA_ACCESS_CONTROL, crcEn | crcCfg, 2, 0));
}
Module* Si443x::getMod() {
return(this->mod);
}
@ -647,7 +679,7 @@ int16_t Si443x::setFrequencyRaw(float newFreq) {
uint8_t freqBand = (newFreq / 10) - 24;
uint8_t afcLimiter = 80;
this->frequency = newFreq;
if(newFreq >= 480.0) {
if(newFreq >= 480.0f) {
bandSelect = RADIOLIB_SI443X_BAND_SELECT_HIGH;
freqBand = (newFreq / 20) - 24;
afcLimiter = 40;
@ -705,9 +737,8 @@ bool Si443x::findChip() {
return(flagFound);
}
void Si443x::clearIRQFlags() {
uint8_t buff[2];
this->mod->SPIreadRegisterBurst(RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1, 2, buff);
void Si443x::clearIrqStatus() {
(void)getIrqFlags();
}
void Si443x::clearFIFO(size_t count) {
@ -757,17 +788,17 @@ int16_t Si443x::updateClockRecovery() {
ndec = (uint16_t)1 << ndecExp;
} else {
ndecExp *= -1;
ndec = 1.0/(float)((uint16_t)1 << ndecExp);
ndec = 1.0f/(float)((uint16_t)1 << ndecExp);
}
float rxOsr = ((float)(500 * (1 + 2*bypass))) / (ndec * this->bitRate * ((float)(1 + manch)));
uint32_t ncoOff = (this->bitRate * (1 + manch) * ((uint32_t)(1) << (20 + decRate))) / (500 * (1 + 2*bypass));
uint16_t crGain = 2 + (((float)(65536.0 * (1 + manch)) * this->bitRate) / (rxOsr * (this->frequencyDev / 0.625)));
uint16_t crGain = 2 + (((float)(65536.0f * (1 + manch)) * this->bitRate) / (rxOsr * (this->frequencyDev / 0.625f)));
uint16_t rxOsr_fixed = (uint16_t)rxOsr;
// print that whole mess
RADIOLIB_DEBUG_BASIC_PRINTLN("%X\n%X\n%X", bypass, decRate, manch);
RADIOLIB_DEBUG_BASIC_PRINT_FLOAT(rxOsr, 2);
RADIOLIB_DEBUG_BASIC_PRINTLN("\t%d\t%X\n%lu\t%lX\n%d\t%X", rxOsr_fixed, rxOsr_fixed, (long unsigned int)ncoOff, (long unsigned int)ncoOff, crGain, crGain);
RADIOLIB_DEBUG_BASIC_PRINTLN("%X %X %X", bypass, decRate, manch);
RADIOLIB_DEBUG_BASIC_PRINT_FLOAT((double)rxOsr, 2);
RADIOLIB_DEBUG_BASIC_PRINTLN("\t%d\t%X" RADIOLIB_LINE_FEED "%lu\t%lX" RADIOLIB_LINE_FEED "%d\t%X", rxOsr_fixed, rxOsr_fixed, (long unsigned int)ncoOff, (long unsigned int)ncoOff, crGain, crGain);
// update oversampling ratio
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_SI443X_REG_CLOCK_REC_OFFSET_2, (uint8_t)((rxOsr_fixed & 0x0700) >> 3), 7, 5);

View file

@ -128,19 +128,19 @@
#define RADIOLIB_SI443X_IDLE 0b00000000 // 1 0 idle
// RADIOLIB_SI443X_REG_INTERRUPT_STATUS_1
#define RADIOLIB_SI443X_FIFO_LEVEL_ERROR_INTERRUPT 0b10000000 // 7 7 Tx/Rx FIFO overflow or underflow
#define RADIOLIB_SI443X_TX_FIFO_ALMOST_FULL_INTERRUPT 0b01000000 // 6 6 Tx FIFO almost full
#define RADIOLIB_SI443X_TX_FIFO_ALMOST_EMPTY_INTERRUPT 0b00100000 // 5 5 Tx FIFO almost empty
#define RADIOLIB_SI443X_RX_FIFO_ALMOST_FULL_INTERRUPT 0b00010000 // 4 4 Rx FIFO almost full
#define RADIOLIB_SI443X_EXTERNAL_INTERRUPT 0b00001000 // 3 3 external interrupt occurred on GPIOx
#define RADIOLIB_SI443X_PACKET_SENT_INTERRUPT 0b00000100 // 2 2 packet transmission done
#define RADIOLIB_SI443X_VALID_PACKET_RECEIVED_INTERRUPT 0b00000010 // 1 1 valid packet has been received
#define RADIOLIB_SI443X_CRC_ERROR_INTERRUPT 0b00000001 // 0 0 CRC failed
#define RADIOLIB_SI443X_FIFO_LEVEL_ERROR_INTERRUPT 0b10000000 << 8 // 7 7 Tx/Rx FIFO overflow or underflow
#define RADIOLIB_SI443X_TX_FIFO_ALMOST_FULL_INTERRUPT 0b01000000 << 8 // 6 6 Tx FIFO almost full
#define RADIOLIB_SI443X_TX_FIFO_ALMOST_EMPTY_INTERRUPT 0b00100000 << 8 // 5 5 Tx FIFO almost empty
#define RADIOLIB_SI443X_RX_FIFO_ALMOST_FULL_INTERRUPT 0b00010000 << 8 // 4 4 Rx FIFO almost full
#define RADIOLIB_SI443X_EXTERNAL_INTERRUPT 0b00001000 << 8 // 3 3 external interrupt occurred on GPIOx
#define RADIOLIB_SI443X_PACKET_SENT_INTERRUPT 0b00000100 << 8 // 2 2 packet transmission done
#define RADIOLIB_SI443X_VALID_PACKET_RECEIVED_INTERRUPT 0b00000010 << 8 // 1 1 valid packet has been received
#define RADIOLIB_SI443X_CRC_ERROR_INTERRUPT 0b00000001 << 8 // 0 0 CRC failed
// RADIOLIB_SI443X_REG_INTERRUPT_STATUS_2
#define RADIOLIB_SI443X_SYNC_WORD_DETECTED_INTERRUPT 0b10000000 // 7 7 sync word has been detected
#define RADIOLIB_SI443X_VALID_RADIOLIB_PREAMBLE_DETECTED_INTERRUPT 0b01000000 // 6 6 valid preamble has been detected
#define RADIOLIB_SI443X_INVALID_RADIOLIB_PREAMBLE_DETECTED_INTERRUPT 0b00100000 // 5 5 invalid preamble has been detected
#define RADIOLIB_SI443X_VALID_PREAMBLE_DETECTED_INTERRUPT 0b01000000 // 6 6 valid preamble has been detected
#define RADIOLIB_SI443X_INVALID_PREAMBLE_DETECTED_INTERRUPT 0b00100000 // 5 5 invalid preamble has been detected
#define RADIOLIB_SI443X_RSSI_INTERRUPT 0b00010000 // 4 4 RSSI exceeded programmed threshold
#define RADIOLIB_SI443X_WAKEUP_TIMER_INTERRUPT 0b00001000 // 3 3 wake-up timer expired
#define RADIOLIB_SI443X_LOW_BATTERY_INTERRUPT 0b00000100 // 2 2 low battery detected
@ -159,8 +159,8 @@
// RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_2
#define RADIOLIB_SI443X_SYNC_WORD_DETECTED_ENABLED 0b10000000 // 7 7 sync word interrupt enabled
#define RADIOLIB_SI443X_VALID_RADIOLIB_PREAMBLE_DETECTED_ENABLED 0b01000000 // 6 6 valid preamble interrupt enabled
#define RADIOLIB_SI443X_INVALID_RADIOLIB_PREAMBLE_DETECTED_ENABLED 0b00100000 // 5 5 invalid preamble interrupt enabled
#define RADIOLIB_SI443X_VALID_PREAMBLE_DETECTED_ENABLED 0b01000000 // 6 6 valid preamble interrupt enabled
#define RADIOLIB_SI443X_INVALID_PREAMBLE_DETECTED_ENABLED 0b00100000 // 5 5 invalid preamble interrupt enabled
#define RADIOLIB_SI443X_RSSI_ENABLED 0b00010000 // 4 4 RSSI exceeded programmed threshold interrupt enabled
#define RADIOLIB_SI443X_WAKEUP_TIMER_ENABLED 0b00001000 // 3 3 wake-up timer interrupt enabled
#define RADIOLIB_SI443X_LOW_BATTERY_ENABLED 0b00000100 // 2 2 low battery interrupt enabled
@ -810,18 +810,39 @@ class Si443x: public PhysicalLayer {
#endif
/*!
\brief Set modem in fixed packet length mode.
\param len Packet length.
\returns \ref status_codes
*/
int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SI443X_MAX_PACKET_LENGTH);
\brief Set modem in fixed packet length mode.
\param len Packet length.
\returns \ref status_codes
*/
int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_SI443X_MAX_PACKET_LENGTH);
/*!
\brief Set modem in variable packet length mode.
\param maxLen Maximum packet length.
\brief Set modem in variable packet length mode.
\param maxLen Maximum packet length.
\returns \ref status_codes
*/
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SI443X_MAX_PACKET_LENGTH);
*/
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SI443X_MAX_PACKET_LENGTH);
/*!
\brief Read currently active IRQ flags.
\returns IRQ flags.
*/
uint32_t getIrqFlags() override;
/*!
\brief Clear interrupt on a specific IRQ bit (e.g. RxTimeout, CadDone).
\param irq Module-specific IRQ flags.
\returns \ref status_codes
*/
int16_t clearIrqFlags(uint32_t irq) override;
/*!
\brief Enables/disables CRC of transmitted or received packets.
\param enable Enable (true) or disable (false) CRC.
\param mode Set CRC mode
\returns \ref status_codes
*/
int16_t setCRC(bool enable, bool mode = false);
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected:
@ -845,9 +866,10 @@ class Si443x: public PhysicalLayer {
size_t packetLength = 0;
bool packetLengthQueried = false;
uint8_t packetLengthConfig = RADIOLIB_SI443X_FIXED_PACKET_LENGTH_ON;
bool crcEnabled = false;
bool findChip();
void clearIRQFlags();
void clearIrqStatus();
void clearFIFO(size_t count);
int16_t config();
int16_t updateClockRecovery();

View file

@ -2,7 +2,9 @@
#include <string.h>
#if !RADIOLIB_EXCLUDE_NRF24
nRF24::nRF24(Module* mod) : PhysicalLayer(RADIOLIB_NRF24_FREQUENCY_STEP_SIZE, RADIOLIB_NRF24_MAX_PACKET_LENGTH) {
nRF24::nRF24(Module* mod) : PhysicalLayer() {
this->freqStep = RADIOLIB_NRF24_FREQUENCY_STEP_SIZE;
this->maxPacketLength = RADIOLIB_NRF24_MAX_PACKET_LENGTH;
this->mod = mod;
}
@ -387,7 +389,7 @@ int16_t nRF24::setAddressWidth(uint8_t addrWidth) {
return(state);
}
int16_t nRF24::setTransmitPipe(uint8_t* addr) {
int16_t nRF24::setTransmitPipe(const uint8_t* addr) {
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
@ -402,7 +404,7 @@ int16_t nRF24::setTransmitPipe(uint8_t* addr) {
return(state);
}
int16_t nRF24::setReceivePipe(uint8_t pipeNum, uint8_t* addr) {
int16_t nRF24::setReceivePipe(uint8_t pipeNum, const uint8_t* addr) {
// set mode to standby
int16_t state = standby();
RADIOLIB_ASSERT(state);
@ -561,6 +563,10 @@ int16_t nRF24::setEncoding(uint8_t encoding) {
return(RADIOLIB_ERR_NONE);
}
int16_t nRF24::setLNA(bool enable) {
return(this->mod->SPIsetRegValue(RADIOLIB_NRF24_REG_RF_SETUP, enable ? RADIOLIB_NRF24_RF_LNA_ON : RADIOLIB_NRF24_RF_LNA_OFF, 0, 0));
}
void nRF24::clearIRQ() {
// clear status bits
this->mod->SPIsetRegValue(RADIOLIB_NRF24_REG_STATUS, RADIOLIB_NRF24_RX_DR | RADIOLIB_NRF24_TX_DS | RADIOLIB_NRF24_MAX_RT, 6, 4);
@ -610,11 +616,11 @@ void nRF24::SPIreadRxPayload(uint8_t* data, uint8_t numBytes) {
SPItransfer(RADIOLIB_NRF24_CMD_READ_RX_PAYLOAD, false, NULL, data, numBytes);
}
void nRF24::SPIwriteTxPayload(uint8_t* data, uint8_t numBytes) {
void nRF24::SPIwriteTxPayload(const uint8_t* data, uint8_t numBytes) {
SPItransfer(RADIOLIB_NRF24_CMD_WRITE_TX_PAYLOAD, true, data, NULL, numBytes);
}
void nRF24::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
void nRF24::SPItransfer(uint8_t cmd, bool write, const uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
(void)this->mod->SPItransferStream(&cmd, 1, write, dataOut, dataIn, numBytes, false);
}

View file

@ -123,6 +123,8 @@
#define RADIOLIB_NRF24_RF_PWR_12_DBM 0b00000010 // 2 1 -12 dBm
#define RADIOLIB_NRF24_RF_PWR_6_DBM 0b00000100 // 2 1 -6 dBm
#define RADIOLIB_NRF24_RF_PWR_0_DBM 0b00000110 // 2 1 0 dBm (default)
#define RADIOLIB_NRF24_RF_LNA_OFF 0b00000000 // 0 0 LNA gain: Off
#define RADIOLIB_NRF24_RF_LNA_ON 0b00000001 // 0 0 On
// RADIOLIB_NRF24_REG_STATUS
#define RADIOLIB_NRF24_RX_DR 0b01000000 // 6 6 Rx data ready
@ -374,7 +376,7 @@ class nRF24: public PhysicalLayer {
\param addr Address to which the next packet shall be transmitted.
\returns \ref status_codes
*/
int16_t setTransmitPipe(uint8_t* addr);
int16_t setTransmitPipe(const uint8_t* addr);
/*!
\brief Sets address of receive pipes 0 or 1. The address width must be the same as the same
@ -384,7 +386,7 @@ class nRF24: public PhysicalLayer {
\param addr Address from which %nRF24 shall receive new packets on the specified pipe.
\returns \ref status_codes
*/
int16_t setReceivePipe(uint8_t pipeNum, uint8_t* addr);
int16_t setReceivePipe(uint8_t pipeNum, const uint8_t* addr);
/*!
\brief Sets address of receive pipes 2 - 5. The first 2 - 4 address bytes for these pipes
@ -464,6 +466,14 @@ class nRF24: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t setEncoding(uint8_t encoding) override;
/*!
\brief Enable or disable the low-noise amplifier.
Improves receive performance at the cost of increased power consumption.
\param enable True to enable.
\returns \ref status_codes
*/
int16_t setLNA(bool enable);
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected:
@ -471,8 +481,8 @@ class nRF24: public PhysicalLayer {
Module* getMod() override;
void SPIreadRxPayload(uint8_t* data, uint8_t numBytes);
void SPIwriteTxPayload(uint8_t* data, uint8_t numBytes);
void SPItransfer(uint8_t cmd, bool write = false, uint8_t* dataOut = NULL, uint8_t* dataIn = NULL, uint8_t numBytes = 0);
void SPIwriteTxPayload(const uint8_t* data, uint8_t numBytes);
void SPItransfer(uint8_t cmd, bool write = false, const uint8_t* dataOut = NULL, uint8_t* dataIn = NULL, uint8_t numBytes = 0);
#if !RADIOLIB_GODMODE
private:

View file

@ -14,7 +14,7 @@ APRSClient::APRSClient(PhysicalLayer* phy) {
phyLayer = phy;
}
int16_t APRSClient::begin(char sym, char* callsign, uint8_t ssid, bool alt) {
int16_t APRSClient::begin(char sym, const char* callsign, uint8_t ssid, bool alt) {
RADIOLIB_CHECK_RANGE(sym, ' ', '}', RADIOLIB_ERR_INVALID_SYMBOL);
symbol = sym;
@ -39,7 +39,7 @@ int16_t APRSClient::begin(char sym, char* callsign, uint8_t ssid, bool alt) {
return(RADIOLIB_ERR_NONE);
}
int16_t APRSClient::sendPosition(char* destCallsign, uint8_t destSSID, char* lat, char* lon, char* msg, char* time) {
int16_t APRSClient::sendPosition(char* destCallsign, uint8_t destSSID, const char* lat, const char* lon, const char* msg, const char* time) {
size_t len = 1 + strlen(lat) + 1 + strlen(lon);
if(msg != NULL) {
len += 1 + strlen(msg);
@ -84,7 +84,7 @@ int16_t APRSClient::sendPosition(char* destCallsign, uint8_t destSSID, char* lat
return(state);
}
int16_t APRSClient::sendMicE(float lat, float lon, uint16_t heading, uint16_t speed, uint8_t type, uint8_t* telem, size_t telemLen, char* grid, char* status, int32_t alt) {
int16_t APRSClient::sendMicE(float lat, float lon, uint16_t heading, uint16_t speed, uint8_t type, const uint8_t* telem, size_t telemLen, const char* grid, const char* status, int32_t alt) {
// sanity checks first
if(((telemLen == 0) && (telem != NULL)) || ((telemLen != 0) && (telem == NULL))) {
return(RADIOLIB_ERR_INVALID_MIC_E_TELEMETRY);

View file

@ -106,7 +106,7 @@ class APRSClient {
\param alt Whether to use the primary (false) or alternate (true) symbol table. Defaults to primary table.
\returns \ref status_codes
*/
int16_t begin(char sym, char* callsign = NULL, uint8_t ssid = 0, bool alt = false);
int16_t begin(char sym, const char* callsign = NULL, uint8_t ssid = 0, bool alt = false);
/*!
\brief Transmit position.
@ -118,7 +118,7 @@ class APRSClient {
\param time Position timestamp. Defaults to NULL (no timestamp).
\returns \ref status_codes
*/
int16_t sendPosition(char* destCallsign, uint8_t destSSID, char* lat, char* lon, char* msg = NULL, char* time = NULL);
int16_t sendPosition(char* destCallsign, uint8_t destSSID, const char* lat, const char* lon, const char* msg = NULL, const char* time = NULL);
/*!
\brief Transmit position using Mic-E encoding.
@ -133,7 +133,7 @@ class APRSClient {
\param status Status message to send. NULL when not used.
\param alt Altitude to send. RADIOLIB_APRS_MIC_E_ALTITUDE_UNUSED when not used.
*/
int16_t sendMicE(float lat, float lon, uint16_t heading, uint16_t speed, uint8_t type, uint8_t* telem = NULL, size_t telemLen = 0, char* grid = NULL, char* status = NULL, int32_t alt = RADIOLIB_APRS_MIC_E_ALTITUDE_UNUSED);
int16_t sendMicE(float lat, float lon, uint16_t heading, uint16_t speed, uint8_t type, const uint8_t* telem = NULL, size_t telemLen = 0, const char* grid = NULL, const char* status = NULL, int32_t alt = RADIOLIB_APRS_MIC_E_ALTITUDE_UNUSED);
/*!
\brief Transmit generic APRS frame.

View file

@ -14,7 +14,7 @@ AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* src
}
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, uint8_t* info, uint16_t infoLen) {
AX25Frame::AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, const uint8_t* info, uint16_t infoLen) {
// destination callsign/SSID
memcpy(this->destCallsign, destCallsign, strlen(destCallsign));
this->destCallsign[strlen(destCallsign)] = '\0';
@ -142,7 +142,7 @@ AX25Frame& AX25Frame::operator=(const AX25Frame& frame) {
return(*this);
}
int16_t AX25Frame::setRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters) {
int16_t AX25Frame::setRepeaters(char** repeaterCallsigns, const uint8_t* repeaterSSIDs, uint8_t numRepeaters) {
// check number of repeaters
if((numRepeaters < 1) || (numRepeaters > 8)) {
return(RADIOLIB_ERR_INVALID_NUM_REPEATERS);

View file

@ -185,7 +185,7 @@ class AX25Frame {
\param info Information field, in the form of arbitrary binary buffer.
\param infoLen Number of bytes in the information field.
*/
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, uint8_t* info, uint16_t infoLen);
AX25Frame(const char* destCallsign, uint8_t destSSID, const char* srcCallsign, uint8_t srcSSID, uint8_t control, uint8_t protocolID, const uint8_t* info, uint16_t infoLen);
/*!
\brief Copy constructor.
@ -211,7 +211,7 @@ class AX25Frame {
\param numRepeaters Number of repeaters, maximum is 8.
\returns \ref status_codes
*/
int16_t setRepeaters(char** repeaterCallsigns, uint8_t* repeaterSSIDs, uint8_t numRepeaters);
int16_t setRepeaters(char** repeaterCallsigns, const uint8_t* repeaterSSIDs, uint8_t numRepeaters);
/*!
\brief Method to set receive sequence number.

View file

@ -43,7 +43,7 @@ int16_t BellClient::begin(const BellModem_t& modem) {
int16_t BellClient::setModem(const BellModem_t& modem) {
this->modemType = modem;
this->toneLen = (1000000.0/(float)this->modemType.baudRate)*this->correction;
this->toneLen = (1000000.0f/(float)this->modemType.baudRate)*this->correction;
return(RADIOLIB_ERR_NONE);
}

View file

@ -1,20 +1,23 @@
#include "ExternalRadio.h"
#if defined(RADIOLIB_BUILD_ARDUINO)
ExternalRadio::ExternalRadio(uint32_t pin) : PhysicalLayer(1, 0) {
ExternalRadio::ExternalRadio(uint32_t pin) : PhysicalLayer() {
this->freqStep = 1;
mod = new Module(RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, pin);
mod->hal->pinMode(pin, mod->hal->GpioModeOutput);
this->prevFrf = 0;
}
#endif
ExternalRadio::ExternalRadio(RadioLibHal *hal, uint32_t pin) : PhysicalLayer(1, 0) {
ExternalRadio::ExternalRadio(RadioLibHal *hal, uint32_t pin) : PhysicalLayer() {
this->freqStep = 1;
mod = new Module(hal, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, pin);
mod->hal->pinMode(pin, mod->hal->GpioModeOutput);
this->prevFrf = 0;
}
ExternalRadio::ExternalRadio(const ExternalRadio& ext) : PhysicalLayer(1, 0) {
ExternalRadio::ExternalRadio(const ExternalRadio& ext) : PhysicalLayer() {
this->freqStep = 1;
this->prevFrf = ext.prevFrf;
if(ext.mod) {
this->mod = new Module(ext.mod->hal, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, ext.mod->getGpio());
@ -32,9 +35,7 @@ ExternalRadio& ExternalRadio::operator=(const ExternalRadio& ext) {
}
ExternalRadio::~ExternalRadio() {
if(this->mod) {
delete this->mod;
}
delete this->mod;
}
Module* ExternalRadio::getMod() {

View file

@ -34,7 +34,7 @@ int16_t FSK4Client::begin(float base, uint32_t shift, uint16_t rate) {
}
// calculate 24-bit frequency
baseFreq = (base * 1000000.0) / phyLayer->getFreqStep();
baseFreq = (base * 1000000.0f) / phyLayer->freqStep;
// configure for direct mode
return(phyLayer->startDirect());
@ -54,7 +54,7 @@ int16_t FSK4Client::setCorrection(int16_t offsets[], float length) {
return(RADIOLIB_ERR_NONE);
}
size_t FSK4Client::write(uint8_t* buff, size_t len) {
size_t FSK4Client::write(const uint8_t* buff, size_t len) {
size_t n = 0;
for(size_t i = 0; i < len; i++) {
n += FSK4Client::write(buff[i]);
@ -109,7 +109,7 @@ int16_t FSK4Client::standby() {
int32_t FSK4Client::getRawShift(int32_t shift) {
// calculate module carrier frequency resolution
int32_t step = round(phyLayer->getFreqStep());
int32_t step = round(phyLayer->freqStep);
// check minimum shift value
if(RADIOLIB_ABS(shift) < step / 2) {

View file

@ -59,7 +59,7 @@ class FSK4Client {
\param len Number of bytes to transmit.
\returns Number of transmitted bytes.
*/
size_t write(uint8_t* buff, size_t len);
size_t write(const uint8_t* buff, size_t len);
/*!
\brief Transmit a single byte.

View file

@ -21,10 +21,10 @@ HellClient::HellClient(AFSKClient* audio) {
int16_t HellClient::begin(float base, float rate) {
// calculate 24-bit frequency
baseFreqHz = base;
baseFreq = (base * 1000000.0) / phyLayer->getFreqStep();
baseFreq = (base * 1000000.0f) / phyLayer->freqStep;
// calculate "pixel" duration
pixelDuration = 1000000.0/rate;
pixelDuration = 1000000.0f/rate;
// configure for direct mode
return(phyLayer->startDirect());
@ -73,7 +73,8 @@ size_t HellClient::write(uint8_t b) {
uint8_t buff[RADIOLIB_HELL_FONT_WIDTH];
buff[0] = 0x00;
for(uint8_t i = 0; i < RADIOLIB_HELL_FONT_WIDTH - 2; i++) {
buff[i + 1] = RADIOLIB_NONVOLATILE_READ_BYTE(&HellFont[pos][i]);
uint8_t* ptr = const_cast<uint8_t*>(&HellFont[pos][i]);
buff[i + 1] = RADIOLIB_NONVOLATILE_READ_BYTE(ptr);
}
buff[RADIOLIB_HELL_FONT_WIDTH - 1] = 0x00;

View file

@ -144,9 +144,6 @@ class HellClient: public RadioLibPrint {
uint32_t pixelDuration = 0;
bool invert = false;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0);
int16_t standby();
};

View file

@ -24,16 +24,16 @@ int16_t LoRaWANNode::sendReceive(const String& strUp, uint8_t fPort, String& str
// build a temporary buffer
// LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL
size_t lenDown = 0;
uint8_t dataDown[251];
uint8_t dataDown[RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE + 1];
state = this->sendReceive((const uint8_t*)dataUp, strlen(dataUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown);
state = this->sendReceive(reinterpret_cast<const uint8_t*>(dataUp), strlen(dataUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown);
if(state == RADIOLIB_ERR_NONE) {
// add null terminator
dataDown[lenDown] = '\0';
// initialize Arduino String class
strDown = String((char*)dataDown);
strDown = String(reinterpret_cast<char*>(dataDown));
}
return(state);
@ -44,20 +44,20 @@ int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, bool isConfir
// build a temporary buffer
// LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL
size_t lenDown = 0;
uint8_t dataDown[251];
uint8_t dataDown[RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE + 1];
return(this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown));
return(this->sendReceive(reinterpret_cast<uint8_t*>(const_cast<char*>(strUp)), strlen(strUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown));
}
int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
return(this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, lenDown, isConfirmed, eventUp, eventDown));
return(this->sendReceive(reinterpret_cast<uint8_t*>(const_cast<char*>(strUp)), strlen(strUp), fPort, dataDown, lenDown, isConfirmed, eventUp, eventDown));
}
int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// build a temporary buffer
// LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL
size_t lenDown = 0;
uint8_t dataDown[251];
uint8_t dataDown[RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE + 1];
return(this->sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown));
}
@ -67,7 +67,6 @@ int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fP
return(RADIOLIB_ERR_NULL_POINTER);
}
int16_t state = RADIOLIB_ERR_UNKNOWN;
Module* mod = this->phyLayer->getMod();
// if after (at) ADR_ACK_LIMIT frames no RekeyConf was received, revert to Join state
if(this->fCntUp == (1UL << this->adrLimitExp)) {
@ -147,7 +146,7 @@ int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fP
// RETRANSMIT_TIMEOUT is 2s +/- 1s (RP v1.0.4)
// must be present after any confirmed frame, so we force this here
if(isConfirmed) {
mod->hal->delay(this->phyLayer->random(1000, 3000));
this->sleepDelay(this->phyLayer->random(1000, 3000));
}
// if an error occured or a downlink was received, stop retransmission
@ -518,10 +517,10 @@ int16_t LoRaWANNode::setBufferSession(const uint8_t* persistentBuffer) {
// for dynamic bands, the additional channels must be restored per-channel
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
// all-zero buffer used for checking if MAC commands are set
uint8_t bufferZeroes[RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_DOWN] = { 0 };
const uint8_t bufferZeroes[RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_DOWN] = { 0 };
// restore the session channels
uint8_t *startChannelsUp = &this->bufferSession[RADIOLIB_LORAWAN_SESSION_UL_CHANNELS];
const uint8_t *startChannelsUp = &this->bufferSession[RADIOLIB_LORAWAN_SESSION_UL_CHANNELS];
cid = RADIOLIB_LORAWAN_MAC_NEW_CHANNEL;
(void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK);
@ -532,7 +531,7 @@ int16_t LoRaWANNode::setBufferSession(const uint8_t* persistentBuffer) {
}
}
uint8_t *startChannelsDown = &this->bufferSession[RADIOLIB_LORAWAN_SESSION_DL_CHANNELS];
const uint8_t *startChannelsDown = &this->bufferSession[RADIOLIB_LORAWAN_SESSION_DL_CHANNELS];
cid = RADIOLIB_LORAWAN_MAC_DL_CHANNEL;
(void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK);
@ -550,12 +549,13 @@ int16_t LoRaWANNode::setBufferSession(const uint8_t* persistentBuffer) {
memcpy(cOcts, &this->bufferSession[RADIOLIB_LORAWAN_SESSION_LINK_ADR], cLen);
(void)execMacCommand(cid, cOcts, cLen);
uint8_t cids[6] = {
const uint8_t cids[6] = {
RADIOLIB_LORAWAN_MAC_DUTY_CYCLE, RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP,
RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP, RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP,
RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP, RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP
};
uint16_t locs[6] = {
const uint16_t locs[6] = {
RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE, RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP,
RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP, RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP,
RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP, RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP
@ -905,25 +905,51 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
RADIOLIB_ASSERT(state);
// calculate JoinRequest time-on-air in milliseconds
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
if(this->dwellTimeUp) {
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
if(toa > this->dwellTimeUp) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp);
return(RADIOLIB_ERR_DWELL_TIME_EXCEEDED);
}
}
RadioModeConfig_t modeCfg;
modeCfg.transmit.data = joinRequestMsg;
modeCfg.transmit.len = RADIOLIB_LORAWAN_JOIN_REQUEST_LEN;
modeCfg.transmit.addr = 0;
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_TX, &modeCfg);
RADIOLIB_ASSERT(state);
// if requested, delay until transmitting JoinRequest
RadioLibTime_t tNow = mod->hal->millis();
if(this->tUplink > tNow) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Delaying transmission by %lu ms", (unsigned long)(this->tUplink - tNow));
if(this->tUplink > mod->hal->millis()) {
mod->hal->delay(this->tUplink - mod->hal->millis());
this->sleepDelay(this->tUplink - mod->hal->millis());
}
}
// send it
state = this->phyLayer->transmit(joinRequestMsg, RADIOLIB_LORAWAN_JOIN_REQUEST_LEN);
// start transmission
state = this->phyLayer->launchMode();
RADIOLIB_ASSERT(state);
// sleep for the duration of the transmission
this->sleepDelay(toa);
RadioLibTime_t txEnd = mod->hal->millis();
// wait for an additional transmission duration as Tx timeout period
while(!mod->hal->digitalRead(mod->getIrq())) {
// yield for multi-threaded platforms
mod->hal->yield();
if(mod->hal->millis() > txEnd + toa) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
state = this->phyLayer->finishTransmit();
// set the timestamp so that we can measure when to start receiving
this->rxDelayStart = mod->hal->millis();
RADIOLIB_ASSERT(state);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("JoinRequest sent (DevNonce = %d) <-- Rx Delay start", this->devNonce);
@ -934,7 +960,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_DEV_NONCE], this->devNonce);
// set the Time on Air of the JoinRequest
this->lastToA = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
this->lastToA = toa;
// configure Rx1 and Rx2 delay for JoinAccept message - these are re-configured once a valid JoinAccept is received
this->rxDelays[1] = RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_1_MS;
@ -995,7 +1021,7 @@ int16_t LoRaWANNode::activateABP(uint8_t initialDr) {
return(RADIOLIB_LORAWAN_NEW_SESSION);
}
void LoRaWANNode::processCFList(uint8_t* cfList) {
void LoRaWANNode::processCFList(const uint8_t* cfList) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Processing CFList");
uint8_t cOcts[14] = { 0 }; // TODO explain
@ -1015,7 +1041,7 @@ void LoRaWANNode::processCFList(uint8_t* cfList) {
cid = RADIOLIB_LORAWAN_MAC_NEW_CHANNEL;
(void)this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_DOWNLINK);
uint8_t freqZero[3] = { 0 };
const uint8_t freqZero[3] = { 0 };
// datarate range for all new channels is equal to the default channels
cOcts[4] = (this->band->txFreqs[0].drMax << 4) | this->band->txFreqs[0].drMin;
@ -1264,12 +1290,11 @@ void LoRaWANNode::micUplink(uint8_t* inOut, uint8_t lenInOut) {
}
}
int16_t LoRaWANNode::transmitUplink(LoRaWANChannel_t* chnl, uint8_t* in, uint8_t len, bool retrans) {
int16_t LoRaWANNode::transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, uint8_t len, bool retrans) {
int16_t state = RADIOLIB_ERR_UNKNOWN;
Module* mod = this->phyLayer->getMod();
// check if the Rx windows were closed after sending the previous uplink
// this FORCES a user to call downlink() after an uplink()
if(this->rxDelayEnd < this->rxDelayStart) {
// not enough time elapsed since the last uplink, we may still be in an Rx window
return(RADIOLIB_ERR_UPLINK_UNAVAILABLE);
@ -1294,24 +1319,57 @@ int16_t LoRaWANNode::transmitUplink(LoRaWANChannel_t* chnl, uint8_t* in, uint8_t
RADIOLIB_LORAWAN_UPLINK,
this->txPowerMax - 2*this->txPowerSteps);
RADIOLIB_ASSERT(state);
// check whether dwell time limitation is exceeded
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(len) / 1000;
if(this->dwellTimeUp) {
if(toa > this->dwellTimeUp) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp);
return(RADIOLIB_ERR_DWELL_TIME_EXCEEDED);
}
}
RadioModeConfig_t modeCfg;
modeCfg.transmit.data = in;
modeCfg.transmit.len = len;
modeCfg.transmit.addr = 0;
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_TX, &modeCfg);
RADIOLIB_ASSERT(state);
// if requested, wait until transmitting uplink
tNow = mod->hal->millis();
if(this->tUplink > tNow) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Delaying transmission by %lu ms", (unsigned long)(this->tUplink - tNow));
if(this->tUplink > mod->hal->millis()) {
mod->hal->delay(this->tUplink - mod->hal->millis());
this->sleepDelay(this->tUplink - mod->hal->millis());
}
}
state = this->phyLayer->transmit(in, len);
// start transmission
state = this->phyLayer->launchMode();
RADIOLIB_ASSERT(state);
// sleep for the duration of the transmission
this->sleepDelay(toa);
RadioLibTime_t txEnd = mod->hal->millis();
// wait for an additional transmission duration as Tx timeout period
while(!mod->hal->digitalRead(mod->getIrq())) {
// yield for multi-threaded platforms
mod->hal->yield();
if(mod->hal->millis() > txEnd + toa) {
return(RADIOLIB_ERR_TX_TIMEOUT);
}
}
state = this->phyLayer->finishTransmit();
// set the timestamp so that we can measure when to start receiving
this->rxDelayStart = mod->hal->millis();
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Uplink sent <-- Rx Delay start");
// increase Time on Air of the uplink sequence
this->lastToA += this->phyLayer->getTimeOnAir(len) / 1000;
this->lastToA += toa;
return(state);
}
@ -1339,7 +1397,7 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
// if function was called while Rx windows are in progress,
// wait until last window closes to prevent very bad stuff
if(now < tReference + dlDelays[numWindows]) {
mod->hal->delay(dlDelays[numWindows] + tReference - now);
this->sleepDelay(dlDelays[numWindows] + tReference - now);
}
// update the end timestamp in case user got stuck between uplink and downlink
this->rxDelayEnd = mod->hal->millis();
@ -1363,8 +1421,17 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
RADIOLIB_ASSERT(state);
// calculate the Rx timeout
RadioLibTime_t timeoutHost = this->phyLayer->getTimeOnAir(0) + 2*this->scanGuard*1000;
RadioLibTime_t timeoutHost = this->phyLayer->getTimeOnAir(0) + this->scanGuard*1000;
RadioLibTime_t timeoutMod = this->phyLayer->calculateRxTimeout(timeoutHost);
// TODO remove default arguments
RadioModeConfig_t modeCfg;
modeCfg.receive.timeout = timeoutMod;
modeCfg.receive.irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS;
modeCfg.receive.irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK;
modeCfg.receive.len = 0;
state = this->phyLayer->stageMode(RADIOLIB_RADIO_MODE_RX, &modeCfg);
RADIOLIB_ASSERT(state);
// wait for the start of the Rx window
RadioLibTime_t waitLen = tReference + dlDelays[window] - mod->hal->millis();
@ -1376,17 +1443,16 @@ int16_t LoRaWANNode::receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChanne
if(waitLen > this->scanGuard) {
waitLen -= this->scanGuard;
}
mod->hal->delay(waitLen);
this->sleepDelay(waitLen);
// open Rx window by starting receive with specified timeout
// TODO remove default arguments
state = this->phyLayer->startReceive(timeoutMod, RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RADIOLIB_IRQ_RX_DEFAULT_MASK, 0);
state = this->phyLayer->launchMode();
tOpen = mod->hal->millis();
RADIOLIB_ASSERT(state);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + scanGuard / 2));
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Opening Rx%d window (%d ms timeout)... <-- Rx Delay end ", window, (int)(timeoutHost / 1000 + 2));
// wait for the timeout to complete (and a small additional delay)
mod->hal->delay(timeoutHost / 1000 + this->scanGuard / 2);
this->sleepDelay(timeoutHost / 1000 + this->scanGuard / 2);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Closing Rx%d window", window);
// if the IRQ bit for Rx Timeout is not set, something is received, so stop the windows
@ -1707,12 +1773,7 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
uint8_t fLen = 1;
uint8_t* mPtr = fOpts;
uint8_t procLen = 0;
#if !RADIOLIB_STATIC_ONLY
uint8_t* fOptsRe = new uint8_t[250];
#else
uint8_t fOptsRe[RADIOLIB_STATIC_ARRAY_SIZE];
#endif
uint8_t fOptsRe[RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE] = { 0 };
uint8_t fOptsReLen = 0;
// indication whether LinkAdr MAC command has been processed
@ -1722,14 +1783,14 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
cid = *mPtr; // MAC id is the first byte
// fetch length of MAC downlink payload
state = this->getMacLen(cid, &fLen, RADIOLIB_LORAWAN_DOWNLINK, true);
state = this->getMacLen(cid, &fLen, RADIOLIB_LORAWAN_DOWNLINK, true, mPtr + 1);
if(state != RADIOLIB_ERR_NONE) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Unknown MAC CID %02x", cid);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Skipping remaining MAC commands");
break;
}
// already fetch length of MAC answer payload (if any)
// already fetch length of MAC answer payload (if any), include CID
uint8_t fLenRe = 0;
(void)this->getMacLen(cid, &fLenRe, RADIOLIB_LORAWAN_UPLINK, true);
// don't care about return value: the previous getMacLen() would have failed anyway
@ -1836,7 +1897,6 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
#if !RADIOLIB_STATIC_ONLY
delete[] fOpts;
delete[] fOptsRe;
delete[] downlinkMsg;
#endif
@ -2112,7 +2172,7 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
// check if the frequency is allowed and possible
if(macFreq >= this->band->freqMin && macFreq <= this->band->freqMax) {
if(this->phyLayer->setFrequency((float)macFreq / 10000.0) == RADIOLIB_ERR_NONE) {
if(this->phyLayer->setFrequency((float)macFreq / 10000.0f) == RADIOLIB_ERR_NONE) {
freqAck = 1;
}
// otherwise, if frequency is 0, disable the channel which is also a valid option
@ -2213,7 +2273,7 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
if(delay == 0) {
delay = 1;
}
this->rxDelays[1] = delay * 1000; // Rx1 delay
this->rxDelays[1] = (RadioLibTime_t)delay * (RadioLibTime_t)1000; // Rx1 delay
this->rxDelays[2] = this->rxDelays[1] + 1000; // Rx2 delay
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP], optIn, lenIn);
@ -2258,7 +2318,7 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
// if not a valid server version, retransmit RekeyInd
uint8_t cLen = 0;
this->getMacLen(cid, &cLen, RADIOLIB_LORAWAN_UPLINK);
uint8_t cOcts[1] = { this->rev };
const uint8_t cOcts[1] = { this->rev };
(void)LoRaWANNode::pushMacCommand(cid, cOcts, this->fOptsUp, &this->fOptsUpLen, RADIOLIB_LORAWAN_UPLINK);
// discard RekeyConf, therefore return false so it doesn't send a reply
@ -2352,16 +2412,19 @@ void LoRaWANNode::preprocessMacLinkAdr(uint8_t* mPtr, uint8_t cLen, uint8_t* mAd
uint8_t chMaskCntl = (mPtr[opt * fLen + 4] & 0x70) >> 4;
uint16_t chMask = LoRaWANNode::ntoh<uint16_t>(&mPtr[opt * fLen + 2]);
switch(chMaskCntl) {
case 0 ... 3:
case 0:
case 1:
case 2:
case 3:
chMaskGrp0123 |= (uint64_t)chMask << (16 * chMaskCntl);
break;
case 4:
chMaskGrp45 |= (uint32_t)chMask;
break;
case 5:
// for CN500, this is just a normal channel mask
// for CN470, this is just a normal channel mask
// for all other bands, the first 10 bits enable banks of 8 125kHz channels
if(this->band->bandNum == BandCN500) {
if(this->band->bandNum == BandCN470) {
chMaskGrp45 |= (uint32_t)chMask << 16;
} else {
int bank = 0;
@ -2380,19 +2443,19 @@ void LoRaWANNode::preprocessMacLinkAdr(uint8_t* mPtr, uint8_t cLen, uint8_t* mAd
case 6:
// for dynamic bands: all channels ON (that are currently defined)
// for fixed bands: all 125kHz channels ON, channel mask similar to ChMask = 4
// except for CN500: all 125kHz channels ON
// except for CN470: all 125kHz channels ON
// for dynamic bands: retrieve all currently defined channels
// for fixed bands: cannot store all defined channels, so select a random one from each bank
this->getChannelPlanMask(&chMaskGrp0123, &chMaskGrp45);
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_FIXED && this->band->bandNum != BandCN500) {
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_FIXED && this->band->bandNum != BandCN470) {
chMaskGrp45 |= (uint32_t)chMask;
}
break;
case 7:
// for fixed bands: all 125kHz channels ON, channel mask similar to ChMask = 4
// except for CN500: RFU
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_FIXED && this->band->bandNum != BandCN500) {
// except for CN470: RFU
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_FIXED && this->band->bandNum != BandCN470) {
chMaskGrp0123 = 0;
chMaskGrp45 |= (uint32_t)chMask;
}
@ -2419,7 +2482,7 @@ void LoRaWANNode::postprocessMacLinkAdr(uint8_t* ack, uint8_t cLen) {
int16_t LoRaWANNode::getMacCommand(uint8_t cid, LoRaWANMacCommand_t* cmd) {
for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_MAC_COMMANDS; i++) {
if(MacTable[i].cid == cid) {
memcpy((void*)cmd, (void*)&MacTable[i], sizeof(LoRaWANMacCommand_t));
memcpy(reinterpret_cast<void*>(cmd), reinterpret_cast<void*>(const_cast<LoRaWANMacCommand_t*>(&MacTable[i])), sizeof(LoRaWANMacCommand_t));
return(RADIOLIB_ERR_NONE);
}
}
@ -2486,17 +2549,21 @@ int16_t LoRaWANNode::getMacDeviceTimeAns(uint32_t* gpsEpoch, uint8_t* fraction,
return(RADIOLIB_ERR_NONE);
}
int16_t LoRaWANNode::getMacLen(uint8_t cid, uint8_t* len, uint8_t dir, bool inclusive) {
int16_t LoRaWANNode::getMacLen(uint8_t cid, uint8_t* len, uint8_t dir, bool inclusive, uint8_t* payload) {
(void)payload;
*len = 0;
if(inclusive) {
*len += 1; // add one byte for CID
}
LoRaWANMacCommand_t cmd = RADIOLIB_LORAWAN_MAC_COMMAND_NONE;
int16_t state = this->getMacCommand(cid, &cmd);
RADIOLIB_ASSERT(state);
if(dir == RADIOLIB_LORAWAN_UPLINK) {
*len = cmd.lenUp;
*len += cmd.lenUp;
} else {
*len = cmd.lenDn;
}
if(inclusive) {
*len += 1; // add one byte for CID
*len += cmd.lenDn;
}
return(RADIOLIB_ERR_NONE);
}
@ -2518,7 +2585,7 @@ bool LoRaWANNode::isPersistentMacCommand(uint8_t cid, uint8_t dir) {
return(false);
}
int16_t LoRaWANNode::pushMacCommand(uint8_t cid, uint8_t* cOcts, uint8_t* out, uint8_t* lenOut, uint8_t dir) {
int16_t LoRaWANNode::pushMacCommand(uint8_t cid, const uint8_t* cOcts, uint8_t* out, uint8_t* lenOut, uint8_t dir) {
uint8_t fLen = 0;
int16_t state = this->getMacLen(cid, &fLen, dir, true);
RADIOLIB_ASSERT(state);
@ -2535,7 +2602,7 @@ int16_t LoRaWANNode::pushMacCommand(uint8_t cid, uint8_t* cOcts, uint8_t* out, u
return(RADIOLIB_ERR_NONE);
}
int16_t LoRaWANNode::getMacPayload(uint8_t cid, uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t dir) {
int16_t LoRaWANNode::getMacPayload(uint8_t cid, const uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t dir) {
size_t i = 0;
while(i < lenIn) {
@ -2598,7 +2665,8 @@ void LoRaWANNode::clearMacCommands(uint8_t* inOut, uint8_t* lenInOut, uint8_t di
uint8_t numDeleted = 0;
while(i < *lenInOut) {
uint8_t id = inOut[i];
uint8_t fLen = 1; // if there is an incorrect MAC command, we should at least move forward by one byte
uint8_t fLen = 0;
// include CID byte, so if command fails, we still move one byte forward
(void)this->getMacLen(id, &fLen, dir, true);
// only clear MAC command if it should not persist until a downlink is received
@ -2622,7 +2690,7 @@ int16_t LoRaWANNode::setDatarate(uint8_t drUp) {
// scan through all enabled channels and check if the requested datarate is available
bool isValidDR = false;
for(size_t i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) {
LoRaWANChannel_t *chnl = &(this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i]);
const LoRaWANChannel_t *chnl = &(this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i]);
if(chnl->enabled) {
if(drUp >= chnl->drMin && drUp <= chnl->drMax) {
isValidDR = true;
@ -2867,7 +2935,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
syncWord[2] = (uint8_t)RADIOLIB_LORAWAN_GFSK_SYNC_WORD;
syncWordLen = 3;
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("FSK: BR = %4.1f, FD = %4.1f kHz",
dr.fsk.bitRate, dr.fsk.freqDev);
(double)dr.fsk.bitRate, (double)dr.fsk.freqDev);
} break;
case(ModemType_t::RADIOLIB_MODEM_LORA): {
@ -2875,7 +2943,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
syncWord[0] = RADIOLIB_LORAWAN_LORA_SYNC_WORD;
syncWordLen = 1;
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("LoRa: SF = %d, BW = %5.1f kHz, CR = 4/%d, IQ: %c",
dr.lora.spreadingFactor, dr.lora.bandwidth, dr.lora.codingRate, dir ? 'D' : 'U');
dr.lora.spreadingFactor, (double)dr.lora.bandwidth, dr.lora.codingRate, dir ? 'D' : 'U');
} break;
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
@ -2960,11 +3028,11 @@ void LoRaWANNode::getChannelPlanMask(uint64_t* chMaskGrp0123, uint32_t* chMaskGr
// if a subband is set, we can set the channel indices straight from subband
if(this->subBand > 0 && this->subBand <= 8) {
// for sub band 1-8, set bank of 8 125kHz + single 500kHz channel
*chMaskGrp0123 |= 0xFF << ((this->subBand - 1) * 8);
*chMaskGrp45 |= 0x01 << ((this->subBand - 1) * 8);
*chMaskGrp0123 |= (uint64_t)0xFF << ((this->subBand - 1) * 8);
*chMaskGrp45 |= (uint32_t)0x01 << (this->subBand - 1);
} else if(this->subBand > 8 && this->subBand <= 12) {
// CN500 only: for sub band 9-12, set bank of 8 125kHz channels
*chMaskGrp45 |= 0xFF << ((this->subBand - 9) * 8);
// CN470 only: for sub band 9-12, set bank of 8 125kHz channels
*chMaskGrp45 |= (uint32_t)0xFF << ((this->subBand - 9) * 8);
} else {
// if subband is set to 0, all 125kHz channels are enabled.
// however, we can 'only' store 16 channels, so we don't use all channels at once.
@ -2981,8 +3049,8 @@ void LoRaWANNode::getChannelPlanMask(uint64_t* chMaskGrp0123, uint32_t* chMaskGr
}
}
// the 500 kHz channels are in the usual channel plan however
// these are the channel indices 64-71 for bands other than CN500
if(this->band->bandNum != BandCN500) {
// these are the channel indices 64-71 for bands other than CN470
if(this->band->bandNum != BandCN470) {
for(int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) {
uint8_t idx = this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i].idx;
if(idx != RADIOLIB_LORAWAN_CHANNEL_INDEX_NONE && idx >= 64) {
@ -3217,7 +3285,7 @@ void LoRaWANNode::printChannels() {
}
#endif
uint32_t LoRaWANNode::generateMIC(uint8_t* msg, size_t len, uint8_t* key) {
uint32_t LoRaWANNode::generateMIC(const uint8_t* msg, size_t len, uint8_t* key) {
if((msg == NULL) || (len == 0)) {
return(0);
}
@ -3307,6 +3375,10 @@ uint8_t LoRaWANNode::getMaxPayloadLen() {
return(curLen - 13 - this->fOptsUpLen);
}
void LoRaWANNode::setSleepFunction(SleepCb_t cb) {
this->sleepCb = cb;
}
int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) {
int16_t state = this->phyLayer->standby();
if(state != RADIOLIB_ERR_NONE) {
@ -3431,6 +3503,18 @@ void LoRaWANNode::processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_
}
}
void LoRaWANNode::sleepDelay(RadioLibTime_t ms) {
// if the user did not provide sleep callback, or the duration is short, just call delay
if((this->sleepCb == nullptr) || (ms <= RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD)) {
Module* mod = this->phyLayer->getMod();
mod->hal->delay(ms);
return;
}
// otherwise, call the user-provided callback
this->sleepCb(ms);
}
int16_t LoRaWANNode::checkBufferCommon(const uint8_t *buffer, uint16_t size) {
// check if there are actually values in the buffer
size_t i = 0;

View file

@ -208,6 +208,11 @@
#define RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_UP (2)
#define RADIOLIB_LORAWAN_MAX_NUM_ADR_COMMANDS (8)
#define RADIOLIB_LORAWAN_MAX_DOWNLINK_SIZE (250)
// threshold at which sleeping via user callback enabled, in ms
#define RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD (50)
/*!
\struct LoRaWANMacCommand_t
\brief MAC command specification structure.
@ -430,7 +435,7 @@ extern const LoRaWANBand_t EU868;
extern const LoRaWANBand_t US915;
extern const LoRaWANBand_t EU433;
extern const LoRaWANBand_t AU915;
extern const LoRaWANBand_t CN500;
extern const LoRaWANBand_t CN470;
extern const LoRaWANBand_t AS923;
extern const LoRaWANBand_t AS923_2;
extern const LoRaWANBand_t AS923_3;
@ -447,7 +452,7 @@ enum LoRaWANBandNum_t {
BandUS915,
BandEU433,
BandAU915,
BandCN500,
BandCN470,
BandAS923,
BandAS923_2,
BandAS923_3,
@ -830,6 +835,18 @@ class LoRaWANNode {
*/
uint8_t getMaxPayloadLen();
/*! \brief Callback to a user-provided sleep function. */
typedef void (*SleepCb_t)(RadioLibTime_t ms);
/*!
\brief Set custom delay/sleep function callback. If set, LoRaWAN node will call
this function to wait for periods of time longer than RADIOLIB_LORAWAN_DELAY_SLEEP_THRESHOLD.
This can be used to lower the power consumption by putting the host microcontroller to sleep.
NOTE: Since this method will call a user-provided function, it is up to the user to ensure
that the time duration spent in that sleep function is accurate to at least 1 ms!
*/
void setSleepFunction(SleepCb_t cb);
/*!
\brief TS009 Protocol Specification Verification switch
(allows FPort 224 and cuts off uplink payload instead of rejecting if maximum length exceeded).
@ -848,7 +865,7 @@ class LoRaWANNode {
500 is the **maximum** value, but it is not a good idea to go anywhere near that.
If you have to go above 50 you probably have a bug somewhere. Check your device timing.
*/
RadioLibTime_t scanGuard = 10;
RadioLibTime_t scanGuard = 5;
#if !RADIOLIB_GODMODE
protected:
@ -971,6 +988,8 @@ class LoRaWANNode {
// allow port 226 for devices implementing TS011
bool TS011 = false;
SleepCb_t sleepCb = nullptr;
// this will reset the device credentials, so the device starts completely new
void clearNonces();
@ -984,7 +1003,7 @@ class LoRaWANNode {
int16_t processJoinAccept(LoRaWANJoinEvent_t *joinEvent);
// a join-accept can piggy-back a set of channels or channel masks
void processCFList(uint8_t* cfList);
void processCFList(const uint8_t* cfList);
// check whether payload length and fport are allowed
int16_t isValidUplink(uint8_t* len, uint8_t fPort);
@ -999,7 +1018,7 @@ class LoRaWANNode {
void micUplink(uint8_t* inOut, uint8_t lenInOut);
// transmit uplink buffer on a specified channel
int16_t transmitUplink(LoRaWANChannel_t* chnl, uint8_t* in, uint8_t len, bool retrans);
int16_t transmitUplink(const LoRaWANChannel_t* chnl, uint8_t* in, uint8_t len, bool retrans);
// wait for, open and listen during receive windows; only performs listening
int16_t receiveCommon(uint8_t dir, const LoRaWANChannel_t* dlChannels, const RadioLibTime_t* dlDelays, uint8_t numWindows, RadioLibTime_t tReference);
@ -1028,7 +1047,8 @@ class LoRaWANNode {
// get the length of a certain MAC command in a specific direction (up/down)
// if inclusive is true, add one for the CID byte
int16_t getMacLen(uint8_t cid, uint8_t* len, uint8_t dir, bool inclusive = false);
// include payload in case the MAC command has a dynamic length
virtual int16_t getMacLen(uint8_t cid, uint8_t* len, uint8_t dir, bool inclusive = false, uint8_t* payload = NULL);
// find out of a MAC command should persist destruction
// in uplink direction, some commands must persist if no downlink is received
@ -1036,10 +1056,10 @@ class LoRaWANNode {
bool isPersistentMacCommand(uint8_t cid, uint8_t dir);
// push MAC command to queue, done by copy
int16_t pushMacCommand(uint8_t cid, uint8_t* cOcts, uint8_t* out, uint8_t* lenOut, uint8_t dir);
int16_t pushMacCommand(uint8_t cid, const uint8_t* cOcts, uint8_t* out, uint8_t* lenOut, uint8_t dir);
// retrieve the payload of a certain MAC command, if present in the buffer
int16_t getMacPayload(uint8_t cid, uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t dir);
int16_t getMacPayload(uint8_t cid, const uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t dir);
// delete a specific MAC command from queue, indicated by the command ID
int16_t deleteMacCommand(uint8_t cid, uint8_t* inOut, uint8_t* lenInOut, uint8_t dir);
@ -1087,7 +1107,7 @@ class LoRaWANNode {
#endif
// method to generate message integrity code
uint32_t generateMIC(uint8_t* msg, size_t len, uint8_t* key);
uint32_t generateMIC(const uint8_t* msg, size_t len, uint8_t* key);
// method to verify message integrity code
// it assumes that the MIC is the last 4 bytes of the message
@ -1099,6 +1119,9 @@ class LoRaWANNode {
// function to encrypt and decrypt payloads (regular uplink/downlink)
void processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fCnt, uint8_t dir, uint8_t ctrId, bool counter);
// function that allows sleeping via user-provided callback
void sleepDelay(RadioLibTime_t ms);
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
static uint16_t checkSum16(const uint8_t *key, uint16_t keyLen);

View file

@ -8,7 +8,7 @@ const LoRaWANBand_t* LoRaWANBands[RADIOLIB_LORAWAN_NUM_SUPPORTED_BANDS] = {
&US915,
&EU433,
&AU915,
&CN500,
&CN470,
&AS923,
&AS923_2,
&AS923_3,
@ -331,8 +331,8 @@ const LoRaWANBand_t AU915 = {
}
};
const LoRaWANBand_t CN500 = {
.bandNum = BandCN500,
const LoRaWANBand_t CN470 = {
.bandNum = BandCN470,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.freqMin = 4700000,
.freqMax = 5100000,
@ -356,7 +356,7 @@ const LoRaWANBand_t CN500 = {
.freqStep = 2000,
.drMin = 0,
.drMax = 5,
.drJoinRequest = 0
.drJoinRequest = 3
},
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},

View file

@ -23,7 +23,7 @@ MorseClient::MorseClient(AFSKClient* audio) {
int16_t MorseClient::begin(float base, uint8_t speed) {
// calculate 24-bit frequency
baseFreqHz = base;
baseFreq = (base * 1000000.0) / phyLayer->getFreqStep();
baseFreq = (base * 1000000.0f) / phyLayer->freqStep;
// calculate tone period for decoding
basePeriod = (1000000.0f/base)/2.0f;
@ -48,7 +48,8 @@ char MorseClient::decode(uint8_t symbol, uint8_t len) {
// iterate over the table
for(uint8_t i = 0; i < sizeof(MorseTable); i++) {
uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(&MorseTable[i]);
uint8_t* ptr = const_cast<uint8_t*>(&MorseTable[i]);
uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(ptr);
if(code == symbol) {
// match, return the index + ASCII offset
return((char)(i + RADIOLIB_MORSE_ASCII_OFFSET));
@ -56,7 +57,7 @@ char MorseClient::decode(uint8_t symbol, uint8_t len) {
}
// nothing found
return(RADIOLIB_MORSE_UNSUPPORTED);
return(RADIOLIB_MORSE_UNKNOWN_SYMBOL);
}
#if !RADIOLIB_EXCLUDE_AFSK
@ -85,7 +86,7 @@ int MorseClient::read(uint8_t* symbol, uint8_t* len, float low, float high) {
if((pauseLen >= low*(float)letterSpace) && (pauseLen <= high*(float)letterSpace)) {
return(RADIOLIB_MORSE_CHAR_COMPLETE);
} else if(pauseLen > wordSpace) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("\n<space>");
RADIOLIB_DEBUG_PROTOCOL_PRINTLN(RADIOLIB_LINE_FEED "<space>");
return(RADIOLIB_MORSE_WORD_COMPLETE);
}
@ -129,7 +130,8 @@ size_t MorseClient::write(uint8_t b) {
}
// get morse code from lookup table
uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(&MorseTable[(uint8_t)(toupper(b) - RADIOLIB_MORSE_ASCII_OFFSET)]);
uint8_t* ptr = const_cast<uint8_t*>(&MorseTable[(uint8_t)(toupper(b) - RADIOLIB_MORSE_ASCII_OFFSET)]);
uint8_t code = RADIOLIB_NONVOLATILE_READ_BYTE(ptr);
// check unsupported characters
if(code == RADIOLIB_MORSE_UNSUPPORTED) {
@ -137,15 +139,16 @@ size_t MorseClient::write(uint8_t b) {
}
// iterate through codeword until guard bit is reached
RADIOLIB_DEBUG_PROTOCOL_PRINT("%c ", b);
while(code > RADIOLIB_MORSE_GUARDBIT) {
// send dot or dash
if (code & RADIOLIB_MORSE_DASH) {
RADIOLIB_DEBUG_PROTOCOL_PRINT("-");
RADIOLIB_DEBUG_PROTOCOL_PRINT_NOTAG("-");
transmitDirect(baseFreq, baseFreqHz);
mod->waitForMicroseconds(mod->hal->micros(), dashLength*1000);
} else {
RADIOLIB_DEBUG_PROTOCOL_PRINT(".");
RADIOLIB_DEBUG_PROTOCOL_PRINT_NOTAG(".");
transmitDirect(baseFreq, baseFreqHz);
mod->waitForMicroseconds(mod->hal->micros(), dotLength*1000);
}
@ -161,7 +164,7 @@ size_t MorseClient::write(uint8_t b) {
// letter space
standby();
mod->waitForMicroseconds(mod->hal->micros(), letterSpace*1000 - dotLength*1000);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN();
RADIOLIB_DEBUG_PROTOCOL_PRINT_NOTAG(RADIOLIB_LINE_FEED);
return(1);
}

View file

@ -14,6 +14,7 @@
#define RADIOLIB_MORSE_INTER_SYMBOL 0x00
#define RADIOLIB_MORSE_CHAR_COMPLETE 0x01
#define RADIOLIB_MORSE_WORD_COMPLETE 0x02
#define RADIOLIB_MORSE_UNKNOWN_SYMBOL '*'
// Morse character table: - using codes defined in ITU-R M.1677-1
// - Morse code representation is saved LSb first, using additional bit as guard
@ -171,9 +172,6 @@ class MorseClient: public RadioLibPrint {
uint32_t pauseCounter = 0;
RadioLibTime_t pauseStart = 0;
size_t printNumber(unsigned long, uint8_t);
size_t printFloat(double, uint8_t);
int16_t transmitDirect(uint32_t freq = 0, uint32_t freqHz = 0);
int16_t standby();
};

View file

@ -39,10 +39,10 @@ int16_t PagerClient::begin(float base, uint16_t speed, bool invert, uint16_t shi
// calculate 24-bit frequency
baseFreq = base;
baseFreqRaw = (baseFreq * 1000000.0) / phyLayer->getFreqStep();
baseFreqRaw = (baseFreq * 1000000.0f) / phyLayer->freqStep;
// calculate module carrier frequency resolution
uint16_t step = round(phyLayer->getFreqStep());
uint16_t step = round(phyLayer->freqStep);
// calculate raw frequency shift
shiftFreqHz = shift;
@ -67,10 +67,10 @@ int16_t PagerClient::transmit(String& str, uint32_t addr, uint8_t encoding, uint
#endif
int16_t PagerClient::transmit(const char* str, uint32_t addr, uint8_t encoding, uint8_t function) {
return(PagerClient::transmit((uint8_t*)str, strlen(str), addr, encoding, function));
return(PagerClient::transmit(reinterpret_cast<uint8_t*>(const_cast<char*>(str)), strlen(str), addr, encoding, function));
}
int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t encoding, uint8_t function) {
int16_t PagerClient::transmit(const uint8_t* data, size_t len, uint32_t addr, uint8_t encoding, uint8_t function) {
if(addr > RADIOLIB_PAGER_ADDRESS_MAX) {
return(RADIOLIB_ERR_INVALID_ADDRESS_WIDTH);
}
@ -326,14 +326,14 @@ int16_t PagerClient::readData(String& str, size_t len, uint32_t* addr) {
// check tone-only transmissions
if(length == 0) {
length = 6;
strncpy((char*)data, "<tone>", length + 1);
strncpy(reinterpret_cast<char*>(data), "<tone>", length + 1);
}
// add null terminator
data[length] = 0;
// initialize Arduino String class
str = String((char*)data);
str = String(reinterpret_cast<char*>(data));
}
// deallocate temporary buffer
@ -494,7 +494,7 @@ bool PagerClient::addressMatched(uint32_t addr) {
return(false);
}
void PagerClient::write(uint32_t* data, size_t len) {
void PagerClient::write(const uint32_t* data, size_t len) {
// write code words from buffer
for(size_t i = 0; i < len; i++) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("POCSAG W\t%lu\t%08lX", (long unsigned int)i, (long unsigned int)data[i]);

View file

@ -117,7 +117,7 @@ class PagerClient {
\param function bits (NUMERIC, TONE, ACTIVATION, ALPHANUMERIC). Allowed values 0 to 3. Defaults to auto select by specified encoding
\returns \ref status_codes
*/
int16_t transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t encoding = RADIOLIB_PAGER_BCD, uint8_t function = RADIOLIB_PAGER_FUNC_AUTO);
int16_t transmit(const uint8_t* data, size_t len, uint32_t addr, uint8_t encoding = RADIOLIB_PAGER_BCD, uint8_t function = RADIOLIB_PAGER_FUNC_AUTO);
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
/*!
@ -190,7 +190,7 @@ class PagerClient {
size_t filterNumAddresses = 0;
bool inv = false;
void write(uint32_t* data, size_t len);
void write(const uint32_t* data, size_t len);
void write(uint32_t codeWord);
int16_t startReceiveCommon();
bool addressMatched(uint32_t addr);

View file

@ -2,9 +2,9 @@
#include <string.h>
PhysicalLayer::PhysicalLayer(float step, size_t maxLen) {
this->freqStep = step;
this->maxPacketLength = maxLen;
PhysicalLayer::PhysicalLayer() {
this->freqStep = 1;
this->maxPacketLength = 1;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
this->bufferBitPos = 0;
this->bufferWritePos = 0;
@ -51,7 +51,7 @@ int16_t PhysicalLayer::transmit(String& str, uint8_t addr) {
#endif
int16_t PhysicalLayer::transmit(const char* str, uint8_t addr) {
return(transmit((uint8_t*)str, strlen(str), addr));
return(transmit(reinterpret_cast<uint8_t*>(const_cast<char*>(str)), strlen(str), addr));
}
int16_t PhysicalLayer::transmit(const uint8_t* data, size_t len, uint8_t addr) {
@ -96,7 +96,7 @@ int16_t PhysicalLayer::receive(String& str, size_t len) {
data[length] = 0;
// initialize Arduino String class
str = String((char*)data);
str = String(reinterpret_cast<char*>(data));
}
// deallocate temporary buffer
@ -132,11 +132,18 @@ int16_t PhysicalLayer::startReceive() {
}
int16_t PhysicalLayer::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)timeout;
(void)irqFlags;
(void)irqMask;
(void)len;
return(RADIOLIB_ERR_UNSUPPORTED);
RadioModeConfig_t cfg = {
.receive = {
.timeout = timeout,
.irqFlags = irqFlags,
.irqMask = irqMask,
.len = len,
}
};
int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_RX, &cfg);
RADIOLIB_ASSERT(state);
return(this->launchMode());
}
#if defined(RADIOLIB_BUILD_ARDUINO)
@ -146,14 +153,21 @@ int16_t PhysicalLayer::startTransmit(String& str, uint8_t addr) {
#endif
int16_t PhysicalLayer::startTransmit(const char* str, uint8_t addr) {
return(startTransmit((uint8_t*)str, strlen(str), addr));
return(startTransmit(reinterpret_cast<uint8_t*>(const_cast<char*>(str)), strlen(str), addr));
}
int16_t PhysicalLayer::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
(void)data;
(void)len;
(void)addr;
return(RADIOLIB_ERR_UNSUPPORTED);
RadioModeConfig_t cfg = {
.transmit = {
.data = data,
.len = len,
.addr = addr,
}
};
int16_t state = this->stageMode(RADIOLIB_RADIO_MODE_TX, &cfg);
RADIOLIB_ASSERT(state);
return(this->launchMode());
}
int16_t PhysicalLayer::finishTransmit() {
@ -191,7 +205,7 @@ int16_t PhysicalLayer::readData(String& str, size_t len) {
data[length] = 0;
// initialize Arduino String class
str = String((char*)data);
str = String(reinterpret_cast<char*>(data));
}
// deallocate temporary buffer
@ -280,10 +294,6 @@ int16_t PhysicalLayer::checkDataRate(DataRate_t dr) {
return(RADIOLIB_ERR_UNSUPPORTED);
}
float PhysicalLayer::getFreqStep() const {
return(this->freqStep);
}
size_t PhysicalLayer::getPacketLength(bool update) {
(void)update;
return(0);
@ -537,6 +547,16 @@ int16_t PhysicalLayer::getModem(ModemType_t* modem) {
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg) {
(void)mode;
(void)cfg;
return(RADIOLIB_ERR_UNSUPPORTED);
}
int16_t PhysicalLayer::launchMode() {
return(RADIOLIB_ERR_UNSUPPORTED);
}
#if RADIOLIB_INTERRUPT_TIMING
void PhysicalLayer::setInterruptSetup(void (*func)(uint32_t)) {
Module* mod = getMod();

View file

@ -130,6 +130,58 @@ union ChannelScanConfig_t {
RSSIScanConfig_t rssi;
};
struct StandbyConfig_t {
/*! \brief Module-specific standby mode configuration. */
uint8_t mode;
};
struct ReceiveConfig_t {
/*! \brief Raw timeout value. Some modules use this argument to specify operation mode (single vs. continuous receive). */
uint32_t timeout;
/*! \brief Sets the IRQ flags. */
RadioLibIrqFlags_t irqFlags;
/*! \brief Sets the mask of IRQ flags that will trigger the radio interrupt pin. */
RadioLibIrqFlags_t irqMask;
/*! \brief Packet length, needed for some modules under special circumstances (e.g. LoRa implicit header mode). */
size_t len;
};
struct TransmitConfig_t {
/*! \brief Binary data that will be transmitted. */
const uint8_t* data;
/*! \brief Length of binary data to transmit (in bytes). */
size_t len;
/*! \brief Node address to transmit the packet to. Only used in FSK mode. */
uint8_t addr;
};
struct SleepConfig_t {
/*! \brief Module-specific sleep mode configuration. */
uint8_t mode;
};
union RadioModeConfig_t {
/*! \brief Interpretation for standby mode */
StandbyConfig_t standby;
/*! \brief Interpretation for Rx mode */
ReceiveConfig_t receive;
/*! \brief Interpretation for Tx mode */
TransmitConfig_t transmit;
/*! \brief Interpretation for scanning */
ChannelScanConfig_t scan;
/*! \brief Interpretation for sleep mode */
SleepConfig_t sleep;
};
/*!
\enum ModemType_t
\brief Type of modem, used by setModem.
@ -140,6 +192,19 @@ enum ModemType_t {
RADIOLIB_MODEM_LRFHSS,
};
/*!
\enum RadioModeType_t
\brief Basic radio operating modes, used by stageMode.
*/
enum RadioModeType_t {
RADIOLIB_RADIO_MODE_NONE = 0,
RADIOLIB_RADIO_MODE_STANDBY,
RADIOLIB_RADIO_MODE_RX,
RADIOLIB_RADIO_MODE_TX,
RADIOLIB_RADIO_MODE_SCAN,
RADIOLIB_RADIO_MODE_SLEEP,
};
/*!
\class PhysicalLayer
@ -151,14 +216,18 @@ enum ModemType_t {
class PhysicalLayer {
public:
/*! \brief Frequency step of the synthesizer in Hz. */
float freqStep;
/*! \brief Maximum length of packet that can be received by the module. */
size_t maxPacketLength;
// constructor
/*!
\brief Default constructor.
\param step Frequency step of the synthesizer in Hz.
\param maxLen Maximum length of packet that can be received by the module.
*/
PhysicalLayer(float step, size_t maxLen);
PhysicalLayer();
// basic methods
@ -241,7 +310,7 @@ class PhysicalLayer {
\param len Packet length, needed for some modules under special circumstances (e.g. LoRa implicit header mode).
\returns \ref status_codes
*/
virtual int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len);
virtual int16_t startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK, size_t len = 0);
/*!
\brief Binary receive method. Must be implemented in module class.
@ -410,12 +479,6 @@ class PhysicalLayer {
*/
virtual int16_t checkDataRate(DataRate_t dr);
/*!
\brief Gets the module frequency step size that was set in constructor.
\returns Synthesizer frequency step size in Hz.
*/
float getFreqStep() const;
/*!
\brief Query modem for the packet length of received payload. Must be implemented in module class.
\param update Update received packet length. Will return cached value when set to false.
@ -669,6 +732,20 @@ class PhysicalLayer {
*/
virtual int16_t getModem(ModemType_t* modem);
/*!
\brief Stage mode of the radio to be launched later using launchMode.
\param mode Radio mode to prepare.
\param cfg Configuration of this mode (mode-dependent).
\returns \ref status_codes
*/
virtual int16_t stageMode(RadioModeType_t mode, RadioModeConfig_t* cfg);
/*!
\brief Launch previously staged mode.
\returns \ref status_codes
*/
virtual int16_t launchMode();
#if RADIOLIB_INTERRUPT_TIMING
/*!
@ -690,6 +767,7 @@ class PhysicalLayer {
protected:
#endif
uint32_t irqMap[10] = { 0 };
RadioModeType_t stagedMode = RADIOLIB_RADIO_MODE_NONE;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
void updateDirectBuffer(uint8_t bit);
@ -698,8 +776,6 @@ class PhysicalLayer {
#if !RADIOLIB_GODMODE
private:
#endif
float freqStep;
size_t maxPacketLength;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
uint8_t bufferBitPos = 0;

View file

@ -122,11 +122,15 @@ uint16_t ITA2String::getBits(char c) {
// search ITA2 table
uint16_t code = 0x0000;
for(uint8_t i = 0; i < RADIOLIB_ITA2_LENGTH; i++) {
if(RADIOLIB_NONVOLATILE_READ_BYTE(&ITA2Table[i][0]) == c) {
char* ptr = const_cast<char*>(&ITA2Table[i][0]);
if(RADIOLIB_NONVOLATILE_READ_BYTE(ptr) == c) {
// character is in letter shift
code = (RADIOLIB_ITA2_LTRS << 5) | i;
break;
} else if(RADIOLIB_NONVOLATILE_READ_BYTE(&ITA2Table[i][1]) == c) {
}
ptr = const_cast<char*>(&ITA2Table[i][1]);
if(RADIOLIB_NONVOLATILE_READ_BYTE(ptr) == c) {
// character is in figures shift
code = (RADIOLIB_ITA2_FIGS << 5) | i;
break;

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