kopia lustrzana https://github.com/jgromes/RadioLib
Porównaj commity
257 Commity
Autor | SHA1 | Data |
---|---|---|
![]() |
bc36c1e98a | |
![]() |
940eb07674 | |
![]() |
a8b6c38488 | |
![]() |
e855636384 | |
![]() |
81b9e6cd53 | |
![]() |
68d0e393b7 | |
![]() |
38abf92aaf | |
![]() |
e42cd7e2a5 | |
![]() |
aebbdd4c93 | |
![]() |
5d9917eb06 | |
![]() |
b8d5b984d1 | |
![]() |
954477b0c0 | |
![]() |
e1830052a3 | |
![]() |
7d96b4290e | |
![]() |
6bd3f92cad | |
![]() |
62df57885a | |
![]() |
2536d8842c | |
![]() |
a465f64969 | |
![]() |
3af427fefb | |
![]() |
f78b3ccc97 | |
![]() |
852d336c50 | |
![]() |
c3e99c8698 | |
![]() |
0d491060b2 | |
![]() |
bb7c6592fc | |
![]() |
cc2cb2c9a0 | |
![]() |
41f89198aa | |
![]() |
79d10c242a | |
![]() |
9a9e04d047 | |
![]() |
a5e2e58c36 | |
![]() |
99bb025173 | |
![]() |
525fdfb1a0 | |
![]() |
45d3aac0d9 | |
![]() |
6c11480416 | |
![]() |
16710d4dae | |
![]() |
195339a0c7 | |
![]() |
77bc8fb33e | |
![]() |
214a566d9a | |
![]() |
139fc7ee35 | |
![]() |
7186ae598b | |
![]() |
237531c9a0 | |
![]() |
ceb91c91c7 | |
![]() |
d4b25e75af | |
![]() |
88b4da94c1 | |
![]() |
fe221cf84f | |
![]() |
875da9d89d | |
![]() |
4a011e0915 | |
![]() |
8864a2a10a | |
![]() |
84402968c2 | |
![]() |
298a612699 | |
![]() |
bfb27ec8c9 | |
![]() |
e52fe99f03 | |
![]() |
90627325d3 | |
![]() |
8cda0d7a26 | |
![]() |
bcbefab4e8 | |
![]() |
020a2ce8df | |
![]() |
2b65070212 | |
![]() |
f660f2794f | |
![]() |
f2e1b547d5 | |
![]() |
e121f963dc | |
![]() |
648268d5c1 | |
![]() |
ffafb7353d | |
![]() |
764c0bf271 | |
![]() |
534a2f2d62 | |
![]() |
98c80a9cb9 | |
![]() |
60d1738c91 | |
![]() |
76f61144df | |
![]() |
9ebafbe507 | |
![]() |
4ab0ac8a13 | |
![]() |
5e398bd868 | |
![]() |
8f5440e4b5 | |
![]() |
ffbcdd0d57 | |
![]() |
b5fd75b4dc | |
![]() |
47f5569e7f | |
![]() |
3b412d7521 | |
![]() |
5ac5bdaadc | |
![]() |
f9af9b4d3f | |
![]() |
63ef9e0977 | |
![]() |
b336dd59f9 | |
![]() |
f12875fac5 | |
![]() |
23dcc4b8b7 | |
![]() |
6fe3eb67e4 | |
![]() |
58c8d2d1f4 | |
![]() |
9e8da76740 | |
![]() |
71ccce4a3d | |
![]() |
e3f851ef6d | |
![]() |
0e28810bb0 | |
![]() |
f3d358bbe3 | |
![]() |
dd9dc39f69 | |
![]() |
330f4e8fe1 | |
![]() |
356e8c8546 | |
![]() |
a93e7b93de | |
![]() |
d4e7af836c | |
![]() |
1dcd61b71d | |
![]() |
be4ad51330 | |
![]() |
f0ed8cdf00 | |
![]() |
f72f7bd46d | |
![]() |
909969aa15 | |
![]() |
89e406775d | |
![]() |
48ed06aa4b | |
![]() |
d779a834a0 | |
![]() |
f53d5b9027 | |
![]() |
0f0ab73832 | |
![]() |
914c616c2a | |
![]() |
98bae46c33 | |
![]() |
ac07269f97 | |
![]() |
d61589a2c5 | |
![]() |
44b2dcaa15 | |
![]() |
3d9815f93d | |
![]() |
e35689cbaa | |
![]() |
2f867153f9 | |
![]() |
c641099e9f | |
![]() |
dec7265f72 | |
![]() |
a643d0db7a | |
![]() |
4d7c16bd44 | |
![]() |
46e6f78731 | |
![]() |
d12e9f11f5 | |
![]() |
c494b983f5 | |
![]() |
2f06885f9f | |
![]() |
8a4514703b | |
![]() |
bfb7c8dd3b | |
![]() |
8eac3f1bf2 | |
![]() |
df9e9ee68c | |
![]() |
be56474596 | |
![]() |
44afc5a6f5 | |
![]() |
2a776f4c09 | |
![]() |
90eca88859 | |
![]() |
2c9446ef1e | |
![]() |
3b62c88a2e | |
![]() |
4f52738ed4 | |
![]() |
26fb617062 | |
![]() |
4f1e5c5521 | |
![]() |
bcd8a05cd4 | |
![]() |
86cdefe8a2 | |
![]() |
bb7fffe95d | |
![]() |
bbeca9a53e | |
![]() |
163a4020d2 | |
![]() |
43adfee174 | |
![]() |
639ff00109 | |
![]() |
b675e0c034 | |
![]() |
6fe581aea7 | |
![]() |
7209690bf6 | |
![]() |
92cb09a932 | |
![]() |
809025eba6 | |
![]() |
cb9cb87556 | |
![]() |
97adb260ce | |
![]() |
05e35407f4 | |
![]() |
2f85326fec | |
![]() |
1b2b8bd67b | |
![]() |
841b283c0f | |
![]() |
205031550b | |
![]() |
ecfc18c35d | |
![]() |
43ca08d8ee | |
![]() |
e8a6297c60 | |
![]() |
ce4d9aa150 | |
![]() |
9451f36332 | |
![]() |
01208574d9 | |
![]() |
b283c1b117 | |
![]() |
3c502b9cdf | |
![]() |
99d2e6c452 | |
![]() |
6fa4aa3ebb | |
![]() |
4d1157e3a4 | |
![]() |
88e1411399 | |
![]() |
4a6e182789 | |
![]() |
7bb747fdba | |
![]() |
f956a66ef2 | |
![]() |
23f45153c1 | |
![]() |
6d232a64cf | |
![]() |
77ed4452ae | |
![]() |
e7da14421d | |
![]() |
46ef20ebe9 | |
![]() |
91f89fa1f3 | |
![]() |
c11ac4703b | |
![]() |
d77823375a | |
![]() |
c9d8c601df | |
![]() |
f982314858 | |
![]() |
4fa0656ddd | |
![]() |
f61be0d273 | |
![]() |
263f7883cf | |
![]() |
a387b3b706 | |
![]() |
5d741779a1 | |
![]() |
aa46a0c8b3 | |
![]() |
a4ad32e6ff | |
![]() |
fbee7471c7 | |
![]() |
e7ee407b0d | |
![]() |
e57c9b08ea | |
![]() |
e5493618a4 | |
![]() |
9daf4c4f26 | |
![]() |
b2c7e98d6c | |
![]() |
721a44c6e4 | |
![]() |
88f26c4aab | |
![]() |
fb7d698007 | |
![]() |
8098bea254 | |
![]() |
eba32d7dcd | |
![]() |
5980e0fb00 | |
![]() |
aafe96faf8 | |
![]() |
936a39ad98 | |
![]() |
1fb5100413 | |
![]() |
0707a326a5 | |
![]() |
78211e7566 | |
![]() |
b91fd2bdad | |
![]() |
9cf04b633d | |
![]() |
5c891ae337 | |
![]() |
5391d5d383 | |
![]() |
c77670c076 | |
![]() |
7b5211130a | |
![]() |
0ed586a840 | |
![]() |
b3ed84a035 | |
![]() |
648b455cff | |
![]() |
9e4783cf8b | |
![]() |
9c6eb20169 | |
![]() |
388a714e53 | |
![]() |
14e1a9bd42 | |
![]() |
61b94bf4fc | |
![]() |
2d454bdc61 | |
![]() |
2f1efdb8a0 | |
![]() |
d1b911b273 | |
![]() |
18c1ce47b4 | |
![]() |
c0ebd5a92e | |
![]() |
ff5ade2aa1 | |
![]() |
5bc97550ec | |
![]() |
0182a123fb | |
![]() |
cfc425970c | |
![]() |
44f6c1d432 | |
![]() |
ca2a3073b9 | |
![]() |
3d5f05b963 | |
![]() |
0b11d101aa | |
![]() |
9fd7db4d13 | |
![]() |
b288485d6c | |
![]() |
24ffbfc284 | |
![]() |
4993ac7c9d | |
![]() |
4ee17cc168 | |
![]() |
9774a2299b | |
![]() |
cf561733d2 | |
![]() |
268e2d704f | |
![]() |
a926d5e13a | |
![]() |
3d8c2e866d | |
![]() |
ec9126dae0 | |
![]() |
7389d74e69 | |
![]() |
22045d7189 | |
![]() |
744834509f | |
![]() |
10acb6d9ca | |
![]() |
a52920bcb2 | |
![]() |
5766d386af | |
![]() |
5c30bb1e32 | |
![]() |
9f0bdffc50 | |
![]() |
0ea00fad44 | |
![]() |
bb239468ef | |
![]() |
ea2ccfd6d0 | |
![]() |
a907026c7b | |
![]() |
e4267760f9 | |
![]() |
7945ffb996 | |
![]() |
bce14023f9 | |
![]() |
547328f375 | |
![]() |
d208f46f93 | |
![]() |
a168f9ba41 | |
![]() |
118980fd27 | |
![]() |
5ebea18572 |
|
@ -0,0 +1,3 @@
|
|||
# exclude binary patch files from language detection
|
||||
src/modules/SX126x/patches/*.h linguist-detectable=false
|
||||
src/modules/LR11x0/firmware/*.h linguist-detectable=false
|
|
@ -8,10 +8,10 @@ assignees: ''
|
|||
---
|
||||
|
||||
**IMPORTANT: Check the wiki**
|
||||
Before submitting new issue, please check the [Wiki](https://github.com/jgromes/RadioLib/wiki) and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. When applicable, please include [debug mode output](https://github.com/jgromes/RadioLib/wiki/Debug-mode).
|
||||
A clear and concise description of what the bug is. When applicable, please include [debug mode output](https://github.com/jgromes/RadioLib/wiki/Debug-mode) **using the appropriate debug mode**.
|
||||
|
||||
**To Reproduce**
|
||||
Minimal Arduino sketch to reproduce the behavior. Please use Markdown to style the code to make it readable (see [Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code)).
|
||||
|
|
|
@ -8,7 +8,7 @@ assignees: ''
|
|||
---
|
||||
|
||||
**IMPORTANT: Check the wiki**
|
||||
Before submitting new issue, please check the [Wiki](https://github.com/jgromes/RadioLib/wiki) and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
|
|
@ -9,7 +9,7 @@ assignees: ''
|
|||
|
||||
**IMPORTANT: Before submitting an issue, please check the following:**
|
||||
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
|
||||
2. RadioLib has a [Wiki](https://github.com/jgromes/RadioLib/wiki) and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
|
||||
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
|
||||
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).
|
||||
|
@ -24,7 +24,7 @@ paste the sketch here, even if it is an unmodified example code
|
|||
Wiring diagram, schematic, pictures etc.
|
||||
|
||||
**Debug mode output**
|
||||
Enable all [debug levels](https://github.com/jgromes/RadioLib/wiki/Debug-mode) and paste the Serial monitor output here.
|
||||
Enable the appropriate [debug levels](https://github.com/jgromes/RadioLib/wiki/Debug-mode) and paste the Serial monitor output here. For debugging protocols, enable `RADIOLIB_DEBUG_PROTOCOL`. For debugging issues with the radio module itself, enable `RADIOLIB_DEBUG_SPI`.
|
||||
|
||||
**Additional info (please complete):**
|
||||
- MCU: [e.g. Arduino Uno, ESP8266 etc.]
|
||||
|
|
|
@ -9,7 +9,7 @@ assignees: ''
|
|||
|
||||
**IMPORTANT: Before submitting an issue, please check the following:**
|
||||
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
|
||||
2. RadioLib has a [Wiki](https://github.com/jgromes/RadioLib/wiki) and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
|
||||
3. Make sure you're using the latest release of the library! Releases can be found [here](https://github.com/jgromes/RadioLib/releases).
|
||||
4. Use [Arduino forums](https://forum.arduino.cc/) to ask generic questions about wireless modules, wiring, usage, etc. Only create issues for problems specific to RadioLib!
|
||||
5. Error codes, their meaning and how to fix them can be found on [this page](https://jgromes.github.io/RadioLib/group__status__codes.html).
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
## Pull request template
|
||||
Thank you for taking the time to contribute to RadioLib development!
|
||||
To keep this library organized, please follow these rules.
|
||||
|
||||
1. Make sure the the code in your PR is tested and that you understand all its impacts.
|
||||
2. Ensure that all CI actions pass - PRs with failed CI will not be merged. CI actions run automatically for every commit pushed to the PR and test the following:
|
||||
a. Compilation for Arduino, ESP-IDF and on Raspberry Pi
|
||||
b. Runtime test on Raspberry Pi
|
||||
c. GitHub CodeQL check
|
||||
d. Cppcheck static code scan
|
||||
3. Follow code style guidelines in [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)
|
||||
4. Heads up - all PRs undergo review, during which you may be asked to correct or change some things. The purpose of this review is to keep regressions and bugs at the minimum, and to keep consistent coding style. Please take them as constructive criticism from people who may have a different point-of-view than you do.
|
||||
|
||||
After addressing/accepting the points above, delete the contents of this template and replace it with text explaining what is the goal of your PR, why you want to add it to the upstream and what are the foreseen impacts. Once again, thank you for taking the time to contribute!
|
|
@ -5,11 +5,14 @@ on:
|
|||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -18,20 +21,11 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
|
@ -63,4 +57,4 @@ jobs:
|
|||
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn arduino:avr:uno $PWD/examples/SX126x/SX126x_Transmit_Blocking/SX126x_Transmit_Blocking.ino --warnings=all
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
name: "Cppcheck"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Perform static code check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install cppcheck
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cppcheck
|
||||
|
||||
- name: Run cppcheck
|
||||
run: ./extras/cppcheck/cppcheck.sh
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y doxygen
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Generate docs
|
||||
run: doxygen Doxyfile
|
||||
|
|
|
@ -46,26 +46,26 @@ jobs:
|
|||
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
|
||||
include:
|
||||
- id: arduino:avr:uno
|
||||
run: echo "skip-pattern=(STM32WL|SSTV|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
run: echo "skip-pattern=(STM32WL|SSTV|LoRaWAN|LR11x0_Firmware_Update|Pager)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:avr:mega
|
||||
run: echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:mbed:nano33ble
|
||||
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:mbed:envie_m4
|
||||
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:megaavr:uno2018
|
||||
run: |
|
||||
echo "options=':mode=on'" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:sam:arduino_due_x
|
||||
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:samd:arduino_zero_native
|
||||
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: adafruit:samd:adafruit_feather_m0
|
||||
run: |
|
||||
echo "options=':usbstack=arduino,debug=off'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: adafruit:nrf52:feather52832
|
||||
run: |
|
||||
sudo apt-get update
|
||||
|
@ -75,7 +75,7 @@ jobs:
|
|||
echo "/home/runner/.local/bin" >> $GITHUB_PATH
|
||||
echo "options=':softdevice=s132v6,debug=l0'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: esp32:esp32:esp32
|
||||
run: |
|
||||
python -m pip install pyserial
|
||||
|
@ -84,35 +84,47 @@ jobs:
|
|||
run: |
|
||||
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: Intel:arc32:arduino_101
|
||||
- id: SparkFun:apollo3:sfe_artemis
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
echo "warnings='none'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json" >> $GITHUB_OUTPUT
|
||||
- id: STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
|
||||
run: echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
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
|
||||
run: |
|
||||
# Do *not* skip STM32WL examples
|
||||
echo "skip-pattern=''" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern='LR11x0_Firmware_Update'" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json" >> $GITHUB_OUTPUT
|
||||
- id: stm32duino:STM32F1:mapleMini
|
||||
run: |
|
||||
echo "options=':bootloader_version=original,cpu_speed=speed_72mhz'" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json" >> $GITHUB_OUTPUT
|
||||
- id: MegaCoreX:megaavr:4809
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: arduino:mbed_rp2040:pico
|
||||
run: echo "skip-pattern=(STM32WL|LoRaWAN_End_Device_Persistent)" >> $GITHUB_OUTPUT
|
||||
- id: rp2040:rp2040:rpipico
|
||||
run: echo "index-url=--additional-urls https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json" >> $GITHUB_OUTPUT
|
||||
- id: CubeCell:CubeCell:CubeCell-Board
|
||||
run: echo "index-url=--additional-urls https://resource.heltec.cn/download/package_CubeCell_index.json" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://resource.heltec.cn/download/package_CubeCell_index.json" >> $GITHUB_OUTPUT
|
||||
- id: MegaCore:avr:1281
|
||||
run: echo "index-url=--additional-urls https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json" >> $GITHUB_OUTPUT
|
||||
run: |
|
||||
echo "index-url=--additional-urls https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json" >> $GITHUB_OUTPUT
|
||||
echo "skip-pattern=(STM32WL|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
- id: teensy:avr:teensy41
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://www.pjrc.com/teensy/package_teensy_index.json" >> $GITHUB_OUTPUT
|
||||
- id: arduino:renesas_uno:minima
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN|LR11x0_Firmware_Update)" >> $GITHUB_OUTPUT
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
name: ${{ matrix.id }}
|
||||
|
@ -158,7 +170,7 @@ jobs:
|
|||
|
||||
- name: Checkout repository
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build examples
|
||||
if: ${{ env.run-build == 'true' }}
|
||||
|
@ -170,9 +182,14 @@ jobs:
|
|||
# skip sketch
|
||||
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with ${{ steps.prep.outputs.skip-pattern }})\033[0m";
|
||||
else
|
||||
# apply special flags for LoRaWAN
|
||||
if [[ ${example} =~ "LoRaWAN" ]]; then
|
||||
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
|
||||
fi
|
||||
|
||||
# build sketch
|
||||
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
|
||||
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn ${{ matrix.id }}${{ steps.prep.outputs.options }} $example --warnings=${{ steps.prep.outputs.warnings }}
|
||||
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn ${{ matrix.id }}${{ steps.prep.outputs.options }} --build-property compiler.cpp.extra_flags="$flags" $example --warnings=${{ steps.prep.outputs.warnings }}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo -e "\033[1;31m${example##*/} build FAILED\033[0m\n";
|
||||
exit 1;
|
||||
|
@ -186,10 +203,12 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
|
||||
|
||||
- name: Clone ESP-IDF
|
||||
run: |
|
||||
|
@ -212,7 +231,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
@ -221,24 +240,31 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -y gcc-arm-none-eabi
|
||||
sudo apt-get install -y gcc-arm-none-eabi gcc-riscv64-unknown-elf
|
||||
cargo install elf2tab
|
||||
|
||||
- name: Build the example
|
||||
run: |
|
||||
cd $PWD/examples/NonArduino/Tock
|
||||
./build.sh
|
||||
git clone https://github.com/tock/libtock-c.git
|
||||
cd libtock-c; git checkout dbee65a56d74b4bad166317f199e80b959f7c82c; cd ../
|
||||
LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
|
||||
|
||||
rpi-build:
|
||||
runs-on: [self-hosted, ARM64]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y pigpio cmake
|
||||
sudo apt-get install -y cmake wget swig python-dev python3-dev python-setuptools python3-setuptools
|
||||
wget http://abyz.me.uk/lg/lg.zip
|
||||
unzip lg.zip
|
||||
cd lg
|
||||
make
|
||||
sudo make install
|
||||
|
||||
- name: Install the library
|
||||
run: |
|
||||
|
@ -268,7 +294,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
|
|
@ -23,3 +23,6 @@ extras/SX126x_Spectrum_Scan/out/*
|
|||
|
||||
# cmake
|
||||
build/
|
||||
|
||||
# Compote build output
|
||||
dist
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "examples/NonArduino/Tock/libtock-c"]
|
||||
path = examples/NonArduino/Tock/libtock-c
|
||||
url = https://github.com/tock/libtock-c.git
|
|
@ -32,6 +32,12 @@ target_include_directories(RadioLib
|
|||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
# use c++20 standard
|
||||
set_property(TARGET RadioLib PROPERTY CXX_STANDARD 20)
|
||||
|
||||
# enable most warnings
|
||||
target_compile_options(RadioLib PRIVATE -Wall -Wextra)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS RadioLib
|
||||
|
|
13
README.md
13
README.md
|
@ -1,4 +1,4 @@
|
|||
# RadioLib ![Build Status](https://github.com/jgromes/RadioLib/workflows/CI/badge.svg) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/jgromes/library/RadioLib.svg)](https://registry.platformio.org/libraries/jgromes/RadioLib)
|
||||
# RadioLib ![Build Status](https://github.com/jgromes/RadioLib/workflows/CI/badge.svg) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/jgromes/library/RadioLib.svg)](https://registry.platformio.org/libraries/jgromes/RadioLib) [![Component Registry](https://components.espressif.com/components/jgromes/radiolib/badge.svg)](https://components.espressif.com/components/jgromes/radiolib)
|
||||
|
||||
### _One radio library to rule them all!_
|
||||
|
||||
|
@ -16,6 +16,7 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
### Supported modules:
|
||||
* __CC1101__ FSK radio module
|
||||
* __LLCC68__ LoRa module
|
||||
* __LR11x0__ series LoRa/GFSK modules (LR1110, LR1120, LR1121)
|
||||
* __nRF24L01__ 2.4 GHz module
|
||||
* __RF69__ FSK/OOK radio module
|
||||
* __RFM2x__ series FSK modules (RFM22, RM23)
|
||||
|
@ -29,21 +30,21 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
|
||||
### Supported protocols and digital modes:
|
||||
* [__AX.25__](https://www.sigidwiki.com/wiki/PACKET) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x and Si443x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__RTTY__](https://www.sigidwiki.com/wiki/RTTY) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__Morse Code__](https://www.sigidwiki.com/wiki/Morse_Code_(CW)) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__SSTV__](https://www.sigidwiki.com/wiki/SSTV) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x and Si443x
|
||||
* [__Hellschreiber__](https://www.sigidwiki.com/wiki/Hellschreiber) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__APRS__](https://www.sigidwiki.com/wiki/APRS) using AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
* [__POCSAG__](https://www.sigidwiki.com/wiki/POCSAG) using 2-FSK for modules:
|
||||
SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
|
||||
* [__LoRaWAN__](https://lora-alliance.org/) using LoRa for modules:
|
||||
SX127x, RFM9x, SX126x and SX128x
|
||||
SX127x, RFM9x, SX126x, LR11x0 and SX128x
|
||||
* NOTE: LoRaWAN support is currently in beta, feedback via [Issues](https://github.com/jgromes/RadioLib/issues) and [Discussions](https://github.com/jgromes/RadioLib/discussions) is appreciated!
|
||||
|
||||
### Supported Arduino platforms:
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
- SX127x/RFM9x
|
||||
- SX126x/LLCC68
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
- SX126x
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- LR11x0
|
||||
|
||||
Using raw AX.25 frames requires some
|
||||
knowledge of the protocol, refer to
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
- SX126x
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Channel Activity Detection Example
|
||||
|
||||
This example uses LR1110 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR11x0 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
Using blocking CAD is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt CAD is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Scanning channel for LoRa transmission ... "));
|
||||
|
||||
// start scanning current channel
|
||||
int state = radio.scanChannel();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa preamble was detected
|
||||
Serial.println(F("detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// no preamble was detected, channel is free
|
||||
Serial.println(F("channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait 100 ms before new scan
|
||||
delay(100);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
RadioLib LR11x0 Channel Activity Detection Example
|
||||
|
||||
This example uses LR1110 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR11x0 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[LR1110] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[LR1110] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[LR1110] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[LR1110] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[LR1110] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
RadioLib LR11x0 Firmware Update Example
|
||||
|
||||
This example updates the internal LR1110 firmware.
|
||||
Newer versions of the firmware introduce fixes
|
||||
and possibly even new features, so it is recommended
|
||||
to use the latest available firmware version
|
||||
when possible.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// select the firmware image you want to upload
|
||||
// WARNING: Make sure you select the correct firmware
|
||||
// for your device! Uploading incorrect firmware
|
||||
// (e.g. LR1110 firmware to LR1120 device)
|
||||
// may damage your hardware!
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_0303
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_0304
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_0305
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_0306
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_0307
|
||||
#define RADIOLIB_LR1110_FIRMWARE_0401
|
||||
//#define RADIOLIB_LR1120_FIRMWARE_0101
|
||||
//#define RADIOLIB_LR1120_FIRMWARE_0102
|
||||
//#define RADIOLIB_LR1120_FIRMWARE_0201
|
||||
//#define RADIOLIB_LR1121_FIRMWARE_0102
|
||||
//#define RADIOLIB_LR1121_FIRMWARE_0103
|
||||
|
||||
// enable this macro if you want to store the image in host
|
||||
// MCU RAM instead of Flash.
|
||||
// NOTE: the firmware images are very large, up to 240 kB!
|
||||
//#define RADIOLIB_LR1110_FIRMWARE_IN_RAM
|
||||
|
||||
// include the firmware image
|
||||
#include <modules/LR11x0/LR11x0_firmware.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// print the firmware versions before the update
|
||||
printVersions();
|
||||
|
||||
// prompt the user
|
||||
Serial.println(F("[LR1110] Send any character to start the update"));
|
||||
while(!Serial.available()) { delay(1); }
|
||||
|
||||
// upload update into LR11x0 non-volatile memory
|
||||
Serial.print(F("[LR1110] Updating firmware, this may take several seconds ... "));
|
||||
state = radio.updateFirmware(lr11xx_firmware_image, RADIOLIB_LR11X0_FIRMWARE_IMAGE_SIZE);
|
||||
/*
|
||||
use the following if you enabled RADIOLIB_LR1110_FIRMWARE_IN_RAM
|
||||
state = radio.updateFirmware(lr11xx_firmware_image, RADIOLIB_LR11X0_FIRMWARE_IMAGE_SIZE, false);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// print the firmware versions after the update
|
||||
printVersions();
|
||||
|
||||
}
|
||||
|
||||
void printVersions() {
|
||||
LR11x0VersionInfo_t version;
|
||||
Serial.print(F("[LR1110] Reading firmware versions ... "));
|
||||
int16_t state = radio.getVersionInfo(&version);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
Serial.print(F("[LR1110] Device: "));
|
||||
Serial.println(version.device);
|
||||
|
||||
Serial.print(F("[LR1110] Base firmware: "));
|
||||
Serial.print(version.fwMajor);
|
||||
Serial.print('.');
|
||||
Serial.println(version.fwMinor);
|
||||
|
||||
Serial.print(F("[LR1110] WiFi firmware: "));
|
||||
Serial.print(version.fwMajorWiFi);
|
||||
Serial.print('.');
|
||||
Serial.println(version.fwMinorWiFi);
|
||||
|
||||
Serial.print(F("[LR1110] GNSS firmware: "));
|
||||
Serial.print(version.fwGNSS);
|
||||
Serial.print('.');
|
||||
Serial.println(version.almanacGNSS);
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
RadioLib LR11x0 GFSK Modem Example
|
||||
|
||||
This example shows how to use GFSK modem in LR11x0 chips.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
GFSK modem, so this code should not be run directly!
|
||||
Instead, modify the other examples to use GFSK
|
||||
modem and use the appropriate configuration
|
||||
methods.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---gfsk-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.beginGFSK();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, you can switch between any of the modems
|
||||
//
|
||||
// radio.begin() start LoRa modem (and disable GFSK)
|
||||
// radio.beginGFSK() start GFSK modem (and disable LoRa)
|
||||
|
||||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setBitRate(100.0);
|
||||
state = radio.setFrequencyDeviation(10.0);
|
||||
state = radio.setRxBandwidth(250.0);
|
||||
state = radio.setOutputPower(10.0);
|
||||
state = radio.setDataShaping(RADIOLIB_SHAPING_1_0);
|
||||
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.setSyncWord(syncWord, 8);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Unable to set configuration, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// GFSK modem on LR11x0 can handle the sync word setting in bits, not just
|
||||
// whole bytes. The value used is left-justified.
|
||||
// This makes same result as radio.setSyncWord(syncWord, 8):
|
||||
state = radio.setSyncBits(syncWord, 64);
|
||||
// This will use 0x012 as sync word (12 bits only):
|
||||
state = radio.setSyncBits(syncWord, 12);
|
||||
|
||||
// GFSK modem allows advanced CRC configuration
|
||||
// Default is CCIT CRC16 (2 bytes, initial 0x1D0F, polynomial 0x1021, inverted)
|
||||
// Set CRC to IBM CRC (2 bytes, initial 0xFFFF, polynomial 0x8005, non-inverted)
|
||||
state = radio.setCRC(2, 0xFFFF, 0x8005, false);
|
||||
// set CRC length to 0 to disable CRC
|
||||
|
||||
#warning "This sketch is just an API guide! Read the note at line 6."
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// GFSK modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// transmit GFSK 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("[LR1110] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[LR1110] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[LR1110] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive GFSK packet
|
||||
String str;
|
||||
state = radio.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
Serial.print(F("[LR1110] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[LR1110] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// GFSK modem has built-in address filtering system
|
||||
// it can be enabled by setting node address, broadcast
|
||||
// address, or both
|
||||
//
|
||||
// to transmit packet to a particular address,
|
||||
// use the following methods:
|
||||
//
|
||||
// radio.transmit("Hello World!", address);
|
||||
// radio.startTransmit("Hello World!", address);
|
||||
|
||||
// set node address to 0x02
|
||||
state = radio.setNodeAddress(0x02);
|
||||
// set broadcast address to 0xFF
|
||||
state = radio.setBroadcastAddress(0xFF);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Unable to set address filter, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// address filtering can also be disabled
|
||||
// NOTE: calling this method will also erase previously set
|
||||
// node and broadcast address
|
||||
/*
|
||||
state = radio.disableAddressFiltering();
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("Unable to remove address filter, code "));
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
RadioLib LR11x0 LR-FHSS Modem Example
|
||||
|
||||
This example shows how to use LR-FHSS modem in LR11x0 chips.
|
||||
|
||||
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#lr11x0---lr-fhss-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] 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);
|
||||
}
|
||||
|
||||
// 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_LR11X0_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_LR11X0_LR_FHSS_CR_1_2, // coding rate
|
||||
3, // header count
|
||||
0x13A); // hopping sequence seed
|
||||
state = radio.setOutputPower(10.0);
|
||||
state = radio.setSyncWord(0x12345678);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Unable to set configuration, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
#warning "This sketch is just an API guide! Read the note at line 6."
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// LR-FHSS modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// 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("[LR1110] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[LR1110] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[LR1110] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive LR-FHSS packet
|
||||
String str;
|
||||
state = radio.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
Serial.print(F("[LR1110] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[LR1110] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Receive Example
|
||||
|
||||
This example listens for LoRa transmissions using LR11x0 Lora modules.
|
||||
To successfully receive data, the following settings have to be the same
|
||||
on both transmitter and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
- preamble length
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
Using blocking receive is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt receive is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Waiting for incoming transmission ... "));
|
||||
|
||||
// you can receive data as an Arduino String
|
||||
String str;
|
||||
int state = radio.receive(str);
|
||||
|
||||
// you can also receive data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the data of the packet
|
||||
Serial.print(F("[LR1110] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print the RSSI (Received Signal Strength Indicator)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR1110] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print the SNR (Signal-to-Noise Ratio)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR1110] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
RadioLib LR11x0 Receive with Interrupts Example
|
||||
|
||||
This example listens for LoRa transmissions and tries to
|
||||
receive them. Once a packet is received, an interrupt is
|
||||
triggered. To successfully receive data, the following
|
||||
settings have to be the same on both transmitter
|
||||
and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR1110] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, 'listen' mode can be disabled by calling
|
||||
// any of the following methods:
|
||||
//
|
||||
// radio.standby()
|
||||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int numBytes = radio.getPacketLength();
|
||||
int state = radio.readData(byteArr, numBytes);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[LR1110] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LR1110] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LR1110] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Transmit Example
|
||||
|
||||
This example transmits packets using LR1110 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 LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
delay(1000);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
// NOTE: transmit() is a blocking method!
|
||||
// See example LR11x0_Transmit_Interrupt for details
|
||||
// on non-blocking transmission method.
|
||||
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("[LR1110] 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 occured 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);
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
RadioLib LR11x0 Transmit with Interrupts Example
|
||||
|
||||
This example transmits LoRa packets with one second delays
|
||||
between them. 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 LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setPacketSentAction(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[LR1110] 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);
|
||||
*/
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
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("[LR1110] 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);
|
||||
*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
RadioLib LR11x0 WiFi scan Blocking Example
|
||||
|
||||
This example performs a passive scan of WiFi networks.
|
||||
The scan shows basic information about the networks,
|
||||
such as the frequency, country code and SSID.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
Using blocking scan is not recommended, as depending
|
||||
on the scan settings, the program may be blocked
|
||||
for several seconds! Instead, interrupt scan is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---wifi-scan
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Running WiFi scan ... "));
|
||||
|
||||
// scan all WiFi signals with default scan configuration
|
||||
uint8_t count = 0;
|
||||
int state = radio.wifiScan('*', &count);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the table header
|
||||
Serial.print(F("[LR1110] Reading "));
|
||||
Serial.print(count);
|
||||
Serial.println(F(" scan results:"));
|
||||
Serial.println(F(" # | WiFi type\t| Frequency\t| MAC Address\t | Country\t| RSSI [dBm]\t| SSID"));
|
||||
|
||||
// read all results one by one
|
||||
// this result type contains the most information, including the SSID
|
||||
LR11x0WifiResultExtended_t result;
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(i < 10) { Serial.print(" "); } Serial.print(i); Serial.print(" | ");
|
||||
state = radio.getWifiScanResult(&result, i);
|
||||
if(state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Failed to read result, code "));
|
||||
Serial.println(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
// print the basic information
|
||||
Serial.print(F("802.11")); Serial.print(result.type); Serial.print("\t| ");
|
||||
Serial.print(result.channelFreq); Serial.print(" MHz\t| ");
|
||||
|
||||
// print MAC address
|
||||
for(int j = 0; j < 6; j++) {
|
||||
if(result.mac[j] < 0x10) { Serial.print("0"); }
|
||||
Serial.print(result.mac[j], HEX);
|
||||
if(j < 5) { Serial.print(":"); }
|
||||
}
|
||||
Serial.print(" | ");
|
||||
|
||||
// print the two-letter country code
|
||||
String country = result.countryCode;
|
||||
Serial.print(country);
|
||||
Serial.print(" \t| ");
|
||||
|
||||
// print the RSSI
|
||||
Serial.print(result.rssi);
|
||||
Serial.print("\t| ");
|
||||
|
||||
// print the network SSID
|
||||
Serial.println((char*)result.ssid);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before scanning again
|
||||
delay(1000);
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
RadioLib LR11x0 WiFi scan Interrupt Example
|
||||
|
||||
This example performs a passive scan of WiFi networks.
|
||||
The scan shows basic information about the networks,
|
||||
such as the frequency, country code and SSID.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
This example assumes Seeed Studio Wio WM1110 is used.
|
||||
For other LR11x0 modules, some configuration such as
|
||||
RF switch control may have to be adjusted.
|
||||
|
||||
Using blocking scan is not recommended, as depending
|
||||
on the scan settings, the program may be blocked
|
||||
for several seconds! Instead, interrupt scan is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---wifi-scan
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// set RF switch configuration for Wio WM1110
|
||||
// Wio WM1110 uses DIO5 and DIO6 for RF switching
|
||||
// NOTE: other boards may be different!
|
||||
static const uint32_t rfswitch_dio_pins[] = {
|
||||
RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6,
|
||||
RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC
|
||||
};
|
||||
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
// mode DIO5 DIO6
|
||||
{ LR11x0::MODE_STBY, { LOW, LOW } },
|
||||
{ LR11x0::MODE_RX, { HIGH, LOW } },
|
||||
{ LR11x0::MODE_TX, { HIGH, HIGH } },
|
||||
{ LR11x0::MODE_TX_HP, { LOW, HIGH } },
|
||||
{ LR11x0::MODE_TX_HF, { LOW, LOW } },
|
||||
{ LR11x0::MODE_GNSS, { LOW, LOW } },
|
||||
{ LR11x0::MODE_WIFI, { LOW, LOW } },
|
||||
END_OF_MODE_TABLE,
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// set RF switch control configuration
|
||||
// this has to be done prior to calling begin()
|
||||
radio.setRfSwitchTable(rfswitch_dio_pins, rfswitch_table);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when WiFi scan is complete
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
// scan all WiFi signals with default scan configuration
|
||||
Serial.print(F("[LR1110] Starting passive WiFi scan ... "));
|
||||
state = radio.startWifiScan('*');
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a scan was completed
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a scan is completed
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// scan is complete, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// get the number of scan results
|
||||
uint8_t count = 0;
|
||||
Serial.print(F("[LR1110] Reading WiFi scan results ... "));
|
||||
int state = radio.getWifiScanResultsCount(&count);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the table header
|
||||
Serial.print(F("[LR1110] Reading "));
|
||||
Serial.print(count);
|
||||
Serial.println(F(" scan results:"));
|
||||
Serial.println(F(" # | WiFi type\t| Frequency\t| MAC Address\t | Country\t| RSSI [dBm]\t| SSID"));
|
||||
|
||||
// read all results one by one
|
||||
// this result type contains the most information, including the SSID
|
||||
LR11x0WifiResultExtended_t result;
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(i < 10) { Serial.print(" "); } Serial.print(i); Serial.print(" | ");
|
||||
state = radio.getWifiScanResult(&result, i);
|
||||
if(state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Failed to read result, code "));
|
||||
Serial.println(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
// print the basic information
|
||||
Serial.print(F("802.11")); Serial.print(result.type); Serial.print("\t| ");
|
||||
Serial.print(result.channelFreq); Serial.print(" MHz\t| ");
|
||||
|
||||
// print MAC address
|
||||
for(int j = 0; j < 6; j++) {
|
||||
if(result.mac[j] < 0x10) { Serial.print("0"); }
|
||||
Serial.print(result.mac[j], HEX);
|
||||
if(j < 5) { Serial.print(":"); }
|
||||
}
|
||||
Serial.print(" | ");
|
||||
|
||||
// print the two-letter country code
|
||||
String country = result.countryCode;
|
||||
Serial.print(country);
|
||||
Serial.print(" \t| ");
|
||||
|
||||
// print the RSSI
|
||||
Serial.print(result.rssi);
|
||||
Serial.print("\t| ");
|
||||
|
||||
// print the network SSID
|
||||
Serial.println((char*)result.ssid);
|
||||
}
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// start scanning again
|
||||
Serial.print(F("[LR1110] Starting passive WiFi scan ... "));
|
||||
state = radio.startWifiScan('*');
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
RadioLib LoRaWAN ABP Example
|
||||
|
||||
ABP = Activation by Personalisation, an alternative
|
||||
to OTAA (Over the Air Activation). OTAA is preferable.
|
||||
|
||||
This example will send uplink packets to a LoRaWAN network.
|
||||
Before you start, you will have to register your device at
|
||||
https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
LoRaWAN v1.1 requires the use of persistent storage.
|
||||
As this example does not use persistent storage, running this
|
||||
examples REQUIRES you to check "Resets frame counters"
|
||||
on your LoRaWAN dashboard. Refer to the notes or the
|
||||
network's documentation on how to do this.
|
||||
To comply with LoRaWAN v1.1's persistent storage, refer to
|
||||
https://github.com/radiolib-org/radiolib-persistence
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
|
||||
For LoRaWAN details, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
*/
|
||||
|
||||
#include "configABP.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
Serial.println(F("Initialise the radio"));
|
||||
int state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
Serial.println(F("Initialise LoRaWAN Network credentials"));
|
||||
node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey);
|
||||
|
||||
node.activateABP();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Activate ABP failed"), state, true);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
// Perform an uplink
|
||||
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
|
||||
|
||||
// Wait until next uplink - observing legal & TTN FUP constraints
|
||||
delay(uplinkIntervalSeconds * 1000UL);
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints - see notes
|
||||
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
||||
|
||||
// device address - either a development address or one assigned
|
||||
// to the LoRaWAN Service Provider - TTN will generate one for you
|
||||
#ifndef RADIOLIB_LORAWAN_DEV_ADDR // Replace with your DevAddr
|
||||
#define RADIOLIB_LORAWAN_DEV_ADDR 0x------
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_LORAWAN_FNWKSINT_KEY // Replace with your FNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_FNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_SNWKSINT_KEY // Replace with your SNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_SNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_NWKSENC_KEY // Replace with your NwkSEnc Key
|
||||
#define RADIOLIB_LORAWAN_NWKSENC_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APPS_KEY // Replace with your AppS Key
|
||||
#define RADIOLIB_LORAWAN_APPS_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
|
||||
// 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
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
||||
// Auto select MCU <-> radio connections
|
||||
// If you get an error message when compiling, it may be that the
|
||||
// pinmap could not be determined - see the notes for more info
|
||||
|
||||
// Adafruit
|
||||
#if defined(ARDUINO_SAMD_FEATHER_M0)
|
||||
#pragma message ("Adafruit Feather M0 with RFM95")
|
||||
#pragma message ("Link required on board")
|
||||
SX1276 radio = new Module(8, 3, 4, 6);
|
||||
|
||||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1262)
|
||||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
// Pending verfication of which radio is shipped
|
||||
// #elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
// #pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
// SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
|
||||
// Following not verified
|
||||
#elif defined (ARDUINO_heltec_wireless_stick)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
|
||||
// If we don't recognise the board
|
||||
#else
|
||||
#pragma message ("Unknown board - no automagic pinmap available")
|
||||
|
||||
// SX1262 pin order: Module(NSS/CS, DIO1, RESET, BUSY);
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 pin order: Module(NSS/CS, DIO0, RESET, DIO1);
|
||||
// SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// For Pi Pico + Waveshare HAT - work in progress
|
||||
// SX1262 radio = new Module(3, 20, 15, 2, SPI1, RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
#endif
|
||||
|
||||
// copy over the keys in to the something that will not compile if incorrectly formatted
|
||||
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
|
||||
uint8_t fNwkSIntKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY };
|
||||
uint8_t sNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY };
|
||||
uint8_t nwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY };
|
||||
uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
|
||||
|
||||
// create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
||||
|
||||
// result code to text ...
|
||||
String stateDecode(const int16_t result) {
|
||||
switch (result) {
|
||||
case RADIOLIB_ERR_NONE:
|
||||
return "ERR_NONE";
|
||||
case RADIOLIB_ERR_CHIP_NOT_FOUND:
|
||||
return "ERR_CHIP_NOT_FOUND";
|
||||
case RADIOLIB_ERR_PACKET_TOO_LONG:
|
||||
return "ERR_PACKET_TOO_LONG";
|
||||
case RADIOLIB_ERR_RX_TIMEOUT:
|
||||
return "ERR_RX_TIMEOUT";
|
||||
case RADIOLIB_ERR_CRC_MISMATCH:
|
||||
return "ERR_CRC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
return "ERR_INVALID_SPREADING_FACTOR";
|
||||
case RADIOLIB_ERR_INVALID_CODING_RATE:
|
||||
return "ERR_INVALID_CODING_RATE";
|
||||
case RADIOLIB_ERR_INVALID_FREQUENCY:
|
||||
return "ERR_INVALID_FREQUENCY";
|
||||
case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
|
||||
return "ERR_INVALID_OUTPUT_POWER";
|
||||
case RADIOLIB_ERR_NETWORK_NOT_JOINED:
|
||||
return "RADIOLIB_ERR_NETWORK_NOT_JOINED";
|
||||
|
||||
case RADIOLIB_ERR_DOWNLINK_MALFORMED:
|
||||
return "RADIOLIB_ERR_DOWNLINK_MALFORMED";
|
||||
case RADIOLIB_ERR_INVALID_REVISION:
|
||||
return "RADIOLIB_ERR_INVALID_REVISION";
|
||||
case RADIOLIB_ERR_INVALID_PORT:
|
||||
return "RADIOLIB_ERR_INVALID_PORT";
|
||||
case RADIOLIB_ERR_NO_RX_WINDOW:
|
||||
return "RADIOLIB_ERR_NO_RX_WINDOW";
|
||||
case RADIOLIB_ERR_INVALID_CID:
|
||||
return "RADIOLIB_ERR_INVALID_CID";
|
||||
case RADIOLIB_ERR_UPLINK_UNAVAILABLE:
|
||||
return "RADIOLIB_ERR_UPLINK_UNAVAILABLE";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_FULL:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_FULL";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND";
|
||||
case RADIOLIB_ERR_JOIN_NONCE_INVALID:
|
||||
return "RADIOLIB_ERR_JOIN_NONCE_INVALID";
|
||||
case RADIOLIB_ERR_N_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_A_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_DWELL_TIME_EXCEEDED:
|
||||
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
|
||||
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
|
||||
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
|
||||
case RADIOLIB_LORAWAN_NO_DOWNLINK:
|
||||
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
|
||||
case RADIOLIB_LORAWAN_SESSION_RESTORED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
|
||||
case RADIOLIB_LORAWAN_NEW_SESSION:
|
||||
return "RADIOLIB_LORAWAN_NEW_SESSION";
|
||||
case RADIOLIB_LORAWAN_NONCES_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_NONCES_DISCARDED";
|
||||
case RADIOLIB_LORAWAN_SESSION_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_DISCARDED";
|
||||
}
|
||||
return "See TypeDef.h";
|
||||
}
|
||||
|
||||
// helper function to display any issues
|
||||
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
|
||||
if (isFail) {
|
||||
Serial.print(message);
|
||||
Serial.print(" - ");
|
||||
Serial.print(stateDecode(state));
|
||||
Serial.print(" (");
|
||||
Serial.print(state);
|
||||
Serial.println(")");
|
||||
while (Freeze);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper function to display a byte array
|
||||
void arrayDump(uint8_t *buffer, uint16_t len) {
|
||||
for(uint16_t c = 0; c < len; c++) {
|
||||
char b = buffer[c];
|
||||
if(b < 0x10) { Serial.print('0'); }
|
||||
Serial.print(b, HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device Example
|
||||
|
||||
This example joins a LoRaWAN network and will send
|
||||
uplink packets. Before you start, you will have to
|
||||
register your device at https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
|
||||
Please refer to the 'persistent' example once you are familiar
|
||||
with LoRaWAN.
|
||||
Running this examples REQUIRES you to check "Resets DevNonces"
|
||||
on your LoRaWAN dashboard. Refer to the network's
|
||||
documentation on how to do this.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following pin order:
|
||||
// Module(NSS/CS, DIO1, RESET, BUSY)
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 has the following pin order:
|
||||
// Module(NSS/CS, DIO0, RESET, DIO1)
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// create the node instance on the EU-868 band
|
||||
// using the radio module and the encryption key
|
||||
// make sure you are using the correct band
|
||||
// based on your geographical location!
|
||||
LoRaWANNode node(&radio, &EU868);
|
||||
|
||||
// for fixed bands with subband selection
|
||||
// such as US915 and AU915, you must specify
|
||||
// the subband that matches the Frequency Plan
|
||||
// that you selected on your LoRaWAN console
|
||||
/*
|
||||
LoRaWANNode node(&radio, &US915, 2);
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278 with default settings
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// application identifier - pre-LoRaWAN 1.1.0, this was called appEUI
|
||||
// when adding new end device in TTN, you will have to enter this number
|
||||
// you can pick any number you want, but it has to be unique
|
||||
uint64_t joinEUI = 0x12AD1011B0C0FFEE;
|
||||
|
||||
// device identifier - this number can be anything
|
||||
// when adding new end device in TTN, you can generate this number,
|
||||
// or you can set any value you want, provided it is also unique
|
||||
uint64_t devEUI = 0x70B3D57ED005E120;
|
||||
|
||||
// select some encryption keys which will be used to secure the communication
|
||||
// there are two of them - network key and application key
|
||||
// because LoRaWAN uses AES-128, the key MUST be 16 bytes (or characters) long
|
||||
|
||||
// network key is the ASCII string "topSecretKey1234"
|
||||
uint8_t nwkKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 };
|
||||
|
||||
// application key is the ASCII string "aDifferentKeyABC"
|
||||
uint8_t appKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 };
|
||||
|
||||
// prior to LoRaWAN 1.1.0, only a single "nwkKey" is used
|
||||
// when connecting to LoRaWAN 1.0 network, "appKey" will be disregarded
|
||||
// and can be set to NULL
|
||||
|
||||
|
||||
// on EEPROM-enabled boards, after the device has been activated,
|
||||
// the session can be restored without rejoining after device power cycle
|
||||
// this is intrinsically done when calling `beginOTAA()` with the same keys
|
||||
// in that case, the function will not need to transmit a JoinRequest
|
||||
|
||||
// now we can start the activation
|
||||
// this can take up to 10 seconds, and requires a LoRaWAN gateway in range
|
||||
// a specific starting-datarate can be selected in dynamic bands (e.g. EU868):
|
||||
/*
|
||||
uint8_t joinDr = 4;
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, joinDr);
|
||||
*/
|
||||
Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... "));
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// send uplink to port 10
|
||||
Serial.print(F("[LoRaWAN] Sending uplink packet ... "));
|
||||
String strUp = "Hello World! #" + String(count++);
|
||||
String strDown;
|
||||
int state = node.sendReceive(strUp, 10, strDown);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("received a downlink!"));
|
||||
|
||||
// print data of the packet (if there are any)
|
||||
Serial.print(F("[LoRaWAN] Data:\t\t"));
|
||||
if(strDown.length() > 0) {
|
||||
Serial.println(strDown);
|
||||
} else {
|
||||
Serial.println(F("<MAC commands only>"));
|
||||
}
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LoRaWAN] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LoRaWAN] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[LoRaWAN] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("no downlink!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device ABP Example
|
||||
|
||||
This example sets up a LoRaWAN node using ABP (activation
|
||||
by personalization). Before you start, you will have to
|
||||
register your device at https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will start uploading data directly,
|
||||
without having to join the network.
|
||||
|
||||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
|
||||
Please refer to the 'persistent' example once you are familiar
|
||||
with LoRaWAN.
|
||||
Running this examples REQUIRES you to check "Resets DevNonces"
|
||||
on your LoRaWAN dashboard. Refer to the network's
|
||||
documentation on how to do this.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following pin order:
|
||||
// Module(NSS/CS, DIO1, RESET, BUSY)
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 has the following pin order:
|
||||
// Module(NSS/CS, DIO0, RESET, DIO1)
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// create the node instance on the EU-868 band
|
||||
// using the radio module and the encryption key
|
||||
// make sure you are using the correct band
|
||||
// based on your geographical location!
|
||||
LoRaWANNode node(&radio, &EU868);
|
||||
|
||||
// for fixed bands with subband selection
|
||||
// such as US915 and AU915, you must specify
|
||||
// the subband that matches the Frequency Plan
|
||||
// that you selected on your LoRaWAN console
|
||||
/*
|
||||
LoRaWANNode node(&radio, &US915, 2);
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278 with default settings
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// device address - this number can be anything
|
||||
// when adding new end device in TTN, you can generate this number,
|
||||
// or you can set any value you want, provided it is unique
|
||||
uint32_t devAddr = 0x12345678;
|
||||
|
||||
// select some encryption keys which will be used to secure the communication
|
||||
// there are two of them - network key and application key
|
||||
// because LoRaWAN uses AES-128, the key MUST be 16 bytes (or characters) long
|
||||
|
||||
// network key is the ASCII string "topSecretKey1234"
|
||||
uint8_t nwkSKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 };
|
||||
|
||||
// application key is the ASCII string "aDifferentKeyABC"
|
||||
uint8_t appSKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 };
|
||||
|
||||
// network key 2 is the ASCII string "topSecretKey5678"
|
||||
uint8_t fNwkSIntKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x35, 0x36, 0x37, 0x38 };
|
||||
|
||||
// network key 3 is the ASCII string "aDifferentKeyDEF"
|
||||
uint8_t sNwkSIntKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x44, 0x45, 0x46 };
|
||||
|
||||
// prior to LoRaWAN 1.1.0, only a single "nwkKey" is used
|
||||
// when connecting to LoRaWAN 1.0 network, "appKey" will be disregarded
|
||||
// and can be set to NULL
|
||||
|
||||
|
||||
// if using EU868 on ABP in TTN, you need to set the SF for RX2 window manually
|
||||
/*
|
||||
node.rx2.drMax = 3;
|
||||
*/
|
||||
|
||||
// on EEPROM-enabled boards, after the device has been activated,
|
||||
// the session can be restored without rejoining after device power cycle
|
||||
// this is intrinsically done when calling `beginABP()` with the same keys
|
||||
// in that case, the function will not need to transmit a JoinRequest
|
||||
|
||||
// to start a LoRaWAN v1.0 session,
|
||||
// the user can remove the fNwkSIntKey and sNwkSIntKey
|
||||
/*
|
||||
state = node.beginABP(devAddr, nwkSKey, appSKey);
|
||||
*/
|
||||
|
||||
// start the device by directly providing the encryption keys and device address
|
||||
Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... "));
|
||||
state = node.beginABP(devAddr, nwkSKey, appSKey, fNwkSIntKey, sNwkSIntKey);
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// send uplink to port 10
|
||||
Serial.print(F("[LoRaWAN] Sending uplink packet ... "));
|
||||
String strUp = "Hello World! #" + String(count++);
|
||||
String strDown;
|
||||
int state = node.sendReceive(strUp, 10, strDown);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("received a downlink!"));
|
||||
|
||||
// print data of the packet (if there are any)
|
||||
Serial.print(F("[LoRaWAN] Data:\t\t"));
|
||||
if(strDown.length() > 0) {
|
||||
Serial.println(strDown);
|
||||
} else {
|
||||
Serial.println(F("<MAC commands only>"));
|
||||
}
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LoRaWAN] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LoRaWAN] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[LoRaWAN] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("no downlink!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device Persistent Example
|
||||
|
||||
This example assumes you have tried one of the OTAA or ABP
|
||||
examples and are familiar with the required keys and procedures.
|
||||
This example restores and saves a session such that you can use
|
||||
deepsleep or survive power cycles. Before you start, you will
|
||||
have to register your device at https://www.thethingsnetwork.org/
|
||||
and join the network using either OTAA or ABP.
|
||||
Please refer to one of the other LoRaWAN examples for more
|
||||
information regarding joining a network.
|
||||
|
||||
NOTE: LoRaWAN requires storing some parameters persistently!
|
||||
RadioLib does this by using EEPROM, by default
|
||||
starting at address 0 and using 448 bytes.
|
||||
If you already use EEPROM in your application,
|
||||
you will have to either avoid this range, or change it
|
||||
by setting a different start address by changing the value of
|
||||
RADIOLIB_HAL_PERSISTENT_STORAGE_BASE macro, either
|
||||
during build or in src/BuildOpt.h.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following pin order:
|
||||
// Module(NSS/CS, DIO1, RESET, BUSY)
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 has the following pin order:
|
||||
// Module(NSS/CS, DIO0, RESET, DIO1)
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// create the node instance on the EU-868 band
|
||||
// using the radio module and the encryption key
|
||||
// make sure you are using the correct band
|
||||
// based on your geographical location!
|
||||
LoRaWANNode node(&radio, &EU868);
|
||||
|
||||
// for fixed bands with subband selection
|
||||
// such as US915 and AU915, you must specify
|
||||
// the subband that matches the Frequency Plan
|
||||
// that you selected on your LoRaWAN console
|
||||
/*
|
||||
LoRaWANNode node(&radio, &US915, 2);
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278 with default settings
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// start the activation
|
||||
// Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... "));
|
||||
// uint64_t joinEUI = 0x12AD1011B0C0FFEE;
|
||||
// uint64_t devEUI = 0x70B3D57ED005E120;
|
||||
// uint8_t nwkKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
// 0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 };
|
||||
// uint8_t appKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
// 0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 };
|
||||
// state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
// on EEPROM-enabled boards, after the device has been activated,
|
||||
// the session can be restored without rejoining after device power cycle
|
||||
// by calling the same `beginOTAA()` or `beginABP()` function with the same keys
|
||||
// or call `restore()` where it will restore any existing session
|
||||
// `restore()` returns the active mode if it succeeded (OTAA or ABP)
|
||||
Serial.print(F("[LoRaWAN] Resuming previous session ... "));
|
||||
state = node.restore();
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
Serial.print(F("Restored an "));
|
||||
if(state == RADIOLIB_LORAWAN_MODE_OTAA)
|
||||
Serial.println(F("OTAA session."));
|
||||
else {
|
||||
Serial.println(F("ABP session."));
|
||||
}
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// send uplink to port 10
|
||||
Serial.print(F("[LoRaWAN] Sending uplink packet ... "));
|
||||
String strUp = "Hello World! #" + String(count++);
|
||||
String strDown;
|
||||
int state = node.sendReceive(strUp, 10, strDown);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("received a downlink!"));
|
||||
|
||||
// print data of the packet (if there are any)
|
||||
Serial.print(F("[LoRaWAN] Data:\t\t"));
|
||||
if(strDown.length() > 0) {
|
||||
Serial.println(strDown);
|
||||
} else {
|
||||
Serial.println(F("<MAC commands only>"));
|
||||
}
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LoRaWAN] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LoRaWAN] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[LoRaWAN] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("no downlink!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// on EEPROM enabled boards, you can save the current session
|
||||
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
|
||||
node.saveSession();
|
||||
|
||||
// wait before sending another packet
|
||||
// alternatively, call a deepsleep function here
|
||||
// make sure to send the radio to sleep as well using radio.sleep()
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device Reference Example
|
||||
|
||||
This example joins a LoRaWAN network and will send
|
||||
uplink packets. Before you start, you will have to
|
||||
register your device at https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
Also, most of the possible and available functions are
|
||||
shown here for reference.
|
||||
|
||||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
|
||||
Please refer to the 'persistent' example once you are familiar
|
||||
with LoRaWAN.
|
||||
Running this examples REQUIRES you to check "Resets DevNonces"
|
||||
on your LoRaWAN dashboard. Refer to the network's
|
||||
documentation on how to do this.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1262 has the following pin order:
|
||||
// Module(NSS/CS, DIO1, RESET, BUSY)
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 has the following pin order:
|
||||
// Module(NSS/CS, DIO0, RESET, DIO1)
|
||||
SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// create the node instance on the EU-868 band
|
||||
// using the radio module and the encryption key
|
||||
// make sure you are using the correct band
|
||||
// based on your geographical location!
|
||||
LoRaWANNode node(&radio, &EU868);
|
||||
|
||||
// for fixed bands with subband selection
|
||||
// such as US915 and AU915, you must specify
|
||||
// the subband that matches the Frequency Plan
|
||||
// that you selected on your LoRaWAN console
|
||||
/*
|
||||
LoRaWANNode node(&radio, &US915, 2);
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1278 with default settings
|
||||
Serial.print(F("[SX1278] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// application identifier - pre-LoRaWAN 1.1.0, this was called appEUI
|
||||
// when adding new end device in TTN, you will have to enter this number
|
||||
// you can pick any number you want, but it has to be unique
|
||||
uint64_t joinEUI = 0x12AD1011B0C0FFEE;
|
||||
|
||||
// device identifier - this number can be anything
|
||||
// when adding new end device in TTN, you can generate this number,
|
||||
// or you can set any value you want, provided it is also unique
|
||||
uint64_t devEUI = 0x70B3D57ED005E120;
|
||||
|
||||
// select some encryption keys which will be used to secure the communication
|
||||
// there are two of them - network key and application key
|
||||
// because LoRaWAN uses AES-128, the key MUST be 16 bytes (or characters) long
|
||||
|
||||
// network key is the ASCII string "topSecretKey1234"
|
||||
uint8_t nwkKey[] = { 0x74, 0x6F, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65,
|
||||
0x74, 0x4B, 0x65, 0x79, 0x31, 0x32, 0x33, 0x34 };
|
||||
|
||||
// application key is the ASCII string "aDifferentKeyABC"
|
||||
uint8_t appKey[] = { 0x61, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65,
|
||||
0x6E, 0x74, 0x4B, 0x65, 0x79, 0x41, 0x42, 0x43 };
|
||||
|
||||
// prior to LoRaWAN 1.1.0, only a single "nwkKey" is used
|
||||
// when connecting to LoRaWAN 1.0 network, "appKey" will be disregarded
|
||||
// and can be set to NULL
|
||||
|
||||
|
||||
// now we can start the activation
|
||||
// this can take up to 10 seconds, and requires a LoRaWAN gateway in range
|
||||
// a specific starting-datarate can be selected in dynamic bands (e.g. EU868):
|
||||
/*
|
||||
uint8_t joinDr = 4;
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, joinDr);
|
||||
*/
|
||||
Serial.print(F("[LoRaWAN] Attempting over-the-air activation ... "));
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
if(state >= RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
|
||||
// on EEPROM-enabled boards, after the device has been activated,
|
||||
// the session can be restored without rejoining after device power cycle
|
||||
// this is intrinsically done when calling `beginOTAA()` with the same keys
|
||||
// or if you 'lost' the keys or don't want them included in your sketch
|
||||
// you can call `restore()`
|
||||
/*
|
||||
Serial.print(F("[LoRaWAN] Resuming previous session ... "));
|
||||
state = node.restore();
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while(true);
|
||||
}
|
||||
*/
|
||||
|
||||
// disable the ADR algorithm
|
||||
node.setADR(false);
|
||||
|
||||
// set a fixed datarate
|
||||
node.setDatarate(5);
|
||||
// in order to save the datarate persistent across reboot/deepsleep, use the following:
|
||||
/*
|
||||
node.setDatarate(5, true);
|
||||
*/
|
||||
|
||||
// enable CSMA
|
||||
// this tries to minimize packet loss by searching for a free channel
|
||||
// before actually sending an uplink
|
||||
node.setCSMA(6, 2, true);
|
||||
|
||||
// enable or disable the dutycycle
|
||||
// the second argument specific allowed airtime per hour in milliseconds
|
||||
// 1250 = TTN FUP (30 seconds / 24 hours)
|
||||
// if not called, this corresponds to setDutyCycle(true, 0)
|
||||
// setting this to 0 corresponds to the band's maximum allowed dutycycle by law
|
||||
node.setDutyCycle(true, 1250);
|
||||
|
||||
// enable or disable the dwell time limits
|
||||
// the second argument specific allowed airtime per uplink in milliseconds
|
||||
// if not called, this corresponds to setDwellTime(true, 0)
|
||||
// setting this to 0 corresponds to the band's maximum allowed dwell time by law
|
||||
node.setDwellTime(true, 1000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int state = RADIOLIB_ERR_NONE;
|
||||
|
||||
// set battery fill level - the LoRaWAN network server
|
||||
// may periodically request this information
|
||||
// 0 = external power source
|
||||
// 1 = lowest (empty battery)
|
||||
// 254 = highest (full battery)
|
||||
// 255 = unable to measure
|
||||
uint8_t battLevel = 146;
|
||||
node.setDeviceStatus(battLevel);
|
||||
|
||||
// retrieve the last uplink frame counter
|
||||
uint32_t fcntUp = node.getFcntUp();
|
||||
|
||||
Serial.print(F("[LoRaWAN] Sending uplink packet ... "));
|
||||
String strUp = "Hello World! #" + String(fcntUp);
|
||||
|
||||
// send a confirmed uplink to port 10 every 64th frame
|
||||
// and also request the LinkCheck and DeviceTime MAC commands
|
||||
if(fcntUp % 64 == 0) {
|
||||
state = node.uplink(strUp, 10, true);
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK);
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME);
|
||||
} else {
|
||||
state = node.uplink(strUp, 10);
|
||||
}
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// after uplink, you can call downlink(),
|
||||
// to receive any possible reply from the server
|
||||
// this function must be called within a few seconds
|
||||
// after uplink to receive the downlink!
|
||||
Serial.print(F("[LoRaWAN] Waiting for downlink ... "));
|
||||
String strDown;
|
||||
|
||||
// you can also retrieve additional information about
|
||||
// uplink or downlink by passing a reference to
|
||||
// LoRaWANEvent_t structure
|
||||
LoRaWANEvent_t event;
|
||||
state = node.downlink(strDown, &event);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print data of the packet (if there are any)
|
||||
Serial.print(F("[LoRaWAN] Data:\t\t"));
|
||||
if(strDown.length() > 0) {
|
||||
Serial.println(strDown);
|
||||
} else {
|
||||
Serial.println(F("<MAC commands only>"));
|
||||
}
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LoRaWAN] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LoRaWAN] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[LoRaWAN] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
// print extra information about the event
|
||||
Serial.println(F("[LoRaWAN] Event information:"));
|
||||
Serial.print(F("[LoRaWAN] Direction:\t"));
|
||||
if(event.dir == RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK) {
|
||||
Serial.println(F("uplink"));
|
||||
} else {
|
||||
Serial.println(F("downlink"));
|
||||
}
|
||||
Serial.print(F("[LoRaWAN] Confirmed:\t"));
|
||||
Serial.println(event.confirmed);
|
||||
Serial.print(F("[LoRaWAN] Confirming:\t"));
|
||||
Serial.println(event.confirming);
|
||||
Serial.print(F("[LoRaWAN] Datarate:\t"));
|
||||
Serial.print(event.datarate);
|
||||
Serial.print(F("[LoRaWAN] Frequency:\t"));
|
||||
Serial.print(event.freq, 3);
|
||||
Serial.println(F(" MHz"));
|
||||
Serial.print(F("[LoRaWAN] Output power:\t"));
|
||||
Serial.print(event.power);
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.print(F("[LoRaWAN] Frame count:\t"));
|
||||
Serial.println(event.fcnt);
|
||||
Serial.print(F("[LoRaWAN] Port:\t\t"));
|
||||
Serial.println(event.port);
|
||||
|
||||
Serial.print(radio.getFrequencyError());
|
||||
|
||||
uint8_t margin = 0;
|
||||
uint8_t gwCnt = 0;
|
||||
if(node.getMacLinkCheckAns(&margin, &gwCnt)) {
|
||||
Serial.print(F("[LoRaWAN] LinkCheck margin:\t"));
|
||||
Serial.println(margin);
|
||||
Serial.print(F("[LoRaWAN] LinkCheck count:\t"));
|
||||
Serial.println(gwCnt);
|
||||
}
|
||||
|
||||
uint32_t networkTime = 0;
|
||||
uint8_t fracSecond = 0;
|
||||
if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true)) {
|
||||
Serial.print(F("[LoRaWAN] DeviceTime Unix:\t"));
|
||||
Serial.println(networkTime);
|
||||
Serial.print(F("[LoRaWAN] LinkCheck second:\t1/"));
|
||||
Serial.println(fracSecond);
|
||||
}
|
||||
|
||||
} else if(state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// on EEPROM enabled boards, you can save the current session
|
||||
// by calling "saveSession" which allows retrieving the session after reboot or deepsleep
|
||||
/*
|
||||
node.saveSession();
|
||||
*/
|
||||
|
||||
// wait before sending another packet
|
||||
uint32_t minimumDelay = 60000; // try to send once every minute
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
delay(delayMs);
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
RadioLib LoRaWAN End Device Reference Example
|
||||
|
||||
This example joins a LoRaWAN network and will send
|
||||
uplink packets. Before you start, you will have to
|
||||
register your device at https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
Also, most of the possible and available functions are
|
||||
shown here for reference.
|
||||
|
||||
LoRaWAN v1.1 requires the use of EEPROM (persistent storage).
|
||||
Running this examples REQUIRES you to check "Resets DevNonces"
|
||||
on your LoRaWAN dashboard. Refer to the notes or the
|
||||
network's documentation on how to do this.
|
||||
To comply with LoRaWAN v1.1's persistent storage, refer to
|
||||
https://github.com/radiolib-org/radiolib-persistence
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
|
||||
For LoRaWAN details, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while(!Serial); // Wait for serial to be initialised
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup"));
|
||||
|
||||
int16_t state = 0; // return value for calls to RadioLib
|
||||
|
||||
Serial.println(F("Initialise the radio"));
|
||||
state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Override the default join rate
|
||||
uint8_t joinDR = 4;
|
||||
|
||||
// Setup the OTAA session information
|
||||
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
Serial.println(F("Join ('login') the LoRaWAN Network"));
|
||||
state = node.activateOTAA(joinDR);
|
||||
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
|
||||
|
||||
// Print the DevAddr
|
||||
Serial.print("[LoRaWAN] DevAddr: ");
|
||||
Serial.println((unsigned long)node.getDevAddr(), HEX);
|
||||
|
||||
// Disable the ADR algorithm (on by default which is preferable)
|
||||
node.setADR(false);
|
||||
|
||||
// Set a fixed datarate
|
||||
node.setDatarate(4);
|
||||
|
||||
// Manages uplink intervals to the TTN Fair Use Policy
|
||||
node.setDutyCycle(true, 1250);
|
||||
|
||||
// Enable the dwell time limits - 400ms is the limit for the US
|
||||
node.setDwellTime(true, 400);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
// set battery fill level - the LoRaWAN network server
|
||||
// may periodically request this information
|
||||
// 0 = external power source
|
||||
// 1 = lowest (empty battery)
|
||||
// 254 = highest (full battery)
|
||||
// 255 = unable to measure
|
||||
uint8_t battLevel = 146;
|
||||
node.setDeviceStatus(battLevel);
|
||||
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
uint8_t downlinkPayload[10]; // Make sure this fits your plans!
|
||||
size_t downlinkSize; // To hold the actual payload size received
|
||||
|
||||
// you can also retrieve additional information about an uplink or
|
||||
// downlink by passing a reference to LoRaWANEvent_t structure
|
||||
LoRaWANEvent_t uplinkDetails;
|
||||
LoRaWANEvent_t downlinkDetails;
|
||||
|
||||
uint8_t Port = 10;
|
||||
|
||||
// Retrieve the last uplink frame counter
|
||||
uint32_t fcntUp = node.getFCntUp();
|
||||
|
||||
// Send a confirmed uplink every 64th frame
|
||||
// and also request the LinkCheck and DeviceTime MAC commands
|
||||
if(fcntUp % 64 == 0) {
|
||||
Serial.println(F("[LoRaWAN] Requesting LinkCheck and DeviceTime"));
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK);
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME);
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize, true, &uplinkDetails, &downlinkDetails);
|
||||
} else {
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize);
|
||||
}
|
||||
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
|
||||
|
||||
// Check if downlink was received
|
||||
if(state != RADIOLIB_LORAWAN_NO_DOWNLINK) {
|
||||
// Did we get a downlink with data for us
|
||||
if(downlinkSize > 0) {
|
||||
Serial.println(F("Downlink data: "));
|
||||
arrayDump(downlinkPayload, downlinkSize);
|
||||
} else {
|
||||
Serial.println(F("<MAC commands only>"));
|
||||
}
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LoRaWAN] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LoRaWAN] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
// print frequency error
|
||||
Serial.print(F("[LoRaWAN] Frequency error:\t"));
|
||||
Serial.print(radio.getFrequencyError());
|
||||
Serial.println(F(" Hz"));
|
||||
|
||||
// print extra information about the event
|
||||
Serial.println(F("[LoRaWAN] Event information:"));
|
||||
Serial.print(F("[LoRaWAN] Confirmed:\t"));
|
||||
Serial.println(downlinkDetails.confirmed);
|
||||
Serial.print(F("[LoRaWAN] Confirming:\t"));
|
||||
Serial.println(downlinkDetails.confirming);
|
||||
Serial.print(F("[LoRaWAN] Datarate:\t"));
|
||||
Serial.println(downlinkDetails.datarate);
|
||||
Serial.print(F("[LoRaWAN] Frequency:\t"));
|
||||
Serial.print(downlinkDetails.freq, 3);
|
||||
Serial.println(F(" MHz"));
|
||||
Serial.print(F("[LoRaWAN] Output power:\t"));
|
||||
Serial.print(downlinkDetails.power);
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.print(F("[LoRaWAN] Frame count:\t"));
|
||||
Serial.println(downlinkDetails.fCnt);
|
||||
Serial.print(F("[LoRaWAN] Port:\t\t"));
|
||||
Serial.println(downlinkDetails.fPort);
|
||||
|
||||
uint8_t margin = 0;
|
||||
uint8_t gwCnt = 0;
|
||||
if(node.getMacLinkCheckAns(&margin, &gwCnt) == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[LoRaWAN] LinkCheck margin:\t"));
|
||||
Serial.println(margin);
|
||||
Serial.print(F("[LoRaWAN] LinkCheck count:\t"));
|
||||
Serial.println(gwCnt);
|
||||
}
|
||||
|
||||
uint32_t networkTime = 0;
|
||||
uint8_t fracSecond = 0;
|
||||
if(node.getMacDeviceTimeAns(&networkTime, &fracSecond, true) == RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("[LoRaWAN] DeviceTime Unix:\t"));
|
||||
Serial.println(networkTime);
|
||||
Serial.print(F("[LoRaWAN] DeviceTime second:\t1/"));
|
||||
Serial.println(fracSecond);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// wait before sending another packet
|
||||
uint32_t minimumDelay = uplinkIntervalSeconds * 1000UL;
|
||||
uint32_t interval = node.timeUntilUplink(); // calculate minimum duty cycle delay (per FUP & law!)
|
||||
uint32_t delayMs = max(interval, minimumDelay); // cannot send faster than duty cycle allows
|
||||
|
||||
Serial.print(F("[LoRaWAN] Next uplink in "));
|
||||
Serial.print(delayMs/1000);
|
||||
Serial.println(F("s"));
|
||||
|
||||
delay(delayMs);
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints - see notes
|
||||
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
||||
|
||||
// joinEUI - previous versions of LoRaWAN called this AppEUI
|
||||
// for development purposes you can use all zeros - see wiki for details
|
||||
#define RADIOLIB_LORAWAN_JOIN_EUI 0x0000000000000000
|
||||
|
||||
// the Device EUI & two keys can be generated on the TTN console
|
||||
#ifndef RADIOLIB_LORAWAN_DEV_EUI // Replace with your Device EUI
|
||||
#define RADIOLIB_LORAWAN_DEV_EUI 0x---------------
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APP_KEY // Replace with your App Key
|
||||
#define RADIOLIB_LORAWAN_APP_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_NWK_KEY // Put your Nwk Key here
|
||||
#define RADIOLIB_LORAWAN_NWK_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
|
||||
// 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
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
||||
// Auto select MCU <-> radio connections
|
||||
// If you get an error message when compiling, it may be that the
|
||||
// pinmap could not be determined - see the notes for more info
|
||||
|
||||
// Adafruit
|
||||
#if defined(ARDUINO_SAMD_FEATHER_M0)
|
||||
#pragma message ("Adafruit Feather M0 with RFM95")
|
||||
#pragma message ("Link required on board")
|
||||
SX1276 radio = new Module(8, 3, 4, 6);
|
||||
|
||||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1262)
|
||||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
// Pending verfication of which radio is shipped
|
||||
// #elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
// #pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
// SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
|
||||
// Following not verified
|
||||
#elif defined (ARDUINO_heltec_wireless_stick)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
|
||||
// If we don't recognise the board
|
||||
#else
|
||||
#pragma message ("Unknown board - no automagic pinmap available")
|
||||
|
||||
// SX1262 pin order: Module(NSS/CS, DIO1, RESET, BUSY);
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 pin order: Module(NSS/CS, DIO0, RESET, DIO1);
|
||||
// SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// For Pi Pico + Waveshare HAT - work in progress
|
||||
// SX1262 radio = new Module(3, 20, 15, 2, SPI1, RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
#endif
|
||||
|
||||
// copy over the EUI's & keys in to the something that will not compile if incorrectly formatted
|
||||
uint64_t joinEUI = RADIOLIB_LORAWAN_JOIN_EUI;
|
||||
uint64_t devEUI = RADIOLIB_LORAWAN_DEV_EUI;
|
||||
uint8_t appKey[] = { RADIOLIB_LORAWAN_APP_KEY };
|
||||
uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };
|
||||
|
||||
// create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
||||
|
||||
// result code to text ...
|
||||
String stateDecode(const int16_t result) {
|
||||
switch (result) {
|
||||
case RADIOLIB_ERR_NONE:
|
||||
return "ERR_NONE";
|
||||
case RADIOLIB_ERR_CHIP_NOT_FOUND:
|
||||
return "ERR_CHIP_NOT_FOUND";
|
||||
case RADIOLIB_ERR_PACKET_TOO_LONG:
|
||||
return "ERR_PACKET_TOO_LONG";
|
||||
case RADIOLIB_ERR_RX_TIMEOUT:
|
||||
return "ERR_RX_TIMEOUT";
|
||||
case RADIOLIB_ERR_CRC_MISMATCH:
|
||||
return "ERR_CRC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
return "ERR_INVALID_SPREADING_FACTOR";
|
||||
case RADIOLIB_ERR_INVALID_CODING_RATE:
|
||||
return "ERR_INVALID_CODING_RATE";
|
||||
case RADIOLIB_ERR_INVALID_FREQUENCY:
|
||||
return "ERR_INVALID_FREQUENCY";
|
||||
case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
|
||||
return "ERR_INVALID_OUTPUT_POWER";
|
||||
case RADIOLIB_ERR_NETWORK_NOT_JOINED:
|
||||
return "RADIOLIB_ERR_NETWORK_NOT_JOINED";
|
||||
|
||||
case RADIOLIB_ERR_DOWNLINK_MALFORMED:
|
||||
return "RADIOLIB_ERR_DOWNLINK_MALFORMED";
|
||||
case RADIOLIB_ERR_INVALID_REVISION:
|
||||
return "RADIOLIB_ERR_INVALID_REVISION";
|
||||
case RADIOLIB_ERR_INVALID_PORT:
|
||||
return "RADIOLIB_ERR_INVALID_PORT";
|
||||
case RADIOLIB_ERR_NO_RX_WINDOW:
|
||||
return "RADIOLIB_ERR_NO_RX_WINDOW";
|
||||
case RADIOLIB_ERR_INVALID_CID:
|
||||
return "RADIOLIB_ERR_INVALID_CID";
|
||||
case RADIOLIB_ERR_UPLINK_UNAVAILABLE:
|
||||
return "RADIOLIB_ERR_UPLINK_UNAVAILABLE";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_FULL:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_FULL";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND";
|
||||
case RADIOLIB_ERR_JOIN_NONCE_INVALID:
|
||||
return "RADIOLIB_ERR_JOIN_NONCE_INVALID";
|
||||
case RADIOLIB_ERR_N_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_A_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_DWELL_TIME_EXCEEDED:
|
||||
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
|
||||
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
|
||||
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
|
||||
case RADIOLIB_LORAWAN_NO_DOWNLINK:
|
||||
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
|
||||
case RADIOLIB_LORAWAN_SESSION_RESTORED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
|
||||
case RADIOLIB_LORAWAN_NEW_SESSION:
|
||||
return "RADIOLIB_LORAWAN_NEW_SESSION";
|
||||
case RADIOLIB_LORAWAN_NONCES_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_NONCES_DISCARDED";
|
||||
case RADIOLIB_LORAWAN_SESSION_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_DISCARDED";
|
||||
}
|
||||
return "See TypeDef.h";
|
||||
}
|
||||
|
||||
// helper function to display any issues
|
||||
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
|
||||
if (isFail) {
|
||||
Serial.print(message);
|
||||
Serial.print(" - ");
|
||||
Serial.print(stateDecode(state));
|
||||
Serial.print(" (");
|
||||
Serial.print(state);
|
||||
Serial.println(")");
|
||||
while (Freeze);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper function to display a byte array
|
||||
void arrayDump(uint8_t *buffer, uint16_t len) {
|
||||
for(uint16_t c = 0; c < len; c++) {
|
||||
char b = buffer[c];
|
||||
if(b < 0x10) { Serial.print('0'); }
|
||||
Serial.print(b, HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
RadioLib LoRaWAN Starter Example
|
||||
|
||||
This example joins a LoRaWAN network and will send
|
||||
uplink packets. Before you start, you will have to
|
||||
register your device at https://www.thethingsnetwork.org/
|
||||
After your device is registered, you can run this example.
|
||||
The device will join the network and start uploading data.
|
||||
|
||||
Running this examples REQUIRES you to check "Resets DevNonces"
|
||||
on your LoRaWAN dashboard. Refer to the network's
|
||||
documentation on how to do this.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
|
||||
For LoRaWAN details, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while(!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
Serial.println(F("Initialise the radio"));
|
||||
int16_t state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Setup the OTAA session information
|
||||
node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
|
||||
|
||||
Serial.println(F("Join ('login') the LoRaWAN Network"));
|
||||
state = node.activateOTAA();
|
||||
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
// Perform an uplink
|
||||
int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
debug((state != RADIOLIB_LORAWAN_NO_DOWNLINK) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);
|
||||
|
||||
Serial.print(F("Uplink complete, next in "));
|
||||
Serial.print(uplinkIntervalSeconds);
|
||||
Serial.println(F(" seconds"));
|
||||
|
||||
// Wait until next uplink - observing legal & TTN FUP constraints
|
||||
delay(uplinkIntervalSeconds * 1000UL); // delay needs milli-seconds
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
// how often to send an uplink - consider legal & FUP constraints - see notes
|
||||
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
||||
|
||||
// joinEUI - previous versions of LoRaWAN called this AppEUI
|
||||
// for development purposes you can use all zeros - see wiki for details
|
||||
#define RADIOLIB_LORAWAN_JOIN_EUI 0x0000000000000000
|
||||
|
||||
// the Device EUI & two keys can be generated on the TTN console
|
||||
#ifndef RADIOLIB_LORAWAN_DEV_EUI // Replace with your Device EUI
|
||||
#define RADIOLIB_LORAWAN_DEV_EUI 0x---------------
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_APP_KEY // Replace with your App Key
|
||||
#define RADIOLIB_LORAWAN_APP_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_NWK_KEY // Put your Nwk Key here
|
||||
#define RADIOLIB_LORAWAN_NWK_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
|
||||
// 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
|
||||
const LoRaWANBand_t Region = EU868;
|
||||
const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
||||
|
||||
// ============================================================================
|
||||
// Below is to support the sketch - only make changes if the notes say so ...
|
||||
|
||||
// Auto select MCU <-> radio connections
|
||||
// If you get an error message when compiling, it may be that the
|
||||
// pinmap could not be determined - see the notes for more info
|
||||
|
||||
// Adafruit
|
||||
#if defined(ARDUINO_SAMD_FEATHER_M0)
|
||||
#pragma message ("Adafruit Feather M0 with RFM95")
|
||||
#pragma message ("Link required on board")
|
||||
SX1276 radio = new Module(8, 3, 4, 6);
|
||||
|
||||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1262)
|
||||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
// Pending verfication of which radio is shipped
|
||||
// #elif defined(ARDUINO_heltec_wifi_lora_32_V2)
|
||||
// #pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
// SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_lora_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
|
||||
// Following not verified
|
||||
#elif defined (ARDUINO_heltec_wireless_stick)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1278 radio = new Module(14, 4, 12, 16);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
|
||||
// If we don't recognise the board
|
||||
#else
|
||||
#pragma message ("Unknown board - no automagic pinmap available")
|
||||
|
||||
// SX1262 pin order: Module(NSS/CS, DIO1, RESET, BUSY);
|
||||
// SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
// SX1278 pin order: Module(NSS/CS, DIO0, RESET, DIO1);
|
||||
// SX1278 radio = new Module(10, 2, 9, 3);
|
||||
|
||||
// For Pi Pico + Waveshare HAT - work in progress
|
||||
// SX1262 radio = new Module(3, 20, 15, 2, SPI1, RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
#endif
|
||||
|
||||
// copy over the EUI's & keys in to the something that will not compile if incorrectly formatted
|
||||
uint64_t joinEUI = RADIOLIB_LORAWAN_JOIN_EUI;
|
||||
uint64_t devEUI = RADIOLIB_LORAWAN_DEV_EUI;
|
||||
uint8_t appKey[] = { RADIOLIB_LORAWAN_APP_KEY };
|
||||
uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };
|
||||
|
||||
// create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
||||
|
||||
// result code to text ...
|
||||
String stateDecode(const int16_t result) {
|
||||
switch (result) {
|
||||
case RADIOLIB_ERR_NONE:
|
||||
return "ERR_NONE";
|
||||
case RADIOLIB_ERR_CHIP_NOT_FOUND:
|
||||
return "ERR_CHIP_NOT_FOUND";
|
||||
case RADIOLIB_ERR_PACKET_TOO_LONG:
|
||||
return "ERR_PACKET_TOO_LONG";
|
||||
case RADIOLIB_ERR_RX_TIMEOUT:
|
||||
return "ERR_RX_TIMEOUT";
|
||||
case RADIOLIB_ERR_CRC_MISMATCH:
|
||||
return "ERR_CRC_MISMATCH";
|
||||
case RADIOLIB_ERR_INVALID_BANDWIDTH:
|
||||
return "ERR_INVALID_BANDWIDTH";
|
||||
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
|
||||
return "ERR_INVALID_SPREADING_FACTOR";
|
||||
case RADIOLIB_ERR_INVALID_CODING_RATE:
|
||||
return "ERR_INVALID_CODING_RATE";
|
||||
case RADIOLIB_ERR_INVALID_FREQUENCY:
|
||||
return "ERR_INVALID_FREQUENCY";
|
||||
case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
|
||||
return "ERR_INVALID_OUTPUT_POWER";
|
||||
case RADIOLIB_ERR_NETWORK_NOT_JOINED:
|
||||
return "RADIOLIB_ERR_NETWORK_NOT_JOINED";
|
||||
|
||||
case RADIOLIB_ERR_DOWNLINK_MALFORMED:
|
||||
return "RADIOLIB_ERR_DOWNLINK_MALFORMED";
|
||||
case RADIOLIB_ERR_INVALID_REVISION:
|
||||
return "RADIOLIB_ERR_INVALID_REVISION";
|
||||
case RADIOLIB_ERR_INVALID_PORT:
|
||||
return "RADIOLIB_ERR_INVALID_PORT";
|
||||
case RADIOLIB_ERR_NO_RX_WINDOW:
|
||||
return "RADIOLIB_ERR_NO_RX_WINDOW";
|
||||
case RADIOLIB_ERR_INVALID_CID:
|
||||
return "RADIOLIB_ERR_INVALID_CID";
|
||||
case RADIOLIB_ERR_UPLINK_UNAVAILABLE:
|
||||
return "RADIOLIB_ERR_UPLINK_UNAVAILABLE";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_FULL:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_FULL";
|
||||
case RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND:
|
||||
return "RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND";
|
||||
case RADIOLIB_ERR_JOIN_NONCE_INVALID:
|
||||
return "RADIOLIB_ERR_JOIN_NONCE_INVALID";
|
||||
case RADIOLIB_ERR_N_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_N_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_A_FCNT_DOWN_INVALID:
|
||||
return "RADIOLIB_ERR_A_FCNT_DOWN_INVALID";
|
||||
case RADIOLIB_ERR_DWELL_TIME_EXCEEDED:
|
||||
return "RADIOLIB_ERR_DWELL_TIME_EXCEEDED";
|
||||
case RADIOLIB_ERR_CHECKSUM_MISMATCH:
|
||||
return "RADIOLIB_ERR_CHECKSUM_MISMATCH";
|
||||
case RADIOLIB_LORAWAN_NO_DOWNLINK:
|
||||
return "RADIOLIB_LORAWAN_NO_DOWNLINK";
|
||||
case RADIOLIB_LORAWAN_SESSION_RESTORED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_RESTORED";
|
||||
case RADIOLIB_LORAWAN_NEW_SESSION:
|
||||
return "RADIOLIB_LORAWAN_NEW_SESSION";
|
||||
case RADIOLIB_LORAWAN_NONCES_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_NONCES_DISCARDED";
|
||||
case RADIOLIB_LORAWAN_SESSION_DISCARDED:
|
||||
return "RADIOLIB_LORAWAN_SESSION_DISCARDED";
|
||||
}
|
||||
return "See TypeDef.h";
|
||||
}
|
||||
|
||||
// helper function to display any issues
|
||||
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
|
||||
if (isFail) {
|
||||
Serial.print(message);
|
||||
Serial.print(" - ");
|
||||
Serial.print(stateDecode(state));
|
||||
Serial.print(" (");
|
||||
Serial.print(state);
|
||||
Serial.println(")");
|
||||
while (Freeze);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// helper function to display a byte array
|
||||
void arrayDump(uint8_t *buffer, uint16_t len) {
|
||||
for(uint16_t c = 0; c < len; c++) {
|
||||
char b = buffer[c];
|
||||
if(b < 0x10) { Serial.print('0'); }
|
||||
Serial.print(b, HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,204 @@
|
|||
|
||||
|
||||
# RadioLib LoRaWAN on TTN starter script
|
||||
|
||||
## Welcome
|
||||
|
||||
These notes are for someone who has successfully created a few sketches for their Arduino based device but is starting out with LoRaWAN. You don't have to be a C coding ninja but some familarity with C and procedural programming is assumed. The absolutely simplest way to get started is to buy some known good hardware that's all done for you so you can concentrate on the code & configuration.
|
||||
|
||||
|
||||
## Introduction
|
||||
|
||||
LoRaWAN is an amazing system for small battery powered sensors collecting data for years at a time. With great features comes some more complex elements which means it is not quite as simple as just providing WiFi credentials and pushing data through. It is in the range of setting up & customising the settings for a home router but with no wizards to do the heavy lifting for you. So we strongly recommend spending a couple of hours reviewing the TTN Getting Started section so you are aware of the minimum knowledge to make a successful start: https://www.thethingsnetwork.org/docs/lorawan/. Johan's video is amazing but is also drinking from the firehose. Read the text first and then watch the video on Youtube where there are bookmarks to deliver it in small digestable chunks.
|
||||
|
||||
These notes plus a lot more are available in the wiki: https://github.com/jgromes/RadioLib/wiki/LoRaWAN
|
||||
|
||||
For questions about using RadioLib there is the discussions section (https://github.com/jgromes/RadioLib/discussions) and if you believe you've found an issue (aka bug), the issues section (https://github.com/jgromes/RadioLib/issues). If posting an issue please ensure you tell us what hardware you are using and provide a debug log - make sure you enable `RADIOLIB_DEBUG_PROTOCOL`. If the question is more LoRaWAN or firmware related, then you can use the TTN forum: https://www.thethingsnetwork.org/forum/
|
||||
|
||||
|
||||
## Register & setup on TTN
|
||||
|
||||
This sketch isn't particularly aimed at The Things Stack (TTS) but you can get a free Sandbox account and the following instructions are for that. Helium does not support LoRaWAN v1.1 which is the version implemented by RadioLib. Chirpstack & other LoRaWAN Network Server (LNS) stacks have not yet been tried so YMMV.
|
||||
|
||||
Why no screen shots? TTS is a web based app, one that you will need to become familiar with and we will need to direct you to some of the less obvious parts. So much better that you learn the layouts in concept than slavishly follow screen shots that can & will go stale.
|
||||
|
||||
There will be some instructions that you have to take on face value. You didn't learn to run before you walked and it's so much more encouraging to get started and build on success than get bogged down in endless details. Once you are up & running more of the details start to slot in to place.
|
||||
|
||||
### Register on TTN
|
||||
|
||||
Go to https://www.thethingsnetwork.org/get-started and register - just like any other website. These instructions are for TTS Sandbox.
|
||||
|
||||
Once you have confirmed your email address, you can login to the console here: https://console.cloud.thethings.network/. If you allow your browser to share your location the best console will be selected. For most users the best one is the obvious one, if you have any doubts you can ask on the forum here: https://www.thethingsnetwork.org/forum/ - you login with the exact same details.
|
||||
|
||||
It is simpler to register your gateway first. If you don't have a gateway, then a The Things Indoor Gateway (TTIG) is a very affordable option. A gateway gives you a console to see if your device is being heard and is hugely useful when debugging a DIY device. If you are in range of a community gateway you may be lucky with your first device creation but you will never know if you are in range unless you have access to that gateway's console.
|
||||
|
||||
You can read up on key concepts and troubleshooting here: https://www.thethingsindustries.com/docs/gateways/
|
||||
|
||||
LoRa stands for Long Range - having the gateway & device on the same desk tends to overload both receiver circuits when they hear a transmission so close to hand. The gateway should be 5 - 10m away, preferably with a solid wall in the way as well.
|
||||
|
||||
### Create your application
|
||||
|
||||
An application is like a box to keep some devices in - normally doing the same thing - on larger deployments this may be 1,000's of similar devices. Starting out it is likely to be just a few so there is no need to get concerned about how to divide up your use just yet.
|
||||
|
||||
Onced logged in to the console you can go in to Applications to create your first application. The ID must be all lower case or numbers, no spaces, dashes are OK and it has to be unique to the entire TTN community - so `first-app` will be rejected - you could use `your-username-first-app` as that's likely to be unique. The name and description are for your own use and are optional.
|
||||
|
||||
The main menu for an application is in the left hand panel - nothing is needed there just yet.
|
||||
|
||||
### Create your device
|
||||
|
||||
On the right hand side about half way down on your application's summary is a big blue button `+ Register end device`. Click this to create the settings for your first device.
|
||||
|
||||
You are making your own device using a third party LoRaWAN stack so there will not be an entry in the device repository so choose 'Enter end device specifics manually'.
|
||||
|
||||
Choose the Frequency plan appropriate for your region. Consider that almost all countries have laws relating to what frequencies you use so don't get creative. For Europe please use the recommended option. For other regions use the entry marked 'used by TTN'.
|
||||
|
||||
Choose LoRaWAN 1.1.0 - the last one in the list - the latest specfication. RadioLib uses RP001 Regional Parameters 1.1 revision A.
|
||||
|
||||
At this point you will be asked for your JoinEUI. As this is a DIY device and we are using RadioLib, you can use all zero's as recommended by The LoRa Alliance TR007 Technical Recommendations document. Once you've put in all zeros and clicked confirm you will be asked for a DevEUI, AppKey and NwkKey. It is preferable to have the console generate them so they are properly formatted.
|
||||
|
||||
Your End device ID can be changed to make the device more identifiable. Something related to your hardware helps - like devicename-01. The you can click the blue 'Register device'.
|
||||
|
||||
When many sensors are big deployed, a device is registered, batteries put in, it joins and gets on with sending data for the next few years. For development purposes we need to turn off one of the security settings so that you can join & uplink out of the normal sequence that a device in the field would do.
|
||||
|
||||
Click on General Settings, scroll down to Join settings, click the Expand button, scroll down and click the 'Resets join nonces' option. You will see a warning about replay attacks which is entirely proper & correct. If anyone eavesdropping in your area on your LoRa transmissions could fake a join and send uplinks from their device but only if they happened to find out your AppKey & NwkKey which is kept securely on the TTN servers and is never transmitted over the air, so they'd also have to login to your account, which is protected by your password.
|
||||
|
||||
You then need to copy over the device details in to the config file for RadioLib. There are buttons to copy items to the clipboard so you don't have to hand type them.
|
||||
|
||||
### Copy & Paste made easy
|
||||
|
||||
You can copy the EUIs & keys from the device overview section.
|
||||
|
||||
The EUIs are really straightforward - click the clipboard icon at the right hand end of the EUI display field and it will be copied in the format you need. You can then paste it in to the code - you must leave the 0x in place so the compiler knows that it's a hex value.
|
||||
|
||||
The keys are relatively straightforward. Click the eye icon at the right hand end of the field. Then click the <> icon that will appear to the left. This will format the hex values as an array. Then you can click the clipboard icon to copy the array and then paste it between the { } brackets.
|
||||
|
||||
### Secrets to keep safe.
|
||||
|
||||
The Join & Dev EUI's are transmitted in plain text when the device joins a network. The gateway ID is public. If you have an issue and are asked for details, there are only three things to keep private - your password, the keys which are used for encryption and any API keys you create which are used for accessing your data & configuration.
|
||||
|
||||
|
||||
### Monitoring your device
|
||||
|
||||
If you are on your application summary page you'll see uplinks in the small activity box top right with a link to the full size table. If you click the Live Data menu item on the left it will show activity for all the devices registered on the application in the full window.
|
||||
|
||||
If you just want your devices activity, from the summary page click on the device in the list in the middle of the page.
|
||||
|
||||
The main menu for a device is the horizontal band: Overview, Live Data, Messaging etc. You can click Live Data or the link above the small activity box.
|
||||
|
||||
**The console shows LIVE data - not a history of everything that has ever happened. A LNS is a management & relay service, not a database. When you open the console you may see a summary of recent activity - this is a bonus. You must leave the console open, even in another tab, if you want to see live activity.**
|
||||
|
||||
|
||||
### Explore
|
||||
|
||||
Nothing on the console can be upset unless you confirm a warning message, so you are safe to explore the different menus to orientate yourself. This is very good idea so you have an understanding of the layout of the land and shouldn't take more than 10 or 15 minutes. The documentation & volunteers on GitHub and the TTN forum will make refer to parts of the console without giving blow by blow directions.
|
||||
|
||||
|
||||
|
||||
|
||||
## The config.h
|
||||
|
||||
### The uplinkInterval
|
||||
|
||||
LoRaWAN devices typically send small amounts of data at intervals between 15 minutes through to once per day. This allows a device to run on two AA batteries for 2 to 5 years. Hoping that LoRaWAN can move lots of data and your device can regularly receive commands to do something on demand is trying to bend the LoRaWAN system in ways it is not designed for and usually ends up with far too many issues to unravel.
|
||||
|
||||
The radio frequencies that are used are usually shared with other Industrial, Scientific & Medical, known as ISM, users. The LoRa modulation is particularly resistant to interference due to other simultaneous transmissions on the same frequency but too much local activity will mean that not all uplinks get through. The Things Industries suggest designing a system to a potential packet loss rate of 10%. Typically we see 1 or 2% loss. This is entirely down to shared use of the radio waves, once an uplink is heard by a gateway the system is super reliable through The Things Stack.
|
||||
|
||||
To ensure that the shared ISM bands are fairly used there are limits defined in law on how often you can transmit, called Duty Cycle. The details vary by region or country but typically you can only transmit for 1% of the time. Some frequencies you can only use 0.1% of the time. See https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/ for more information.
|
||||
|
||||
Additionally, as The Things Stack Sandbox aka TTN is an array of servers in three locations around the world paid for by The Things Industries, there is a Fair Use Policy so that those learning LoRaWAN, communities, hobbyists & makers are guided on how much of the resource any one device can use. In short, it's 30 seconds of airtime a day and 10 downlinks. When a gateway is transmitting a downlink it can not hear any uplinks (contributing to the potential uplink loss outlined above). The community consensus is that 1 downlink a fortnight to update or adjust settings is appropriate. See https://www.thethingsnetwork.org/docs/lorawan/duty-cycle/#fair-use-policy for more information.
|
||||
|
||||
You can see what intervals can be used with this interactive calculator: https://avbentem.github.io/airtime-calculator/ttn/. Devices further away from gateways will have to use a higher Spread Factor to be heard - do not assume everything will happen at SF7. An uplink takes a minimum of 6 seconds from start to end, sometimes longer if the device is further away from the gateway, so you will need to be patient for just a short while whilst waiting for feedback after seeing "Sending uplink"
|
||||
|
||||
With all these considerations, trying to use LoRaWAN for command & control isn't appropriate and realtime GPS tracking almost always breaches FUP and usually legal limits, leaving aside the challenges of coverage.
|
||||
|
||||
See the hints & tips section on testing your device.
|
||||
|
||||
|
||||
### EUI's & Keys
|
||||
|
||||
In the `config.h` towards the top there are four lines thus:
|
||||
|
||||
// replace-with-your-device-id
|
||||
uint64_t joinEUI = 0x0000000000000000;
|
||||
uint64_t devEUI = 0x0000000000000000;
|
||||
uint8_t appKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t nwkKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
On the TTN console on the device summary page, click the clipboard icon next to the DevEUI, highlight the 16 0's in the third line after the x and paste.
|
||||
|
||||
The devEUI must start with 0x and will end up looking something like 0x70B3D57ED006544E
|
||||
|
||||
For the appKey we need TTN to format it correctly. Click the eye icon and an extra icon will appear <> - click this and the key will be formatted for you. Click the clipboard icon and then paste over the 32 0x00's in the config file. Then do the same for nwkKey.
|
||||
|
||||
A key will end up something like 0x31, 0x16, 0x6A, 0x22, 0x97, 0x52, 0xB6, 0x34, 0x57, 0x45, 0x1B, 0xC3, 0xC9, 0xD8, 0x83, 0xE8
|
||||
|
||||
|
||||
### Region
|
||||
|
||||
The region value you use MUST match the one you selected on the console.
|
||||
|
||||
If you are using US915 or AU915 then you should change the subBand const to 2.
|
||||
|
||||
### The pinmap
|
||||
|
||||
This is the connection between the MCU (ESP32/ATmega/SAMD) and the LoRa radio (SX1276/SX1262).
|
||||
|
||||
Prebuilt modules are easy - we can detect the board and setup the pinmap for you. These boards are:
|
||||
|
||||
* TTGO_LoRa32
|
||||
* TTGO_LoRa32_V1
|
||||
* TTGO_LORA32_V2
|
||||
* TTGO_LORA32_v21NEW
|
||||
* HELTEC_WIFI_LORA_32
|
||||
* HELTEC_WIFI_LORA_32_V2
|
||||
* HELTEC_WIFI_LORA_32_V3
|
||||
* HELTEC_WIRELESS_STICK
|
||||
* HELTEC_WIRELESS_STICK_V3
|
||||
* HELTEC_WIRELESS_STICK_LITE
|
||||
* HELTEC_WIRELESS_STICK_LITE_V3
|
||||
|
||||
If you have a TTGO T-Beam, you must choose the correct radio from the Board Revision sub-menu found under the main Tools menu.
|
||||
|
||||
* TBEAM_USE_RADIO_SX1262
|
||||
* TBEAM_USE_RADIO_SX1276
|
||||
|
||||
Auto-setup for the Adafruit Feather M0 with RFM95 is included but you must solder a wire or use a jumper to link from pin 6 to io1: https://learn.adafruit.com/the-things-network-for-feather/arduino-wiring
|
||||
|
||||
If you have a module that's not on this list, please go to the "Pinmap How-To" below.
|
||||
|
||||
|
||||
|
||||
## Observations on the main sketch
|
||||
|
||||
Most of the sketch has comments that tell you what the various parts are doing. This should add a little more info:
|
||||
|
||||
### The Join
|
||||
|
||||
When a device is first started, it needs to register with the LoRaWAN Network Server (LNS) and setup it's session. With the settings from the console copied over and a gateway an appropriate distance away, most of the time the join will 'just work'.
|
||||
|
||||
If it doesn't, then there is no point trying repeatedly without going through the troubleshootng sequence. So this starter sketch will try once only to save the airwaves & TTN Community servers from repeated misfires.
|
||||
|
||||
|
||||
### The payload
|
||||
|
||||
You may see other starter sketches sending text. Apart from being massively inefficient, the text isn't easily displayed on the TTN console which makes it rather pointless and pro embedded engineers don't send strings. So this sketch sends the data as a sequence of bytes as recommended.
|
||||
|
||||
Further reading on this can be found here, just ignore the pink message about v2, it's all still valid: https://www.thethingsnetwork.org/docs/devices/bytes/
|
||||
|
||||
We've not assumed anything about any sensors you have, so we are just reading a digital & an analog pin. An analog reading is typically a two byte value - an integer - this is split using the Arduino highByte & lowByte function. You'll see how we put it back together in the TTN console below.
|
||||
|
||||
|
||||
## TTN Console Payload Decoder
|
||||
|
||||
Coming soon
|
||||
|
||||
## Hints & Tips
|
||||
|
||||
### Device testing
|
||||
|
||||
The LoRaWAN code base works to a specification and once you are happy your device is able to join & send a few dozen uplinks, continuing to sit around waiting for an uplink to test your sensor code & payload format is a waste of your time. The solution is to write everything else in a different sketch, output the array to the serial console and then you can copy & paste the hex array in to the TTN console Payload Formatters section to test the decoding.
|
||||
|
||||
|
||||
## Pinmap How-To
|
||||
|
||||
Coming soon
|
|
@ -0,0 +1,20 @@
|
|||
# LoRaWAN examples
|
||||
RadioLib LoRaWAN v1.1 examples.
|
||||
|
||||
* [LoRaWAN_Starter](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Starter): this is the recommended entry point for new users. Please read the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) that come with this example to learn more about LoRaWAN and how to use it in RadioLib!
|
||||
* [LoRaWAN_Reference](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Reference): this sketch showcases most of the available API for LoRaWAN in RadioLib. Be frightened by the possibilities! It is recommended you have read all the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) for the Starter sketch first, as well as the [Learn section on The Things Network](https://www.thethingsnetwork.org/docs/lorawan/)!
|
||||
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA (but why?), this example shows how you can do this using RadioLib.
|
||||
|
||||
---
|
||||
|
||||
> [!WARNING]
|
||||
> These examples do not fully comply with LoRaWAN v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
|
||||
|
||||
## RadioLib persistence
|
||||
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN v1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
|
||||
Currently, examples are available for the following platforms:
|
||||
|
||||
* [LoRaWAN for ESP32](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP32)
|
||||
* [LoRaWAN for ESP8266](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP8266)
|
||||
|
||||
_This list is last updated at 30/03/2024._
|
|
@ -14,6 +14,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
@ -15,7 +15,8 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CUR
|
|||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
|
||||
# link both libraries
|
||||
target_link_libraries(${PROJECT_NAME} RadioLib pigpio)
|
||||
target_link_libraries(${PROJECT_NAME} RadioLib lgpio)
|
||||
|
||||
# you can also specify RadioLib compile-time flags here
|
||||
#target_compile_definitions(${PROJECT_NAME} PUBLIC RADIOLIB_DEBUG RADIOLIB_VERBOSE)
|
||||
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_BASIC RADIOLIB_DEBUG_SPI)
|
||||
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_PORT=stdout)
|
||||
|
|
|
@ -1,47 +1,53 @@
|
|||
#ifndef PI_HAL_H
|
||||
#define PI_HAL_H
|
||||
#ifndef PI_HAL_LGPIO_H
|
||||
#define PI_HAL_LGPIO_H
|
||||
|
||||
// include RadioLib
|
||||
#include <RadioLib.h>
|
||||
|
||||
// include the library for Raspberry GPIO pins
|
||||
#include "pigpio.h"
|
||||
#include <lgpio.h>
|
||||
|
||||
#define PI_RISING (LG_RISING_EDGE)
|
||||
#define PI_FALLING (LG_FALLING_EDGE)
|
||||
#define PI_INPUT (0)
|
||||
#define PI_OUTPUT (1)
|
||||
#define PI_MAX_USER_GPIO (31)
|
||||
|
||||
// forward declaration of alert handler that will be used to emulate interrupts
|
||||
static void lgpioAlertHandler(int num_alerts, lgGpioAlert_p alerts, void *userdata);
|
||||
|
||||
// create a new Raspberry Pi hardware abstraction layer
|
||||
// using the pigpio library
|
||||
// using the lgpio library
|
||||
// the HAL must inherit from the base RadioLibHal class
|
||||
// and implement all of its virtual methods
|
||||
class PiHal : public RadioLibHal {
|
||||
public:
|
||||
// default constructor - initializes the base HAL and any needed private members
|
||||
PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000)
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, RISING_EDGE, FALLING_EDGE),
|
||||
PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000, uint8_t spiDevice = 0, uint8_t gpioDevice = 0)
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, LG_LOW, LG_HIGH, PI_RISING, PI_FALLING),
|
||||
_gpioDevice(gpioDevice),
|
||||
_spiDevice(spiDevice),
|
||||
_spiChannel(spiChannel),
|
||||
_spiSpeed(spiSpeed) {
|
||||
}
|
||||
|
||||
void init() override {
|
||||
// first initialise pigpio library
|
||||
gpioInitialise();
|
||||
// first initialise lgpio library
|
||||
if((_gpioHandle = lgGpiochipOpen(_gpioDevice)) < 0) {
|
||||
fprintf(stderr, "Could not open GPIO chip: %s\n", lguErrorText(_gpioHandle));
|
||||
return;
|
||||
}
|
||||
|
||||
// now the SPI
|
||||
spiBegin();
|
||||
|
||||
// Waveshare LoRaWAN Hat also needs pin 18 to be pulled high to enable the radio
|
||||
gpioSetMode(18, PI_OUTPUT);
|
||||
gpioWrite(18, PI_HIGH);
|
||||
}
|
||||
|
||||
void term() override {
|
||||
// stop the SPI
|
||||
spiEnd();
|
||||
|
||||
// pull the enable pin low
|
||||
gpioSetMode(18, PI_OUTPUT);
|
||||
gpioWrite(18, PI_LOW);
|
||||
|
||||
// finally, stop the pigpio library
|
||||
gpioTerminate();
|
||||
// finally, stop the lgpio library
|
||||
lgGpiochipClose(_gpioHandle);
|
||||
}
|
||||
|
||||
// GPIO-related methods (pinMode, digitalWrite etc.) should check
|
||||
|
@ -51,7 +57,24 @@ class PiHal : public RadioLibHal {
|
|||
return;
|
||||
}
|
||||
|
||||
gpioSetMode(pin, mode);
|
||||
int result;
|
||||
int flags = 0;
|
||||
switch(mode) {
|
||||
case PI_INPUT:
|
||||
result = lgGpioClaimInput(_gpioHandle, 0, pin);
|
||||
break;
|
||||
case PI_OUTPUT:
|
||||
result = lgGpioClaimOutput(_gpioHandle, flags, pin, LG_HIGH);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown pinMode mode %" PRIu32 "\n", mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Could not claim pin %" PRIu32 " for mode %" PRIu32 ": %s\n",
|
||||
pin, mode, lguErrorText(result));
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override {
|
||||
|
@ -59,7 +82,10 @@ class PiHal : public RadioLibHal {
|
|||
return;
|
||||
}
|
||||
|
||||
gpioWrite(pin, value);
|
||||
int result = lgGpioWrite(_gpioHandle, pin, value);
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Error writing value to pin %" PRIu32 ": %s\n", pin, lguErrorText(result));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t digitalRead(uint32_t pin) override {
|
||||
|
@ -67,39 +93,78 @@ class PiHal : public RadioLibHal {
|
|||
return(0);
|
||||
}
|
||||
|
||||
return(gpioRead(pin));
|
||||
int result = lgGpioRead(_gpioHandle, pin);
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Error writing reading from pin %" PRIu32 ": %s\n", pin, lguErrorText(result));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
if((interruptNum == RADIOLIB_NC) || (interruptNum > PI_MAX_USER_GPIO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, mode, 0, (gpioISRFunc_t)interruptCb);
|
||||
// set lgpio alert callback
|
||||
int result = lgGpioClaimAlert(_gpioHandle, 0, mode, interruptNum, -1);
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Could not claim pin %" PRIu32 " for alert: %s\n", interruptNum, lguErrorText(result));
|
||||
return;
|
||||
}
|
||||
|
||||
// enable emulated interrupt
|
||||
interruptEnabled[interruptNum] = true;
|
||||
interruptModes[interruptNum] = mode;
|
||||
interruptCallbacks[interruptNum] = interruptCb;
|
||||
|
||||
lgGpioSetAlertsFunc(_gpioHandle, interruptNum, lgpioAlertHandler, (void *)this);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
if((interruptNum == RADIOLIB_NC) || (interruptNum > PI_MAX_USER_GPIO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, 0, 0, NULL);
|
||||
// clear emulated interrupt
|
||||
interruptEnabled[interruptNum] = false;
|
||||
interruptModes[interruptNum] = 0;
|
||||
interruptCallbacks[interruptNum] = NULL;
|
||||
|
||||
// disable lgpio alert callback
|
||||
lgGpioFree(_gpioHandle, interruptNum);
|
||||
lgGpioSetAlertsFunc(_gpioHandle, interruptNum, NULL, NULL);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override {
|
||||
gpioDelay(ms * 1000);
|
||||
if(ms == 0) {
|
||||
sched_yield();
|
||||
return;
|
||||
}
|
||||
|
||||
lguSleep(ms / 1000.0);
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned long us) override {
|
||||
gpioDelay(us);
|
||||
if(us == 0) {
|
||||
sched_yield();
|
||||
return;
|
||||
}
|
||||
|
||||
lguSleep(us / 1000000.0);
|
||||
}
|
||||
|
||||
void yield() override {
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
unsigned long millis() override {
|
||||
return(gpioTick() / 1000);
|
||||
uint32_t time = lguTimestamp() / 1000000UL;
|
||||
return time;
|
||||
}
|
||||
|
||||
unsigned long micros() override {
|
||||
return(gpioTick());
|
||||
uint32_t time = lguTimestamp() / 1000UL;
|
||||
return time;
|
||||
}
|
||||
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
|
||||
|
@ -120,32 +185,72 @@ class PiHal : public RadioLibHal {
|
|||
return(this->micros() - start);
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
void spiBegin() {
|
||||
if(_spiHandle < 0) {
|
||||
_spiHandle = spiOpen(_spiChannel, _spiSpeed, 0);
|
||||
if((_spiHandle = lgSpiOpen(_spiDevice, _spiChannel, _spiSpeed, 0)) < 0) {
|
||||
fprintf(stderr, "Could not open SPI handle on 0: %s\n", lguErrorText(_spiHandle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spiBeginTransaction() {}
|
||||
|
||||
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
|
||||
spiXfer(_spiHandle, (char*)out, (char*)in, len);
|
||||
int result = lgSpiXfer(_spiHandle, (char *)out, (char*)in, len);
|
||||
if(result < 0) {
|
||||
fprintf(stderr, "Could not perform SPI transfer: %s\n", lguErrorText(result));
|
||||
}
|
||||
}
|
||||
|
||||
void spiEndTransaction() {}
|
||||
|
||||
void spiEnd() {
|
||||
if(_spiHandle >= 0) {
|
||||
spiClose(_spiHandle);
|
||||
lgSpiClose(_spiHandle);
|
||||
_spiHandle = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) {
|
||||
lgTxPwm(_gpioHandle, pin, frequency, 50, 0, duration);
|
||||
}
|
||||
|
||||
void noTone(uint32_t pin) {
|
||||
lgTxPwm(_gpioHandle, pin, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// interrupt emulation
|
||||
bool interruptEnabled[PI_MAX_USER_GPIO + 1];
|
||||
uint32_t interruptModes[PI_MAX_USER_GPIO + 1];
|
||||
typedef void (*RadioLibISR)(void);
|
||||
RadioLibISR interruptCallbacks[PI_MAX_USER_GPIO + 1];
|
||||
|
||||
private:
|
||||
// the HAL can contain any additional private members
|
||||
const unsigned int _spiSpeed;
|
||||
const uint8_t _gpioDevice;
|
||||
const uint8_t _spiDevice;
|
||||
const uint8_t _spiChannel;
|
||||
int _gpioHandle = -1;
|
||||
int _spiHandle = -1;
|
||||
};
|
||||
|
||||
// this handler emulates interrupts
|
||||
static void lgpioAlertHandler(int num_alerts, lgGpioAlert_p alerts, void *userdata) {
|
||||
if(!userdata)
|
||||
return;
|
||||
|
||||
// PiHal instance is passed via the user data
|
||||
PiHal* hal = (PiHal*)userdata;
|
||||
|
||||
// check the interrupt is enabled, the level matches and a callback exists
|
||||
for(lgGpioAlert_t *alert = alerts; alert < (alerts + num_alerts); alert++) {
|
||||
if((hal->interruptEnabled[alert->report.gpio]) &&
|
||||
(hal->interruptModes[alert->report.gpio] == alert->report.level) &&
|
||||
(hal->interruptCallbacks[alert->report.gpio])) {
|
||||
hal->interruptCallbacks[alert->report.gpio]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,3 +6,4 @@ cd build
|
|||
cmake -G "CodeBlocks - Unix Makefiles" ..
|
||||
make
|
||||
cd ..
|
||||
size build/rpi-sx1261
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
This example shows how to use RadioLib without Arduino.
|
||||
In this case, a Raspberry Pi with WaveShare SX1302 LoRaWAN Hat
|
||||
using the pigpio library.
|
||||
using the lgpio library
|
||||
https://abyz.me.uk/lg/lgpio.html
|
||||
|
||||
Can be used as a starting point to port RadioLib to any platform!
|
||||
See this API reference page for details on the RadioLib hardware abstraction
|
||||
|
@ -44,10 +45,13 @@ int main(int argc, char** argv) {
|
|||
printf("success!\n");
|
||||
|
||||
// loop forever
|
||||
int count = 0;
|
||||
for(;;) {
|
||||
// send a packet
|
||||
printf("[SX1261] Transmitting packet ... ");
|
||||
state = radio.transmit("Hello World!");
|
||||
char str[64];
|
||||
sprintf(str, "Hello World! #%d", count++);
|
||||
state = radio.transmit(str);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
printf("success!\n");
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
build/
|
||||
build-*
|
||||
TockApp.tab
|
||||
|
|
|
@ -27,9 +27,13 @@ cmake_minimum_required(VERSION 3.18)
|
|||
# create the project
|
||||
project(tock-sx1261)
|
||||
|
||||
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/userland_generic.ld)
|
||||
set(LINKER_SCRIPT $ENV{LIBTOCK_C_DIRECTORY}/userland_generic.ld)
|
||||
|
||||
include("tock.cmake")
|
||||
if (RISCV_BUILD)
|
||||
include("tock-riscv.cmake")
|
||||
else()
|
||||
include("tock-arm.cmake")
|
||||
endif()
|
||||
|
||||
# when using debuggers such as gdb, the following line can be used
|
||||
#set(CMAKE_BUILD_TYPE Debug)
|
||||
|
@ -43,18 +47,66 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CUR
|
|||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
|
||||
# link with RadioLib and libtock-c
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libtock/build/cortex-m4/libtock.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libc++/cortex-m/libgcc.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libc++/cortex-m/libstdc++.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/newlib/cortex-m/v7-m/libc.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/newlib/cortex-m/v7-m/libm.a
|
||||
)
|
||||
# The build system for libtock-c is a bit odd and the version of libraries
|
||||
# built changes based on compiler version.
|
||||
if (RISCV_BUILD)
|
||||
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/rv32imc/libtocksync.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/rv32i/ilp32/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libm.a
|
||||
)
|
||||
|
||||
target_include_directories(RadioLib AFTER PUBLIC
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/include/
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/rv32imc/libtocksync.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/riscv/lib/gcc/riscv64-unknown-elf/10.5.0/rv32i/ilp32/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libm.a
|
||||
)
|
||||
|
||||
target_include_directories(RadioLib AFTER PUBLIC
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/include/
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/cortex-m4/libtocksync.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/arm/lib/gcc/arm-none-eabi/13.2.0/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/arm/arm-none-eabi/lib/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/arm/arm-none-eabi/lib/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/arm/arm-none-eabi/lib/libm.a
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock-sync/build/cortex-m4/libtocksync.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/arm/lib/gcc/arm-none-eabi/10.5.0/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/arm/arm-none-eabi/lib/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/arm/arm-none-eabi/lib/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/arm/arm-none-eabi/lib/libm.a
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/
|
||||
$ENV{LIBTOCK_C_DIRECTORY}
|
||||
)
|
||||
|
||||
# you can also specify RadioLib compile-time flags here
|
||||
|
|
|
@ -13,16 +13,22 @@ This has been tested on the
|
|||
but will work on any LoRa compatible Tock board (currently only the
|
||||
expLoRaBLE board).
|
||||
|
||||
libtock-c by default is bulit for RISC-V and ARM. RadioLib is also built
|
||||
for both architectures by default. You can skip the RISC-V RadioLib build
|
||||
by setting the `SKIP_RISCV` varaible.
|
||||
|
||||
The RadioLib example can be built with:
|
||||
|
||||
```shell
|
||||
$ git clone https://github.com/jgromes/RadioLib.git
|
||||
$ cd RadioLib/examples/NonArduino/Tock/
|
||||
$ ./build.sh
|
||||
$ git clone https://github.com/tock/libtock-c.git
|
||||
$ cd libtock-c; git checkout dbee65a56d74b4bad166317f199e80b959f7c82c; cd ../
|
||||
$ LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
|
||||
```
|
||||
|
||||
Then in the Tock repo you can flash the kernel and app with:
|
||||
|
||||
```shell
|
||||
$ make flash; APP=RadioLib/examples/NonArduino/Tock/build/tock-sx1261.tbf make flash-app
|
||||
$ make flash; APP=RadioLib/examples/NonArduino/Tock/build-arm/tock-sx1261.tbf make flash-app
|
||||
```
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf ./build
|
||||
rm -rf ./build-*
|
||||
|
||||
cd libtock-c/libtock
|
||||
cd libtock-c/examples/cxx_hello
|
||||
make -j4
|
||||
cd ../../
|
||||
cd ../../../
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p build-arm
|
||||
cd build-arm
|
||||
|
||||
cmake -G "CodeBlocks - Unix Makefiles" ..
|
||||
make -j4
|
||||
|
||||
cd ..
|
||||
|
||||
if ! env | grep SKIP_RISCV; then
|
||||
mkdir -p build-riscv
|
||||
cd build-riscv
|
||||
|
||||
cmake -G "CodeBlocks - Unix Makefiles" -DRISCV_BUILD=1 ..
|
||||
make -j4
|
||||
|
||||
cd ..
|
||||
fi
|
||||
|
||||
elf2tab -n radio-lib --stack 4096 --app-heap 2048 --kernel-heap 2048 \
|
||||
--kernel-major 2 --kernel-minor 1 \
|
||||
-v ./build/tock-sx1261
|
||||
-v ./build-arm/tock-sx1261
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 1c1f4c0810aa0fbd50aa91a11aaa7c05d2abb1bc
|
|
@ -31,10 +31,12 @@
|
|||
#include <RadioLib.h>
|
||||
|
||||
// include all the dependencies
|
||||
#include "libtock/lora_phy.h"
|
||||
#include "libtock/gpio.h"
|
||||
#include "libtock/timer.h"
|
||||
#include "libtock/read_only_state.h"
|
||||
#include "libtock/net/lora_phy.h"
|
||||
#include "libtock/net/syscalls/lora_phy_syscalls.h"
|
||||
#include "libtock-sync/net/lora_phy.h"
|
||||
#include "libtock/peripherals/gpio.h"
|
||||
#include "libtock-sync/services/alarm.h"
|
||||
#include "libtock/kernel/read_only_state.h"
|
||||
|
||||
#define RADIO_BUSY 1
|
||||
#define RADIO_DIO_1 2
|
||||
|
@ -99,9 +101,9 @@ class TockHal : public RadioLibHal {
|
|||
}
|
||||
|
||||
if (mode == PIN_OUTPUT) {
|
||||
lora_phy_gpio_enable_output(pin);
|
||||
libtock_lora_phy_gpio_enable_output(pin);
|
||||
} else if (mode == PIN_INPUT) {
|
||||
lora_phy_gpio_enable_input(pin, PullDown);
|
||||
libtock_lora_phy_gpio_enable_input(pin, libtock_pull_down);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,9 +113,9 @@ class TockHal : public RadioLibHal {
|
|||
}
|
||||
|
||||
if (value) {
|
||||
lora_phy_gpio_set(pin);
|
||||
libtock_lora_phy_gpio_set(pin);
|
||||
} else {
|
||||
lora_phy_gpio_clear(pin);
|
||||
libtock_lora_phy_gpio_clear(pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +126,7 @@ class TockHal : public RadioLibHal {
|
|||
return 0;
|
||||
}
|
||||
|
||||
lora_phy_gpio_read(pin, &value);
|
||||
libtock_lora_phy_gpio_read(pin, &value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -134,11 +136,11 @@ class TockHal : public RadioLibHal {
|
|||
return;
|
||||
}
|
||||
|
||||
lora_phy_gpio_interrupt_callback(lora_phy_gpio_Callback, &interruptCb);
|
||||
libtock_lora_phy_gpio_command_interrupt_callback(lora_phy_gpio_Callback, &interruptCb);
|
||||
|
||||
// set GPIO as input and enable interrupts on it
|
||||
lora_phy_gpio_enable_input(interruptNum, PullDown);
|
||||
lora_phy_gpio_enable_interrupt(interruptNum, Change);
|
||||
libtock_lora_phy_gpio_enable_input(interruptNum, libtock_pull_down);
|
||||
libtock_lora_phy_gpio_enable_interrupt(interruptNum, libtock_change);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override {
|
||||
|
@ -146,15 +148,15 @@ class TockHal : public RadioLibHal {
|
|||
return;
|
||||
}
|
||||
|
||||
lora_phy_gpio_disable_interrupt(interruptNum);
|
||||
libtock_lora_phy_gpio_disable_interrupt(interruptNum);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override {
|
||||
delay_ms( ms );
|
||||
libtocksync_alarm_delay_ms( ms );
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned long us) override {
|
||||
delay_ms( us / 1000 );
|
||||
libtocksync_alarm_delay_ms( us / 1000 );
|
||||
}
|
||||
|
||||
unsigned long millis() override {
|
||||
|
@ -181,7 +183,7 @@ class TockHal : public RadioLibHal {
|
|||
}
|
||||
|
||||
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
|
||||
lora_phy_read_write_sync((const char*) out, (char*) in, len);
|
||||
libtocksync_lora_phy_read_write(out, in, len);
|
||||
}
|
||||
|
||||
void spiEndTransaction() {
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
# This is copied from https://github.com/Lora-net/LoRaMac-node/pull/1390
|
||||
# and has been relicensed by the original author
|
||||
|
||||
include("toolchain-arm-none-eabi.cmake")
|
||||
|
||||
if(NOT DEFINED LINKER_SCRIPT)
|
||||
message(FATAL_ERROR "No linker script defined")
|
||||
endif(NOT DEFINED LINKER_SCRIPT)
|
||||
|
@ -40,6 +38,22 @@ set(STACK_SIZE 4096)
|
|||
set(APP_HEAP_SIZE 2048)
|
||||
set(KERNEL_HEAP_SIZE 2048)
|
||||
|
||||
set(TOOLCHAIN arm-none-eabi)
|
||||
|
||||
find_program(TOOLCHAIN_PREFIX ${TOOLCHAIN}-gcc NO_CACHE)
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN_PREFIX} DIRECTORY)
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++ CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
# Object build options
|
||||
set(OBJECT_GEN_FLAGS "-mthumb -g2 -fno-builtin -mcpu=cortex-m4 -Wall -Wextra -pedantic -Wno-unused-parameter -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize -frecord-gcc-switches -gdwarf-2 -Os -fdata-sections -ffunction-sections -fstack-usage -Wl,--emit-relocs -fPIC -mthumb -mfloat-abi=soft -msingle-pic-base -mpic-register=r9 -mno-pic-data-is-text-relative -D__TOCK__ -DSVCALL_AS_NORMAL_FUNCTION -DSOFTDEVICE_s130")
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# Tock target specific CMake file
|
||||
#
|
||||
# Licensed under the MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Alistair Francis <alistair@alistair23.me>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# This is copied from https://github.com/Lora-net/LoRaMac-node/pull/1390
|
||||
# and has been relicensed by the original author
|
||||
|
||||
if(NOT DEFINED LINKER_SCRIPT)
|
||||
message(FATAL_ERROR "No linker script defined")
|
||||
endif(NOT DEFINED LINKER_SCRIPT)
|
||||
message("Linker script: ${LINKER_SCRIPT}")
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compiler/linker flags
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
set(STACK_SIZE 4096)
|
||||
set(APP_HEAP_SIZE 2048)
|
||||
set(KERNEL_HEAP_SIZE 2048)
|
||||
|
||||
find_program(TOOLCHAIN
|
||||
NAMES
|
||||
riscv64-none-elf-gcc
|
||||
riscv32-none-elf-gcc
|
||||
riscv64-elf-gcc
|
||||
riscv32-unknown-elf-gcc
|
||||
riscv64-unknown-elf-gcc
|
||||
riscv64-unknown-elf-clang
|
||||
riscv32-unknown-elf-clang
|
||||
NO_CACHE)
|
||||
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN} DIRECTORY)
|
||||
|
||||
get_filename_component(TOOLCHAIN ${TOOLCHAIN} NAME)
|
||||
string(REPLACE "-gcc" "" TOOLCHAIN ${TOOLCHAIN})
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++ CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
# Object build options
|
||||
set(OBJECT_GEN_FLAGS "-march=rv32i -mabi=ilp32 -mcmodel=medlow -g2 -fno-builtin -Wall -Wextra -pedantic -Wno-unused-parameter -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-unroll-loops -ffast-math -ftree-vectorize -frecord-gcc-switches -gdwarf-2 -Os -fdata-sections -ffunction-sections -fstack-usage -Wl,--emit-relocs -D__TOCK__ -DSVCALL_AS_NORMAL_FUNCTION -DSOFTDEVICE_s130")
|
||||
|
||||
set(CMAKE_C_FLAGS "${OBJECT_GEN_FLAGS} -std=gnu99 " CACHE INTERNAL "C Compiler options")
|
||||
set(CMAKE_CXX_FLAGS "${OBJECT_GEN_FLAGS} -std=c++20 " CACHE INTERNAL "C++ Compiler options")
|
||||
set(CMAKE_ASM_FLAGS "${OBJECT_GEN_FLAGS} -x assembler-with-cpp " CACHE INTERNAL "ASM Compiler options")
|
||||
|
||||
# Linker flags
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -march=rv32i -mabi=ilp32 -mcmodel=medlow -T${LINKER_SCRIPT} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Xlinker --defsym=STACK_SIZE=${STACK_SIZE} -Xlinker --defsym=APP_HEAP_SIZE=${APP_HEAP_SIZE} -Xlinker --defsym=KERNEL_HEAP_SIZE=${KERNEL_HEAP_SIZE} -nostdlib -Wl,--start-group" CACHE INTERNAL "Linker options")
|
|
@ -1,90 +0,0 @@
|
|||
# Arm specific CMake file
|
||||
#
|
||||
# This is copied from:
|
||||
# https://github.com/Lora-net/LoRaMac-node/blob/2bf36bde72f68257eb96b5c00900619546bedca8/cmake/toolchain-arm-none-eabi.cmake
|
||||
#
|
||||
# The below file is licensed as Revised BSD License
|
||||
# See https://github.com/Lora-net/LoRaMac-node/blob/master/LICENSE for details
|
||||
|
||||
##
|
||||
## ______ _
|
||||
## / _____) _ | |
|
||||
## ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
## \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
## _____) ) ____| | | || |_| ____( (___| | | |
|
||||
## (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
## (C)2013-2017 Semtech
|
||||
## ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
## / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
## \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
## |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
## embedded.connectivity.solutions.==============
|
||||
##
|
||||
## License: Revised BSD License, see LICENSE.TXT file included in the project
|
||||
## Authors: Johannes Bruder ( STACKFORCE ), Miguel Luis ( Semtech )
|
||||
##
|
||||
##
|
||||
## CMake arm-none-eabi toolchain file
|
||||
##
|
||||
|
||||
# Append current directory to CMAKE_MODULE_PATH for making device specific cmake modules visible
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Target definition
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set toolchain paths
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(TOOLCHAIN arm-none-eabi)
|
||||
|
||||
find_program(TOOLCHAIN_PREFIX ${TOOLCHAIN}-gcc NO_CACHE)
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN_PREFIX} DIRECTORY)
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
# Set system depended extensions
|
||||
if(WIN32)
|
||||
set(TOOLCHAIN_EXT ".exe" )
|
||||
else()
|
||||
set(TOOLCHAIN_EXT "" )
|
||||
endif()
|
||||
|
||||
# Perform compiler test with static library
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Preset some general GCC Options
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
# Options for DEBUG build
|
||||
# -Og enables optimizations that do not interfere with debugging
|
||||
# -g produce debugging information in the operating system's native format
|
||||
set(CMAKE_C_FLAGS_DEBUG "-Og -g -DDEBUG" CACHE INTERNAL "C Compiler options for debug build type")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DDEBUG" CACHE INTERNAL "C++ Compiler options for debug build type")
|
||||
set(CMAKE_ASM_FLAGS_DEBUG "-g" CACHE INTERNAL "ASM Compiler options for debug build type")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "Linker options for debug build type")
|
||||
|
||||
# Options for RELEASE build
|
||||
# -Os Optimize for size. -Os enables all -O2 optimizations
|
||||
set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "C Compiler options for release build type")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "C++ Compiler options for release build type")
|
||||
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "ASM Compiler options for release build type")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE INTERNAL "Linker options for release build type")
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc${TOOLCHAIN_EXT} CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++${TOOLCHAIN_EXT} CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc${TOOLCHAIN_EXT} CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/${${TOOLCHAIN}} ${CMAKE_PREFIX_PATH})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
@ -24,7 +24,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -24,7 +24,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -40,7 +40,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -34,7 +34,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -35,7 +35,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -26,7 +26,7 @@ STM32WLx radio = new STM32WLx_Module();
|
|||
// Some boards may not have either LP or HP.
|
||||
// For those, do not set the LP/HP entry in the table.
|
||||
static const uint32_t rfswitch_pins[] =
|
||||
{PC3, PC4, PC5};
|
||||
{PC3, PC4, PC5, RADIOLIB_NC, RADIOLIB_NC};
|
||||
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||
|
|
|
@ -42,6 +42,9 @@ volatile bool operationDone = false;
|
|||
// is transmitted or received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent or received a packet, set the flag
|
||||
operationDone = true;
|
||||
|
|
|
@ -39,6 +39,9 @@ volatile bool operationDone = false;
|
|||
// is transmitted or received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent or received packet, set the flag
|
||||
operationDone = true;
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
RadioLib SX128x Channel Activity Detection Example
|
||||
|
||||
This example uses SX1280 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
|
||||
Other modules from SX128x family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx128x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1280 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1280 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//SX1280 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1280 with default settings
|
||||
Serial.print(F("[SX1280] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setDio1Action(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[SX1280] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[SX1280] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[SX1280] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[SX1280] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[SX1280] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# ignore all output files
|
||||
*.h
|
||||
*.png
|
||||
!radiolib.png
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib image to array conversion tool.
|
||||
|
||||
Input is a PNG image to be transmitted via RadioLib SSTV.
|
||||
The image must have correct size for the chose SSTV mode!
|
||||
|
||||
Output is a file (by default named "img.h") which can be included and transmitted.
|
||||
The resulting array will be very large (typically 320 kB),
|
||||
make sure your platform has sufficient Flash/RAM space.
|
||||
''')
|
||||
parser.add_argument('input',
|
||||
type=str,
|
||||
help='Input PNG file')
|
||||
parser.add_argument('output',
|
||||
type=str,
|
||||
nargs='?',
|
||||
default='img',
|
||||
help='Output header file')
|
||||
args = parser.parse_args()
|
||||
outfile = f'{args.output}.h'
|
||||
print(f'Converting "{args.input}" to "{outfile}"')
|
||||
|
||||
# open the image as numpy array
|
||||
img = Image.open(args.input)
|
||||
arr = np.array(img)
|
||||
|
||||
# open the output file
|
||||
with open(outfile, 'w') as f:
|
||||
print(f'const uint32_t img[{arr.shape[0]}][{arr.shape[1]}] = {{', file=f)
|
||||
for row in arr:
|
||||
print(' { ', end='', file=f)
|
||||
for pix in row:
|
||||
rgb = pix[0] << 16 | pix[1] << 8 | pix[2]
|
||||
print(hex(rgb), end=', ', file=f)
|
||||
print(' },', file=f)
|
||||
print('};', file=f)
|
||||
|
||||
print('Done!')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 62 KiB |
|
@ -0,0 +1,19 @@
|
|||
#! /bin/bash
|
||||
|
||||
file=cppcheck.txt
|
||||
cppcheck --version
|
||||
cppcheck src --enable=all --force --inline-suppr --suppress=ConfigurationNotChecked --suppress=unusedFunction --quiet >> $file 2>&1
|
||||
echo "Cppcheck finished with exit code $?"
|
||||
|
||||
error=$(grep ": error:" $file | wc -l)
|
||||
warning=$(grep ": warning:" $file | wc -l)
|
||||
style=$(grep ": style:" $file | wc -l)
|
||||
echo "found $error erros, $warning warnings and $style style issues"
|
||||
if [ $error -gt "0" ] || [ $warning -gt "0" ] || [ $style -gt "0" ]
|
||||
then
|
||||
cat $file
|
||||
exitcode=1
|
||||
fi
|
||||
|
||||
rm $file
|
||||
exit $exitcode
|
|
@ -86,30 +86,30 @@ class PiHal : public RadioLibHal {
|
|||
gpioSetISRFunc(interruptNum, 0, 0, NULL);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override {
|
||||
void delay(RadioLibTime_t ms) override {
|
||||
gpioDelay(ms * 1000);
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned long us) override {
|
||||
void delayMicroseconds(RadioLibTime_t us) override {
|
||||
gpioDelay(us);
|
||||
}
|
||||
|
||||
unsigned long millis() override {
|
||||
RadioLibTime_t millis() override {
|
||||
return(gpioTick() / 1000);
|
||||
}
|
||||
|
||||
unsigned long micros() override {
|
||||
RadioLibTime_t micros() override {
|
||||
return(gpioTick());
|
||||
}
|
||||
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
|
||||
long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
this->pinMode(pin, PI_INPUT);
|
||||
uint32_t start = this->micros();
|
||||
uint32_t curtick = this->micros();
|
||||
RadioLibTime_t start = this->micros();
|
||||
RadioLibTime_t curtick = this->micros();
|
||||
|
||||
while(this->digitalRead(pin) == state) {
|
||||
if((this->micros() - curtick) > timeout) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
version: "6.6.0"
|
||||
description: "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN)."
|
||||
tags: "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan, lr1110, lr1120, lr1121"
|
||||
url: "https://github.com/jgromes/RadioLib"
|
||||
repository: "https://github.com/jgromes/RadioLib.git"
|
||||
license: "MIT"
|
||||
dependencies:
|
||||
# Required IDF version
|
||||
idf: ">=4.1"
|
||||
maintainers:
|
||||
"Jan Gromeš <gromes.jan@gmail.com>"
|
80
keywords.txt
80
keywords.txt
|
@ -15,6 +15,9 @@ ArduinoHal KEYWORD1
|
|||
# modules
|
||||
CC1101 KEYWORD1
|
||||
LLCC68 KEYWORD1
|
||||
LR1110 KEYWORD1
|
||||
LR1120 KEYWORD1
|
||||
LR1121 KEYWORD1
|
||||
nRF24 KEYWORD1
|
||||
RF69 KEYWORD1
|
||||
RFM22 KEYWORD1
|
||||
|
@ -80,14 +83,22 @@ Bell202 KEYWORD1
|
|||
# LoRaWAN bands
|
||||
EU868 KEYWORD1
|
||||
US915 KEYWORD1
|
||||
CN780 KEYWORD1
|
||||
EU433 KEYWORD1
|
||||
AU915 KEYWORD1
|
||||
CN500 KEYWORD1
|
||||
AS923 KEYWORD1
|
||||
AS923_2 KEYWORD1
|
||||
AS923_3 KEYWORD1
|
||||
AS923_4 KEYWORD1
|
||||
KR920 KEYWORD1
|
||||
IN865 KEYWORD1
|
||||
|
||||
# LR11x0 structures
|
||||
LR11x0WifiResult_t KEYWORD1
|
||||
LR11x0WifiResultFull_t KEYWORD1
|
||||
LR11x0WifiResultExtended_t KEYWORD1
|
||||
LR11x0VersionInfo_t KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
@ -124,6 +135,7 @@ setCodingRate KEYWORD2
|
|||
setFrequency KEYWORD2
|
||||
setSyncWord KEYWORD2
|
||||
setOutputPower KEYWORD2
|
||||
checkOutputPower KEYWORD2
|
||||
setCurrentLimit KEYWORD2
|
||||
setPreambleLength KEYWORD2
|
||||
setGain KEYWORD2
|
||||
|
@ -134,6 +146,7 @@ getSNR KEYWORD2
|
|||
getDataRate KEYWORD2
|
||||
setBitRate KEYWORD2
|
||||
setRxBandwidth KEYWORD2
|
||||
autoSetRxBandwidth KEYWORD2
|
||||
setAFCBandwidth KEYWORD2
|
||||
setAFC KEYWORD2
|
||||
setAFCAGCTrigger KEYWORD2
|
||||
|
@ -224,6 +237,7 @@ spectralScanStart KEYWORD2
|
|||
spectralScanAbort KEYWORD2
|
||||
spectralScanGetStatus KEYWORD2
|
||||
spectralScanGetResult KEYWORD2
|
||||
setPaRampTime KEYWORD2
|
||||
|
||||
# nRF24
|
||||
setIrqAction KEYWORD2
|
||||
|
@ -234,6 +248,18 @@ disablePipe KEYWORD2
|
|||
getStatus KEYWORD2
|
||||
setAutoAck KEYWORD2
|
||||
|
||||
# LR11x0
|
||||
beginLRFHSS KEYWORD2
|
||||
setLrFhssConfig KEYWORD2
|
||||
startWifiScan KEYWORD2
|
||||
getWifiScanResultsCount KEYWORD2
|
||||
getWifiScanResult KEYWORD2
|
||||
wifiScan KEYWORD2
|
||||
setWiFiScanAction KEYWORD2
|
||||
clearWiFiScanAction KEYWORD2
|
||||
getVersionInfo KEYWORD2
|
||||
updateFirmware KEYWORD2
|
||||
|
||||
# RTTY
|
||||
idle KEYWORD2
|
||||
byteArr KEYWORD2
|
||||
|
@ -292,21 +318,26 @@ checkDataRate KEYWORD2
|
|||
setModem KEYWORD2
|
||||
|
||||
# LoRaWAN
|
||||
wipe KEYWORD2
|
||||
restore KEYWORD2
|
||||
clearSession KEYWORD2
|
||||
getBufferNonces KEYWORD2
|
||||
setBufferNonces KEYWORD2
|
||||
getBufferSession KEYWORD2
|
||||
setBufferSession KEYWORD2
|
||||
beginOTAA KEYWORD2
|
||||
activateOTAA KEYWORD2
|
||||
beginABP KEYWORD2
|
||||
isJoined KEYWORD2
|
||||
saveSession KEYWORD2
|
||||
activateABP KEYWORD2
|
||||
isActivated KEYWORD2
|
||||
setRx2Dr KEYWORD2
|
||||
sendMacCommandReq KEYWORD2
|
||||
uplink KEYWORD2
|
||||
downlink KEYWORD2
|
||||
sendReceive KEYWORD2
|
||||
setDeviceStatus KEYWORD2
|
||||
getFcntUp KEYWORD2
|
||||
getNFcntDown KEYWORD2
|
||||
getAFcntDown KEYWORD2
|
||||
resetFcntDown KEYWORD2
|
||||
getFCntUp KEYWORD2
|
||||
getNFCntDown KEYWORD2
|
||||
getAFCntDown KEYWORD2
|
||||
resetFCntDown KEYWORD2
|
||||
setDatarate KEYWORD2
|
||||
setADR KEYWORD2
|
||||
setDutyCycle KEYWORD2
|
||||
|
@ -315,9 +346,10 @@ timeUntilUplink KEYWORD2
|
|||
setDwellTime KEYWORD2
|
||||
maxPayloadDwellTime KEYWORD2
|
||||
setTxPower KEYWORD2
|
||||
setCSMA KEYWORD2
|
||||
getMacLinkCheckAns KEYWORD2
|
||||
getMacDeviceTimeAns KEYWORD2
|
||||
getDevAddr KEYWORD2
|
||||
getLastToA KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
@ -421,13 +453,35 @@ RADIOLIB_ERR_DOWNLINK_MALFORMED LITERAL1
|
|||
RADIOLIB_ERR_INVALID_REVISION LITERAL1
|
||||
RADIOLIB_ERR_INVALID_PORT LITERAL1
|
||||
RADIOLIB_ERR_NO_RX_WINDOW LITERAL1
|
||||
RADIOLIB_ERR_INVALID_CHANNEL LITERAL1
|
||||
RADIOLIB_ERR_NO_CHANNEL_AVAILABLE LITERAL1
|
||||
RADIOLIB_ERR_INVALID_CID LITERAL1
|
||||
RADIOLIB_ERR_UPLINK_UNAVAILABLE LITERAL1
|
||||
RADIOLIB_ERR_COMMAND_QUEUE_FULL LITERAL1
|
||||
RADIOLIB_ERR_COMMAND_QUEUE_EMPTY LITERAL1
|
||||
RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND LITERAL1
|
||||
RADIOLIB_ERR_JOIN_NONCE_INVALID LITERAL1
|
||||
RADIOLIB_ERR_N_FCNT_DOWN_INVALID LITERAL1
|
||||
RADIOLIB_ERR_A_FCNT_DOWN_INVALID LITERAL1
|
||||
RADIOLIB_ERR_DATA_RATE_INVALID LITERAL1
|
||||
RADIOLIB_ERR_DWELL_TIME_EXCEEDED LITERAL1
|
||||
RADIOLIB_ERR_CHECKSUM_MISMATCH LITERAL1
|
||||
RADIOLIB_LORAWAN_NO_DOWNLINK LITERAL1
|
||||
RADIOLIB_LORAWAN_SESSION_RESTORED LITERAL1
|
||||
RADIOLIB_LORAWAN_NEW_SESSION LITERAL1
|
||||
RADIOLIB_LORAWAN_NONCES_DISCARDED LITERAL1
|
||||
RADIOLIB_LORAWAN_SESSION_DISCARDED LITERAL1
|
||||
RADIOLIB_LORAWAN_INVALID_MODE LITERAL1
|
||||
|
||||
RADIOLIB_ERR_INVALID_WIFI_TYPE LITERAL1
|
||||
|
||||
RADIOLIB_LR1110_FIRMWARE_IN_RAM LITERAL1
|
||||
RADIOLIB_LR11X0_FIRMWARE_IMAGE_SIZE LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0303 LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0304 LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0305 LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0306 LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0307 LITERAL1
|
||||
RADIOLIB_LR1110_FIRMWARE_0401 LITERAL1
|
||||
RADIOLIB_LR1120_FIRMWARE_0101 LITERAL1
|
||||
RADIOLIB_LR1120_FIRMWARE_0102 LITERAL1
|
||||
RADIOLIB_LR1120_FIRMWARE_0201 LITERAL1
|
||||
RADIOLIB_LR1121_FIRMWARE_0102 LITERAL1
|
||||
RADIOLIB_LR1121_FIRMWARE_0103 LITERAL1
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "RadioLib",
|
||||
"version": "6.4.1",
|
||||
"version": "6.6.0",
|
||||
"description": "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).",
|
||||
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan",
|
||||
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan, lr1110, lr1120, lr1121",
|
||||
"homepage": "https://github.com/jgromes/RadioLib",
|
||||
"repository":
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
name=RadioLib
|
||||
version=6.4.1
|
||||
version=6.6.0
|
||||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library
|
||||
paragraph=User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).
|
||||
paragraph=User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, LR1110 and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).
|
||||
category=Communication
|
||||
url=https://github.com/jgromes/RadioLib
|
||||
architectures=*
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
#include <EEPROM.h>
|
||||
#endif
|
||||
|
||||
ArduinoHal::ArduinoHal(): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&RADIOLIB_DEFAULT_SPI), initInterface(true) {}
|
||||
|
||||
ArduinoHal::ArduinoHal(SPIClass& spi, SPISettings spiSettings): RadioLibHal(INPUT, OUTPUT, LOW, HIGH, RISING, FALLING), spi(&spi), spiSettings(spiSettings) {}
|
||||
|
@ -57,7 +53,7 @@ void inline ArduinoHal::detachInterrupt(uint32_t interruptNum) {
|
|||
::detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delay(unsigned long ms) {
|
||||
void inline ArduinoHal::delay(RadioLibTime_t ms) {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
::delay(ms);
|
||||
#else
|
||||
|
@ -65,7 +61,7 @@ void inline ArduinoHal::delay(unsigned long ms) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delayMicroseconds(unsigned long us) {
|
||||
void inline ArduinoHal::delayMicroseconds(RadioLibTime_t us) {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
::delayMicroseconds(us);
|
||||
#else
|
||||
|
@ -73,7 +69,7 @@ void inline ArduinoHal::delayMicroseconds(unsigned long us) {
|
|||
#endif
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::millis() {
|
||||
RadioLibTime_t inline ArduinoHal::millis() {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
return(::millis());
|
||||
#else
|
||||
|
@ -81,7 +77,7 @@ unsigned long inline ArduinoHal::millis() {
|
|||
#endif
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::micros() {
|
||||
RadioLibTime_t inline ArduinoHal::micros() {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
return(::micros());
|
||||
#else
|
||||
|
@ -89,7 +85,7 @@ unsigned long inline ArduinoHal::micros() {
|
|||
#endif
|
||||
}
|
||||
|
||||
long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) {
|
||||
long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -118,48 +114,7 @@ void inline ArduinoHal::spiEnd() {
|
|||
spi->end();
|
||||
}
|
||||
|
||||
void ArduinoHal::readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
|
||||
EEPROM.begin(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE);
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3)
|
||||
EEPROM.init();
|
||||
#endif
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
buff[i] = EEPROM.read(addr + i);
|
||||
}
|
||||
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
|
||||
EEPROM.end();
|
||||
#endif
|
||||
#else
|
||||
(void)addr;
|
||||
(void)buff;
|
||||
(void)len;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ArduinoHal::writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
|
||||
#if !defined(RADIOLIB_EEPROM_UNSUPPORTED)
|
||||
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
|
||||
EEPROM.begin(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE);
|
||||
#elif defined(ARDUINO_ARCH_APOLLO3)
|
||||
EEPROM.init();
|
||||
#endif
|
||||
for(size_t i = 0; i < len; i++) {
|
||||
EEPROM.write(addr + i, buff[i]);
|
||||
}
|
||||
#if defined(RADIOLIB_ESP32) || defined(ARDUINO_ARCH_RP2040)
|
||||
EEPROM.commit();
|
||||
EEPROM.end();
|
||||
#endif
|
||||
#else
|
||||
(void)addr;
|
||||
(void)buff;
|
||||
(void)len;
|
||||
#endif
|
||||
}
|
||||
|
||||
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
|
@ -171,6 +126,8 @@ void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, unsigned long
|
|||
if(prev == -1) {
|
||||
#if !defined(ESP_IDF_VERSION) || (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5,0,0))
|
||||
ledcAttachPin(pin, RADIOLIB_TONE_ESP32_CHANNEL);
|
||||
#else
|
||||
ledcAttach(pin, frequency, 14); // 14-bit resolution should be enough
|
||||
#endif
|
||||
}
|
||||
if(prev != frequency) {
|
||||
|
|
|
@ -32,7 +32,7 @@ class ArduinoHal : public RadioLibHal {
|
|||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
\param spiSettings SPI interface settings.
|
||||
*/
|
||||
ArduinoHal(SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
explicit ArduinoHal(SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
// implementations of pure virtual RadioLibHal methods
|
||||
void pinMode(uint32_t pin, uint32_t mode) override;
|
||||
|
@ -40,30 +40,27 @@ class ArduinoHal : public RadioLibHal {
|
|||
uint32_t digitalRead(uint32_t pin) override;
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override;
|
||||
void detachInterrupt(uint32_t interruptNum) override;
|
||||
void delay(unsigned long ms) override;
|
||||
void delayMicroseconds(unsigned long us) override;
|
||||
unsigned long millis() override;
|
||||
unsigned long micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override;
|
||||
void delay(RadioLibTime_t ms) override;
|
||||
void delayMicroseconds(RadioLibTime_t us) override;
|
||||
RadioLibTime_t millis() override;
|
||||
RadioLibTime_t micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) override;
|
||||
void spiBegin() override;
|
||||
void spiBeginTransaction() override;
|
||||
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) override;
|
||||
void spiEndTransaction() override;
|
||||
void spiEnd() override;
|
||||
|
||||
void readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) override;
|
||||
void writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) override;
|
||||
|
||||
// implementations of virtual RadioLibHal methods
|
||||
void init() override;
|
||||
void term() override;
|
||||
void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) override;
|
||||
void tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration = 0) override;
|
||||
void noTone(uint32_t pin) override;
|
||||
void yield() override;
|
||||
uint32_t pinToInterrupt(uint32_t pin) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
protected:
|
||||
#endif
|
||||
SPIClass* spi = NULL;
|
||||
SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS;
|
||||
|
|
122
src/BuildOpt.h
122
src/BuildOpt.h
|
@ -1,20 +1,26 @@
|
|||
#if !defined(_RADIOLIB_BUILD_OPTIONS_H)
|
||||
#define _RADIOLIB_BUILD_OPTIONS_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
|
||||
/* RadioLib build configuration options */
|
||||
|
||||
/*
|
||||
* Debug output enable.
|
||||
* Warning: Debug output will slow down the whole system significantly.
|
||||
* Also, it will result in larger compiled binary.
|
||||
* Levels: debug - only main info
|
||||
* verbose - full transcript of all SPI communication
|
||||
* Levels: basic - only main info
|
||||
* protocol - mainly LoRaWAN stuff, but other protocols as well
|
||||
* SPI - full transcript of all SPI communication
|
||||
*/
|
||||
#if !defined(RADIOLIB_DEBUG)
|
||||
#define RADIOLIB_DEBUG (0)
|
||||
#if !defined(RADIOLIB_DEBUG_BASIC)
|
||||
#define RADIOLIB_DEBUG_BASIC (0)
|
||||
#endif
|
||||
#if !defined(RADIOLIB_VERBOSE)
|
||||
#define RADIOLIB_VERBOSE (0)
|
||||
#if !defined(RADIOLIB_DEBUG_PROTOCOL)
|
||||
#define RADIOLIB_DEBUG_PROTOCOL (0)
|
||||
#endif
|
||||
#if !defined(RADIOLIB_DEBUG_SPI)
|
||||
#define RADIOLIB_DEBUG_SPI (0)
|
||||
#endif
|
||||
|
||||
// set which output port should be used for debug output
|
||||
|
@ -100,21 +106,6 @@
|
|||
#define RADIOLIB_STATIC_ARRAY_SIZE (256)
|
||||
#endif
|
||||
|
||||
// the base address for persistent storage
|
||||
// some protocols (e.g. LoRaWAN) require a method
|
||||
// to store some data persistently
|
||||
// on Arduino, this will use EEPROM, on non-Arduino platform,
|
||||
// it will use anything provided by the hardware abstraction layer
|
||||
// RadioLib will place these starting at this address
|
||||
#if !defined(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE)
|
||||
#define RADIOLIB_HAL_PERSISTENT_STORAGE_BASE (0)
|
||||
#endif
|
||||
|
||||
// the amount of space allocated to the persistent storage
|
||||
#if !defined(RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE)
|
||||
#define RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE (0x01C0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Uncomment on boards whose clock runs too slow or too fast
|
||||
* Set the value according to the following scheme:
|
||||
|
@ -234,7 +225,6 @@
|
|||
#elif defined(SAMD_SERIES)
|
||||
// Adafruit SAMD boards (M0 and M4)
|
||||
#define RADIOLIB_PLATFORM "Adafruit SAMD"
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
#elif defined(ARDUINO_ARCH_SAMD)
|
||||
// Arduino SAMD (Zero, MKR, etc.)
|
||||
|
@ -242,18 +232,15 @@
|
|||
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
|
||||
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
|
||||
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
#elif defined(__SAM3X8E__)
|
||||
// Arduino Due
|
||||
#define RADIOLIB_PLATFORM "Arduino Due"
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
#elif (defined(NRF52832_XXAA) || defined(NRF52840_XXAA)) && !defined(ARDUINO_ARDUINO_NANO33BLE)
|
||||
// Adafruit nRF52 boards
|
||||
#define RADIOLIB_PLATFORM "Adafruit nRF52"
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
#elif defined(ARDUINO_ARC32_TOOLS)
|
||||
// Intel Curie
|
||||
|
@ -276,7 +263,6 @@
|
|||
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
|
||||
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
|
||||
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
@ -288,7 +274,6 @@
|
|||
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
|
||||
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
|
||||
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
@ -310,7 +295,6 @@
|
|||
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
|
||||
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
|
||||
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
|
||||
#define RADIOLIB_EEPROM_UNSUPPORTED
|
||||
|
||||
// Arduino mbed OS boards have a really bad tone implementation which will crash after a couple seconds
|
||||
#define RADIOLIB_TONE_UNSUPPORTED
|
||||
|
@ -368,12 +352,12 @@
|
|||
// ... and for the grand finale, we have millis() and micros() DEFINED AS MACROS!
|
||||
#if defined(millis)
|
||||
#undef millis
|
||||
inline unsigned long millis() { return((unsigned long)(STCV / 1000)); };
|
||||
inline RadioLibTime_t millis() { return((RadioLibTime_t)(STCV / 1000)); };
|
||||
#endif
|
||||
|
||||
#if defined(micros)
|
||||
#undef micros
|
||||
inline unsigned long micros() { return((unsigned long)(STCV)); };
|
||||
inline RadioLibTime_t micros() { return((RadioLibTime_t)(STCV)); };
|
||||
#endif
|
||||
|
||||
#elif defined(TEENSYDUINO)
|
||||
|
@ -469,23 +453,35 @@
|
|||
#define RADIOLIB_EXCLUDE_STM32WLX (1)
|
||||
#endif
|
||||
|
||||
// set the global debug mode flag
|
||||
#if RADIOLIB_DEBUG_BASIC || RADIOLIB_DEBUG_PROTOCOL || RADIOLIB_DEBUG_SPI
|
||||
#define RADIOLIB_DEBUG (1)
|
||||
#else
|
||||
#define RADIOLIB_DEBUG (0)
|
||||
#endif
|
||||
|
||||
#if RADIOLIB_DEBUG
|
||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||
#define RADIOLIB_DEBUG_PRINT(...) Module::serialPrintf(__VA_ARGS__)
|
||||
#define RADIOLIB_DEBUG_PRINTLN(M, ...) Module::serialPrintf(M "\n", ##__VA_ARGS__)
|
||||
#define RADIOLIB_DEBUG_PRINT_LVL(LEVEL, M, ...) Module::serialPrintf(LEVEL "" M, ##__VA_ARGS__)
|
||||
#define RADIOLIB_DEBUG_PRINTLN_LVL(LEVEL, M, ...) Module::serialPrintf(LEVEL "" M "\n", ##__VA_ARGS__)
|
||||
|
||||
// some platforms do not support printf("%f"), so it has to be done this way
|
||||
#define RADIOLIB_DEBUG_PRINT_FLOAT(VAL, DECIMALS) RADIOLIB_DEBUG_PORT.print(VAL, DECIMALS)
|
||||
#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(VAL, DECIMALS) RADIOLIB_DEBUG_PRINT("%.3f", VAL)
|
||||
#define RADIOLIB_DEBUG_PRINT_FLOAT(LEVEL, VAL, DECIMALS) RADIOLIB_DEBUG_PRINT(LEVEL "%.3f", VAL)
|
||||
#endif
|
||||
#define RADIOLIB_DEBUG_HEXDUMP(...) Module::hexdump(__VA_ARGS__)
|
||||
|
||||
#define RADIOLIB_DEBUG_HEXDUMP(LEVEL, ...) Module::hexdump(LEVEL, __VA_ARGS__)
|
||||
#else
|
||||
#define RADIOLIB_DEBUG_PRINT(...) {}
|
||||
#define RADIOLIB_DEBUG_PRINTLN(...) {}
|
||||
|
@ -493,14 +489,60 @@
|
|||
#define RADIOLIB_DEBUG_HEXDUMP(...) {}
|
||||
#endif
|
||||
|
||||
#if RADIOLIB_VERBOSE
|
||||
#define RADIOLIB_VERBOSE_PRINT(...) RADIOLIB_DEBUG_PRINT(__VA_ARGS__)
|
||||
#define RADIOLIB_VERBOSE_PRINTLN(...) RADIOLIB_DEBUG_PRINTLN(__VA_ARGS__)
|
||||
#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__);
|
||||
#else
|
||||
#define RADIOLIB_VERBOSE_PRINT(...) {}
|
||||
#define RADIOLIB_VERBOSE_PRINTLN(...) {}
|
||||
#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(...) {}
|
||||
#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__);
|
||||
#else
|
||||
#define RADIOLIB_DEBUG_PROTOCOL_PRINT(...) {}
|
||||
#define RADIOLIB_DEBUG_PROTOCOL_PRINTLN(...) {}
|
||||
#define RADIOLIB_DEBUG_PROTOCOL_PRINT_FLOAT(...) {}
|
||||
#define RADIOLIB_DEBUG_PROTOCOL_HEXDUMP(...) {}
|
||||
#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__);
|
||||
#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(...) {}
|
||||
#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: \"" \
|
||||
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__)
|
||||
|
||||
/*!
|
||||
\brief A simple assert macro, will return on error.
|
||||
*/
|
||||
|
@ -528,8 +570,8 @@
|
|||
|
||||
// version definitions
|
||||
#define RADIOLIB_VERSION_MAJOR 6
|
||||
#define RADIOLIB_VERSION_MINOR 4
|
||||
#define RADIOLIB_VERSION_PATCH 1
|
||||
#define RADIOLIB_VERSION_MINOR 6
|
||||
#define RADIOLIB_VERSION_PATCH 0
|
||||
#define RADIOLIB_VERSION_EXTRA 0
|
||||
|
||||
#define RADIOLIB_VERSION (((RADIOLIB_VERSION_MAJOR) << 24) | ((RADIOLIB_VERSION_MINOR) << 16) | ((RADIOLIB_VERSION_PATCH) << 8) | (RADIOLIB_VERSION_EXTRA))
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
// most commonly, RADIOLIB_EXCLUDE_* macros
|
||||
// or enabling debug output
|
||||
|
||||
//#define RADIOLIB_DEBUG (1)
|
||||
//#define RADIOLIB_VERBOSE (1)
|
||||
//#define RADIOLIB_DEBUG_BASIC (1) // basic debugging (e.g. reporting GPIO timeouts or module not being found)
|
||||
//#define RADIOLIB_DEBUG_PROTOCOL (1) // protocol information (e.g. LoRaWAN internal information)
|
||||
//#define RADIOLIB_DEBUG_SPI (1) // verbose transcription of all SPI communication - produces large debug logs!
|
||||
|
||||
#endif
|
||||
|
|
49
src/Hal.cpp
49
src/Hal.cpp
|
@ -16,7 +16,7 @@ void RadioLibHal::term() {
|
|||
|
||||
}
|
||||
|
||||
void RadioLibHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
void RadioLibHal::tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration) {
|
||||
(void)pin;
|
||||
(void)frequency;
|
||||
(void)duration;
|
||||
|
@ -33,50 +33,3 @@ void RadioLibHal::yield() {
|
|||
uint32_t RadioLibHal::pinToInterrupt(uint32_t pin) {
|
||||
return(pin);
|
||||
}
|
||||
|
||||
void RadioLibHal::readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
|
||||
// these are only needed for some protocols, so it's not needed to have them by default
|
||||
(void)addr;
|
||||
(void)buff;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
void RadioLibHal::writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len) {
|
||||
// these are only needed for some protocols, so it's not needed to have them by default
|
||||
(void)addr;
|
||||
(void)buff;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
void RadioLibHal::wipePersistentStorage() {
|
||||
uint8_t dummy = 0;
|
||||
for(size_t i = 0; i < RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE; i++) {
|
||||
this->writePersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + i, &dummy, sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RadioLibHal::getPersistentAddr(uint32_t id) {
|
||||
return(RadioLibPersistentParamTable[id]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void RadioLibHal::setPersistentParameter(uint32_t id, T val, uint32_t offset) {
|
||||
uint8_t *ptr = (uint8_t*)&val;
|
||||
this->writePersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + RadioLibPersistentParamTable[id] + offset, ptr, sizeof(T));
|
||||
}
|
||||
|
||||
template void RadioLibHal::setPersistentParameter(uint32_t id, uint8_t val, uint32_t offset);
|
||||
template void RadioLibHal::setPersistentParameter(uint32_t id, uint16_t val, uint32_t offset);
|
||||
template void RadioLibHal::setPersistentParameter(uint32_t id, uint32_t val, uint32_t offset);
|
||||
|
||||
template<typename T>
|
||||
T RadioLibHal::getPersistentParameter(uint32_t id) {
|
||||
T val = 0;
|
||||
uint8_t *ptr = (uint8_t*)&val;
|
||||
this->readPersistentStorage(RADIOLIB_HAL_PERSISTENT_STORAGE_BASE + RadioLibPersistentParamTable[id], ptr, sizeof(T));
|
||||
return(val);
|
||||
}
|
||||
|
||||
template uint8_t RadioLibHal::getPersistentParameter(uint32_t id);
|
||||
template uint16_t RadioLibHal::getPersistentParameter(uint32_t id);
|
||||
template uint32_t RadioLibHal::getPersistentParameter(uint32_t id);
|
||||
|
|
144
src/Hal.h
144
src/Hal.h
|
@ -6,88 +6,6 @@
|
|||
|
||||
#include "BuildOpt.h"
|
||||
|
||||
#define RADIOLIB_EEPROM_TABLE_VERSION (0x0002)
|
||||
|
||||
// list of persistent parameters
|
||||
enum RADIOLIB_EEPROM_PARAMS {
|
||||
RADIOLIB_EEPROM_TABLE_VERSION_ID, // table layout version
|
||||
RADIOLIB_EEPROM_LORAWAN_CLASS_ID, // class A, B or C
|
||||
RADIOLIB_EEPROM_LORAWAN_MODE_ID, // none, OTAA or ABP
|
||||
RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID, // checksum of keys used for device activation
|
||||
RADIOLIB_EEPROM_LORAWAN_VERSION_ID, // LoRaWAN version
|
||||
RADIOLIB_EEPROM_LORAWAN_LAST_TIME_ID, // last heard time through DeviceTimeReq or Beacon
|
||||
RADIOLIB_EEPROM_LORAWAN_DEV_ADDR_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_APP_S_KEY_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_FNWK_SINT_KEY_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_SNWK_SINT_KEY_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_NWK_SENC_KEY_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_N_FCNT_DOWN_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_UP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_DOWN_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_ADR_FCNT_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_RJ_COUNT0_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_RJ_COUNT1_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_FCNT_UP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_DUTY_CYCLE_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_RX_PARAM_SETUP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_RX_TIMING_SETUP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_TX_PARAM_SETUP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_ADR_PARAM_SETUP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_REJOIN_PARAM_SETUP_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_BEACON_FREQ_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_PING_SLOT_CHANNEL_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_PERIODICITY_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_MAC_QUEUE_UL_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID,
|
||||
RADIOLIB_EEPROM_LORAWAN_DL_CHANNELS_ID
|
||||
};
|
||||
|
||||
static const uint32_t RadioLibPersistentParamTable[] = {
|
||||
0x00, // RADIOLIB_EEPROM_LORAWAN_TABLE_VERSION_ID
|
||||
0x02, // RADIOLIB_EEPROM_LORAWAN_CLASS_ID
|
||||
0x03, // RADIOLIB_EEPROM_LORAWAN_MODE_ID
|
||||
0x05, // RADIOLIB_EEPROM_LORAWAN_CHECKSUM_ID
|
||||
0x07, // RADIOLIB_EEPROM_LORAWAN_VERSION_ID
|
||||
0x08, // RADIOLIB_EEPROM_LORAWAN_LAST_TIME_ID
|
||||
0x0C, // RADIOLIB_EEPROM_LORAWAN_DEV_ADDR_ID
|
||||
0x10, // RADIOLIB_EEPROM_LORAWAN_APP_S_KEY_ID
|
||||
0x20, // RADIOLIB_EEPROM_LORAWAN_FNWK_SINT_KEY_ID
|
||||
0x30, // RADIOLIB_EEPROM_LORAWAN_SNWK_SINT_KEY_ID
|
||||
0x40, // RADIOLIB_EEPROM_LORAWAN_NWK_SENC_KEY_ID
|
||||
0x50, // RADIOLIB_EEPROM_LORAWAN_DEV_NONCE_ID
|
||||
0x54, // RADIOLIB_EEPROM_LORAWAN_JOIN_NONCE_ID
|
||||
0x58, // RADIOLIB_EEPROM_LORAWAN_HOME_NET_ID
|
||||
0x5C, // RADIOLIB_EEPROM_LORAWAN_A_FCNT_DOWN_ID
|
||||
0x60, // RADIOLIB_EEPROM_LORAWAN_N_FCNT_DOWN_ID
|
||||
0x64, // RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_UP_ID
|
||||
0x68, // RADIOLIB_EEPROM_LORAWAN_CONF_FCNT_DOWN_ID
|
||||
0x6C, // RADIOLIB_EEPROM_LORAWAN_ADR_FCNT_ID
|
||||
0x70, // RADIOLIB_EEPROM_LORAWAN_RJ_COUNT0_ID
|
||||
0x72, // RADIOLIB_EEPROM_LORAWAN_RJ_COUNT1_ID
|
||||
0x74, // RADIOLIB_EEPROM_LORAWAN_FCNT_UP_ID
|
||||
0xA0, // RADIOLIB_EEPROM_LORAWAN_LINK_ADR_ID
|
||||
0xA4, // RADIOLIB_EEPROM_LORAWAN_DUTY_CYCLE_ID
|
||||
0xA5, // RADIOLIB_EEPROM_LORAWAN_RX_PARAM_SETUP_ID
|
||||
0xA9, // RADIOLIB_EEPROM_LORAWAN_RX_TIMING_SETUP_ID
|
||||
0xAA, // RADIOLIB_EEPROM_LORAWAN_TX_PARAM_SETUP_ID
|
||||
0xAB, // RADIOLIB_EEPROM_LORAWAN_ADR_PARAM_SETUP_ID
|
||||
0xAC, // RADIOLIB_EEPROM_LORAWAN_REJOIN_PARAM_SETUP_ID
|
||||
0xAD, // RADIOLIB_EEPROM_LORAWAN_BEACON_FREQ_ID
|
||||
0xB0, // RADIOLIB_EEPROM_LORAWAN_PING_SLOT_CHANNEL_ID
|
||||
0xB4, // RADIOLIB_EEPROM_LORAWAN_PERIODICITY_ID
|
||||
0xB5, // RADIOLIB_EEPROM_LORAWAN_NUM_ADR_MASKS_ID
|
||||
0xB6, // RADIOLIB_EEPROM_LORAWAN_MAC_QUEUE_UL_ID
|
||||
0x0100, // RADIOLIB_EEPROM_LORAWAN_UL_CHANNELS_ID
|
||||
0x0180, // RADIOLIB_EEPROM_LORAWAN_DL_CHANNELS_ID
|
||||
0x01C0, // end
|
||||
};
|
||||
|
||||
/*!
|
||||
\class RadioLibHal
|
||||
\brief Hardware abstraction library base interface.
|
||||
|
@ -186,28 +104,28 @@ class RadioLibHal {
|
|||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param ms Number of milliseconds to wait.
|
||||
*/
|
||||
virtual void delay(unsigned long ms) = 0;
|
||||
virtual void delay(RadioLibTime_t ms) = 0;
|
||||
|
||||
/*!
|
||||
\brief Blocking microsecond wait function.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param us Number of microseconds to wait.
|
||||
*/
|
||||
virtual void delayMicroseconds(unsigned long us) = 0;
|
||||
virtual void delayMicroseconds(RadioLibTime_t us) = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of milliseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of milliseconds since start.
|
||||
*/
|
||||
virtual unsigned long millis() = 0;
|
||||
virtual RadioLibTime_t millis() = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of microseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of microseconds since start.
|
||||
*/
|
||||
virtual unsigned long micros() = 0;
|
||||
virtual RadioLibTime_t micros() = 0;
|
||||
|
||||
/*!
|
||||
\brief Measure the length of incoming digital pulse in microseconds.
|
||||
|
@ -217,7 +135,7 @@ class RadioLibHal {
|
|||
\param timeout Timeout in microseconds.
|
||||
\returns Pulse length in microseconds, or 0 if the pulse did not start before timeout.
|
||||
*/
|
||||
virtual long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) = 0;
|
||||
virtual long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) = 0;
|
||||
|
||||
/*!
|
||||
\brief SPI initialization method.
|
||||
|
@ -270,7 +188,7 @@ class RadioLibHal {
|
|||
\param frequency Frequency of the square wave.
|
||||
\param duration Duration of the tone in ms. When set to 0, the tone will be infinite.
|
||||
*/
|
||||
virtual void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0);
|
||||
virtual void tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration = 0);
|
||||
|
||||
/*!
|
||||
\brief Method to stop producing a tone.
|
||||
|
@ -289,56 +207,6 @@ class RadioLibHal {
|
|||
\returns The interrupt number of a given pin.
|
||||
*/
|
||||
virtual uint32_t pinToInterrupt(uint32_t pin);
|
||||
|
||||
/*!
|
||||
\brief Method to read from persistent storage (e.g. EEPROM).
|
||||
\param addr Address to start reading at.
|
||||
\param buff Buffer to read into.
|
||||
\param len Number of bytes to read.
|
||||
*/
|
||||
virtual void readPersistentStorage(uint32_t addr, uint8_t* buff, size_t len);
|
||||
|
||||
/*!
|
||||
\brief Method to write to persistent storage (e.g. EEPROM).
|
||||
\param addr Address to start writing to.
|
||||
\param buff Buffer to write.
|
||||
\param len Number of bytes to write.
|
||||
*/
|
||||
virtual void writePersistentStorage(uint32_t addr, uint8_t* buff, size_t len);
|
||||
|
||||
/*!
|
||||
\brief Method to wipe the persistent storage by writing to 0.
|
||||
Will write at most RADIOLIB_HAL_PERSISTENT_STORAGE_SIZE bytes.
|
||||
*/
|
||||
void wipePersistentStorage();
|
||||
|
||||
/*!
|
||||
\brief Method to convert from persistent parameter ID to its physical address.
|
||||
\param id Parameter ID.
|
||||
\returns Parameter physical address.
|
||||
*/
|
||||
uint32_t getPersistentAddr(uint32_t id);
|
||||
|
||||
/*!
|
||||
\brief Method to set arbitrary parameter to persistent storage.
|
||||
This method DOES NOT perform any endianness conversion, so the value
|
||||
will be stored in the system endian!
|
||||
\param id Parameter ID to save at.
|
||||
\param val Value to set.
|
||||
\param offset An additional offset added to the address.
|
||||
*/
|
||||
template<typename T>
|
||||
void setPersistentParameter(uint32_t id, T val, uint32_t offset = 0);
|
||||
|
||||
/*!
|
||||
\brief Method to get arbitrary parameter from persistent storage.
|
||||
This method DOES NOT perform any endianness conversion, so the value
|
||||
will be retrieved in the system endian!
|
||||
\param id Parameter ID to load from.
|
||||
\returns The loaded value.
|
||||
*/
|
||||
template<typename T>
|
||||
T getPersistentParameter(uint32_t id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
295
src/Module.cpp
295
src/Module.cpp
|
@ -31,8 +31,7 @@ Module::Module(const Module& mod) {
|
|||
}
|
||||
|
||||
Module& Module::operator=(const Module& mod) {
|
||||
this->SPIreadCommand = mod.SPIreadCommand;
|
||||
this->SPIwriteCommand = mod.SPIwriteCommand;
|
||||
memcpy((void*)&mod.spiConfig, &this->spiConfig, sizeof(SPIConfig_t));
|
||||
this->csPin = mod.csPin;
|
||||
this->irqPin = mod.irqPin;
|
||||
this->rstPin = mod.rstPin;
|
||||
|
@ -40,14 +39,12 @@ Module& Module::operator=(const Module& mod) {
|
|||
return(*this);
|
||||
}
|
||||
|
||||
static volatile const char info[] = RADIOLIB_INFO;
|
||||
void Module::init() {
|
||||
this->hal->init();
|
||||
this->hal->pinMode(csPin, this->hal->GpioModeOutput);
|
||||
this->hal->digitalWrite(csPin, this->hal->GpioLevelHigh);
|
||||
RADIOLIB_DEBUG_PRINTLN("\nRadioLib Debug Info");
|
||||
RADIOLIB_DEBUG_PRINTLN("Version: %d.%d.%d.%d", RADIOLIB_VERSION_MAJOR, RADIOLIB_VERSION_MINOR, RADIOLIB_VERSION_PATCH, RADIOLIB_VERSION_EXTRA);
|
||||
RADIOLIB_DEBUG_PRINTLN("Platform: " RADIOLIB_PLATFORM);
|
||||
RADIOLIB_DEBUG_PRINTLN("Compiled: " __DATE__ " " __TIME__ "\n");
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN(RADIOLIB_INFO);
|
||||
}
|
||||
|
||||
void Module::term() {
|
||||
|
@ -55,7 +52,7 @@ void Module::term() {
|
|||
this->hal->term();
|
||||
}
|
||||
|
||||
int16_t Module::SPIgetRegValue(uint16_t reg, uint8_t msb, uint8_t lsb) {
|
||||
int16_t Module::SPIgetRegValue(uint32_t reg, uint8_t msb, uint8_t lsb) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
@ -65,7 +62,7 @@ int16_t Module::SPIgetRegValue(uint16_t reg, uint8_t msb, uint8_t lsb) {
|
|||
return(maskedValue);
|
||||
}
|
||||
|
||||
int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
@ -78,25 +75,30 @@ int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#if RADIOLIB_SPI_PARANOID
|
||||
// check register value each millisecond until check interval is reached
|
||||
// some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
|
||||
uint32_t start = this->hal->micros();
|
||||
RadioLibTime_t start = this->hal->micros();
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
uint8_t readValue = 0x00;
|
||||
#endif
|
||||
while(this->hal->micros() - start < (checkInterval * 1000)) {
|
||||
readValue = SPIreadRegister(reg);
|
||||
if((readValue & checkMask) == (newValue & checkMask)) {
|
||||
uint8_t val = SPIreadRegister(reg);
|
||||
if((val & checkMask) == (newValue & checkMask)) {
|
||||
// check passed, we can stop the loop
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
readValue = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
// check failed, print debug info
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
RADIOLIB_DEBUG_PRINTLN("address:\t0x%X", reg);
|
||||
RADIOLIB_DEBUG_PRINTLN("bits:\t\t%d %d", msb, lsb);
|
||||
RADIOLIB_DEBUG_PRINTLN("value:\t\t0x%X", value);
|
||||
RADIOLIB_DEBUG_PRINTLN("current:\t0x%X", currentValue);
|
||||
RADIOLIB_DEBUG_PRINTLN("mask:\t\t0x%X", mask);
|
||||
RADIOLIB_DEBUG_PRINTLN("new:\t\t0x%X", newValue);
|
||||
RADIOLIB_DEBUG_PRINTLN("read:\t\t0x%X", readValue);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN();
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("address:\t0x%X", reg);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("bits:\t\t%d %d", msb, lsb);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("value:\t\t0x%X", value);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("current:\t0x%X", currentValue);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("mask:\t\t0x%X", mask);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("new:\t\t0x%X", newValue);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("read:\t\t0x%X", readValue);
|
||||
|
||||
return(RADIOLIB_ERR_SPI_WRITE_FAILED);
|
||||
#else
|
||||
|
@ -104,47 +106,75 @@ int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#endif
|
||||
}
|
||||
|
||||
void Module::SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
|
||||
void Module::SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes) {
|
||||
if(!this->spiConfig.stream) {
|
||||
SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, inBytes, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, inBytes, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, inBytes, numBytes, true);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Module::SPIreadRegister(uint16_t reg) {
|
||||
uint8_t Module::SPIreadRegister(uint32_t reg) {
|
||||
uint8_t resp = 0;
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, &resp, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, &resp, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, &resp, 1, true);
|
||||
}
|
||||
return(resp);
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegisterBurst(uint16_t reg, uint8_t* data, size_t numBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
|
||||
void Module::SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes) {
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, data, NULL, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, data, NULL, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, data, NULL, numBytes, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegister(uint16_t reg, uint8_t data) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
|
||||
void Module::SPIwriteRegister(uint32_t reg, uint8_t data) {
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, &data, NULL, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, &data, NULL, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, &data, NULL, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
|
||||
void Module::SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
|
||||
// prepare the buffers
|
||||
size_t buffLen = this->SPIaddrWidth/8 + numBytes;
|
||||
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
|
||||
uint8_t buffOut[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
|
@ -155,7 +185,8 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
uint8_t* buffOutPtr = buffOut;
|
||||
|
||||
// copy the command
|
||||
if(this->SPIaddrWidth <= 8) {
|
||||
// TODO properly handle variable commands and addresses
|
||||
if(this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] <= 8) {
|
||||
*(buffOutPtr++) = reg | cmd;
|
||||
} else {
|
||||
*(buffOutPtr++) = (reg >> 8) | cmd;
|
||||
|
@ -163,10 +194,10 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
}
|
||||
|
||||
// copy the data
|
||||
if(cmd == SPIwriteCommand) {
|
||||
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
|
||||
memcpy(buffOutPtr, dataOut, numBytes);
|
||||
} else {
|
||||
memset(buffOutPtr, this->SPInopCommand, numBytes);
|
||||
memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes);
|
||||
}
|
||||
|
||||
// do the transfer
|
||||
|
@ -177,24 +208,24 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
this->hal->spiEndTransaction();
|
||||
|
||||
// copy the data
|
||||
if(cmd == SPIreadCommand) {
|
||||
memcpy(dataIn, &buffIn[this->SPIaddrWidth/8], numBytes);
|
||||
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
|
||||
memcpy(dataIn, &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8], numBytes);
|
||||
}
|
||||
|
||||
// print debug information
|
||||
#if RADIOLIB_VERBOSE
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
uint8_t* debugBuffPtr = NULL;
|
||||
if(cmd == SPIwriteCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT("W\t%X\t", reg);
|
||||
debugBuffPtr = &buffOut[this->SPIaddrWidth/8];
|
||||
} else if(cmd == SPIreadCommand) {
|
||||
RADIOLIB_VERBOSE_PRINT("R\t%X\t", reg);
|
||||
debugBuffPtr = &buffIn[this->SPIaddrWidth/8];
|
||||
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];
|
||||
} else if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
|
||||
RADIOLIB_DEBUG_SPI_PRINT("R\t%X\t", reg);
|
||||
debugBuffPtr = &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
|
||||
}
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", debugBuffPtr[n]);
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", debugBuffPtr[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
|
||||
#endif
|
||||
|
||||
#if !RADIOLIB_STATIC_ONLY
|
||||
|
@ -203,38 +234,60 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIreadStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIreadStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
int16_t Module::SPIreadStream(uint16_t cmd, 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--) {
|
||||
*(cmdPtr++) = (cmd >> 8*i) & 0xFF;
|
||||
}
|
||||
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) {
|
||||
// send the command
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#if !RADIOLIB_SPI_PARANOID
|
||||
(void)verify;
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
#else
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
|
||||
state = this->spiConfig.checkStatusCb(this);
|
||||
}
|
||||
|
||||
return(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIwriteStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIwriteStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
int16_t Module::SPIwriteStream(uint16_t cmd, 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--) {
|
||||
*(cmdPtr++) = (cmd >> 8*i) & 0xFF;
|
||||
}
|
||||
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) {
|
||||
// send the command
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#if !RADIOLIB_SPI_PARANOID
|
||||
(void)verify;
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
#else
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
|
||||
state = this->spiConfig.checkStatusCb(this);
|
||||
}
|
||||
|
||||
return(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIcheckStream() {
|
||||
|
@ -243,31 +296,33 @@ int16_t Module::SPIcheckStream() {
|
|||
#if RADIOLIB_SPI_PARANOID
|
||||
// get the status
|
||||
uint8_t spiStatus = 0;
|
||||
uint8_t cmd = this->SPIstatusCommand;
|
||||
state = this->SPItransferStream(&cmd, 1, false, NULL, &spiStatus, 0, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
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--) {
|
||||
*(cmdPtr++) = ( this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] >> 8*i) & 0xFF;
|
||||
}
|
||||
state = this->SPItransferStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, false, NULL, &spiStatus, 1, true);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// translate to RadioLib status code
|
||||
if(this->SPIparseStatusCb != nullptr) {
|
||||
this->SPIstreamError = this->SPIparseStatusCb(spiStatus);
|
||||
if(this->spiConfig.parseStatusCb != nullptr) {
|
||||
this->spiConfig.err = this->spiConfig.parseStatusCb(spiStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout) {
|
||||
// prepare the buffers
|
||||
int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio) {
|
||||
// prepare the output buffer
|
||||
size_t buffLen = cmdLen + numBytes;
|
||||
if(!write) {
|
||||
buffLen++;
|
||||
buffLen += (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8);
|
||||
}
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buffOut[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buffOut = new uint8_t[buffLen];
|
||||
uint8_t* buffIn = new uint8_t[buffLen];
|
||||
#endif
|
||||
uint8_t* buffOutPtr = buffOut;
|
||||
|
||||
|
@ -280,27 +335,33 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
if(write) {
|
||||
memcpy(buffOutPtr, dataOut, numBytes);
|
||||
} else {
|
||||
memset(buffOutPtr, this->SPInopCommand, numBytes + 1);
|
||||
memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8));
|
||||
}
|
||||
|
||||
// ensure GPIO is low
|
||||
if(this->gpioPin == RADIOLIB_NC) {
|
||||
this->hal->delay(1);
|
||||
this->hal->delay(50);
|
||||
} else {
|
||||
uint32_t start = this->hal->millis();
|
||||
RadioLibTime_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
RADIOLIB_DEBUG_PRINTLN("GPIO pre-transfer timeout, is it connected?");
|
||||
if(this->hal->millis() - start >= this->spiConfig.timeout) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO pre-transfer timeout, is it connected?");
|
||||
#if !RADIOLIB_STATIC_ONLY
|
||||
delete[] buffOut;
|
||||
delete[] buffIn;
|
||||
#endif
|
||||
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the input buffer
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buffIn = new uint8_t[buffLen];
|
||||
#endif
|
||||
|
||||
// do the transfer
|
||||
this->hal->spiBeginTransaction();
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
|
||||
|
@ -314,11 +375,11 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
this->hal->delay(1);
|
||||
} else {
|
||||
this->hal->delayMicroseconds(1);
|
||||
uint32_t start = this->hal->millis();
|
||||
RadioLibTime_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
RADIOLIB_DEBUG_PRINTLN("GPIO post-transfer timeout, is it connected?");
|
||||
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;
|
||||
|
@ -331,42 +392,45 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
|
||||
// parse status
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
if((this->SPIparseStatusCb != nullptr) && (numBytes > 0)) {
|
||||
state = this->SPIparseStatusCb(buffIn[cmdLen]);
|
||||
if((this->spiConfig.parseStatusCb != nullptr) && (numBytes > 0)) {
|
||||
state = this->spiConfig.parseStatusCb(buffIn[this->spiConfig.statusPos]);
|
||||
}
|
||||
|
||||
// copy the data
|
||||
if(!write) {
|
||||
// skip the first byte for read-type commands (status-only)
|
||||
memcpy(dataIn, &buffIn[cmdLen + 1], numBytes);
|
||||
// skip the status bytes if present
|
||||
memcpy(dataIn, &buffIn[cmdLen + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8)], numBytes);
|
||||
}
|
||||
|
||||
// print debug information
|
||||
#if RADIOLIB_VERBOSE
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
// print command byte(s)
|
||||
RADIOLIB_VERBOSE_PRINT("CMD");
|
||||
RADIOLIB_DEBUG_SPI_PRINT("CMD");
|
||||
if(write) {
|
||||
RADIOLIB_VERBOSE_PRINT("W\t");
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("W\t");
|
||||
} else {
|
||||
RADIOLIB_VERBOSE_PRINT("R\t");
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("R\t");
|
||||
}
|
||||
size_t n = 0;
|
||||
for(; n < cmdLen; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", cmd[n]);
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", cmd[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
|
||||
|
||||
// print data bytes
|
||||
RADIOLIB_VERBOSE_PRINT("SI\t");
|
||||
RADIOLIB_DEBUG_SPI_PRINT("SI\t");
|
||||
for(n = 0; n < cmdLen; n++) {
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("\t");
|
||||
}
|
||||
for(; n < buffLen; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", buffOut[n]);
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", buffOut[n]);
|
||||
}
|
||||
RADIOLIB_VERBOSE_PRINTLN();
|
||||
RADIOLIB_VERBOSE_PRINT("SO\t");
|
||||
for(n = cmdLen; n < buffLen; n++) {
|
||||
RADIOLIB_VERBOSE_PRINT("%X\t", buffIn[n]);
|
||||
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_VERBOSE_PRINTLN();
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN_NOTAG();
|
||||
#endif
|
||||
|
||||
#if !RADIOLIB_STATIC_ONLY
|
||||
|
@ -377,7 +441,7 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
return(state);
|
||||
}
|
||||
|
||||
void Module::waitForMicroseconds(uint32_t start, uint32_t len) {
|
||||
void Module::waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len) {
|
||||
#if RADIOLIB_INTERRUPT_TIMING
|
||||
(void)start;
|
||||
if((this->TimerSetupCb != nullptr) && (len != this->prevTimingLen)) {
|
||||
|
@ -404,11 +468,11 @@ uint32_t Module::reflect(uint32_t in, uint8_t bits) {
|
|||
}
|
||||
|
||||
#if RADIOLIB_DEBUG
|
||||
void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
|
||||
void Module::hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
|
||||
size_t rem_len = len;
|
||||
for(size_t i = 0; i < len; i+=16) {
|
||||
char str[80];
|
||||
sprintf(str, "%07" PRIx32 " ", i+offset);
|
||||
char str[120];
|
||||
sprintf(str, "%07" PRIx32 " ", (uint32_t)i+offset);
|
||||
size_t line_len = 16;
|
||||
if(rem_len < line_len) {
|
||||
line_len = rem_len;
|
||||
|
@ -433,15 +497,24 @@ void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width,
|
|||
}
|
||||
str[56] = '|';
|
||||
str[57] = ' ';
|
||||
|
||||
// at this point we need to start escaping "%" characters
|
||||
char* strPtr = &str[58];
|
||||
for(size_t j = 0; j < line_len; j++) {
|
||||
char c = data[i+j];
|
||||
if((c < ' ') || (c > '~')) {
|
||||
c = '.';
|
||||
} else if(c == '%') {
|
||||
*strPtr++ = '%';
|
||||
}
|
||||
sprintf(&str[58 + j], "%c", c);
|
||||
sprintf(strPtr++, "%c", c);
|
||||
|
||||
}
|
||||
for(size_t j = line_len; j < 16; j++) {
|
||||
sprintf(&str[58 + j], " ");
|
||||
sprintf(strPtr++, " ");
|
||||
}
|
||||
if(level) {
|
||||
RADIOLIB_DEBUG_PRINT(level);
|
||||
}
|
||||
RADIOLIB_DEBUG_PRINT(str);
|
||||
RADIOLIB_DEBUG_PRINTLN();
|
||||
|
@ -449,14 +522,14 @@ void Module::hexdump(uint8_t* data, size_t len, uint32_t offset, uint8_t width,
|
|||
}
|
||||
}
|
||||
|
||||
void Module::regdump(uint16_t start, size_t len) {
|
||||
void Module::regdump(const char* level, uint16_t start, size_t len) {
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buff[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buff = new uint8_t[len];
|
||||
#endif
|
||||
SPIreadRegisterBurst(start, len, buff);
|
||||
hexdump(buff, len, start);
|
||||
hexdump(level, buff, len, start);
|
||||
#if !RADIOLIB_STATIC_ONLY
|
||||
delete[] buff;
|
||||
#endif
|
||||
|
@ -481,7 +554,7 @@ size_t Module::serialPrintf(const char* format, ...) {
|
|||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = RADIOLIB_DEBUG_PORT.write((const uint8_t*)buffer, len);
|
||||
len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
@ -492,7 +565,7 @@ size_t Module::serialPrintf(const char* format, ...) {
|
|||
void Module::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
|
||||
// This can be on the stack, setRfSwitchTable copies the contents
|
||||
const uint32_t pins[] = {
|
||||
rxEn, txEn, RADIOLIB_NC,
|
||||
rxEn, txEn, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC,
|
||||
};
|
||||
|
||||
// This must be static, since setRfSwitchTable stores a reference.
|
||||
|
@ -505,7 +578,7 @@ void Module::setRfSwitchPins(uint32_t rxEn, uint32_t txEn) {
|
|||
setRfSwitchTable(pins, table);
|
||||
}
|
||||
|
||||
void Module::setRfSwitchTable(const uint32_t (&pins)[3], const RfSwitchMode_t table[]) {
|
||||
void Module::setRfSwitchTable(const uint32_t (&pins)[RFSWITCH_MAX_PINS], const RfSwitchMode_t table[]) {
|
||||
memcpy(this->rfSwitchPins, pins, sizeof(this->rfSwitchPins));
|
||||
this->rfSwitchTable = table;
|
||||
for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++)
|
||||
|
|
233
src/Module.h
233
src/Module.h
|
@ -13,15 +13,49 @@
|
|||
#endif
|
||||
|
||||
/*!
|
||||
* Value to use as the last element in a mode table to indicate the
|
||||
* end of the table.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
\def END_OF_MODE_TABLE Value to use as the last element in a mode table to indicate the
|
||||
end of the table. See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
#define END_OF_MODE_TABLE { Module::MODE_END_OF_TABLE, {} }
|
||||
|
||||
// default timeout for SPI transfers
|
||||
#define RADIOLIB_MODULE_SPI_TIMEOUT (1000)
|
||||
/*!
|
||||
\defgroup module_spi_command_pos Position of commands in Module::spiConfig command array.
|
||||
\{
|
||||
*/
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_READ Position of the read command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_READ (0)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_WRITE Position of the write command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_WRITE (1)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_NOP Position of the no-operation command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_NOP (2)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_STATUS Position of the status command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_STATUS (3)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup module_spi_width_pos Position of bit field widths in Module::spiConfig width array.
|
||||
\{
|
||||
*/
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_ADDR Position of the address width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_ADDR (0)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_CMD Position of the command width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_CMD (1)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_STATUS Position of the status width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_STATUS (2)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class Module
|
||||
|
@ -31,43 +65,49 @@
|
|||
class Module {
|
||||
public:
|
||||
/*!
|
||||
* \brief The maximum number of pins supported by the RF switch
|
||||
* code.
|
||||
*
|
||||
* Note: It is not recommended to use this constant in your sketch
|
||||
* when defining a rfswitch pins array, to prevent issues when this
|
||||
* value is ever increased and such an array gets extra zero
|
||||
* elements (that will be interpreted as pin 0).
|
||||
*/
|
||||
static const size_t RFSWITCH_MAX_PINS = 3;
|
||||
\brief The maximum number of pins supported by the RF switch code.
|
||||
Note: It is not recommended to use this constant in your sketch
|
||||
when defining a rfswitch pins array, to prevent issues when this
|
||||
value is ever increased and such an array gets extra zero
|
||||
elements (that will be interpreted as pin 0).
|
||||
*/
|
||||
static const size_t RFSWITCH_MAX_PINS = 5;
|
||||
|
||||
/*!
|
||||
* Description of RF switch pin states for a single mode.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
\struct RfSwitchMode_t
|
||||
\brief Description of RF switch pin states for a single mode.
|
||||
See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
struct RfSwitchMode_t {
|
||||
/*! \brief RF switching mode, one of \ref OpMode_t or a custom radio-defined value. */
|
||||
uint8_t mode;
|
||||
|
||||
/*! \brief Output pin values */
|
||||
uint32_t values[RFSWITCH_MAX_PINS];
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constants to use in a mode table set be setRfSwitchTable. These
|
||||
* constants work for most radios, but some radios define their own
|
||||
* constants to be used instead.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
\enum OpMode_t
|
||||
\brief Constants to use in a mode table set be setRfSwitchTable. These
|
||||
constants work for most radios, but some radios define their own
|
||||
constants to be used instead.
|
||||
|
||||
See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
enum OpMode_t {
|
||||
/*! End of table marker, use \ref END_OF_MODE_TABLE constant
|
||||
* instead. Value is zero to ensure zero-initialized mode ends the
|
||||
* table */
|
||||
/*!
|
||||
\brief End of table marker, use \ref END_OF_MODE_TABLE constant instead.
|
||||
Value is zero to ensure zero-initialized mode ends the table.
|
||||
*/
|
||||
MODE_END_OF_TABLE = 0,
|
||||
/*! Idle mode */
|
||||
|
||||
/*! \brief Idle mode */
|
||||
MODE_IDLE,
|
||||
/*! Receive mode */
|
||||
|
||||
/*! \brief Receive mode */
|
||||
MODE_RX,
|
||||
/*! Transmission mode */
|
||||
|
||||
/*! \brief Transmission mode */
|
||||
MODE_TX,
|
||||
};
|
||||
|
||||
|
@ -111,62 +151,68 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief Overload for assignment operator.
|
||||
\param frame rvalue Module.
|
||||
\param mod rvalue Module.
|
||||
*/
|
||||
Module& operator=(const Module& mod);
|
||||
|
||||
// public member variables
|
||||
/*!
|
||||
\brief Hardware abstraction layer to be used.
|
||||
*/
|
||||
/*! \brief Hardware abstraction layer to be used. */
|
||||
RadioLibHal* hal = NULL;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI read command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPIreadCommand = 0b00000000;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI write command. Defaults to 0x80.
|
||||
*/
|
||||
uint8_t SPIwriteCommand = 0b10000000;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI no-operation command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPInopCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI status read command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPIstatusCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief SPI address width. Defaults to 8, currently only supports 8 and 16-bit addresses.
|
||||
*/
|
||||
uint8_t SPIaddrWidth = 8;
|
||||
|
||||
/*!
|
||||
\brief Whether the SPI interface is stream-type (e.g. SX126x) or register-type (e.g. SX127x).
|
||||
Defaults to register-type SPI interfaces.
|
||||
*/
|
||||
bool SPIstreamType = false;
|
||||
|
||||
/*!
|
||||
\brief The last recorded SPI stream error.
|
||||
*/
|
||||
int16_t SPIstreamError = RADIOLIB_ERR_UNKNOWN;
|
||||
|
||||
/*!
|
||||
\brief SPI status parsing callback typedef.
|
||||
*/
|
||||
/*! \brief Callback for parsing SPI status. */
|
||||
typedef int16_t (*SPIparseStatusCb_t)(uint8_t in);
|
||||
|
||||
/*! \brief Callback for validation SPI status. */
|
||||
typedef int16_t (*SPIcheckStatusCb_t)(Module* mod);
|
||||
|
||||
enum BitWidth_t {
|
||||
BITS_0 = 0,
|
||||
BITS_8 = 8,
|
||||
BITS_16 = 16,
|
||||
BITS_32 = 32,
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Callback to function that will parse the module-specific status codes to RadioLib status codes.
|
||||
Typically used for modules with SPI stream-type interface (e.g. SX126x/SX128x).
|
||||
\struct SPIConfig_t
|
||||
\brief SPI configuration structure.
|
||||
*/
|
||||
SPIparseStatusCb_t SPIparseStatusCb = nullptr;
|
||||
struct SPIConfig_t {
|
||||
/*! \brief Whether the SPI module is stream-type (SX126x/8x) or registrer access type (SX127x, CC1101 etc). */
|
||||
bool stream;
|
||||
|
||||
/*! \brief Last recorded SPI error - only updated for modules that return status during SPI transfers. */
|
||||
int16_t err;
|
||||
|
||||
/*! \brief SPI commands */
|
||||
uint16_t cmds[4];
|
||||
|
||||
/*! \brief Bit widths of SPI addresses, commands and status bytes */
|
||||
BitWidth_t widths[3];
|
||||
|
||||
/*! \brief Byte position of status command in SPI stream */
|
||||
uint8_t statusPos;
|
||||
|
||||
/*! \brief Callback for parsing SPI status. */
|
||||
SPIparseStatusCb_t parseStatusCb;
|
||||
|
||||
/*! \brief Callback for validation SPI status. */
|
||||
SPIcheckStatusCb_t checkStatusCb;
|
||||
|
||||
/*! \brief Timeout in ms when waiting for GPIO signals. */
|
||||
RadioLibTime_t timeout;
|
||||
};
|
||||
|
||||
/*! \brief SPI configuration structure. The default configuration corresponds to register-access modules, such as SX127x. */
|
||||
SPIConfig_t spiConfig = {
|
||||
.stream = false,
|
||||
.err = RADIOLIB_ERR_UNKNOWN,
|
||||
.cmds = { 0x00, 0x80, 0x00, 0x00 },
|
||||
.widths = { Module::BITS_8, Module::BITS_0, Module::BITS_8 },
|
||||
.statusPos = 0,
|
||||
.parseStatusCb = nullptr,
|
||||
.checkStatusCb = nullptr,
|
||||
.timeout = 1000,
|
||||
};
|
||||
|
||||
#if RADIOLIB_INTERRUPT_TIMING
|
||||
|
||||
|
@ -208,7 +254,7 @@ class Module {
|
|||
\param lsb Least significant bit of the register variable. Bits below this one will be masked out.
|
||||
\returns Masked register value or status code.
|
||||
*/
|
||||
int16_t SPIgetRegValue(uint16_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
int16_t SPIgetRegValue(uint32_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
|
||||
/*!
|
||||
\brief Overwrite-safe SPI write method with verification. This method is the preferred SPI write mechanism.
|
||||
|
@ -220,7 +266,7 @@ class Module {
|
|||
\param checkMask Mask of bits to check, only bits set to 1 will be verified.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
|
||||
/*!
|
||||
\brief SPI burst read method.
|
||||
|
@ -228,14 +274,14 @@ class Module {
|
|||
\param numBytes Number of bytes that will be read.
|
||||
\param inBytes Pointer to array that will hold the read data.
|
||||
*/
|
||||
void SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes);
|
||||
void SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes);
|
||||
|
||||
/*!
|
||||
\brief SPI basic read method. Use of this method is reserved for special cases, SPIgetRegValue should be used instead.
|
||||
\param reg Address of SPI register to read.
|
||||
\returns Value that was read from register.
|
||||
*/
|
||||
uint8_t SPIreadRegister(uint16_t reg);
|
||||
uint8_t SPIreadRegister(uint32_t reg);
|
||||
|
||||
/*!
|
||||
\brief SPI burst write method.
|
||||
|
@ -243,14 +289,14 @@ 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(uint16_t reg, uint8_t* data, size_t numBytes);
|
||||
void SPIwriteRegisterBurst(uint32_t reg, 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.
|
||||
\param reg Address of SPI register to write.
|
||||
\param data Value that will be written to the register.
|
||||
*/
|
||||
void SPIwriteRegister(uint16_t reg, uint8_t data);
|
||||
void SPIwriteRegister(uint32_t reg, uint8_t data);
|
||||
|
||||
/*!
|
||||
\brief SPI single transfer method.
|
||||
|
@ -260,7 +306,7 @@ class Module {
|
|||
\param dataIn Data that was transferred from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
*/
|
||||
void SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
|
||||
void SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
|
||||
|
||||
/*!
|
||||
\brief Method to check the result of last SPI stream transfer.
|
||||
|
@ -277,7 +323,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* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
int16_t SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a read transaction with SPI stream.
|
||||
|
@ -300,7 +346,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* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
int16_t SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a write transaction with SPI stream.
|
||||
|
@ -323,10 +369,9 @@ class Module {
|
|||
\param dataIn Data that was transferred from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
\param waitForGpio Whether to wait for some GPIO at the end of transfer (e.g. BUSY line on SX126x/SX128x).
|
||||
\param timeout GPIO wait period timeout in milliseconds.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout);
|
||||
int16_t SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio);
|
||||
|
||||
// pin number access methods
|
||||
|
||||
|
@ -438,7 +483,7 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief Find a mode in the RfSwitchTable.
|
||||
\param The mode to find.
|
||||
\param mode The mode to find.
|
||||
\returns A pointer to the RfSwitchMode_t struct in the table that
|
||||
matches the passed mode. Returns nullptr if no rfswitch pins are
|
||||
configured, or the passed mode is not listed in the table.
|
||||
|
@ -458,7 +503,7 @@ class Module {
|
|||
\param start Waiting start timestamp, in microseconds.
|
||||
\param len Waiting duration, in microseconds;
|
||||
*/
|
||||
void waitForMicroseconds(uint32_t start, uint32_t len);
|
||||
void waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len);
|
||||
|
||||
/*!
|
||||
\brief Function to reflect bits within a byte.
|
||||
|
@ -471,19 +516,21 @@ class Module {
|
|||
#if RADIOLIB_DEBUG
|
||||
/*!
|
||||
\brief Function to dump data as hex into the debug port.
|
||||
\param level RadioLib debug level, set to NULL to not print.
|
||||
\param data Data to dump.
|
||||
\param len Number of bytes to dump.
|
||||
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
|
||||
\param be Print multi-byte data as big endian. Defaults to false.
|
||||
*/
|
||||
static void hexdump(uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
|
||||
static void hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
|
||||
|
||||
/*!
|
||||
\brief Function to dump device registers as hex into the debug port.
|
||||
\param level RadioLib debug level, set to NULL to not print.
|
||||
\param start First address to dump.
|
||||
\param len Number of bytes to dump.
|
||||
*/
|
||||
void regdump(uint16_t start, size_t len);
|
||||
void regdump(const char* level, uint16_t start, size_t len);
|
||||
#endif
|
||||
|
||||
#if RADIOLIB_DEBUG and defined(RADIOLIB_BUILD_ARDUINO)
|
||||
|
@ -499,7 +546,7 @@ class Module {
|
|||
uint32_t gpioPin = RADIOLIB_NC;
|
||||
|
||||
// RF switch pins and table
|
||||
uint32_t rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
|
||||
uint32_t rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
|
||||
const RfSwitchMode_t *rfSwitchTable = nullptr;
|
||||
|
||||
#if RADIOLIB_INTERRUPT_TIMING
|
||||
|
|
|
@ -53,16 +53,7 @@
|
|||
|
||||
// print debug info
|
||||
#if RADIOLIB_DEBUG
|
||||
#define RADIOLIB_VALUE_TO_STRING(x) #x
|
||||
#define RADIOLIB_VALUE(x) RADIOLIB_VALUE_TO_STRING(x)
|
||||
#pragma message("\nRadioLib Debug 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__) \
|
||||
)
|
||||
#pragma message(RADIOLIB_INFO)
|
||||
#endif
|
||||
|
||||
// check unknown/unsupported platform
|
||||
|
@ -77,6 +68,9 @@
|
|||
|
||||
#include "modules/CC1101/CC1101.h"
|
||||
#include "modules/LLCC68/LLCC68.h"
|
||||
#include "modules/LR11x0/LR1110.h"
|
||||
#include "modules/LR11x0/LR1120.h"
|
||||
#include "modules/LR11x0/LR1121.h"
|
||||
#include "modules/nRF24/nRF24.h"
|
||||
#include "modules/RF69/RF69.h"
|
||||
#include "modules/RFM2x/RFM22.h"
|
||||
|
|
|
@ -499,7 +499,7 @@
|
|||
#define RADIOLIB_ERR_INVALID_REVISION (-1103)
|
||||
|
||||
/*!
|
||||
\brief Invalid LoRaWAN uplink port requested by user.
|
||||
\brief Invalid LoRaWAN uplink port requested by user, or downlink received at invalid port.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_PORT (-1104)
|
||||
|
||||
|
@ -509,9 +509,9 @@
|
|||
#define RADIOLIB_ERR_NO_RX_WINDOW (-1105)
|
||||
|
||||
/*!
|
||||
\brief No valid channel for the currently active LoRaWAN band was found.
|
||||
\brief There are no channels available for the requested datarate.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_CHANNEL (-1106)
|
||||
#define RADIOLIB_ERR_NO_CHANNEL_AVAILABLE (-1106)
|
||||
|
||||
/*!
|
||||
\brief Invalid LoRaWAN MAC command ID.
|
||||
|
@ -528,30 +528,87 @@
|
|||
*/
|
||||
#define RADIOLIB_ERR_COMMAND_QUEUE_FULL (-1109)
|
||||
|
||||
/*!
|
||||
\brief Unable to pop existing MAC command because the queue is empty.
|
||||
*/
|
||||
#define RADIOLIB_ERR_COMMAND_QUEUE_EMPTY (-1110)
|
||||
|
||||
/*!
|
||||
\brief Unable to delete MAC command because it was not found in the queue.
|
||||
*/
|
||||
#define RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND (-1111)
|
||||
#define RADIOLIB_ERR_COMMAND_QUEUE_ITEM_NOT_FOUND (-1110)
|
||||
|
||||
/*!
|
||||
\brief Unable to join network because JoinNonce is not higher than saved value.
|
||||
*/
|
||||
#define RADIOLIB_ERR_JOIN_NONCE_INVALID (-1112)
|
||||
#define RADIOLIB_ERR_JOIN_NONCE_INVALID (-1111)
|
||||
|
||||
/*!
|
||||
\brief Received downlink Network frame counter is invalid (lower than last heard value).
|
||||
*/
|
||||
#define RADIOLIB_ERR_N_FCNT_DOWN_INVALID (-1113)
|
||||
#define RADIOLIB_ERR_N_FCNT_DOWN_INVALID (-1112)
|
||||
|
||||
/*!
|
||||
\brief Received downlink Application frame counter is invalid (lower than last heard value).
|
||||
*/
|
||||
#define RADIOLIB_ERR_A_FCNT_DOWN_INVALID (-1114)
|
||||
#define RADIOLIB_ERR_A_FCNT_DOWN_INVALID (-1113)
|
||||
|
||||
/*!
|
||||
\brief Uplink payload length at this datarate exceeds the active dwell time limitations.
|
||||
*/
|
||||
#define RADIOLIB_ERR_DWELL_TIME_EXCEEDED (-1114)
|
||||
|
||||
/*!
|
||||
\brief The buffer integrity check did not match the supplied checksum value.
|
||||
*/
|
||||
#define RADIOLIB_ERR_CHECKSUM_MISMATCH (-1115)
|
||||
|
||||
/*!
|
||||
\brief No downlink was received - most likely none was sent from the server.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_NO_DOWNLINK (-1116)
|
||||
|
||||
/*!
|
||||
\brief The LoRaWAN session was successfully re-activated.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_SESSION_RESTORED (-1117)
|
||||
|
||||
/*!
|
||||
\brief A new LoRaWAN session is started.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_NEW_SESSION (-1118)
|
||||
|
||||
/*!
|
||||
\brief The supplied Nonces buffer is discarded as its activation information is invalid.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_NONCES_DISCARDED (-1119)
|
||||
|
||||
/*!
|
||||
\brief The supplied Session buffer is discarded as it doesn't match the Nonces.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_SESSION_DISCARDED (-1120)
|
||||
|
||||
/*!
|
||||
\brief The requested command is unavailable under the current LoRaWAN mode.
|
||||
*/
|
||||
#define RADIOLIB_LORAWAN_INVALID_MODE (-1121)
|
||||
|
||||
// LR11x0-specific status codes
|
||||
|
||||
/*!
|
||||
\brief The selected 802.11 WiFi type is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_WIFI_TYPE (-1200)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup typedefs Type aliases used by RadioLib.
|
||||
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Type used for durations in RadioLib
|
||||
*/
|
||||
typedef unsigned long RadioLibTime_t;
|
||||
|
||||
/*!
|
||||
\}
|
||||
|
|
|
@ -8,8 +8,8 @@ CC1101::CC1101(Module* module) : PhysicalLayer(RADIOLIB_CC1101_FREQUENCY_STEP_SI
|
|||
|
||||
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
|
||||
// set module properties
|
||||
this->mod->SPIreadCommand = RADIOLIB_CC1101_CMD_READ;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_CC1101_CMD_WRITE;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
|
||||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
|
||||
|
@ -21,18 +21,18 @@ int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pw
|
|||
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
|
||||
flagFound = true;
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
|
||||
this->mod->hal->delay(10);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!flagFound) {
|
||||
RADIOLIB_DEBUG_PRINTLN("No CC1101 found!");
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("No CC1101 found!");
|
||||
this->mod->term();
|
||||
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
|
||||
} else {
|
||||
RADIOLIB_DEBUG_PRINTLN("M\tCC1101");
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tCC1101");
|
||||
}
|
||||
|
||||
// configure settings not accessible by API
|
||||
|
@ -100,29 +100,29 @@ void CC1101::reset() {
|
|||
|
||||
int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// calculate timeout (5ms + 500 % of expected time-on-air)
|
||||
uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (this->bitRate * 1000.0)) * 5000000.0);
|
||||
RadioLibTime_t timeout = 5 + (RadioLibTime_t)((((float)(len * 8)) / this->bitRate) * 5);
|
||||
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission start or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for transmission end or timeout
|
||||
start = this->mod->hal->micros();
|
||||
start = this->mod->hal->millis();
|
||||
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
@ -133,18 +133,18 @@ int16_t CC1101::transmit(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)
|
||||
uint32_t timeout = 500000 + (1.0/(this->bitRate*1000.0))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
RadioLibTime_t timeout = 500 + (1.0/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet start or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
@ -152,11 +152,11 @@ int16_t CC1101::receive(uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
// wait for packet end or timeout
|
||||
start = this->mod->hal->micros();
|
||||
start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
@ -172,7 +172,7 @@ int16_t CC1101::standby() {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
||||
// wait until idle is reached
|
||||
uint32_t start = this->mod->hal->millis();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(SPIgetRegValue(RADIOLIB_CC1101_REG_MARCSTATE, 4, 0) != RADIOLIB_CC1101_MARC_STATE_IDLE) {
|
||||
mod->hal->yield();
|
||||
if(this->mod->hal->millis() - start > 100) {
|
||||
|
@ -361,7 +361,7 @@ int16_t CC1101::startReceive() {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t CC1101::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)timeout;
|
||||
(void)irqFlags;
|
||||
(void)irqMask;
|
||||
|
@ -424,11 +424,13 @@ int16_t CC1101::readData(uint8_t* data, size_t len) {
|
|||
|
||||
int16_t CC1101::setFrequency(float freq) {
|
||||
// check allowed frequency range
|
||||
if(!(((freq > 300.0) && (freq < 348.0)) ||
|
||||
((freq > 387.0) && (freq < 464.0)) ||
|
||||
((freq > 779.0) && (freq < 928.0)))) {
|
||||
#if RADIOLIB_CHECK_PARAMS
|
||||
if(!(((freq >= 300.0) && (freq <= 348.0)) ||
|
||||
((freq >= 387.0) && (freq <= 464.0)) ||
|
||||
((freq >= 779.0) && (freq <= 928.0)))) {
|
||||
return(RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
#endif
|
||||
|
||||
// set mode to standby
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
@ -489,6 +491,24 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
|
|||
return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t CC1101::setFrequencyDeviation(float freqDev) {
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
|
@ -542,6 +562,62 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
|
|||
}
|
||||
|
||||
int16_t CC1101::setOutputPower(int8_t pwr) {
|
||||
// check if power value is configurable
|
||||
uint8_t powerRaw = 0;
|
||||
int16_t state = checkOutputPower(pwr, NULL, &powerRaw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// store the value
|
||||
this->power = pwr;
|
||||
|
||||
if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// 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};
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
} else {
|
||||
// Freq modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting.
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, NULL));
|
||||
}
|
||||
|
||||
int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
|
||||
const int8_t allowedPwrs[8] = { -30, -20, -15, -10, 0, 5, 7, 10 };
|
||||
|
||||
if(clipped) {
|
||||
if(power <= -30) {
|
||||
*clipped = -30;
|
||||
} else if(power >= 10) {
|
||||
*clipped = 10;
|
||||
} else {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(allowedPwrs[i] > power) {
|
||||
break;
|
||||
}
|
||||
*clipped = allowedPwrs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if just a check occurs (and not requesting the raw power value), return now
|
||||
if(!raw) {
|
||||
for(size_t i = 0; i < sizeof(allowedPwrs); i++) {
|
||||
if(allowedPwrs[i] == power) {
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
}
|
||||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// round to the known frequency settings
|
||||
uint8_t f;
|
||||
if(this->frequency < 374.0) {
|
||||
|
@ -568,53 +644,14 @@ int16_t CC1101::setOutputPower(int8_t pwr) {
|
|||
{0xCB, 0xC8, 0xCB, 0xC7},
|
||||
{0xC2, 0xC0, 0xC2, 0xC0}};
|
||||
|
||||
uint8_t powerRaw;
|
||||
switch(pwr) {
|
||||
case -30:
|
||||
powerRaw = paTable[0][f];
|
||||
break;
|
||||
case -20:
|
||||
powerRaw = paTable[1][f];
|
||||
break;
|
||||
case -15:
|
||||
powerRaw = paTable[2][f];
|
||||
break;
|
||||
case -10:
|
||||
powerRaw = paTable[3][f];
|
||||
break;
|
||||
case 0:
|
||||
powerRaw = paTable[4][f];
|
||||
break;
|
||||
case 5:
|
||||
powerRaw = paTable[5][f];
|
||||
break;
|
||||
case 7:
|
||||
powerRaw = paTable[6][f];
|
||||
break;
|
||||
case 10:
|
||||
powerRaw = paTable[7][f];
|
||||
break;
|
||||
default:
|
||||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// store the value
|
||||
this->power = pwr;
|
||||
|
||||
if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// 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};
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
} else {
|
||||
// Freq modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting.
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
|
||||
for(uint8_t i = 0; i < sizeof(allowedPwrs); i++) {
|
||||
if(power == allowedPwrs[i]) {
|
||||
*raw = paTable[i][f];
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
|
@ -740,7 +777,7 @@ int16_t CC1101::setOOK(bool enableOOK) {
|
|||
float CC1101::getRSSI() {
|
||||
float rssi;
|
||||
|
||||
if (this->directModeEnabled) {
|
||||
if(!this->directModeEnabled) {
|
||||
if(this->rawRSSI >= 128) {
|
||||
rssi = (((float)this->rawRSSI - 256.0)/2.0) - 74.0;
|
||||
} else {
|
||||
|
@ -748,12 +785,9 @@ float CC1101::getRSSI() {
|
|||
}
|
||||
} else {
|
||||
uint8_t rawRssi = SPIreadRegister(RADIOLIB_CC1101_REG_RSSI);
|
||||
if (rawRssi >= 128)
|
||||
{
|
||||
if(rawRssi >= 128) {
|
||||
rssi = ((rawRssi - 256) / 2) - 74;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rssi = (rawRssi / 2) - 74;
|
||||
}
|
||||
}
|
||||
|
@ -826,7 +860,7 @@ int16_t CC1101::setCrcFiltering(bool enable) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPromiscuousMode(bool enable) {
|
||||
int16_t CC1101::setPromiscuousMode(bool enable, bool requireCarrierSense) {
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
|
||||
if(this->promiscuous == enable) {
|
||||
|
@ -834,9 +868,14 @@ int16_t CC1101::setPromiscuousMode(bool enable) {
|
|||
}
|
||||
|
||||
if(enable) {
|
||||
// Lets set PQT to 0 with Promiscuous too
|
||||
// We have to set the length to set PQT, but it should get disabled with disableSyncWordFiltering()
|
||||
state = setPreambleLength(16, 0);
|
||||
RADIOLIB_ASSERT(state);
|
||||
// disable sync word filtering and insertion
|
||||
// this also disables preamble
|
||||
state = disableSyncWordFiltering();
|
||||
// Can enable Sync Mode with carriersense when promiscuous is enabled. Default is false: Sync Mode None
|
||||
state = disableSyncWordFiltering(requireCarrierSense);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// disable CRC filtering
|
||||
|
@ -916,7 +955,6 @@ void CC1101::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS],
|
|||
uint8_t CC1101::randomByte() {
|
||||
// set mode to Rx
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
||||
RADIOLIB_DEBUG_PRINTLN("CC1101::randomByte");
|
||||
|
||||
// wait a bit for the RSSI reading to stabilise
|
||||
this->mod->hal->delay(10);
|
||||
|
@ -985,14 +1023,14 @@ int16_t CC1101::directMode(bool sync) {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
||||
int16_t state = 0;
|
||||
this->directModeEnabled = sync;
|
||||
this->directModeEnabled = true;
|
||||
if(sync) {
|
||||
// set GDO0 and GDO2 mapping
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SERIAL_CLOCK , 5, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SERIAL_DATA_SYNC , 5, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SERIAL_CLOCK , 5, 0);
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG2, RADIOLIB_CC1101_GDOX_SERIAL_DATA_SYNC , 5, 0);
|
||||
|
||||
// set continuous mode
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_PKT_FORMAT_SYNCHRONOUS, 5, 4);
|
||||
// set continuous mode
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_PKTCTRL0, RADIOLIB_CC1101_PKT_FORMAT_SYNCHRONOUS, 5, 4);
|
||||
} else {
|
||||
// set GDO0 mapping
|
||||
state |= SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0, RADIOLIB_CC1101_GDOX_SERIAL_DATA_ASYNC , 5, 0);
|
||||
|
@ -1012,23 +1050,23 @@ void CC1101::getExpMant(float target, uint16_t mantOffset, uint8_t divExp, uint8
|
|||
// iterate over possible exponent values
|
||||
for(int8_t e = expMax; e >= 0; e--) {
|
||||
// get table column start value (exp = e, mant = 0);
|
||||
float intervalStart = ((uint32_t)1 << e) * origin;
|
||||
float intervalStart = ((uint32_t)1 << e) * origin;
|
||||
|
||||
// check if target value is in this column
|
||||
if(target >= intervalStart) {
|
||||
if(target >= intervalStart) {
|
||||
// save exponent value
|
||||
exp = e;
|
||||
|
||||
// calculate size of step between table rows
|
||||
float stepSize = intervalStart/(float)mantOffset;
|
||||
float stepSize = intervalStart/(float)mantOffset;
|
||||
|
||||
// get target point position (exp = e, mant = m)
|
||||
mant = ((target - intervalStart) / stepSize);
|
||||
mant = ((target - intervalStart) / stepSize);
|
||||
|
||||
// we only need the first match, terminate
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::setPacketMode(uint8_t mode, uint16_t len) {
|
||||
|
@ -1045,6 +1083,9 @@ int16_t CC1101::setPacketMode(uint8_t mode, uint16_t len) {
|
|||
state = SPIsetRegValue(RADIOLIB_CC1101_REG_PKTLEN, len);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// no longer in a direct mode
|
||||
this->directModeEnabled = false;
|
||||
|
||||
// update the cached values
|
||||
this->packetLength = len;
|
||||
this->packetLengthConfig = mode;
|
||||
|
@ -1113,7 +1154,7 @@ void CC1101::SPIsendCommand(uint8_t cmd) {
|
|||
// stop transfer
|
||||
this->mod->hal->spiEndTransaction();
|
||||
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
|
||||
RADIOLIB_VERBOSE_PRINTLN("CMD\tW\t%02X\t%02X", cmd, status);
|
||||
RADIOLIB_DEBUG_SPI_PRINTLN("CMD\tW\t%02X\t%02X", cmd, status);
|
||||
(void)status;
|
||||
}
|
||||
|
||||
|
|
|
@ -537,8 +537,9 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
\param module Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
CC1101(Module* module);
|
||||
|
||||
// basic methods
|
||||
|
@ -599,14 +600,14 @@ class CC1101: public PhysicalLayer {
|
|||
int16_t standby(uint8_t mode) override;
|
||||
|
||||
/*!
|
||||
\brief Starts direct mode transmission.
|
||||
\brief Starts synchronous direct mode transmission.
|
||||
\param frf Raw RF frequency value. Defaults to 0, required for quick frequency shifts in RTTY.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t transmitDirect(uint32_t frf = 0) override;
|
||||
|
||||
/*!
|
||||
\brief Starts direct mode reception.
|
||||
\brief Starts synchronous direct mode reception.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t receiveDirect() override;
|
||||
|
@ -660,23 +661,23 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
|
@ -698,7 +699,7 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Interrupt-driven receive method. GDO0 will be activated when full packet is received.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method, implemented for compatibility with PhysicalLayer.
|
||||
|
@ -708,7 +709,7 @@ class CC1101: public PhysicalLayer {
|
|||
\param len Ignored.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len);
|
||||
int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method. When the packet length is not known in advance,
|
||||
|
@ -728,14 +729,14 @@ class CC1101: public PhysicalLayer {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets bit rate. Allowed values range from 0.025 to 600.0 kbps.
|
||||
\param br Bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
/*!
|
||||
\brief Sets receiver bandwidth. Allowed values are 58, 68, 81, 102, 116, 135, 162,
|
||||
|
@ -745,6 +746,14 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setRxBandwidth(float rxBw);
|
||||
|
||||
/*!
|
||||
\brief calculates and sets Rx bandwidth based on the freq, baud and freq uncertainty.
|
||||
Reimplement of atlas0fd00m's (RfCat) CalculatePktChanBw function.
|
||||
Modified for worse ppm with the CC1101, and adjusted for the supportted CC1101 bw.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t autoSetRxBandwidth();
|
||||
|
||||
/*!
|
||||
\brief Sets frequency deviation. Allowed values range from 1.587 to 380.8 kHz.
|
||||
\param freqDev Frequency deviation to be set in kHz.
|
||||
|
@ -764,7 +773,25 @@ class CC1101: public PhysicalLayer {
|
|||
\param pwr Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t pwr);
|
||||
int16_t setOutputPower(int8_t pwr) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param raw Raw internal value.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw);
|
||||
|
||||
/*!
|
||||
\brief Sets 16-bit sync word as a two byte value.
|
||||
|
@ -789,6 +816,7 @@ class CC1101: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Sets preamble length.
|
||||
\param preambleLength Preamble length to be set (in bits), allowed values: 16, 24, 32, 48, 64, 96, 128 and 192.
|
||||
\param qualityThreshold Preamble quality threshold (PQT) to set.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPreambleLength(uint8_t preambleLength, uint8_t qualityThreshold);
|
||||
|
@ -817,68 +845,69 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet.
|
||||
In asynchronous direct mode, returns the current RSSI level.
|
||||
In direct or asynchronous direct mode, returns the current RSSI level.
|
||||
\returns RSSI in dBm.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Gets LQI (Link Quality Indicator) of the last received packet.
|
||||
\returns Last packet LQI (lower is better).
|
||||
*/
|
||||
uint8_t getLQI() const;
|
||||
uint8_t getLQI() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
\returns Length of last received packet in bytes.
|
||||
*/
|
||||
size_t getPacketLength(bool update = true) override;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode.
|
||||
\param len Packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode.
|
||||
\param len Maximum packet length.
|
||||
\param maxLen Maximum packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Enable sync word filtering and generation.
|
||||
\param numBits Sync word length in bits.
|
||||
\param maxErrBits Maximum number of allowed error bits in sync word.
|
||||
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
\param requireCarrierSense Require carrier sense above threshold.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering(bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
\param enable Set or unset CRC generation and filtering.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool enable = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
|
||||
\param enable Set or unset promiscuous mode.
|
||||
\param requireCarrierSense Set carriersense required above threshold, defaults to false.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPromiscuousMode(bool enable = true);
|
||||
int16_t setPromiscuousMode(bool enable = true, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Get whether the modem is in promiscuous mode: no packet filtering
|
||||
(e.g., no preamble, sync word, address, CRC).
|
||||
\returns Whether the modem is in promiscuous mode.
|
||||
|
@ -908,16 +937,16 @@ class CC1101: public PhysicalLayer {
|
|||
void setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return CC1101_VERSION_LEGACY (0x04) or
|
||||
CC1101_VERSION_CURRENT (0x14) if CC1101 is connected and working.
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
\brief Read version SPI register. Should return CC1101_VERSION_LEGACY (0x04) or
|
||||
CC1101_VERSION_CURRENT (0x14) if CC1101 is connected and working.
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
|
||||
|
@ -925,13 +954,13 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Set interrupt service routine function to call when data bit is receveid in direct mode.
|
||||
\param func Pointer to interrupt service routine.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Function to read and process data bit in direct reception mode.
|
||||
\param pin Pin on which to read.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
@ -940,12 +969,12 @@ class CC1101: public PhysicalLayer {
|
|||
\param value The value that indicates which function to place on that pin. See chip datasheet for details.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value);
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
// SPI read overrides to set bit for burst write and status registers access
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
|
@ -974,7 +1003,7 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
bool promiscuous = false;
|
||||
bool crcOn = true;
|
||||
bool directModeEnabled = true;
|
||||
bool directModeEnabled = false;
|
||||
|
||||
int8_t power = RADIOLIB_CC1101_DEFAULT_POWER;
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) {
|
|||
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);
|
||||
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);
|
||||
|
@ -108,6 +109,7 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) {
|
|||
default:
|
||||
return(RADIOLIB_ERR_INVALID_BANDWIDTH);
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class LLCC68: public SX1262 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LLCC68(Module* mod);
|
||||
LLCC68(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
#include "LR1110.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1110::LR1110(Module* mod) : LR11x0(mod) {
|
||||
chipType = RADIOLIB_LR11X0_DEVICE_LR1110;
|
||||
}
|
||||
|
||||
int16_t LR1110::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, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::setFrequency(float freq) {
|
||||
return(this->setFrequency(freq, true));
|
||||
}
|
||||
|
||||
int16_t LR1110::setFrequency(float freq, bool calibrate, float band) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = LR11x0::calibImage(freq - band, freq + band);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
#if !defined(_RADIOLIB_LR1110_H)
|
||||
#define _RADIOLIB_LR1110_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
|
||||
/*!
|
||||
\class LR1110
|
||||
\brief Derived class for %LR1110 modules.
|
||||
*/
|
||||
class LR1110: public LR11x0 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1110(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
\param sf LoRa spreading factor. Defaults to 9.
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
\param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE (0x12).
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\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_LR11X0_LORA_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\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. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginGFSK(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);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LR-FHSS modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
|
||||
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_LR11X0_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_LR11X0_LR_FHSS_CR_2_3, int8_t power = 10, float tcxoVoltage = 1.6);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,59 @@
|
|||
#include "LR1120.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1120::LR1120(Module* mod) : LR11x0(mod) {
|
||||
chipType = RADIOLIB_LR11X0_DEVICE_LR1120;
|
||||
}
|
||||
|
||||
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, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::setFrequency(float freq) {
|
||||
return(this->setFrequency(freq, true));
|
||||
}
|
||||
|
||||
int16_t LR1120::setFrequency(float freq, bool calibrate, float band) {
|
||||
if(!(((freq >= 150.0) && (freq <= 960.0)) ||
|
||||
((freq >= 1900.0) && (freq <= 2200.0)) ||
|
||||
((freq >= 2400.0) && (freq <= 2500.0)))) {
|
||||
return(RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = LR11x0::calibImage(freq - band, freq + band);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,99 @@
|
|||
#if !defined(_RADIOLIB_LR1120_H)
|
||||
#define _RADIOLIB_LR1120_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
|
||||
/*!
|
||||
\class LR1120
|
||||
\brief Derived class for %LR1120 modules.
|
||||
*/
|
||||
class LR1120: public LR11x0 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1120(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
\param sf LoRa spreading factor. Defaults to 9.
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
\param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE (0x12).
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\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_LR11X0_LORA_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\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. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginGFSK(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);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LR-FHSS modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
|
||||
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
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 LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_LR11X0_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_LR11X0_LR_FHSS_CR_2_3, int8_t power = 10, float tcxoVoltage = 1.6);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz,
|
||||
1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz,
|
||||
1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,8 @@
|
|||
#include "LR1121.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1121::LR1121(Module* mod) : LR1120(mod) {
|
||||
chipType = RADIOLIB_LR11X0_DEVICE_LR1121;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
#if !defined(_RADIOLIB_LR1121_H)
|
||||
#define _RADIOLIB_LR1121_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
#include "LR1120.h"
|
||||
|
||||
/*!
|
||||
\class LR1121
|
||||
\brief Derived class for %LR1121 modules.
|
||||
*/
|
||||
class LR1121: public LR1120 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1121(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// TODO this is where overrides to disable GNSS+WiFi scanning methods on LR1121
|
||||
// will be put once those are implemented
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,38 @@
|
|||
#if !defined(_RADIOLIB_LR11X0_FIRMWARE_H)
|
||||
#define _RADIOLIB_LR11X0_FIRMWARE_H
|
||||
|
||||
#if defined(RADIOLIB_LR1110_FIRMWARE_IN_RAM)
|
||||
#define RADIOLIB_LR1110_FIRMWARE_ATTR
|
||||
#else
|
||||
#define RADIOLIB_LR1110_FIRMWARE_ATTR RADIOLIB_NONVOLATILE
|
||||
#endif
|
||||
|
||||
#define RADIOLIB_LR11X0_FIRMWARE_IMAGE_SIZE LR11XX_FIRMWARE_IMAGE_SIZE
|
||||
|
||||
#if defined(RADIOLIB_LR1110_FIRMWARE_0303)
|
||||
#include "firmware/lr1110_transceiver_0303.h"
|
||||
#elif defined(RADIOLIB_LR1110_FIRMWARE_0304)
|
||||
#include "firmware/lr1110_transceiver_0304.h"
|
||||
#elif defined(RADIOLIB_LR1110_FIRMWARE_0305)
|
||||
#include "firmware/lr1110_transceiver_0305.h"
|
||||
#elif defined(RADIOLIB_LR1110_FIRMWARE_0306)
|
||||
#include "firmware/lr1110_transceiver_0306.h"
|
||||
#elif defined(RADIOLIB_LR1110_FIRMWARE_0307)
|
||||
#include "firmware/lr1110_transceiver_0307.h"
|
||||
#elif defined(RADIOLIB_LR1110_FIRMWARE_0401)
|
||||
#include "firmware/lr1110_transceiver_0401.h"
|
||||
#elif defined(RADIOLIB_LR1120_FIRMWARE_0101)
|
||||
#include "firmware/lr1120_transceiver_0101.h"
|
||||
#elif defined(RADIOLIB_LR1120_FIRMWARE_0102)
|
||||
#include "firmware/lr1120_transceiver_0102.h"
|
||||
#elif defined(RADIOLIB_LR1120_FIRMWARE_0201)
|
||||
#include "firmware/lr1120_transceiver_0201.h"
|
||||
#elif defined(RADIOLIB_LR1121_FIRMWARE_0102)
|
||||
#include "firmware/lr1121_transceiver_0102.h"
|
||||
#elif defined(RADIOLIB_LR1121_FIRMWARE_0103)
|
||||
#include "firmware/lr1121_transceiver_0103.h"
|
||||
#else
|
||||
#error "No LR11x0 firmware image selected!"
|
||||
#endif
|
||||
|
||||
#endif
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue