Update RadioLib to master branch

This commit is contained in:
lewisxhe 2024-06-21 17:26:31 +08:00
commit e41f89b2de
83 changed files with 77813 additions and 2363 deletions

3
lib/RadioLib/.gitattributes vendored Normal file
View file

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

View file

@ -1,30 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**IMPORTANT: Check the wiki**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
**Describe the bug**
A clear and concise description of what the bug is. When applicable, please include [debug mode output](https://github.com/jgromes/RadioLib/wiki/Debug-mode) **using the appropriate debug mode**.
**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)).
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional info (please complete):**
- MCU: [e.g. Arduino Uno, ESP8266 etc.]
- Link to Arduino core: [e.g. https://github.com/stm32duino/Arduino_Core_STM32 when using official STM32 core. See readme for links to all supported cores]
- Wireless module type [e.g. CC1101, SX1268, etc.]
- Arduino IDE version [e.g. 1.8.5]
- Library version [e.g. 3.0.0]

View file

@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: RadioLib Discussions
url: https://github.com/jgromes/RadioLib/discussions
about: Please ask generic questions here.

View file

@ -1,23 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**IMPORTANT: Check the wiki**
Before submitting new issue, please check the [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and the [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
**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 [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -1,34 +0,0 @@
---
name: Module not working
about: Template to use when your module isn't working
title: ''
labels: ''
assignees: ''
---
**IMPORTANT: Before submitting an issue, please check the following:**
1. **Read [CONTRIBUTING.md](https://github.com/jgromes/RadioLib/blob/master/CONTRIBUTING.md)!** Issues that do not follow this document will be closed/locked/deleted/ignored.
2. RadioLib has a [Troubleshooting Guide](https://github.com/jgromes/RadioLib/wiki/Troubleshooting-Guide) Wiki page and an extensive [API documentation](https://jgromes.github.io/RadioLib/). You might find a solution to your issue there.
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).
**Sketch that is causing the module fail**
```c++
paste the sketch here, even if it is an unmodified example code
```
**Hardware setup**
Wiring diagram, schematic, pictures etc.
**Debug mode output**
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.]
- Link to Arduino core: [e.g. https://github.com/stm32duino/Arduino_Core_STM32 when using official STM32 core. See readme for links to all supported cores]
- Wireless module type [e.g. CC1101, SX1268, etc.]
- Arduino IDE version [e.g. 1.8.5]
- Library version [e.g. 3.0.0]

View file

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

View file

@ -1,60 +0,0 @@
name: "CodeQL"
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
security-events: write
strategy:
fail-fast: false
matrix:
language: ['cpp']
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
- name: Install arduino-cli
run:
|
mkdir -p ~/.local/bin
echo "~/.local/bin" >> $GITHUB_PATH
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
- name: Install platform
run:
|
arduino-cli core update-index
arduino-cli core install arduino:avr
- name: Static link
run:
|
# static link fix from https://github.com/github/securitylab/discussions/171
for i in ~/.arduino*/packages/arduino/tools/avr-gcc/*/bin/*; do
mv "$i" "$i.real";
printf '#!/bin/bash\nexec "'"$i"'.real" ${1+"$@"}\n' > "$i";
chmod +x "$i";
done
- name: Build example
run:
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@v3

View file

@ -1,27 +0,0 @@
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:
cppcheck src --enable=all --force --inline-suppr --quiet --suppress=ConfigurationNotChecked --suppress=unusedFunction

View file

@ -1,26 +0,0 @@
name: Doxygen
on:
push:
branches: [ master ]
workflow_dispatch:
jobs:
doxygen:
runs-on: ubuntu-latest
steps:
- name: Install Doxygen
run: |
sudo apt-get update
sudo apt-get install -y doxygen
- uses: actions/checkout@v4
- name: Generate docs
run: doxygen Doxyfile
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: docs/html

View file

@ -1,296 +0,0 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
inputs:
id:
description: The ID of the platform on which the build is run
required: true
default: arduino:avr:uno
type: choice
options:
- all
- none
- arduino:avr:uno
- arduino:avr:mega
- arduino:mbed:nano33ble
- arduino:mbed:envie_m4
- arduino:megaavr:uno2018
- arduino:sam:arduino_due_x
- arduino:samd:arduino_zero_native
- adafruit:samd:adafruit_feather_m0
- adafruit:nrf52:feather52832
- esp32:esp32:esp32
- esp8266:esp8266:generic
- Intel:arc32:arduino_101
- SparkFun:apollo3:sfe_artemis
- STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
- stm32duino:STM32F1:mapleMini
- MegaCoreX:megaavr:4809
- arduino:mbed_rp2040:pico
- rp2040:rp2040:rpipico
- CubeCell:CubeCell:CubeCell-Board
- MegaCore:avr:1281
- teensy:avr:teensy41
- arduino:renesas_uno:minima
jobs:
build:
strategy:
matrix:
# 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
- id: arduino:avr:mega
run: echo "options=':cpu=atmega2560'" >> $GITHUB_OUTPUT
- id: arduino:mbed:nano33ble
- id: arduino:mbed:envie_m4
- id: arduino:megaavr:uno2018
run: |
echo "options=':mode=on'" >> $GITHUB_OUTPUT
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
- id: arduino:sam:arduino_due_x
- id: arduino:samd:arduino_zero_native
- 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
- id: adafruit:nrf52:feather52832
run: |
sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-setuptools
pip3 install wheel
pip3 install --user adafruit-nrfutil
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
- id: esp32:esp32:esp32
run: |
python -m pip install pyserial
echo "index-url=--additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" >> $GITHUB_OUTPUT
- id: esp8266:esp8266:generic
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: 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
- id: STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
run: |
# Do *not* skip STM32WL examples
echo "skip-pattern=''" >> $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 "index-url=--additional-urls http://dan.drown.org/stm32duino/package_STM32duino_index.json" >> $GITHUB_OUTPUT
- id: MegaCoreX:megaavr:4809
run: |
echo "index-url=--additional-urls https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json" >> $GITHUB_OUTPUT
- id: arduino:mbed_rp2040:pico
- 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
- id: MegaCore:avr:1281
run: echo "index-url=--additional-urls https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json" >> $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)" >> $GITHUB_OUTPUT
runs-on: ubuntu-latest
name: ${{ matrix.id }}
env:
run-build: ${{ (inputs.id != 'none' && matrix.id == 'arduino:avr:uno') || contains(github.event.head_commit.message, 'CI_BUILD_ALL') || contains(github.event.head_commit.message, 'Bump version to') || contains(github.event.head_commit.message, format('{0}', matrix.id)) || inputs.id == 'all' || inputs.id == matrix.id }}
steps:
- name: Install arduino-cli
if: ${{ env.run-build == 'true' }}
run:
|
mkdir -p ~/.local/bin
echo "~/.local/bin" >> $GITHUB_PATH
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
- name: Get platform name
if: ${{ env.run-build == 'true' }}
uses: jungwinter/split@v1
id: split
with:
msg: ${{ matrix.id }}
seperator: ':'
- name: Prepare platform-specific settings
if: ${{ env.run-build == 'true' }}
id: prep
run:
|
# common settings - no extra options, skip STM32WL examples, all warnings
echo "options=''" >> $GITHUB_OUTPUT
echo "skip-pattern=STM32WL" >> $GITHUB_OUTPUT
echo "warnings=all" >> $GITHUB_OUTPUT
# run platform-dependent scripts defined in matrix
${{ matrix.run }}
- name: Install platform
if: ${{ env.run-build == 'true' }}
run:
|
arduino-cli core update-index ${{ format('{0}', steps.prep.outputs.index-url) }}
arduino-cli core install ${{ format('{0}:{1} {2}', steps.split.outputs._0, steps.split.outputs._1, steps.prep.outputs.index-url) }}
- name: Checkout repository
if: ${{ env.run-build == 'true' }}
uses: actions/checkout@v4
- name: Build examples
if: ${{ env.run-build == 'true' }}
run:
|
for example in $(find $PWD/examples -name '*.ino' | sort); do
# check whether to skip this sketch
if [ ! -z '${{ steps.prep.outputs.skip-pattern }}' ] && [[ ${example} =~ ${{ steps.prep.outputs.skip-pattern }} ]]; then
# skip sketch
echo -e "\n\033[1;33mSkipped ${example##*/} (matched with ${{ steps.prep.outputs.skip-pattern }})\033[0m";
else
# apply special flags for LoRaWAN
if [[ ${example} =~ "LoRaWAN" ]]; then
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
fi
# build sketch
echo -e "\n\033[1;33mBuilding ${example##*/} ... \033[0m";
arduino-cli compile --libraries /home/runner/work/RadioLib --fqbn ${{ matrix.id }}${{ steps.prep.outputs.options }} --build-property compiler.cpp.extra_flags="$flags" $example --warnings=${{ steps.prep.outputs.warnings }}
if [ $? -ne 0 ]; then
echo -e "\033[1;31m${example##*/} build FAILED\033[0m\n";
exit 1;
else
echo -e "\033[1;32m${example##*/} build PASSED\033[0m\n";
fi
fi
done
esp-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
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: |
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
- name: Install ESP-IDF
run: |
cd ~/esp/esp-idf
./install.sh esp32
- name: Build the example
run: |
cd $PWD/examples/NonArduino/ESP-IDF
. ~/esp/esp-idf/export.sh
idf.py build
tock-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
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
git clone https://github.com/tock/libtock-c.git
cd libtock-c; git checkout 44bf89c545953d8859faf101d4b4a4b6a151fe6c; cd ../
LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
rpi-build:
runs-on: [self-hosted, ARM64]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y pigpio cmake
- name: Install the library
run: |
cd $PWD
mkdir build
cd build
cmake ..
sudo make install
- name: Build the example
run: |
cd $PWD/examples/NonArduino/Raspberry
./build.sh
rpi-test:
needs: rpi-build
runs-on: [self-hosted, ARM64]
steps:
- name: SX126x test
run: |
cd $PWD/extras/test/SX126x
./clean.sh
./build.sh
sudo ./build/rpi-sx1261
rpi-pico-build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
sudo apt install git cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
- name: Clone the SDK
run: |
mkdir -p ~/rpi-pico
cd ~/rpi-pico
git clone https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk && git checkout 1.5.1
- name: Build the example
run: |
export PICO_SDK_PATH=~/rpi-pico/pico-sdk
cd $PWD/examples/NonArduino/Pico
./build.sh

View file

@ -7,6 +7,10 @@
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
@ -30,13 +34,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -1,18 +1,22 @@
/*
RadioLib LR11x0 Channel Activity Detection Example
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.
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.
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 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/
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
@ -25,13 +29,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -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() {
}

View file

@ -1,19 +1,19 @@
/*
RadioLib LR11x0 GFSK Modem Example
RadioLib LR11x0 GFSK Modem Example
This example shows how to use GFSK modem in LR11x0 chips.
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.
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 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/
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library

View file

@ -1,19 +1,19 @@
/*
RadioLib LR11x0 LR-FHSS Modem Example
RadioLib LR11x0 LR-FHSS Modem Example
This example shows how to use LR-FHSS modem in LR11x0 chips.
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.
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 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/
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library

View file

@ -12,6 +12,10 @@
- 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
@ -35,13 +39,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -1,24 +1,28 @@
/*
RadioLib LR11x0 Receive with Interrupts Example
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:
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.
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 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/
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
@ -31,13 +35,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -8,6 +8,10 @@
- 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
@ -26,13 +30,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();
@ -44,17 +68,6 @@ void setup() {
delay(1000);
while (true);
}
// some modules have an external RF switch
// controlled via two pins (RX enable, TX enable)
// to enable automatic control of the switch,
// call the following method
// RX enable: 4
// TX enable: 5
/*
radio.setRfSwitchPins(4, 5);
*/
}
// counter to keep track of transmitted packets

View file

@ -9,6 +9,10 @@
- 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
@ -27,9 +31,25 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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;
@ -37,6 +57,10 @@ 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();

View file

@ -6,6 +6,10 @@
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
@ -28,13 +32,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -6,6 +6,10 @@
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
@ -28,13 +32,33 @@
// BUSY pin: 9
LR1110 radio = new Module(10, 2, 3, 9);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//LR1110 radio = RadioShield.ModuleA;
// 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();

View file

@ -42,8 +42,10 @@ void setup() {
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
Serial.println(F("Initialise LoRaWAN Network credentials"));
state = node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey, true);
debug(state < RADIOLIB_ERR_NONE, F("Session setup failed"), state, true);
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"));
}

View file

@ -1,8 +1,21 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
#define _RADIOLIB_EX_LORAWAN_CONFIG_H
#include <RadioLib.h>
// first you have to set your radio model and pin configuration
// this is provided just as a default example
SX1278 radio = new Module(10, 2, 9, 3);
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
// and are using one of the supported boards, you can do the following:
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
// how often to send an uplink - consider legal & FUP constraints - see notes
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
@ -28,94 +41,13 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, IN865, KR920, CN780, CN500
// 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")
SX1276 radio = new Module(18, 26, 14, 35);
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
#pragma message ("Using Heltec WiFi LoRa32 v3")
SX1262 radio = new Module(8, 14, 12, 13);
#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);
#elif defined(ARDUINO_CUBECELL_BOARD)
#pragma message ("Using CubeCell")
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
#pragma error ("ARDUINO_CUBECELL_BOARD_V2 awaiting pin map")
#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);
#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 };
@ -126,14 +58,82 @@ uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
// create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand);
// result code to text - these are error codes that can be raised when using LoRaWAN
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
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 https://jgromes.github.io/RadioLib/group__status__codes.html";
}
// helper function to display any issues
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
if (isFail) {
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
if(failed) {
Serial.print(message);
Serial.print("(");
Serial.print(" - ");
Serial.print(stateDecode(state));
Serial.print(" (");
Serial.print(state);
Serial.println(")");
while (Freeze);
while(halt) { delay(1); }
}
}

View file

@ -46,11 +46,14 @@ void setup() {
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
// Override the default join rate
// uint8_t joinDR = 3;
uint8_t joinDR = 4;
Serial.println(F("Join ('login') to the LoRaWAN Network"));
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, true);
debug(state < RADIOLIB_ERR_NONE, F("Join 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(joinDR);
debug(state != RADIOLIB_LORAWAN_NEW_SESSION, F("Join failed"), state, true);
// Print the DevAddr
Serial.print("[LoRaWAN] DevAddr: ");
@ -72,7 +75,7 @@ void setup() {
}
void loop() {
int state = RADIOLIB_ERR_NONE;
int16_t state = RADIOLIB_ERR_NONE;
// set battery fill level - the LoRaWAN network server
// may periodically request this information
@ -111,8 +114,8 @@ void loop() {
// and also request the LinkCheck and DeviceTime MAC commands
if(fcntUp % 64 == 0) {
Serial.println(F("[LoRaWAN] Requesting LinkCheck and DeviceTime"));
node.sendMacCommandReq(RADIOLIB_LW_MAC_LINK_CHECK);
node.sendMacCommandReq(RADIOLIB_LW_MAC_DEVICE_TIME);
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);

View file

@ -1,8 +1,21 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
#define _RADIOLIB_EX_LORAWAN_CONFIG_H
#include <RadioLib.h>
// first you have to set your radio model and pin configuration
// this is provided just as a default example
SX1278 radio = new Module(10, 2, 9, 3);
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
// and are using one of the supported boards, you can do the following:
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
// how often to send an uplink - consider legal & FUP constraints - see notes
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
@ -24,93 +37,13 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, IN865, KR920, CN780, CN500
// 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")
SX1276 radio = new Module(18, 26, 14, 35);
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
#pragma message ("Using Heltec WiFi LoRa32 v3")
SX1262 radio = new Module(8, 14, 12, 13);
#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);
#elif defined(ARDUINO_CUBECELL_BOARD)
#pragma message ("Using CubeCell")
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
#pragma error ("ARDUINO_CUBECELL_BOARD_V2 awaiting pin map")
#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);
#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;
@ -120,14 +53,82 @@ uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };
// create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand);
// result code to text - these are error codes that can be raised when using LoRaWAN
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
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 https://jgromes.github.io/RadioLib/group__status__codes.html";
}
// helper function to display any issues
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
if (isFail) {
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
if(failed) {
Serial.print(message);
Serial.print("(");
Serial.print(" - ");
Serial.print(stateDecode(state));
Serial.print(" (");
Serial.print(state);
Serial.println(")");
while (Freeze);
while(halt) { delay(1); }
}
}

View file

@ -31,12 +31,15 @@ void setup() {
Serial.println(F("\nSetup ... "));
Serial.println(F("Initialise the radio"));
int state = radio.begin();
int16_t state = radio.begin();
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
Serial.println(F("Join ('login') to the LoRaWAN Network"));
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, true);
debug(state < RADIOLIB_ERR_NONE, F("Join 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"));
}
@ -56,7 +59,7 @@ void loop() {
uplinkPayload[2] = lowByte(value2);
// Perform an uplink
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
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 "));

View file

@ -1,8 +1,21 @@
#ifndef _CONFIG_H
#define _CONFIG_H
#ifndef _RADIOLIB_EX_LORAWAN_CONFIG_H
#define _RADIOLIB_EX_LORAWAN_CONFIG_H
#include <RadioLib.h>
// first you have to set your radio model and pin configuration
// this is provided just as a default example
SX1278 radio = new Module(10, 2, 9, 3);
// if you have RadioBoards (https://github.com/radiolib-org/RadioBoards)
// and are using one of the supported boards, you can do the following:
/*
#define RADIO_BOARD_AUTO
#include <RadioBoards.h>
Radio radio = new RadioModule();
*/
// how often to send an uplink - consider legal & FUP constraints - see notes
const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
@ -24,93 +37,13 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
// for the curious, the #ifndef blocks allow for automated testing &/or you can
// put your EUI & keys in to your platformio.ini - see wiki for more tips
// regional choices: EU868, US915, AU915, AS923, IN865, KR920, CN780, CN500
// 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")
SX1276 radio = new Module(18, 26, 14, 35);
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
#pragma message ("Using Heltec WiFi LoRa32 v3")
SX1262 radio = new Module(8, 14, 12, 13);
#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);
#elif defined(ARDUINO_CUBECELL_BOARD)
#pragma message ("Using CubeCell")
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
#pragma error ("ARDUINO_CUBECELL_BOARD_V2 awaiting pin map")
#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);
#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;
@ -120,14 +53,82 @@ uint8_t nwkKey[] = { RADIOLIB_LORAWAN_NWK_KEY };
// create the LoRaWAN node
LoRaWANNode node(&radio, &Region, subBand);
// result code to text - these are error codes that can be raised when using LoRaWAN
// however, RadioLib has many more - see https://jgromes.github.io/RadioLib/group__status__codes.html for a complete list
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 https://jgromes.github.io/RadioLib/group__status__codes.html";
}
// helper function to display any issues
void debug(bool isFail, const __FlashStringHelper* message, int state, bool Freeze) {
if (isFail) {
void debug(bool failed, const __FlashStringHelper* message, int state, bool halt) {
if(failed) {
Serial.print(message);
Serial.print("(");
Serial.print(" - ");
Serial.print(stateDecode(state));
Serial.print(" (");
Serial.print(state);
Serial.println(")");
while (Freeze);
while(halt) { delay(1); }
}
}

View file

@ -141,31 +141,12 @@ 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).
This is the connection between your microcontroller (ESP32, ATmega, SAMD etc.) and the radio (SX1276, SX1262, LR1110 etc.).
You have to select the correct module and set the correct pins.
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.
Pin maps for commonly used radio modules are kept in a separate library, called RadioBoards: https://github.com/radiolib-org/RadioBoards
It can automatically detect your microcontroller platform and radio, and configure things for you. If you have a board that is not supported by RadioBoards, feel free to suggest it in the RadioBoards issues, or better yet - open a pull request there!
## Observations on the main sketch
@ -197,8 +178,3 @@ Coming soon
### 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

View file

@ -15,7 +15,7 @@ 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(RadioLib PUBLIC RADIOLIB_DEBUG_BASIC RADIOLIB_DEBUG_SPI)

View file

@ -1,55 +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>
// these should really be swapped, but for some reason,
// it seems like the change directions are inverted in gpioSetAlert functions
#define PI_RISING (FALLING_EDGE)
#define PI_FALLING (RISING_EDGE)
#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 pigpioAlertHandler(int event, int level, uint32_t tick, void *userdata);
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, PI_RISING, PI_FALLING),
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
@ -59,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 {
@ -67,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 {
@ -75,7 +93,11 @@ 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 {
@ -83,13 +105,19 @@ class PiHal : public RadioLibHal {
return;
}
// 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;
// set pigpio alert callback
gpioSetAlertFuncEx(interruptNum, pigpioAlertHandler, (void*)this);
lgGpioSetAlertsFunc(_gpioHandle, interruptNum, lgpioAlertHandler, (void *)this);
}
void detachInterrupt(uint32_t interruptNum) override {
@ -102,27 +130,44 @@ class PiHal : public RadioLibHal {
interruptModes[interruptNum] = 0;
interruptCallbacks[interruptNum] = NULL;
// disable pigpio alert callback
gpioSetAlertFuncEx(interruptNum, NULL, NULL);
// disable lgpio alert callback
lgGpioFree(_gpioHandle, interruptNum);
lgGpioSetAlertsFunc(_gpioHandle, interruptNum, NULL, NULL);
}
void delay(RadioLibTime_t ms) override {
gpioDelay(ms * 1000);
void delay(unsigned long ms) override {
if(ms == 0) {
sched_yield();
return;
}
lguSleep(ms / 1000.0);
}
void delayMicroseconds(RadioLibTime_t us) override {
gpioDelay(us);
void delayMicroseconds(unsigned long us) override {
if(us == 0) {
sched_yield();
return;
}
lguSleep(us / 1000000.0);
}
RadioLibTime_t millis() override {
return(gpioTick() / 1000);
void yield() override {
sched_yield();
}
RadioLibTime_t micros() override {
return(gpioTick());
unsigned long millis() override {
uint32_t time = lguTimestamp() / 1000000UL;
return time;
}
long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) override {
unsigned long micros() override {
uint32_t time = lguTimestamp() / 1000UL;
return time;
}
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
if(pin == RADIOLIB_NC) {
return(0);
}
@ -142,25 +187,38 @@ class PiHal : public RadioLibHal {
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];
@ -170,24 +228,28 @@ class PiHal : public RadioLibHal {
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 pigpioAlertHandler(int event, int level, uint32_t tick, void *userdata) {
if((event > PI_MAX_USER_GPIO) || (!userdata)) {
static void lgpioAlertHandler(int num_alerts, lgGpioAlert_p alerts, void *userdata) {
if(!userdata)
return;
}
// PiHal isntance is passed via the user data
// PiHal instance is passed via the user data
PiHal* hal = (PiHal*)userdata;
// check the interrupt is enabled, the level matches and a callback exists
if((hal->interruptEnabled[event]) &&
(hal->interruptModes[event] == level) &&
(hal->interruptCallbacks[event])) {
hal->interruptCallbacks[event]();
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]();
}
}
}

View file

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

View file

@ -54,6 +54,7 @@ if (RISCV_BUILD)
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
@ -67,6 +68,7 @@ if (RISCV_BUILD)
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
@ -82,6 +84,7 @@ 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++-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
@ -91,6 +94,7 @@ 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

View file

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

View file

@ -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() {

View file

@ -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}},

View file

@ -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}},

View file

@ -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}},

View file

@ -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}},

View file

@ -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}},

View file

@ -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}},

