RadioLib update to v7.1.2

This commit is contained in:
lewisxhe 2025-01-13 10:28:08 +08:00
commit 24815c6cdc
93 changed files with 1143 additions and 1305 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,27 @@
name: "Unit test"
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
unit-test:
name: Build and run unit test
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libboost-all-dev libfmt-dev
- name: Run unit test
run: |
cd extras/test/unit
./test.sh

View file

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

View file

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

View file

@ -82,10 +82,10 @@ void setup() {
void loop() {
Serial.print(F("[CC1101] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to 63 characters long
// you can transmit C-string or Arduino string up to 64 characters long
int state = radio.transmit("Hello World!");
// you can also transmit byte array up to 63 bytes long
// you can also transmit byte array up to 64 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);

View file

@ -57,11 +57,11 @@ int count = 0;
void loop() {
Serial.print(F("[CC1101] Transmitting packet ... "));
// you can transmit C-string or Arduino string up to 63 characters long
// you can transmit C-string or Arduino string up to 64 characters long
String str = "Hello World! #" + String(count++);
int state = radio.transmit(str);
// you can also transmit byte array up to 63 bytes long
// you can also transmit byte array up to 64 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
int state = radio.transmit(byteArr, 8);

View file

@ -36,6 +36,21 @@ Radio radio = new RadioModule();
// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
void setup() {
Serial.begin(9600);
@ -69,21 +84,6 @@ void setup() {
*/
}
// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;
// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent a packet, set the flag
transmittedFlag = true;
}
// counter to keep track of transmitted packets
int count = 0;
@ -119,11 +119,11 @@ void loop() {
Serial.print(F("[CC1101] Sending another packet ... "));
// you can transmit C-string or Arduino string up to
// 256 characters long
// 64 characters long
String str = "Hello World! #" + String(count++);
transmissionState = radio.startTransmit(str);
// you can also transmit byte array up to 256 bytes long
// you can also transmit byte array up to 64 bytes long
/*
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
0x89, 0xAB, 0xCD, 0xEF};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -68,7 +68,7 @@ void setup() {
// Manages uplink intervals to the TTN Fair Use Policy
node.setDutyCycle(true, 1250);
// Enable the dwell time limits - 400ms is the limit for the US
// Update dwell time limits - 400ms is the limit for the US
node.setDwellTime(true, 400);
Serial.println(F("Ready!\n"));

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -197,6 +197,7 @@ randomByte KEYWORD2
getPacketLength KEYWORD2
setFifoEmptyAction KEYWORD2
clearFifoEmptyAction KEYWORD2
setFifoThreshold KEYWORD2
setFifoFullAction KEYWORD2
clearFifoFullAction KEYWORD2
fifoAdd KEYWORD2
@ -221,6 +222,7 @@ setGdo2Action KEYWORD2
clearGdo0Action KEYWORD2
clearGdo2Action KEYWORD2
setCrcFiltering KEYWORD2
beginFSK4 KEYWORD2
# SX126x-specific
setTCXO KEYWORD2

View file

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

View file

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

View file

@ -133,11 +133,9 @@
* RADIOLIB_DEFAULT_SPI - default SPIClass instance to use.
* RADIOLIB_NONVOLATILE - macro to place variable into program storage (usually Flash).
* RADIOLIB_NONVOLATILE_READ_BYTE - function/macro to read variables saved in program storage (usually Flash).
* RADIOLIB_TYPE_ALIAS - construct to create an alias for a type, usually vai the `using` keyword.
* RADIOLIB_TYPE_ALIAS - construct to create an alias for a type, usually via the `using` keyword.
* RADIOLIB_TONE_UNSUPPORTED - some platforms do not have tone()/noTone(), which is required for AFSK.
*
* In addition, some platforms may require RadioLib to disable specific drivers (such as ESP8266).
*
* Users may also specify their own configuration by uncommenting the RADIOLIB_CUSTOM_ARDUINO,
* and then specifying all platform parameters in the section below. This will override automatic
* platform detection.
@ -365,6 +363,13 @@
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#elif defined(ARDUINO_ARCH_SILABS)
// Silicon Labs Arduino
#define RADIOLIB_PLATFORM "Arduino Silicon Labs"
#define RADIOLIB_ARDUINOHAL_PIN_MODE_CAST (PinMode)
#define RADIOLIB_ARDUINOHAL_PIN_STATUS_CAST (PinStatus)
#define RADIOLIB_ARDUINOHAL_INTERRUPT_MODE_CAST (PinStatus)
#else
// other Arduino platforms not covered by the above list - this may or may not work
#define RADIOLIB_PLATFORM "Unknown Arduino"
@ -578,7 +583,7 @@
// version definitions
#define RADIOLIB_VERSION_MAJOR 7
#define RADIOLIB_VERSION_MINOR 1
#define RADIOLIB_VERSION_PATCH 0
#define RADIOLIB_VERSION_PATCH 2
#define RADIOLIB_VERSION_EXTRA 0
#define RADIOLIB_VERSION (((RADIOLIB_VERSION_MAJOR) << 24) | ((RADIOLIB_VERSION_MINOR) << 16) | ((RADIOLIB_VERSION_PATCH) << 8) | (RADIOLIB_VERSION_EXTRA))

View file

@ -56,13 +56,21 @@ int16_t Module::SPIgetRegValue(uint32_t reg, uint8_t msb, uint8_t lsb) {
return(maskedValue);
}
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask, bool force) {
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
}
// read the current value
uint8_t currentValue = SPIreadRegister(reg);
uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
// check if we actually need to update the register
if((currentValue & mask) == (value & mask) && !force) {
return(RADIOLIB_ERR_NONE);
}
// update the register
uint8_t newValue = (currentValue & ~mask) | (value & mask);
SPIwriteRegister(reg, newValue);

View file

@ -272,9 +272,10 @@ class Module {
\param lsb Least significant bit of the register variable. Bits below this one will not be affected by the write operation.
\param checkInterval Number of milliseconds between register writing and verification reading. Some registers need up to 10ms to process the change.
\param checkMask Mask of bits to check, only bits set to 1 will be verified.
\param force Write new value even if the old value is the same.
\returns \ref status_codes
*/
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF, bool force = false);
/*!
\brief SPI burst read method.
@ -382,12 +383,9 @@ class Module {
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
/*!
\brief Access method to get the pin number of SPI chip select.
\returns Pin number of SPI chip select configured in the constructor.
*/
uint32_t getCs() const { return(csPin); }
// getCs is omitted on purpose, as it can interfere when accessing the SPI in a concurrent environment
// so it is considered to be part of the SPI pins and hence not accessible from outside
// see https://github.com/jgromes/RadioLib/discussions/1364
/*!
\brief Access method to get the pin number of interrupt/GPIO.

View file

@ -4,11 +4,15 @@
/*!
\mainpage RadioLib Documentation
Universal wireless communication library for Arduino.
Universal wireless communication library for embedded devices.
\par Currently Supported Wireless Modules and Protocols
- CC1101 FSK module
- LLCC68 LoRa/FSK module
- LR11x0 LoRa/FSK/LR-FHSS module
- nRF24 FSK module
- RF69 FSK module
- RFM2x FSK module
- Si443x FSK module
- SX126x LoRa/FSK module
- SX127x LoRa/FSK module
@ -22,6 +26,8 @@
- Hellschreiber (HellClient)
- 4-FSK (FSK4Client)
- APRS (APRSClient)
- POCSAG (PagerClient)
- LoRaWAN (LoRaWANNode)
\par Quick Links
Documentation for most common methods can be found in its reference page (see the list above).\n

View file

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

View file

@ -7,94 +7,19 @@ CC1101::CC1101(Module* module) : PhysicalLayer(RADIOLIB_CC1101_FREQUENCY_STEP_SI
}
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set module properties
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
// set the modulation and execute the common part
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_2_FSK;
return(this->beginCommon(freq, br, freqDev, rxBw, pwr, preambleLength));
}
// try to find the CC1101 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
flagFound = true;
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
this->mod->hal->delay(10);
i++;
}
}
if(!flagFound) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No CC1101 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tCC1101");
}
// configure settings not accessible by API
int16_t state = config();
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
// configure bitrate
state = setBitRate(br);
RADIOLIB_ASSERT(state);
// configure default RX bandwidth
state = setRxBandwidth(rxBw);
RADIOLIB_ASSERT(state);
// configure default frequency deviation
state = setFrequencyDeviation(freqDev);
RADIOLIB_ASSERT(state);
// configure default TX output power
state = setOutputPower(pwr);
RADIOLIB_ASSERT(state);
// set default packet length mode
state = variablePacketLengthMode();
RADIOLIB_ASSERT(state);
// configure default preamble length
state = setPreambleLength(preambleLength, preambleLength - 4);
RADIOLIB_ASSERT(state);
// set default data shaping
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
// set default encoding
state = setEncoding(RADIOLIB_ENCODING_NRZ);
RADIOLIB_ASSERT(state);
// set default sync word
uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
state = setSyncWord(sw[0], sw[1], 0, false);
RADIOLIB_ASSERT(state);
// flush FIFOs
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
return(state);
int16_t CC1101::beginFSK4(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set the modulation and execute the common part
this->modulation = RADIOLIB_CC1101_MOD_FORMAT_4_FSK;
return(this->beginCommon(freq, br, freqDev, rxBw, pwr, preambleLength));
}
void CC1101::reset() {
// this is the manual power-on-reset sequence
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delayMicroseconds(5);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
this->mod->hal->delayMicroseconds(40);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delay(10);
// just send the command, the reset sequence as described in datasheet seems unnecessary in our usage
SPIsendCommand(RADIOLIB_CC1101_CMD_RESET);
}
@ -922,7 +847,7 @@ int16_t CC1101::setDataShaping(uint8_t sh) {
// set data shaping
switch(sh) {
case RADIOLIB_SHAPING_NONE:
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, RADIOLIB_CC1101_MOD_FORMAT_2_FSK, 6, 4);
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, this->modulation, 6, 4);
break;
case RADIOLIB_SHAPING_0_5:
state = SPIsetRegValue(RADIOLIB_CC1101_REG_MDMCFG2, RADIOLIB_CC1101_MOD_FORMAT_GFSK, 6, 4);
@ -1006,6 +931,87 @@ int16_t CC1101::setDIOMapping(uint32_t pin, uint32_t value) {
return(SPIsetRegValue(RADIOLIB_CC1101_REG_IOCFG0 - pin, value));
}
int16_t CC1101::beginCommon(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
// set module properties
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
this->mod->init();
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
// try to find the CC1101 chip
uint8_t i = 0;
bool flagFound = false;
while((i < 10) && !flagFound) {
int16_t version = getChipVersion();
if((version == RADIOLIB_CC1101_VERSION_CURRENT) || (version == RADIOLIB_CC1101_VERSION_LEGACY) || (version == RADIOLIB_CC1101_VERSION_CLONE)) {
flagFound = true;
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("CC1101 not found! (%d of 10 tries) RADIOLIB_CC1101_REG_VERSION == 0x%04X, expected 0x0004/0x0014", i + 1, version);
this->mod->hal->delay(10);
i++;
}
}
if(!flagFound) {
RADIOLIB_DEBUG_BASIC_PRINTLN("No CC1101 found!");
this->mod->term();
return(RADIOLIB_ERR_CHIP_NOT_FOUND);
} else {
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tCC1101");
}
// configure settings not accessible by API
int16_t state = config();
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
// configure bitrate
state = setBitRate(br);
RADIOLIB_ASSERT(state);
// configure default RX bandwidth
state = setRxBandwidth(rxBw);
RADIOLIB_ASSERT(state);
// configure default frequency deviation
state = setFrequencyDeviation(freqDev);
RADIOLIB_ASSERT(state);
// configure default TX output power
state = setOutputPower(pwr);
RADIOLIB_ASSERT(state);
// set default packet length mode
state = variablePacketLengthMode();
RADIOLIB_ASSERT(state);
// configure default preamble length
state = setPreambleLength(preambleLength, preambleLength - 4);
RADIOLIB_ASSERT(state);
// set default data shaping
state = setDataShaping(RADIOLIB_SHAPING_NONE);
RADIOLIB_ASSERT(state);
// set default encoding
state = setEncoding(RADIOLIB_ENCODING_NRZ);
RADIOLIB_ASSERT(state);
// set default sync word
uint8_t sw[RADIOLIB_CC1101_DEFAULT_SW_LEN] = RADIOLIB_CC1101_DEFAULT_SW;
state = setSyncWord(sw[0], sw[1], 0, false);
RADIOLIB_ASSERT(state);
// flush FIFOs
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_TX);
return(state);
}
int16_t CC1101::config() {
// Reset the radio. Registers may be dirty from previous usage.
reset();
@ -1154,21 +1160,7 @@ void CC1101::SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, size_t len) {
}
void CC1101::SPIsendCommand(uint8_t cmd) {
// pull NSS low
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
// start transfer
this->mod->hal->spiBeginTransaction();
// send the command byte
uint8_t status = 0;
this->mod->hal->spiTransfer(&cmd, 1, &status);
// stop transfer
this->mod->hal->spiEndTransaction();
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
RADIOLIB_DEBUG_SPI_PRINTLN("CMD\tW\t%02X\t%02X", cmd, status);
(void)status;
this->mod->SPItransferStream(&cmd, 1, true, NULL, NULL, 0, false);
}
#endif

View file

@ -8,7 +8,7 @@
// CC1101 physical layer properties
#define RADIOLIB_CC1101_FREQUENCY_STEP_SIZE 396.7285156
#define RADIOLIB_CC1101_MAX_PACKET_LENGTH 63
#define RADIOLIB_CC1101_MAX_PACKET_LENGTH 64
#define RADIOLIB_CC1101_CRYSTAL_FREQ 26.0
#define RADIOLIB_CC1101_DIV_EXPONENT 16
@ -191,9 +191,6 @@
// RADIOLIB_CC1101_REG_SYNC0
#define RADIOLIB_CC1101_SYNC_WORD_LSB 0x91 // 7 0 sync word LSB
// RADIOLIB_CC1101_REG_PKTLEN
#define RADIOLIB_CC1101_PACKET_LENGTH 0xFF // 7 0 packet length in bytes
// RADIOLIB_CC1101_REG_PKTCTRL1
#define RADIOLIB_CC1101_PQT 0x00 // 7 5 preamble quality threshold
#define RADIOLIB_CC1101_CRC_AUTOFLUSH_OFF 0b00000000 // 3 3 automatic Rx FIFO flush on CRC check fail: disabled (default)
@ -562,6 +559,24 @@ class CC1101: public PhysicalLayer {
int8_t pwr = RADIOLIB_CC1101_DEFAULT_POWER,
uint8_t preambleLength = RADIOLIB_CC1101_DEFAULT_PREAMBLELEN);
/*!
\brief Initialization method for 4-FSK modulation.
\param freq Carrier frequency in MHz. Defaults to 434 MHz.
\param br Bit rate to be used in kbps. Defaults to 4.8 kbps.
\param freqDev Frequency deviation from carrier frequency in kHz Defaults to 5.0 kHz.
\param rxBw Receiver bandwidth in kHz. Defaults to 135.0 kHz.
\param pwr Output power in dBm. Defaults to 10 dBm.
\param preambleLength Preamble Length in bits. Defaults to 16 bits.
\returns \ref status_codes
*/
int16_t beginFSK4(
float freq = RADIOLIB_CC1101_DEFAULT_FREQ,
float br = RADIOLIB_CC1101_DEFAULT_BR,
float freqDev = RADIOLIB_CC1101_DEFAULT_FREQDEV,
float rxBw = RADIOLIB_CC1101_DEFAULT_RXBW,
int8_t pwr = RADIOLIB_CC1101_DEFAULT_POWER,
uint8_t preambleLength = RADIOLIB_CC1101_DEFAULT_PREAMBLELEN);
/*!
\brief Reset method - resets the chip using manual reset sequence (without RESET pin).
*/
@ -1014,6 +1029,7 @@ class CC1101: public PhysicalLayer {
int8_t power = RADIOLIB_CC1101_DEFAULT_POWER;
int16_t beginCommon(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength);
int16_t config();
int16_t transmitDirect(bool sync, uint32_t frf);
int16_t receiveDirect(bool sync);

View file

@ -9,6 +9,13 @@ LLCC68::LLCC68(Module* mod) : SX1262(mod) {
int16_t LLCC68::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t pwr, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
// execute common part
int16_t state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
if(state == RADIOLIB_ERR_CHIP_NOT_FOUND) {
// bit of a hack, but some LLCC68 chips report as "SX1261", try that
// for full discussion, see https://github.com/jgromes/RadioLib/issues/1329
chipType = RADIOLIB_SX1261_CHIP_TYPE;
state = SX126x::begin(cr, syncWord, preambleLength, tcxoVoltage, useRegulatorLDO);
RADIOLIB_DEBUG_PRINTLN("LLCC68 version string not found, using SX1261 instead");
}
RADIOLIB_ASSERT(state);
// configure publicly accessible settings
@ -118,13 +125,13 @@ int16_t LLCC68::checkDataRate(DataRate_t dr) {
int16_t LLCC68::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
default:

View file

@ -7,6 +7,7 @@
#include "../../Module.h"
#include "../SX126x/SX1262.h"
#include "../SX126x/SX1261.h"
//RADIOLIB_SX126X_REG_VERSION_STRING
#define RADIOLIB_LLCC68_CHIP_TYPE "LLCC68"

View file

@ -113,13 +113,13 @@ int16_t LR1110::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo
int16_t LR1110::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginGFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
}

View file

@ -133,13 +133,13 @@ int16_t LR1120::checkOutputPower(int8_t power, int8_t* clipped, bool forceHighPo
int16_t LR1120::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginGFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
}

View file

@ -110,7 +110,8 @@ int16_t LR11x0::beginLRFHSS(uint8_t bw, uint8_t cr, bool narrowGrid, float tcxoV
state = setLrFhssConfig(bw, cr);
RADIOLIB_ASSERT(state);
state = setSyncWord(0x12AD101B);
uint8_t syncWord[] = { 0x12, 0xAD, 0x10, 0x1B };
state = setSyncWord(syncWord, 4);
RADIOLIB_ASSERT(state);
state = setRegulatorLDO();
@ -128,6 +129,8 @@ int16_t LR11x0::beginGNSS(uint8_t constellations, float tcxoVoltage) {
state = this->clearErrors();
RADIOLIB_ASSERT(state);
// set GNSS flag to reserve DIO11 for LF clock
this->gnss = true;
state = this->configLfClock(RADIOLIB_LR11X0_LF_BUSY_RELEASE_DISABLED | RADIOLIB_LR11X0_LF_CLK_XOSC);
RADIOLIB_ASSERT(state);
@ -353,10 +356,9 @@ int16_t LR11x0::standby(uint8_t mode, bool wakeup) {
this->mod->setRfSwitchState(Module::MODE_IDLE);
if(wakeup) {
// pull NSS low for a while to wake up
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->delay(1);
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
// send a NOP command - this pulls the NSS low to exit the sleep mode,
// while preventing interference with possible other SPI transactions
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_LR11X0_CMD_NOP, NULL, 0, false, false);
}
uint8_t buff[] = { mode };
@ -758,20 +760,16 @@ int16_t LR11x0::setCodingRate(uint8_t cr, bool longInterleave) {
return(setModulationParamsLoRa(this->spreadingFactor, this->bandwidth, this->codingRate, this->ldrOptimize));
}
int16_t LR11x0::setSyncWord(uint32_t syncWord) {
int16_t LR11x0::setSyncWord(uint8_t syncWord) {
// check active modem
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
return(setLoRaSyncWord(syncWord & 0xFF));
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
return(lrFhssSetSyncWord(syncWord));
if(type != RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
return(RADIOLIB_ERR_WRONG_MODEM);
return(setLoRaSyncWord(syncWord));
}
int16_t LR11x0::setBitRate(float br) {
@ -885,27 +883,36 @@ int16_t LR11x0::setSyncWord(uint8_t* syncWord, size_t len) {
uint8_t type = RADIOLIB_LR11X0_PACKET_TYPE_NONE;
int16_t state = getPacketType(&type);
RADIOLIB_ASSERT(state);
if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
if(type == RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
// update sync word length
this->syncWordLength = len*8;
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, RADIOLIB_LR11X0_MAX_PACKET_LENGTH, this->crcTypeGFSK, this->whitening);
RADIOLIB_ASSERT(state);
// sync word is passed most-significant byte first
uint8_t fullSyncWord[RADIOLIB_LR11X0_GFSK_SYNC_WORD_LEN] = { 0 };
memcpy(fullSyncWord, syncWord, len);
return(setGfskSyncWord(fullSyncWord));
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LORA) {
// with length set to 1 and LoRa modem active, assume it is the LoRa sync word
if(len > 1) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
return(setSyncWord(syncWord[0]));
} else if(type != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
} else if(type == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) {
// with length set to 4 and LR-FHSS modem active, assume it is the LR-FHSS sync word
if(len != sizeof(uint32_t)) {
return(RADIOLIB_ERR_INVALID_SYNC_WORD);
}
uint32_t sync = 0;
memcpy(&sync, syncWord, sizeof(uint32_t));
return(lrFhssSetSyncWord(sync));
}
// update sync word length
this->syncWordLength = len*8;
state = setPacketParamsGFSK(this->preambleLengthGFSK, this->preambleDetLength, this->syncWordLength, this->addrComp, this->packetType, RADIOLIB_LR11X0_MAX_PACKET_LENGTH, this->crcTypeGFSK, this->whitening);
RADIOLIB_ASSERT(state);
// sync word is passed most-significant byte first
uint8_t fullSyncWord[RADIOLIB_LR11X0_GFSK_SYNC_WORD_LEN] = { 0 };
memcpy(fullSyncWord, syncWord, len);
return(setGfskSyncWord(fullSyncWord));
return(RADIOLIB_ERR_WRONG_MODEM);
}
int16_t LR11x0::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
@ -2032,13 +2039,13 @@ int16_t LR11x0::getModem(ModemType_t* modem) {
switch(packetType) {
case(RADIOLIB_LR11X0_PACKET_TYPE_LORA):
*modem = ModemType_t::LoRa;
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_LR11X0_PACKET_TYPE_GFSK):
*modem = ModemType_t::FSK;
*modem = ModemType_t::RADIOLIB_MODEM_FSK;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS):
*modem = ModemType_t::LRFHSS;
*modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
return(RADIOLIB_ERR_NONE);
}
@ -2060,6 +2067,7 @@ int16_t LR11x0::modSetup(float tcxoVoltage, uint8_t modem) {
this->mod->spiConfig.stream = true;
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
this->mod->spiConfig.checkStatusCb = SPIcheckStatus;
this->gnss = false;
// try to find the LR11x0 chip - this will also reset the module at least once
if(!LR11x0::findChip(this->chipType)) {
@ -2446,7 +2454,7 @@ int16_t LR11x0::setDioIrqParams(uint32_t irq1, uint32_t irq2) {
}
int16_t LR11x0::setDioIrqParams(uint32_t irq) {
return(setDioIrqParams(irq,irq));
return(setDioIrqParams(irq, this->gnss ? 0 : irq));
}
int16_t LR11x0::clearIrq(uint32_t irq) {
@ -2457,7 +2465,7 @@ int16_t LR11x0::clearIrq(uint32_t irq) {
}
int16_t LR11x0::configLfClock(uint8_t setup) {
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK, true, &setup, 1));
return(this->SPIcommand(RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK, true, &setup, 1));
}
int16_t LR11x0::setTcxoMode(uint8_t tune, uint32_t delay) {

View file

@ -33,7 +33,7 @@
#define RADIOLIB_LR11X0_CMD_SET_DIO_AS_RF_SWITCH (0x0112)
#define RADIOLIB_LR11X0_CMD_SET_DIO_IRQ_PARAMS (0x0113)
#define RADIOLIB_LR11X0_CMD_CLEAR_IRQ (0x0114)
#define RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK (0x0116)
#define RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK (0x0116)
#define RADIOLIB_LR11X0_CMD_SET_TCXO_MODE (0x0117)
#define RADIOLIB_LR11X0_CMD_REBOOT (0x0118)
#define RADIOLIB_LR11X0_CMD_GET_VBAT (0x0119)
@ -281,7 +281,7 @@
#define RADIOLIB_LR11X0_IRQ_ALL (0x1BF80FFCUL) // 31 0 all interrupts
#define RADIOLIB_LR11X0_IRQ_NONE (0x00UL << 0) // 31 0 no interrupts
// RADIOLIB_LR11X0_CMD_CONFIG_LF_LOCK
// RADIOLIB_LR11X0_CMD_CONFIG_LF_CLOCK
#define RADIOLIB_LR11X0_LF_CLK_RC (0x00UL << 0) // 1 0 32.768 kHz source: RC oscillator
#define RADIOLIB_LR11X0_LF_CLK_XOSC (0x01UL << 0) // 1 0 crystal oscillator
#define RADIOLIB_LR11X0_LF_CLK_EXT (0x02UL << 0) // 1 0 external signal on DIO11
@ -1176,11 +1176,11 @@ class LR11x0: public PhysicalLayer {
int16_t setCodingRate(uint8_t cr, bool longInterleave = false);
/*!
\brief Sets LoRa or LR-FHSS sync word.
\param syncWord LoRa or LR-FHSS sync word to be set. For LoRa, only 8 least significant bits will be used
\brief Sets LoRa sync word.
\param syncWord LoRa sync word to be set.
\returns \ref status_codes
*/
int16_t setSyncWord(uint32_t syncWord);
int16_t setSyncWord(uint8_t syncWord);
/*!
\brief Sets GFSK bit rate. Allowed values range from 0.6 to 300.0 kbps.
@ -1828,6 +1828,7 @@ class LR11x0: public PhysicalLayer {
float dataRateMeasured = 0;
uint8_t wifiScanMode = 0;
bool gnss = false;
int16_t modSetup(float tcxoVoltage, uint8_t modem);
static int16_t SPIparseStatus(uint8_t in);

View file

@ -321,6 +321,10 @@ void RF69::clearFifoEmptyAction() {
clearDio1Action();
}
void RF69::setFifoThreshold(uint8_t threshold) {
this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_FIFO_THRESH, threshold, 6, 0);
}
void RF69::setFifoFullAction(void (*func)(void)) {
// set the interrupt
this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_FIFO_THRESH, RADIOLIB_RF69_FIFO_THRESH, 6, 0);

View file

@ -648,6 +648,14 @@ class RF69: public PhysicalLayer {
*/
void clearFifoEmptyAction();
/*!
\brief Set FIFO threshold level.
Be aware that threshold is also set in setFifoFullAction method.
setFifoThreshold method must be called AFTER calling setFifoFullAction!
\param threshold Threshold level in bytes.
*/
void setFifoThreshold(uint8_t threshold);
/*!
\brief Set interrupt service routine function to call when FIFO is full.
\param func Pointer to interrupt service routine.

View file

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

View file

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

View file

@ -116,13 +116,13 @@ int16_t SX1262::checkOutputPower(int8_t power, int8_t* clipped) {
int16_t SX1262::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
default:

View file

@ -117,13 +117,13 @@ int16_t SX1268::checkOutputPower(int8_t power, int8_t* clipped) {
int16_t SX1268::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
return(this->beginLRFHSS());
} break;
default:

View file

@ -74,7 +74,6 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleL
this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5;
this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV; // CCITT CRC configuration
this->preambleLengthFSK = preambleLength;
this->addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF;
// set module properties and perform initial setup
int16_t state = this->modSetup(tcxoVoltage, useRegulatorLDO, RADIOLIB_SX126X_PACKET_TYPE_GFSK);
@ -203,8 +202,8 @@ int16_t SX126x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// calculate timeout in ms (500% of expected time-on-air)
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
// calculate timeout in ms (5ms + 500 % of expected time-on-air)
RadioLibTime_t timeout = 5 + (getTimeOnAir(len) * 5) / 1000;
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
// start transmission
@ -468,8 +467,10 @@ int16_t SX126x::standby(uint8_t mode, bool wakeup) {
this->mod->setRfSwitchState(Module::MODE_IDLE);
if(wakeup) {
// pull NSS low to wake up
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
// send a NOP command - this pulls the NSS low to exit the sleep mode,
// while preventing interference with possible other SPI transactions
// see https://github.com/jgromes/RadioLib/discussions/1364
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_SX126X_CMD_NOP, NULL, 0, false, false);
}
uint8_t data[] = { mode };
@ -509,13 +510,15 @@ void SX126x::clearChannelScanAction() {
}
int16_t SX126x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
(void)addr;
// check packet length
if(len > RADIOLIB_SX126X_MAX_PACKET_LENGTH) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
// maximum packet length is decreased by 1 when address filtering is active
if((this->addrComp != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) {
if((RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) && (len > RADIOLIB_SX126X_MAX_PACKET_LENGTH - 1)) {
return(RADIOLIB_ERR_PACKET_TOO_LONG);
}
@ -526,13 +529,7 @@ int16_t SX126x::startTransmit(const uint8_t* data, size_t len, uint8_t addr) {
state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, len, this->headerType, this->invertIQEnabled);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
state = setPacketParamsFSK(this->preambleLengthFSK, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType, len);
// address is taken from the register
if(this->addrComp != RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF) {
RADIOLIB_ASSERT(state);
state = writeRegister(RADIOLIB_SX126X_REG_NODE_ADDRESS, &addr, 1);
}
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType, len);
} else if(modem != RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS) {
return(RADIOLIB_ERR_UNKNOWN);
@ -626,12 +623,6 @@ int16_t SX126x::finishTransmit() {
int16_t state = clearIrqStatus();
RADIOLIB_ASSERT(state);
// restore the original node address
if(getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
state = writeRegister(RADIOLIB_SX126X_REG_NODE_ADDRESS, &this->nodeAddr, 1);
RADIOLIB_ASSERT(state);
}
// set mode to standby to disable transmitter/RF switch
return(standby());
}
@ -641,7 +632,12 @@ int16_t SX126x::startReceive() {
}
int16_t SX126x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)len;
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX126X_LORA_HEADER_IMPLICIT) && (len != 0)) {
this->implicitLen = len;
}
int16_t state = startReceiveCommon(timeout, irqFlags, irqMask);
RADIOLIB_ASSERT(state);
@ -743,7 +739,7 @@ int16_t SX126x::startReceiveCommon(uint32_t timeout, RadioLibIrqFlags_t irqFlags
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
state = setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled);
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
state = setPacketParamsFSK(this->preambleLengthFSK, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
} else {
return(RADIOLIB_ERR_UNKNOWN);
}
@ -968,12 +964,15 @@ int16_t SX126x::setPreambleLength(size_t preambleLength) {
return(setPacketParams(this->preambleLengthLoRa, this->crcTypeLoRa, this->implicitLen, this->headerType, this->invertIQEnabled));
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
this->preambleLengthFSK = preambleLength;
this->preambleDetLength = preambleLength >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
preambleLength >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
preambleLength >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
preambleLength > 0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
// maximum preamble detector length is limited by sync word length
// for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
maxDetLen > 0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
return(setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType));
return(setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType));
}
return(RADIOLIB_ERR_UNKNOWN);
@ -1209,7 +1208,16 @@ int16_t SX126x::setSyncWord(uint8_t* syncWord, size_t len) {
// update packet parameters
this->syncWordLength = len * 8;
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
// maximum preamble detector length is limited by sync word length
// for details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45
uint8_t maxDetLen = RADIOLIB_MIN(this->syncWordLength, this->preambleLengthFSK);
this->preambleDetLength = maxDetLen >= 32 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_32 :
maxDetLen >= 24 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_24 :
maxDetLen >= 16 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_16 :
maxDetLen > 0 ? RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_8 :
RADIOLIB_SX126X_GFSK_PREAMBLE_DETECT_OFF;
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
return(state);
@ -1251,52 +1259,6 @@ int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
return(setSyncWord(syncWord, bytesLen));
}
int16_t SX126x::setNodeAddress(uint8_t addr) {
// check active modem
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// enable address filtering (node only)
this->addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE;
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
// set node address
this->nodeAddr = addr;
state = writeRegister(RADIOLIB_SX126X_REG_NODE_ADDRESS, &addr, 1);
return(state);
}
int16_t SX126x::setBroadcastAddress(uint8_t broadAddr) {
// check active modem
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// enable address filtering (node and broadcast)
this->addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST;
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
// set broadcast address
state = writeRegister(RADIOLIB_SX126X_REG_BROADCAST_ADDRESS, &broadAddr, 1);
return(state);
}
int16_t SX126x::disableAddressFiltering() {
// check active modem
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// disable address filtering
this->addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF;
return(setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening));
}
int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool inverted) {
// check active modem
uint8_t modem = getPacketType();
@ -1325,7 +1287,7 @@ int16_t SX126x::setCRC(uint8_t len, uint16_t initial, uint16_t polynomial, bool
return(RADIOLIB_ERR_INVALID_CRC_CONFIGURATION);
}
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
// write initial CRC value
@ -1367,7 +1329,7 @@ int16_t SX126x::setWhitening(bool enabled, uint16_t initial) {
// disable whitening
this->whitening = RADIOLIB_SX126X_GFSK_WHITENING_OFF;
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
} else {
@ -1387,7 +1349,7 @@ int16_t SX126x::setWhitening(bool enabled, uint16_t initial) {
state = writeRegister(RADIOLIB_SX126X_REG_WHITENING_INITIAL_MSB, data, 2);
RADIOLIB_ASSERT(state);
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, this->packetType);
RADIOLIB_ASSERT(state);
}
return(state);
@ -1682,13 +1644,13 @@ int16_t SX126x::getModem(ModemType_t* modem) {
uint8_t packetType = getPacketType();
switch(packetType) {
case(RADIOLIB_SX126X_PACKET_TYPE_LORA):
*modem = ModemType_t::LoRa;
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_SX126X_PACKET_TYPE_GFSK):
*modem = ModemType_t::FSK;
*modem = ModemType_t::RADIOLIB_MODEM_FSK;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_SX126X_PACKET_TYPE_LR_FHSS):
*modem = ModemType_t::LRFHSS;
*modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
return(RADIOLIB_ERR_NONE);
}
@ -2049,7 +2011,7 @@ int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) {
}
// set requested packet mode
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, mode, len);
int16_t state = setPacketParamsFSK(this->preambleLengthFSK, this->preambleDetLength, this->crcTypeFSK, this->syncWordLength, RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF, this->whitening, mode, len);
RADIOLIB_ASSERT(state);
// update cached value

View file

@ -823,6 +823,10 @@ class SX126x: public PhysicalLayer {
/*!
\brief Sets preamble length for LoRa or FSK modem. Allowed values range from 1 to 65535.
\param preambleLength Preamble length to be set in symbols (LoRa) or bits (FSK).
NOTE: In FSK mode, sync word length limits the preamble detector length
(the number of preamble bits that must be detected to start receiving packet).
For details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45.
Preamble detector length is adjusted automatically each time this method is called.
\returns \ref status_codes
*/
int16_t setPreambleLength(size_t preambleLength) override;
@ -887,6 +891,10 @@ class SX126x: public PhysicalLayer {
Can also set LR-FHSS sync word, but its length must be 4 bytes.
\param syncWord FSK sync word to be set.
\param len FSK sync word length in bytes.
NOTE: In FSK mode, sync word length limits the preamble detector length
(the number of preamble bits that must be detected to start receiving packet).
For details, see the note in SX1261 datasheet, Rev 2.1, section 6.2.2.1, page 45.
Preamble detector length is adjusted automatically each time this method is called.
\returns \ref status_codes
*/
int16_t setSyncWord(uint8_t* syncWord, size_t len) override;
@ -1278,10 +1286,9 @@ class SX126x: public PhysicalLayer {
bool ldroAuto = true;
uint32_t bitRate = 0, frequencyDev = 0;
uint8_t preambleDetLength = 0, rxBandwidth = 0, pulseShape = 0, crcTypeFSK = 0, syncWordLength = 0, addrComp = 0, whitening = 0, packetType = 0;
uint8_t preambleDetLength = 0, rxBandwidth = 0, pulseShape = 0, crcTypeFSK = 0, syncWordLength = 0, whitening = 0, packetType = 0;
uint16_t preambleLengthFSK = 0;
float rxBandwidthKhz = 0;
uint8_t nodeAddr = 0;
float dataRateMeasured = 0;

View file

@ -497,11 +497,13 @@ int16_t SX1272::autoLDRO() {
}
int16_t SX1272::implicitHeader(size_t len) {
return(setHeaderType(RADIOLIB_SX1272_HEADER_IMPL_MODE, len));
this->implicitHdr = true;
return(setHeaderType(RADIOLIB_SX1272_HEADER_IMPL_MODE, 2, len));
}
int16_t SX1272::explicitHeader() {
return(setHeaderType(RADIOLIB_SX1272_HEADER_EXPL_MODE));
this->implicitHdr = false;
return(setHeaderType(RADIOLIB_SX1272_HEADER_EXPL_MODE, 2));
}
int16_t SX1272::setBandwidthRaw(uint8_t newBandwidth) {
@ -521,11 +523,13 @@ int16_t SX1272::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
// write registers
Module* mod = this->getMod();
if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) {
this->implicitHdr = true;
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_HEADER_IMPL_MODE | (SX127x::crcEnabled ? RADIOLIB_SX1272_RX_CRC_MODE_ON : RADIOLIB_SX1272_RX_CRC_MODE_OFF), 2, 1);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6);
} else {
this->implicitHdr = false;
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1272_HEADER_EXPL_MODE | (SX127x::crcEnabled ? RADIOLIB_SX1272_RX_CRC_MODE_ON : RADIOLIB_SX1272_RX_CRC_MODE_OFF), 2, 1);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
@ -544,27 +548,6 @@ int16_t SX1272::setCodingRateRaw(uint8_t newCodingRate) {
return(state);
}
int16_t SX1272::setHeaderType(uint8_t headerType, size_t len) {
// check active modem
if(getActiveModem() != RADIOLIB_SX127X_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set requested packet mode
Module* mod = this->getMod();
int16_t state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, 2, 2);
RADIOLIB_ASSERT(state);
// set length to register
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
RADIOLIB_ASSERT(state);
// update cached value
SX127x::packetLength = len;
return(state);
}
int16_t SX1272::configFSK() {
// configure common registers
int16_t state = SX127x::configFSK();
@ -587,10 +570,10 @@ void SX1272::errataFix(bool rx) {
int16_t SX1272::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -316,7 +316,6 @@ class SX1272: public SX127x {
int16_t setBandwidthRaw(uint8_t newBandwidth);
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
int16_t configFSK();
void errataFix(bool rx) override;

View file

@ -117,10 +117,10 @@ int16_t SX1273::checkDataRate(DataRate_t dr) {
int16_t SX1273::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -81,10 +81,10 @@ int16_t SX1276::setFrequency(float freq) {
int16_t SX1276::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -159,10 +159,10 @@ int16_t SX1277::checkDataRate(DataRate_t dr) {
int16_t SX1277::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -535,11 +535,13 @@ int16_t SX1278::autoLDRO() {
}
int16_t SX1278::implicitHeader(size_t len) {
return(setHeaderType(RADIOLIB_SX1278_HEADER_IMPL_MODE, len));
this->implicitHdr = true;
return(setHeaderType(RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, len));
}
int16_t SX1278::explicitHeader() {
return(setHeaderType(RADIOLIB_SX1278_HEADER_EXPL_MODE));
this->implicitHdr = false;
return(setHeaderType(RADIOLIB_SX1278_HEADER_EXPL_MODE, 0));
}
int16_t SX1278::setBandwidthRaw(uint8_t newBandwidth) {
@ -559,11 +561,13 @@ int16_t SX1278::setSpreadingFactorRaw(uint8_t newSpreadingFactor) {
// write registers
Module* mod = this->getMod();
if(newSpreadingFactor == RADIOLIB_SX127X_SF_6) {
this->implicitHdr = true;
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_IMPL_MODE, 0, 0);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, RADIOLIB_SX127X_SF_6 | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_6, 2, 0);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECTION_THRESHOLD, RADIOLIB_SX127X_DETECTION_THRESHOLD_SF_6);
} else {
this->implicitHdr = false;
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, RADIOLIB_SX1278_HEADER_EXPL_MODE, 0, 0);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_2, newSpreadingFactor | RADIOLIB_SX127X_TX_MODE_SINGLE, 7, 3);
state |= mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DETECT_OPTIMIZE, RADIOLIB_SX127X_DETECT_OPTIMIZE_SF_7_12, 2, 0);
@ -582,27 +586,6 @@ int16_t SX1278::setCodingRateRaw(uint8_t newCodingRate) {
return(state);
}
int16_t SX1278::setHeaderType(uint8_t headerType, size_t len) {
// check active modem
if(getActiveModem() != RADIOLIB_SX127X_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set requested packet mode
Module* mod = this->getMod();
int16_t state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, 0, 0);
RADIOLIB_ASSERT(state);
// set length to register
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
RADIOLIB_ASSERT(state);
// update cached value
SX127x::packetLength = len;
return(state);
}
int16_t SX1278::configFSK() {
// configure common registers
int16_t state = SX127x::configFSK();
@ -707,10 +690,10 @@ void SX1278::errataFix(bool rx) {
int16_t SX1278::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -328,7 +328,6 @@ class SX1278: public SX127x {
int16_t setBandwidthRaw(uint8_t newBandwidth);
int16_t setSpreadingFactorRaw(uint8_t newSpreadingFactor);
int16_t setCodingRateRaw(uint8_t newCodingRate);
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
int16_t configFSK();
void errataFix(bool rx) override;

View file

@ -81,10 +81,10 @@ int16_t SX1279::setFrequency(float freq) {
int16_t SX1279::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginFSK());
} break;
default:

View file

@ -417,8 +417,9 @@ int16_t SX127x::startReceive(uint32_t timeout, RadioLibIrqFlags_t irqFlags, Radi
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_DIO_MAPPING_1, RADIOLIB_SX127X_DIO1_LORA_FHSS_CHANGE_CHANNEL, 5, 4);
}
// set expected packet length for SF6
if(this->spreadingFactor == 6) {
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->implicitHdr) && (len != 0)) {
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
this->packetLength = len;
}
@ -504,6 +505,10 @@ void SX127x::clearFifoEmptyAction() {
clearDio1Action();
}
void SX127x::setFifoThreshold(uint8_t threshold) {
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_THRESH, threshold, 5, 0);
}
void SX127x::setFifoFullAction(void (*func)(void)) {
// set the interrupt
this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FIFO_THRESH, RADIOLIB_SX127X_FIFO_THRESH, 5, 0);
@ -1197,9 +1202,10 @@ int16_t SX127x::setFrequencyRaw(float newFreq) {
uint32_t FRF = (newFreq * (uint32_t(1) << RADIOLIB_SX127X_DIV_EXPONENT)) / RADIOLIB_SX127X_CRYSTAL_FREQ;
// write registers
// lsb needs to be written no matter what in order for the module to update the frequency
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FRF_MSB, (FRF & 0xFF0000) >> 16);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FRF_MID, (FRF & 0x00FF00) >> 8);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FRF_LSB, FRF & 0x0000FF);
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_FRF_LSB, FRF & 0x0000FF, 7U, 0U, 2U, 0xFF, true);
return(state);
}
@ -1207,12 +1213,12 @@ size_t SX127x::getPacketLength(bool update) {
int16_t modem = getActiveModem();
if(modem == RADIOLIB_SX127X_LORA) {
if(this->spreadingFactor != 6) {
// get packet length for SF7 - SF12
if(!this->implicitHdr) {
// get packet length for explicit header mode
return(this->mod->SPIreadRegister(RADIOLIB_SX127X_REG_RX_NB_BYTES));
} else {
// return the cached value for SF6
// return the cached value for implicit header mode
return(this->packetLength);
}
@ -1320,7 +1326,7 @@ int16_t SX127x::setIrqFlags(uint32_t irq) {
uint8_t usedPinFlags = 0;
bool conflict = false;
int16_t modem = getActiveModem();
int16_t state;
int16_t state = RADIOLIB_ERR_NONE;
for(uint8_t i = 0; i <= 31; i++) {
// check if the bit is set
uint32_t irqBit = irq & (1UL << i);
@ -1760,10 +1766,10 @@ int16_t SX127x::getModem(ModemType_t* modem) {
int16_t packetType = getActiveModem();
switch(packetType) {
case(RADIOLIB_SX127X_LORA):
*modem = ModemType_t::LoRa;
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_SX127X_FSK_OOK):
*modem = ModemType_t::FSK;
*modem = ModemType_t::RADIOLIB_MODEM_FSK;
return(RADIOLIB_ERR_NONE);
}
@ -1856,6 +1862,27 @@ float SX127x::getRSSI(bool packet, bool skipReceive, int16_t offset) {
}
}
int16_t SX127x::setHeaderType(uint8_t headerType, uint8_t bitIndex, size_t len) {
// check active modem
if(getActiveModem() != RADIOLIB_SX127X_LORA) {
return(RADIOLIB_ERR_WRONG_MODEM);
}
// set requested packet mode
Module* mod = this->getMod();
int16_t state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_MODEM_CONFIG_1, headerType, bitIndex, bitIndex);
RADIOLIB_ASSERT(state);
// set length to register
state = mod->SPIsetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH, len);
RADIOLIB_ASSERT(state);
// update cached value
SX127x::packetLength = len;
return(state);
}
int16_t SX127x::setLowBatteryThreshold(int8_t level, uint32_t pin) {
// check disable
if(level < 0) {

View file

@ -761,6 +761,14 @@ class SX127x: public PhysicalLayer {
*/
void clearFifoEmptyAction();
/*!
\brief Set FIFO threshold level.
Be aware that threshold is also set in setFifoFullAction method.
setFifoThreshold method must be called AFTER calling setFifoFullAction!
\param threshold Threshold level in bytes.
*/
void setFifoThreshold(uint8_t threshold);
/*!
\brief Set interrupt service routine function to call when FIFO is full.
\param func Pointer to interrupt service routine.
@ -1241,12 +1249,14 @@ class SX127x: public PhysicalLayer {
uint8_t codingRate = 0;
bool crcEnabled = false;
bool ookEnabled = false;
bool implicitHdr = false;
int16_t configFSK();
int16_t getActiveModem();
int16_t setFrequencyRaw(float newFreq);
int16_t setBitRateCommon(float br, uint8_t fracRegAddr);
float getRSSI(bool packet, bool skipReceive, int16_t offset);
int16_t setHeaderType(uint8_t headerType, uint8_t bitIndex, size_t len = 0xFF);
#if !RADIOLIB_GODMODE
private:

View file

@ -327,8 +327,8 @@ int16_t SX128x::transmit(const uint8_t* data, size_t len, uint8_t addr) {
int16_t state = standby();
RADIOLIB_ASSERT(state);
// calculate timeout in ms (500% of expected time-on-air)
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
// calculate timeout in ms (5ms + 500 % of expected time-on-air)
RadioLibTime_t timeout = 5 + (getTimeOnAir(len) * 5) / 1000;
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
// start transmission
@ -480,8 +480,9 @@ int16_t SX128x::standby(uint8_t mode, bool wakeup) {
this->mod->setRfSwitchState(Module::MODE_IDLE);
if(wakeup) {
// pull NSS low to wake up
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
// send a NOP command - this pulls the NSS low to exit the sleep mode,
// while preventing interference with possible other SPI transactions
(void)this->mod->SPIwriteStream((uint16_t)RADIOLIB_SX128X_CMD_NOP, NULL, 0, false, false);
}
uint8_t data[] = { mode };
@ -589,7 +590,11 @@ int16_t SX128x::startReceive() {
}
int16_t SX128x::startReceive(uint16_t timeout, RadioLibIrqFlags_t irqFlags, RadioLibIrqFlags_t irqMask, size_t len) {
(void)len;
// in implicit header mode, use the provided length if it is nonzero
// otherwise we trust the user has previously set the payload length manually
if((this->headerType == RADIOLIB_SX128X_LORA_HEADER_IMPLICIT) && (len != 0)) {
this->payloadLen = len;
}
// check active modem
if(getPacketType() == RADIOLIB_SX128X_PACKET_TYPE_RANGING) {
@ -858,10 +863,10 @@ int16_t SX128x::checkOutputPower(int8_t pwr, int8_t* clipped) {
int16_t SX128x::setModem(ModemType_t modem) {
switch(modem) {
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
return(this->begin());
} break;
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
return(this->beginGFSK());
} break;
default:
@ -875,10 +880,10 @@ int16_t SX128x::getModem(ModemType_t* modem) {
uint8_t packetType = getPacketType();
switch(packetType) {
case(RADIOLIB_SX128X_PACKET_TYPE_LORA):
*modem = ModemType_t::LoRa;
*modem = ModemType_t::RADIOLIB_MODEM_LORA;
return(RADIOLIB_ERR_NONE);
case(RADIOLIB_SX128X_PACKET_TYPE_GFSK):
*modem = ModemType_t::FSK;
*modem = ModemType_t::RADIOLIB_MODEM_FSK;
return(RADIOLIB_ERR_NONE);
}

View file

@ -615,43 +615,7 @@ void nRF24::SPIwriteTxPayload(uint8_t* data, uint8_t numBytes) {
}
void nRF24::SPItransfer(uint8_t cmd, bool write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes) {
// prepare the buffers
size_t buffLen = 1 + numBytes;
#if RADIOLIB_STATIC_ONLY
uint8_t buffOut[RADIOLIB_STATIC_ARRAY_SIZE];
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
#else
uint8_t* buffOut = new uint8_t[buffLen];
uint8_t* buffIn = new uint8_t[buffLen];
#endif
uint8_t* buffOutPtr = buffOut;
// copy the command
*(buffOutPtr++) = cmd;
// copy the data
if(write) {
memcpy(buffOutPtr, dataOut, numBytes);
} else {
memset(buffOutPtr, 0x00, numBytes);
}
// do the transfer
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelLow);
this->mod->hal->spiBeginTransaction();
this->mod->hal->spiTransfer(buffOut, buffLen, buffIn);
this->mod->hal->spiEndTransaction();
this->mod->hal->digitalWrite(this->mod->getCs(), this->mod->hal->GpioLevelHigh);
// copy the data
if(!write) {
memcpy(dataIn, &buffIn[1], numBytes);
}
#if !RADIOLIB_STATIC_ONLY
delete[] buffOut;
delete[] buffIn;
#endif
(void)this->mod->SPItransferStream(&cmd, 1, write, dataOut, dataIn, numBytes, false);
}
#endif

View file

@ -12,13 +12,11 @@ LoRaWANNode::LoRaWANNode(PhysicalLayer* phy, const LoRaWANBand_t* band, uint8_t
this->channels[RADIOLIB_LORAWAN_DIR_RX2] = this->band->rx2;
this->txPowerMax = this->band->powerMax;
this->subBand = subBand;
this->dwellTimeEnabledUp = this->dwellTimeUp != 0;
this->dwellTimeEnabledDn = this->dwellTimeDn != 0;
memset(this->channelPlan, 0, sizeof(this->channelPlan));
}
#if defined(RADIOLIB_BUILD_ARDUINO)
int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t fPort, String& strDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
int16_t LoRaWANNode::sendReceive(const String& strUp, uint8_t fPort, String& strDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
int16_t state = RADIOLIB_ERR_UNKNOWN;
const char* dataUp = strUp.c_str();
@ -28,7 +26,7 @@ int16_t LoRaWANNode::sendReceive(String& strUp, uint8_t fPort, String& strDown,
size_t lenDown = 0;
uint8_t dataDown[251];
state = this->sendReceive((uint8_t*)dataUp, strlen(dataUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown);
state = this->sendReceive((const uint8_t*)dataUp, strlen(dataUp), fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown);
if(state == RADIOLIB_ERR_NONE) {
// add null terminator
@ -55,7 +53,7 @@ int16_t LoRaWANNode::sendReceive(const char* strUp, uint8_t fPort, uint8_t* data
return(this->sendReceive((uint8_t*)strUp, strlen(strUp), fPort, dataDown, lenDown, isConfirmed, eventUp, eventDown));
}
int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fPort, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
// build a temporary buffer
// LoRaWAN downlinks can have 250 bytes at most with 1 extra byte for NULL
size_t lenDown = 0;
@ -64,7 +62,7 @@ int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, b
return(this->sendReceive(dataUp, lenUp, fPort, dataDown, &lenDown, isConfirmed, eventUp, eventDown));
}
int16_t LoRaWANNode::sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
int16_t LoRaWANNode::sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed, LoRaWANEvent_t* eventUp, LoRaWANEvent_t* eventDown) {
if(!dataUp || !dataDown || !lenDown) {
return(RADIOLIB_ERR_NULL_POINTER);
}
@ -241,7 +239,7 @@ uint8_t* LoRaWANNode::getBufferNonces() {
return(this->bufferNonces);
}
int16_t LoRaWANNode::setBufferNonces(uint8_t* persistentBuffer) {
int16_t LoRaWANNode::setBufferNonces(const uint8_t* persistentBuffer) {
if(this->isActivated()) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Did not update buffer: session already active");
return(RADIOLIB_ERR_NONE);
@ -292,7 +290,8 @@ void LoRaWANNode::clearSession() {
this->confFCntDown = RADIOLIB_LORAWAN_FCNT_NONE;
this->adrFCnt = 0;
// reset number of retransmissions from ADR
// reset ADR state
this->txPowerSteps = 0;
this->nbTrans = 1;
// clear CSMA settings
@ -307,7 +306,7 @@ void LoRaWANNode::createSession(uint16_t lwMode, uint8_t initialDr) {
// setup JoinRequest uplink/downlink frequencies and datarates
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
this->selectChannelPlanDyn(true);
this->selectChannelPlanDyn();
} else {
this->selectChannelPlanFix();
}
@ -346,15 +345,9 @@ void LoRaWANNode::createSession(uint16_t lwMode, uint8_t initialDr) {
}
// if there is no (channel that allowed the) user-specified datarate, use a default datarate
// we use the floor of the average datarate of the first enabled channel
if(initialDr == RADIOLIB_LORAWAN_DATA_RATE_UNUSED) {
for(int i = 0; i < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; i++) {
if(this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i].enabled) {
uint8_t drMin = this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i].drMin;
uint8_t drMax = this->channelPlan[RADIOLIB_LORAWAN_UPLINK][i].drMax;
drUp = (drMin + drMax) / 2;
}
}
// use the specified datarate from the first channel (this is always defined)
drUp = this->channelPlan[RADIOLIB_LORAWAN_UPLINK][0].dr;
}
}
@ -464,7 +457,7 @@ uint8_t* LoRaWANNode::getBufferSession() {
return(this->bufferSession);
}
int16_t LoRaWANNode::setBufferSession(uint8_t* persistentBuffer) {
int16_t LoRaWANNode::setBufferSession(const uint8_t* persistentBuffer) {
if(this->isActivated()) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Did not update buffer: session already active");
return(RADIOLIB_ERR_NONE);
@ -588,7 +581,7 @@ int16_t LoRaWANNode::setBufferSession(uint8_t* persistentBuffer) {
return(state);
}
int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey) {
int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, const uint8_t* nwkKey, const uint8_t* appKey) {
if(!appKey) {
return(RADIOLIB_ERR_NULL_POINTER);
}
@ -617,7 +610,7 @@ int16_t LoRaWANNode::beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKe
return(RADIOLIB_ERR_NONE);
}
int16_t LoRaWANNode::beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey) {
int16_t LoRaWANNode::beginABP(uint32_t addr, const uint8_t* fNwkSIntKey, const uint8_t* sNwkSIntKey, const uint8_t* nwkSEncKey, const uint8_t* appSKey) {
if(!nwkSEncKey || !appSKey) {
return(RADIOLIB_ERR_NULL_POINTER);
}
@ -723,7 +716,7 @@ int16_t LoRaWANNode::processJoinAccept(LoRaWANJoinEvent_t *joinEvent) {
}
} else {
// for v1.0.4, the JoinNonce is simply a non-repeating value (we only check the last value)
if(joinNonceNew == this->joinNonce) {
if((this->joinNonce > 0) && (joinNonceNew == this->joinNonce)) {
return(RADIOLIB_ERR_JOIN_NONCE_INVALID);
}
}
@ -767,7 +760,7 @@ int16_t LoRaWANNode::processJoinAccept(LoRaWANJoinEvent_t *joinEvent) {
// in case of dynamic band, reset the channels to clear JoinRequest-specific channels
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
this->selectChannelPlanDyn(false);
this->selectChannelPlanDyn();
}
uint8_t cOcts[5];
@ -846,8 +839,10 @@ int16_t LoRaWANNode::processJoinAccept(LoRaWANJoinEvent_t *joinEvent) {
this->bufferNonces[RADIOLIB_LORAWAN_NONCES_ACTIVE] = (uint8_t)true;
// generate the signature of the Nonces buffer, and store it in the last two bytes of the Nonces buffer
// also store this signature in the Session buffer to make sure these buffers match
uint16_t signature = LoRaWANNode::checkSum16(this->bufferNonces, RADIOLIB_LORAWAN_NONCES_BUF_SIZE - 2);
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_SIGNATURE], signature);
LoRaWANNode::hton<uint16_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE], signature);
// store DevAddr and all keys
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_DEV_ADDR], this->devAddr);
@ -855,9 +850,6 @@ int16_t LoRaWANNode::processJoinAccept(LoRaWANJoinEvent_t *joinEvent) {
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_NWK_SENC_KEY], this->nwkSEncKey, RADIOLIB_AES128_KEY_SIZE);
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY], this->fNwkSIntKey, RADIOLIB_AES128_KEY_SIZE);
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY], this->sNwkSIntKey, RADIOLIB_AES128_KEY_SIZE);
// set the signature of the Nonces buffer in the Session buffer
LoRaWANNode::hton<uint16_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE], signature);
// store network parameters
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_HOMENET_ID], this->homeNetId);
@ -913,7 +905,7 @@ int16_t LoRaWANNode::activateOTAA(uint8_t joinDr, LoRaWANJoinEvent_t *joinEvent)
RADIOLIB_ASSERT(state);
// calculate JoinRequest time-on-air in milliseconds
if(this->dwellTimeEnabledUp) {
if(this->dwellTimeUp) {
RadioLibTime_t toa = this->phyLayer->getTimeOnAir(RADIOLIB_LORAWAN_JOIN_REQUEST_LEN) / 1000;
if(toa > this->dwellTimeUp) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Dwell time exceeded: ToA = %lu, max = %d", (unsigned long)toa, this->dwellTimeUp);
@ -982,8 +974,10 @@ int16_t LoRaWANNode::activateABP(uint8_t initialDr) {
this->bufferNonces[RADIOLIB_LORAWAN_NONCES_ACTIVE] = (uint8_t)true;
// generate the signature of the Nonces buffer, and store it in the last two bytes of the Nonces buffer
// also store this signature in the Session buffer to make sure these buffers match
uint16_t signature = LoRaWANNode::checkSum16(this->bufferNonces, RADIOLIB_LORAWAN_NONCES_BUF_SIZE - 2);
LoRaWANNode::hton<uint16_t>(&this->bufferNonces[RADIOLIB_LORAWAN_NONCES_SIGNATURE], signature);
LoRaWANNode::hton<uint16_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE], signature);
// store DevAddr and all keys
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_DEV_ADDR], this->devAddr);
@ -992,9 +986,6 @@ int16_t LoRaWANNode::activateABP(uint8_t initialDr) {
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY], this->fNwkSIntKey, RADIOLIB_AES128_BLOCK_SIZE);
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY], this->sNwkSIntKey, RADIOLIB_AES128_BLOCK_SIZE);
// set the signature of the Nonces buffer in the Session buffer
LoRaWANNode::hton<uint16_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE], signature);
// store network parameters
LoRaWANNode::hton<uint32_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_HOMENET_ID], this->homeNetId);
LoRaWANNode::hton<uint8_t>(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_VERSION], this->rev);
@ -1139,15 +1130,26 @@ void LoRaWANNode::adrBackoff() {
}
}
// try to decrease the datarate
// if datarate can be decreased, try it
if(this->channels[RADIOLIB_LORAWAN_UPLINK].dr > 0) {
if(this->setDatarate(this->channels[RADIOLIB_LORAWAN_UPLINK].dr - 1) == RADIOLIB_ERR_NONE) {
return;
uint8_t oldDr = this->channels[RADIOLIB_LORAWAN_UPLINK].dr;
if(this->setDatarate(oldDr - 1) == RADIOLIB_ERR_NONE) {
// if there is no dwell time limit, a lower datarate is OK
if(!this->dwellTimeUp) {
return;
}
// if there is a dwell time limit, check if this datarate allows an empty uplink
if(this->phyLayer->getTimeOnAir(13) / 1000 < this->dwellTimeUp) {
return;
}
// if the Time on Air of an empty uplink exceeded the dwell time, revert
this->setDatarate(oldDr);
}
}
if(this->band->bandType == RADIOLIB_LORAWAN_BAND_DYNAMIC) {
this->selectChannelPlanDyn(false); // revert to default frequencies
this->selectChannelPlanDyn(); // revert to default frequencies
} else {
this->selectChannelPlanFix(); // go back to default selected subband
}
@ -1159,7 +1161,7 @@ void LoRaWANNode::adrBackoff() {
return;
}
void LoRaWANNode::composeUplink(uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t fPort, bool isConfirmed) {
void LoRaWANNode::composeUplink(const uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t fPort, bool isConfirmed) {
// set the packet fields
if(isConfirmed) {
out[RADIOLIB_LORAWAN_FHDR_LEN_START_OFFS] = RADIOLIB_LORAWAN_MHDR_MTYPE_CONF_DATA_UP;
@ -1175,10 +1177,18 @@ void LoRaWANNode::composeUplink(uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_
out[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= RADIOLIB_LORAWAN_FCTRL_ADR_ENABLED;
// AdrAckReq is set if no downlink has been received for >=Limit uplinks
// but it is unset once backoff has been completed (which is internally denoted by adrFCnt == FCNT_NONE)
uint32_t adrLimit = 0x01 << this->adrLimitExp;
if(this->adrFCnt != RADIOLIB_LORAWAN_FCNT_NONE && (this->fCntUp - this->adrFCnt) >= adrLimit) {
out[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= RADIOLIB_LORAWAN_FCTRL_ADR_ACK_REQ;
if(this->rev == 1) {
// AdrAckReq is unset once backoff has been completed
// (which is internally denoted by adrFCnt == FCNT_NONE)
if(this->adrFCnt != RADIOLIB_LORAWAN_FCNT_NONE && (this->fCntUp - this->adrFCnt) >= adrLimit) {
out[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= RADIOLIB_LORAWAN_FCTRL_ADR_ACK_REQ;
}
} else { // rev == 0
// AdrAckReq is always set, also when backoff has been completed
if(this->adrFCnt == RADIOLIB_LORAWAN_FCNT_NONE || (this->fCntUp - this->adrFCnt) >= adrLimit) {
out[RADIOLIB_LORAWAN_FHDR_FCTRL_POS] |= RADIOLIB_LORAWAN_FCTRL_ADR_ACK_REQ;
}
}
}
@ -1561,7 +1571,7 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
#if !RADIOLIB_STATIC_ONLY
delete[] downlinkMsg;
#endif
return(RADIOLIB_ERR_INVALID_PORT);
return(RADIOLIB_ERR_DOWNLINK_MALFORMED);
}
// get the frame counter
@ -1641,8 +1651,8 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
isConfirmedDown = true;
}
// a downlink was received, so reset the ADR counter to the last uplink's fCnt
this->adrFCnt = this->getFCntUp();
// a downlink was received, so restart the ADR counter with the next uplink
this->adrFCnt = this->getFCntUp() + 1;
// if this downlink is on FPort 0, the FOptsLen is the length of the payload
// in any other case, the payload (length) is user accessible
@ -1710,15 +1720,24 @@ int16_t LoRaWANNode::parseDownlink(uint8_t* data, size_t* len, LoRaWANEvent_t* e
while(procLen < fOptsLen) {
cid = *mPtr; // MAC id is the first byte
// fetch length of MAC downlink payload
state = this->getMacLen(cid, &fLen, RADIOLIB_LORAWAN_DOWNLINK, true);
RADIOLIB_ASSERT(state);
if(state != RADIOLIB_ERR_NONE) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Unknown MAC CID %02x", cid);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Skipping remaining MAC commands");
break;
}
// already fetch length of MAC answer payload (if any)
uint8_t fLenRe = 0;
state = this->getMacLen(cid, &fLenRe, RADIOLIB_LORAWAN_UPLINK, true);
RADIOLIB_ASSERT(state);
(void)this->getMacLen(cid, &fLenRe, RADIOLIB_LORAWAN_UPLINK, true);
// don't care about return value: the previous getMacLen() would have failed anyway
if(procLen + fLen > fOptsLen) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Incomplete MAC command %02x (%d bytes, expected %d)", cid, fOptsLen, fLen);
return(RADIOLIB_ERR_INVALID_CID);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Incomplete MAC command %02x (%d bytes, expected %d)", cid, fOptsLen - procLen, fLen);
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("WARNING: Skipping remaining MAC commands");
break;
}
bool reply = false;
@ -1929,7 +1948,6 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
// only acknowledge if the radio is able to operate at or below the requested power level
if(state == RADIOLIB_ERR_NONE || (state == RADIOLIB_ERR_INVALID_OUTPUT_POWER && powerActual < power)) {
pwrAck = 1;
this->txPowerSteps = macTxSteps;
} else {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("ADR failed to configure Tx power %d, code %d!", power, state);
}
@ -1941,10 +1959,17 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
// if ACK not completely successful, revert and stop
if(optOut[0] != 0x07) {
this->applyChannelMask(chMaskGrp0123, chMaskGrp45);
this->setAvailableChannels(chMaskActive);
// according to paragraph 4.3.1.1, if ADR is disabled,
// the ADR channel mask must be accepted even if drAck/pwrAck fails.
// therefore, only revert the channel mask if ADR is enabled.
if(this->adrEnabled) {
this->applyChannelMask(chMaskGrp0123, chMaskGrp45);
this->setAvailableChannels(chMaskActive);
}
// revert datarate
this->channels[RADIOLIB_LORAWAN_UPLINK].dr = currentDr;
// Tx power was not modified
// Tx power was not actually modified
return(true);
}
@ -2211,10 +2236,7 @@ bool LoRaWANNode::execMacCommand(uint8_t cid, uint8_t* optIn, uint8_t lenIn, uin
this->txPowerMax = eirpEncoding[maxEirpRaw];
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("TxParamSetupReq: dlDwell = %d, ulDwell = %d, maxEirp = %d dBm", dlDwell, ulDwell, eirpEncoding[maxEirpRaw]);
this->dwellTimeEnabledUp = ulDwell ? true : false;
this->dwellTimeUp = ulDwell ? RADIOLIB_LORAWAN_DWELL_TIME : 0;
this->dwellTimeEnabledDn = dlDwell ? true : false;
this->dwellTimeDn = dlDwell ? RADIOLIB_LORAWAN_DWELL_TIME : 0;
memcpy(&this->bufferSession[RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP], optIn, lenIn);
@ -2699,11 +2721,13 @@ void LoRaWANNode::setDutyCycle(bool enable, RadioLibTime_t msPerHour) {
}
void LoRaWANNode::setDwellTime(bool enable, RadioLibTime_t msPerUplink) {
this->dwellTimeEnabledUp = enable;
if(msPerUplink == 0) {
this->dwellTimeUp = this->band->dwellTimeUp;
} else {
if(!enable) {
this->dwellTimeUp = 0;
} else if(msPerUplink > 0) {
this->dwellTimeUp = msPerUplink;
} else { //msPerUplink == 0
this->dwellTimeUp = this->band->dwellTimeUp;
}
}
@ -2776,11 +2800,11 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
// set modem-dependent functions
switch(this->band->dataRates[chnl->dr] & RADIOLIB_LORAWAN_DATA_RATE_MODEM) {
case(RADIOLIB_LORAWAN_DATA_RATE_LORA):
if(modem != ModemType_t::LoRa) {
state = this->phyLayer->setModem(ModemType_t::LoRa);
if(modem != ModemType_t::RADIOLIB_MODEM_LORA) {
state = this->phyLayer->setModem(ModemType_t::RADIOLIB_MODEM_LORA);
RADIOLIB_ASSERT(state);
}
modem = ModemType_t::LoRa;
modem = ModemType_t::RADIOLIB_MODEM_LORA;
// downlink messages are sent with inverted IQ
if(dir == RADIOLIB_LORAWAN_DOWNLINK) {
state = this->phyLayer->invertIQ(true);
@ -2791,11 +2815,11 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
break;
case(RADIOLIB_LORAWAN_DATA_RATE_FSK):
if(modem != ModemType_t::FSK) {
state = this->phyLayer->setModem(ModemType_t::FSK);
if(modem != ModemType_t::RADIOLIB_MODEM_FSK) {
state = this->phyLayer->setModem(ModemType_t::RADIOLIB_MODEM_FSK);
RADIOLIB_ASSERT(state);
}
modem = ModemType_t::FSK;
modem = ModemType_t::RADIOLIB_MODEM_FSK;
state = this->phyLayer->setDataShaping(RADIOLIB_SHAPING_1_0);
RADIOLIB_ASSERT(state);
state = this->phyLayer->setEncoding(RADIOLIB_ENCODING_WHITENING);
@ -2803,11 +2827,11 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
break;
case(RADIOLIB_LORAWAN_DATA_RATE_LR_FHSS):
if(modem != ModemType_t::LRFHSS) {
state = this->phyLayer->setModem(ModemType_t::LRFHSS);
if(modem != ModemType_t::RADIOLIB_MODEM_LRFHSS) {
state = this->phyLayer->setModem(ModemType_t::RADIOLIB_MODEM_LRFHSS);
RADIOLIB_ASSERT(state);
}
modem = ModemType_t::LRFHSS;
modem = ModemType_t::RADIOLIB_MODEM_LRFHSS;
break;
default:
@ -2836,7 +2860,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
uint8_t syncWordLen = 0;
size_t preLen = 0;
switch(modem) {
case(ModemType_t::FSK): {
case(ModemType_t::RADIOLIB_MODEM_FSK): {
preLen = 8*RADIOLIB_LORAWAN_GFSK_PREAMBLE_LEN;
syncWord[0] = (uint8_t)(RADIOLIB_LORAWAN_GFSK_SYNC_WORD >> 16);
syncWord[1] = (uint8_t)(RADIOLIB_LORAWAN_GFSK_SYNC_WORD >> 8);
@ -2846,7 +2870,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
dr.fsk.bitRate, dr.fsk.freqDev);
} break;
case(ModemType_t::LoRa): {
case(ModemType_t::RADIOLIB_MODEM_LORA): {
preLen = RADIOLIB_LORAWAN_LORA_PREAMBLE_LEN;
syncWord[0] = RADIOLIB_LORAWAN_LORA_SYNC_WORD;
syncWordLen = 1;
@ -2854,7 +2878,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
dr.lora.spreadingFactor, dr.lora.bandwidth, dr.lora.codingRate, dir ? 'D' : 'U');
} break;
case(ModemType_t::LRFHSS): {
case(ModemType_t::RADIOLIB_MODEM_LRFHSS): {
syncWord[0] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 24);
syncWord[1] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 16);
syncWord[2] = (uint8_t)(RADIOLIB_LORAWAN_LR_FHSS_SYNC_WORD >> 8);
@ -2875,7 +2899,7 @@ int16_t LoRaWANNode::setPhyProperties(const LoRaWANChannel_t* chnl, uint8_t dir,
if(pre) {
preLen = pre;
}
if(modem != ModemType_t::LRFHSS) {
if(modem != ModemType_t::RADIOLIB_MODEM_LRFHSS) {
state = this->phyLayer->setPreambleLength(preLen);
}
return(state);
@ -2970,7 +2994,7 @@ void LoRaWANNode::getChannelPlanMask(uint64_t* chMaskGrp0123, uint32_t* chMaskGr
}
}
void LoRaWANNode::selectChannelPlanDyn(bool joinRequest) {
void LoRaWANNode::selectChannelPlanDyn() {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("Setting up dynamic channels");
size_t num = 0;
@ -2980,15 +3004,6 @@ void LoRaWANNode::selectChannelPlanDyn(bool joinRequest) {
this->channelPlan[RADIOLIB_LORAWAN_DOWNLINK][num] = this->band->txFreqs[num];
}
// if we're about to send a JoinRequest, copy the JoinRequest channels to the next slots
if(joinRequest) {
size_t numJR = 0;
for(; numJR < 3 && this->band->txJoinReq[num].enabled; numJR++, num++) {
this->channelPlan[RADIOLIB_LORAWAN_UPLINK][num] = this->band->txFreqs[num];
this->channelPlan[RADIOLIB_LORAWAN_DOWNLINK][num] = this->band->txFreqs[num];
}
}
// clear all remaining channels
for(; num < RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS; num++) {
this->channelPlan[RADIOLIB_LORAWAN_UPLINK][num] = RADIOLIB_LORAWAN_CHANNEL_NONE;
@ -3115,7 +3130,7 @@ int16_t LoRaWANNode::selectChannels() {
// if downlink dwelltime is enabled, datarate < 2 cannot be used, so clip to 2
// only in use on AS923_x bands
if(this->dwellTimeEnabledDn && rx1Dr < 2) {
if(this->dwellTimeDn && rx1Dr < 2) {
rx1Dr = 2;
}
this->channels[RADIOLIB_LORAWAN_DOWNLINK].dr = rx1Dr;
@ -3267,7 +3282,7 @@ uint8_t LoRaWANNode::getMaxPayloadLen() {
maxLen += 13; // mandatory FHDR is 12/13 bytes
// if not limited by dwell-time, just return maximum
if(!this->dwellTimeEnabledUp) {
if(!this->dwellTimeUp) {
// subtract FHDR (13 bytes) as well as any FOpts
return(maxLen - 13 - this->fOptsUpLen);
}
@ -3305,7 +3320,7 @@ int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) {
switch(dataRateBand & RADIOLIB_LORAWAN_DATA_RATE_MODEM) {
case(RADIOLIB_LORAWAN_DATA_RATE_LORA):
modemNew = ModemType_t::LoRa;
modemNew = ModemType_t::RADIOLIB_MODEM_LORA;
dataRate->lora.spreadingFactor = ((dataRateBand & RADIOLIB_LORAWAN_DATA_RATE_SF) >> 3) + 7;
switch(dataRateBand & RADIOLIB_LORAWAN_DATA_RATE_BW) {
case(RADIOLIB_LORAWAN_DATA_RATE_BW_125_KHZ):
@ -3323,12 +3338,12 @@ int16_t LoRaWANNode::findDataRate(uint8_t dr, DataRate_t* dataRate) {
dataRate->lora.codingRate = 5;
break;
case(RADIOLIB_LORAWAN_DATA_RATE_FSK):
modemNew = ModemType_t::FSK;
modemNew = ModemType_t::RADIOLIB_MODEM_FSK;
dataRate->fsk.bitRate = 50;
dataRate->fsk.freqDev = 25;
break;
case(RADIOLIB_LORAWAN_DATA_RATE_LR_FHSS):
modemNew = ModemType_t::LRFHSS;
modemNew = ModemType_t::RADIOLIB_MODEM_LRFHSS;
switch(dataRateBand & RADIOLIB_LORAWAN_DATA_RATE_BW) {
case(RADIOLIB_LORAWAN_DATA_RATE_BW_137_KHZ):
dataRate->lrFhss.bw = 0x02; // specific encoding
@ -3416,7 +3431,7 @@ void LoRaWANNode::processAES(const uint8_t* in, size_t len, uint8_t* key, uint8_
}
}
int16_t LoRaWANNode::checkBufferCommon(uint8_t *buffer, uint16_t size) {
int16_t LoRaWANNode::checkBufferCommon(const uint8_t *buffer, uint16_t size) {
// check if there are actually values in the buffer
size_t i = 0;
for(; i < size; i++) {

View file

@ -232,7 +232,7 @@ struct LoRaWANMacCommand_t {
#define RADIOLIB_LORAWAN_MAC_COMMAND_NONE { .cid = 0, .lenDn = 0, .lenUp = 0, .persist = false, .user = false }
constexpr LoRaWANMacCommand_t MacTable[RADIOLIB_LORAWAN_NUM_MAC_COMMANDS] = {
{ RADIOLIB_LORAWAN_MAC_RESET, 1, 1, false, false },
{ RADIOLIB_LORAWAN_MAC_RESET, 1, 1, true, false },
{ RADIOLIB_LORAWAN_MAC_LINK_CHECK, 2, 0, false, true },
{ RADIOLIB_LORAWAN_MAC_LINK_ADR, 4, 1, false, false },
{ RADIOLIB_LORAWAN_MAC_DUTY_CYCLE, 1, 0, false, false },
@ -242,7 +242,7 @@ constexpr LoRaWANMacCommand_t MacTable[RADIOLIB_LORAWAN_NUM_MAC_COMMANDS] = {
{ RADIOLIB_LORAWAN_MAC_RX_TIMING_SETUP, 1, 0, true, false },
{ RADIOLIB_LORAWAN_MAC_TX_PARAM_SETUP, 1, 0, true, false },
{ RADIOLIB_LORAWAN_MAC_DL_CHANNEL, 4, 1, true, false },
{ RADIOLIB_LORAWAN_MAC_REKEY, 1, 1, false, false },
{ RADIOLIB_LORAWAN_MAC_REKEY, 1, 1, true, false },
{ RADIOLIB_LORAWAN_MAC_ADR_PARAM_SETUP, 1, 0, false, false },
{ RADIOLIB_LORAWAN_MAC_DEVICE_TIME, 5, 0, false, true },
{ RADIOLIB_LORAWAN_MAC_FORCE_REJOIN, 2, 0, false, false },
@ -273,8 +273,8 @@ enum LoRaWANSchemeSession_t {
RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY = RADIOLIB_LORAWAN_SESSION_APP_SKEY + RADIOLIB_AES128_KEY_SIZE, // 16 bytes
RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY = RADIOLIB_LORAWAN_SESSION_FNWK_SINT_KEY + RADIOLIB_AES128_KEY_SIZE, // 16 bytes
RADIOLIB_LORAWAN_SESSION_DEV_ADDR = RADIOLIB_LORAWAN_SESSION_SNWK_SINT_KEY + RADIOLIB_AES128_KEY_SIZE, // 4 bytes
RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE = RADIOLIB_LORAWAN_SESSION_DEV_ADDR + sizeof(uint32_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_FCNT_UP = RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE + 2, // 4 bytes
RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE = RADIOLIB_LORAWAN_SESSION_DEV_ADDR + sizeof(uint32_t), // 2 bytes
RADIOLIB_LORAWAN_SESSION_FCNT_UP = RADIOLIB_LORAWAN_SESSION_NONCES_SIGNATURE + sizeof(uint16_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_FCNT_UP + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_A_FCNT_DOWN = RADIOLIB_LORAWAN_SESSION_N_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
RADIOLIB_LORAWAN_SESSION_ADR_FCNT = RADIOLIB_LORAWAN_SESSION_A_FCNT_DOWN + sizeof(uint32_t), // 4 bytes
@ -291,11 +291,7 @@ enum LoRaWANSchemeSession_t {
RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_RX_TIMING_SETUP + 1, // 1 byte
RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_TX_PARAM_SETUP + 1, // 1 byte
RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP = RADIOLIB_LORAWAN_SESSION_ADR_PARAM_SETUP + 1, // 1 byte
RADIOLIB_LORAWAN_SESSION_BEACON_FREQ = RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP + 1, // 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_UL_CHANNELS = RADIOLIB_LORAWAN_SESSION_REJOIN_PARAM_SETUP + 1, // 16*5 bytes
RADIOLIB_LORAWAN_SESSION_DL_CHANNELS = RADIOLIB_LORAWAN_SESSION_UL_CHANNELS + RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS*5, // 16*4 bytes
RADIOLIB_LORAWAN_SESSION_AVAILABLE_CHANNELS = RADIOLIB_LORAWAN_SESSION_DL_CHANNELS + RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS*4, // 2 bytes
RADIOLIB_LORAWAN_SESSION_MAC_QUEUE = RADIOLIB_LORAWAN_SESSION_AVAILABLE_CHANNELS + sizeof(uint16_t), // 15 bytes
@ -405,9 +401,6 @@ struct LoRaWANBand_t {
/*! \brief A set of default uplink (TX) channels for dynamic bands */
LoRaWANChannel_t txFreqs[3];
/*! \brief A set of possible extra channels for the Join-Request message for dynamic bands */
LoRaWANChannel_t txJoinReq[3];
/*! \brief The number of TX channel spans for fixed bands */
uint8_t numTxSpans;
@ -548,7 +541,7 @@ class LoRaWANNode {
\param persistentBuffer Buffer that should match the internal format (previously extracted using getBufferNonces)
\returns \ref status_codes
*/
int16_t setBufferNonces(uint8_t* persistentBuffer);
int16_t setBufferNonces(const uint8_t* persistentBuffer);
/*!
\brief Clear an active session, so that the device will have to rejoin the network.
@ -566,7 +559,7 @@ class LoRaWANNode {
\param persistentBuffer Buffer that should match the internal format (previously extracted using getBufferSession)
\returns \ref status_codes
*/
int16_t setBufferSession(uint8_t* persistentBuffer);
int16_t setBufferSession(const uint8_t* persistentBuffer);
/*!
\brief Set the device credentials and activation configuration
@ -576,7 +569,7 @@ class LoRaWANNode {
\param appKey Pointer to the application AES-128 key.
\returns \ref status_codes
*/
int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, uint8_t* nwkKey, uint8_t* appKey);
int16_t beginOTAA(uint64_t joinEUI, uint64_t devEUI, const uint8_t* nwkKey, const uint8_t* appKey);
/*!
\brief Set the device credentials and activation configuration
@ -588,7 +581,7 @@ class LoRaWANNode {
\param appSKey Pointer to the application session AES-128 key.
\returns \ref status_codes
*/
int16_t beginABP(uint32_t addr, uint8_t* fNwkSIntKey, uint8_t* sNwkSIntKey, uint8_t* nwkSEncKey, uint8_t* appSKey);
int16_t beginABP(uint32_t addr, const uint8_t* fNwkSIntKey, const uint8_t* sNwkSIntKey, const uint8_t* nwkSEncKey, const uint8_t* appSKey);
/*!
\brief Join network by restoring OTAA session or performing over-the-air activation. By this procedure,
@ -622,7 +615,7 @@ class LoRaWANNode {
(fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes
*/
virtual int16_t sendReceive(String& strUp, uint8_t fPort, String& strDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
virtual int16_t sendReceive(const String& strUp, uint8_t fPort, String& strDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
#endif
/*!
@ -665,7 +658,7 @@ class LoRaWANNode {
(fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes
*/
virtual int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
virtual int16_t sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fPort = 1, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
/*!
\brief Send a message to the server and wait for a downlink during Rx1 and/or Rx2 window.
@ -681,7 +674,7 @@ class LoRaWANNode {
(fPort, frame counter, etc.). If set to NULL, no extra information will be passed to the user.
\returns Window number > 0 if downlink was received, 0 is no downlink was received, otherwise \ref status_codes
*/
virtual int16_t sendReceive(uint8_t* dataUp, size_t lenUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
virtual int16_t sendReceive(const uint8_t* dataUp, size_t lenUp, uint8_t fPort, uint8_t* dataDown, size_t* lenDown, bool isConfirmed = false, LoRaWANEvent_t* eventUp = NULL, LoRaWANEvent_t* eventDown = NULL);
/*!
\brief Add a MAC command to the uplink queue.
@ -750,10 +743,10 @@ class LoRaWANNode {
void setDutyCycle(bool enable = true, RadioLibTime_t msPerHour = 0);
/*!
\brief Toggle adherence to dwellTime limits to on or off.
\brief Set or disable uplink dwell time limitation; enabled by default if mandatory.
\param enable Whether to adhere to dwellTime limits or not (default true).
\param msPerUplink The maximum allowed Time-on-Air per uplink in milliseconds
(default 0 = maximum allowed for configured band).
(default 0 = band default value); make sure you follow regulations/law!
*/
void setDwellTime(bool enable, RadioLibTime_t msPerUplink = 0);
@ -920,9 +913,7 @@ class LoRaWANNode {
uint32_t dutyCycle = 0;
// dwell time is set upon initialization and activated in regions that impose this
bool dwellTimeEnabledUp = false;
uint16_t dwellTimeUp = 0;
bool dwellTimeEnabledDn = false;
uint16_t dwellTimeDn = 0;
RadioLibTime_t tUplink = 0; // scheduled uplink transmission time (internal clock)
@ -1002,7 +993,7 @@ class LoRaWANNode {
void adrBackoff();
// create an encrypted uplink buffer, composing metadata, user data and MAC data
void composeUplink(uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t fPort, bool isConfirmed);
void composeUplink(const uint8_t* in, uint8_t lenIn, uint8_t* out, uint8_t fPort, bool isConfirmed);
// generate and set the MIC of an uplink buffer (depends on selected channels)
void micUplink(uint8_t* inOut, uint8_t lenInOut);
@ -1071,7 +1062,7 @@ class LoRaWANNode {
// setup uplink/downlink channel data rates and frequencies
// for dynamic channels, there is a small set of predefined channels
// in case of JoinRequest, add some optional extra frequencies
void selectChannelPlanDyn(bool joinRequest = false);
void selectChannelPlanDyn();
// setup uplink/downlink channel data rates and frequencies
// for fixed bands, we only allow one sub-band at a time to be selected
@ -1112,11 +1103,11 @@ class LoRaWANNode {
static uint16_t checkSum16(const uint8_t *key, uint16_t keyLen);
// check the integrity of a buffer using a 16-bit checksum located in the last two bytes of the buffer
static int16_t checkBufferCommon(uint8_t *buffer, uint16_t size);
static int16_t checkBufferCommon(const uint8_t *buffer, uint16_t size);
// network-to-host conversion method - takes data from network packet and converts it to the host endians
template<typename T>
static T ntoh(uint8_t* buff, size_t size = 0);
static T ntoh(const uint8_t* buff, size_t size = 0);
// host-to-network conversion method - takes data from host variable and and converts it to network packet endians
template<typename T>
@ -1124,8 +1115,8 @@ class LoRaWANNode {
};
template<typename T>
T LoRaWANNode::ntoh(uint8_t* buff, size_t size) {
uint8_t* buffPtr = buff;
T LoRaWANNode::ntoh(const uint8_t* buff, size_t size) {
const uint8_t* buffPtr = buff;
size_t targetSize = sizeof(T);
if(size != 0) {
targetSize = size;

View file

@ -30,14 +30,9 @@ const LoRaWANBand_t EU868 = {
.dwellTimeDn = 0,
.txParamSupported = false,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 8681000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 8683000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 2, .freq = 8685000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
{ .enabled = true, .idx = 0, .freq = 8681000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 8683000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 2, .freq = 8685000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
},
.numTxSpans = 0,
.txSpans = {
@ -107,11 +102,6 @@ const LoRaWANBand_t US915 = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 2,
.txSpans = {
{
@ -197,14 +187,9 @@ const LoRaWANBand_t EU433 = {
.dwellTimeDn = 0,
.txParamSupported = false,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 4331750, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 4333750, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 2, .freq = 4335750, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
{ .enabled = true, .idx = 0, .freq = 4331750, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 4333750, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 2, .freq = 4335750, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
},
.numTxSpans = 0,
.txSpans = {
@ -274,11 +259,6 @@ const LoRaWANBand_t AU915 = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 2,
.txSpans = {
{
@ -368,11 +348,6 @@ const LoRaWANBand_t CN500 = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 1,
.txSpans = {
{
@ -451,13 +426,8 @@ const LoRaWANBand_t AS923 = {
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txParamSupported = true,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 9232000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 9234000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
{ .enabled = true, .idx = 0, .freq = 9232000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 9234000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
@ -524,13 +494,8 @@ const LoRaWANBand_t AS923_2 = {
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txParamSupported = true,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 9214000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 9216000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
{ .enabled = true, .idx = 0, .freq = 9214000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 9216000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
@ -597,13 +562,8 @@ const LoRaWANBand_t AS923_3 = {
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txParamSupported = true,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 9166000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 9168000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
{ .enabled = true, .idx = 0, .freq = 9166000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 9168000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
@ -670,13 +630,8 @@ const LoRaWANBand_t AS923_4 = {
.dwellTimeDn = RADIOLIB_LORAWAN_DWELL_TIME,
.txParamSupported = true,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 9173000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 9175000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
{ .enabled = true, .idx = 0, .freq = 9173000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 9175000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
RADIOLIB_LORAWAN_CHANNEL_NONE
},
.numTxSpans = 0,
@ -743,14 +698,9 @@ const LoRaWANBand_t KR920 = {
.dwellTimeDn = 0,
.txParamSupported = false,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 9221000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 9223000, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 2, .freq = 9225000, .drMin = 0, .drMax = 5, .dr = 5, .available = true }
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
{ .enabled = true, .idx = 0, .freq = 9221000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 9223000, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 2, .freq = 9225000, .drMin = 0, .drMax = 5, .dr = 3, .available = true }
},
.numTxSpans = 0,
.txSpans = {
@ -816,14 +766,9 @@ const LoRaWANBand_t IN865 = {
.dwellTimeDn = 0,
.txParamSupported = false,
.txFreqs = {
{ .enabled = true, .idx = 0, .freq = 8650625, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 1, .freq = 8654025, .drMin = 0, .drMax = 5, .dr = 5, .available = true },
{ .enabled = true, .idx = 2, .freq = 8659850, .drMin = 0, .drMax = 5, .dr = 5, .available = true }
},
.txJoinReq = {
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE,
RADIOLIB_LORAWAN_CHANNEL_NONE
{ .enabled = true, .idx = 0, .freq = 8650625, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 1, .freq = 8654025, .drMin = 0, .drMax = 5, .dr = 3, .available = true },
{ .enabled = true, .idx = 2, .freq = 8659850, .drMin = 0, .drMax = 5, .dr = 3, .available = true }
},
.numTxSpans = 0,
.txSpans = {

View file

@ -93,7 +93,7 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
}
// Automatically set function bits based on given encoding
if (function == RADIOLIB_PAGER_FUNC_AUTO) {
if(function == RADIOLIB_PAGER_FUNC_AUTO) {
if(encoding == RADIOLIB_PAGER_BCD) {
function = RADIOLIB_PAGER_FUNC_BITS_NUMERIC;
@ -101,14 +101,14 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
function = RADIOLIB_PAGER_FUNC_BITS_ALPHA;
} else {
return(RADIOLIB_ERR_INVALID_ENCODING);
return(RADIOLIB_ERR_INVALID_ENCODING);
}
if(len == 0) {
function = RADIOLIB_PAGER_FUNC_BITS_TONE;
}
}
if (function > RADIOLIB_PAGER_FUNC_BITS_ALPHA) {
if(function > RADIOLIB_PAGER_FUNC_BITS_ALPHA) {
return(RADIOLIB_ERR_INVALID_FUNCTION);
}
@ -168,7 +168,7 @@ int16_t PagerClient::transmit(uint8_t* data, size_t len, uint32_t addr, uint8_t
uint8_t blockPos = RADIOLIB_PAGER_PREAMBLE_LENGTH + 1 + framePos + 1 + i;
// check if we need to skip a frame sync marker
if(((blockPos - (RADIOLIB_PAGER_PREAMBLE_LENGTH + 1)) % RADIOLIB_PAGER_BATCH_LEN) == 0) {
if(((blockPos - RADIOLIB_PAGER_PREAMBLE_LENGTH) % (RADIOLIB_PAGER_BATCH_LEN + 1)) == 0) {
blockPos++;
i++;
}
@ -323,7 +323,7 @@ int16_t PagerClient::readData(String& str, size_t len, uint32_t* addr) {
state = readData(data, &length, addr);
if(state == RADIOLIB_ERR_NONE) {
// check tone-only tramsissions
// check tone-only transmissions
if(length == 0) {
length = 6;
strncpy((char*)data, "<tone>", length + 1);
@ -497,6 +497,7 @@ bool PagerClient::addressMatched(uint32_t addr) {
void PagerClient::write(uint32_t* data, size_t len) {
// write code words from buffer
for(size_t i = 0; i < len; i++) {
RADIOLIB_DEBUG_PROTOCOL_PRINTLN("POCSAG W\t%lu\t%08lX", (long unsigned int)i, (long unsigned int)data[i]);
PagerClient::write(data[i]);
}
}

View file

@ -135,9 +135,9 @@ union ChannelScanConfig_t {
\brief Type of modem, used by setModem.
*/
enum ModemType_t {
FSK = 0,
LoRa,
LRFHSS,
RADIOLIB_MODEM_FSK = 0,
RADIOLIB_MODEM_LORA,
RADIOLIB_MODEM_LRFHSS,
};
/*!

View file

@ -13,7 +13,7 @@ uint32_t rlb_reflect(uint32_t in, uint8_t bits) {
return(res);
}
void rlb_hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
void rlb_hexdump(const char* level, const uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
#if RADIOLIB_DEBUG
size_t rem_len = len;
for(size_t i = 0; i < len; i+=16) {

View file

@ -33,7 +33,7 @@ uint32_t rlb_reflect(uint32_t in, uint8_t bits);
\param width Word width (1 for uint8_t, 2 for uint16_t, 4 for uint32_t).
\param be Print multi-byte data as big endian. Defaults to false.
*/
void rlb_hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
void rlb_hexdump(const char* level, const uint8_t* data, size_t len, uint32_t offset = 0, uint8_t width = 1, bool be = false);
#if RADIOLIB_DEBUG && defined(RADIOLIB_BUILD_ARDUINO)
size_t rlb_printf(const char* format, ...);