View file

@ -1,4 +1,4 @@
version: "6.5.0"
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"

View file

@ -83,18 +83,21 @@ 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 scan results
# LR11x0 structures
LR11x0WifiResult_t KEYWORD1
LR11x0WifiResultFull_t KEYWORD1
LR11x0WifiResultExtended_t KEYWORD1
LR11x0VersionInfo_t KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
@ -254,6 +257,8 @@ getWifiScanResult KEYWORD2
wifiScan KEYWORD2
setWiFiScanAction KEYWORD2
clearWiFiScanAction KEYWORD2
getVersionInfo KEYWORD2
updateFirmware KEYWORD2
# RTTY
idle KEYWORD2
@ -313,16 +318,17 @@ checkDataRate KEYWORD2
setModem KEYWORD2
# LoRaWAN
wipe KEYWORD2
clearSession KEYWORD2
getBufferNonces KEYWORD2
setBufferNonces KEYWORD2
getBufferSession KEYWORD2
setBufferSession KEYWORD2
restore KEYWORD2
beginOTAA KEYWORD2
activateOTAA KEYWORD2
beginABP KEYWORD2
isJoined KEYWORD2
saveSession KEYWORD2
activateABP KEYWORD2
isActivated KEYWORD2
setRx2Dr KEYWORD2
sendMacCommandReq KEYWORD2
uplink KEYWORD2
downlink KEYWORD2
@ -447,7 +453,7 @@ 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
@ -455,7 +461,27 @@ 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_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

View file

@ -1,6 +1,6 @@
{
"name": "RadioLib",
"version": "6.5.0",
"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, lr1110, lr1120, lr1121",
"homepage": "https://github.com/jgromes/RadioLib",

View file

@ -1,5 +1,5 @@
name=RadioLib
version=6.5.0
version=6.6.0
author=Jan Gromes <gromes.jan@gmail.com>
maintainer=Jan Gromes <gromes.jan@gmail.com>
sentence=Universal wireless communication library

View file

@ -126,6 +126,8 @@ void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, RadioLibTime_
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) {

View file

@ -570,7 +570,7 @@
// version definitions
#define RADIOLIB_VERSION_MAJOR 6
#define RADIOLIB_VERSION_MINOR 5
#define RADIOLIB_VERSION_MINOR 6
#define RADIOLIB_VERSION_PATCH 0
#define RADIOLIB_VERSION_EXTRA 0

View file

@ -118,7 +118,7 @@ void Module::SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inByte
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, RADIOLIB_MODULE_SPI_TIMEOUT);
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);
}
}
@ -135,7 +135,7 @@ uint8_t Module::SPIreadRegister(uint32_t reg) {
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, RADIOLIB_MODULE_SPI_TIMEOUT);
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);
}
@ -152,7 +152,7 @@ void Module::SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes)
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, RADIOLIB_MODULE_SPI_TIMEOUT);
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);
}
}
@ -168,7 +168,7 @@ void Module::SPIwriteRegister(uint32_t reg, uint8_t data) {
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, RADIOLIB_MODULE_SPI_TIMEOUT);
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);
}
}
@ -245,7 +245,7 @@ int16_t Module::SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool
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
@ -273,7 +273,7 @@ int16_t Module::SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, boo
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
@ -301,7 +301,7 @@ int16_t Module::SPIcheckStream() {
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_MODULE_SPI_TIMEOUT);
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
@ -313,7 +313,7 @@ int16_t Module::SPIcheckStream() {
return(state);
}
int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, RadioLibTime_t timeout) {
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) {
@ -345,7 +345,7 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
RadioLibTime_t start = this->hal->millis();
while(this->hal->digitalRead(this->gpioPin)) {
this->hal->yield();
if(this->hal->millis() - start >= timeout) {
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;
@ -378,7 +378,7 @@ int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write
RadioLibTime_t start = this->hal->millis();
while(this->hal->digitalRead(this->gpioPin)) {
this->hal->yield();
if(this->hal->millis() - start >= timeout) {
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;
@ -565,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.
@ -578,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++)

View file

@ -18,9 +18,6 @@
*/
#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.
\{
@ -74,7 +71,7 @@ class Module {
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;
static const size_t RFSWITCH_MAX_PINS = 5;
/*!
\struct RfSwitchMode_t
@ -200,6 +197,9 @@ class Module {
/*! \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. */
@ -211,6 +211,7 @@ class Module {
.statusPos = 0,
.parseStatusCb = nullptr,
.checkStatusCb = nullptr,
.timeout = 1000,
};
#if RADIOLIB_INTERRUPT_TIMING
@ -368,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(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, RadioLibTime_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
@ -546,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

View file

@ -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.
@ -563,6 +563,31 @@
*/
#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
/*!

View file

@ -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);
@ -589,7 +591,7 @@ int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped) {
}
int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
constexpr int8_t allowedPwrs[8] = { -30, -20, -15, -10, 0, 5, 7, 10 };
const int8_t allowedPwrs[8] = { -30, -20, -15, -10, 0, 5, 7, 10 };
if(clipped) {
if(power <= -30) {
@ -608,7 +610,7 @@ int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
// if just a check occurs (and not requesting the raw power value), return now
if(!raw) {
for(int i = 0; i < 8; i++) {
for(size_t i = 0; i < sizeof(allowedPwrs); i++) {
if(allowedPwrs[i] == power) {
return(RADIOLIB_ERR_NONE);
}
@ -642,35 +644,14 @@ int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
{0xCB, 0xC8, 0xCB, 0xC7},
{0xC2, 0xC0, 0xC2, 0xC0}};
switch(power) {
case allowedPwrs[0]: // -30
*raw = paTable[0][f];
break;
case allowedPwrs[1]: // -20
*raw = paTable[1][f];
break;
case allowedPwrs[2]: // -15
*raw = paTable[2][f];
break;
case allowedPwrs[3]: // -10
*raw = paTable[3][f];
break;
case allowedPwrs[4]: // 0
*raw = paTable[4][f];
break;
case allowedPwrs[5]: // 5
*raw = paTable[5][f];
break;
case allowedPwrs[6]: // 7
*raw = paTable[6][f];
break;
case allowedPwrs[7]: // 10
*raw = paTable[7][f];
break;
default:
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
for(uint8_t i = 0; i < sizeof(allowedPwrs); i++) {
if(power == allowedPwrs[i]) {
*raw = paTable[i][f];
return(RADIOLIB_ERR_NONE);
}
}
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) {
@ -1042,7 +1023,7 @@ 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);
@ -1102,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;

View file

@ -845,7 +845,7 @@ 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() override;
@ -1003,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;

View file

@ -2,7 +2,7 @@
#if !RADIOLIB_EXCLUDE_LR11X0
LR1110::LR1110(Module* mod) : LR11x0(mod) {
chipType = RADIOLIB_LR11X0_HW_LR1110;
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) {

View file

@ -2,7 +2,7 @@
#if !RADIOLIB_EXCLUDE_LR11X0
LR1120::LR1120(Module* mod) : LR11x0(mod) {
chipType = RADIOLIB_LR11X0_HW_LR1120;
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) {

View file

@ -2,7 +2,47 @@
#if !RADIOLIB_EXCLUDE_LR11X0
LR1121::LR1121(Module* mod) : LR1120(mod) {
chipType = RADIOLIB_LR11X0_HW_LR1121;
chipType = RADIOLIB_LR11X0_DEVICE_LR1121;
}
int16_t LR1121::setOutputPower(int8_t power, bool useHighFreqPa)
{
int16_t state = RADIOLIB_ERR_INVALID_OUTPUT_POWER;
if (useHighFreqPa) {
if ((-18 <= power ) && ( power <= 13 )) {
state = setPaConfig(0x02, // High-frequency Power Amplifier
0x00, // Power amplifier supplied by the main regulator
0x04, // Power Amplifier duty cycle (Default 0x04)
0x07 // Number of slices for HPA (Default 0x07)
);
} else {
return RADIOLIB_ERR_INVALID_OUTPUT_POWER;
}
} else {
if (( -17 <= power ) && (power <= 22 )) {
if (power == 22) {
state = setPaConfig(0x01, // High-power Power Amplifier
0x01, // Power amplifier supplied by the battery
0x04, // Power Amplifier duty cycle (Default 0x04)
0x07 // Number of slices for HPA (Default 0x07)
);
} else {
state = setPaConfig(0x00, // Low-power Power Amplifier
0x00, // Power amplifier supplied by the main regulator
0x04, // Power Amplifier duty cycle (Default 0x04)
0x07 // Number of slices for HPA (Default 0x07)
);
}
} else {
return RADIOLIB_ERR_INVALID_OUTPUT_POWER;
}
}
RADIOLIB_ASSERT(state);
// set output power
state = setTxParams(power, RADIOLIB_LR11X0_PA_RAMP_48U);
return (state);
}
#endif

View file

@ -21,6 +21,15 @@ class LR1121: public LR1120 {
*/
LR1121(Module* mod); // cppcheck-suppress noExplicitConstructor
/*!
\brief Sets output power. Allowed values are in range from -17 to 22 dBm (high-power PA) or -18 to 13 dBm (High-frequency PA).
\param power Output power to be set in dBm.
\param useHighFreqPa When using 2.4G frequency, need to switch to High-frequency PA
\returns \ref status_codes
*/
int16_t setOutputPower(int8_t power,bool useHighFreqPa = false);
// TODO this is where overrides to disable GNSS+WiFi scanning methods on LR1121
// will be put once those are implemented

View file

@ -44,6 +44,9 @@ int16_t LR11x0::begin(float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t
state = invertIQ(false);
RADIOLIB_ASSERT(state);
state = setRegulatorLDO();
RADIOLIB_ASSERT(state);
return(RADIOLIB_ERR_NONE);
}
@ -85,6 +88,9 @@ int16_t LR11x0::beginGFSK(float br, float freqDev, float rxBw, int8_t power, uin
state = setCRC(2);
RADIOLIB_ASSERT(state);
state = setRegulatorLDO();
RADIOLIB_ASSERT(state);
return(RADIOLIB_ERR_NONE);
}
@ -103,6 +109,9 @@ int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, int8_t power, float tcxoVolt
state = setSyncWord(0x12AD101B);
RADIOLIB_ASSERT(state);
state = setRegulatorLDO();
RADIOLIB_ASSERT(state);
// set fixed configuration
return(setModulationParamsLrFhss(RADIOLIB_LR11X0_LR_FHSS_BIT_RATE_RAW, RADIOLIB_LR11X0_LR_FHSS_SHAPING_GAUSSIAN_BT_1_0));
}
@ -314,6 +323,10 @@ int16_t LR11x0::standby(uint8_t mode, bool wakeup) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_STANDBY, true, buff, 1));
}
int16_t LR11x0::sleep() {
return(LR11x0::sleep(true, 0));
}
int16_t LR11x0::sleep(bool retainConfig, uint32_t sleepTime) {
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_IDLE);
@ -485,7 +498,7 @@ uint32_t LR11x0::getIrqStatus() {
// there is no dedicated "get IRQ" command, the IRQ bits are sent after the status bytes
uint8_t buff[6] = { 0 };
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_0;
mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true, RADIOLIB_MODULE_SPI_TIMEOUT);
mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_8;
uint32_t irq = ((uint32_t)(buff[2]) << 24) | ((uint32_t)(buff[3]) << 16) | ((uint32_t)(buff[4]) << 8) | (uint32_t)buff[5];
return(irq);
@ -1316,7 +1329,36 @@ RadioLibTime_t LR11x0::getTimeOnAir(size_t len) {
return(((uint32_t)len * 8 * 1000000UL) / this->bitRate);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(((uint32_t)len * 8 * 1000000UL) / RADIOLIB_LR11X0_LR_FHSS_BIT_RATE);
// calculate the number of bits based on coding rate
uint16_t N_bits;
switch(this->lrFhssCr) {
case RADIOLIB_LR11X0_LR_FHSS_CR_5_6:
N_bits = ((len * 6) + 4) / 5; // this is from the official LR11xx driver, but why the extra +4?
break;
case RADIOLIB_LR11X0_LR_FHSS_CR_2_3:
N_bits = (len * 3) / 2;
break;
case RADIOLIB_LR11X0_LR_FHSS_CR_1_2:
N_bits = len * 2;
break;
case RADIOLIB_LR11X0_LR_FHSS_CR_1_3:
N_bits = len * 3;
break;
default:
return(RADIOLIB_ERR_INVALID_CODING_RATE);
}
// calculate number of bits when accounting for unaligned last block
uint16_t N_payBits = (N_bits / RADIOLIB_LR11X0_LR_FHSS_FRAG_BITS) * RADIOLIB_LR11X0_LR_FHSS_BLOCK_BITS;
uint16_t N_lastBlockBits = N_bits % RADIOLIB_LR11X0_LR_FHSS_FRAG_BITS;
if(N_lastBlockBits) {
N_payBits += N_lastBlockBits + 2;
}
// add header bits
uint16_t N_totalBits = (RADIOLIB_LR11X0_LR_FHSS_HEADER_BITS * this->lrFhssHdrCount) + N_payBits;
return(((uint32_t)N_totalBits * 8 * 1000000UL) / RADIOLIB_LR11X0_LR_FHSS_BIT_RATE);
}
return(0);
@ -1359,6 +1401,41 @@ float LR11x0::getDataRate() const {
return(this->dataRateMeasured);
}
int16_t LR11x0::setRegulatorLDO() {
return(this->setRegMode(RADIOLIB_LR11X0_REG_MODE_LDO));
}
int16_t LR11x0::setRegulatorDCDC() {
return(this->setRegMode(RADIOLIB_LR11X0_REG_MODE_DC_DC));
}
int16_t LR11x0::setRxBoostedGainMode(bool en) {
uint8_t buff[1] = { (uint8_t)en };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RX_BOOSTED, true, buff, sizeof(buff)));
}
void LR11x0::setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
// find which pins are used
uint8_t enable = 0;
for(size_t i = 0; i < Module::RFSWITCH_MAX_PINS; i++) {
if((pins[i] == RADIOLIB_NC) || (pins[i] > RADIOLIB_LR11X0_DIO10)) {
continue;
}
enable |= 1UL << pins[i];
}
// now get the configuration
uint8_t modes[7] = { 0 };
for(size_t i = 0; i < 7; i++) {
for(size_t j = 0; j < Module::RFSWITCH_MAX_PINS; j++) {
modes[i] |= (table[i].values[j] > 0) ? (1UL << j) : 0;
}
}
// set it
this->setDioAsRfSwitch(enable, modes[0], modes[1], modes[2], modes[3], modes[4], modes[5], modes[6]);
}
int16_t LR11x0::setLrFhssConfig(uint8_t bw, uint8_t cr, uint8_t hdrCount, uint16_t hopSeed) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
@ -1542,6 +1619,83 @@ int16_t LR11x0::wifiScan(uint8_t wifiType, uint8_t* count, uint8_t mode, uint16_
return(getWifiScanResultsCount(count));
}
int16_t LR11x0::getVersionInfo(LR11x0VersionInfo_t* info) {
if(!info) {
return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED);
}
int16_t state = this->getVersion(&info->hardware, &info->device, &info->fwMajor, &info->fwMinor);
RADIOLIB_ASSERT(state);
if(this->chipType != RADIOLIB_LR11X0_DEVICE_LR1121){
state = this->wifiReadVersion(&info->fwMajorWiFi, &info->fwMinorWiFi);
RADIOLIB_ASSERT(state);
return(this->gnssReadVersion(&info->fwGNSS, &info->almanacGNSS));
}
return RADIOLIB_ERR_NONE;
}
int16_t LR11x0::updateFirmware(const uint32_t* image, size_t size, bool nonvolatile) {
if(!image) {
return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED);
}
// put the device to bootloader mode
int16_t state = this->reboot(true);
RADIOLIB_ASSERT(state);
this->mod->hal->delay(500);
// check we're in bootloader
uint8_t device = 0xFF;
state = this->getVersion(NULL, &device, NULL, NULL);
RADIOLIB_ASSERT(state);
if(device != RADIOLIB_LR11X0_DEVICE_BOOT) {
RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to put device to bootloader mode, %02x != %02x", (unsigned int)device, (unsigned int)RADIOLIB_LR11X0_DEVICE_BOOT);
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
}
// erase the image
state = this->bootEraseFlash();
RADIOLIB_ASSERT(state);
// wait for BUSY to go low
RadioLibTime_t start = this->mod->hal->millis();
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
this->mod->hal->yield();
if(this->mod->hal->millis() - start >= 3000) {
RADIOLIB_DEBUG_BASIC_PRINTLN("BUSY pin timeout after erase!");
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
}
}
// upload the new image
const size_t maxLen = 64;
size_t rem = size % maxLen;
size_t numWrites = (rem == 0) ? (size / maxLen) : ((size / maxLen) + 1);
RADIOLIB_DEBUG_BASIC_PRINTLN("Writing image in %lu chunks, last chunk size is %lu words", (unsigned long)numWrites, (unsigned long)rem);
for(size_t i = 0; i < numWrites; i ++) {
uint32_t offset = i * maxLen;
uint32_t len = (i == (numWrites - 1)) ? rem : maxLen;
RADIOLIB_DEBUG_BASIC_PRINTLN("Writing chunk %d at offset %08lx (%u words)", (int)i, (unsigned long)offset, (unsigned int)len);
this->bootWriteFlashEncrypted(offset*sizeof(uint32_t), (uint32_t*)&image[offset], len, nonvolatile);
}
// kick the device from bootloader
state = this->reset();
RADIOLIB_ASSERT(state);
// verify we are no longer in bootloader
state = this->getVersion(NULL, &device, NULL, NULL);
RADIOLIB_ASSERT(state);
if(device == RADIOLIB_LR11X0_DEVICE_BOOT) {
RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to kick device from bootloader mode, %02x == %02x", (unsigned int)device, (unsigned int)RADIOLIB_LR11X0_DEVICE_BOOT);
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
}
return(state);
}
int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
@ -1597,7 +1751,7 @@ int16_t LR11x0::SPIcheckStatus(Module* mod) {
// it also seems to ignore the actual command, and just sending in bunch of NOPs will work
uint8_t buff[6] = { 0 };
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_0;
int16_t state = mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true, RADIOLIB_MODULE_SPI_TIMEOUT);
int16_t state = mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] = Module::BITS_8;
RADIOLIB_ASSERT(state);
return(LR11x0::SPIparseStatus(buff[0]));
@ -1633,12 +1787,18 @@ bool LR11x0::findChip(uint8_t ver) {
reset();
// read the version
uint8_t device = 0xFF;
if((this->getVersion(NULL, &device, NULL, NULL) == RADIOLIB_ERR_NONE) && (device == ver)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("Found LR11x0: RADIOLIB_LR11X0_CMD_GET_VERSION = 0x%02x", device);
LR11x0VersionInfo_t info;
int16_t state = getVersionInfo(&info);
if((state == RADIOLIB_ERR_NONE) && (info.device == ver)) {
RADIOLIB_DEBUG_BASIC_PRINTLN("Found LR11x0: RADIOLIB_LR11X0_CMD_GET_VERSION = 0x%02x", info.device);
RADIOLIB_DEBUG_BASIC_PRINTLN("Base FW version: %d.%d", (int)info.fwMajor, (int)info.fwMinor);
if(this->chipType != RADIOLIB_LR11X0_DEVICE_LR1121){
RADIOLIB_DEBUG_BASIC_PRINTLN("WiFi FW version: %d.%d", (int)info.fwMajorWiFi, (int)info.fwMinorWiFi);
RADIOLIB_DEBUG_BASIC_PRINTLN("GNSS FW version: %d.%d", (int)info.fwGNSS, (int)info.almanacGNSS);
}
flagFound = true;
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("LR11x0 not found! (%d of 10 tries) RADIOLIB_LR11X0_CMD_GET_VERSION = 0x%02x", i + 1, device);
RADIOLIB_DEBUG_BASIC_PRINTLN("LR11x0 not found! (%d of 10 tries) RADIOLIB_LR11X0_CMD_GET_VERSION = 0x%02x", i + 1, info.device);
RADIOLIB_DEBUG_BASIC_PRINTLN("Expected: 0x%02x", ver);
this->mod->hal->delay(10);
i++;
@ -1768,7 +1928,7 @@ int16_t LR11x0::writeRegMem32(uint32_t addr, uint32_t* data, size_t len) {
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
}
return(this->writeCommon(RADIOLIB_LR11X0_CMD_WRITE_REG_MEM, addr, data, len));
return(this->writeCommon(RADIOLIB_LR11X0_CMD_WRITE_REG_MEM, addr, data, len, false));
}
int16_t LR11x0::readRegMem32(uint32_t addr, uint32_t* data, size_t len) {
@ -1861,7 +2021,7 @@ int16_t LR11x0::getStatus(uint8_t* stat1, uint8_t* stat2, uint32_t* irq) {
// the status check command doesn't return status in the same place as other read commands
// but only as the first byte (as with any other command), hence LR11x0::SPIcommand can't be used
// it also seems to ignore the actual command, and just sending in bunch of NOPs will work
int16_t state = this->mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true, RADIOLIB_MODULE_SPI_TIMEOUT);
int16_t state = this->mod->SPItransferStream(NULL, 0, false, NULL, buff, sizeof(buff), true);
// pass the replies
if(stat1) { *stat1 = buff[0]; }
@ -1946,8 +2106,8 @@ int16_t LR11x0::setTcxoMode(uint8_t tune, uint32_t delay) {
}
int16_t LR11x0::reboot(bool stay) {
uint8_t buff[1] = { (uint8_t)stay };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_REBOOT, true, buff, sizeof(buff)));
uint8_t buff[1] = { (uint8_t)(stay*3) };
return(this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_REBOOT, buff, sizeof(buff), true, false));
}
int16_t LR11x0::getVbat(float* vbat) {
@ -2355,7 +2515,7 @@ int16_t LR11x0::setRangingReqAddr(uint32_t addr) {
int16_t LR11x0::getRangingResult(uint8_t type, float* res) {
uint8_t reqBuff[1] = { type };
uint8_t rplBuff[4] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_NOP, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GET_RANGING_RESULT, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
RADIOLIB_ASSERT(state);
if(res) {
@ -2396,17 +2556,28 @@ int16_t LR11x0::setGfskWhitParams(uint16_t seed) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_GFSK_WHIT_PARAMS, true, buff, sizeof(buff)));
}
int16_t LR11x0::setRxBoosted(bool en) {
uint8_t buff[1] = { (uint8_t)en };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RX_BOOSTED, true, buff, sizeof(buff)));
}
int16_t LR11x0::setRangingParameter(uint8_t symbolNum) {
// the first byte is reserved
uint8_t buff[2] = { 0x00, symbolNum };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RANGING_PARAMETER, true, buff, sizeof(buff)));
}
int16_t LR11x0::setRssiCalibration(const int8_t* tune, int16_t gainOffset) {
uint8_t buff[11] = {
(uint8_t)((tune[0] & 0x0F) | (uint8_t)(tune[1] & 0x0F) << 4),
(uint8_t)((tune[2] & 0x0F) | (uint8_t)(tune[3] & 0x0F) << 4),
(uint8_t)((tune[4] & 0x0F) | (uint8_t)(tune[5] & 0x0F) << 4),
(uint8_t)((tune[6] & 0x0F) | (uint8_t)(tune[7] & 0x0F) << 4),
(uint8_t)((tune[8] & 0x0F) | (uint8_t)(tune[9] & 0x0F) << 4),
(uint8_t)((tune[10] & 0x0F) | (uint8_t)(tune[11] & 0x0F) << 4),
(uint8_t)((tune[12] & 0x0F) | (uint8_t)(tune[13] & 0x0F) << 4),
(uint8_t)((tune[14] & 0x0F) | (uint8_t)(tune[15] & 0x0F) << 4),
(uint8_t)((tune[16] & 0x0F) | (uint8_t)(tune[17] & 0x0F) << 4),
(uint8_t)(((uint16_t)gainOffset >> 8) & 0xFF), (uint8_t)(gainOffset & 0xFF),
};
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_RSSI_CALIBRATION, true, buff, sizeof(buff)));
}
int16_t LR11x0::setLoRaSyncWord(uint8_t sync) {
uint8_t buff[1] = { sync };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_SET_LORA_SYNC_WORD, true, buff, sizeof(buff)));
@ -2716,7 +2887,7 @@ int16_t LR11x0::gnssGetContextStatus(uint8_t* fwVersion, uint32_t* almanacCrc, u
// read the result - this requires some magic bytes first, that's why LR11x0::SPIcommand cannot be used
uint8_t cmd_buff[3] = { 0x00, 0x02, 0x18 };
uint8_t buff[9] = { 0 };
state = this->mod->SPItransferStream(cmd_buff, sizeof(cmd_buff), false, NULL, buff, sizeof(buff), true, RADIOLIB_MODULE_SPI_TIMEOUT);
state = this->mod->SPItransferStream(cmd_buff, sizeof(cmd_buff), false, NULL, buff, sizeof(buff), true);
// pass the replies
if(fwVersion) { *fwVersion = buff[0]; }
@ -2824,6 +2995,196 @@ int16_t LR11x0::gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t co
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE, false, nbSv, 1, reqBuff, sizeof(reqBuff)));
}
// TODO check version > 02.01
int16_t LR11x0::gnssScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax) {
uint8_t buff[3] = { effort, resMask, nbSvMax };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SCAN, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssReadLastScanModeLaunched(uint8_t* lastScanMode) {
uint8_t buff[1] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_LAST_SCAN_MODE_LAUNCHED, false, buff, sizeof(buff));
// pass the replies
if(lastScanMode) { *lastScanMode = buff[0]; }
return(state);
}
int16_t LR11x0::gnssFetchTime(uint8_t effort, uint8_t opt) {
uint8_t buff[2] = { effort, opt };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_FETCH_TIME, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssReadTime(uint8_t* err, uint32_t* time, uint32_t* nbUs, uint32_t* timeAccuracy) {
uint8_t buff[12] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_TIME, false, buff, sizeof(buff));
// pass the replies
if(err) { *err = buff[0]; }
if(time) { *time = ((uint32_t)(buff[1]) << 24) | ((uint32_t)(buff[2]) << 16) | ((uint32_t)(buff[3]) << 8) | (uint32_t)buff[4]; }
if(nbUs) { *nbUs = ((uint32_t)(buff[5]) << 16) | ((uint32_t)(buff[6]) << 8) | (uint32_t)buff[7]; }
if(timeAccuracy) { *timeAccuracy = ((uint32_t)(buff[8]) << 24) | ((uint32_t)(buff[9]) << 16) | ((uint32_t)(buff[10]) << 8) | (uint32_t)buff[11]; }
return(state);
}
int16_t LR11x0::gnssResetTime(void) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_RESET_TIME, true, NULL, 0));
}
int16_t LR11x0::gnssResetPosition(void) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_RESET_POSITION, true, NULL, 0));
}
int16_t LR11x0::gnssReadDemodStatus(int8_t* status, uint8_t* info) {
uint8_t buff[2] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DEMOD_STATUS, false, buff, sizeof(buff));
// pass the replies
if(status) { *status = (int8_t)buff[0]; }
if(info) { *info = buff[1]; }
return(state);
}
int16_t LR11x0::gnssReadCumulTiming(uint32_t* timing, uint8_t* constDemod) {
uint8_t rplBuff[125] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_READ_REG_MEM, false, rplBuff, 125);
RADIOLIB_ASSERT(state);
// convert endians
if(timing) {
for(size_t i = 0; i < 31; i++) {
timing[i] = ((uint32_t)rplBuff[i*sizeof(uint32_t)] << 24) | ((uint32_t)rplBuff[1 + i*sizeof(uint32_t)] << 16) | ((uint32_t)rplBuff[2 + i*sizeof(uint32_t)] << 8) | (uint32_t)rplBuff[3 + i*sizeof(uint32_t)];
}
}
if(constDemod) { *constDemod = rplBuff[124]; }
return(state);
}
int16_t LR11x0::gnssSetTime(uint32_t time, uint16_t accuracy) {
uint8_t buff[6] = {
(uint8_t)((time >> 24) & 0xFF), (uint8_t)((time >> 16) & 0xFF),
(uint8_t)((time >> 8) & 0xFF), (uint8_t)(time & 0xFF),
(uint8_t)((accuracy >> 8) & 0xFF), (uint8_t)(accuracy & 0xFF),
};
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_SET_TIME, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssReadDopplerSolverRes(uint8_t* error, uint8_t* nbSvUsed, float* lat, float* lon, uint16_t* accuracy, uint16_t* xtal, float* latFilt, float* lonFilt, uint16_t* accuracyFilt, uint16_t* xtalFilt) {
uint8_t buff[18] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DOPPLER_SOLVER_RES, false, buff, sizeof(buff));
// pass the replies
if(error) { *error = buff[0]; }
if(nbSvUsed) { *nbSvUsed = buff[1]; }
if(lat) {
uint16_t latRaw = ((uint16_t)(buff[2]) << 8) | (uint16_t)buff[3];
*lat = ((float)latRaw * 90.0f)/2048.0f;
}
if(lon) {
uint16_t lonRaw = ((uint16_t)(buff[4]) << 8) | (uint16_t)buff[5];
*lon = ((float)lonRaw * 180.0f)/2048.0f;
}
if(accuracy) { *accuracy = ((uint16_t)(buff[6]) << 8) | (uint16_t)buff[7]; }
if(xtal) { *xtal = ((uint16_t)(buff[8]) << 8) | (uint16_t)buff[9]; }
if(latFilt) {
uint16_t latRaw = ((uint16_t)(buff[10]) << 8) | (uint16_t)buff[11];
*latFilt = ((float)latRaw * 90.0f)/2048.0f;
}
if(lonFilt) {
uint16_t lonRaw = ((uint16_t)(buff[12]) << 8) | (uint16_t)buff[13];
*lonFilt = ((float)lonRaw * 180.0f)/2048.0f;
}
if(accuracyFilt) { *accuracyFilt = ((uint16_t)(buff[14]) << 8) | (uint16_t)buff[15]; }
if(xtalFilt) { *xtalFilt = ((uint16_t)(buff[16]) << 8) | (uint16_t)buff[17]; }
return(state);
}
int16_t LR11x0::gnssReadDelayResetAP(uint32_t* delay) {
uint8_t buff[3] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_DELAY_RESET_AP, false, buff, sizeof(buff));
if(delay) { *delay = ((uint32_t)(buff[0]) << 16) | ((uint32_t)(buff[1]) << 8) | (uint32_t)buff[2]; }
return(state);
}
int16_t LR11x0::gnssAlmanacUpdateFromSat(uint8_t effort, uint8_t bitMask) {
uint8_t buff[2] = { effort, bitMask };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssReadAlmanacStatus(uint8_t* status) {
// TODO parse the reply into some structure
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_STATUS, false, status, 53));
}
int16_t LR11x0::gnssConfigAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t period) {
uint8_t buff[4] = { bitMask, svType, (uint8_t)((period >> 8) & 0xFF), (uint8_t)(period & 0xFF) };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_CONFIG_ALMANAC_UPDATE_PERIOD, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssReadAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t* period) {
uint8_t reqBuff[2] = { bitMask, svType };
uint8_t rplBuff[2] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE_PERIOD, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
RADIOLIB_ASSERT(state);
if(period) { *period = ((uint16_t)(rplBuff[0]) << 8) | (uint16_t)rplBuff[1]; }
return(state);
}
int16_t LR11x0::gnssConfigDelayResetAP(uint32_t delay) {
uint8_t buff[3] = { (uint8_t)((delay >> 16) & 0xFF), (uint8_t)((delay >> 8) & 0xFF), (uint8_t)(delay & 0xFF) };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_CONFIG_DELAY_RESET_AP, true, buff, sizeof(buff)));
}
int16_t LR11x0::gnssGetSvWarmStart(uint8_t bitMask, uint8_t* sv, uint8_t nbVisSat) {
uint8_t reqBuff[1] = { bitMask };
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_GET_SV_WARM_START, false, sv, nbVisSat, reqBuff, sizeof(reqBuff)));
}
int16_t LR11x0::gnssReadWNRollover(uint8_t* status, uint8_t* rollover) {
uint8_t buff[2] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WN_ROLLOVER, false, buff, sizeof(buff));
if(status) { *status = buff[0]; }
if(rollover) { *rollover = buff[1]; }
return(state);
}
int16_t LR11x0::gnssReadWarmStartStatus(uint8_t bitMask, uint8_t* nbVisSat, uint32_t* timeElapsed) {
uint8_t reqBuff[1] = { bitMask };
uint8_t rplBuff[5] = { 0 };
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WARM_START_STATUS, false, rplBuff, sizeof(rplBuff), reqBuff, sizeof(reqBuff));
RADIOLIB_ASSERT(state);
if(nbVisSat) { *nbVisSat = rplBuff[0]; }
if(timeElapsed) { *timeElapsed = ((uint32_t)(rplBuff[1]) << 24) | ((uint32_t)(rplBuff[2]) << 16) | ((uint32_t)(rplBuff[3]) << 8) | (uint32_t)rplBuff[4]; }
return(state);
}
int16_t LR11x0::gnssWriteBitMaskSatActivated(uint8_t bitMask, uint32_t* bitMaskActivated0, uint32_t* bitMaskActivated1) {
uint8_t reqBuff[1] = { bitMask };
uint8_t rplBuff[8] = { 0 };
size_t rplLen = (bitMask & 0x01) ? 8 : 4; // GPS only has the first bit mask
int16_t state = this->SPIcommand(RADIOLIB_LR11X0_CMD_GNSS_READ_WARM_START_STATUS, false, rplBuff, rplLen, reqBuff, sizeof(reqBuff));
RADIOLIB_ASSERT(state);
if(bitMaskActivated0) { *bitMaskActivated0 = ((uint32_t)(rplBuff[0]) << 24) | ((uint32_t)(rplBuff[1]) << 16) | ((uint32_t)(rplBuff[2]) << 8) | (uint32_t)rplBuff[3]; }
if(bitMaskActivated1) { *bitMaskActivated1 = ((uint32_t)(rplBuff[4]) << 24) | ((uint32_t)(rplBuff[5]) << 16) | ((uint32_t)(rplBuff[6]) << 8) | (uint32_t)rplBuff[7]; }
return(state);
}
int16_t LR11x0::cryptoSetKey(uint8_t keyId, uint8_t* key) {
if(!key) {
return(RADIOLIB_ERR_MEMORY_ALLOCATION_FAILED);
@ -2988,13 +3349,12 @@ int16_t LR11x0::cryptoGetParam(uint8_t id, uint32_t* value) {
return(state);
}
int16_t LR11x0::cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len) {
int16_t LR11x0::cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile) {
// check maximum size
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
}
return(this->writeCommon(RADIOLIB_LR11X0_CMD_CRYPTO_CHECK_ENCRYPTED_FIRMWARE_IMAGE, offset, data, len));
return(this->writeCommon(RADIOLIB_LR11X0_CMD_CRYPTO_CHECK_ENCRYPTED_FIRMWARE_IMAGE, offset, data, len, nonvolatile));
}
int16_t LR11x0::cryptoCheckEncryptedFirmwareImageResult(bool* result) {
@ -3008,12 +3368,20 @@ int16_t LR11x0::cryptoCheckEncryptedFirmwareImageResult(bool* result) {
}
int16_t LR11x0::bootEraseFlash(void) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_ERASE_FLASH, true, NULL, 0));
// erasing flash takes about 2.5 seconds, temporarily tset SPI timeout to 3 seconds
RadioLibTime_t timeout = this->mod->spiConfig.timeout;
this->mod->spiConfig.timeout = 3000;
int16_t state = this->mod->SPIwriteStream(RADIOLIB_LR11X0_CMD_BOOT_ERASE_FLASH, NULL, 0, false, false);
this->mod->spiConfig.timeout = timeout;
return(state);
}
int16_t LR11x0::bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len) {
RADIOLIB_CHECK_RANGE(len, 1, 32, RADIOLIB_ERR_SPI_CMD_INVALID);
return(this->writeCommon(RADIOLIB_LR11X0_CMD_BOOT_WRITE_FLASH_ENCRYPTED, offset, data, len));
int16_t LR11x0::bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile) {
// check maximum size
if(len > (RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN/sizeof(uint32_t))) {
return(RADIOLIB_ERR_SPI_CMD_INVALID);
}
return(this->writeCommon(RADIOLIB_LR11X0_CMD_BOOT_WRITE_FLASH_ENCRYPTED, offset, data, len, nonvolatile));
}
int16_t LR11x0::bootReboot(bool stay) {
@ -3042,7 +3410,7 @@ int16_t LR11x0::bootGetJoinEui(uint8_t* eui) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_BOOT_GET_JOIN_EUI, false, eui, RADIOLIB_LR11X0_EUI_LEN));
}
int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len) {
int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len, bool nonvolatile) {
// build buffers - later we need to ensure endians are correct,
// so there is probably no way to do this without copying buffers and iterating
size_t buffLen = sizeof(uint32_t) + len*sizeof(uint32_t);
@ -3060,13 +3428,19 @@ int16_t LR11x0::writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* d
// convert endians
for(size_t i = 0; i < len; i++) {
dataBuff[4 + i] = (uint8_t)((data[i] >> 24) & 0xFF);
dataBuff[5 + i] = (uint8_t)((data[i] >> 16) & 0xFF);
dataBuff[6 + i] = (uint8_t)((data[i] >> 8) & 0xFF);
dataBuff[7 + i] = (uint8_t)(data[i] & 0xFF);
uint32_t bin = 0;
if(nonvolatile) {
bin = RADIOLIB_NONVOLATILE_READ_DWORD(data + i);
} else {
bin = data[i];
}
dataBuff[4 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 24) & 0xFF);
dataBuff[5 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 16) & 0xFF);
dataBuff[6 + i*sizeof(uint32_t)] = (uint8_t)((bin >> 8) & 0xFF);
dataBuff[7 + i*sizeof(uint32_t)] = (uint8_t)(bin & 0xFF);
}
int16_t state = this->SPIcommand(cmd, true, dataBuff, buffLen);
int16_t state = this->mod->SPIwriteStream(cmd, dataBuff, buffLen, true, false);
#if !RADIOLIB_STATIC_ONLY
delete[] dataBuff;
#endif

View file

@ -84,6 +84,7 @@
#define RADIOLIB_LR11X0_CMD_SET_GFSK_WHIT_PARAMS (0x0225)
#define RADIOLIB_LR11X0_CMD_SET_RX_BOOSTED (0x0227)
#define RADIOLIB_LR11X0_CMD_SET_RANGING_PARAMETER (0x0228)
#define RADIOLIB_LR11X0_CMD_SET_RSSI_CALIBRATION (0x0229)
#define RADIOLIB_LR11X0_CMD_SET_LORA_SYNC_WORD (0x022B)
#define RADIOLIB_LR11X0_CMD_LR_FHSS_BUILD_FRAME (0x022C)
#define RADIOLIB_LR11X0_CMD_LR_FHSS_SET_SYNC_WORD (0x022D)
@ -111,6 +112,10 @@
#define RADIOLIB_LR11X0_CMD_GNSS_SET_MODE (0x0408)
#define RADIOLIB_LR11X0_CMD_GNSS_AUTONOMOUS (0x0409)
#define RADIOLIB_LR11X0_CMD_GNSS_ASSISTED (0x040A)
#define RADIOLIB_LR11X0_CMD_GNSS_SCAN (0x040B)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_RESULT_SIZE (0x040C)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_RESULTS (0x040D)
#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE (0x040E)
#define RADIOLIB_LR11X0_CMD_GNSS_SET_ASSISTANCE_POSITION (0x0410)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_ASSISTANCE_POSITION (0x0411)
#define RADIOLIB_LR11X0_CMD_GNSS_PUSH_SOLVER_MSG (0x0414)
@ -119,10 +124,26 @@
#define RADIOLIB_LR11X0_CMD_GNSS_GET_NB_SV_DETECTED (0x0417)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_DETECTED (0x0418)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_CONSUMPTION (0x0419)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_RESULT_SIZE (0x040C)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_RESULTS (0x040D)
#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_FULL_UPDATE (0x040E)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_VISIBLE (0x041F)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_LAST_SCAN_MODE_LAUNCHED (0x0426)
#define RADIOLIB_LR11X0_CMD_GNSS_FETCH_TIME (0x0432)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_TIME (0x0434)
#define RADIOLIB_LR11X0_CMD_GNSS_RESET_TIME (0x0435)
#define RADIOLIB_LR11X0_CMD_GNSS_RESET_POSITION (0x0437)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_DEMOD_STATUS (0x0439)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_CUMUL_TIMING (0x044A)
#define RADIOLIB_LR11X0_CMD_GNSS_SET_TIME (0x044B)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_DOPPLER_SOLVER_RES (0x044F)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_DELAY_RESET_AP (0x0453)
#define RADIOLIB_LR11X0_CMD_GNSS_ALMANAC_UPDATE_FROM_SAT (0x0455)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_STATUS (0x0457)
#define RADIOLIB_LR11X0_CMD_GNSS_CONFIG_ALMANAC_UPDATE_PERIOD (0x0463)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_ALMANAC_UPDATE_PERIOD (0x0464)
#define RADIOLIB_LR11X0_CMD_GNSS_CONFIG_DELAY_RESET_AP (0x0465)
#define RADIOLIB_LR11X0_CMD_GNSS_GET_SV_WARM_START (0x0466)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_WN_ROLLOVER (0x0467)
#define RADIOLIB_LR11X0_CMD_GNSS_READ_WARM_START_STATUS (0x0469)
#define RADIOLIB_LR11X0_CMD_GNSS_WRITE_BIT_MASK_SAT_ACTIVATED (0x0472)
#define RADIOLIB_LR11X0_CMD_CRYPTO_SET_KEY (0x0502)
#define RADIOLIB_LR11X0_CMD_CRYPTO_DERIVE_KEY (0x0503)
#define RADIOLIB_LR11X0_CMD_CRYPTO_PROCESS_JOIN_ACCEPT (0x0504)
@ -147,6 +168,7 @@
// LR11X0 register map
#define RADIOLIB_LR11X0_REG_SF6_SX127X_COMPAT (0x00F20414)
#define RADIOLIB_LR11X0_REG_LORA_HIGH_POWER_FIX (0x00F30054)
// TODO add fix for br 600/1200 bps
// LR11X0 SPI command variables
@ -178,10 +200,10 @@
#define RADIOLIB_LR11X0_SPI_MAX_READ_WRITE_LEN (256) // 7 0 maximum length of read/write SPI payload in bytes
// RADIOLIB_LR11X0_CMD_GET_VERSION
#define RADIOLIB_LR11X0_HW_LR1110 (0x01UL << 0) // 7 0 HW version: LR1110
#define RADIOLIB_LR11X0_HW_LR1120 (0x02UL << 0) // 7 0 LR1120
#define RADIOLIB_LR11X0_HW_LR1121 (0x03UL << 0) // 7 0 LR1121
#define RADIOLIB_LR11X0_HW_BOOT (0xDFUL << 0) // 7 0 bootloader mode
#define RADIOLIB_LR11X0_DEVICE_LR1110 (0x01UL << 0) // 7 0 HW device: LR1110
#define RADIOLIB_LR11X0_DEVICE_LR1120 (0x02UL << 0) // 7 0 LR1120
#define RADIOLIB_LR11X0_DEVICE_LR1121 (0x03UL << 0) // 7 0 LR1121
#define RADIOLIB_LR11X0_DEVICE_BOOT (0xDFUL << 0) // 7 0 bootloader mode
// RADIOLIB_LR11X0_CMD_GET_ERRORS
#define RADIOLIB_LR11X0_ERROR_STAT_LF_RC_CALIB_ERR (0x01UL << 0) // 15 0 error: low frequency RC not calibrated
@ -218,6 +240,11 @@
#define RADIOLIB_LR11X0_RFSW_DIO8_DISABLED (0x00UL << 3) // 4 0 DIO8 disabled (default)
#define RADIOLIB_LR11X0_RFSW_DIO10_ENABLED (0x01UL << 4) // 4 0 RF switch: DIO10 enabled
#define RADIOLIB_LR11X0_RFSW_DIO10_DISABLED (0x00UL << 4) // 4 0 DIO10 disabled (default)
#define RADIOLIB_LR11X0_DIO5 (0)
#define RADIOLIB_LR11X0_DIO6 (1)
#define RADIOLIB_LR11X0_DIO7 (2)
#define RADIOLIB_LR11X0_DIO8 (3)
#define RADIOLIB_LR11X0_DIO10 (4)
// RADIOLIB_LR11X0_CMD_SET_DIO_IRQ_PARAMS
#define RADIOLIB_LR11X0_IRQ_TX_DONE (0x01UL << 2) // 31 0 interrupt: packet transmitted
@ -455,6 +482,10 @@
#define RADIOLIB_LR11X0_LR_FHSS_BW_773_44 (0x07UL << 0) // 7 0 773.44 kHz
#define RADIOLIB_LR11X0_LR_FHSS_BW_1523_4 (0x08UL << 0) // 7 0 1523.4 kHz
#define RADIOLIB_LR11X0_LR_FHSS_BW_1574_2 (0x09UL << 0) // 7 0 1574.2 kHz
#define RADIOLIB_LR11X0_LR_FHSS_HEADER_BITS (114) // 7 0 LR FHSS packet bit widths: header
#define RADIOLIB_LR11X0_LR_FHSS_FRAG_BITS (48) // 7 0 payload fragment
#define RADIOLIB_LR11X0_LR_FHSS_BLOCK_PREAMBLE_BITS (2) // 7 0 block preamble
#define RADIOLIB_LR11X0_LR_FHSS_BLOCK_BITS (RADIOLIB_LR11X0_LR_FHSS_FRAG_BITS + RADIOLIB_LR11X0_LR_FHSS_BLOCK_PREAMBLE_BITS)
// RADIOLIB_LR11X0_CMD_GET_LORA_RX_HEADER_INFOS
#define RADIOLIB_LR11X0_LAST_HEADER_CRC_ENABLED (0x01UL << 4) // 4 4 last header CRC: enabled
@ -639,6 +670,36 @@ struct LR11x0WifiResultExtended_t: public LR11x0WifiResultFull_t {
bool fcsCheckOk;
};
/*!
\struct LR11x0VersionInfo_t
\brief Structure to report information about versions of the LR11x0 hardware and firmware.
*/
struct LR11x0VersionInfo_t {
/*! \brief Hardware revision. */
uint8_t hardware;
/*! \brief Which device this is - one of RADIOLIB_LR11X0_DEVICE_* macros. */
uint8_t device;
/*! \brief Major revision of the base firmware. */
uint8_t fwMajor;
/*! \brief Minor revision of the base firmware. */
uint8_t fwMinor;
/*! \brief Major revision of the WiFi firmware. */
uint8_t fwMajorWiFi;
/*! \brief Minor revision of the WiFi firmware. */
uint8_t fwMinorWiFi;
/*! \brief Revision of the GNSS firmware. */
uint8_t fwGNSS;
/*! \brief Almanac revision of the GNSS firmware. */
uint8_t almanacGNSS;
};
/*!
\class LR11x0
\brief Base class for %LR11x0 series. All derived classes for %LR11x0 (e.g. LR1110 or LR1120) inherit from this base class.
@ -658,6 +719,29 @@ class LR11x0: public PhysicalLayer {
*/
explicit LR11x0(Module* mod);
/*!
\brief Custom operation modes for LR11x0.
Needed because LR11x0 has several modems (sub-GHz, 2.4 GHz etc.) in one package
*/
enum OpMode_t {
/*! End of table marker, use \ref END_OF_MODE_TABLE constant instead */
MODE_END_OF_TABLE = Module::MODE_END_OF_TABLE,
/*! Standby/idle mode */
MODE_STBY = Module::MODE_IDLE,
/*! Receive mode */
MODE_RX = Module::MODE_RX,
/*! Low power transmission mode */
MODE_TX = Module::MODE_TX,
/*! High power transmission mode */
MODE_TX_HP,
/*! High frequency transmission mode */
MODE_TX_HF,
/*! GNSS scanning mode */
MODE_GNSS,
/*! WiFi scanning mode */
MODE_WIFI,
};
/*!
\brief Whether the module has an XTAL (true) or TCXO (false). Defaults to false.
*/
@ -766,7 +850,14 @@ class LR11x0: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t standby(uint8_t mode, bool wakeup = true);
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
Overload with warm start enabled for PhysicalLayer compatibility.
\returns \ref status_codes
*/
int16_t sleep() override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
\param retainConfig Set to true to retain configuration of the currently active modem ("warm start")
@ -774,7 +865,7 @@ class LR11x0: public PhysicalLayer {
\param sleepTime Sleep duration (enables automatic wakeup), in multiples of 30.52 us. Ignored if set to 0.
\returns \ref status_codes
*/
int16_t sleep(bool retainConfig = true, uint32_t sleepTime = 0);
int16_t sleep(bool retainConfig, uint32_t sleepTime);
// interrupt methods
@ -1188,6 +1279,28 @@ class LR11x0: public PhysicalLayer {
*/
float getDataRate() const;
/*!
\brief Set regulator mode to LDO.
\returns \ref status_codes
*/
int16_t setRegulatorLDO();
/*!
\brief Set regulator mode to DC-DC.
\returns \ref status_codes
*/
int16_t setRegulatorDCDC();
/*!
\brief Enables or disables Rx Boosted Gain mode (additional Rx gain for increased power consumption).
\param en True for Rx Boosted Gain, false for Rx Power Saving Gain
\returns \ref status_codes
*/
int16_t setRxBoostedGainMode(bool en);
/*! \copydoc Module::setRfSwitchTable */
void setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
/*!
\brief Sets LR-FHSS configuration.
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values.
@ -1260,7 +1373,26 @@ class LR11x0: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t wifiScan(uint8_t wifiType, uint8_t* count, uint8_t mode = RADIOLIB_LR11X0_WIFI_ACQ_MODE_FULL_BEACON, uint16_t chanMask = RADIOLIB_LR11X0_WIFI_ALL_CHANNELS, uint8_t numScans = 16, uint16_t timeout = 100);
/*!
\brief Retrieve LR11x0 hardware, device and firmware version information.
\param info Pointer to LR11x0VersionInfo_t structure to populate.
\returns \ref status_codes
*/
int16_t getVersionInfo(LR11x0VersionInfo_t* info);
/*!
\brief Method to upload new firmware image to the device.
The device will be automatically erased, a new firmware will be uploaded,
written to flash and executed.
\param image Pointer to the image to upload.
\param size Size of the image in 32-bit words.
\param nonvolatile Set to true when the image is saved in non-volatile memory of the host processor,
or to false when the patch is in its RAM. Defaults to true.
\returns \ref status_codes
*/
int16_t updateFirmware(const uint32_t* image, size_t size, bool nonvolatile = true);
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
protected:
#endif
@ -1338,8 +1470,8 @@ class LR11x0: public PhysicalLayer {
int16_t setRangingTxRxDelay(uint32_t delay);
int16_t setGfskCrcParams(uint32_t init, uint32_t poly);
int16_t setGfskWhitParams(uint16_t seed);
int16_t setRxBoosted(bool en);
int16_t setRangingParameter(uint8_t symbolNum);
int16_t setRssiCalibration(const int8_t* tune, int16_t gainOffset);
int16_t setLoRaSyncWord(uint8_t sync);
int16_t lrFhssBuildFrame(uint8_t hdrCount, uint8_t cr, uint8_t grid, bool hop, uint8_t bw, uint16_t hopSeq, int8_t devOffset, uint8_t* payload, size_t len);
int16_t lrFhssSetSyncWord(uint32_t sync);
@ -1382,6 +1514,26 @@ class LR11x0: public PhysicalLayer {
int16_t gnssAlmanacFullUpdateHeader(uint16_t date, uint32_t globalCrc);
int16_t gnssAlmanacFullUpdateSV(uint8_t svn, uint8_t* svnAlmanac);
int16_t gnssGetSvVisible(uint32_t time, float lat, float lon, uint8_t constellation, uint8_t* nbSv);
int16_t gnssScan(uint8_t effort, uint8_t resMask, uint8_t nbSvMax);
int16_t gnssReadLastScanModeLaunched(uint8_t* lastScanMode);
int16_t gnssFetchTime(uint8_t effort, uint8_t opt);
int16_t gnssReadTime(uint8_t* err, uint32_t* time, uint32_t* nbUs, uint32_t* timeAccuracy);
int16_t gnssResetTime(void);
int16_t gnssResetPosition(void);
int16_t gnssReadDemodStatus(int8_t* status, uint8_t* info);
int16_t gnssReadCumulTiming(uint32_t* timing, uint8_t* constDemod);
int16_t gnssSetTime(uint32_t time, uint16_t accuracy);
int16_t gnssReadDopplerSolverRes(uint8_t* error, uint8_t* nbSvUsed, float* lat, float* lon, uint16_t* accuracy, uint16_t* xtal, float* latFilt, float* lonFilt, uint16_t* accuracyFilt, uint16_t* xtalFilt);
int16_t gnssReadDelayResetAP(uint32_t* delay);
int16_t gnssAlmanacUpdateFromSat(uint8_t effort, uint8_t bitMask);
int16_t gnssReadAlmanacStatus(uint8_t* status);
int16_t gnssConfigAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t period);
int16_t gnssReadAlmanacUpdatePeriod(uint8_t bitMask, uint8_t svType, uint16_t* period);
int16_t gnssConfigDelayResetAP(uint32_t delay);
int16_t gnssGetSvWarmStart(uint8_t bitMask, uint8_t* sv, uint8_t nbVisSat);
int16_t gnssReadWNRollover(uint8_t* status, uint8_t* rollover);
int16_t gnssReadWarmStartStatus(uint8_t bitMask, uint8_t* nbVisSat, uint32_t* timeElapsed);
int16_t gnssWriteBitMaskSatActivated(uint8_t bitMask, uint32_t* bitMaskActivated0, uint32_t* bitMaskActivated1);
int16_t cryptoSetKey(uint8_t keyId, uint8_t* key);
int16_t cryptoDeriveKey(uint8_t srcKeyId, uint8_t dstKeyId, uint8_t* key);
@ -1395,11 +1547,11 @@ class LR11x0: public PhysicalLayer {
int16_t cryptoRestoreFromFlash(void);
int16_t cryptoSetParam(uint8_t id, uint32_t value);
int16_t cryptoGetParam(uint8_t id, uint32_t* value);
int16_t cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len);
int16_t cryptoCheckEncryptedFirmwareImage(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile);
int16_t cryptoCheckEncryptedFirmwareImageResult(bool* result);
int16_t bootEraseFlash(void);
int16_t bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len);
int16_t bootWriteFlashEncrypted(uint32_t offset, uint32_t* data, size_t len, bool nonvolatile);
int16_t bootReboot(bool stay);
int16_t bootGetPin(uint8_t* pin);
int16_t bootGetChipEui(uint8_t* eui);
@ -1449,7 +1601,7 @@ class LR11x0: public PhysicalLayer {
// common methods to avoid some copy-paste
int16_t bleBeaconCommon(uint16_t cmd, uint8_t chan, uint8_t* payload, size_t len);
int16_t writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len);
int16_t writeCommon(uint16_t cmd, uint32_t addrOffset, const uint32_t* data, size_t len, bool nonvolatile);
int16_t cryptoCommon(uint16_t cmd, uint8_t keyId, uint8_t* dataIn, size_t len, uint8_t* dataOut);
};

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -93,9 +93,8 @@ int16_t STM32WLx::setOutputPower(int8_t power) {
state = SX126x::fixPaClamping(use_hp);
RADIOLIB_ASSERT(state);
// set output power
/// \todo power ramp time configuration
state = SX126x::setTxParams(power);
// set output power with default 200us ramp
state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
RADIOLIB_ASSERT(state);
// restore OCP configuration

View file

@ -442,6 +442,11 @@ int16_t SX126x::scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin)
return(getChannelScanResult());
}
int16_t SX126x::sleep() {
return(SX126x::sleep(true));
}
int16_t SX126x::sleep(bool retainConfig) {
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_IDLE);
@ -1843,6 +1848,8 @@ int16_t SX126x::setRfFrequency(uint32_t frf) {
int16_t SX126x::calibrateImageRejection(float freqMin, float freqMax) {
// calculate the calibration coefficients and calibrate image
uint8_t data[] = { (uint8_t)floor((freqMin - 1.0f) / 4.0f), (uint8_t)ceil((freqMax + 1.0f) / 4.0f) };
data[0] = (data[0] % 2) ? data[0] : data[0] - 1;
data[1] = (data[1] % 2) ? data[1] : data[1] + 1;
return(this->calibrateImage(data));
}

View file

@ -545,6 +545,13 @@ class SX126x: public PhysicalLayer {
\returns \ref status_codes
*/
int16_t scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin);
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
Overload with warm start enabled for PhysicalLayer compatibility.
\returns \ref status_codes
*/
int16_t sleep() override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
@ -552,7 +559,7 @@ class SX126x: public PhysicalLayer {
or to false to discard current configuration ("cold start"). Defaults to true.
\returns \ref status_codes
*/
int16_t sleep(bool retainConfig = true);
int16_t sleep(bool retainConfig);
/*!
\brief Sets the module to standby mode (overload for PhysicalLayer compatibility, uses 13 MHz RC oscillator).

View file

@ -424,6 +424,10 @@ int16_t SX128x::scanChannel() {
return(getChannelScanResult());
}
int16_t SX128x::sleep() {
return(SX128x::sleep(true));
}
int16_t SX128x::sleep(bool retainConfig) {
// set RF switch (if present)
this->mod->setRfSwitchState(Module::MODE_IDLE);
@ -782,7 +786,6 @@ int16_t SX128x::setCodingRate(uint8_t cr, bool longInterleaving) {
int16_t SX128x::setOutputPower(int8_t pwr) {
// check if power value is configurable
int16_t state = checkOutputPower(pwr, NULL);
Serial.println(state);
RADIOLIB_ASSERT(state);
this->power = pwr + 18;

View file

@ -457,13 +457,20 @@ class SX128x: public PhysicalLayer {
*/
int16_t scanChannel() override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
Overload for PhysicalLayer compatibility.
\returns \ref status_codes
*/
int16_t sleep() override;
/*!
\brief Sets the module to sleep mode. To wake the device up, call standby().
\param retainConfig Set to true to retain configuration and data buffer or to false
to discard current configuration and data buffer. Defaults to true.
\returns \ref status_codes
*/
int16_t sleep(bool retainConfig = true);
int16_t sleep(bool retainConfig);
/*!
\brief Sets the module to standby mode (overload for PhysicalLayer compatibility, uses 13 MHz RC oscillator).
@ -623,11 +630,11 @@ class SX128x: public PhysicalLayer {
/*!
\brief Check if output power is configurable.
\param power Output power in dBm.
\param pwr 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;
int16_t checkOutputPower(int8_t pwr, int8_t* clipped) override;
/*!
\brief Sets preamble length for currently active modem. Allowed values range from 1 to 65535.

View file

@ -59,8 +59,8 @@ AX25Frame::AX25Frame(const AX25Frame& frame)
infoLen(frame.infoLen),
rcvSeqNumber(frame.rcvSeqNumber),
sendSeqNumber(frame.sendSeqNumber) {
strncpy(this->destCallsign, frame.destCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN);
strncpy(this->srcCallsign, frame.srcCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN);
strncpy(this->destCallsign, frame.destCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1);
strncpy(this->srcCallsign, frame.srcCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1);
if(frame.infoLen) {
#if !RADIOLIB_STATIC_ONLY
@ -204,7 +204,7 @@ AX25Client::AX25Client(const AX25Client& ax25)
: phyLayer(ax25.phyLayer),
sourceSSID(ax25.sourceSSID),
preambleLen(ax25.preambleLen) {
strncpy(sourceCallsign, ax25.sourceCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN);
strncpy(sourceCallsign, ax25.sourceCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1);
#if !RADIOLIB_EXCLUDE_AFSK
if(ax25.bellModem) {
this->audio = ax25.audio;
@ -214,16 +214,18 @@ AX25Client::AX25Client(const AX25Client& ax25)
}
AX25Client& AX25Client::operator=(const AX25Client& ax25) {
this->phyLayer = ax25.phyLayer;
this->sourceSSID = ax25.sourceSSID;
this->preambleLen = ax25.preambleLen;
strncpy(sourceCallsign, ax25.sourceCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN);
#if !RADIOLIB_EXCLUDE_AFSK
if(ax25.bellModem) {
this->audio = ax25.audio;
this->bellModem = new BellClient(ax25.audio);
if(&ax25 != this) {
this->phyLayer = ax25.phyLayer;
this->sourceSSID = ax25.sourceSSID;
this->preambleLen = ax25.preambleLen;
strncpy(sourceCallsign, ax25.sourceCallsign, RADIOLIB_AX25_MAX_CALLSIGN_LEN + 1);
#if !RADIOLIB_EXCLUDE_AFSK
if(ax25.bellModem) {
this->audio = ax25.audio;
this->bellModem = new BellClient(ax25.audio);
}
#endif
}
#endif
return(*this);
}

View file

@ -22,9 +22,11 @@ ExternalRadio::ExternalRadio(const ExternalRadio& ext) : PhysicalLayer(1, 0) {
}
ExternalRadio& ExternalRadio::operator=(const ExternalRadio& ext) {
this->prevFrf = ext.prevFrf;
if(ext.mod) {
this->mod = new Module(ext.mod->hal, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, ext.mod->getGpio());
if(&ext != this) {
this->prevFrf = ext.prevFrf;
if(ext.mod) {
this->mod = new Module(ext.mod->hal, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, ext.mod->getGpio());
}
}
return(*this);
}

File diff suppressed because it is too large Load diff

View file

@ -1,200 +1,207 @@
#if !defined(_RADIOLIB_LW_H) && !RADIOLIB_EXCLUDE_LORAWAN
#define _RADIOLIB_LW_H
#if !defined(_RADIOLIB_LORAWAN_H) && !RADIOLIB_EXCLUDE_LORAWAN
#define _RADIOLIB_LORAWAN_H
#include "../../TypeDef.h"
#include "../PhysicalLayer/PhysicalLayer.h"
#include "../../utils/Cryptography.h"
// activation mode
#define RADIOLIB_LW_MODE_OTAA (0x07AA)
#define RADIOLIB_LW_MODE_ABP (0x0AB9)
#define RADIOLIB_LW_MODE_NONE (0x0000)
#define RADIOLIB_LORAWAN_MODE_OTAA (0x07AA)
#define RADIOLIB_LORAWAN_MODE_ABP (0x0AB9)
#define RADIOLIB_LORAWAN_MODE_NONE (0x0000)
// operation mode
#define RADIOLIB_LW_CLASS_A (0x0A)
#define RADIOLIB_LW_CLASS_B (0x0B)
#define RADIOLIB_LW_CLASS_C (0x0C)
#define RADIOLIB_LORAWAN_CLASS_A (0x0A)
#define RADIOLIB_LORAWAN_CLASS_B (0x0B)
#define RADIOLIB_LORAWAN_CLASS_C (0x0C)
// modulation type
#define RADIOLIB_LORAWAN_MODULATION_LORA (0)
#define RADIOLIB_LORAWAN_MODULATION_GFSK (1)
#define RADIOLIB_LORAWAN_MODULATION_LR_FHSS (2)
// preamble format
#define RADIOLIB_LW_LORA_SYNC_WORD (0x34)
#define RADIOLIB_LW_LORA_PREAMBLE_LEN (8)
#define RADIOLIB_LW_GFSK_SYNC_WORD (0xC194C1)
#define RADIOLIB_LW_GFSK_PREAMBLE_LEN (5)
#define RADIOLIB_LORAWAN_LORA_SYNC_WORD (0x34)
#define RADIOLIB_LORAWAN_LORA_PREAMBLE_LEN (8)
#define RADIOLIB_LORAWAN_GFSK_SYNC_WORD (0xC194C1)
#define RADIOLIB_LORAWAN_GFSK_PREAMBLE_LEN (5)
#define RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD (0x2C0F7995)
// MAC header field encoding MSB LSB DESCRIPTION
#define RADIOLIB_LW_MHDR_MTYPE_JOIN_REQUEST (0x00 << 5) // 7 5 message type: join request
#define RADIOLIB_LW_MHDR_MTYPE_JOIN_ACCEPT (0x01 << 5) // 7 5 join accept
#define RADIOLIB_LW_MHDR_MTYPE_UNCONF_DATA_UP (0x02 << 5) // 7 5 unconfirmed data up
#define RADIOLIB_LW_MHDR_MTYPE_UNCONF_DATA_DOWN (0x03 << 5) // 7 5 unconfirmed data down
#define RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_UP (0x04 << 5) // 7 5 confirmed data up
#define RADIOLIB_LW_MHDR_MTYPE_CONF_DATA_DOWN (0x05 << 5) // 7 5 confirmed data down
#define RADIOLIB_LW_MHDR_MTYPE_PROPRIETARY (0x07 << 5) // 7 5 proprietary
#define RADIOLIB_LW_MHDR_MTYPE_MASK (0x07 << 5) // 7 5 bitmask of all possible options
#define RADIOLIB_LW_MHDR_MAJOR_R1 (0x00 << 0) // 1 0 major version: LoRaWAN R1
#define RADIOLIB_LORAWAN_MHDR_MTYPE_JOIN_REQUEST (0x00 << 5) // 7 5 message type: join request
#define RADIOLIB_LORAWAN_MHDR_MTYPE_JOIN_ACCEPT (0x01 << 5) // 7 5 join accept
#define RADIOLIB_LORAWAN_MHDR_MTYPE_UNCONF_DATA_UP (0x02 << 5) // 7 5 unconfirmed data up
#define RADIOLIB_LORAWAN_MHDR_MTYPE_UNCONF_DATA_DOWN (0x03 << 5) // 7 5 unconfirmed data down
#define RADIOLIB_LORAWAN_MHDR_MTYPE_CONF_DATA_UP (0x04 << 5) // 7 5 confirmed data up
#define RADIOLIB_LORAWAN_MHDR_MTYPE_CONF_DATA_DOWN (0x05 << 5) // 7 5 confirmed data down
#define RADIOLIB_LORAWAN_MHDR_MTYPE_PROPRIETARY (0x07 << 5) // 7 5 proprietary
#define RADIOLIB_LORAWAN_MHDR_MTYPE_MASK (0x07 << 5) // 7 5 bitmask of all possible options
#define RADIOLIB_LORAWAN_MHDR_MAJOR_R1 (0x00 << 0) // 1 0 major version: LoRaWAN R1
// frame control field encoding
#define RADIOLIB_LW_FCTRL_ADR_ENABLED (0x01 << 7) // 7 7 adaptive data rate: enabled
#define RADIOLIB_LW_FCTRL_ADR_DISABLED (0x00 << 7) // 7 7 disabled
#define RADIOLIB_LW_FCTRL_ADR_ACK_REQ (0x01 << 6) // 6 6 adaptive data rate ACK request
#define RADIOLIB_LW_FCTRL_ACK (0x01 << 5) // 5 5 confirmed message acknowledge
#define RADIOLIB_LW_FCTRL_FRAME_PENDING (0x01 << 4) // 4 4 downlink frame is pending
#define RADIOLIB_LORAWAN_FCTRL_ADR_ENABLED (0x01 << 7) // 7 7 adaptive data rate: enabled
#define RADIOLIB_LORAWAN_FCTRL_ADR_DISABLED (0x00 << 7) // 7 7 disabled
#define RADIOLIB_LORAWAN_FCTRL_ADR_ACK_REQ (0x01 << 6) // 6 6 adaptive data rate ACK request
#define RADIOLIB_LORAWAN_FCTRL_ACK (0x01 << 5) // 5 5 confirmed message acknowledge
#define RADIOLIB_LORAWAN_FCTRL_FRAME_PENDING (0x01 << 4) // 4 4 downlink frame is pending
// fPort field
#define RADIOLIB_LW_FPORT_MAC_COMMAND (0x00 << 0) // 7 0 payload contains MAC commands only
#define RADIOLIB_LW_FPORT_RESERVED (0xE0 << 0) // 7 0 reserved fPort values
#define RADIOLIB_LORAWAN_FPORT_MAC_COMMAND (0x00 << 0) // 7 0 payload contains MAC commands only
#define RADIOLIB_LORAWAN_FPORT_TS009 (0xE0 << 0) // 7 0 fPort used for TS009 testing
#define RADIOLIB_LORAWAN_FPORT_RESERVED (0xE0 << 0) // 7 0 fPort values equal to and larger than this are reserved
// MAC commands - only those sent from end-device to gateway
#define RADIOLIB_LW_LINK_CHECK_REQ (0x02 << 0) // 7 0 MAC command: request to check connectivity to network
#define RADIOLIB_LW_LINK_ADR_ANS (0x03 << 0) // 7 0 answer to ADR change
#define RADIOLIB_LW_DUTY_CYCLE_ANS (0x04 << 0) // 7 0 answer to duty cycle change
#define RADIOLIB_LW_RX_PARAM_SETUP_ANS (0x05 << 0) // 7 0 answer to reception slot setup request
#define RADIOLIB_LW_DEV_STATUS_ANS (0x06 << 0) // 7 0 device status information
#define RADIOLIB_LW_NEW_CHANNEL_ANS (0x07 << 0) // 7 0 acknowledges change of a radio channel
#define RADIOLIB_LW_RX_TIMING_SETUP_ANS (0x08 << 0) // 7 0 acknowledges change of a reception slots timing
#define RADIOLIB_LORAWAN_LINK_CHECK_REQ (0x02 << 0) // 7 0 MAC command: request to check connectivity to network
#define RADIOLIB_LORAWAN_LINK_ADR_ANS (0x03 << 0) // 7 0 answer to ADR change
#define RADIOLIB_LORAWAN_DUTY_CYCLE_ANS (0x04 << 0) // 7 0 answer to duty cycle change
#define RADIOLIB_LORAWAN_RX_PARAM_SETUP_ANS (0x05 << 0) // 7 0 answer to reception slot setup request
#define RADIOLIB_LORAWAN_DEV_STATUS_ANS (0x06 << 0) // 7 0 device status information
#define RADIOLIB_LORAWAN_NEW_CHANNEL_ANS (0x07 << 0) // 7 0 acknowledges change of a radio channel
#define RADIOLIB_LORAWAN_RX_TIMING_SETUP_ANS (0x08 << 0) // 7 0 acknowledges change of a reception slots timing
#define RADIOLIB_LW_NOPTS_LEN (8)
#define RADIOLIB_LORAWAN_NOPTS_LEN (8)
// data rate encoding
#define RADIOLIB_LW_DATA_RATE_FSK_50_K (0x01 << 7) // 7 7 FSK @ 50 kbps
#define RADIOLIB_LW_DATA_RATE_SF_12 (0x06 << 4) // 6 4 LoRa spreading factor: SF12
#define RADIOLIB_LW_DATA_RATE_SF_11 (0x05 << 4) // 6 4 SF11
#define RADIOLIB_LW_DATA_RATE_SF_10 (0x04 << 4) // 6 4 SF10
#define RADIOLIB_LW_DATA_RATE_SF_9 (0x03 << 4) // 6 4 SF9
#define RADIOLIB_LW_DATA_RATE_SF_8 (0x02 << 4) // 6 4 SF8
#define RADIOLIB_LW_DATA_RATE_SF_7 (0x01 << 4) // 6 4 SF7
#define RADIOLIB_LW_DATA_RATE_BW_500_KHZ (0x00 << 2) // 3 2 LoRa bandwidth: 500 kHz
#define RADIOLIB_LW_DATA_RATE_BW_250_KHZ (0x01 << 2) // 3 2 250 kHz
#define RADIOLIB_LW_DATA_RATE_BW_125_KHZ (0x02 << 2) // 3 2 125 kHz
#define RADIOLIB_LW_DATA_RATE_BW_RESERVED (0x03 << 2) // 3 2 reserved value
#define RADIOLIB_LW_DATA_RATE_CR_4_5 (0x00 << 0) // 1 0 LoRa coding rate: 4/5
#define RADIOLIB_LW_DATA_RATE_CR_4_6 (0x01 << 0) // 1 0 4/6
#define RADIOLIB_LW_DATA_RATE_CR_4_7 (0x02 << 0) // 1 0 4/7
#define RADIOLIB_LW_DATA_RATE_CR_4_8 (0x03 << 0) // 1 0 4/8
#define RADIOLIB_LW_DATA_RATE_UNUSED (0xFF << 0) // 7 0 unused data rate
#define RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K (0x01 << 7) // 7 7 FSK @ 50 kbps
#define RADIOLIB_LORAWAN_DATA_RATE_SF_12 (0x06 << 4) // 6 4 LoRa spreading factor: SF12
#define RADIOLIB_LORAWAN_DATA_RATE_SF_11 (0x05 << 4) // 6 4 SF11
#define RADIOLIB_LORAWAN_DATA_RATE_SF_10 (0x04 << 4) // 6 4 SF10
#define RADIOLIB_LORAWAN_DATA_RATE_SF_9 (0x03 << 4) // 6 4 SF9
#define RADIOLIB_LORAWAN_DATA_RATE_SF_8 (0x02 << 4) // 6 4 SF8
#define RADIOLIB_LORAWAN_DATA_RATE_SF_7 (0x01 << 4) // 6 4 SF7
#define RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ (0x00 << 2) // 3 2 LoRa bandwidth: 500 kHz
#define RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ (0x01 << 2) // 3 2 250 kHz
#define RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ (0x02 << 2) // 3 2 125 kHz
#define RADIOLIB_LORAWAN_DATA_RATE_BW_RESERVED (0x03 << 2) // 3 2 reserved value
#define RADIOLIB_LORAWAN_DATA_RATE_CR_4_5 (0x00 << 0) // 1 0 LoRa coding rate: 4/5
#define RADIOLIB_LORAWAN_DATA_RATE_CR_4_6 (0x01 << 0) // 1 0 4/6
#define RADIOLIB_LORAWAN_DATA_RATE_CR_4_7 (0x02 << 0) // 1 0 4/7
#define RADIOLIB_LORAWAN_DATA_RATE_CR_4_8 (0x03 << 0) // 1 0 4/8
#define RADIOLIB_LORAWAN_DATA_RATE_UNUSED (0xFF << 0) // 7 0 unused data rate
#define RADIOLIB_LW_CHANNEL_DIR_UPLINK (0x00 << 0)
#define RADIOLIB_LW_CHANNEL_DIR_DOWNLINK (0x01 << 0)
#define RADIOLIB_LW_CHANNEL_DIR_BOTH (0x02 << 0)
#define RADIOLIB_LW_CHANNEL_DIR_NONE (0x03 << 0)
#define RADIOLIB_LW_BAND_DYNAMIC (0)
#define RADIOLIB_LW_BAND_FIXED (1)
#define RADIOLIB_LW_CHANNEL_NUM_DATARATES (15)
#define RADIOLIB_LW_CHANNEL_INDEX_NONE (0xFF >> 0)
#define RADIOLIB_LORAWAN_CHANNEL_DIR_UPLINK (0x00 << 0)
#define RADIOLIB_LORAWAN_CHANNEL_DIR_DOWNLINK (0x01 << 0)
#define RADIOLIB_LORAWAN_CHANNEL_DIR_BOTH (0x02 << 0)
#define RADIOLIB_LORAWAN_CHANNEL_DIR_NONE (0x03 << 0)
#define RADIOLIB_LORAWAN_BAND_DYNAMIC (0)
#define RADIOLIB_LORAWAN_BAND_FIXED (1)
#define RADIOLIB_LORAWAN_CHANNEL_NUM_DATARATES (15)
#define RADIOLIB_LORAWAN_CHANNEL_INDEX_NONE (0xFF >> 0)
// recommended default settings
#define RADIOLIB_LW_RECEIVE_DELAY_1_MS (1000)
#define RADIOLIB_LW_RECEIVE_DELAY_2_MS ((RADIOLIB_LW_RECEIVE_DELAY_1_MS) + 1000)
#define RADIOLIB_LW_RX1_DR_OFFSET (0)
#define RADIOLIB_LW_JOIN_ACCEPT_DELAY_1_MS (5000)
#define RADIOLIB_LW_JOIN_ACCEPT_DELAY_2_MS (6000)
#define RADIOLIB_LW_MAX_FCNT_GAP (16384)
#define RADIOLIB_LW_ADR_ACK_LIMIT_EXP (0x06)
#define RADIOLIB_LW_ADR_ACK_DELAY_EXP (0x05)
#define RADIOLIB_LW_RETRANSMIT_TIMEOUT_MIN_MS (1000)
#define RADIOLIB_LW_RETRANSMIT_TIMEOUT_MAX_MS (3000)
#define RADIOLIB_LW_POWER_STEP_SIZE_DBM (-2)
#define RADIOLIB_LW_REJOIN_MAX_COUNT_N (10) // send rejoin request 16384 uplinks
#define RADIOLIB_LW_REJOIN_MAX_TIME_N (15) // once every year, not actually implemented
#define RADIOLIB_LORAWAN_RECEIVE_DELAY_1_MS (1000)
#define RADIOLIB_LORAWAN_RECEIVE_DELAY_2_MS ((RADIOLIB_LORAWAN_RECEIVE_DELAY_1_MS) + 1000)
#define RADIOLIB_LORAWAN_RX1_DR_OFFSET (0)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_1_MS (5000)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_DELAY_2_MS (6000)
#define RADIOLIB_LORAWAN_MAX_FCNT_GAP (16384)
#define RADIOLIB_LORAWAN_ADR_ACK_LIMIT_EXP (0x06)
#define RADIOLIB_LORAWAN_ADR_ACK_DELAY_EXP (0x05)
#define RADIOLIB_LORAWAN_RETRANSMIT_TIMEOUT_MIN_MS (1000)
#define RADIOLIB_LORAWAN_RETRANSMIT_TIMEOUT_MAX_MS (3000)
#define RADIOLIB_LORAWAN_POWER_STEP_SIZE_DBM (-2)
#define RADIOLIB_LORAWAN_REJOIN_MAX_COUNT_N (10) // send rejoin request 16384 uplinks
#define RADIOLIB_LORAWAN_REJOIN_MAX_TIME_N (15) // once every year, not actually implemented
// join request message layout
#define RADIOLIB_LW_JOIN_REQUEST_LEN (23)
#define RADIOLIB_LW_JOIN_REQUEST_JOIN_EUI_POS (1)
#define RADIOLIB_LW_JOIN_REQUEST_DEV_EUI_POS (9)
#define RADIOLIB_LW_JOIN_REQUEST_DEV_NONCE_POS (17)
#define RADIOLIB_LW_JOIN_REQUEST_TYPE (0xFF)
#define RADIOLIB_LW_JOIN_REQUEST_TYPE_0 (0x00)
#define RADIOLIB_LW_JOIN_REQUEST_TYPE_1 (0x01)
#define RADIOLIB_LW_JOIN_REQUEST_TYPE_2 (0x02)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_LEN (23)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_JOIN_EUI_POS (1)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_DEV_EUI_POS (9)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_DEV_NONCE_POS (17)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_TYPE (0xFF)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_TYPE_0 (0x00)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_TYPE_1 (0x01)
#define RADIOLIB_LORAWAN_JOIN_REQUEST_TYPE_2 (0x02)
// join accept message layout
#define RADIOLIB_LW_JOIN_ACCEPT_MAX_LEN (33)
#define RADIOLIB_LW_JOIN_ACCEPT_JOIN_NONCE_POS (1)
#define RADIOLIB_LW_JOIN_ACCEPT_HOME_NET_ID_POS (4)
#define RADIOLIB_LW_JOIN_ACCEPT_DEV_ADDR_POS (7)
#define RADIOLIB_LW_JOIN_ACCEPT_JOIN_EUI_POS (4)
#define RADIOLIB_LW_JOIN_ACCEPT_DL_SETTINGS_POS (11)
#define RADIOLIB_LW_JOIN_ACCEPT_RX_DELAY_POS (12)
#define RADIOLIB_LW_JOIN_ACCEPT_DEV_NONCE_POS (12)
#define RADIOLIB_LW_JOIN_ACCEPT_CFLIST_POS (13)
#define RADIOLIB_LW_JOIN_ACCEPT_CFLIST_LEN (16)
#define RADIOLIB_LW_JOIN_ACCEPT_CFLIST_TYPE_POS (RADIOLIB_LW_JOIN_ACCEPT_CFLIST_POS + RADIOLIB_LW_JOIN_ACCEPT_CFLIST_LEN - 1)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_MAX_LEN (33)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_JOIN_NONCE_POS (1)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_HOME_NET_ID_POS (4)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_ADDR_POS (7)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_JOIN_EUI_POS (4)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_DL_SETTINGS_POS (11)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_RX_DELAY_POS (12)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_DEV_NONCE_POS (12)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_CFLIST_POS (13)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_CFLIST_LEN (16)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_CFLIST_TYPE_POS (RADIOLIB_LORAWAN_JOIN_ACCEPT_CFLIST_POS + RADIOLIB_LORAWAN_JOIN_ACCEPT_CFLIST_LEN - 1)
// join accept message variables
#define RADIOLIB_LW_JOIN_ACCEPT_R_1_0 (0x00 << 7) // 7 7 LoRaWAN revision: 1.0
#define RADIOLIB_LW_JOIN_ACCEPT_R_1_1 (0x01 << 7) // 7 7 1.1
#define RADIOLIB_LW_JOIN_ACCEPT_F_NWK_S_INT_KEY (0x01)
#define RADIOLIB_LW_JOIN_ACCEPT_APP_S_KEY (0x02)
#define RADIOLIB_LW_JOIN_ACCEPT_S_NWK_S_INT_KEY (0x03)
#define RADIOLIB_LW_JOIN_ACCEPT_NWK_S_ENC_KEY (0x04)
#define RADIOLIB_LW_JOIN_ACCEPT_JS_ENC_KEY (0x05)
#define RADIOLIB_LW_JOIN_ACCEPT_JS_INT_KEY (0x06)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_R_1_0 (0x00 << 7) // 7 7 LoRaWAN revision: 1.0
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_R_1_1 (0x01 << 7) // 7 7 1.1
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_F_NWK_S_INT_KEY (0x01)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_APP_S_KEY (0x02)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_S_NWK_S_INT_KEY (0x03)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_NWK_S_ENC_KEY (0x04)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_JS_ENC_KEY (0x05)
#define RADIOLIB_LORAWAN_JOIN_ACCEPT_JS_INT_KEY (0x06)
// frame header layout
#define RADIOLIB_LW_FHDR_LEN_START_OFFS (16)
#define RADIOLIB_LW_FHDR_DEV_ADDR_POS (RADIOLIB_LW_FHDR_LEN_START_OFFS + 1)
#define RADIOLIB_LW_FHDR_FCTRL_POS (RADIOLIB_LW_FHDR_LEN_START_OFFS + 5)
#define RADIOLIB_LW_FHDR_FCNT_POS (RADIOLIB_LW_FHDR_LEN_START_OFFS + 6)
#define RADIOLIB_LW_FHDR_FOPTS_POS (RADIOLIB_LW_FHDR_LEN_START_OFFS + 8)
#define RADIOLIB_LW_FHDR_FOPTS_LEN_MASK (0x0F)
#define RADIOLIB_LW_FHDR_FOPTS_MAX_LEN (15)
#define RADIOLIB_LW_FHDR_FPORT_POS(FOPTS) (RADIOLIB_LW_FHDR_LEN_START_OFFS + 8 + (FOPTS))
#define RADIOLIB_LW_FRAME_PAYLOAD_POS(FOPTS) (RADIOLIB_LW_FHDR_LEN_START_OFFS + 9 + (FOPTS))
#define RADIOLIB_LW_FRAME_LEN(PAYLOAD, FOPTS) (16 + 13 + (PAYLOAD) + (FOPTS))
#define RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS (16)
#define RADIOLIB_LORAWAN_FHDR_DEV_ADDR_POS (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 1)
#define RADIOLIB_LORAWAN_FHDR_FCTRL_POS (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 5)
#define RADIOLIB_LORAWAN_FHDR_FCNT_POS (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 6)
#define RADIOLIB_LORAWAN_FHDR_FOPTS_POS (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 8)
#define RADIOLIB_LORAWAN_FHDR_FOPTS_LEN_MASK (0x0F)
#define RADIOLIB_LORAWAN_FHDR_FOPTS_MAX_LEN (15)
#define RADIOLIB_LORAWAN_FHDR_FPORT_POS(FOPTS) (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 8 + (FOPTS))
#define RADIOLIB_LORAWAN_FRAME_PAYLOAD_POS(FOPTS) (RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS + 9 + (FOPTS))
#define RADIOLIB_LORAWAN_FRAME_LEN(PAYLOAD, FOPTS) (16 + 13 + (PAYLOAD) + (FOPTS))
// payload encryption/MIC blocks common layout
#define RADIOLIB_LW_BLOCK_MAGIC_POS (0)
#define RADIOLIB_LW_BLOCK_CONF_FCNT_POS (1)
#define RADIOLIB_LW_BLOCK_DIR_POS (5)
#define RADIOLIB_LW_BLOCK_DEV_ADDR_POS (6)
#define RADIOLIB_LW_BLOCK_FCNT_POS (10)
#define RADIOLIB_LORAWAN_BLOCK_MAGIC_POS (0)
#define RADIOLIB_LORAWAN_BLOCK_CONF_FCNT_POS (1)
#define RADIOLIB_LORAWAN_BLOCK_DIR_POS (5)
#define RADIOLIB_LORAWAN_BLOCK_DEV_ADDR_POS (6)
#define RADIOLIB_LORAWAN_BLOCK_FCNT_POS (10)
// payload encryption block layout
#define RADIOLIB_LW_ENC_BLOCK_MAGIC (0x01)
#define RADIOLIB_LW_ENC_BLOCK_COUNTER_ID_POS (4)
#define RADIOLIB_LW_ENC_BLOCK_COUNTER_POS (15)
#define RADIOLIB_LORAWAN_ENC_BLOCK_MAGIC (0x01)
#define RADIOLIB_LORAWAN_ENC_BLOCK_COUNTER_ID_POS (4)
#define RADIOLIB_LORAWAN_ENC_BLOCK_COUNTER_POS (15)
// payload MIC blocks layout
#define RADIOLIB_LW_MIC_BLOCK_MAGIC (0x49)
#define RADIOLIB_LW_MIC_BLOCK_LEN_POS (15)
#define RADIOLIB_LW_MIC_DATA_RATE_POS (3)
#define RADIOLIB_LW_MIC_CH_INDEX_POS (4)
#define RADIOLIB_LORAWAN_MIC_BLOCK_MAGIC (0x49)
#define RADIOLIB_LORAWAN_MIC_BLOCK_LEN_POS (15)
#define RADIOLIB_LORAWAN_MIC_DATA_RATE_POS (3)
#define RADIOLIB_LORAWAN_MIC_CH_INDEX_POS (4)
// maximum allowed dwell time on bands that implement dwell time limitations
#define RADIOLIB_LW_DWELL_TIME (400)
#define RADIOLIB_LORAWAN_DWELL_TIME (400)
// unused frame counter value
#define RADIOLIB_LW_FCNT_NONE (0xFFFFFFFF)
#define RADIOLIB_LORAWAN_FCNT_NONE (0xFFFFFFFF)
// MAC commands
#define RADIOLIB_LW_NUM_MAC_COMMANDS (16)
#define RADIOLIB_LORAWAN_NUM_MAC_COMMANDS (16)
#define RADIOLIB_LW_MAC_RESET (0x01)
#define RADIOLIB_LW_MAC_LINK_CHECK (0x02)
#define RADIOLIB_LW_MAC_LINK_ADR (0x03)
#define RADIOLIB_LW_MAC_DUTY_CYCLE (0x04)
#define RADIOLIB_LW_MAC_RX_PARAM_SETUP (0x05)
#define RADIOLIB_LW_MAC_DEV_STATUS (0x06)
#define RADIOLIB_LW_MAC_NEW_CHANNEL (0x07)
#define RADIOLIB_LW_MAC_RX_TIMING_SETUP (0x08)
#define RADIOLIB_LW_MAC_TX_PARAM_SETUP (0x09)
#define RADIOLIB_LW_MAC_DL_CHANNEL (0x0A)
#define RADIOLIB_LW_MAC_REKEY (0x0B)
#define RADIOLIB_LW_MAC_ADR_PARAM_SETUP (0x0C)
#define RADIOLIB_LW_MAC_DEVICE_TIME (0x0D)
#define RADIOLIB_LW_MAC_FORCE_REJOIN (0x0E)
#define RADIOLIB_LW_MAC_REJOIN_PARAM_SETUP (0x0F)
#define RADIOLIB_LW_MAC_PROPRIETARY (0x80)
#define RADIOLIB_LORAWAN_MAC_RESET (0x01)
#define RADIOLIB_LORAWAN_MAC_LINK_CHECK (0x02)
#define RADIOLIB_LORAWAN_MAC_LINK_ADR (0x03)
#define RADIOLIB_LORAWAN_MAC_DUTY_CYCLE (0x04)
#define RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP (0x05)
#define RADIOLIB_LORAWAN_MAC_DEV_STATUS (0x06)
#define RADIOLIB_LORAWAN_MAC_NEW_CHANNEL (0x07)
#define RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP (0x08)
#define RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP (0x09)
#define RADIOLIB_LORAWAN_MAC_DL_CHANNEL (0x0A)
#define RADIOLIB_LORAWAN_MAC_REKEY (0x0B)
#define RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP (0x0C)
#define RADIOLIB_LORAWAN_MAC_DEVICE_TIME (0x0D)
#define RADIOLIB_LORAWAN_MAC_FORCE_REJOIN (0x0E)
#define RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP (0x0F)
#define RADIOLIB_LORAWAN_MAC_PROPRIETARY (0x80)
// the length of internal MAC command queue - hopefully this is enough for most use cases
#define RADIOLIB_LW_MAC_COMMAND_QUEUE_SIZE (9)
#define RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE (9)
// the maximum number of simultaneously available channels
#define RADIOLIB_LW_NUM_AVAILABLE_CHANNELS (16)
#define RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS (16)
// maximum MAC command sizes
#define RADIOLIB_LW_MAX_MAC_COMMAND_LEN_DOWN (5)
#define RADIOLIB_LW_MAX_MAC_COMMAND_LEN_UP (2)
#define RADIOLIB_LW_MAX_NUM_ADR_COMMANDS (8)
#define RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_DOWN (5)
#define RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_UP (2)
#define RADIOLIB_LORAWAN_MAX_NUM_ADR_COMMANDS (8)
/*!
\struct LoRaWANMacSpec_t
@ -214,24 +221,24 @@ struct LoRaWANMacSpec_t {
const bool user;
};
constexpr LoRaWANMacSpec_t MacTable[RADIOLIB_LW_NUM_MAC_COMMANDS + 1] = {
constexpr LoRaWANMacSpec_t MacTable[RADIOLIB_LORAWAN_NUM_MAC_COMMANDS + 1] = {
{ 0x00, 0, 0, false }, // not an actual MAC command, exists for index offsetting
{ RADIOLIB_LW_MAC_RESET, 1, 1, false },
{ RADIOLIB_LW_MAC_LINK_CHECK, 2, 0, true },
{ RADIOLIB_LW_MAC_LINK_ADR, 4, 1, false },
{ RADIOLIB_LW_MAC_DUTY_CYCLE, 1, 0, false },
{ RADIOLIB_LW_MAC_RX_PARAM_SETUP, 4, 1, false },
{ RADIOLIB_LW_MAC_DEV_STATUS, 0, 2, false },
{ RADIOLIB_LW_MAC_NEW_CHANNEL, 5, 1, false },
{ RADIOLIB_LW_MAC_RX_TIMING_SETUP, 1, 0, false },
{ RADIOLIB_LW_MAC_TX_PARAM_SETUP, 1, 0, false },
{ RADIOLIB_LW_MAC_DL_CHANNEL, 4, 1, false },
{ RADIOLIB_LW_MAC_REKEY, 1, 1, false },
{ RADIOLIB_LW_MAC_ADR_PARAM_SETUP, 1, 0, false },
{ RADIOLIB_LW_MAC_DEVICE_TIME, 5, 0, true },
{ RADIOLIB_LW_MAC_FORCE_REJOIN, 2, 0, false },
{ RADIOLIB_LW_MAC_REJOIN_PARAM_SETUP, 1, 1, false },
{ RADIOLIB_LW_MAC_PROPRIETARY, 5, 0, true }
{ RADIOLIB_LORAWAN_MAC_RESET, 1, 1, false },
{ RADIOLIB_LORAWAN_MAC_LINK_CHECK, 2, 0, true },
{ RADIOLIB_LORAWAN_MAC_LINK_ADR, 4, 1, false },
{ RADIOLIB_LORAWAN_MAC_DUTY_CYCLE, 1, 0, false },
{ RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP, 4, 1, false },
{ RADIOLIB_LORAWAN_MAC_DEV_STATUS, 0, 2, false },
{ RADIOLIB_LORAWAN_MAC_NEW_CHANNEL, 5, 1, false },
{ RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP, 1, 0, false },
{ RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP, 1, 0, false },
{ RADIOLIB_LORAWAN_MAC_DL_CHANNEL, 4, 1, false },
{ RADIOLIB_LORAWAN_MAC_REKEY, 1, 1, false },
{ RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP, 1, 0, false },
{ RADIOLIB_LORAWAN_MAC_DEVICE_TIME, 5, 0, true },
{ RADIOLIB_LORAWAN_MAC_FORCE_REJOIN, 2, 0, false },
{ RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP, 1, 1, false },
{ RADIOLIB_LORAWAN_MAC_PROPRIETARY, 5, 0, true }
};
/*!
@ -243,7 +250,7 @@ struct LoRaWANMacCommand_t {
uint8_t cid;
/*! \brief Payload buffer (5 bytes is the longest possible) */
uint8_t payload[5];
uint8_t payload[RADIOLIB_LORAWAN_MAX_MAC_COMMAND_LEN_DOWN];
/*! \brief Length of the payload */
uint8_t len;
@ -264,59 +271,59 @@ struct LoRaWANMacCommandQueue_t {
uint8_t len;
/*! \brief MAC command buffer */
LoRaWANMacCommand_t commands[RADIOLIB_LW_MAC_COMMAND_QUEUE_SIZE];
LoRaWANMacCommand_t commands[RADIOLIB_LORAWAN_MAC_COMMAND_QUEUE_SIZE];
};
#define RADIOLIB_LW_NONCES_VERSION_VAL (0x0001)
#define RADIOLIB_LORAWAN_NONCES_VERSION_VAL (0x0001)
enum LoRaWANSchemeBase_t {
RADIOLIB_LW_NONCES_START = 0x00,
RADIOLIB_LW_NONCES_VERSION = RADIOLIB_LW_NONCES_START, // 2 bytes
RADIOLIB_LW_NONCES_MODE = RADIOLIB_LW_NONCES_VERSION + sizeof(uint16_t), // 2 bytes
RADIOLIB_LW_NONCES_CLASS = RADIOLIB_LW_NONCES_MODE + sizeof(uint16_t), // 1 byte
RADIOLIB_LW_NONCES_PLAN = RADIOLIB_LW_NONCES_CLASS + sizeof(uint8_t), // 1 byte
RADIOLIB_LW_NONCES_CHECKSUM = RADIOLIB_LW_NONCES_PLAN + sizeof(uint8_t), // 2 bytes
RADIOLIB_LW_NONCES_DEV_NONCE = RADIOLIB_LW_NONCES_CHECKSUM + sizeof(uint16_t), // 2 bytes
RADIOLIB_LW_NONCES_JOIN_NONCE = RADIOLIB_LW_NONCES_DEV_NONCE + sizeof(uint16_t), // 3 bytes
RADIOLIB_LW_NONCES_ACTIVE = RADIOLIB_LW_NONCES_JOIN_NONCE + 3, // 1 byte
RADIOLIB_LW_NONCES_SIGNATURE = RADIOLIB_LW_NONCES_ACTIVE + sizeof(uint8_t), // 2 bytes
RADIOLIB_LW_NONCES_BUF_SIZE = RADIOLIB_LW_NONCES_SIGNATURE + sizeof(uint16_t) // Nonces buffer size
RADIOLIB_LORAWAN_NONCES_START = 0x00,
RADIOLIB_LORAWAN_NONCES_VERSION = RADIOLIB_LORAWAN_NONCES_START, // 2 bytes
RADIOLIB_LORAWAN_NONCES_MODE = RADIOLIB_LORAWAN_NONCES_VERSION + sizeof(uint16_t), // 2 bytes
RADIOLIB_LORAWAN_NONCES_CLASS = RADIOLIB_LORAWAN_NONCES_MODE + sizeof(uint16_t), // 1 byte
RADIOLIB_LORAWAN_NONCES_PLAN = RADIOLIB_LORAWAN_NONCES_CLASS + sizeof(uint8_t), // 1 byte
RADIOLIB_LORAWAN_NONCES_CHECKSUM = RADIOLIB_LORAWAN_NONCES_PLAN + sizeof(uint8_t), // 2 bytes
RADIOLIB_LORAWAN_NONCES_DEV_NONCE = RADIOLIB_LORAWAN_NONCES_CHECKSUM + sizeof(uint16_t), // 2 bytes
RADIOLIB_LORAWAN_NONCES_JOIN_NONCE = RADIOLIB_LORAWAN_NONCES_DEV_NONCE + sizeof(uint16_t), // 3 bytes
RADIOLIB_LORAWAN_NONCES_ACTIVE = RADIOLIB_LORAWAN_NONCES_JOIN_NONCE + 3, // 1 byte
RADIOLIB_LORAWAN_NONCES_SIGNATURE = RADIOLIB_LORAWAN_NONCES_ACTIVE + sizeof(uint8_t), // 2 bytes
RADIOLIB_LORAWAN_NONCES_BUF_SIZE = RADIOLIB_LORAWAN_NONCES_SIGNATURE + sizeof(uint16_t) // Nonces buffer size
};
enum LoRaWANSchemeSession_t {
RADIOLIB_LW_SESSION_START = 0x00,
RADIOLIB_LW_SESSION_NWK_SENC_KEY = RADIOLIB_LW_SESSION_START, // 16 bytes
RADIOLIB_LW_SESSION_APP_SKEY = RADIOLIB_LW_SESSION_NWK_SENC_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LW_SESSION_FNWK_SINT_KEY = RADIOLIB_LW_SESSION_APP_SKEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LW_SESSION_SNWK_SINT_KEY = RADIOLIB_LW_SESSION_FNWK_SINT_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LW_SESSION_DEV_ADDR = RADIOLIB_LW_SESSION_SNWK_SINT_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 4 bytes
RADIOLIB_LW_SESSION_NONCES_SIGNATURE = RADIOLIB_LW_SESSION_DEV_ADDR + sizeof(uint32_t), // 2 bytes
RADIOLIB_LW_SESSION_A_FCNT_DOWN = RADIOLIB_LW_SESSION_NONCES_SIGNATURE + sizeof(uint16_t), // 4 bytes
RADIOLIB_LW_SESSION_CONF_FCNT_UP = RADIOLIB_LW_SESSION_A_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
RADIOLIB_LW_SESSION_CONF_FCNT_DOWN = RADIOLIB_LW_SESSION_CONF_FCNT_UP + sizeof(uint32_t), // 4 bytes
RADIOLIB_LW_SESSION_RJ_COUNT0 = RADIOLIB_LW_SESSION_CONF_FCNT_DOWN + sizeof(uint32_t), // 2 bytes
RADIOLIB_LW_SESSION_RJ_COUNT1 = RADIOLIB_LW_SESSION_RJ_COUNT0 + sizeof(uint16_t), // 2 bytes
RADIOLIB_LW_SESSION_HOMENET_ID = RADIOLIB_LW_SESSION_RJ_COUNT1 + sizeof(uint16_t), // 4 bytes
RADIOLIB_LW_SESSION_VERSION = RADIOLIB_LW_SESSION_HOMENET_ID + sizeof(uint32_t), // 1 byte
RADIOLIB_LW_SESSION_DUTY_CYCLE = RADIOLIB_LW_SESSION_VERSION + sizeof(uint8_t), // 1 byte
RADIOLIB_LW_SESSION_RX_PARAM_SETUP = RADIOLIB_LW_SESSION_DUTY_CYCLE + MacTable[RADIOLIB_LW_MAC_DUTY_CYCLE].lenDn, // 4 bytes
RADIOLIB_LW_SESSION_RX_TIMING_SETUP = RADIOLIB_LW_SESSION_RX_PARAM_SETUP + MacTable[RADIOLIB_LW_MAC_RX_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LW_SESSION_TX_PARAM_SETUP = RADIOLIB_LW_SESSION_RX_TIMING_SETUP + MacTable[RADIOLIB_LW_MAC_RX_TIMING_SETUP].lenDn, // 1 byte
RADIOLIB_LW_SESSION_ADR_PARAM_SETUP = RADIOLIB_LW_SESSION_TX_PARAM_SETUP + MacTable[RADIOLIB_LW_MAC_TX_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LW_SESSION_REJOIN_PARAM_SETUP = RADIOLIB_LW_SESSION_ADR_PARAM_SETUP + MacTable[RADIOLIB_LW_MAC_ADR_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LW_SESSION_BEACON_FREQ = RADIOLIB_LW_SESSION_REJOIN_PARAM_SETUP + MacTable[RADIOLIB_LW_MAC_REJOIN_PARAM_SETUP].lenDn, // 3 bytes
RADIOLIB_LW_SESSION_PING_SLOT_CHANNEL = RADIOLIB_LW_SESSION_BEACON_FREQ + 3, // 4 bytes
RADIOLIB_LW_SESSION_PERIODICITY = RADIOLIB_LW_SESSION_PING_SLOT_CHANNEL + 4, // 1 byte
RADIOLIB_LW_SESSION_LAST_TIME = RADIOLIB_LW_SESSION_PERIODICITY + 1, // 4 bytes
RADIOLIB_LW_SESSION_UL_CHANNELS = RADIOLIB_LW_SESSION_LAST_TIME + 4, // 16*5 bytes
RADIOLIB_LW_SESSION_DL_CHANNELS = RADIOLIB_LW_SESSION_UL_CHANNELS + 16*MacTable[RADIOLIB_LW_MAC_NEW_CHANNEL].lenDn, // 16*4 bytes
RADIOLIB_LW_SESSION_MAC_QUEUE_UL = RADIOLIB_LW_SESSION_DL_CHANNELS + 16*MacTable[RADIOLIB_LW_MAC_DL_CHANNEL].lenDn, // 9*8+2 bytes
RADIOLIB_LW_SESSION_N_FCNT_DOWN = RADIOLIB_LW_SESSION_MAC_QUEUE_UL + sizeof(LoRaWANMacCommandQueue_t), // 4 bytes
RADIOLIB_LW_SESSION_ADR_FCNT = RADIOLIB_LW_SESSION_N_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
RADIOLIB_LW_SESSION_LINK_ADR = RADIOLIB_LW_SESSION_ADR_FCNT + sizeof(uint32_t), // 4 bytes
RADIOLIB_LW_SESSION_FCNT_UP = RADIOLIB_LW_SESSION_LINK_ADR + MacTable[RADIOLIB_LW_MAC_LINK_ADR].lenDn, // 4 bytes
RADIOLIB_LW_SESSION_SIGNATURE = RADIOLIB_LW_SESSION_FCNT_UP + sizeof(uint32_t), // 2 bytes
RADIOLIB_LW_SESSION_BUF_SIZE = RADIOLIB_LW_SESSION_SIGNATURE + sizeof(uint16_t) // Session buffer size
RADIOLIB_LORAWAN_SESSION_START = 0x00,
RADIOLIB_LORAWAN_SESSION_NWK_SENC_KEY = RADIOLIB_LORAWAN_SESSION_START, // 16 bytes
RADIOLIB_LORAWAN_SESSION_APP_SKEY = RADIOLIB_LORAWAN_SESSION_NWK_SENC_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY = RADIOLIB_LORAWAN_SESSION_APP_SKEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY = RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 16 bytes
RADIOLIB_LORAWAN_SESSION_DEV_ADDR = RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY + RADIOLIB_AES128_BLOCK_SIZE, // 4 bytes
RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE = RADIOLIB_LORAWAN_SESSION_DEV_ADDR + sizeof(uint32_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_A_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE + sizeof(uint16_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_CONF_FCNT_UP = RADIOLIB_LORAWAN_SESSION_A_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_CONF_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_CONF_FCNT_UP + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_RJ_COUNT0 = RADIOLIB_LORAWAN_SESSION_CONF_FCNT_DOWN + sizeof(uint32_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_RJ_COUNT1 = RADIOLIB_LORAWAN_SESSION_RJ_COUNT0 + sizeof(uint16_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_HOMENET_ID = RADIOLIB_LORAWAN_SESSION_RJ_COUNT1 + sizeof(uint16_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_VERSION = RADIOLIB_LORAWAN_SESSION_HOMENET_ID + sizeof(uint32_t), // 1 byte
RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE = RADIOLIB_LORAWAN_SESSION_VERSION + sizeof(uint8_t), // 1 byte
RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_DUTY_CYCLE + MacTable[RADIOLIB_LORAWAN_MAC_DUTY_CYCLE].lenDn, // 4 bytes
RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP = RADIOLIB_LORAWAN_SESSION_RX_PARAM_SETUP + MacTable[RADIOLIB_LORAWAN_MAC_RX_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP + MacTable[RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP].lenDn, // 1 byte
RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP + MacTable[RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP + MacTable[RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP].lenDn, // 1 byte
RADIOLIB_LORAWAN_SESSION_BEACON_FREQ = RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP + MacTable[RADIOLIB_LORAWAN_MAC_REJOIN_PARAM_SETUP].lenDn, // 3 bytes
RADIOLIB_LORAWAN_SESSION_PING_SLOT_CHANNEL = RADIOLIB_LORAWAN_SESSION_BEACON_FREQ + 3, // 4 bytes
RADIOLIB_LORAWAN_SESSION_PERIODICITY = RADIOLIB_LORAWAN_SESSION_PING_SLOT_CHANNEL + 4, // 1 byte
RADIOLIB_LORAWAN_SESSION_LAST_TIME = RADIOLIB_LORAWAN_SESSION_PERIODICITY + 1, // 4 bytes
RADIOLIB_LORAWAN_SESSION_UL_CHANNELS = RADIOLIB_LORAWAN_SESSION_LAST_TIME + 4, // 16*5 bytes
RADIOLIB_LORAWAN_SESSION_DL_CHANNELS = RADIOLIB_LORAWAN_SESSION_UL_CHANNELS + 16*MacTable[RADIOLIB_LORAWAN_MAC_NEW_CHANNEL].lenDn, // 16*4 bytes
RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL = RADIOLIB_LORAWAN_SESSION_DL_CHANNELS + 16*MacTable[RADIOLIB_LORAWAN_MAC_DL_CHANNEL].lenDn, // 9*8+2 bytes
RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_MAC_QUEUE_UL + sizeof(LoRaWANMacCommandQueue_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_ADR_FCNT = RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_LINK_ADR = RADIOLIB_LORAWAN_SESSION_ADR_FCNT + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_FCNT_UP = RADIOLIB_LORAWAN_SESSION_LINK_ADR + MacTable[RADIOLIB_LORAWAN_MAC_LINK_ADR].lenDn, // 4 bytes
RADIOLIB_LORAWAN_SESSION_SIGNATURE = RADIOLIB_LORAWAN_SESSION_FCNT_UP + sizeof(uint32_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_BUF_SIZE = RADIOLIB_LORAWAN_SESSION_SIGNATURE + sizeof(uint16_t) // Session buffer size
};
/*!
@ -342,7 +349,7 @@ struct LoRaWANChannel_t {
};
// alias for unused channel
#define RADIOLIB_LW_CHANNEL_NONE { .enabled = false, .idx = RADIOLIB_LW_CHANNEL_INDEX_NONE, .freq = 0, .drMin = 0, .drMax = 0 }
#define RADIOLIB_LORAWAN_CHANNEL_NONE { .enabled = false, .idx = RADIOLIB_LORAWAN_CHANNEL_INDEX_NONE, .freq = 0, .drMin = 0, .drMax = 0 }
/*!
\struct LoRaWANChannelSpan_t
@ -370,7 +377,7 @@ struct LoRaWANChannelSpan_t {
};
// alias for unused channel span
#define RADIOLIB_LW_CHANNEL_SPAN_NONE { .numChannels = 0, .freqStart = 0, .freqStep = 0, .drMin = 0, .drMax = 0, .joinRequestDataRate = RADIOLIB_LW_DATA_RATE_UNUSED }
#define RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE { .numChannels = 0, .freqStart = 0, .freqStep = 0, .drMin = 0, .drMax = 0, .joinRequestDataRate = RADIOLIB_LORAWAN_DATA_RATE_UNUSED }
/*!
\struct LoRaWANBand_t
@ -384,7 +391,7 @@ struct LoRaWANBand_t {
uint8_t bandType;
/*! \brief Array of allowed maximum payload lengths for each data rate */
uint8_t payloadLenMax[RADIOLIB_LW_CHANNEL_NUM_DATARATES];
uint8_t payloadLenMax[RADIOLIB_LORAWAN_CHANNEL_NUM_DATARATES];
/*! \brief Maximum allowed output power in this band in dBm */
int8_t powerMax;
@ -423,17 +430,19 @@ struct LoRaWANBand_t {
LoRaWANChannel_t rx2;
/*! \brief The corresponding datarates, bandwidths and coding rates for DR index */
uint8_t dataRates[RADIOLIB_LW_CHANNEL_NUM_DATARATES];
uint8_t dataRates[RADIOLIB_LORAWAN_CHANNEL_NUM_DATARATES];
};
// supported bands
extern const LoRaWANBand_t EU868;
extern const LoRaWANBand_t US915;
extern const LoRaWANBand_t CN780;
extern const LoRaWANBand_t EU433;
extern const LoRaWANBand_t AU915;
extern const LoRaWANBand_t CN500;
extern const LoRaWANBand_t AS923;
extern const LoRaWANBand_t AS923_2;
extern const LoRaWANBand_t AS923_3;
extern const LoRaWANBand_t AS923_4;
extern const LoRaWANBand_t KR920;
extern const LoRaWANBand_t IN865;
@ -444,28 +453,45 @@ extern const LoRaWANBand_t IN865;
enum LoRaWANBandNum_t {
BandEU868,
BandUS915,
BandCN780,
BandEU433,
BandAU915,
BandCN500,
BandAS923,
BandAS923_2,
BandAS923_3,
BandAS923_4,
BandKR920,
BandIN865,
BandLast
};
// provide easy access to the number of currently supported bands
#define RADIOLIB_LW_NUM_SUPPORTED_BANDS (BandLast - BandEU868)
#define RADIOLIB_LORAWAN_NUM_SUPPORTED_BANDS (BandLast - BandEU868)
// array of currently supported bands
extern const LoRaWANBand_t* LoRaWANBands[];
/*!
\struct LoRaWANJoinEvent_t
\brief Structure to save extra information about activation event.
*/
struct LoRaWANJoinEvent_t {
/*! \brief Whether a new session was started */
bool newSession = false;
/*! \brief The transmitted Join-Request DevNonce value */
uint16_t devNonce = 0;
/*! \brief The received Join-Request JoinNonce value */
uint32_t joinNonce = 0;
};
/*!
\struct LoRaWANEvent_t
\brief Structure to save extra information about uplink/downlink event.
*/
struct LoRaWANEvent_t {
/*! \brief Event direction, one of RADIOLIB_LW_CHANNEL_DIR_* */
/*! \brief Event direction, one of RADIOLIB_LORAWAN_CHANNEL_DIR_* */
uint8_t dir;
/*! \brief Whether the event is confirmed or not (e.g., confirmed uplink sent by user application) */
@ -498,12 +524,6 @@ struct LoRaWANEvent_t {
class LoRaWANNode {
public:
/*! \brief Offset between TX and RX1 (such that RX1 has equal or lower DR) */
uint8_t rx1DrOffset = 0;
/*! \brief RX2 channel properties - may be changed by MAC command */
LoRaWANChannel_t rx2;
/*!
\brief Default constructor.
\param phy Pointer to the PhysicalLayer radio module.
@ -513,14 +533,13 @@ class LoRaWANNode {
LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band, uint8_t subBand = 0);
/*!
\brief Wipe internal persistent parameters.
This will reset all counters and saved variables, so the device will have to rejoin the network.
\brief Clear an active session, so that the device will have to rejoin the network.
*/
void wipe();
void clearSession();
/*!
\brief Returns the pointer to the internal buffer that holds the LW base parameters
\returns Pointer to uint8_t array of size RADIOLIB_LW_NONCES_BUF_SIZE
\returns Pointer to uint8_t array of size RADIOLIB_LORAWAN_NONCES_BUF_SIZE
*/
uint8_t* getBufferNonces();
@ -533,7 +552,7 @@ class LoRaWANNode {
/*!
\brief Returns the pointer to the internal buffer that holds the LW session parameters
\returns Pointer to uint8_t array of size RADIOLIB_LW_SESSION_BUF_SIZE
\returns Pointer to uint8_t array of size RADIOLIB_LORAWAN_SESSION_BUF_SIZE
*/
uint8_t* getBufferSession();
@ -545,47 +564,51 @@ class LoRaWANNode {
int16_t setBufferSession(uint8_t* persistentBuffer);
/*!
\brief Restore session by loading information from persistent storage.
\returns \ref status_codes
*/
int16_t restore(uint16_t checkSum, uint16_t lwMode, uint8_t lwClass, uint8_t freqPlan);
/*!
\brief Join network by performing over-the-air activation. By this procedure,
the device will perform an exchange with the network server and set all necessary configuration.
\brief Set the device credentials and activation configuration
\param joinEUI 8-byte application identifier.
\param devEUI 8-byte device identifier.
\param nwkKey Pointer to the network AES-128 key.
\param appKey Pointer to the application AES-128 key.
\param force Set to true to force joining even if previously joined.
*/
void beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey);
/*!
\brief Join network by restoring OTAA session or performing over-the-air activation. By this procedure,
the device will perform an exchange with the network server and set all necessary configuration.
\param joinDr The datarate at which to send the join-request and any subsequent uplinks (unless ADR is enabled)
\returns \ref status_codes
*/
int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey, bool force = false, uint8_t joinDr = RADIOLIB_LW_DATA_RATE_UNUSED);
int16_t activateOTAA(uint8_t initialDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED, LoRaWANJoinEvent_t *joinEvent = NULL);
/*!
\brief Join network by performing activation by personalization.
In this procedure, all necessary configuration must be provided by the user.
\brief Set the device credentials and activation configuration
\param addr Device address.
\param fNwkSIntKey Pointer to the Forwarding network session (LoRaWAN 1.1), NULL for LoRaWAN 1.0.
\param sNwkSIntKey Pointer to the Serving network session (LoRaWAN 1.1), NULL for LoRaWAN 1.0.
\param nwkSEncKey Pointer to the MAC command network session key [NwkSEncKey] (LoRaWAN 1.1)
or network session AES-128 key [NwkSKey] (LoRaWAN 1.0).
\param appSKey Pointer to the application session AES-128 key.
\param force Set to true to force a new session, even if one exists.
\param initialDr The datarate at which to send the first uplink and any subsequent uplinks (unless ADR is enabled)
\returns \ref status_codes
*/
int16_t beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey, bool force = false, uint8_t initialDr = RADIOLIB_LW_DATA_RATE_UNUSED);
/*! \brief Whether there is an ongoing session active */
bool isJoined();
void beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey);
/*!
\brief Save the current state of the session to the session buffer.
\brief Join network by restoring ABP session or performing over-the-air activation.
In this procedure, all necessary configuration must be provided by the user.
\param initialDr The datarate at which to send the first uplink and any subsequent uplinks (unless ADR is enabled).
\returns \ref status_codes
*/
int16_t saveSession();
int16_t activateABP(uint8_t initialDr = RADIOLIB_LORAWAN_DATA_RATE_UNUSED);
/*! \brief Whether there is an ongoing session active */
bool isActivated();
/*!
\brief Configure the Rx2 datarate for ABP mode.
This should not be needed for LoRaWAN 1.1 as it is configured through the first downlink.
\param dr The datarate to be used for listening for downlinks in Rx2.
\returns \ref status_codes
*/
int16_t setRx2Dr(uint8_t dr);
/*!
\brief Add a MAC command to the uplink queue.
@ -837,10 +860,16 @@ class LoRaWANNode {
uint64_t getDevAddr();
/*!
\brief Get the Time-on-air of the last uplink message
\returns (RadioLibTime_t) time-on-air (ToA) of last uplink message
\brief Get the Time-on-air of the last uplink message.
\returns (RadioLibTime_t) time-on-air (ToA) of last uplink message.
*/
RadioLibTime_t getLastToA();
RadioLibTime_t getLastToA();
/*!
\brief TS009 Protocol Specification Verification switch
(allows FPort 224 and cuts off uplink payload instead of rejecting if maximum length exceeded).
*/
bool TS009 = false;
#if !RADIOLIB_GODMODE
private:
@ -850,13 +879,13 @@ class LoRaWANNode {
static int16_t checkBufferCommon(uint8_t *buffer, uint16_t size);
void beginCommon(uint8_t initialDr);
void activateCommon(uint8_t initialDr);
// a buffer that holds all LW base parameters that should persist at all times!
uint8_t bufferNonces[RADIOLIB_LW_NONCES_BUF_SIZE] = { 0 };
uint8_t bufferNonces[RADIOLIB_LORAWAN_NONCES_BUF_SIZE] = { 0 };
// a buffer that holds all LW session parameters that preferably persist, but can be afforded to get lost
uint8_t bufferSession[RADIOLIB_LW_SESSION_BUF_SIZE] = { 0 };
uint8_t bufferSession[RADIOLIB_LORAWAN_SESSION_BUF_SIZE] = { 0 };
LoRaWANMacCommandQueue_t commandsUp = {
.numCommands = 0,
@ -869,6 +898,15 @@ class LoRaWANNode {
.commands = { { .cid = 0, .payload = { 0 }, .len = 0, .repeat = 0, } },
};
uint16_t lwMode = RADIOLIB_LORAWAN_MODE_NONE;
uint8_t lwClass = RADIOLIB_LORAWAN_CLASS_A;
bool isActive = false;
uint64_t joinEUI = 0;
uint64_t devEUI = 0;
uint8_t nwkKey[RADIOLIB_AES128_KEY_SIZE] = { 0 };
uint8_t appKey[RADIOLIB_AES128_KEY_SIZE] = { 0 };
// the following is either provided by the network server (OTAA)
// or directly entered by the user (ABP)
uint32_t devAddr = 0;
@ -877,6 +915,8 @@ class LoRaWANNode {
uint8_t sNwkSIntKey[RADIOLIB_AES128_KEY_SIZE] = { 0 };
uint8_t nwkSEncKey[RADIOLIB_AES128_KEY_SIZE] = { 0 };
uint8_t jSIntKey[RADIOLIB_AES128_KEY_SIZE] = { 0 };
uint16_t keyCheckSum = 0;
// device-specific parameters, persistent through sessions
uint16_t devNonce = 0;
@ -884,20 +924,20 @@ class LoRaWANNode {
// session-specific parameters
uint32_t homeNetId = 0;
uint8_t adrLimitExp = RADIOLIB_LW_ADR_ACK_LIMIT_EXP;
uint8_t adrDelayExp = RADIOLIB_LW_ADR_ACK_DELAY_EXP;
uint8_t adrLimitExp = RADIOLIB_LORAWAN_ADR_ACK_LIMIT_EXP;
uint8_t adrDelayExp = RADIOLIB_LORAWAN_ADR_ACK_DELAY_EXP;
uint8_t nbTrans = 1; // Number of allowed frame retransmissions
uint8_t txPowerSteps = 0;
uint8_t txPowerMax = 0;
uint32_t fCntUp = 0;
uint32_t aFCntDown = 0;
uint32_t nFCntDown = 0;
uint32_t confFCntUp = RADIOLIB_LW_FCNT_NONE;
uint32_t confFCntDown = RADIOLIB_LW_FCNT_NONE;
uint32_t confFCntUp = RADIOLIB_LORAWAN_FCNT_NONE;
uint32_t confFCntDown = RADIOLIB_LORAWAN_FCNT_NONE;
uint32_t adrFCnt = 0;
// whether the current configured channel is in FSK mode
bool FSK = false;
// modulation of the currently configured channel
uint8_t modulation = RADIOLIB_LORAWAN_MODULATION_LORA;
// ADR is enabled by default
bool adrEnabled = true;
@ -924,13 +964,19 @@ class LoRaWANNode {
uint8_t difsSlots;
// available channel frequencies from list passed during OTA activation
LoRaWANChannel_t availableChannels[2][RADIOLIB_LW_NUM_AVAILABLE_CHANNELS];
LoRaWANChannel_t availableChannels[2][RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS];
// currently configured channels for TX and RX1
LoRaWANChannel_t currentChannels[2] = { RADIOLIB_LW_CHANNEL_NONE, RADIOLIB_LW_CHANNEL_NONE };
LoRaWANChannel_t currentChannels[2] = { RADIOLIB_LORAWAN_CHANNEL_NONE, RADIOLIB_LORAWAN_CHANNEL_NONE };
// currently configured datarates for TX and RX1
uint8_t dataRates[2] = { RADIOLIB_LW_DATA_RATE_UNUSED, RADIOLIB_LW_DATA_RATE_UNUSED };
uint8_t dataRates[2] = { RADIOLIB_LORAWAN_DATA_RATE_UNUSED, RADIOLIB_LORAWAN_DATA_RATE_UNUSED };
// Rx2 channel properties - may be changed by MAC command
LoRaWANChannel_t rx2 = RADIOLIB_LORAWAN_CHANNEL_NONE;
// offset between TX and RX1 (such that RX1 has equal or lower DR)
uint8_t rx1DrOffset = 0;
// LoRaWAN revision (1.0 vs 1.1)
uint8_t rev = 0;
@ -945,7 +991,7 @@ class LoRaWANNode {
RadioLibTime_t rxDelayEnd = 0;
// delays between the uplink and RX1/2 windows
RadioLibTime_t rxDelays[2] = { RADIOLIB_LW_RECEIVE_DELAY_1_MS, RADIOLIB_LW_RECEIVE_DELAY_2_MS };
RadioLibTime_t rxDelays[2] = { RADIOLIB_LORAWAN_RECEIVE_DELAY_1_MS, RADIOLIB_LORAWAN_RECEIVE_DELAY_2_MS };
// device status - battery level
uint8_t battLevel = 0xFF;
@ -956,6 +1002,9 @@ class LoRaWANNode {
// save the selected sub-band in case this must be restored in ADR control
uint8_t subBand = 0;
// this will reset the device credentials, so the device starts completely new
void clearNonces();
// wait for, open and listen during Rx1 and Rx2 windows; only performs listening
int16_t downlinkCommon();
@ -1025,7 +1074,7 @@ class LoRaWANNode {
bool performCAD();
// function to encrypt and decrypt payloads
void processAES(uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fCnt, uint8_t dir, uint8_t ctrId, bool counter);
void processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_t* out, uint32_t fCnt, uint8_t dir, uint8_t ctrId, bool counter);
// 16-bit checksum method that takes a uint8_t array of even length and calculates the checksum
static uint16_t checkSum16(uint8_t *key, uint16_t keyLen);

View file

@ -3,21 +3,23 @@
#if !RADIOLIB_EXCLUDE_LORAWAN
// array of pointers to currently supported LoRaWAN bands
const LoRaWANBand_t* LoRaWANBands[RADIOLIB_LW_NUM_SUPPORTED_BANDS] = {
const LoRaWANBand_t* LoRaWANBands[RADIOLIB_LORAWAN_NUM_SUPPORTED_BANDS] = {
&EU868,
&US915,
&CN780,
&EU433,
&AU915,
&CN500,
&AS923,
&AS923_2,
&AS923_3,
&AS923_4,
&KR920,
&IN865,
};
const LoRaWANBand_t EU868 = {
.bandNum = BandEU868,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
.powerNumSteps = 7,
@ -30,55 +32,55 @@ const LoRaWANBand_t EU868 = {
{ .enabled = true, .idx = 2, .freq = 868.500, .drMin = 0, .drMax = 5},
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 869.525, .drMin = 0, .drMax = 0 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_250_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_FSK_50_K,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t US915 = {
.bandNum = BandUS915,
.bandType = RADIOLIB_LW_BAND_FIXED,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 19, 61, 133, 250, 250, 0, 0, 0, 41, 117, 230, 230, 230, 230, 0 },
.powerMax = 30,
.powerNumSteps = 10,
.dutyCycle = 0,
.dwellTimeUp = RADIOLIB_LW_DWELL_TIME,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = 0,
.txFreqs = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 2,
.txSpans = {
@ -105,78 +107,32 @@ const LoRaWANBand_t US915 = {
.freqStep = 0.600,
.drMin = 8,
.drMax = 13,
.joinRequestDataRate = RADIOLIB_LW_DATA_RATE_UNUSED
.joinRequestDataRate = RADIOLIB_LORAWAN_DATA_RATE_UNUSED
},
.rx1DataRateBase = 10,
.rx2 = { .enabled = true, .idx = 0, .freq = 923.300, .drMin = 8, .drMax = 8 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t CN780 = {
.bandNum = BandCN780,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 250, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 12,
.powerNumSteps = 5,
.dutyCycle = 3600,
.dwellTimeUp = 0,
.dwellTimeDn = 0,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 779.500, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 1, .freq = 779.700, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 2, .freq = 779.900, .drMin = 0, .drMax = 5},
},
.txJoinReq = {
{ .enabled = true, .idx = 3, .freq = 780.500, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 4, .freq = 780.700, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 5, .freq = 780.900, .drMin = 0, .drMax = 5}
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 786.000, .drMin = 0, .drMax = 0 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_250_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_FSK_50_K,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t EU433 = {
.bandNum = BandEU433,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 12,
.powerNumSteps = 5,
@ -189,55 +145,55 @@ const LoRaWANBand_t EU433 = {
{ .enabled = true, .idx = 2, .freq = 433.575, .drMin = 0, .drMax = 5},
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 434.665, .drMin = 0, .drMax = 0 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_250_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_FSK_50_K,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t AU915 = {
.bandNum = BandAU915,
.bandType = RADIOLIB_LW_BAND_FIXED,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 0, 41, 117, 230, 230, 230, 230, 0 },
.powerMax = 30,
.powerNumSteps = 10,
.dutyCycle = 0,
.dwellTimeUp = 0,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = 0,
.txFreqs = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 2,
.txSpans = {
@ -247,7 +203,7 @@ const LoRaWANBand_t AU915 = {
.freqStep = 0.200,
.drMin = 0,
.drMax = 5,
.joinRequestDataRate = 0
.joinRequestDataRate = 2
},
{
.numChannels = 8,
@ -264,32 +220,32 @@ const LoRaWANBand_t AU915 = {
.freqStep = 0.600,
.drMin = 8,
.drMax = 13,
.joinRequestDataRate = RADIOLIB_LW_DATA_RATE_UNUSED
.joinRequestDataRate = RADIOLIB_LORAWAN_DATA_RATE_UNUSED
},
.rx1DataRateBase = 8,
.rx2 = { .enabled = true, .idx = 0, .freq = 923.300, .drMin = 8, .drMax = 8 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_500_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_500_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t CN500 = {
.bandNum = BandCN500,
.bandType = RADIOLIB_LW_BAND_FIXED,
.bandType = RADIOLIB_LORAWAN_BAND_FIXED,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 19,
.powerNumSteps = 7,
@ -297,14 +253,14 @@ const LoRaWANBand_t CN500 = {
.dwellTimeUp = 0,
.dwellTimeDn = 0,
.txFreqs = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 1,
.txSpans = {
@ -316,7 +272,7 @@ const LoRaWANBand_t CN500 = {
.drMax = 5,
.joinRequestDataRate = 0
},
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = {
.numChannels = 48,
@ -324,78 +280,216 @@ const LoRaWANBand_t CN500 = {
.freqStep = 0.200,
.drMin = 0,
.drMax = 5,
.joinRequestDataRate = RADIOLIB_LW_DATA_RATE_UNUSED
.joinRequestDataRate = RADIOLIB_LORAWAN_DATA_RATE_UNUSED
},
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 505.300, .drMin = 0, .drMax = 0 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_5,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t AS923 = {
.bandNum = BandAS923,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
.powerNumSteps = 7,
.dutyCycle = 36000,
.dwellTimeUp = RADIOLIB_LW_DWELL_TIME,
.dwellTimeDn = RADIOLIB_LW_DWELL_TIME,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 923.200, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 1, .freq = 923.400, .drMin = 0, .drMax = 5},
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 923.200, .drMin = 2, .drMax = 2 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_250_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_FSK_50_K,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t AS923_2 = {
.bandNum = BandAS923_2,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
.powerNumSteps = 7,
.dutyCycle = 36000,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 921.400, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 1, .freq = 921.600, .drMin = 0, .drMax = 5},
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 921.400, .drMin = 2, .drMax = 2 },
.dataRates = {
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t AS923_3 = {
.bandNum = BandAS923_3,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
.powerNumSteps = 7,
.dutyCycle = 36000,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 916.600, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 1, .freq = 916.800, .drMin = 0, .drMax = 5},
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 916.600, .drMin = 2, .drMax = 2 },
.dataRates = {
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t AS923_4 = {
.bandNum = BandAS923_4,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 16,
.powerNumSteps = 7,
.dutyCycle = 36000,
.dwellTimeUp = RADIOLIB_LORAWAN_DWELL_TIME,
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 917.300, .drMin = 0, .drMax = 5},
{ .enabled = true, .idx = 1, .freq = 917.500, .drMin = 0, .drMax = 5},
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 917.300, .drMin = 2, .drMax = 2 },
.dataRates = {
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_250_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t KR920 = {
.bandNum = BandKR920,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 14,
.powerNumSteps = 7,
@ -408,40 +502,40 @@ const LoRaWANBand_t KR920 = {
{ .enabled = true, .idx = 2, .freq = 922.500, .drMin = 0, .drMax = 5}
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 921.900, .drMin = 0, .drMax = 0 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};
const LoRaWANBand_t IN865 = {
.bandNum = BandIN865,
.bandType = RADIOLIB_LW_BAND_DYNAMIC,
.bandType = RADIOLIB_LORAWAN_BAND_DYNAMIC,
.payloadLenMax = { 59, 59, 59, 123, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0 },
.powerMax = 30,
.powerNumSteps = 10,
@ -454,34 +548,34 @@ const LoRaWANBand_t IN865 = {
{ .enabled = true, .idx = 2, .freq = 865.9850, .drMin = 0, .drMax = 5}
},
.txJoinReq = {
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE,
RADIOLIB_LW_CHANNEL_NONE
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
.txSpans = {
RADIOLIB_LW_CHANNEL_SPAN_NONE,
RADIOLIB_LW_CHANNEL_SPAN_NONE
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE
},
.rx1Span = RADIOLIB_LW_CHANNEL_SPAN_NONE,
.rx1Span = RADIOLIB_LORAWAN_CHANNEL_SPAN_NONE,
.rx1DataRateBase = 0,
.rx2 = { .enabled = true, .idx = 0, .freq = 866.550, .drMin = 2, .drMax = 2 },
.dataRates = {
RADIOLIB_LW_DATA_RATE_SF_12 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_11 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_10 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_9 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_8 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_SF_7 | RADIOLIB_LW_DATA_RATE_BW_125_KHZ | RADIOLIB_LW_DATA_RATE_CR_4_7,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_FSK_50_K,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED,
RADIOLIB_LW_DATA_RATE_UNUSED
RADIOLIB_LORAWAN_DATA_RATE_SF_12 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_11 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_10 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_9 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_8 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_SF_7 | RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ | RADIOLIB_LORAWAN_DATA_RATE_CR_4_5,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_FSK_50_K,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED,
RADIOLIB_LORAWAN_DATA_RATE_UNUSED
}
};

View file

@ -529,15 +529,15 @@ class PhysicalLayer {
size_t maxPacketLength;
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
uint8_t bufferBitPos;
uint8_t bufferWritePos;
uint8_t bufferReadPos;
uint8_t buffer[RADIOLIB_STATIC_ARRAY_SIZE];
uint32_t syncBuffer;
uint32_t directSyncWord;
uint8_t directSyncWordLen;
uint32_t directSyncWordMask;
bool gotSync;
uint8_t bufferBitPos = 0;
uint8_t bufferWritePos = 0;
uint8_t bufferReadPos = 0;
uint8_t buffer[RADIOLIB_STATIC_ARRAY_SIZE] = { 0 };
uint32_t syncBuffer = 0;
uint32_t directSyncWord = 0;
uint8_t directSyncWordLen = 0;
uint32_t directSyncWordMask = 0;
bool gotSync = false;
#endif
virtual Module* getMod() = 0;

View file

@ -30,12 +30,14 @@ ITA2String::ITA2String(const ITA2String& ita2) {
}
ITA2String& ITA2String::operator=(const ITA2String& ita2) {
this->asciiLen = ita2.asciiLen;
this->ita2Len = ita2.ita2Len;
#if !RADIOLIB_STATIC_ONLY
this->strAscii = new char[asciiLen + 1];
#endif
strcpy(this->strAscii, ita2.strAscii);
if(&ita2 != this) {
this->asciiLen = ita2.asciiLen;
this->ita2Len = ita2.ita2Len;
#if !RADIOLIB_STATIC_ONLY
this->strAscii = new char[asciiLen + 1];
#endif
strcpy(this->strAscii, ita2.strAscii);
}
return(*this);
}

View file

@ -155,8 +155,6 @@ class RadioLibAES128 {
void subWord(uint8_t* word);
void rotWord(uint8_t* word);
void addRoundKey(uint8_t round, state_t* state, const uint8_t* roundKey);
void blockXor(uint8_t* dst, const uint8_t* a, const uint8_t* b);
void blockLeftshift(uint8_t* dst, const uint8_t* src);
void generateSubkeys(uint8_t* key1, uint8_t* key2);
@ -165,7 +163,9 @@ class RadioLibAES128 {
void shiftRows(state_t* state, bool inv);
void mixColumns(state_t* state, bool inv);
uint8_t mul(uint8_t a, uint8_t b);
// cppcheck seems convinced these are nut used, which is not true
uint8_t mul(uint8_t a, uint8_t b); // cppcheck-suppress unusedPrivateFunction
void addRoundKey(uint8_t round, state_t* state, const uint8_t* roundKey); // cppcheck-suppress unusedPrivateFunction
};
// the global singleton