Update RadioLib
This commit is contained in:
parent
f5c9cebd61
commit
1fba8bc2ec
143 changed files with 10097 additions and 2417 deletions
2
lib/RadioLib/.github/workflows/cppcheck.yml
vendored
2
lib/RadioLib/.github/workflows/cppcheck.yml
vendored
|
|
@ -24,4 +24,4 @@ jobs:
|
|||
|
||||
- name: Run cppcheck
|
||||
run:
|
||||
cppcheck src --enable=all --force
|
||||
cppcheck src --enable=all --force --inline-suppr --quiet --suppress=ConfigurationNotChecked --suppress=unusedFunction
|
||||
|
|
|
|||
12
lib/RadioLib/.github/workflows/main.yml
vendored
12
lib/RadioLib/.github/workflows/main.yml
vendored
|
|
@ -104,6 +104,10 @@ jobs:
|
|||
run: echo "index-url=--additional-urls https://resource.heltec.cn/download/package_CubeCell_index.json" >> $GITHUB_OUTPUT
|
||||
- id: MegaCore:avr:1281
|
||||
run: echo "index-url=--additional-urls https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json" >> $GITHUB_OUTPUT
|
||||
- id: teensy:avr:teensy41
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
echo "index-url=--additional-urls https://www.pjrc.com/teensy/package_teensy_index.json" >> $GITHUB_OUTPUT
|
||||
- id: arduino:renesas_uno:minima
|
||||
run: |
|
||||
echo "skip-pattern=(STM32WL|LoRaWAN)" >> $GITHUB_OUTPUT
|
||||
|
|
@ -166,7 +170,7 @@ jobs:
|
|||
else
|
||||
# apply special flags for LoRaWAN
|
||||
if [[ ${example} =~ "LoRaWAN" ]]; then
|
||||
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_NWKS_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"
|
||||
flags="-DRADIOLIB_LORAWAN_DEV_ADDR=0 -DRADIOLIB_LORAWAN_FNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_SNWKSINT_KEY=0 -DRADIOLIB_LORAWAN_NWKSENC_KEY=0 -DRADIOLIB_LORAWAN_APPS_KEY=0 -DRADIOLIB_LORAWAN_APP_KEY=0 -DRADIOLIB_LORAWAN_NWK_KEY=0 -DRADIOLIB_LORAWAN_DEV_EUI=0 -DARDUINO_TTGO_LORA32_V1"
|
||||
fi
|
||||
|
||||
# build sketch
|
||||
|
|
@ -222,13 +226,15 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get install -y gcc-arm-none-eabi
|
||||
sudo apt-get install -y gcc-arm-none-eabi gcc-riscv64-unknown-elf
|
||||
cargo install elf2tab
|
||||
|
||||
- name: Build the example
|
||||
run: |
|
||||
cd $PWD/examples/NonArduino/Tock
|
||||
./build.sh
|
||||
git clone https://github.com/tock/libtock-c.git
|
||||
cd libtock-c; git checkout 44bf89c545953d8859faf101d4b4a4b6a151fe6c; cd ../
|
||||
LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
|
||||
|
||||
rpi-build:
|
||||
runs-on: [self-hosted, ARM64]
|
||||
|
|
|
|||
3
lib/RadioLib/.gitmodules
vendored
3
lib/RadioLib/.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "examples/NonArduino/Tock/libtock-c"]
|
||||
path = examples/NonArduino/Tock/libtock-c
|
||||
url = https://github.com/tock/libtock-c.git
|
||||
|
|
@ -32,6 +32,12 @@ target_include_directories(RadioLib
|
|||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
# use c++20 standard
|
||||
set_property(TARGET RadioLib PROPERTY CXX_STANDARD 20)
|
||||
|
||||
# enable most warnings
|
||||
target_compile_options(RadioLib PRIVATE -Wall -Wextra)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS RadioLib
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
### Supported modules:
|
||||
* __CC1101__ FSK radio module
|
||||
* __LLCC68__ LoRa module
|
||||
* __LR11x0__ series LoRa/GFSK modules (LR1110, LR1120, LR1121)
|
||||
* __nRF24L01__ 2.4 GHz module
|
||||
* __RF69__ FSK/OOK radio module
|
||||
* __RFM2x__ series FSK modules (RFM22, RM23)
|
||||
|
|
@ -29,21 +30,21 @@ RadioLib was originally created as a driver for [__RadioShield__](https://github
|
|||
|
||||
### Supported protocols and digital modes:
|
||||
* [__AX.25__](https://www.sigidwiki.com/wiki/PACKET) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x and Si443x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__RTTY__](https://www.sigidwiki.com/wiki/RTTY) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__Morse Code__](https://www.sigidwiki.com/wiki/Morse_Code_(CW)) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__SSTV__](https://www.sigidwiki.com/wiki/SSTV) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, RFM2x and Si443x
|
||||
* [__Hellschreiber__](https://www.sigidwiki.com/wiki/Hellschreiber) using 2-FSK or AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x, LR11x0 and SX128x
|
||||
* [__APRS__](https://www.sigidwiki.com/wiki/APRS) using AFSK for modules:
|
||||
SX127x, RFM9x, SX126x, RF69, SX1231, CC1101, nRF24L01, RFM2x, Si443x and SX128x
|
||||
* [__POCSAG__](https://www.sigidwiki.com/wiki/POCSAG) using 2-FSK for modules:
|
||||
SX127x, RFM9x, RF69, SX1231, CC1101, nRF24L01, RFM2x and Si443x
|
||||
* [__LoRaWAN__](https://lora-alliance.org/) using LoRa for modules:
|
||||
SX127x, RFM9x, SX126x and SX128x
|
||||
SX127x, RFM9x, SX126x, LR11x0 and SX128x
|
||||
* NOTE: LoRaWAN support is currently in beta, feedback via [Issues](https://github.com/jgromes/RadioLib/issues) and [Discussions](https://github.com/jgromes/RadioLib/discussions) is appreciated!
|
||||
|
||||
### Supported Arduino platforms:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
- SX127x/RFM9x
|
||||
- SX126x/LLCC68
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
- SX126x
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- LR11x0
|
||||
|
||||
Using raw AX.25 frames requires some
|
||||
knowledge of the protocol, refer to
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
- SX126x
|
||||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Channel Activity Detection Example
|
||||
|
||||
This example uses LR1110 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR11x0 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
Using blocking CAD is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt CAD is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Scanning channel for LoRa transmission ... "));
|
||||
|
||||
// start scanning current channel
|
||||
int state = radio.scanChannel();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa preamble was detected
|
||||
Serial.println(F("detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// no preamble was detected, channel is free
|
||||
Serial.println(F("channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait 100 ms before new scan
|
||||
delay(100);
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
RadioLib LR11x0 Channel Activity Detection Example
|
||||
|
||||
This example uses LR1110 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
Unlike SX127x CAD, LR11x0 can detect any part
|
||||
of LoRa transmission, not just the preamble.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[LR1110] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[LR1110] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[LR1110] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[LR1110] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[LR1110] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
RadioLib LR11x0 GFSK Modem Example
|
||||
|
||||
This example shows how to use GFSK modem in LR11x0 chips.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
GFSK modem, so this code should not be run directly!
|
||||
Instead, modify the other examples to use GFSK
|
||||
modem and use the appropriate configuration
|
||||
methods.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---gfsk-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.beginGFSK();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, you can switch between any of the modems
|
||||
//
|
||||
// radio.begin() start LoRa modem (and disable GFSK)
|
||||
// radio.beginGFSK() start GFSK modem (and disable LoRa)
|
||||
|
||||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setBitRate(100.0);
|
||||
state = radio.setFrequencyDeviation(10.0);
|
||||
state = radio.setRxBandwidth(250.0);
|
||||
state = radio.setOutputPower(10.0);
|
||||
state = radio.setDataShaping(RADIOLIB_SHAPING_1_0);
|
||||
uint8_t syncWord[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.setSyncWord(syncWord, 8);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Unable to set configuration, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// GFSK modem on LR11x0 can handle the sync word setting in bits, not just
|
||||
// whole bytes. The value used is left-justified.
|
||||
// This makes same result as radio.setSyncWord(syncWord, 8):
|
||||
state = radio.setSyncBits(syncWord, 64);
|
||||
// This will use 0x012 as sync word (12 bits only):
|
||||
state = radio.setSyncBits(syncWord, 12);
|
||||
|
||||
// GFSK modem allows advanced CRC configuration
|
||||
// Default is CCIT CRC16 (2 bytes, initial 0x1D0F, polynomial 0x1021, inverted)
|
||||
// Set CRC to IBM CRC (2 bytes, initial 0xFFFF, polynomial 0x8005, non-inverted)
|
||||
state = radio.setCRC(2, 0xFFFF, 0x8005, false);
|
||||
// set CRC length to 0 to disable CRC
|
||||
|
||||
#warning "This sketch is just an API guide! Read the note at line 6."
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// GFSK modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// transmit GFSK packet
|
||||
int state = radio.transmit("Hello World!");
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[LR1110] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[LR1110] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive GFSK packet
|
||||
String str;
|
||||
state = radio.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
Serial.print(F("[LR1110] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[LR1110] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// GFSK modem has built-in address filtering system
|
||||
// it can be enabled by setting node address, broadcast
|
||||
// address, or both
|
||||
//
|
||||
// to transmit packet to a particular address,
|
||||
// use the following methods:
|
||||
//
|
||||
// radio.transmit("Hello World!", address);
|
||||
// radio.startTransmit("Hello World!", address);
|
||||
|
||||
// set node address to 0x02
|
||||
state = radio.setNodeAddress(0x02);
|
||||
// set broadcast address to 0xFF
|
||||
state = radio.setBroadcastAddress(0xFF);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Unable to set address filter, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// address filtering can also be disabled
|
||||
// NOTE: calling this method will also erase previously set
|
||||
// node and broadcast address
|
||||
/*
|
||||
state = radio.disableAddressFiltering();
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("Unable to remove address filter, code "));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
RadioLib LR11x0 LR-FHSS Modem Example
|
||||
|
||||
This example shows how to use LR-FHSS modem in LR11x0 chips.
|
||||
|
||||
NOTE: The sketch below is just a guide on how to use
|
||||
LR-FHSS modem, so this code should not be run directly!
|
||||
Instead, modify the other examples to use LR-FHSS
|
||||
modem and use the appropriate configuration
|
||||
methods.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lr-fhss-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.beginLRFHSS();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, you can switch between any of the modems
|
||||
//
|
||||
// radio.begin() start LoRa modem (and disable LR-FHSS)
|
||||
// radio.beginLRFHSS() start LR-FHSS modem (and disable LoRa)
|
||||
|
||||
// the following settings can also
|
||||
// be modified at run-time
|
||||
state = radio.setFrequency(433.5);
|
||||
state = radio.setLrFhssConfig(RADIOLIB_LR11X0_LR_FHSS_BW_1523_4, // bandwidth
|
||||
RADIOLIB_LR11X0_LR_FHSS_CR_1_2, // coding rate
|
||||
3, // header count
|
||||
0x13A); // hopping sequence seed
|
||||
state = radio.setOutputPower(10.0);
|
||||
state = radio.setSyncWord(0x12345678);
|
||||
if (state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Unable to set configuration, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
#warning "This sketch is just an API guide! Read the note at line 6."
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// LR-FHSS modem can use the same transmit/receive methods
|
||||
// as the LoRa modem, even their interrupt-driven versions
|
||||
|
||||
// transmit LR-FHSS packet
|
||||
int state = radio.transmit("Hello World!");
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Packet transmitted successfully!"));
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
Serial.println(F("[LR1110] Packet too long!"));
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while transmitting!"));
|
||||
} else {
|
||||
Serial.println(F("[LR1110] Failed to transmit packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// receive LR-FHSS packet
|
||||
String str;
|
||||
state = radio.receive(str);
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
Serial.print(F("[LR1110] Data:\t"));
|
||||
Serial.println(str);
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
Serial.println(F("[LR1110] Timed out while waiting for packet!"));
|
||||
} else {
|
||||
Serial.print(F("[LR1110] Failed to receive packet, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Receive Example
|
||||
|
||||
This example listens for LoRa transmissions using LR11x0 Lora modules.
|
||||
To successfully receive data, the following settings have to be the same
|
||||
on both transmitter and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
- preamble length
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
Using blocking receive is not recommended, as it will lead
|
||||
to significant amount of timeouts, inefficient use of processor
|
||||
time and can some miss packets!
|
||||
Instead, interrupt receive is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Waiting for incoming transmission ... "));
|
||||
|
||||
// you can receive data as an Arduino String
|
||||
String str;
|
||||
int state = radio.receive(str);
|
||||
|
||||
// you can also receive data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int state = radio.receive(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the data of the packet
|
||||
Serial.print(F("[LR1110] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print the RSSI (Received Signal Strength Indicator)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR1110] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print the SNR (Signal-to-Noise Ratio)
|
||||
// of the last received packet
|
||||
Serial.print(F("[LR1110] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
|
||||
// timeout occurred while waiting for a packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
RadioLib LR11x0 Receive with Interrupts Example
|
||||
|
||||
This example listens for LoRa transmissions and tries to
|
||||
receive them. Once a packet is received, an interrupt is
|
||||
triggered. To successfully receive data, the following
|
||||
settings have to be the same on both transmitter
|
||||
and receiver:
|
||||
- carrier frequency
|
||||
- bandwidth
|
||||
- spreading factor
|
||||
- coding rate
|
||||
- sync word
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when new packet is received
|
||||
radio.setPacketReceivedAction(setFlag);
|
||||
|
||||
// start listening for LoRa packets
|
||||
Serial.print(F("[LR1110] Starting to listen ... "));
|
||||
state = radio.startReceive();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// if needed, 'listen' mode can be disabled by calling
|
||||
// any of the following methods:
|
||||
//
|
||||
// radio.standby()
|
||||
// radio.sleep()
|
||||
// radio.transmit();
|
||||
// radio.receive();
|
||||
// radio.scanChannel();
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was received
|
||||
volatile bool receivedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we got a packet, set the flag
|
||||
receivedFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(receivedFlag) {
|
||||
// reset flag
|
||||
receivedFlag = false;
|
||||
|
||||
// you can read received data as an Arduino String
|
||||
String str;
|
||||
int state = radio.readData(str);
|
||||
|
||||
// you can also read received data as byte array
|
||||
/*
|
||||
byte byteArr[8];
|
||||
int numBytes = radio.getPacketLength();
|
||||
int state = radio.readData(byteArr, numBytes);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully received
|
||||
Serial.println(F("[LR1110] Received packet!"));
|
||||
|
||||
// print data of the packet
|
||||
Serial.print(F("[LR1110] Data:\t\t"));
|
||||
Serial.println(str);
|
||||
|
||||
// print RSSI (Received Signal Strength Indicator)
|
||||
Serial.print(F("[LR1110] RSSI:\t\t"));
|
||||
Serial.print(radio.getRSSI());
|
||||
Serial.println(F(" dBm"));
|
||||
|
||||
// print SNR (Signal-to-Noise Ratio)
|
||||
Serial.print(F("[LR1110] SNR:\t\t"));
|
||||
Serial.print(radio.getSNR());
|
||||
Serial.println(F(" dB"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
|
||||
// packet was received, but is malformed
|
||||
Serial.println(F("CRC error!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
RadioLib LR11x0 Blocking Transmit Example
|
||||
|
||||
This example transmits packets using LR1110 LoRa radio module.
|
||||
Each packet contains up to 256 bytes of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
delay(1000);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// some modules have an external RF switch
|
||||
|
||||
// controlled via two pins (RX enable, TX enable)
|
||||
// to enable automatic control of the switch,
|
||||
// call the following method
|
||||
// RX enable: 4
|
||||
// TX enable: 5
|
||||
/*
|
||||
radio.setRfSwitchPins(4, 5);
|
||||
*/
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Transmitting packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
// NOTE: transmit() is a blocking method!
|
||||
// See example LR11x0_Transmit_Interrupt for details
|
||||
// on non-blocking transmission method.
|
||||
String str = "Hello World! #" + String(count++);
|
||||
int state = radio.transmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x56, 0x78, 0xAB, 0xCD, 0xEF};
|
||||
int state = radio.transmit(byteArr, 8);
|
||||
*/
|
||||
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
// the packet was successfully transmitted
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print measured data rate
|
||||
Serial.print(F("[LR1110] Datarate:\t"));
|
||||
Serial.print(radio.getDataRate());
|
||||
Serial.println(F(" bps"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
|
||||
// the supplied packet was longer than 256 bytes
|
||||
Serial.println(F("too long!"));
|
||||
|
||||
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
|
||||
// timeout occured while transmitting packet
|
||||
Serial.println(F("timeout!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before transmitting again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
RadioLib LR11x0 Transmit with Interrupts Example
|
||||
|
||||
This example transmits LoRa packets with one second delays
|
||||
between them. Each packet contains up to 256 bytes
|
||||
of data, in the form of:
|
||||
- Arduino String
|
||||
- null-terminated char array (C-string)
|
||||
- arbitrary binary data (byte array)
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// IRQ pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
// save transmission state between loops
|
||||
int transmissionState = RADIOLIB_ERR_NONE;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when packet transmission is finished
|
||||
radio.setPacketSentAction(setFlag);
|
||||
|
||||
// start transmitting the first packet
|
||||
Serial.print(F("[LR1110] Sending first packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
transmissionState = radio.startTransmit("Hello World!");
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
state = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was sent
|
||||
volatile bool transmittedFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is transmitted by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// we sent a packet, set the flag
|
||||
transmittedFlag = true;
|
||||
}
|
||||
|
||||
// counter to keep track of transmitted packets
|
||||
int count = 0;
|
||||
|
||||
void loop() {
|
||||
// check if the previous transmission finished
|
||||
if(transmittedFlag) {
|
||||
// reset flag
|
||||
transmittedFlag = false;
|
||||
|
||||
if (transmissionState == RADIOLIB_ERR_NONE) {
|
||||
// packet was successfully sent
|
||||
Serial.println(F("transmission finished!"));
|
||||
|
||||
// NOTE: when using interrupt-driven transmit method,
|
||||
// it is not possible to automatically measure
|
||||
// transmission data rate using getDataRate()
|
||||
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(transmissionState);
|
||||
|
||||
}
|
||||
|
||||
// clean up after transmission is finished
|
||||
// this will ensure transmitter is disabled,
|
||||
// RF switch is powered down etc.
|
||||
radio.finishTransmit();
|
||||
|
||||
// wait a second before transmitting again
|
||||
delay(1000);
|
||||
|
||||
// send another one
|
||||
Serial.print(F("[LR1110] Sending another packet ... "));
|
||||
|
||||
// you can transmit C-string or Arduino string up to
|
||||
// 256 characters long
|
||||
String str = "Hello World! #" + String(count++);
|
||||
transmissionState = radio.startTransmit(str);
|
||||
|
||||
// you can also transmit byte array up to 256 bytes long
|
||||
/*
|
||||
byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
|
||||
0x89, 0xAB, 0xCD, 0xEF};
|
||||
transmissionState = radio.startTransmit(byteArr, 8);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
RadioLib LR11x0 WiFi scan Blocking Example
|
||||
|
||||
This example performs a passive scan of WiFi networks.
|
||||
The scan shows basic information about the networks,
|
||||
such as the frequency, country code and SSID.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
Using blocking scan is not recommended, as depending
|
||||
on the scan settings, the program may be blocked
|
||||
for several seconds! Instead, interrupt scan is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---wifi-scan
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print(F("[LR1110] Running WiFi scan ... "));
|
||||
|
||||
// scan all WiFi signals with default scan configuration
|
||||
uint8_t count = 0;
|
||||
int state = radio.wifiScan('*', &count);
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the table header
|
||||
Serial.print(F("[LR1110] Reading "));
|
||||
Serial.print(count);
|
||||
Serial.println(F(" scan results:"));
|
||||
Serial.println(F(" # | WiFi type\t| Frequency\t| MAC Address\t | Country\t| RSSI [dBm]\t| SSID"));
|
||||
|
||||
// read all results one by one
|
||||
// this result type contains the most information, including the SSID
|
||||
LR11x0WifiResultExtended_t result;
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(i < 10) { Serial.print(" "); } Serial.print(i); Serial.print(" | ");
|
||||
state = radio.getWifiScanResult(&result, i);
|
||||
if(state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Failed to read result, code "));
|
||||
Serial.println(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
// print the basic information
|
||||
Serial.print(F("802.11")); Serial.print(result.type); Serial.print("\t| ");
|
||||
Serial.print(result.channelFreq); Serial.print(" MHz\t| ");
|
||||
|
||||
// print MAC address
|
||||
for(int j = 0; j < 6; j++) {
|
||||
if(result.mac[j] < 0x10) { Serial.print("0"); }
|
||||
Serial.print(result.mac[j], HEX);
|
||||
if(j < 5) { Serial.print(":"); }
|
||||
}
|
||||
Serial.print(" | ");
|
||||
|
||||
// print the two-letter country code
|
||||
String country = result.countryCode;
|
||||
Serial.print(country);
|
||||
Serial.print(" \t| ");
|
||||
|
||||
// print the RSSI
|
||||
Serial.print(result.rssi);
|
||||
Serial.print("\t| ");
|
||||
|
||||
// print the network SSID
|
||||
Serial.println((char*)result.ssid);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// wait for a second before scanning again
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
RadioLib LR11x0 WiFi scan Interrupt Example
|
||||
|
||||
This example performs a passive scan of WiFi networks.
|
||||
The scan shows basic information about the networks,
|
||||
such as the frequency, country code and SSID.
|
||||
|
||||
Other modules from LR11x0 family can also be used.
|
||||
|
||||
Using blocking scan is not recommended, as depending
|
||||
on the scan settings, the program may be blocked
|
||||
for several seconds! Instead, interrupt scan is recommended.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#lr11x0---wifi-scan
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// LR1110 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
LR1110 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//LR1110 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize LR1110 with default settings
|
||||
Serial.print(F("[LR1110] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when WiFi scan is complete
|
||||
radio.setIrqAction(setFlag);
|
||||
|
||||
// scan all WiFi signals with default scan configuration
|
||||
Serial.print(F("[LR1110] Starting passive WiFi scan ... "));
|
||||
state = radio.startWifiScan('*');
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a scan was completed
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a scan is completed
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// scan is complete, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// get the number of scan results
|
||||
uint8_t count = 0;
|
||||
Serial.print(F("[LR1110] Reading WiFi scan results ... "));
|
||||
int state = radio.getWifiScanResultsCount(&count);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
|
||||
// print the table header
|
||||
Serial.print(F("[LR1110] Reading "));
|
||||
Serial.print(count);
|
||||
Serial.println(F(" scan results:"));
|
||||
Serial.println(F(" # | WiFi type\t| Frequency\t| MAC Address\t | Country\t| RSSI [dBm]\t| SSID"));
|
||||
|
||||
// read all results one by one
|
||||
// this result type contains the most information, including the SSID
|
||||
LR11x0WifiResultExtended_t result;
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(i < 10) { Serial.print(" "); } Serial.print(i); Serial.print(" | ");
|
||||
state = radio.getWifiScanResult(&result, i);
|
||||
if(state != RADIOLIB_ERR_NONE) {
|
||||
Serial.print(F("Failed to read result, code "));
|
||||
Serial.println(state);
|
||||
continue;
|
||||
}
|
||||
|
||||
// print the basic information
|
||||
Serial.print(F("802.11")); Serial.print(result.type); Serial.print("\t| ");
|
||||
Serial.print(result.channelFreq); Serial.print(" MHz\t| ");
|
||||
|
||||
// print MAC address
|
||||
for(int j = 0; j < 6; j++) {
|
||||
if(result.mac[j] < 0x10) { Serial.print("0"); }
|
||||
Serial.print(result.mac[j], HEX);
|
||||
if(j < 5) { Serial.print(":"); }
|
||||
}
|
||||
Serial.print(" | ");
|
||||
|
||||
// print the two-letter country code
|
||||
String country = result.countryCode;
|
||||
Serial.print(country);
|
||||
Serial.print(" \t| ");
|
||||
|
||||
// print the RSSI
|
||||
Serial.print(result.rssi);
|
||||
Serial.print("\t| ");
|
||||
|
||||
// print the network SSID
|
||||
Serial.println((char*)result.ssid);
|
||||
}
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
|
||||
// start scanning again
|
||||
Serial.print(F("[LR1110] Starting passive WiFi scan ... "));
|
||||
state = radio.startWifiScan('*');
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,34 +33,34 @@
|
|||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
while(!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
Serial.println(F("Initalise the radio"));
|
||||
Serial.println(F("Initialise the radio"));
|
||||
int state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true);
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
Serial.println(F("Initalise LoRaWAN Network credentials"));
|
||||
state = node.beginABP(devAddr, NwkSEncKey, AppSKey, NwkSKey, SNwkSIntKey, true);
|
||||
Serial.println(F("Initialise LoRaWAN Network credentials"));
|
||||
state = node.beginABP(devAddr, fNwkSIntKey, sNwkSIntKey, nwkSEncKey, appSKey, true);
|
||||
debug(state < RADIOLIB_ERR_NONE, F("Session setup failed"), state, true);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// Read some inputs
|
||||
uint8_t Digital1 = digitalRead(2);
|
||||
uint16_t Analog1 = analogRead(3);
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = Digital1;
|
||||
uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(Analog1);
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
// Perform an uplink
|
||||
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ const uint32_t uplinkIntervalSeconds = 5UL * 60UL; // minutes x seconds
|
|||
#define RADIOLIB_LORAWAN_DEV_ADDR 0x------
|
||||
#endif
|
||||
|
||||
#ifndef RADIOLIB_LORAWAN_NWKS_KEY // Replace with your NwkS Key
|
||||
#define RADIOLIB_LORAWAN_NWKS_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#ifndef RADIOLIB_LORAWAN_FNWKSINT_KEY // Replace with your FNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_FNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
#endif
|
||||
#ifndef RADIOLIB_LORAWAN_SNWKSINT_KEY // Replace with your SNwkSInt Key
|
||||
#define RADIOLIB_LORAWAN_SNWKSINT_KEY 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--, 0x--
|
||||
|
|
@ -49,11 +49,12 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("TTGO LoRa32 v1 - no Display")
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma error ("ARDUINO_TTGO_LORA32_V2 awaiting pin map")
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
|
|
@ -63,24 +64,41 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// Heltec
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma error ("ARDUINO_HELTEC_WIFI_LORA_32 awaiting pin map")
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V2)
|
||||
#pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using CubeCell")
|
||||
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
|
||||
|
|
@ -100,10 +118,10 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
|
||||
// copy over the keys in to the something that will not compile if incorrectly formatted
|
||||
uint32_t devAddr = RADIOLIB_LORAWAN_DEV_ADDR;
|
||||
uint8_t NwkSKey[] = { RADIOLIB_LORAWAN_NWKS_KEY };
|
||||
uint8_t SNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY }; // Previously sNwkSIntKey
|
||||
uint8_t NwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY }; // Previously fNwkSIntKey
|
||||
uint8_t AppSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
|
||||
uint8_t fNwkSIntKey[] = { RADIOLIB_LORAWAN_FNWKSINT_KEY };
|
||||
uint8_t sNwkSIntKey[] = { RADIOLIB_LORAWAN_SNWKSINT_KEY };
|
||||
uint8_t nwkSEncKey[] = { RADIOLIB_LORAWAN_NWKSENC_KEY };
|
||||
uint8_t appSKey[] = { RADIOLIB_LORAWAN_APPS_KEY };
|
||||
|
||||
// create the LoRaWAN node
|
||||
LoRaWANNode node(&radio, &Region, subBand);
|
||||
|
|
|
|||
|
|
@ -33,18 +33,17 @@
|
|||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // Wait for serial to be initalised
|
||||
while(!Serial); // Wait for serial to be initialised
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup"));
|
||||
|
||||
int16_t state = 0; // return value for calls to RadioLib
|
||||
|
||||
Serial.println(F("Initalise the radio"));
|
||||
Serial.println(F("Initialise the radio"));
|
||||
state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true);
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
// Override the default join rate
|
||||
// uint8_t joinDR = 3;
|
||||
|
|
@ -60,13 +59,9 @@ void setup() {
|
|||
// Disable the ADR algorithm (on by default which is preferable)
|
||||
node.setADR(false);
|
||||
|
||||
// Set a fixed datarate & make it persistent (not normal)
|
||||
// Set a fixed datarate
|
||||
node.setDatarate(4);
|
||||
|
||||
// Enable CSMA which tries to minimize packet loss by searching
|
||||
// for a free channel before actually sending an uplink
|
||||
node.setCSMA(6, 2, true);
|
||||
|
||||
// Manages uplink intervals to the TTN Fair Use Policy
|
||||
node.setDutyCycle(true, 1250);
|
||||
|
||||
|
|
@ -74,8 +69,7 @@ void setup() {
|
|||
node.setDwellTime(true, 400);
|
||||
|
||||
Serial.println(F("Ready!\n"));
|
||||
} // setup
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
int state = RADIOLIB_ERR_NONE;
|
||||
|
|
@ -89,19 +83,19 @@ void loop() {
|
|||
uint8_t battLevel = 146;
|
||||
node.setDeviceStatus(battLevel);
|
||||
|
||||
|
||||
// Read some inputs
|
||||
uint8_t Digital1 = digitalRead(2);
|
||||
uint16_t Analog1 = analogRead(3);
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = Digital1;
|
||||
uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(Analog1);
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
uint8_t downlinkPayload[10]; // Make sure this fits your plans!
|
||||
size_t downlinkSize; // To hold the actual payload size rec'd
|
||||
size_t downlinkSize; // To hold the actual payload size received
|
||||
|
||||
// you can also retrieve additional information about an uplink or
|
||||
// downlink by passing a reference to LoRaWANEvent_t structure
|
||||
|
|
@ -111,13 +105,14 @@ void loop() {
|
|||
uint8_t Port = 10;
|
||||
|
||||
// Retrieve the last uplink frame counter
|
||||
uint32_t fcntUp = node.getFcntUp();
|
||||
uint32_t fcntUp = node.getFCntUp();
|
||||
|
||||
// Send a confirmed uplink every 64th frame
|
||||
// and also request the LinkCheck and DeviceTime MAC commands
|
||||
if(fcntUp % 64 == 0) {
|
||||
Serial.println(F("[LoRaWAN] Requesting LinkCheck and DeviceTime"));
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_LINK_CHECK);
|
||||
node.sendMacCommandReq(RADIOLIB_LORAWAN_MAC_DEVICE_TIME);
|
||||
node.sendMacCommandReq(RADIOLIB_LW_MAC_LINK_CHECK);
|
||||
node.sendMacCommandReq(RADIOLIB_LW_MAC_DEVICE_TIME);
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize, true, &uplinkDetails, &downlinkDetails);
|
||||
} else {
|
||||
state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload), Port, downlinkPayload, &downlinkSize);
|
||||
|
|
@ -127,7 +122,7 @@ void loop() {
|
|||
// Check if downlink was received
|
||||
if(state != RADIOLIB_LORAWAN_NO_DOWNLINK) {
|
||||
// Did we get a downlink with data for us
|
||||
if (downlinkSize > 0) {
|
||||
if(downlinkSize > 0) {
|
||||
Serial.println(F("Downlink data: "));
|
||||
arrayDump(downlinkPayload, downlinkSize);
|
||||
} else {
|
||||
|
|
@ -164,9 +159,9 @@ void loop() {
|
|||
Serial.print(downlinkDetails.power);
|
||||
Serial.println(F(" dBm"));
|
||||
Serial.print(F("[LoRaWAN] Frame count:\t"));
|
||||
Serial.println(downlinkDetails.fcnt);
|
||||
Serial.println(downlinkDetails.fCnt);
|
||||
Serial.print(F("[LoRaWAN] Port:\t\t"));
|
||||
Serial.println(downlinkDetails.port);
|
||||
Serial.println(downlinkDetails.fPort);
|
||||
|
||||
uint8_t margin = 0;
|
||||
uint8_t gwCnt = 0;
|
||||
|
|
@ -198,5 +193,4 @@ void loop() {
|
|||
Serial.println(F("s"));
|
||||
|
||||
delay(delayMs);
|
||||
|
||||
} // loop
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,11 +44,12 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("TTGO LoRa32 v1 - no Display")
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma error ("ARDUINO_TTGO_LORA32_V2 awaiting pin map")
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
|
|
@ -58,24 +59,41 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// Heltec
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma error ("ARDUINO_HELTEC_WIFI_LORA_32 awaiting pin map")
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V2)
|
||||
#pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using CubeCell")
|
||||
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@
|
|||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
while(!Serial);
|
||||
delay(5000); // Give time to switch to the serial monitor
|
||||
Serial.println(F("\nSetup ... "));
|
||||
|
||||
Serial.println(F("Initalise the radio"));
|
||||
Serial.println(F("Initialise the radio"));
|
||||
int state = radio.begin();
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initalise radio failed"), state, true);
|
||||
debug(state != RADIOLIB_ERR_NONE, F("Initialise radio failed"), state, true);
|
||||
|
||||
Serial.println(F("Join ('login') to the LoRaWAN Network"));
|
||||
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey, true);
|
||||
|
|
@ -41,19 +41,19 @@ void setup() {
|
|||
Serial.println(F("Ready!\n"));
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
Serial.println(F("Sending uplink"));
|
||||
|
||||
// Read some inputs
|
||||
uint8_t Digital1 = digitalRead(2);
|
||||
uint16_t Analog1 = analogRead(3);
|
||||
// This is the place to gather the sensor inputs
|
||||
// Instead of reading any real sensor, we just generate some random numbers as example
|
||||
uint8_t value1 = radio.random(100);
|
||||
uint16_t value2 = radio.random(2000);
|
||||
|
||||
// Build payload byte array
|
||||
uint8_t uplinkPayload[3];
|
||||
uplinkPayload[0] = Digital1;
|
||||
uplinkPayload[1] = highByte(Analog1); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(Analog1);
|
||||
uplinkPayload[0] = value1;
|
||||
uplinkPayload[1] = highByte(value2); // See notes for high/lowByte functions
|
||||
uplinkPayload[2] = lowByte(value2);
|
||||
|
||||
// Perform an uplink
|
||||
int state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
|
||||
|
|
|
|||
|
|
@ -44,11 +44,12 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
|
||||
// LilyGo
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V1)
|
||||
#pragma message ("TTGO LoRa32 v1 - no Display")
|
||||
#pragma message ("Using TTGO LoRa32 v1 - no Display")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LORA32_V2)
|
||||
#pragma error ("ARDUINO_TTGO_LORA32_V2 awaiting pin map")
|
||||
#pragma message ("Using TTGO LoRa32 v2 + Display")
|
||||
SX1276 radio = new Module(18, 26, 12, RADIOLIB_NC);
|
||||
|
||||
#elif defined(ARDUINO_TTGO_LoRa32_v21new) // T3_V1.6.1
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
|
|
@ -58,24 +59,41 @@ const uint8_t subBand = 0; // For US915, change this to 2, otherwise leave on 0
|
|||
#pragma error ("ARDUINO_TBEAM_USE_RADIO_SX1262 awaiting pin map")
|
||||
|
||||
#elif defined(ARDUINO_TBEAM_USE_RADIO_SX1276)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using TTGO T-Beam")
|
||||
SX1276 radio = new Module(18, 26, 23, 33);
|
||||
|
||||
|
||||
// Heltec
|
||||
// HelTec: https://github.com/espressif/arduino-esp32/blob/master/variants/heltec_*/pins_arduino.h
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32)
|
||||
#pragma error ("ARDUINO_HELTEC_WIFI_LORA_32 awaiting pin map")
|
||||
#pragma message ("Using Heltec WiFi LoRa32")
|
||||
SX1276 radio = new Module(18, 26, 14, 33);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V2)
|
||||
#pragma message ("ARDUINO_heltec_wifi_kit_32_V2 awaiting pin map")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V2)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v2")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined(ARDUINO_heltec_wifi_kit_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3 - Display + USB-C")
|
||||
#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3)
|
||||
#pragma message ("Using Heltec WiFi LoRa32 v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK)
|
||||
#pragma message ("Using Heltec Wireless Stick")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick v3")
|
||||
SX1262 radio = new Module(8, 14, 12, 13);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite")
|
||||
SX1276 radio = new Module(18, 26, 14, 35);
|
||||
|
||||
#elif defined (ARDUINO_HELTEC_WIRELESS_STICK_LITE_V3)
|
||||
#pragma message ("Using Heltec Wireless Stick Lite v3")
|
||||
SX1262 radio = new Module(34, 14, 12, 13);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD)
|
||||
#pragma message ("Using TTGO LoRa32 v2.1 marked T3_V1.6.1 + Display")
|
||||
#pragma message ("Using CubeCell")
|
||||
SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
|
||||
|
||||
#elif defined(ARDUINO_CUBECELL_BOARD_V2)
|
||||
|
|
|
|||
|
|
@ -152,6 +152,10 @@ Prebuilt modules are easy - we can detect the board and setup the pinmap for you
|
|||
* HELTEC_WIFI_LORA_32
|
||||
* HELTEC_WIFI_LORA_32_V2
|
||||
* HELTEC_WIFI_LORA_32_V3
|
||||
* HELTEC_WIRELESS_STICK
|
||||
* HELTEC_WIRELESS_STICK_V3
|
||||
* HELTEC_WIRELESS_STICK_LITE
|
||||
* HELTEC_WIRELESS_STICK_LITE_V3
|
||||
|
||||
If you have a TTGO T-Beam, you must choose the correct radio from the Board Revision sub-menu found under the main Tools menu.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
# LoRaWAN examples
|
||||
RadioLib LoRaWAN v1.1 examples.
|
||||
|
||||
* [LoRaWAN_Starter](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Starter): this is the recommended entry point for new users. Please read the `notes` that come with this example to learn more about LoRaWAN and how to use it in RadioLib!
|
||||
* [LoRaWAN_Reference](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Reference): this sketch showcases most of the available API for LoRaWAN in RadioLib. Be frightened by the possibilities! It is recommended you have read all the `notes` for the Starter sketch first, as well as the [Learn section on The Things Network](https://www.thethingsnetwork.org/docs/lorawan/)!
|
||||
* [LoRaWAN_Starter](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Starter): this is the recommended entry point for new users. Please read the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) that come with this example to learn more about LoRaWAN and how to use it in RadioLib!
|
||||
* [LoRaWAN_Reference](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_Reference): this sketch showcases most of the available API for LoRaWAN in RadioLib. Be frightened by the possibilities! It is recommended you have read all the [`notes`](https://github.com/jgromes/RadioLib/blob/master/examples/LoRaWAN/LoRaWAN_Starter/notes.md) for the Starter sketch first, as well as the [Learn section on The Things Network](https://www.thethingsnetwork.org/docs/lorawan/)!
|
||||
* [LoRaWAN_ABP](https://github.com/jgromes/RadioLib/tree/master/examples/LoRaWAN/LoRaWAN_ABP): if you wish to use ABP instead of OTAA (but why?), this example shows how you can do this using RadioLib.
|
||||
|
||||
---
|
||||
|
||||
All three of these examples do not fully comply with LoRaWAN v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
|
||||
> [!WARNING]
|
||||
> These examples do not fully comply with LoRaWAN v1.1: for that, persistent storage is necessary. As the implementation of persistent storage differs between different platforms, these are not given here, but in a separate repository, see below:
|
||||
|
||||
## RadioLib persistence
|
||||
In [this repository](https://github.com/radiolib-org/radiolib-persistence), examples are provided that do comply with the required persistence of certain parameters for LoRaWAN v1.1. Examples are (or will become) available for some of the most popular platforms. **These examples assume you have successfully used the Starter sketch and understood (most of) the accompanying notes!**
|
||||
Currently, examples are available for the following platforms:
|
||||
|
||||
* [LoRaWAN for ESP32](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP32)
|
||||
* [LoRaWAN for ESP8266](https://github.com/radiolib-org/radiolib-persistence/tree/main/examples/LoRaWAN_ESP8266)
|
||||
|
||||
_This list is last updated for RadioLib 6.5.0_
|
||||
_This list is last updated at 30/03/2024._
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ add_executable(${PROJECT_NAME} main.cpp)
|
|||
target_link_libraries(${PROJECT_NAME} RadioLib pigpio)
|
||||
|
||||
# you can also specify RadioLib compile-time flags here
|
||||
#target_compile_definitions(${PROJECT_NAME} PUBLIC RADIOLIB_DEBUG RADIOLIB_VERBOSE)
|
||||
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_BASIC RADIOLIB_DEBUG_SPI)
|
||||
#target_compile_definitions(RadioLib PUBLIC RADIOLIB_DEBUG_PORT=stdout)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@
|
|||
// include the library for Raspberry GPIO pins
|
||||
#include "pigpio.h"
|
||||
|
||||
// these should really be swapped, but for some reason,
|
||||
// it seems like the change directions are inverted in gpioSetAlert functions
|
||||
#define PI_RISING (FALLING_EDGE)
|
||||
#define PI_FALLING (RISING_EDGE)
|
||||
|
||||
// forward declaration of alert handler that will be used to emulate interrupts
|
||||
static void pigpioAlertHandler(int event, int level, uint32_t tick, void *userdata);
|
||||
|
||||
// create a new Raspberry Pi hardware abstraction layer
|
||||
// using the pigpio library
|
||||
// the HAL must inherit from the base RadioLibHal class
|
||||
|
|
@ -15,7 +23,7 @@ class PiHal : public RadioLibHal {
|
|||
public:
|
||||
// default constructor - initializes the base HAL and any needed private members
|
||||
PiHal(uint8_t spiChannel, uint32_t spiSpeed = 2000000)
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, RISING_EDGE, FALLING_EDGE),
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, PI_RISING, PI_FALLING),
|
||||
_spiChannel(spiChannel),
|
||||
_spiSpeed(spiSpeed) {
|
||||
}
|
||||
|
|
@ -71,38 +79,50 @@ class PiHal : public RadioLibHal {
|
|||
}
|
||||
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
if((interruptNum == RADIOLIB_NC) || (interruptNum > PI_MAX_USER_GPIO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, mode, 0, (gpioISRFunc_t)interruptCb);
|
||||
// enable emulated interrupt
|
||||
interruptEnabled[interruptNum] = true;
|
||||
interruptModes[interruptNum] = mode;
|
||||
interruptCallbacks[interruptNum] = interruptCb;
|
||||
|
||||
// set pigpio alert callback
|
||||
gpioSetAlertFuncEx(interruptNum, pigpioAlertHandler, (void*)this);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
if((interruptNum == RADIOLIB_NC) || (interruptNum > PI_MAX_USER_GPIO)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpioSetISRFunc(interruptNum, 0, 0, NULL);
|
||||
// clear emulated interrupt
|
||||
interruptEnabled[interruptNum] = false;
|
||||
interruptModes[interruptNum] = 0;
|
||||
interruptCallbacks[interruptNum] = NULL;
|
||||
|
||||
// disable pigpio alert callback
|
||||
gpioSetAlertFuncEx(interruptNum, NULL, NULL);
|
||||
}
|
||||
|
||||
void delay(unsigned long ms) override {
|
||||
void delay(RadioLibTime_t ms) override {
|
||||
gpioDelay(ms * 1000);
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned long us) override {
|
||||
void delayMicroseconds(RadioLibTime_t us) override {
|
||||
gpioDelay(us);
|
||||
}
|
||||
|
||||
unsigned long millis() override {
|
||||
RadioLibTime_t millis() override {
|
||||
return(gpioTick() / 1000);
|
||||
}
|
||||
|
||||
unsigned long micros() override {
|
||||
RadioLibTime_t micros() override {
|
||||
return(gpioTick());
|
||||
}
|
||||
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override {
|
||||
long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) override {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -120,7 +140,7 @@ class PiHal : public RadioLibHal {
|
|||
return(this->micros() - start);
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
void spiBegin() {
|
||||
if(_spiHandle < 0) {
|
||||
_spiHandle = spiOpen(_spiChannel, _spiSpeed, 0);
|
||||
}
|
||||
|
|
@ -141,6 +161,12 @@ class PiHal : public RadioLibHal {
|
|||
}
|
||||
}
|
||||
|
||||
// interrupt emulation
|
||||
bool interruptEnabled[PI_MAX_USER_GPIO + 1];
|
||||
uint32_t interruptModes[PI_MAX_USER_GPIO + 1];
|
||||
typedef void (*RadioLibISR)(void);
|
||||
RadioLibISR interruptCallbacks[PI_MAX_USER_GPIO + 1];
|
||||
|
||||
private:
|
||||
// the HAL can contain any additional private members
|
||||
const unsigned int _spiSpeed;
|
||||
|
|
@ -148,4 +174,21 @@ class PiHal : public RadioLibHal {
|
|||
int _spiHandle = -1;
|
||||
};
|
||||
|
||||
// this handler emulates interrupts
|
||||
static void pigpioAlertHandler(int event, int level, uint32_t tick, void *userdata) {
|
||||
if((event > PI_MAX_USER_GPIO) || (!userdata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// PiHal isntance is passed via the user data
|
||||
PiHal* hal = (PiHal*)userdata;
|
||||
|
||||
// check the interrupt is enabled, the level matches and a callback exists
|
||||
if((hal->interruptEnabled[event]) &&
|
||||
(hal->interruptModes[event] == level) &&
|
||||
(hal->interruptCallbacks[event])) {
|
||||
hal->interruptCallbacks[event]();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ cd build
|
|||
cmake -G "CodeBlocks - Unix Makefiles" ..
|
||||
make
|
||||
cd ..
|
||||
size build/rpi-sx1261
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@ cmake_minimum_required(VERSION 3.18)
|
|||
# create the project
|
||||
project(tock-sx1261)
|
||||
|
||||
set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/userland_generic.ld)
|
||||
set(LINKER_SCRIPT $ENV{LIBTOCK_C_DIRECTORY}/userland_generic.ld)
|
||||
|
||||
include("tock.cmake")
|
||||
if (RISCV_BUILD)
|
||||
include("tock-riscv.cmake")
|
||||
else()
|
||||
include("tock-arm.cmake")
|
||||
endif()
|
||||
|
||||
# when using debuggers such as gdb, the following line can be used
|
||||
#set(CMAKE_BUILD_TYPE Debug)
|
||||
|
|
@ -43,18 +47,62 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../../../../RadioLib" "${CMAKE_CUR
|
|||
add_executable(${PROJECT_NAME} main.cpp)
|
||||
|
||||
# link with RadioLib and libtock-c
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libtock/build/cortex-m4/libtock.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libc++/cortex-m/libgcc.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/libc++/cortex-m/libstdc++.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/newlib/cortex-m/v7-m/libc.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c/newlib/cortex-m/v7-m/libm.a
|
||||
)
|
||||
# The build system for libtock-c is a bit odd and the version of libraries
|
||||
# built changes based on compiler version.
|
||||
if (RISCV_BUILD)
|
||||
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/rv32i/ilp32/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libm.a
|
||||
)
|
||||
|
||||
target_include_directories(RadioLib AFTER PUBLIC
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/riscv/riscv64-unknown-elf/include/
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/rv32imc/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/riscv/lib/gcc/riscv64-unknown-elf/10.5.0/rv32i/ilp32/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/lib/rv32i/ilp32/libm.a
|
||||
)
|
||||
|
||||
target_include_directories(RadioLib AFTER PUBLIC
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/riscv/riscv64-unknown-elf/include/
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
if(EXISTS "$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/arm/lib/gcc/arm-none-eabi/13.2.0/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-13.2.0/arm/arm-none-eabi/lib/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/arm/arm-none-eabi/lib/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.3.0.20230120/arm/arm-none-eabi/lib/libm.a
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
RadioLib
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/libtock/build/cortex-m4/libtock.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/arm/lib/gcc/arm-none-eabi/10.5.0/libgcc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-libc++-10.5.0/arm/arm-none-eabi/lib/libstdc++.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/arm/arm-none-eabi/lib/libc.a
|
||||
$ENV{LIBTOCK_C_DIRECTORY}/lib/libtock-newlib-4.2.0.20211231/arm/arm-none-eabi/lib/libm.a
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libtock-c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/
|
||||
$ENV{LIBTOCK_C_DIRECTORY}
|
||||
)
|
||||
|
||||
# you can also specify RadioLib compile-time flags here
|
||||
|
|
|
|||
|
|
@ -13,16 +13,22 @@ This has been tested on the
|
|||
but will work on any LoRa compatible Tock board (currently only the
|
||||
expLoRaBLE board).
|
||||
|
||||
libtock-c by default is bulit for RISC-V and ARM. RadioLib is also built
|
||||
for both architectures by default. You can skip the RISC-V RadioLib build
|
||||
by setting the `SKIP_RISCV` varaible.
|
||||
|
||||
The RadioLib example can be built with:
|
||||
|
||||
```shell
|
||||
$ git clone https://github.com/jgromes/RadioLib.git
|
||||
$ cd RadioLib/examples/NonArduino/Tock/
|
||||
$ ./build.sh
|
||||
$ git clone https://github.com/tock/libtock-c.git
|
||||
$ cd libtock-c; git checkout 44bf89c545953d8859faf101d4b4a4b6a151fe6c; cd ../
|
||||
$ LIBTOCK_C_DIRECTORY="$(pwd)/libtock-c" ./build.sh
|
||||
```
|
||||
|
||||
Then in the Tock repo you can flash the kernel and app with:
|
||||
|
||||
```shell
|
||||
$ make flash; APP=RadioLib/examples/NonArduino/Tock/build/tock-sx1261.tbf make flash-app
|
||||
$ make flash; APP=RadioLib/examples/NonArduino/Tock/build-arm/tock-sx1261.tbf make flash-app
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,20 +1,30 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf ./build
|
||||
rm -rf ./build-*
|
||||
|
||||
cd libtock-c/libtock
|
||||
cd libtock-c/examples/cxx_hello
|
||||
make -j4
|
||||
cd ../../
|
||||
cd ../../../
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
mkdir -p build-arm
|
||||
cd build-arm
|
||||
|
||||
cmake -G "CodeBlocks - Unix Makefiles" ..
|
||||
make -j4
|
||||
|
||||
cd ..
|
||||
|
||||
if ! env | grep SKIP_RISCV; then
|
||||
mkdir -p build-riscv
|
||||
cd build-riscv
|
||||
|
||||
cmake -G "CodeBlocks - Unix Makefiles" -DRISCV_BUILD=1 ..
|
||||
make -j4
|
||||
|
||||
cd ..
|
||||
fi
|
||||
|
||||
elf2tab -n radio-lib --stack 4096 --app-heap 2048 --kernel-heap 2048 \
|
||||
--kernel-major 2 --kernel-minor 1 \
|
||||
-v ./build/tock-sx1261
|
||||
-v ./build-arm/tock-sx1261
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
# This is copied from https://github.com/Lora-net/LoRaMac-node/pull/1390
|
||||
# and has been relicensed by the original author
|
||||
|
||||
include("toolchain-arm-none-eabi.cmake")
|
||||
|
||||
if(NOT DEFINED LINKER_SCRIPT)
|
||||
message(FATAL_ERROR "No linker script defined")
|
||||
endif(NOT DEFINED LINKER_SCRIPT)
|
||||
|
|
@ -40,6 +38,22 @@ set(STACK_SIZE 4096)
|
|||
set(APP_HEAP_SIZE 2048)
|
||||
set(KERNEL_HEAP_SIZE 2048)
|
||||
|
||||
set(TOOLCHAIN arm-none-eabi)
|
||||
|
||||
find_program(TOOLCHAIN_PREFIX ${TOOLCHAIN}-gcc NO_CACHE)
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN_PREFIX} DIRECTORY)
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++ CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
# Object build options
|
||||
set(OBJECT_GEN_FLAGS "-mthumb -g2 -fno-builtin -mcpu=cortex-m4 -Wall -Wextra -pedantic -Wno-unused-parameter -ffunction-sections -fdata-sections -fomit-frame-pointer -mabi=aapcs -fno-unroll-loops -ffast-math -ftree-vectorize -frecord-gcc-switches -gdwarf-2 -Os -fdata-sections -ffunction-sections -fstack-usage -Wl,--emit-relocs -fPIC -mthumb -mfloat-abi=soft -msingle-pic-base -mpic-register=r9 -mno-pic-data-is-text-relative -D__TOCK__ -DSVCALL_AS_NORMAL_FUNCTION -DSOFTDEVICE_s130")
|
||||
|
||||
76
lib/RadioLib/examples/NonArduino/Tock/tock-riscv.cmake
Normal file
76
lib/RadioLib/examples/NonArduino/Tock/tock-riscv.cmake
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Tock target specific CMake file
|
||||
#
|
||||
# Licensed under the MIT License
|
||||
#
|
||||
# Copyright (c) 2023 Alistair Francis <alistair@alistair23.me>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
# This is copied from https://github.com/Lora-net/LoRaMac-node/pull/1390
|
||||
# and has been relicensed by the original author
|
||||
|
||||
if(NOT DEFINED LINKER_SCRIPT)
|
||||
message(FATAL_ERROR "No linker script defined")
|
||||
endif(NOT DEFINED LINKER_SCRIPT)
|
||||
message("Linker script: ${LINKER_SCRIPT}")
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compiler/linker flags
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
set(STACK_SIZE 4096)
|
||||
set(APP_HEAP_SIZE 2048)
|
||||
set(KERNEL_HEAP_SIZE 2048)
|
||||
|
||||
find_program(TOOLCHAIN
|
||||
NAMES
|
||||
riscv64-none-elf-gcc
|
||||
riscv32-none-elf-gcc
|
||||
riscv64-elf-gcc
|
||||
riscv32-unknown-elf-gcc
|
||||
riscv64-unknown-elf-gcc
|
||||
riscv64-unknown-elf-clang
|
||||
riscv32-unknown-elf-clang
|
||||
NO_CACHE)
|
||||
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN} DIRECTORY)
|
||||
|
||||
get_filename_component(TOOLCHAIN ${TOOLCHAIN} NAME)
|
||||
string(REPLACE "-gcc" "" TOOLCHAIN ${TOOLCHAIN})
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++ CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
# Object build options
|
||||
set(OBJECT_GEN_FLAGS "-march=rv32i -mabi=ilp32 -mcmodel=medlow -g2 -fno-builtin -Wall -Wextra -pedantic -Wno-unused-parameter -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-unroll-loops -ffast-math -ftree-vectorize -frecord-gcc-switches -gdwarf-2 -Os -fdata-sections -ffunction-sections -fstack-usage -Wl,--emit-relocs -D__TOCK__ -DSVCALL_AS_NORMAL_FUNCTION -DSOFTDEVICE_s130")
|
||||
|
||||
set(CMAKE_C_FLAGS "${OBJECT_GEN_FLAGS} -std=gnu99 " CACHE INTERNAL "C Compiler options")
|
||||
set(CMAKE_CXX_FLAGS "${OBJECT_GEN_FLAGS} -std=c++20 " CACHE INTERNAL "C++ Compiler options")
|
||||
set(CMAKE_ASM_FLAGS "${OBJECT_GEN_FLAGS} -x assembler-with-cpp " CACHE INTERNAL "ASM Compiler options")
|
||||
|
||||
# Linker flags
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections -march=rv32i -mabi=ilp32 -mcmodel=medlow -T${LINKER_SCRIPT} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Xlinker --defsym=STACK_SIZE=${STACK_SIZE} -Xlinker --defsym=APP_HEAP_SIZE=${APP_HEAP_SIZE} -Xlinker --defsym=KERNEL_HEAP_SIZE=${KERNEL_HEAP_SIZE} -nostdlib -Wl,--start-group" CACHE INTERNAL "Linker options")
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
# Arm specific CMake file
|
||||
#
|
||||
# This is copied from:
|
||||
# https://github.com/Lora-net/LoRaMac-node/blob/2bf36bde72f68257eb96b5c00900619546bedca8/cmake/toolchain-arm-none-eabi.cmake
|
||||
#
|
||||
# The below file is licensed as Revised BSD License
|
||||
# See https://github.com/Lora-net/LoRaMac-node/blob/master/LICENSE for details
|
||||
|
||||
##
|
||||
## ______ _
|
||||
## / _____) _ | |
|
||||
## ( (____ _____ ____ _| |_ _____ ____| |__
|
||||
## \____ \| ___ | (_ _) ___ |/ ___) _ \
|
||||
## _____) ) ____| | | || |_| ____( (___| | | |
|
||||
## (______/|_____)_|_|_| \__)_____)\____)_| |_|
|
||||
## (C)2013-2017 Semtech
|
||||
## ___ _____ _ ___ _ _____ ___ ___ ___ ___
|
||||
## / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
||||
## \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
||||
## |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
||||
## embedded.connectivity.solutions.==============
|
||||
##
|
||||
## License: Revised BSD License, see LICENSE.TXT file included in the project
|
||||
## Authors: Johannes Bruder ( STACKFORCE ), Miguel Luis ( Semtech )
|
||||
##
|
||||
##
|
||||
## CMake arm-none-eabi toolchain file
|
||||
##
|
||||
|
||||
# Append current directory to CMAKE_MODULE_PATH for making device specific cmake modules visible
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Target definition
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set toolchain paths
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(TOOLCHAIN arm-none-eabi)
|
||||
|
||||
find_program(TOOLCHAIN_PREFIX ${TOOLCHAIN}-gcc NO_CACHE)
|
||||
get_filename_component(TOOLCHAIN_PREFIX ${TOOLCHAIN_PREFIX} DIRECTORY)
|
||||
|
||||
set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/../bin)
|
||||
set(TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/include)
|
||||
set(TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/../${TOOLCHAIN}/lib)
|
||||
|
||||
# Set system depended extensions
|
||||
if(WIN32)
|
||||
set(TOOLCHAIN_EXT ".exe" )
|
||||
else()
|
||||
set(TOOLCHAIN_EXT "" )
|
||||
endif()
|
||||
|
||||
# Perform compiler test with static library
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Preset some general GCC Options
|
||||
#---------------------------------------------------------------------------------------
|
||||
|
||||
# Options for DEBUG build
|
||||
# -Og enables optimizations that do not interfere with debugging
|
||||
# -g produce debugging information in the operating system's native format
|
||||
set(CMAKE_C_FLAGS_DEBUG "-Og -g -DDEBUG" CACHE INTERNAL "C Compiler options for debug build type")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -DDEBUG" CACHE INTERNAL "C++ Compiler options for debug build type")
|
||||
set(CMAKE_ASM_FLAGS_DEBUG "-g" CACHE INTERNAL "ASM Compiler options for debug build type")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE INTERNAL "Linker options for debug build type")
|
||||
|
||||
# Options for RELEASE build
|
||||
# -Os Optimize for size. -Os enables all -O2 optimizations
|
||||
set(CMAKE_C_FLAGS_RELEASE "-Os" CACHE INTERNAL "C Compiler options for release build type")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Os" CACHE INTERNAL "C++ Compiler options for release build type")
|
||||
set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "ASM Compiler options for release build type")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "" CACHE INTERNAL "Linker options for release build type")
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
# Set compilers
|
||||
#---------------------------------------------------------------------------------------
|
||||
set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc${TOOLCHAIN_EXT} CACHE INTERNAL "C Compiler")
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-g++${TOOLCHAIN_EXT} CACHE INTERNAL "C++ Compiler")
|
||||
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN_DIR}/${TOOLCHAIN}-gcc${TOOLCHAIN_EXT} CACHE INTERNAL "ASM Compiler")
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_PREFIX}/${${TOOLCHAIN}} ${CMAKE_PREFIX_PATH})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
- nRF24
|
||||
- Si443x/RFM2x
|
||||
- SX128x
|
||||
- LR11x0
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
RadioLib SX128x Channel Activity Detection Example
|
||||
|
||||
This example uses SX1280 to scan the current LoRa
|
||||
channel and detect ongoing LoRa transmissions.
|
||||
|
||||
Other modules from SX128x family can also be used.
|
||||
|
||||
For default module settings, see the wiki page
|
||||
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx128x---lora-modem
|
||||
|
||||
For full API reference, see the GitHub Pages
|
||||
https://jgromes.github.io/RadioLib/
|
||||
*/
|
||||
|
||||
// include the library
|
||||
#include <RadioLib.h>
|
||||
|
||||
// SX1280 has the following connections:
|
||||
// NSS pin: 10
|
||||
// DIO1 pin: 2
|
||||
// NRST pin: 3
|
||||
// BUSY pin: 9
|
||||
SX1280 radio = new Module(10, 2, 3, 9);
|
||||
|
||||
// or using RadioShield
|
||||
// https://github.com/jgromes/RadioShield
|
||||
//SX1280 radio = RadioShield.ModuleA;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
// initialize SX1280 with default settings
|
||||
Serial.print(F("[SX1280] Initializing ... "));
|
||||
int state = radio.begin();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
while (true);
|
||||
}
|
||||
|
||||
// set the function that will be called
|
||||
// when LoRa packet or timeout is detected
|
||||
radio.setDio1Action(setFlag);
|
||||
|
||||
// start scanning the channel
|
||||
Serial.print(F("[SX1280] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
|
||||
// flag to indicate that a packet was detected or CAD timed out
|
||||
volatile bool scanFlag = false;
|
||||
|
||||
// this function is called when a complete packet
|
||||
// is received by the module
|
||||
// IMPORTANT: this function MUST be 'void' type
|
||||
// and MUST NOT have any arguments!
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
ICACHE_RAM_ATTR
|
||||
#endif
|
||||
void setFlag(void) {
|
||||
// something happened, set the flag
|
||||
scanFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check if the flag is set
|
||||
if(scanFlag) {
|
||||
// reset flag
|
||||
scanFlag = false;
|
||||
|
||||
// check CAD result
|
||||
int state = radio.getChannelScanResult();
|
||||
|
||||
if (state == RADIOLIB_LORA_DETECTED) {
|
||||
// LoRa packet was detected
|
||||
Serial.println(F("[SX1280] Packet detected!"));
|
||||
|
||||
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||
// channel is free
|
||||
Serial.println(F("[SX1280] Channel is free!"));
|
||||
|
||||
} else {
|
||||
// some other error occurred
|
||||
Serial.print(F("[SX1280] Failed, code "));
|
||||
Serial.println(state);
|
||||
|
||||
}
|
||||
|
||||
// start scanning the channel again
|
||||
Serial.print(F("[SX1280] Starting scan for LoRa preamble ... "));
|
||||
state = radio.startChannelScan();
|
||||
if (state == RADIOLIB_ERR_NONE) {
|
||||
Serial.println(F("success!"));
|
||||
} else {
|
||||
Serial.print(F("failed, code "));
|
||||
Serial.println(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
lib/RadioLib/extras/SSTV_Image_Converter/ImageConverter.py
Normal file
50
lib/RadioLib/extras/SSTV_Image_Converter/ImageConverter.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib image to array conversion tool.
|
||||
|
||||
Input is a PNG image to be transmitted via RadioLib SSTV.
|
||||
The image must have correct size for the chose SSTV mode!
|
||||
|
||||
Output is a file (by default named "img.h") which can be included and transmitted.
|
||||
The resulting array will be very large (typically 320 kB),
|
||||
make sure your platform has sufficient Flash/RAM space.
|
||||
''')
|
||||
parser.add_argument('input',
|
||||
type=str,
|
||||
help='Input PNG file')
|
||||
parser.add_argument('output',
|
||||
type=str,
|
||||
nargs='?',
|
||||
default='img',
|
||||
help='Output header file')
|
||||
args = parser.parse_args()
|
||||
outfile = f'{args.output}.h'
|
||||
print(f'Converting "{args.input}" to "{outfile}"')
|
||||
|
||||
# open the image as numpy array
|
||||
img = Image.open(args.input)
|
||||
arr = np.array(img)
|
||||
|
||||
# open the output file
|
||||
with open(outfile, 'w') as f:
|
||||
print(f'const uint32_t img[{arr.shape[0]}][{arr.shape[1]}] = {{', file=f)
|
||||
for row in arr:
|
||||
print(' { ', end='', file=f)
|
||||
for pix in row:
|
||||
rgb = pix[0] << 16 | pix[1] << 8 | pix[2]
|
||||
print(hex(rgb), end=', ', file=f)
|
||||
print(' },', file=f)
|
||||
print('};', file=f)
|
||||
|
||||
print('Done!')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
lib/RadioLib/extras/SSTV_Image_Converter/radiolib.png
Normal file
BIN
lib/RadioLib/extras/SSTV_Image_Converter/radiolib.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
176
lib/RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
Normal file
176
lib/RadioLib/extras/SX126x_Spectrum_Scan/SpectrumScan.py
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import serial
|
||||
import sys
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from datetime import datetime
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
# number of samples in each scanline
|
||||
SCAN_WIDTH = 33
|
||||
|
||||
# scanline Serial start/end markers
|
||||
SCAN_MARK_START = 'SCAN '
|
||||
SCAN_MARK_FREQ = 'FREQ '
|
||||
SCAN_MARK_END = ' END'
|
||||
|
||||
# output path
|
||||
OUT_PATH = 'out'
|
||||
|
||||
# default settings
|
||||
DEFAULT_BAUDRATE = 115200
|
||||
DEFAULT_COLOR_MAP = 'viridis'
|
||||
DEFAULT_SCAN_LEN = 200
|
||||
DEFAULT_RSSI_OFFSET = -11
|
||||
|
||||
# Print iterations progress
|
||||
# from https://stackoverflow.com/questions/3173320/text-progress-bar-in-terminal-with-block-characters
|
||||
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 50, fill = '█', printEnd = "\r"):
|
||||
"""
|
||||
Call in a loop to create terminal progress bar
|
||||
@params:
|
||||
iteration - Required : current iteration (Int)
|
||||
total - Required : total iterations (Int)
|
||||
prefix - Optional : prefix string (Str)
|
||||
suffix - Optional : suffix string (Str)
|
||||
decimals - Optional : positive number of decimals in percent complete (Int)
|
||||
length - Optional : character length of bar (Int)
|
||||
fill - Optional : bar fill character (Str)
|
||||
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
|
||||
"""
|
||||
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
|
||||
filledLength = int(length * iteration // total)
|
||||
bar = fill * filledLength + '-' * (length - filledLength)
|
||||
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
|
||||
if iteration == total:
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib SX126x_Spectrum_Scan plotter script. Displays output from SX126x_Spectrum_Scan example
|
||||
as grayscale and
|
||||
|
||||
Depends on pyserial and matplotlib, install by:
|
||||
'python3 -m pip install pyserial matplotlib'
|
||||
|
||||
Step-by-step guide on how to use the script:
|
||||
1. Upload the SX126x_Spectrum_Scan example to your Arduino board with SX1262 connected.
|
||||
2. Run the script with appropriate arguments.
|
||||
3. Once the scan is complete, output files will be saved to out/
|
||||
''')
|
||||
parser.add_argument('port',
|
||||
type=str,
|
||||
help='COM port to connect to the device')
|
||||
parser.add_argument('--speed',
|
||||
default=DEFAULT_BAUDRATE,
|
||||
type=int,
|
||||
help=f'COM port baudrate (defaults to {DEFAULT_BAUDRATE})')
|
||||
parser.add_argument('--map',
|
||||
default=DEFAULT_COLOR_MAP,
|
||||
type=str,
|
||||
help=f'Matplotlib color map to use for the output (defaults to "{DEFAULT_COLOR_MAP}")')
|
||||
parser.add_argument('--len',
|
||||
default=DEFAULT_SCAN_LEN,
|
||||
type=int,
|
||||
help=f'Number of scanlines to record (defaults to {DEFAULT_SCAN_LEN})')
|
||||
parser.add_argument('--offset',
|
||||
default=DEFAULT_RSSI_OFFSET,
|
||||
type=int,
|
||||
help=f'Default RSSI offset in dBm (defaults to {DEFAULT_RSSI_OFFSET})')
|
||||
parser.add_argument('--freq',
|
||||
default=-1,
|
||||
type=float,
|
||||
help=f'Default starting frequency in MHz')
|
||||
args = parser.parse_args()
|
||||
|
||||
freq_mode = False
|
||||
scan_len = args.len
|
||||
if (args.freq != -1):
|
||||
freq_mode = True
|
||||
scan_len = 1000
|
||||
|
||||
# create the color map and the result array
|
||||
arr = np.zeros((SCAN_WIDTH, scan_len))
|
||||
|
||||
# scanline counter
|
||||
row = 0
|
||||
|
||||
# list of frequencies in frequency mode
|
||||
freq_list = []
|
||||
|
||||
# open the COM port
|
||||
with serial.Serial(args.port, args.speed, timeout=None) as com:
|
||||
while(True):
|
||||
# update the progress bar
|
||||
if not freq_mode:
|
||||
printProgressBar(row, scan_len)
|
||||
|
||||
# read a single line
|
||||
try:
|
||||
line = com.readline().decode('utf-8')
|
||||
except:
|
||||
continue
|
||||
|
||||
if SCAN_MARK_FREQ in line:
|
||||
new_freq = float(line.split(' ')[1])
|
||||
if (len(freq_list) > 1) and (new_freq < freq_list[-1]):
|
||||
break
|
||||
|
||||
freq_list.append(new_freq)
|
||||
print('{:.3f}'.format(new_freq), end = '\r')
|
||||
continue
|
||||
|
||||
# check the markers
|
||||
if (SCAN_MARK_START in line) and (SCAN_MARK_END in line):
|
||||
# get the values
|
||||
scanline = line[len(SCAN_MARK_START):-len(SCAN_MARK_END)].split(',')
|
||||
for col in range(SCAN_WIDTH):
|
||||
arr[col][row] = int(scanline[col])
|
||||
|
||||
# increment the row counter
|
||||
row = row + 1
|
||||
|
||||
# check if we're done
|
||||
if (not freq_mode) and (row >= scan_len):
|
||||
break
|
||||
|
||||
# scale to the number of scans (sum of any given scanline)
|
||||
num_samples = arr.sum(axis=0)[0]
|
||||
arr *= (num_samples/arr.max())
|
||||
|
||||
if freq_mode:
|
||||
scan_len = len(freq_list)
|
||||
|
||||
# create the figure
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
# display the result as heatmap
|
||||
extent = [0, scan_len, -4*(SCAN_WIDTH + 1), args.offset]
|
||||
if freq_mode:
|
||||
extent[0] = freq_list[0]
|
||||
extent[1] = freq_list[-1]
|
||||
im = ax.imshow(arr[:,:scan_len], cmap=args.map, extent=extent)
|
||||
fig.colorbar(im)
|
||||
|
||||
# set some properites and show
|
||||
timestamp = datetime.now().strftime('%y-%m-%d %H-%M-%S')
|
||||
title = f'RadioLib SX126x Spectral Scan {timestamp}'
|
||||
if freq_mode:
|
||||
plt.xlabel("Frequency [Hz]")
|
||||
else:
|
||||
plt.xlabel("Time [sample]")
|
||||
plt.ylabel("RSSI [dBm]")
|
||||
ax.set_aspect('auto')
|
||||
fig.suptitle(title)
|
||||
fig.canvas.manager.set_window_title(title)
|
||||
plt.savefig(f'{OUT_PATH}/{title.replace(" ", "_")}.png', dpi=300)
|
||||
plt.show()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
111
lib/RadioLib/extras/decoder/DebugDecoder.py
Normal file
111
lib/RadioLib/extras/decoder/DebugDecoder.py
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
import re, sys, argparse
|
||||
from pathlib import Path
|
||||
from argparse import RawTextHelpFormatter
|
||||
|
||||
|
||||
'''
|
||||
TODO list:
|
||||
1. Parse macro values (the names of bits in all registers in header file)
|
||||
2. Failed SPI write handling
|
||||
3. SX126x/SX128x handling
|
||||
'''
|
||||
|
||||
|
||||
def get_macro_name(value, macros):
|
||||
for macro in macros:
|
||||
if macro[1] == value:
|
||||
return macro[0]
|
||||
return 'UNKNOWN_VALUE'
|
||||
|
||||
|
||||
def get_macro_value(value):
|
||||
return ' 0x{0:02X}\n'.format(int(value, 16))
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''
|
||||
RadioLib debug output decoder script. Turns RadioLib Serial dumps into readable text.
|
||||
|
||||
Step-by-step guid on how to use the decoder:
|
||||
1. Uncomment lines 312 (#define RADIOLIB_DEBUG) and 313 (#define RADIOLIB_VERBOSE) in RadioLib/src/BuildOpt.h
|
||||
2. Recompile and upload the failing Arduino sketch
|
||||
3. Open Arduino IDE Serial Monitor and enable timestamps
|
||||
4. Copy the Serial output and save it into a .txt file
|
||||
5. Run this script
|
||||
|
||||
Output will be saved in the file specified by --out and printed to the terminal
|
||||
''')
|
||||
parser.add_argument('file', metavar='file', type=str, help='Text file of the debug output')
|
||||
parser.add_argument('--out', metavar='out', default='./out.txt', type=str, help='Where to save the decoded file (defaults to ./out.txt)')
|
||||
args = parser.parse_args()
|
||||
|
||||
# open the log file
|
||||
log = open(args.file, 'r').readlines()
|
||||
|
||||
# find modules that are in use
|
||||
used_modules = []
|
||||
pattern_module = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?M\t')
|
||||
for entry in log:
|
||||
m = pattern_module.search(entry)
|
||||
if m != None:
|
||||
used_modules.append(entry[m.end():].rstrip())
|
||||
|
||||
# get paths to all relevant header files
|
||||
header_files = []
|
||||
for path in Path('../../src').rglob('*.h'):
|
||||
for module in used_modules:
|
||||
if module in path.name:
|
||||
header_files.append(path)
|
||||
|
||||
# extract names of address macros from the header files
|
||||
macro_addresses = []
|
||||
pattern_define = re.compile('#define \w* +\w*(\n| +\/\/){1}')
|
||||
for path in header_files:
|
||||
file = open(path, 'r').readlines()
|
||||
for line in file:
|
||||
m = pattern_define.search(line)
|
||||
if m != None:
|
||||
s = re.split(' +', m.group().rstrip())
|
||||
if (s.__len__() > 1) and ('_REG' in s[1]):
|
||||
macro_addresses.append([s[1], int(s[2], 0)])
|
||||
|
||||
'''
|
||||
# extract names of value macros for each adddress macro
|
||||
macro_values = []
|
||||
for path in header_files:
|
||||
file = open(path, 'r').readlines()
|
||||
for line in file:
|
||||
for module in used_modules:
|
||||
pattern_addr_macro = re.compile('\/\/ SI443X_REG_\w+'.format(module.capitalize()))
|
||||
'''
|
||||
|
||||
# parse every line in the log file
|
||||
out = []
|
||||
pattern_debug = re.compile('(([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?.[0-9]{3} -> )?[RWM]\t.+')
|
||||
for entry in log:
|
||||
m = pattern_debug.search(entry)
|
||||
if m != None:
|
||||
s = re.split('( |\t)+', entry.rstrip())
|
||||
cmd_len = int((s.__len__() - 7)/2)
|
||||
new_entry = s[0] + s[1] + s[2] + s[3]
|
||||
if s[4] == 'W':
|
||||
macro_address = int(s[6], 16)
|
||||
new_entry += 'write {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
|
||||
for i in range(cmd_len):
|
||||
new_entry += get_macro_value(s[8 + 2*i]);
|
||||
elif s[4] == 'R':
|
||||
macro_address = int(s[6], 16)
|
||||
new_entry += 'read {0:>2} 0x{1:02X} {2}\n'.format(cmd_len, macro_address, get_macro_name(macro_address, macro_addresses))
|
||||
for i in range(cmd_len):
|
||||
new_entry += get_macro_value(s[8 + 2*i]);
|
||||
elif s[4] == 'M':
|
||||
new_entry += 'module {}\n'.format(s[6])
|
||||
out.append(new_entry)
|
||||
else:
|
||||
out.append(entry)
|
||||
|
||||
# write the output file
|
||||
out_file = open(args.out, 'w')
|
||||
for line in out:
|
||||
print(line, end='')
|
||||
out_file.write(line)
|
||||
out_file.close()
|
||||
22
lib/RadioLib/extras/template/ModuleTemplate.cpp
Normal file
22
lib/RadioLib/extras/template/ModuleTemplate.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "<module_name>.h"
|
||||
#if !defined(RADIOLIB_EXCLUDE_<module_name>)
|
||||
|
||||
<module_name>::<module_name>(Module* mod) {
|
||||
/*
|
||||
Constructor implementation MUST assign the provided "mod" pointer to the private "_mod" pointer.
|
||||
*/
|
||||
_mod = mod;
|
||||
}
|
||||
|
||||
int16_t <module_name>::begin() {
|
||||
/*
|
||||
"begin" method implementation MUST call the "init" method with appropriate settings.
|
||||
*/
|
||||
_mod->init();
|
||||
|
||||
/*
|
||||
"begin" method SHOULD implement some sort of mechanism to verify the connection between Arduino and the module.
|
||||
|
||||
For example, reading a version register
|
||||
*/
|
||||
}
|
||||
99
lib/RadioLib/extras/template/ModuleTemplate.h
Normal file
99
lib/RadioLib/extras/template/ModuleTemplate.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
RadioLib Module Template header file
|
||||
|
||||
Before opening pull request, please make sure that:
|
||||
1. All files MUST be compiled without errors using default Arduino IDE settings.
|
||||
2. All files SHOULD be compiled without warnings with compiler warnings set to "All".
|
||||
3. Example sketches MUST be working correctly and MUST be stable enough to run for prolonged periods of time.
|
||||
4. Writing style SHOULD be consistent.
|
||||
5. Comments SHOULD be in place for the most important chunks of code and SHOULD be free of typos.
|
||||
6. To indent, 2 spaces MUST be used.
|
||||
|
||||
If at any point you are unsure about the required style, please refer to the rest of the modules.
|
||||
*/
|
||||
|
||||
#if !defined(_RADIOLIB_<module_name>_H) && !defined(RADIOLIB_EXCLUDE_<module_name>)
|
||||
#if !defined(_RADIOLIB_<module_name>_H)
|
||||
#define _RADIOLIB_<module_name>_H
|
||||
|
||||
/*
|
||||
Header file for each module MUST include Module.h and TypeDef.h in the src folder.
|
||||
The header file MAY include additional header files.
|
||||
*/
|
||||
#include "../../Module.h"
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
/*
|
||||
Only use the following include if the module implements methods for OSI physical layer control.
|
||||
This concerns only modules similar to SX127x/RF69/CC1101 etc.
|
||||
|
||||
In this case, your class MUST implement all virtual methods of PhysicalLayer class.
|
||||
*/
|
||||
//#include "../../protocols/PhysicalLayer/PhysicalLayer.h"
|
||||
|
||||
/*
|
||||
Register map
|
||||
Definition of SPI register map SHOULD be placed here. The register map SHOULD have two parts:
|
||||
|
||||
1 - Address map: only defines register names and addresses. Register names MUST match names in
|
||||
official documentation (datasheets etc.).
|
||||
2 - Variable map: defines variables inside register. This functions as a bit range map for a specific register.
|
||||
Bit range (MSB and LSB) as well as short description for each variable MUST be provided in a comment.
|
||||
|
||||
See RF69 and SX127x header files for examples of register maps.
|
||||
*/
|
||||
// <module_name> register map | spaces up to this point
|
||||
#define RADIOLIB_<module_name>_REG_<register_name> 0x00
|
||||
|
||||
// <module_name>_REG_<register_name> MSB LSB DESCRIPTION
|
||||
#define RADIOLIB_<module_name>_<register_variable> 0b00000000 // 7 0 <description>
|
||||
|
||||
|
||||
/*
|
||||
Module class definition
|
||||
|
||||
The module class MAY inherit from the following classes:
|
||||
|
||||
1 - PhysicalLayer: In case the module implements methods for OSI physical layer control (e.g. SX127x).
|
||||
2 - Common class: In case the module further specifies some more generic class (e.g. SX127x/SX1278)
|
||||
*/
|
||||
class <module_name> {
|
||||
public:
|
||||
/*
|
||||
Constructor MUST have only one parameter "Module* mod".
|
||||
The class MAY implement additional overloaded constructors.
|
||||
*/
|
||||
// constructor
|
||||
<module_name>(Module* mod);
|
||||
|
||||
/*
|
||||
The class MUST implement at least one basic method called "begin".
|
||||
The "begin" method MUST initialize the module and return the status as int16_t type.
|
||||
*/
|
||||
// basic methods
|
||||
int16_t begin();
|
||||
|
||||
/*
|
||||
The class MAY implement additional methods.
|
||||
All implemented methods SHOULD return the status as int16_t type.
|
||||
*/
|
||||
|
||||
#if !defined(RADIOLIB_GODMODE)
|
||||
private:
|
||||
#endif
|
||||
/*
|
||||
The class MUST contain private member "Module* _mod"
|
||||
*/
|
||||
Module* _mod;
|
||||
|
||||
/*
|
||||
The class MAY contain additional private variables and/or methods.
|
||||
Private member variables MUST have a name prefixed with "_" (underscore, ASCII 0x5F)
|
||||
|
||||
Usually, these are variables for saving module configuration, or methods that do not have to be exposed to the end user.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
version: "6.5.0"
|
||||
description: "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN)."
|
||||
tags: "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan"
|
||||
tags: "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan, lr1110, lr1120, lr1121"
|
||||
url: "https://github.com/jgromes/RadioLib"
|
||||
repository: "https://github.com/jgromes/RadioLib.git"
|
||||
license: "MIT"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ ArduinoHal KEYWORD1
|
|||
# modules
|
||||
CC1101 KEYWORD1
|
||||
LLCC68 KEYWORD1
|
||||
LR1110 KEYWORD1
|
||||
LR1120 KEYWORD1
|
||||
LR1121 KEYWORD1
|
||||
nRF24 KEYWORD1
|
||||
RF69 KEYWORD1
|
||||
RFM22 KEYWORD1
|
||||
|
|
@ -88,6 +91,11 @@ AS923 KEYWORD1
|
|||
KR920 KEYWORD1
|
||||
IN865 KEYWORD1
|
||||
|
||||
# LR11x0 scan results
|
||||
LR11x0WifiResult_t KEYWORD1
|
||||
LR11x0WifiResultFull_t KEYWORD1
|
||||
LR11x0WifiResultExtended_t KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
|
@ -124,6 +132,7 @@ setCodingRate KEYWORD2
|
|||
setFrequency KEYWORD2
|
||||
setSyncWord KEYWORD2
|
||||
setOutputPower KEYWORD2
|
||||
checkOutputPower KEYWORD2
|
||||
setCurrentLimit KEYWORD2
|
||||
setPreambleLength KEYWORD2
|
||||
setGain KEYWORD2
|
||||
|
|
@ -134,6 +143,7 @@ getSNR KEYWORD2
|
|||
getDataRate KEYWORD2
|
||||
setBitRate KEYWORD2
|
||||
setRxBandwidth KEYWORD2
|
||||
autoSetRxBandwidth KEYWORD2
|
||||
setAFCBandwidth KEYWORD2
|
||||
setAFC KEYWORD2
|
||||
setAFCAGCTrigger KEYWORD2
|
||||
|
|
@ -224,6 +234,7 @@ spectralScanStart KEYWORD2
|
|||
spectralScanAbort KEYWORD2
|
||||
spectralScanGetStatus KEYWORD2
|
||||
spectralScanGetResult KEYWORD2
|
||||
setPaRampTime KEYWORD2
|
||||
|
||||
# nRF24
|
||||
setIrqAction KEYWORD2
|
||||
|
|
@ -234,6 +245,16 @@ disablePipe KEYWORD2
|
|||
getStatus KEYWORD2
|
||||
setAutoAck KEYWORD2
|
||||
|
||||
# LR11x0
|
||||
beginLRFHSS KEYWORD2
|
||||
setLrFhssConfig KEYWORD2
|
||||
startWifiScan KEYWORD2
|
||||
getWifiScanResultsCount KEYWORD2
|
||||
getWifiScanResult KEYWORD2
|
||||
wifiScan KEYWORD2
|
||||
setWiFiScanAction KEYWORD2
|
||||
clearWiFiScanAction KEYWORD2
|
||||
|
||||
# RTTY
|
||||
idle KEYWORD2
|
||||
byteArr KEYWORD2
|
||||
|
|
@ -307,10 +328,10 @@ uplink KEYWORD2
|
|||
downlink KEYWORD2
|
||||
sendReceive KEYWORD2
|
||||
setDeviceStatus KEYWORD2
|
||||
getFcntUp KEYWORD2
|
||||
getNFcntDown KEYWORD2
|
||||
getAFcntDown KEYWORD2
|
||||
resetFcntDown KEYWORD2
|
||||
getFCntUp KEYWORD2
|
||||
getNFCntDown KEYWORD2
|
||||
getAFCntDown KEYWORD2
|
||||
resetFCntDown KEYWORD2
|
||||
setDatarate KEYWORD2
|
||||
setADR KEYWORD2
|
||||
setDutyCycle KEYWORD2
|
||||
|
|
@ -319,10 +340,10 @@ timeUntilUplink KEYWORD2
|
|||
setDwellTime KEYWORD2
|
||||
maxPayloadDwellTime KEYWORD2
|
||||
setTxPower KEYWORD2
|
||||
setCSMA KEYWORD2
|
||||
getMacLinkCheckAns KEYWORD2
|
||||
getMacDeviceTimeAns KEYWORD2
|
||||
getDevAddr KEYWORD2
|
||||
getLastToA KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "RadioLib",
|
||||
"version": "6.5.0",
|
||||
"description": "Universal wireless communication library. User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).",
|
||||
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan",
|
||||
"keywords": "radio, communication, morse, cc1101, aprs, sx1276, sx1278, sx1272, rtty, ax25, afsk, nrf24, rfm96, sx1231, rfm96, rfm98, sstv, sx1278, sx1272, sx1276, sx1280, sx1281, sx1282, sx1261, sx1262, sx1268, si4432, rfm22, llcc68, pager, pocsag, lorawan, lr1110, lr1120, lr1121",
|
||||
"homepage": "https://github.com/jgromes/RadioLib",
|
||||
"repository":
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ version=6.5.0
|
|||
author=Jan Gromes <gromes.jan@gmail.com>
|
||||
maintainer=Jan Gromes <gromes.jan@gmail.com>
|
||||
sentence=Universal wireless communication library
|
||||
paragraph=User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).
|
||||
paragraph=User-friendly library for sub-GHz radio modules (SX1278, RF69, CC1101, SX1268, LR1110 and many others), as well as ham radio digital modes (RTTY, SSTV, AX.25 etc.) and other protocols (Pagers, LoRaWAN).
|
||||
category=Communication
|
||||
url=https://github.com/jgromes/RadioLib
|
||||
architectures=*
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void inline ArduinoHal::detachInterrupt(uint32_t interruptNum) {
|
|||
::detachInterrupt(interruptNum);
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delay(unsigned long ms) {
|
||||
void inline ArduinoHal::delay(RadioLibTime_t ms) {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
::delay(ms);
|
||||
#else
|
||||
|
|
@ -61,7 +61,7 @@ void inline ArduinoHal::delay(unsigned long ms) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void inline ArduinoHal::delayMicroseconds(unsigned long us) {
|
||||
void inline ArduinoHal::delayMicroseconds(RadioLibTime_t us) {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
::delayMicroseconds(us);
|
||||
#else
|
||||
|
|
@ -69,7 +69,7 @@ void inline ArduinoHal::delayMicroseconds(unsigned long us) {
|
|||
#endif
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::millis() {
|
||||
RadioLibTime_t inline ArduinoHal::millis() {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
return(::millis());
|
||||
#else
|
||||
|
|
@ -77,7 +77,7 @@ unsigned long inline ArduinoHal::millis() {
|
|||
#endif
|
||||
}
|
||||
|
||||
unsigned long inline ArduinoHal::micros() {
|
||||
RadioLibTime_t inline ArduinoHal::micros() {
|
||||
#if !defined(RADIOLIB_CLOCK_DRIFT_MS)
|
||||
return(::micros());
|
||||
#else
|
||||
|
|
@ -85,7 +85,7 @@ unsigned long inline ArduinoHal::micros() {
|
|||
#endif
|
||||
}
|
||||
|
||||
long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) {
|
||||
long inline ArduinoHal::pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -114,7 +114,7 @@ void inline ArduinoHal::spiEnd() {
|
|||
spi->end();
|
||||
}
|
||||
|
||||
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
void inline ArduinoHal::tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration) {
|
||||
#if !defined(RADIOLIB_TONE_UNSUPPORTED)
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class ArduinoHal : public RadioLibHal {
|
|||
\param spi SPI interface to be used, can also use software SPI implementations.
|
||||
\param spiSettings SPI interface settings.
|
||||
*/
|
||||
ArduinoHal(SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
explicit ArduinoHal(SPIClass& spi, SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS);
|
||||
|
||||
// implementations of pure virtual RadioLibHal methods
|
||||
void pinMode(uint32_t pin, uint32_t mode) override;
|
||||
|
|
@ -40,11 +40,11 @@ class ArduinoHal : public RadioLibHal {
|
|||
uint32_t digitalRead(uint32_t pin) override;
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override;
|
||||
void detachInterrupt(uint32_t interruptNum) override;
|
||||
void delay(unsigned long ms) override;
|
||||
void delayMicroseconds(unsigned long us) override;
|
||||
unsigned long millis() override;
|
||||
unsigned long micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override;
|
||||
void delay(RadioLibTime_t ms) override;
|
||||
void delayMicroseconds(RadioLibTime_t us) override;
|
||||
RadioLibTime_t millis() override;
|
||||
RadioLibTime_t micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) override;
|
||||
void spiBegin() override;
|
||||
void spiBeginTransaction() override;
|
||||
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) override;
|
||||
|
|
@ -54,13 +54,13 @@ class ArduinoHal : public RadioLibHal {
|
|||
// implementations of virtual RadioLibHal methods
|
||||
void init() override;
|
||||
void term() override;
|
||||
void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0) override;
|
||||
void tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration = 0) override;
|
||||
void noTone(uint32_t pin) override;
|
||||
void yield() override;
|
||||
uint32_t pinToInterrupt(uint32_t pin) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
protected:
|
||||
#endif
|
||||
SPIClass* spi = NULL;
|
||||
SPISettings spiSettings = RADIOLIB_DEFAULT_SPI_SETTINGS;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#if !defined(_RADIOLIB_BUILD_OPTIONS_H)
|
||||
#define _RADIOLIB_BUILD_OPTIONS_H
|
||||
|
||||
#include "TypeDef.h"
|
||||
|
||||
/* RadioLib build configuration options */
|
||||
|
||||
/*
|
||||
|
|
@ -350,12 +352,12 @@
|
|||
// ... and for the grand finale, we have millis() and micros() DEFINED AS MACROS!
|
||||
#if defined(millis)
|
||||
#undef millis
|
||||
inline unsigned long millis() { return((unsigned long)(STCV / 1000)); };
|
||||
inline RadioLibTime_t millis() { return((RadioLibTime_t)(STCV / 1000)); };
|
||||
#endif
|
||||
|
||||
#if defined(micros)
|
||||
#undef micros
|
||||
inline unsigned long micros() { return((unsigned long)(STCV)); };
|
||||
inline RadioLibTime_t micros() { return((RadioLibTime_t)(STCV)); };
|
||||
#endif
|
||||
|
||||
#elif defined(TEENSYDUINO)
|
||||
|
|
@ -529,6 +531,17 @@
|
|||
#define RADIOLIB_DEBUG_SPI_HEXDUMP(...) {}
|
||||
#endif
|
||||
|
||||
// debug info strings
|
||||
#define RADIOLIB_VALUE_TO_STRING(x) #x
|
||||
#define RADIOLIB_VALUE(x) RADIOLIB_VALUE_TO_STRING(x)
|
||||
|
||||
#define RADIOLIB_INFO "\nRadioLib Info\nVersion: \"" \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_MAJOR) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_MINOR) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_PATCH) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_EXTRA) "\"\n" \
|
||||
"Platform: " RADIOLIB_VALUE(RADIOLIB_PLATFORM) "\n" \
|
||||
"Compiled: " RADIOLIB_VALUE(__DATE__) " " RADIOLIB_VALUE(__TIME__)
|
||||
|
||||
/*!
|
||||
\brief A simple assert macro, will return on error.
|
||||
|
|
@ -563,4 +576,4 @@
|
|||
|
||||
#define RADIOLIB_VERSION (((RADIOLIB_VERSION_MAJOR) << 24) | ((RADIOLIB_VERSION_MINOR) << 16) | ((RADIOLIB_VERSION_PATCH) << 8) | (RADIOLIB_VERSION_EXTRA))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ void RadioLibHal::term() {
|
|||
|
||||
}
|
||||
|
||||
void RadioLibHal::tone(uint32_t pin, unsigned int frequency, unsigned long duration) {
|
||||
void RadioLibHal::tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration) {
|
||||
(void)pin;
|
||||
(void)frequency;
|
||||
(void)duration;
|
||||
|
|
|
|||
|
|
@ -104,28 +104,28 @@ class RadioLibHal {
|
|||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param ms Number of milliseconds to wait.
|
||||
*/
|
||||
virtual void delay(unsigned long ms) = 0;
|
||||
virtual void delay(RadioLibTime_t ms) = 0;
|
||||
|
||||
/*!
|
||||
\brief Blocking microsecond wait function.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\param us Number of microseconds to wait.
|
||||
*/
|
||||
virtual void delayMicroseconds(unsigned long us) = 0;
|
||||
virtual void delayMicroseconds(RadioLibTime_t us) = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of milliseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of milliseconds since start.
|
||||
*/
|
||||
virtual unsigned long millis() = 0;
|
||||
virtual RadioLibTime_t millis() = 0;
|
||||
|
||||
/*!
|
||||
\brief Get number of microseconds since start.
|
||||
Must be implemented by the platform-specific hardware abstraction!
|
||||
\returns Number of microseconds since start.
|
||||
*/
|
||||
virtual unsigned long micros() = 0;
|
||||
virtual RadioLibTime_t micros() = 0;
|
||||
|
||||
/*!
|
||||
\brief Measure the length of incoming digital pulse in microseconds.
|
||||
|
|
@ -135,7 +135,7 @@ class RadioLibHal {
|
|||
\param timeout Timeout in microseconds.
|
||||
\returns Pulse length in microseconds, or 0 if the pulse did not start before timeout.
|
||||
*/
|
||||
virtual long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) = 0;
|
||||
virtual long pulseIn(uint32_t pin, uint32_t state, RadioLibTime_t timeout) = 0;
|
||||
|
||||
/*!
|
||||
\brief SPI initialization method.
|
||||
|
|
@ -188,7 +188,7 @@ class RadioLibHal {
|
|||
\param frequency Frequency of the square wave.
|
||||
\param duration Duration of the tone in ms. When set to 0, the tone will be infinite.
|
||||
*/
|
||||
virtual void tone(uint32_t pin, unsigned int frequency, unsigned long duration = 0);
|
||||
virtual void tone(uint32_t pin, unsigned int frequency, RadioLibTime_t duration = 0);
|
||||
|
||||
/*!
|
||||
\brief Method to stop producing a tone.
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ Module::Module(const Module& mod) {
|
|||
}
|
||||
|
||||
Module& Module::operator=(const Module& mod) {
|
||||
this->SPIreadCommand = mod.SPIreadCommand;
|
||||
this->SPIwriteCommand = mod.SPIwriteCommand;
|
||||
memcpy((void*)&mod.spiConfig, &this->spiConfig, sizeof(SPIConfig_t));
|
||||
this->csPin = mod.csPin;
|
||||
this->irqPin = mod.irqPin;
|
||||
this->rstPin = mod.rstPin;
|
||||
|
|
@ -40,14 +39,12 @@ Module& Module::operator=(const Module& mod) {
|
|||
return(*this);
|
||||
}
|
||||
|
||||
static volatile const char info[] = RADIOLIB_INFO;
|
||||
void Module::init() {
|
||||
this->hal->init();
|
||||
this->hal->pinMode(csPin, this->hal->GpioModeOutput);
|
||||
this->hal->digitalWrite(csPin, this->hal->GpioLevelHigh);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("RadioLib Debug Info");
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Version: %d.%d.%d.%d", RADIOLIB_VERSION_MAJOR, RADIOLIB_VERSION_MINOR, RADIOLIB_VERSION_PATCH, RADIOLIB_VERSION_EXTRA);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Platform: " RADIOLIB_PLATFORM);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Compiled: " __DATE__ " " __TIME__ "\n");
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN(RADIOLIB_INFO);
|
||||
}
|
||||
|
||||
void Module::term() {
|
||||
|
|
@ -55,7 +52,7 @@ void Module::term() {
|
|||
this->hal->term();
|
||||
}
|
||||
|
||||
int16_t Module::SPIgetRegValue(uint16_t reg, uint8_t msb, uint8_t lsb) {
|
||||
int16_t Module::SPIgetRegValue(uint32_t reg, uint8_t msb, uint8_t lsb) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
|
@ -65,7 +62,7 @@ int16_t Module::SPIgetRegValue(uint16_t reg, uint8_t msb, uint8_t lsb) {
|
|||
return(maskedValue);
|
||||
}
|
||||
|
||||
int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
int16_t Module::SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb, uint8_t lsb, uint8_t checkInterval, uint8_t checkMask) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return(RADIOLIB_ERR_INVALID_BIT_RANGE);
|
||||
}
|
||||
|
|
@ -78,14 +75,19 @@ int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#if RADIOLIB_SPI_PARANOID
|
||||
// check register value each millisecond until check interval is reached
|
||||
// some registers need a bit of time to process the change (e.g. SX127X_REG_OP_MODE)
|
||||
uint32_t start = this->hal->micros();
|
||||
RadioLibTime_t start = this->hal->micros();
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
uint8_t readValue = 0x00;
|
||||
#endif
|
||||
while(this->hal->micros() - start < (checkInterval * 1000)) {
|
||||
readValue = SPIreadRegister(reg);
|
||||
if((readValue & checkMask) == (newValue & checkMask)) {
|
||||
uint8_t val = SPIreadRegister(reg);
|
||||
if((val & checkMask) == (newValue & checkMask)) {
|
||||
// check passed, we can stop the loop
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
readValue = val;
|
||||
#endif
|
||||
}
|
||||
|
||||
// check failed, print debug info
|
||||
|
|
@ -104,47 +106,75 @@ int16_t Module::SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb, uint8_t
|
|||
#endif
|
||||
}
|
||||
|
||||
void Module::SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, inBytes, numBytes);
|
||||
void Module::SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes) {
|
||||
if(!this->spiConfig.stream) {
|
||||
SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, inBytes, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, inBytes, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, inBytes, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Module::SPIreadRegister(uint16_t reg) {
|
||||
uint8_t Module::SPIreadRegister(uint32_t reg) {
|
||||
uint8_t resp = 0;
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIreadCommand, reg, NULL, &resp, 1);
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ], reg, NULL, &resp, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIreadCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, false, NULL, &resp, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, false, NULL, &resp, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
return(resp);
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegisterBurst(uint16_t reg, uint8_t* data, size_t numBytes) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, data, NULL, numBytes);
|
||||
void Module::SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes) {
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, data, NULL, numBytes);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, data, NULL, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, data, NULL, numBytes, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPIwriteRegister(uint16_t reg, uint8_t data) {
|
||||
if(!SPIstreamType) {
|
||||
SPItransfer(SPIwriteCommand, reg, &data, NULL, 1);
|
||||
void Module::SPIwriteRegister(uint32_t reg, uint8_t data) {
|
||||
if(!spiConfig.stream) {
|
||||
SPItransfer(spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE], reg, &data, NULL, 1);
|
||||
} else {
|
||||
uint8_t cmd[] = { SPIwriteCommand, (uint8_t)((reg >> 8) & 0xFF), (uint8_t)(reg & 0xFF) };
|
||||
SPItransferStream(cmd, 3, true, &data, NULL, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmd[6];
|
||||
uint8_t* cmdPtr = cmd;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] >> 8*i) & 0xFF;
|
||||
}
|
||||
for(int8_t i = (int8_t)((this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8) - 1); i >= 0; i--) {
|
||||
*(cmdPtr++) = (reg >> 8*i) & 0xFF;
|
||||
}
|
||||
SPItransferStream(cmd, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8, true, &data, NULL, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
|
||||
void Module::SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes) {
|
||||
// prepare the buffers
|
||||
size_t buffLen = this->SPIaddrWidth/8 + numBytes;
|
||||
size_t buffLen = this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 + this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8 + numBytes;
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buffOut[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
|
|
@ -155,7 +185,8 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
uint8_t* buffOutPtr = buffOut;
|
||||
|
||||
// copy the command
|
||||
if(this->SPIaddrWidth <= 8) {
|
||||
// TODO properly handle variable commands and addresses
|
||||
if(this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] <= 8) {
|
||||
*(buffOutPtr++) = reg | cmd;
|
||||
} else {
|
||||
*(buffOutPtr++) = (reg >> 8) | cmd;
|
||||
|
|
@ -163,10 +194,10 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
}
|
||||
|
||||
// copy the data
|
||||
if(cmd == SPIwriteCommand) {
|
||||
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
|
||||
memcpy(buffOutPtr, dataOut, numBytes);
|
||||
} else {
|
||||
memset(buffOutPtr, this->SPInopCommand, numBytes);
|
||||
memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes);
|
||||
}
|
||||
|
||||
// do the transfer
|
||||
|
|
@ -177,19 +208,19 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
this->hal->spiEndTransaction();
|
||||
|
||||
// copy the data
|
||||
if(cmd == SPIreadCommand) {
|
||||
memcpy(dataIn, &buffIn[this->SPIaddrWidth/8], numBytes);
|
||||
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
|
||||
memcpy(dataIn, &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8], numBytes);
|
||||
}
|
||||
|
||||
// print debug information
|
||||
#if RADIOLIB_DEBUG_SPI
|
||||
uint8_t* debugBuffPtr = NULL;
|
||||
if(cmd == SPIwriteCommand) {
|
||||
if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE]) {
|
||||
RADIOLIB_DEBUG_SPI_PRINT("W\t%X\t", reg);
|
||||
debugBuffPtr = &buffOut[this->SPIaddrWidth/8];
|
||||
} else if(cmd == SPIreadCommand) {
|
||||
debugBuffPtr = &buffOut[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
|
||||
} else if(cmd == spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ]) {
|
||||
RADIOLIB_DEBUG_SPI_PRINT("R\t%X\t", reg);
|
||||
debugBuffPtr = &buffIn[this->SPIaddrWidth/8];
|
||||
debugBuffPtr = &buffIn[this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR]/8];
|
||||
}
|
||||
for(size_t n = 0; n < numBytes; n++) {
|
||||
RADIOLIB_DEBUG_SPI_PRINT_NOTAG("%X\t", debugBuffPtr[n]);
|
||||
|
|
@ -203,8 +234,13 @@ void Module::SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* d
|
|||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIreadStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIreadStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
int16_t Module::SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
uint8_t cmdBuf[2];
|
||||
uint8_t* cmdPtr = cmdBuf;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (cmd >> 8*i) & 0xFF;
|
||||
}
|
||||
return(this->SPIreadStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
|
||||
}
|
||||
|
||||
int16_t Module::SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
|
|
@ -212,16 +248,27 @@ int16_t Module::SPIreadStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_
|
|||
int16_t state = this->SPItransferStream(cmd, cmdLen, false, NULL, data, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#if !RADIOLIB_SPI_PARANOID
|
||||
(void)verify;
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
#else
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
|
||||
state = this->spiConfig.checkStatusCb(this);
|
||||
}
|
||||
|
||||
return(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIwriteStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
return(this->SPIwriteStream(&cmd, 1, data, numBytes, waitForGpio, verify));
|
||||
int16_t Module::SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
uint8_t cmdBuf[2];
|
||||
uint8_t* cmdPtr = cmdBuf;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = (cmd >> 8*i) & 0xFF;
|
||||
}
|
||||
return(this->SPIwriteStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, data, numBytes, waitForGpio, verify));
|
||||
}
|
||||
|
||||
int16_t Module::SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size_t numBytes, bool waitForGpio, bool verify) {
|
||||
|
|
@ -229,12 +276,18 @@ int16_t Module::SPIwriteStream(uint8_t* cmd, uint8_t cmdLen, uint8_t* data, size
|
|||
int16_t state = this->SPItransferStream(cmd, cmdLen, true, data, NULL, numBytes, waitForGpio, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
#if !RADIOLIB_SPI_PARANOID
|
||||
(void)verify;
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
#else
|
||||
|
||||
// check the status
|
||||
if(verify) {
|
||||
state = this->SPIcheckStream();
|
||||
if(verify && (this->spiConfig.checkStatusCb != nullptr)) {
|
||||
state = this->spiConfig.checkStatusCb(this);
|
||||
}
|
||||
|
||||
return(state);
|
||||
#endif
|
||||
}
|
||||
|
||||
int16_t Module::SPIcheckStream() {
|
||||
|
|
@ -243,31 +296,33 @@ int16_t Module::SPIcheckStream() {
|
|||
#if RADIOLIB_SPI_PARANOID
|
||||
// get the status
|
||||
uint8_t spiStatus = 0;
|
||||
uint8_t cmd = this->SPIstatusCommand;
|
||||
state = this->SPItransferStream(&cmd, 1, false, NULL, &spiStatus, 0, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
uint8_t cmdBuf[2];
|
||||
uint8_t* cmdPtr = cmdBuf;
|
||||
for(int8_t i = (int8_t)this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8 - 1; i >= 0; i--) {
|
||||
*(cmdPtr++) = ( this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] >> 8*i) & 0xFF;
|
||||
}
|
||||
state = this->SPItransferStream(cmdBuf, this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD]/8, false, NULL, &spiStatus, 1, true, RADIOLIB_MODULE_SPI_TIMEOUT);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// translate to RadioLib status code
|
||||
if(this->SPIparseStatusCb != nullptr) {
|
||||
this->SPIstreamError = this->SPIparseStatusCb(spiStatus);
|
||||
if(this->spiConfig.parseStatusCb != nullptr) {
|
||||
this->spiConfig.err = this->spiConfig.parseStatusCb(spiStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout) {
|
||||
// prepare the buffers
|
||||
int16_t Module::SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, RadioLibTime_t timeout) {
|
||||
// prepare the output buffer
|
||||
size_t buffLen = cmdLen + numBytes;
|
||||
if(!write) {
|
||||
buffLen++;
|
||||
buffLen += (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8);
|
||||
}
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buffOut[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buffOut = new uint8_t[buffLen];
|
||||
uint8_t* buffIn = new uint8_t[buffLen];
|
||||
#endif
|
||||
uint8_t* buffOutPtr = buffOut;
|
||||
|
||||
|
|
@ -280,27 +335,33 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
if(write) {
|
||||
memcpy(buffOutPtr, dataOut, numBytes);
|
||||
} else {
|
||||
memset(buffOutPtr, this->SPInopCommand, numBytes + 1);
|
||||
memset(buffOutPtr, this->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP], numBytes + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8));
|
||||
}
|
||||
|
||||
// ensure GPIO is low
|
||||
if(this->gpioPin == RADIOLIB_NC) {
|
||||
this->hal->delay(1);
|
||||
this->hal->delay(50);
|
||||
} else {
|
||||
uint32_t start = this->hal->millis();
|
||||
RadioLibTime_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("GPIO pre-transfer timeout, is it connected?");
|
||||
#if !RADIOLIB_STATIC_ONLY
|
||||
delete[] buffOut;
|
||||
delete[] buffIn;
|
||||
#endif
|
||||
return(RADIOLIB_ERR_SPI_CMD_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the input buffer
|
||||
#if RADIOLIB_STATIC_ONLY
|
||||
uint8_t buffIn[RADIOLIB_STATIC_ARRAY_SIZE];
|
||||
#else
|
||||
uint8_t* buffIn = new uint8_t[buffLen];
|
||||
#endif
|
||||
|
||||
// do the transfer
|
||||
this->hal->spiBeginTransaction();
|
||||
this->hal->digitalWrite(this->csPin, this->hal->GpioLevelLow);
|
||||
|
|
@ -314,7 +375,7 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
this->hal->delay(1);
|
||||
} else {
|
||||
this->hal->delayMicroseconds(1);
|
||||
uint32_t start = this->hal->millis();
|
||||
RadioLibTime_t start = this->hal->millis();
|
||||
while(this->hal->digitalRead(this->gpioPin)) {
|
||||
this->hal->yield();
|
||||
if(this->hal->millis() - start >= timeout) {
|
||||
|
|
@ -331,14 +392,14 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
|
||||
// parse status
|
||||
int16_t state = RADIOLIB_ERR_NONE;
|
||||
if((this->SPIparseStatusCb != nullptr) && (numBytes > 0)) {
|
||||
state = this->SPIparseStatusCb(buffIn[cmdLen]);
|
||||
if((this->spiConfig.parseStatusCb != nullptr) && (numBytes > 0)) {
|
||||
state = this->spiConfig.parseStatusCb(buffIn[this->spiConfig.statusPos]);
|
||||
}
|
||||
|
||||
// copy the data
|
||||
if(!write) {
|
||||
// skip the first byte for read-type commands (status-only)
|
||||
memcpy(dataIn, &buffIn[cmdLen + 1], numBytes);
|
||||
// skip the status bytes if present
|
||||
memcpy(dataIn, &buffIn[cmdLen + (this->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_STATUS] / 8)], numBytes);
|
||||
}
|
||||
|
||||
// print debug information
|
||||
|
|
@ -380,7 +441,7 @@ int16_t Module::SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint
|
|||
return(state);
|
||||
}
|
||||
|
||||
void Module::waitForMicroseconds(uint32_t start, uint32_t len) {
|
||||
void Module::waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len) {
|
||||
#if RADIOLIB_INTERRUPT_TIMING
|
||||
(void)start;
|
||||
if((this->TimerSetupCb != nullptr) && (len != this->prevTimingLen)) {
|
||||
|
|
@ -410,8 +471,8 @@ uint32_t Module::reflect(uint32_t in, uint8_t bits) {
|
|||
void Module::hexdump(const char* level, uint8_t* data, size_t len, uint32_t offset, uint8_t width, bool be) {
|
||||
size_t rem_len = len;
|
||||
for(size_t i = 0; i < len; i+=16) {
|
||||
char str[80];
|
||||
sprintf(str, "%07" PRIx32 " ", i+offset);
|
||||
char str[120];
|
||||
sprintf(str, "%07" PRIx32 " ", (uint32_t)i+offset);
|
||||
size_t line_len = 16;
|
||||
if(rem_len < line_len) {
|
||||
line_len = rem_len;
|
||||
|
|
@ -436,15 +497,21 @@ void Module::hexdump(const char* level, uint8_t* data, size_t len, uint32_t offs
|
|||
}
|
||||
str[56] = '|';
|
||||
str[57] = ' ';
|
||||
|
||||
// at this point we need to start escaping "%" characters
|
||||
char* strPtr = &str[58];
|
||||
for(size_t j = 0; j < line_len; j++) {
|
||||
char c = data[i+j];
|
||||
if((c < ' ') || (c > '~')) {
|
||||
c = '.';
|
||||
} else if(c == '%') {
|
||||
*strPtr++ = '%';
|
||||
}
|
||||
sprintf(&str[58 + j], "%c", c);
|
||||
sprintf(strPtr++, "%c", c);
|
||||
|
||||
}
|
||||
for(size_t j = line_len; j < 16; j++) {
|
||||
sprintf(&str[58 + j], " ");
|
||||
sprintf(strPtr++, " ");
|
||||
}
|
||||
if(level) {
|
||||
RADIOLIB_DEBUG_PRINT(level);
|
||||
|
|
@ -487,7 +554,7 @@ size_t Module::serialPrintf(const char* format, ...) {
|
|||
vsnprintf(buffer, len + 1, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
len = RADIOLIB_DEBUG_PORT.write((const uint8_t*)buffer, len);
|
||||
len = RADIOLIB_DEBUG_PORT.write(reinterpret_cast<const uint8_t*>(buffer), len);
|
||||
if (buffer != temp) {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,16 +13,53 @@
|
|||
#endif
|
||||
|
||||
/*!
|
||||
* Value to use as the last element in a mode table to indicate the
|
||||
* end of the table.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
\def END_OF_MODE_TABLE Value to use as the last element in a mode table to indicate the
|
||||
end of the table. See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
#define END_OF_MODE_TABLE { Module::MODE_END_OF_TABLE, {} }
|
||||
|
||||
// default timeout for SPI transfers
|
||||
#define RADIOLIB_MODULE_SPI_TIMEOUT (1000)
|
||||
|
||||
/*!
|
||||
\defgroup module_spi_command_pos Position of commands in Module::spiConfig command array.
|
||||
\{
|
||||
*/
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_READ Position of the read command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_READ (0)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_WRITE Position of the write command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_WRITE (1)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_NOP Position of the no-operation command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_NOP (2)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_COMMAND_STATUS Position of the status command. */
|
||||
#define RADIOLIB_MODULE_SPI_COMMAND_STATUS (3)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup module_spi_width_pos Position of bit field widths in Module::spiConfig width array.
|
||||
\{
|
||||
*/
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_ADDR Position of the address width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_ADDR (0)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_CMD Position of the command width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_CMD (1)
|
||||
|
||||
/*! \def RADIOLIB_MODULE_SPI_WIDTH_STATUS Position of the status width. */
|
||||
#define RADIOLIB_MODULE_SPI_WIDTH_STATUS (2)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class Module
|
||||
\brief Implements all common low-level methods to control the wireless module.
|
||||
|
|
@ -31,43 +68,49 @@
|
|||
class Module {
|
||||
public:
|
||||
/*!
|
||||
* \brief The maximum number of pins supported by the RF switch
|
||||
* code.
|
||||
*
|
||||
* Note: It is not recommended to use this constant in your sketch
|
||||
* when defining a rfswitch pins array, to prevent issues when this
|
||||
* value is ever increased and such an array gets extra zero
|
||||
* elements (that will be interpreted as pin 0).
|
||||
*/
|
||||
\brief The maximum number of pins supported by the RF switch code.
|
||||
Note: It is not recommended to use this constant in your sketch
|
||||
when defining a rfswitch pins array, to prevent issues when this
|
||||
value is ever increased and such an array gets extra zero
|
||||
elements (that will be interpreted as pin 0).
|
||||
*/
|
||||
static const size_t RFSWITCH_MAX_PINS = 3;
|
||||
|
||||
/*!
|
||||
* Description of RF switch pin states for a single mode.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
\struct RfSwitchMode_t
|
||||
\brief Description of RF switch pin states for a single mode.
|
||||
See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
struct RfSwitchMode_t {
|
||||
/*! \brief RF switching mode, one of \ref OpMode_t or a custom radio-defined value. */
|
||||
uint8_t mode;
|
||||
|
||||
/*! \brief Output pin values */
|
||||
uint32_t values[RFSWITCH_MAX_PINS];
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constants to use in a mode table set be setRfSwitchTable. These
|
||||
* constants work for most radios, but some radios define their own
|
||||
* constants to be used instead.
|
||||
*
|
||||
* See setRfSwitchTable() for details.
|
||||
*/
|
||||
\enum OpMode_t
|
||||
\brief Constants to use in a mode table set be setRfSwitchTable. These
|
||||
constants work for most radios, but some radios define their own
|
||||
constants to be used instead.
|
||||
|
||||
See \ref setRfSwitchTable for details.
|
||||
*/
|
||||
enum OpMode_t {
|
||||
/*! End of table marker, use \ref END_OF_MODE_TABLE constant
|
||||
* instead. Value is zero to ensure zero-initialized mode ends the
|
||||
* table */
|
||||
/*!
|
||||
\brief End of table marker, use \ref END_OF_MODE_TABLE constant instead.
|
||||
Value is zero to ensure zero-initialized mode ends the table.
|
||||
*/
|
||||
MODE_END_OF_TABLE = 0,
|
||||
/*! Idle mode */
|
||||
|
||||
/*! \brief Idle mode */
|
||||
MODE_IDLE,
|
||||
/*! Receive mode */
|
||||
|
||||
/*! \brief Receive mode */
|
||||
MODE_RX,
|
||||
/*! Transmission mode */
|
||||
|
||||
/*! \brief Transmission mode */
|
||||
MODE_TX,
|
||||
};
|
||||
|
||||
|
|
@ -111,62 +154,64 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief Overload for assignment operator.
|
||||
\param frame rvalue Module.
|
||||
\param mod rvalue Module.
|
||||
*/
|
||||
Module& operator=(const Module& mod);
|
||||
|
||||
// public member variables
|
||||
/*!
|
||||
\brief Hardware abstraction layer to be used.
|
||||
*/
|
||||
/*! \brief Hardware abstraction layer to be used. */
|
||||
RadioLibHal* hal = NULL;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI read command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPIreadCommand = 0b00000000;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI write command. Defaults to 0x80.
|
||||
*/
|
||||
uint8_t SPIwriteCommand = 0b10000000;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI no-operation command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPInopCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief Basic SPI status read command. Defaults to 0x00.
|
||||
*/
|
||||
uint8_t SPIstatusCommand = 0x00;
|
||||
|
||||
/*!
|
||||
\brief SPI address width. Defaults to 8, currently only supports 8 and 16-bit addresses.
|
||||
*/
|
||||
uint8_t SPIaddrWidth = 8;
|
||||
|
||||
/*!
|
||||
\brief Whether the SPI interface is stream-type (e.g. SX126x) or register-type (e.g. SX127x).
|
||||
Defaults to register-type SPI interfaces.
|
||||
*/
|
||||
bool SPIstreamType = false;
|
||||
|
||||
/*!
|
||||
\brief The last recorded SPI stream error.
|
||||
*/
|
||||
int16_t SPIstreamError = RADIOLIB_ERR_UNKNOWN;
|
||||
|
||||
/*!
|
||||
\brief SPI status parsing callback typedef.
|
||||
*/
|
||||
/*! \brief Callback for parsing SPI status. */
|
||||
typedef int16_t (*SPIparseStatusCb_t)(uint8_t in);
|
||||
|
||||
/*! \brief Callback for validation SPI status. */
|
||||
typedef int16_t (*SPIcheckStatusCb_t)(Module* mod);
|
||||
|
||||
enum BitWidth_t {
|
||||
BITS_0 = 0,
|
||||
BITS_8 = 8,
|
||||
BITS_16 = 16,
|
||||
BITS_32 = 32,
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Callback to function that will parse the module-specific status codes to RadioLib status codes.
|
||||
Typically used for modules with SPI stream-type interface (e.g. SX126x/SX128x).
|
||||
\struct SPIConfig_t
|
||||
\brief SPI configuration structure.
|
||||
*/
|
||||
SPIparseStatusCb_t SPIparseStatusCb = nullptr;
|
||||
struct SPIConfig_t {
|
||||
/*! \brief Whether the SPI module is stream-type (SX126x/8x) or registrer access type (SX127x, CC1101 etc). */
|
||||
bool stream;
|
||||
|
||||
/*! \brief Last recorded SPI error - only updated for modules that return status during SPI transfers. */
|
||||
int16_t err;
|
||||
|
||||
/*! \brief SPI commands */
|
||||
uint16_t cmds[4];
|
||||
|
||||
/*! \brief Bit widths of SPI addresses, commands and status bytes */
|
||||
BitWidth_t widths[3];
|
||||
|
||||
/*! \brief Byte position of status command in SPI stream */
|
||||
uint8_t statusPos;
|
||||
|
||||
/*! \brief Callback for parsing SPI status. */
|
||||
SPIparseStatusCb_t parseStatusCb;
|
||||
|
||||
/*! \brief Callback for validation SPI status. */
|
||||
SPIcheckStatusCb_t checkStatusCb;
|
||||
};
|
||||
|
||||
/*! \brief SPI configuration structure. The default configuration corresponds to register-access modules, such as SX127x. */
|
||||
SPIConfig_t spiConfig = {
|
||||
.stream = false,
|
||||
.err = RADIOLIB_ERR_UNKNOWN,
|
||||
.cmds = { 0x00, 0x80, 0x00, 0x00 },
|
||||
.widths = { Module::BITS_8, Module::BITS_0, Module::BITS_8 },
|
||||
.statusPos = 0,
|
||||
.parseStatusCb = nullptr,
|
||||
.checkStatusCb = nullptr,
|
||||
};
|
||||
|
||||
#if RADIOLIB_INTERRUPT_TIMING
|
||||
|
||||
|
|
@ -208,7 +253,7 @@ class Module {
|
|||
\param lsb Least significant bit of the register variable. Bits below this one will be masked out.
|
||||
\returns Masked register value or status code.
|
||||
*/
|
||||
int16_t SPIgetRegValue(uint16_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
int16_t SPIgetRegValue(uint32_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
|
||||
/*!
|
||||
\brief Overwrite-safe SPI write method with verification. This method is the preferred SPI write mechanism.
|
||||
|
|
@ -220,7 +265,7 @@ class Module {
|
|||
\param checkMask Mask of bits to check, only bits set to 1 will be verified.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIsetRegValue(uint16_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
int16_t SPIsetRegValue(uint32_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0, uint8_t checkInterval = 2, uint8_t checkMask = 0xFF);
|
||||
|
||||
/*!
|
||||
\brief SPI burst read method.
|
||||
|
|
@ -228,14 +273,14 @@ class Module {
|
|||
\param numBytes Number of bytes that will be read.
|
||||
\param inBytes Pointer to array that will hold the read data.
|
||||
*/
|
||||
void SPIreadRegisterBurst(uint16_t reg, size_t numBytes, uint8_t* inBytes);
|
||||
void SPIreadRegisterBurst(uint32_t reg, size_t numBytes, uint8_t* inBytes);
|
||||
|
||||
/*!
|
||||
\brief SPI basic read method. Use of this method is reserved for special cases, SPIgetRegValue should be used instead.
|
||||
\param reg Address of SPI register to read.
|
||||
\returns Value that was read from register.
|
||||
*/
|
||||
uint8_t SPIreadRegister(uint16_t reg);
|
||||
uint8_t SPIreadRegister(uint32_t reg);
|
||||
|
||||
/*!
|
||||
\brief SPI burst write method.
|
||||
|
|
@ -243,14 +288,14 @@ class Module {
|
|||
\param data Pointer to array that holds the data that will be written.
|
||||
\param numBytes Number of bytes that will be written.
|
||||
*/
|
||||
void SPIwriteRegisterBurst(uint16_t reg, uint8_t* data, size_t numBytes);
|
||||
void SPIwriteRegisterBurst(uint32_t reg, uint8_t* data, size_t numBytes);
|
||||
|
||||
/*!
|
||||
\brief SPI basic write method. Use of this method is reserved for special cases, SPIsetRegValue should be used instead.
|
||||
\param reg Address of SPI register to write.
|
||||
\param data Value that will be written to the register.
|
||||
*/
|
||||
void SPIwriteRegister(uint16_t reg, uint8_t data);
|
||||
void SPIwriteRegister(uint32_t reg, uint8_t data);
|
||||
|
||||
/*!
|
||||
\brief SPI single transfer method.
|
||||
|
|
@ -260,7 +305,7 @@ class Module {
|
|||
\param dataIn Data that was transferred from slave to master.
|
||||
\param numBytes Number of bytes to transfer.
|
||||
*/
|
||||
void SPItransfer(uint8_t cmd, uint16_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
|
||||
void SPItransfer(uint16_t cmd, uint32_t reg, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes);
|
||||
|
||||
/*!
|
||||
\brief Method to check the result of last SPI stream transfer.
|
||||
|
|
@ -277,7 +322,7 @@ class Module {
|
|||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIreadStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
int16_t SPIreadStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a read transaction with SPI stream.
|
||||
|
|
@ -300,7 +345,7 @@ class Module {
|
|||
\param verify Whether to verify the result of the transaction after it is finished.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPIwriteStream(uint8_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
int16_t SPIwriteStream(uint16_t cmd, uint8_t* data, size_t numBytes, bool waitForGpio = true, bool verify = true);
|
||||
|
||||
/*!
|
||||
\brief Method to perform a write transaction with SPI stream.
|
||||
|
|
@ -326,7 +371,7 @@ class Module {
|
|||
\param timeout GPIO wait period timeout in milliseconds.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t SPItransferStream(uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, uint32_t timeout);
|
||||
int16_t SPItransferStream(const uint8_t* cmd, uint8_t cmdLen, bool write, uint8_t* dataOut, uint8_t* dataIn, size_t numBytes, bool waitForGpio, RadioLibTime_t timeout);
|
||||
|
||||
// pin number access methods
|
||||
|
||||
|
|
@ -438,7 +483,7 @@ class Module {
|
|||
|
||||
/*!
|
||||
\brief Find a mode in the RfSwitchTable.
|
||||
\param The mode to find.
|
||||
\param mode The mode to find.
|
||||
\returns A pointer to the RfSwitchMode_t struct in the table that
|
||||
matches the passed mode. Returns nullptr if no rfswitch pins are
|
||||
configured, or the passed mode is not listed in the table.
|
||||
|
|
@ -458,7 +503,7 @@ class Module {
|
|||
\param start Waiting start timestamp, in microseconds.
|
||||
\param len Waiting duration, in microseconds;
|
||||
*/
|
||||
void waitForMicroseconds(uint32_t start, uint32_t len);
|
||||
void waitForMicroseconds(RadioLibTime_t start, RadioLibTime_t len);
|
||||
|
||||
/*!
|
||||
\brief Function to reflect bits within a byte.
|
||||
|
|
|
|||
|
|
@ -53,16 +53,7 @@
|
|||
|
||||
// print debug info
|
||||
#if RADIOLIB_DEBUG
|
||||
#define RADIOLIB_VALUE_TO_STRING(x) #x
|
||||
#define RADIOLIB_VALUE(x) RADIOLIB_VALUE_TO_STRING(x)
|
||||
#pragma message("\nRadioLib Debug Info\nVersion: \"" \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_MAJOR) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_MINOR) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_PATCH) "." \
|
||||
RADIOLIB_VALUE(RADIOLIB_VERSION_EXTRA) "\"\n" \
|
||||
"Platform: " RADIOLIB_VALUE(RADIOLIB_PLATFORM) "\n" \
|
||||
"Compiled: " RADIOLIB_VALUE(__DATE__) " " RADIOLIB_VALUE(__TIME__) \
|
||||
)
|
||||
#pragma message(RADIOLIB_INFO)
|
||||
#endif
|
||||
|
||||
// check unknown/unsupported platform
|
||||
|
|
@ -77,6 +68,9 @@
|
|||
|
||||
#include "modules/CC1101/CC1101.h"
|
||||
#include "modules/LLCC68/LLCC68.h"
|
||||
#include "modules/LR11x0/LR1110.h"
|
||||
#include "modules/LR11x0/LR1120.h"
|
||||
#include "modules/LR11x0/LR1121.h"
|
||||
#include "modules/nRF24/nRF24.h"
|
||||
#include "modules/RF69/RF69.h"
|
||||
#include "modules/RFM2x/RFM22.h"
|
||||
|
|
|
|||
|
|
@ -563,6 +563,28 @@
|
|||
*/
|
||||
#define RADIOLIB_LORAWAN_NO_DOWNLINK (-1116)
|
||||
|
||||
// LR11x0-specific status codes
|
||||
|
||||
/*!
|
||||
\brief The selected 802.11 WiFi type is invalid.
|
||||
*/
|
||||
#define RADIOLIB_ERR_INVALID_WIFI_TYPE (-1200)
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\defgroup typedefs Type aliases used by RadioLib.
|
||||
|
||||
\{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Type used for durations in RadioLib
|
||||
*/
|
||||
typedef unsigned long RadioLibTime_t;
|
||||
|
||||
/*!
|
||||
\}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ CC1101::CC1101(Module* module) : PhysicalLayer(RADIOLIB_CC1101_FREQUENCY_STEP_SI
|
|||
|
||||
int16_t CC1101::begin(float freq, float br, float freqDev, float rxBw, int8_t pwr, uint8_t preambleLength) {
|
||||
// set module properties
|
||||
this->mod->SPIreadCommand = RADIOLIB_CC1101_CMD_READ;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_CC1101_CMD_WRITE;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_CC1101_CMD_READ;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_CC1101_CMD_WRITE;
|
||||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
|
||||
|
|
@ -100,29 +100,29 @@ void CC1101::reset() {
|
|||
|
||||
int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// calculate timeout (5ms + 500 % of expected time-on-air)
|
||||
uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (this->bitRate * 1000.0)) * 5000000.0);
|
||||
RadioLibTime_t timeout = 5 + (RadioLibTime_t)((((float)(len * 8)) / this->bitRate) * 5);
|
||||
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission start or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// wait for transmission end or timeout
|
||||
start = this->mod->hal->micros();
|
||||
start = this->mod->hal->millis();
|
||||
while(this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -133,18 +133,18 @@ int16_t CC1101::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
int16_t CC1101::receive(uint8_t* data, size_t len) {
|
||||
// calculate timeout (500 ms + 400 full max-length packets at current bit rate)
|
||||
uint32_t timeout = 500000 + (1.0/(this->bitRate*1000.0))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
RadioLibTime_t timeout = 500 + (1.0/(this->bitRate))*(RADIOLIB_CC1101_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet start or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
|
@ -152,11 +152,11 @@ int16_t CC1101::receive(uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
// wait for packet end or timeout
|
||||
start = this->mod->hal->micros();
|
||||
start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
standby();
|
||||
SPIsendCommand(RADIOLIB_CC1101_CMD_FLUSH_RX);
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
|
@ -172,7 +172,7 @@ int16_t CC1101::standby() {
|
|||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||
|
||||
// wait until idle is reached
|
||||
uint32_t start = this->mod->hal->millis();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(SPIgetRegValue(RADIOLIB_CC1101_REG_MARCSTATE, 4, 0) != RADIOLIB_CC1101_MARC_STATE_IDLE) {
|
||||
mod->hal->yield();
|
||||
if(this->mod->hal->millis() - start > 100) {
|
||||
|
|
@ -361,7 +361,7 @@ int16_t CC1101::startReceive() {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t CC1101::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t CC1101::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)timeout;
|
||||
(void)irqFlags;
|
||||
(void)irqMask;
|
||||
|
|
@ -489,6 +489,24 @@ int16_t CC1101::setRxBandwidth(float rxBw) {
|
|||
return(RADIOLIB_ERR_INVALID_RX_BANDWIDTH);
|
||||
}
|
||||
|
||||
int16_t CC1101::autoSetRxBandwidth() {
|
||||
// Uncertainty ~ +/- 40ppm for a cheap CC1101
|
||||
// Uncertainty * 2 for both transmitter and receiver
|
||||
float uncertainty = ((this->frequency) * 40 * 2);
|
||||
uncertainty = (uncertainty/1000); //Since bitrate is in kBit
|
||||
float minbw = ((this->bitRate) + uncertainty);
|
||||
|
||||
int possibles[16] = {58, 68, 81, 102, 116, 135, 162, 203, 232, 270, 325, 406, 464, 541, 650, 812};
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (possibles[i] > minbw) {
|
||||
int16_t state = setRxBandwidth(possibles[i]);
|
||||
return(state);
|
||||
}
|
||||
}
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
int16_t CC1101::setFrequencyDeviation(float freqDev) {
|
||||
// set frequency deviation to lowest available setting (required for digimodes)
|
||||
float newFreqDev = freqDev;
|
||||
|
|
@ -542,6 +560,62 @@ int16_t CC1101::getFrequencyDeviation(float *freqDev) {
|
|||
}
|
||||
|
||||
int16_t CC1101::setOutputPower(int8_t pwr) {
|
||||
// check if power value is configurable
|
||||
uint8_t powerRaw = 0;
|
||||
int16_t state = checkOutputPower(pwr, NULL, &powerRaw);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// store the value
|
||||
this->power = pwr;
|
||||
|
||||
if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
|
||||
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)
|
||||
|
||||
uint8_t paValues[2] = {0x00, powerRaw};
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
} else {
|
||||
// Freq modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting.
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
}
|
||||
|
||||
int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, NULL));
|
||||
}
|
||||
|
||||
int16_t CC1101::checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw) {
|
||||
constexpr int8_t allowedPwrs[8] = { -30, -20, -15, -10, 0, 5, 7, 10 };
|
||||
|
||||
if(clipped) {
|
||||
if(power <= -30) {
|
||||
*clipped = -30;
|
||||
} else if(power >= 10) {
|
||||
*clipped = 10;
|
||||
} else {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(allowedPwrs[i] > power) {
|
||||
break;
|
||||
}
|
||||
*clipped = allowedPwrs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if just a check occurs (and not requesting the raw power value), return now
|
||||
if(!raw) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(allowedPwrs[i] == power) {
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
}
|
||||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// round to the known frequency settings
|
||||
uint8_t f;
|
||||
if(this->frequency < 374.0) {
|
||||
|
|
@ -568,53 +642,35 @@ int16_t CC1101::setOutputPower(int8_t pwr) {
|
|||
{0xCB, 0xC8, 0xCB, 0xC7},
|
||||
{0xC2, 0xC0, 0xC2, 0xC0}};
|
||||
|
||||
uint8_t powerRaw;
|
||||
switch(pwr) {
|
||||
case -30:
|
||||
powerRaw = paTable[0][f];
|
||||
switch(power) {
|
||||
case allowedPwrs[0]: // -30
|
||||
*raw = paTable[0][f];
|
||||
break;
|
||||
case -20:
|
||||
powerRaw = paTable[1][f];
|
||||
case allowedPwrs[1]: // -20
|
||||
*raw = paTable[1][f];
|
||||
break;
|
||||
case -15:
|
||||
powerRaw = paTable[2][f];
|
||||
case allowedPwrs[2]: // -15
|
||||
*raw = paTable[2][f];
|
||||
break;
|
||||
case -10:
|
||||
powerRaw = paTable[3][f];
|
||||
case allowedPwrs[3]: // -10
|
||||
*raw = paTable[3][f];
|
||||
break;
|
||||
case 0:
|
||||
powerRaw = paTable[4][f];
|
||||
case allowedPwrs[4]: // 0
|
||||
*raw = paTable[4][f];
|
||||
break;
|
||||
case 5:
|
||||
powerRaw = paTable[5][f];
|
||||
case allowedPwrs[5]: // 5
|
||||
*raw = paTable[5][f];
|
||||
break;
|
||||
case 7:
|
||||
powerRaw = paTable[6][f];
|
||||
case allowedPwrs[6]: // 7
|
||||
*raw = paTable[6][f];
|
||||
break;
|
||||
case 10:
|
||||
powerRaw = paTable[7][f];
|
||||
case allowedPwrs[7]: // 10
|
||||
*raw = paTable[7][f];
|
||||
break;
|
||||
default:
|
||||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
|
||||
// store the value
|
||||
this->power = pwr;
|
||||
|
||||
if(this->modulation == RADIOLIB_CC1101_MOD_FORMAT_ASK_OOK){
|
||||
// Amplitude modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting a 0 (no power)
|
||||
// PA_TABLE[1] is the power to be used when transmitting a 1 (full power)
|
||||
|
||||
uint8_t paValues[2] = {0x00, powerRaw};
|
||||
SPIwriteRegisterBurst(RADIOLIB_CC1101_REG_PATABLE, paValues, 2);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
||||
} else {
|
||||
// Freq modulation:
|
||||
// PA_TABLE[0] is the power to be used when transmitting.
|
||||
return(SPIsetRegValue(RADIOLIB_CC1101_REG_PATABLE, powerRaw));
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t CC1101::setSyncWord(uint8_t* syncWord, uint8_t len, uint8_t maxErrBits, bool requireCarrierSense) {
|
||||
|
|
@ -740,7 +796,7 @@ int16_t CC1101::setOOK(bool enableOOK) {
|
|||
float CC1101::getRSSI() {
|
||||
float rssi;
|
||||
|
||||
if (this->directModeEnabled) {
|
||||
if(!this->directModeEnabled) {
|
||||
if(this->rawRSSI >= 128) {
|
||||
rssi = (((float)this->rawRSSI - 256.0)/2.0) - 74.0;
|
||||
} else {
|
||||
|
|
@ -748,12 +804,9 @@ float CC1101::getRSSI() {
|
|||
}
|
||||
} else {
|
||||
uint8_t rawRssi = SPIreadRegister(RADIOLIB_CC1101_REG_RSSI);
|
||||
if (rawRssi >= 128)
|
||||
{
|
||||
if(rawRssi >= 128) {
|
||||
rssi = ((rawRssi - 256) / 2) - 74;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rssi = (rawRssi / 2) - 74;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -537,8 +537,9 @@ class CC1101: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
\param module Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
CC1101(Module* module);
|
||||
|
||||
// basic methods
|
||||
|
|
@ -660,23 +661,23 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
|
|
@ -698,7 +699,7 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Interrupt-driven receive method. GDO0 will be activated when full packet is received.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method, implemented for compatibility with PhysicalLayer.
|
||||
|
|
@ -708,7 +709,7 @@ class CC1101: public PhysicalLayer {
|
|||
\param len Ignored.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len);
|
||||
int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method. When the packet length is not known in advance,
|
||||
|
|
@ -728,14 +729,14 @@ class CC1101: public PhysicalLayer {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets bit rate. Allowed values range from 0.025 to 600.0 kbps.
|
||||
\param br Bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
/*!
|
||||
\brief Sets receiver bandwidth. Allowed values are 58, 68, 81, 102, 116, 135, 162,
|
||||
|
|
@ -745,6 +746,14 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setRxBandwidth(float rxBw);
|
||||
|
||||
/*!
|
||||
\brief calculates and sets Rx bandwidth based on the freq, baud and freq uncertainty.
|
||||
Reimplement of atlas0fd00m's (RfCat) CalculatePktChanBw function.
|
||||
Modified for worse ppm with the CC1101, and adjusted for the supportted CC1101 bw.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t autoSetRxBandwidth();
|
||||
|
||||
/*!
|
||||
\brief Sets frequency deviation. Allowed values range from 1.587 to 380.8 kHz.
|
||||
\param freqDev Frequency deviation to be set in kHz.
|
||||
|
|
@ -764,7 +773,25 @@ class CC1101: public PhysicalLayer {
|
|||
\param pwr Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t pwr);
|
||||
int16_t setOutputPower(int8_t pwr) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param raw Raw internal value.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, uint8_t* raw);
|
||||
|
||||
/*!
|
||||
\brief Sets 16-bit sync word as a two byte value.
|
||||
|
|
@ -789,6 +816,7 @@ class CC1101: public PhysicalLayer {
|
|||
/*!
|
||||
\brief Sets preamble length.
|
||||
\param preambleLength Preamble length to be set (in bits), allowed values: 16, 24, 32, 48, 64, 96, 128 and 192.
|
||||
\param qualityThreshold Preamble quality threshold (PQT) to set.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPreambleLength(uint8_t preambleLength, uint8_t qualityThreshold);
|
||||
|
|
@ -820,58 +848,58 @@ class CC1101: public PhysicalLayer {
|
|||
In asynchronous direct mode, returns the current RSSI level.
|
||||
\returns RSSI in dBm.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Gets LQI (Link Quality Indicator) of the last received packet.
|
||||
\returns Last packet LQI (lower is better).
|
||||
*/
|
||||
uint8_t getLQI() const;
|
||||
uint8_t getLQI() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Query modem for the packet length of received payload.
|
||||
\param update Update received packet length. Will return cached value when set to false.
|
||||
\returns Length of last received packet in bytes.
|
||||
*/
|
||||
size_t getPacketLength(bool update = true) override;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in fixed packet length mode.
|
||||
\param len Packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t fixedPacketLengthMode(uint8_t len = RADIOLIB_CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode.
|
||||
\param len Maximum packet length.
|
||||
\param maxLen Maximum packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_CC1101_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Enable sync word filtering and generation.
|
||||
\param numBits Sync word length in bits.
|
||||
\param maxErrBits Maximum number of allowed error bits in sync word.
|
||||
\param requireCarrierSense Require carrier sense above threshold in addition to sync word.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Disable preamble and sync word filtering and generation.
|
||||
\param requireCarrierSense Require carrier sense above threshold.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t disableSyncWordFiltering(bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
\param enable Set or unset CRC generation and filtering.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setCrcFiltering(bool enable = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Set modem in "sniff" mode: no packet filtering (e.g., no preamble, sync word, address, CRC).
|
||||
\param enable Set or unset promiscuous mode.
|
||||
\param requireCarrierSense Set carriersense required above threshold, defaults to false.
|
||||
|
|
@ -879,7 +907,7 @@ class CC1101: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setPromiscuousMode(bool enable = true, bool requireCarrierSense = false);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
\brief Get whether the modem is in promiscuous mode: no packet filtering
|
||||
(e.g., no preamble, sync word, address, CRC).
|
||||
\returns Whether the modem is in promiscuous mode.
|
||||
|
|
@ -909,16 +937,16 @@ class CC1101: public PhysicalLayer {
|
|||
void setRfSwitchTable(const uint32_t (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||
|
||||
/*!
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return CC1101_VERSION_LEGACY (0x04) or
|
||||
CC1101_VERSION_CURRENT (0x14) if CC1101 is connected and working.
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
\brief Read version SPI register. Should return CC1101_VERSION_LEGACY (0x04) or
|
||||
CC1101_VERSION_CURRENT (0x14) if CC1101 is connected and working.
|
||||
\returns Version register contents or \ref status_codes
|
||||
*/
|
||||
int16_t getChipVersion();
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
|
||||
|
|
@ -926,13 +954,13 @@ class CC1101: public PhysicalLayer {
|
|||
\brief Set interrupt service routine function to call when data bit is receveid in direct mode.
|
||||
\param func Pointer to interrupt service routine.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Function to read and process data bit in direct reception mode.
|
||||
\param pin Pin on which to read.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
|
@ -941,12 +969,12 @@ class CC1101: public PhysicalLayer {
|
|||
\param value The value that indicates which function to place on that pin. See chip datasheet for details.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value);
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
// SPI read overrides to set bit for burst write and status registers access
|
||||
int16_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class LLCC68: public SX1262 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LLCC68(Module* mod);
|
||||
LLCC68(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
|
|
|
|||
55
lib/RadioLib/src/modules/LR11x0/LR1110.cpp
Normal file
55
lib/RadioLib/src/modules/LR11x0/LR1110.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#include "LR1110.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1110::LR1110(Module* mod) : LR11x0(mod) {
|
||||
chipType = RADIOLIB_LR11X0_HW_LR1110;
|
||||
}
|
||||
|
||||
int16_t LR1110::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1110::setFrequency(float freq) {
|
||||
return(this->setFrequency(freq, true));
|
||||
}
|
||||
|
||||
int16_t LR1110::setFrequency(float freq, bool calibrate, float band) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = LR11x0::calibImage(freq - band, freq + band);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)));
|
||||
}
|
||||
|
||||
#endif
|
||||
98
lib/RadioLib/src/modules/LR11x0/LR1110.h
Normal file
98
lib/RadioLib/src/modules/LR11x0/LR1110.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#if !defined(_RADIOLIB_LR1110_H)
|
||||
#define _RADIOLIB_LR1110_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
|
||||
/*!
|
||||
\class LR1110
|
||||
\brief Derived class for %LR1110 modules.
|
||||
*/
|
||||
class LR1110: public LR11x0 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1110(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
\param sf LoRa spreading factor. Defaults to 9.
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
\param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE (0x12).
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param br FSK bit rate in kbps. Defaults to 4.8 kbps.
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz. Defaults to 5.0 kHz.
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 156.2 kHz.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength FSK preamble length in bits. Defaults to 16 bits.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginGFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LR-FHSS modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
|
||||
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_LR11X0_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_LR11X0_LR_FHSS_CR_2_3, int8_t power = 10, float tcxoVoltage = 1.6);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
59
lib/RadioLib/src/modules/LR11x0/LR1120.cpp
Normal file
59
lib/RadioLib/src/modules/LR11x0/LR1120.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#include "LR1120.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1120::LR1120(Module* mod) : LR11x0(mod) {
|
||||
chipType = RADIOLIB_LR11X0_HW_LR1120;
|
||||
}
|
||||
|
||||
int16_t LR1120::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::begin(bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginGFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginGFSK(br, freqDev, rxBw, power, preambleLength, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::beginLRFHSS(float freq, uint8_t bw, uint8_t cr, int8_t power, float tcxoVoltage) {
|
||||
// execute common part
|
||||
int16_t state = LR11x0::beginLRFHSS(bw, cr, power, tcxoVoltage);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// configure publicly accessible settings
|
||||
state = setFrequency(freq);
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t LR1120::setFrequency(float freq) {
|
||||
return(this->setFrequency(freq, true));
|
||||
}
|
||||
|
||||
int16_t LR1120::setFrequency(float freq, bool calibrate, float band) {
|
||||
if(!(((freq >= 150.0) && (freq <= 960.0)) ||
|
||||
((freq >= 1900.0) && (freq <= 2200.0)) ||
|
||||
((freq >= 2400.0) && (freq <= 2500.0)))) {
|
||||
return(RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
}
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = LR11x0::calibImage(freq - band, freq + band);
|
||||
RADIOLIB_ASSERT(state);
|
||||
}
|
||||
|
||||
// set frequency
|
||||
return(LR11x0::setRfFrequency((uint32_t)(freq*1000000.0f)));
|
||||
}
|
||||
|
||||
#endif
|
||||
99
lib/RadioLib/src/modules/LR11x0/LR1120.h
Normal file
99
lib/RadioLib/src/modules/LR11x0/LR1120.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
#if !defined(_RADIOLIB_LR1120_H)
|
||||
#define _RADIOLIB_LR1120_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
|
||||
/*!
|
||||
\class LR1120
|
||||
\brief Derived class for %LR1120 modules.
|
||||
*/
|
||||
class LR1120: public LR11x0 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1120(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LoRa modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LoRa bandwidth in kHz. Defaults to 125.0 kHz.
|
||||
\param sf LoRa spreading factor. Defaults to 9.
|
||||
\param cr LoRa coding rate denominator. Defaults to 7 (coding rate 4/7).
|
||||
\param syncWord 1-byte LoRa sync word. Defaults to RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE (0x12).
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength LoRa preamble length in symbols. Defaults to 8 symbols.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param br FSK bit rate in kbps. Defaults to 4.8 kbps.
|
||||
\param freqDev Frequency deviation from carrier frequency in kHz. Defaults to 5.0 kHz.
|
||||
\param rxBw Receiver bandwidth in kHz. Defaults to 156.2 kHz.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param preambleLength FSK preamble length in bits. Defaults to 16 bits.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginGFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6);
|
||||
|
||||
/*!
|
||||
\brief Initialization method for LR-FHSS modem.
|
||||
\param freq Carrier frequency in MHz. Defaults to 434.0 MHz.
|
||||
\param bw LR-FHSS bandwidth, one of RADIOLIB_LR11X0_LR_FHSS_BW_* values. Defaults to 722.66 kHz.
|
||||
\param cr LR-FHSS coding rate, one of RADIOLIB_LR11X0_LR_FHSS_CR_* values. Defaults to 2/3 coding rate.
|
||||
\param power Output power in dBm. Defaults to 10 dBm.
|
||||
\param tcxoVoltage TCXO reference voltage to be set. Defaults to 1.6 V.
|
||||
If you are seeing -706/-707 error codes, it likely means you are using non-0 value for module with XTAL.
|
||||
To use XTAL, either set this value to 0, or set LR11x0::XTAL to true.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t beginLRFHSS(float freq = 434.0, uint8_t bw = RADIOLIB_LR11X0_LR_FHSS_BW_722_66, uint8_t cr = RADIOLIB_LR11X0_LR_FHSS_CR_2_3, int8_t power = 10, float tcxoVoltage = 1.6);
|
||||
|
||||
// configuration methods
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz,
|
||||
1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz,
|
||||
1900 - 2200 MHz and 2400 - 2500 MHz. Will also perform calibrations.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
8
lib/RadioLib/src/modules/LR11x0/LR1121.cpp
Normal file
8
lib/RadioLib/src/modules/LR11x0/LR1121.cpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include "LR1121.h"
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
LR1121::LR1121(Module* mod) : LR1120(mod) {
|
||||
chipType = RADIOLIB_LR11X0_HW_LR1121;
|
||||
}
|
||||
|
||||
#endif
|
||||
35
lib/RadioLib/src/modules/LR11x0/LR1121.h
Normal file
35
lib/RadioLib/src/modules/LR11x0/LR1121.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#if !defined(_RADIOLIB_LR1121_H)
|
||||
#define _RADIOLIB_LR1121_H
|
||||
|
||||
#include "../../TypeDef.h"
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_LR11X0
|
||||
|
||||
#include "../../Module.h"
|
||||
#include "LR11x0.h"
|
||||
#include "LR1120.h"
|
||||
|
||||
/*!
|
||||
\class LR1121
|
||||
\brief Derived class for %LR1121 modules.
|
||||
*/
|
||||
class LR1121: public LR1120 {
|
||||
public:
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
LR1121(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// TODO this is where overrides to disable GNSS+WiFi scanning methods on LR1121
|
||||
// will be put once those are implemented
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
3112
lib/RadioLib/src/modules/LR11x0/LR11x0.cpp
Normal file
3112
lib/RadioLib/src/modules/LR11x0/LR11x0.cpp
Normal file
File diff suppressed because it is too large
Load diff
1458
lib/RadioLib/src/modules/LR11x0/LR11x0.h
Normal file
1458
lib/RadioLib/src/modules/LR11x0/LR11x0.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -100,18 +100,18 @@ void RF69::reset() {
|
|||
|
||||
int16_t RF69::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||
// calculate timeout (5ms + 500 % of expected time-on-air)
|
||||
uint32_t timeout = 5000000 + (uint32_t)((((float)(len * 8)) / (this->bitRate * 1000.0)) * 5000000.0);
|
||||
RadioLibTime_t timeout = 5 + (RadioLibTime_t)((((float)(len * 8)) / this->bitRate) * 5);
|
||||
|
||||
// start transmission
|
||||
int16_t state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for transmission end or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -122,18 +122,18 @@ int16_t RF69::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
|
||||
int16_t RF69::receive(uint8_t* data, size_t len) {
|
||||
// calculate timeout (500 ms + 400 full 64-byte packets at current bit rate)
|
||||
uint32_t timeout = 500000 + (1.0/(this->bitRate*1000.0))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0);
|
||||
RadioLibTime_t timeout = 500 + (1.0/(this->bitRate))*(RADIOLIB_RF69_MAX_PACKET_LENGTH*400.0);
|
||||
|
||||
// start reception
|
||||
int16_t state = startReceive();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
standby();
|
||||
clearIRQFlags();
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
|
|
@ -259,7 +259,7 @@ int16_t RF69::startReceive() {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t RF69::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t RF69::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)timeout;
|
||||
(void)irqFlags;
|
||||
(void)irqMask;
|
||||
|
|
@ -566,9 +566,9 @@ int16_t RF69::setBitRate(float br) {
|
|||
setMode(RADIOLIB_RF69_STANDBY);
|
||||
|
||||
// set bit rate
|
||||
uint16_t bitRate = 32000 / br;
|
||||
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0);
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0);
|
||||
uint16_t bitRateRaw = 32000 / br;
|
||||
int16_t state = this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_BITRATE_MSB, (bitRateRaw & 0xFF00) >> 8, 7, 0);
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_RF69_REG_BITRATE_LSB, bitRateRaw & 0x00FF, 7, 0);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
this->bitRate = br;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,9 +486,9 @@ class RF69: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
\param module Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
RF69(Module* module);
|
||||
RF69(Module* module); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -538,7 +538,7 @@ class RF69: public PhysicalLayer {
|
|||
\brief Sets the module to sleep mode.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t sleep();
|
||||
int16_t sleep() override;
|
||||
|
||||
/*!
|
||||
\brief Sets the module to standby mode.
|
||||
|
|
@ -575,7 +575,7 @@ class RF69: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Sets AES key.
|
||||
\param Key to be used for AES encryption. Must be exactly 16 bytes long.
|
||||
\param key Key to be used for AES encryption. Must be exactly 16 bytes long.
|
||||
*/
|
||||
void setAESKey(uint8_t* key);
|
||||
|
||||
|
|
@ -619,23 +619,23 @@ class RF69: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Set interrupt service routine function to call when FIFO is empty.
|
||||
|
|
@ -697,7 +697,7 @@ class RF69: public PhysicalLayer {
|
|||
\brief Interrupt-driven receive method. GDO0 will be activated when full packet is received.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method, implemented for compatibility with PhysicalLayer.
|
||||
|
|
@ -707,7 +707,7 @@ class RF69: public PhysicalLayer {
|
|||
\param len Ignored.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len);
|
||||
int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Reads data received after calling startReceive method. When the packet length is not known in advance,
|
||||
|
|
@ -727,7 +727,7 @@ class RF69: public PhysicalLayer {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Gets carrier frequency.
|
||||
|
|
@ -741,7 +741,7 @@ class RF69: public PhysicalLayer {
|
|||
\param br Bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
/*!
|
||||
\brief Sets receiver bandwidth. Allowed values are 2.6, 3.1, 3.9, 5.2, 6.3, 7.8, 10.4, 12.5, 15.6,
|
||||
|
|
@ -872,14 +872,14 @@ class RF69: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode.
|
||||
\param len Maximum packet length.
|
||||
\param maxLen Maximum packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_RF69_MAX_PACKET_LENGTH);
|
||||
|
||||
/*!
|
||||
\brief Enable sync word filtering and generation.
|
||||
\param numBits Sync word length in bits.
|
||||
\param maxErrBits Maximum allowed number of error bits in sync word.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t enableSyncWordFiltering(uint8_t maxErrBits = 0);
|
||||
|
|
@ -944,7 +944,7 @@ class RF69: public PhysicalLayer {
|
|||
\brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet.
|
||||
\returns Last packet RSSI in dBm.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Sets the RSSI value above which the RSSI interrupt is signaled
|
||||
|
|
@ -963,7 +963,7 @@ class RF69: public PhysicalLayer {
|
|||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return RF69_CHIP_VERSION (0x24) if SX127x is connected and working.
|
||||
|
|
@ -976,13 +976,13 @@ class RF69: public PhysicalLayer {
|
|||
\brief Set interrupt service routine function to call when data bit is received in direct mode.
|
||||
\param func Pointer to interrupt service routine.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Function to read and process data bit in direct reception mode.
|
||||
\param pin Pin on which to read.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
|
@ -991,12 +991,12 @@ class RF69: public PhysicalLayer {
|
|||
\param value The value that indicates which function to place on that pin. See chip datasheet for details.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value);
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class SX1231: public RF69 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1231(Module* mod);
|
||||
SX1231(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Initialization method.
|
||||
|
|
@ -111,7 +111,7 @@ class SX1231: public RF69 {
|
|||
int16_t begin(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 125.0, int8_t power = 10, uint8_t preambleLen = 16);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
protected:
|
||||
#endif
|
||||
uint8_t chipRevision = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class SX1233: public SX1231 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1233(Module* mod);
|
||||
SX1233(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Initialization method.
|
||||
|
|
@ -48,12 +48,12 @@ class SX1233: public SX1231 {
|
|||
\param br Bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
#endif
|
||||
uint8_t chipRevision = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ int16_t STM32WLx::setOutputPower(int8_t power) {
|
|||
return(RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// Apply workaround for HP only
|
||||
state = SX126x::fixPaClamping(use_hp);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class STM32WLx : public SX1262 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of STM32WLx_Module that will be used to communicate with the radio.
|
||||
*/
|
||||
STM32WLx(STM32WLx_Module* mod);
|
||||
STM32WLx(STM32WLx_Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Custom operation modes for STMWLx.
|
||||
|
|
@ -124,34 +124,34 @@ class STM32WLx : public SX1262 {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a channel scan is finished.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setChannelScanAction(void (*func)(void));
|
||||
void setChannelScanAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a channel scan is finished.
|
||||
*/
|
||||
void clearChannelScanAction();
|
||||
void clearChannelScanAction() override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -22,10 +22,19 @@ enum {
|
|||
RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET,
|
||||
};
|
||||
|
||||
/*!
|
||||
\class Stm32wlxHal
|
||||
\brief Hardware Abstraction Layer for STM32WL.
|
||||
*/
|
||||
class Stm32wlxHal : public ArduinoHal {
|
||||
public:
|
||||
Stm32wlxHal(): ArduinoHal(SubGhz.SPI, SubGhz.spi_settings) {}
|
||||
|
||||
/*!
|
||||
\brief Pin mode override to handle STM32WL virtual pins.
|
||||
\param dwPin Pin to set.
|
||||
\param dwMode Mode to set.
|
||||
*/
|
||||
void pinMode(uint32_t dwPin, uint32_t dwMode) {
|
||||
switch(dwPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||
|
|
@ -40,6 +49,11 @@ class Stm32wlxHal : public ArduinoHal {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Digital write override to handle STM32WL virtual pins.
|
||||
\param dwPin Pin to set.
|
||||
\param dwVal Value to set.
|
||||
*/
|
||||
void digitalWrite(uint32_t dwPin, uint32_t dwVal) {
|
||||
switch (dwPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||
|
|
@ -61,6 +75,11 @@ class Stm32wlxHal : public ArduinoHal {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Digital read override to handle STM32WL virtual pins.
|
||||
\param ulPin Pin to read.
|
||||
\returns Value read on the pin.
|
||||
*/
|
||||
uint32_t digitalRead(uint32_t ulPin) {
|
||||
switch (ulPin) {
|
||||
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||
|
|
|
|||
|
|
@ -6,24 +6,33 @@ SX1261::SX1261(Module* mod): SX1262(mod) {
|
|||
}
|
||||
|
||||
int16_t SX1261::setOutputPower(int8_t power) {
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, RADIOLIB_SX126X_PA_CONFIG_SX1261, 0x00);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
/// \todo power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
// set output power with default 200us ramp
|
||||
state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
||||
int16_t SX1261::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-17, RADIOLIB_MIN(14, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,14 +25,22 @@ class SX1261 : public SX1262 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1261(Module* mod);
|
||||
SX1261(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -17 to 14 dBm.
|
||||
\param power Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -51,13 +51,46 @@ int16_t SX1262::setFrequency(float freq) {
|
|||
return(setFrequency(freq, true));
|
||||
}
|
||||
|
||||
int16_t SX1262::setFrequency(float freq, bool calibrate, float band) {
|
||||
int16_t SX1262::setFrequency(float freq, bool calibrate) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 150.0, 960.0, RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = SX126x::calibrateImage(freq - band, freq + band);
|
||||
uint8_t data[2] = { 0, 0 };
|
||||
|
||||
// try to match the frequency ranges
|
||||
int freqBand = (int)freq;
|
||||
if((freqBand >= 902) && (freqBand <= 928)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_902_MHZ_2;
|
||||
} else if((freqBand >= 863) && (freqBand <= 870)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_863_MHZ_2;
|
||||
} else if((freqBand >= 779) && (freqBand <= 787)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_2;
|
||||
} else if((freqBand >= 470) && (freqBand <= 510)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_2;
|
||||
} else if((freqBand >= 430) && (freqBand <= 440)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_2;
|
||||
}
|
||||
|
||||
int16_t state;
|
||||
if(data[0]) {
|
||||
// matched with predefined ranges, do the calibration
|
||||
state = SX126x::calibrateImage(data);
|
||||
|
||||
} else {
|
||||
// if nothing matched, try custom calibration - the may or may not work
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to match predefined frequency range, trying custom");
|
||||
state = SX126x::calibrateImageRejection(freq - 4.0f, freq + 4.0f);
|
||||
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
}
|
||||
|
||||
// set frequency
|
||||
|
|
@ -65,24 +98,33 @@ int16_t SX1262::setFrequency(float freq, bool calibrate, float band) {
|
|||
}
|
||||
|
||||
int16_t SX1262::setOutputPower(int8_t power) {
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, RADIOLIB_SX126X_PA_CONFIG_SX1262);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
/// \todo power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
// set output power with default 200us ramp
|
||||
state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
||||
int16_t SX1262::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class SX1262: public SX126x {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1262(Module* mod);
|
||||
SX1262(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -69,18 +69,15 @@ class SX1262: public SX126x {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
int16_t setFrequency(float freq, bool calibrate);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -9 to 22 dBm.
|
||||
|
|
@ -88,7 +85,15 @@ class SX1262: public SX126x {
|
|||
\param power Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
virtual int16_t setOutputPower(int8_t power);
|
||||
virtual int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -52,13 +52,40 @@ int16_t SX1268::setFrequency(float freq) {
|
|||
}
|
||||
|
||||
/// \todo integers only (all modules - frequency, data rate, bandwidth etc.)
|
||||
int16_t SX1268::setFrequency(float freq, bool calibrate, float band) {
|
||||
int16_t SX1268::setFrequency(float freq, bool calibrate) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 410.0, 810.0, RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
|
||||
// calibrate image rejection
|
||||
if(calibrate) {
|
||||
int16_t state = SX126x::calibrateImage(freq - band, freq + band);
|
||||
uint8_t data[2] = { 0, 0 };
|
||||
|
||||
// try to match the frequency ranges
|
||||
int freqBand = (int)freq;
|
||||
if((freqBand >= 779) && (freqBand <= 787)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_779_MHZ_2;
|
||||
} else if((freqBand >= 470) && (freqBand <= 510)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_470_MHZ_2;
|
||||
} else if((freqBand >= 430) && (freqBand <= 440)) {
|
||||
data[0] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_1;
|
||||
data[1] = RADIOLIB_SX126X_CAL_IMG_430_MHZ_2;
|
||||
}
|
||||
|
||||
int16_t state;
|
||||
if(data[0]) {
|
||||
// matched with predefined ranges, do the calibration
|
||||
state = SX126x::calibrateImage(data);
|
||||
|
||||
} else {
|
||||
// if nothing matched, try custom calibration - the may or may not work
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Failed to match predefined frequency range, trying custom");
|
||||
state = SX126x::calibrateImageRejection(freq - 4.0f, freq + 4.0f);
|
||||
|
||||
}
|
||||
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
}
|
||||
|
||||
// set frequency
|
||||
|
|
@ -66,24 +93,33 @@ int16_t SX1268::setFrequency(float freq, bool calibrate, float band) {
|
|||
}
|
||||
|
||||
int16_t SX1268::setOutputPower(int8_t power) {
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// get current OCP configuration
|
||||
uint8_t ocp = 0;
|
||||
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set PA config
|
||||
state = SX126x::setPaConfig(0x04, RADIOLIB_SX126X_PA_CONFIG_SX1268);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set output power
|
||||
/// \todo power ramp time configuration
|
||||
state = SX126x::setTxParams(power);
|
||||
// set output power with default 200us ramp
|
||||
state = SX126x::setTxParams(power, RADIOLIB_SX126X_PA_RAMP_200U);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// restore OCP configuration
|
||||
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||
}
|
||||
|
||||
int16_t SX1268::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-9, RADIOLIB_MIN(22, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class SX1268: public SX126x {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1268(Module* mod);
|
||||
SX1268(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -68,25 +68,30 @@ class SX1268: public SX126x {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets carrier frequency. Allowed values are in range from 150.0 to 960.0 MHz.
|
||||
\param freq Carrier frequency to be set in MHz.
|
||||
\param calibrate Run image calibration.
|
||||
\param band Half bandwidth for image calibration. For example,
|
||||
if carrier is 434 MHz and band is set to 4 MHz, then the image will be calibrate
|
||||
for band 430 - 438 MHz. Unused if calibrate is set to false, defaults to 4 MHz
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq, bool calibrate, float band = 4);
|
||||
int16_t setFrequency(float freq, bool calibrate);
|
||||
|
||||
/*!
|
||||
\brief Sets output power. Allowed values are in range from -9 to 22 dBm.
|
||||
\param power Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t power);
|
||||
int16_t setOutputPower(int8_t power) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -14,12 +14,15 @@ int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, flo
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX126X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX126X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX126X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
|
||||
// try to find the SX126x chip
|
||||
if(!SX126x::findChip(this->chipType)) {
|
||||
|
|
@ -73,10 +76,11 @@ int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, flo
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
if (useRegulatorLDO) {
|
||||
state = setRegulatorLDO();
|
||||
state = setRegulatorLDO();
|
||||
} else {
|
||||
state = setRegulatorDCDC();
|
||||
state = setRegulatorDCDC();
|
||||
}
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set publicly accessible settings that are not a part of begin method
|
||||
state = setCurrentLimit(60.0);
|
||||
|
|
@ -99,12 +103,15 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleL
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX126X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX126X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX126X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
|
||||
// try to find the SX126x chip
|
||||
if(!SX126x::findChip(this->chipType)) {
|
||||
|
|
@ -201,7 +208,7 @@ int16_t SX126x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// set mode to standby - SX126x often refuses first few commands after reset
|
||||
uint32_t start = this->mod->hal->millis();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(true) {
|
||||
// try to set mode to standby
|
||||
int16_t state = standby();
|
||||
|
|
@ -231,41 +238,27 @@ int16_t SX126x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
return(RADIOLIB_ERR_PACKET_TOO_LONG);
|
||||
}
|
||||
|
||||
uint32_t timeout = 0;
|
||||
|
||||
// get currently active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
|
||||
// calculate timeout (150% of expected time-on-air)
|
||||
timeout = (getTimeOnAir(len) * 3) / 2;
|
||||
|
||||
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
|
||||
// calculate timeout (500% of expected time-on-air)
|
||||
timeout = getTimeOnAir(len) * 5;
|
||||
|
||||
} else {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
|
||||
// calculate timeout in ms (500% of expected time-on-air)
|
||||
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
|
||||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
uint32_t elapsed = this->mod->hal->micros() - start;
|
||||
|
||||
// update data rate
|
||||
this->dataRateMeasured = (len*8.0)/((float)elapsed/1000000.0);
|
||||
RadioLibTime_t elapsed = this->mod->hal->millis() - start;
|
||||
this->dataRateMeasured = (len*8.0)/((float)elapsed/1000.0);
|
||||
|
||||
return(finishTransmit());
|
||||
}
|
||||
|
|
@ -275,14 +268,15 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
|||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
uint32_t timeout = 0;
|
||||
RadioLibTime_t timeout = 0;
|
||||
|
||||
// get currently active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(modem == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
|
||||
// calculate timeout (100 LoRa symbols, the default for SX127x series)
|
||||
float symbolLength = (float)(uint32_t(1) << this->spreadingFactor) / (float)this->bandwidthKhz;
|
||||
timeout = (uint32_t)(symbolLength * 100.0 * 1000.0);
|
||||
timeout = (RadioLibTime_t)(symbolLength * 100.0);
|
||||
|
||||
} else if(modem == RADIOLIB_SX126X_PACKET_TYPE_GFSK) {
|
||||
// calculate timeout (500 % of expected time-one-air)
|
||||
size_t maxLen = len;
|
||||
|
|
@ -290,26 +284,27 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
|||
maxLen = 0xFF;
|
||||
}
|
||||
float brBps = ((float)(RADIOLIB_SX126X_CRYSTAL_FREQ) * 1000000.0 * 32.0) / (float)this->bitRate;
|
||||
timeout = (uint32_t)(((maxLen * 8.0) / brBps) * 1000000.0 * 5.0);
|
||||
timeout = (RadioLibTime_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0);
|
||||
|
||||
} else {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
|
||||
|
||||
// start reception
|
||||
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625);
|
||||
uint32_t timeoutValue = (uint32_t)(((float)timeout * 1000.0) / 15.625);
|
||||
state = startReceive(timeoutValue);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
bool softTimeout = false;
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
// safety check, the timeout should be done by the radio
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
softTimeout = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -586,7 +581,7 @@ int16_t SX126x::startReceive() {
|
|||
return(this->startReceive(RADIOLIB_SX126X_RX_TIMEOUT_INF, RADIOLIB_SX126X_IRQ_RX_DEFAULT, RADIOLIB_SX126X_IRQ_RX_DONE, 0));
|
||||
}
|
||||
|
||||
int16_t SX126x::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t SX126x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)len;
|
||||
int16_t state = startReceiveCommon(timeout, irqFlags, irqMask);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
|
@ -644,7 +639,7 @@ int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_
|
|||
|
||||
uint32_t symbolLength = ((uint32_t)(10 * 1000) << this->spreadingFactor) / (10 * this->bandwidthKhz);
|
||||
uint32_t sleepPeriod = symbolLength * sleepSymbols;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Auto sleep period: %lu", sleepPeriod);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Auto sleep period: %lu", (long unsigned int)sleepPeriod);
|
||||
|
||||
// when the unit detects a preamble, it starts a timer that will timeout if it doesn't receive a header in time.
|
||||
// the duration is sleepPeriod + 2 * wakePeriod.
|
||||
|
|
@ -655,7 +650,7 @@ int16_t SX126x::startReceiveDutyCycleAuto(uint16_t senderPreambleLength, uint16_
|
|||
uint32_t wakePeriod = RADIOLIB_MAX(
|
||||
(symbolLength * (senderPreambleLength + 1) - (sleepPeriod - 1000)) / 2, // (A)
|
||||
symbolLength * (minSymbols + 1)); //(B)
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Auto wake period: %lu", wakePeriod);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Auto wake period: %lu", (long unsigned int)wakePeriod);
|
||||
|
||||
// If our sleep period is shorter than our transition time, just use the standard startReceive
|
||||
if(sleepPeriod < this->tcxoDelay + 1016) {
|
||||
|
|
@ -1179,15 +1174,7 @@ int16_t SX126x::setSyncBits(uint8_t *syncWord, uint8_t bitsLen) {
|
|||
bytesLen++;
|
||||
}
|
||||
|
||||
// write sync word
|
||||
int16_t state = writeRegister(RADIOLIB_SX126X_REG_SYNC_WORD_0, syncWord, bytesLen);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// update packet parameters
|
||||
this->syncWordLength = bitsLen;
|
||||
state = setPacketParamsFSK(this->preambleLengthFSK, this->crcTypeFSK, this->syncWordLength, this->addrComp, this->whitening, this->packetType);
|
||||
|
||||
return(state);
|
||||
return(setSyncWord(syncWord, bytesLen));
|
||||
}
|
||||
|
||||
int16_t SX126x::setNodeAddress(uint8_t nodeAddr) {
|
||||
|
|
@ -1419,7 +1406,7 @@ int16_t SX126x::variablePacketLengthMode(uint8_t maxLen) {
|
|||
return(setPacketMode(RADIOLIB_SX126X_GFSK_PACKET_VARIABLE, maxLen));
|
||||
}
|
||||
|
||||
uint32_t SX126x::getTimeOnAir(size_t len) {
|
||||
RadioLibTime_t SX126x::getTimeOnAir(size_t len) {
|
||||
// everything is in microseconds to allow integer arithmetic
|
||||
// some constants have .25, these are multiplied by 4, and have _x4 postfix to indicate that fact
|
||||
if(getPacketType() == RADIOLIB_SX126X_PACKET_TYPE_LORA) {
|
||||
|
|
@ -1450,18 +1437,18 @@ uint32_t SX126x::getTimeOnAir(size_t len) {
|
|||
|
||||
return((symbolLength_us * nSymbol_x4) / 4);
|
||||
} else {
|
||||
return((len * 8 * this->bitRate) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 32));
|
||||
return(((uint32_t)len * 8 * this->bitRate) / (RADIOLIB_SX126X_CRYSTAL_FREQ * 32));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t SX126x::calculateRxTimeout(uint32_t timeoutUs) {
|
||||
RadioLibTime_t SX126x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
|
||||
// the timeout value is given in units of 15.625 microseconds
|
||||
// the calling function should provide some extra width, as this number of units is truncated to integer
|
||||
uint32_t timeout = timeoutUs / 15.625;
|
||||
RadioLibTime_t timeout = timeoutUs / 15.625;
|
||||
return(timeout);
|
||||
}
|
||||
|
||||
int16_t SX126x::irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask) {
|
||||
int16_t SX126x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
|
||||
irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT; // flags that can appear in the IRQ register
|
||||
irqMask = RADIOLIB_SX126X_IRQ_RX_DONE | RADIOLIB_SX126X_IRQ_TIMEOUT; // flags that will trigger DIO0
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
|
|
@ -1583,7 +1570,7 @@ int16_t SX126x::uploadPatch(const uint32_t* patch, size_t len, bool nonvolatile)
|
|||
// check the version
|
||||
#if RADIOLIB_DEBUG_BASIC
|
||||
char ver_pre[16];
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, (uint8_t*)ver_pre);
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, reinterpret_cast<uint8_t*>(ver_pre));
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Pre-update version string: %s", ver_pre);
|
||||
#endif
|
||||
|
||||
|
|
@ -1615,7 +1602,7 @@ int16_t SX126x::uploadPatch(const uint32_t* patch, size_t len, bool nonvolatile)
|
|||
// check the version again
|
||||
#if RADIOLIB_DEBUG_BASIC
|
||||
char ver_post[16];
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, (uint8_t*)ver_post);
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, reinterpret_cast<uint8_t*>(ver_post));
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Post-update version string: %s", ver_post);
|
||||
#endif
|
||||
|
||||
|
|
@ -1742,7 +1729,7 @@ int16_t SX126x::setRx(uint32_t timeout) {
|
|||
|
||||
int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
|
||||
// default CAD parameters are shown in Semtech AN1200.48, page 41.
|
||||
uint8_t detPeakValues[6] = { 22, 22, 24, 25, 26, 30};
|
||||
const uint8_t detPeakValues[6] = { 22, 22, 24, 25, 26, 30};
|
||||
|
||||
// CAD parameters aren't available for SF-6. Just to be safe.
|
||||
if(this->spreadingFactor < 7) {
|
||||
|
|
@ -1853,8 +1840,17 @@ int16_t SX126x::setRfFrequency(uint32_t frf) {
|
|||
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RF_FREQUENCY, data, 4));
|
||||
}
|
||||
|
||||
int16_t SX126x::calibrateImage(float freqMin, float freqMax) {
|
||||
int16_t SX126x::calibrateImageRejection(float freqMin, float freqMax) {
|
||||
// calculate the calibration coefficients and calibrate image
|
||||
uint8_t data[] = { (uint8_t)floor((freqMin - 1.0f) / 4.0f), (uint8_t)ceil((freqMax + 1.0f) / 4.0f) };
|
||||
return(this->calibrateImage(data));
|
||||
}
|
||||
|
||||
int16_t SX126x::setPaRampTime(uint8_t rampTime) {
|
||||
return(this->setTxParams(this->pwr, rampTime));
|
||||
}
|
||||
|
||||
int16_t SX126x::calibrateImage(uint8_t* data) {
|
||||
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE, data, 2);
|
||||
|
||||
// if something failed, show the device errors
|
||||
|
|
@ -1877,7 +1873,11 @@ uint8_t SX126x::getPacketType() {
|
|||
|
||||
int16_t SX126x::setTxParams(uint8_t pwr, uint8_t rampTime) {
|
||||
uint8_t data[] = { pwr, rampTime };
|
||||
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_TX_PARAMS, data, 2));
|
||||
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_TX_PARAMS, data, 2);
|
||||
if(state == RADIOLIB_ERR_NONE) {
|
||||
this->pwr = pwr;
|
||||
}
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX126x::setPacketMode(uint8_t mode, uint8_t len) {
|
||||
|
|
@ -2156,18 +2156,18 @@ bool SX126x::findChip(const char* verStr) {
|
|||
|
||||
// read the version string
|
||||
char version[16];
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, (uint8_t*)version);
|
||||
this->mod->SPIreadRegisterBurst(RADIOLIB_SX126X_REG_VERSION_STRING, 16, reinterpret_cast<uint8_t*>(version));
|
||||
|
||||
// check version register
|
||||
if(strncmp(verStr, version, 6) == 0) {
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Found SX126x: RADIOLIB_SX126X_REG_VERSION_STRING:");
|
||||
RADIOLIB_DEBUG_BASIC_HEXDUMP((uint8_t*)version, 16, RADIOLIB_SX126X_REG_VERSION_STRING);
|
||||
RADIOLIB_DEBUG_BASIC_HEXDUMP(reinterpret_cast<uint8_t*>(version), 16, RADIOLIB_SX126X_REG_VERSION_STRING);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN();
|
||||
flagFound = true;
|
||||
} else {
|
||||
#if RADIOLIB_DEBUG_BASIC
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("SX126x not found! (%d of 10 tries) RADIOLIB_SX126X_REG_VERSION_STRING:", i + 1);
|
||||
RADIOLIB_DEBUG_BASIC_HEXDUMP((uint8_t*)version, 16, RADIOLIB_SX126X_REG_VERSION_STRING);
|
||||
RADIOLIB_DEBUG_BASIC_HEXDUMP(reinterpret_cast<uint8_t*>(version), 16, RADIOLIB_SX126X_REG_VERSION_STRING);
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Expected string: %s", verStr);
|
||||
#endif
|
||||
this->mod->hal->delay(10);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,18 @@
|
|||
#define RADIOLIB_SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled
|
||||
#define RADIOLIB_SX126X_CALIBRATE_ALL 0b01111111 // 6 0 calibrate all blocks
|
||||
|
||||
//RADIOLIB_SX126X_CMD_CALIBRATE_IMAGE
|
||||
#define RADIOLIB_SX126X_CAL_IMG_430_MHZ_1 0x6B
|
||||
#define RADIOLIB_SX126X_CAL_IMG_430_MHZ_2 0x6F
|
||||
#define RADIOLIB_SX126X_CAL_IMG_470_MHZ_1 0x75
|
||||
#define RADIOLIB_SX126X_CAL_IMG_470_MHZ_2 0x81
|
||||
#define RADIOLIB_SX126X_CAL_IMG_779_MHZ_1 0xC1
|
||||
#define RADIOLIB_SX126X_CAL_IMG_779_MHZ_2 0xC5
|
||||
#define RADIOLIB_SX126X_CAL_IMG_863_MHZ_1 0xD7
|
||||
#define RADIOLIB_SX126X_CAL_IMG_863_MHZ_2 0xDB
|
||||
#define RADIOLIB_SX126X_CAL_IMG_902_MHZ_1 0xE1
|
||||
#define RADIOLIB_SX126X_CAL_IMG_902_MHZ_2 0xE9
|
||||
|
||||
//RADIOLIB_SX126X_CMD_SET_PA_CONFIG
|
||||
#define RADIOLIB_SX126X_PA_CONFIG_HP_MAX 0x07
|
||||
#define RADIOLIB_SX126X_PA_CONFIG_PA_LUT 0x01
|
||||
|
|
@ -440,7 +452,7 @@ class SX126x: public PhysicalLayer {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX126x(Module* mod);
|
||||
explicit SX126x(Module* mod);
|
||||
|
||||
/*!
|
||||
\brief Whether the module has an XTAL (true) or TCXO (false). Defaults to false.
|
||||
|
|
@ -574,34 +586,34 @@ class SX126x: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a channel scan is finished.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setChannelScanAction(void (*func)(void));
|
||||
void setChannelScanAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a channel scan is finished.
|
||||
*/
|
||||
void clearChannelScanAction();
|
||||
void clearChannelScanAction() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
|
|
@ -625,7 +637,7 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method. DIO1 will be activated when full packet is received.
|
||||
|
|
@ -642,7 +654,7 @@ class SX126x: public PhysicalLayer {
|
|||
\param len Only for PhysicalLayer compatibility, not used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint32_t timeout, uint16_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint16_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE, size_t len = 0);
|
||||
int16_t startReceive(uint32_t timeout, uint32_t irqFlags = RADIOLIB_SX126X_IRQ_RX_DEFAULT, uint32_t irqMask = RADIOLIB_SX126X_IRQ_RX_DONE, size_t len = 0);
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method where the device mostly sleeps and periodically wakes to listen.
|
||||
|
|
@ -774,7 +786,7 @@ class SX126x: public PhysicalLayer {
|
|||
\param br FSK bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
/*!
|
||||
\brief Set data.
|
||||
|
|
@ -908,7 +920,7 @@ class SX126x: public PhysicalLayer {
|
|||
\brief Gets SNR (Signal to Noise Ratio) of the last received packet. Only available for LoRa modem.
|
||||
\returns SNR of the last received packet in dB.
|
||||
*/
|
||||
float getSNR();
|
||||
float getSNR() override;
|
||||
|
||||
/*!
|
||||
\brief Gets frequency error of the latest received packet.
|
||||
|
|
@ -935,7 +947,7 @@ class SX126x: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode. Available in FSK mode only.
|
||||
\param len Maximum packet length.
|
||||
\param maxLen Maximum packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SX126X_MAX_PACKET_LENGTH);
|
||||
|
|
@ -945,14 +957,14 @@ class SX126x: public PhysicalLayer {
|
|||
\param len Payload length in bytes.
|
||||
\returns Expected time-on-air in microseconds.
|
||||
*/
|
||||
uint32_t getTimeOnAir(size_t len) override;
|
||||
RadioLibTime_t getTimeOnAir(size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Calculate the timeout value for this specific module / series (in number of symbols or units of time)
|
||||
\param timeoutUs Timeout in microseconds to listen for
|
||||
\returns Timeout value in a unit that is specific for the used module
|
||||
*/
|
||||
uint32_t calculateRxTimeout(uint32_t timeoutUs);
|
||||
RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs) override;
|
||||
|
||||
/*!
|
||||
\brief Create the flags that make up RxDone and RxTimeout used for receiving downlinks
|
||||
|
|
@ -960,13 +972,13 @@ class SX126x: public PhysicalLayer {
|
|||
\param irqMask Mask indicating which IRQ triggers a DIO
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask);
|
||||
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
|
||||
|
||||
/*!
|
||||
\brief Check whether the IRQ bit for RxTimeout is set
|
||||
\returns \ref RxTimeout IRQ is set
|
||||
\returns Whether RxTimeout IRQ is set
|
||||
*/
|
||||
bool isRxTimeout();
|
||||
bool isRxTimeout() override;
|
||||
|
||||
/*!
|
||||
\brief Set implicit header mode for future reception/transmission.
|
||||
|
|
@ -1028,7 +1040,7 @@ class SX126x: public PhysicalLayer {
|
|||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Enable/disable inversion of the I and Q signals
|
||||
|
|
@ -1042,13 +1054,13 @@ class SX126x: public PhysicalLayer {
|
|||
\brief Set interrupt service routine function to call when data bit is received in direct mode.
|
||||
\param func Pointer to interrupt service routine.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Function to read and process data bit in direct reception mode.
|
||||
\param pin Pin on which to read.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
|
@ -1102,10 +1114,25 @@ class SX126x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setPaConfig(uint8_t paDutyCycle, uint8_t deviceSel, uint8_t hpMax = RADIOLIB_SX126X_PA_CONFIG_HP_MAX, uint8_t paLut = RADIOLIB_SX126X_PA_CONFIG_PA_LUT);
|
||||
|
||||
/*!
|
||||
\brief Perform image rejection calibration for the specified frequency band.
|
||||
WARNING: Use at your own risk! Setting incorrect values may lead to decreased performance
|
||||
\param freqMin Frequency band lower bound.
|
||||
\param freqMax Frequency band upper bound.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t calibrateImageRejection(float freqMin, float freqMax);
|
||||
|
||||
/*!
|
||||
\brief Set PA ramp-up time. Set to 200us by default.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setPaRampTime(uint8_t rampTime);
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
// SX126x SPI command implementations
|
||||
int16_t setFs();
|
||||
|
|
@ -1119,9 +1146,9 @@ class SX126x: public PhysicalLayer {
|
|||
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX126X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX126X_IRQ_NONE);
|
||||
virtual int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
|
||||
int16_t setRfFrequency(uint32_t frf);
|
||||
int16_t calibrateImage(float freqMin, float freqMax);
|
||||
int16_t calibrateImage(uint8_t* data);
|
||||
uint8_t getPacketType();
|
||||
int16_t setTxParams(uint8_t power, uint8_t rampTime = RADIOLIB_SX126X_PA_RAMP_200U);
|
||||
int16_t setTxParams(uint8_t power, uint8_t rampTime);
|
||||
int16_t setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, uint8_t ldro);
|
||||
int16_t setModulationParamsFSK(uint32_t br, uint8_t sh, uint8_t rxBw, uint32_t freqDev);
|
||||
int16_t setPacketParams(uint16_t preambleLen, uint8_t crcType, uint8_t payloadLen, uint8_t hdrType, uint8_t invertIQ);
|
||||
|
|
@ -1136,7 +1163,7 @@ class SX126x: public PhysicalLayer {
|
|||
#if !RADIOLIB_GODMODE
|
||||
protected:
|
||||
#endif
|
||||
const char* chipType;
|
||||
const char* chipType = NULL;
|
||||
uint8_t bandwidth = 0;
|
||||
|
||||
// Allow subclasses to define different TX modes
|
||||
|
|
@ -1166,6 +1193,7 @@ class SX126x: public PhysicalLayer {
|
|||
float dataRateMeasured = 0;
|
||||
|
||||
uint32_t tcxoDelay = 0;
|
||||
uint8_t pwr = 0;
|
||||
|
||||
size_t implicitLen = 0;
|
||||
uint8_t invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD;
|
||||
|
|
|
|||
|
|
@ -280,15 +280,12 @@ int16_t SX1272::setOutputPower(int8_t power) {
|
|||
}
|
||||
|
||||
int16_t SX1272::setOutputPower(int8_t power, bool useRfo) {
|
||||
// check allowed power range
|
||||
if(useRfo) {
|
||||
RADIOLIB_CHECK_RANGE(power, -1, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
} else {
|
||||
RADIOLIB_CHECK_RANGE(power, 2, 20, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL, useRfo);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = SX127x::standby();
|
||||
state = SX127x::standby();
|
||||
Module* mod = this->getMod();
|
||||
|
||||
if(useRfo) {
|
||||
|
|
@ -317,6 +314,26 @@ int16_t SX1272::setOutputPower(int8_t power, bool useRfo) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1272::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, false));
|
||||
}
|
||||
|
||||
int16_t SX1272::checkOutputPower(int8_t power, int8_t* clipped, bool useRfo) {
|
||||
// check allowed power range
|
||||
if(useRfo) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-1, RADIOLIB_MIN(14, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -1, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
} else {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(2, RADIOLIB_MIN(20, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, 2, 20, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX1272::setGain(uint8_t gain) {
|
||||
// check allowed range
|
||||
if(gain > 6) {
|
||||
|
|
@ -419,6 +436,10 @@ int16_t SX1272::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
float SX1272::getRSSI() {
|
||||
return(SX1272::getRSSI(true, false));
|
||||
}
|
||||
|
||||
float SX1272::getRSSI(bool packet, bool skipReceive) {
|
||||
return(SX127x::getRSSI(packet, skipReceive, -139));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class SX1272: public SX127x {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1272(Module* mod);
|
||||
SX1272(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -111,8 +111,7 @@ class SX1272: public SX127x {
|
|||
\param sf %LoRa link spreading factor. Allowed values range from 6 to 12.
|
||||
\param cr %LoRa link coding rate denominator. Allowed values range from 5 to 8.
|
||||
\param syncWord %LoRa sync word. Can be used to distinguish different networks. Note that value 0x34 is reserved for LoRaWAN networks.
|
||||
\param currentLimit Trim value for OCP (over current protection) in mA. Can be set to multiplies of 5 in range 45 to 120 mA and to multiples of 10 in range 120 to 240 mA.
|
||||
Set to 0 to disable OCP (not recommended).
|
||||
\param power Transmission output power in dBm. Allowed values range from 2 to 17 dBm.
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols. The actual preamble length is 4.25 symbols longer than the set number.
|
||||
Allowed values range from 6 to 65535.
|
||||
\param gain Gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
|
|
@ -147,7 +146,7 @@ class SX1272: public SX127x {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link bandwidth. Allowed values are 125, 250 and 500 kHz. Only available in %LoRa mode.
|
||||
|
|
@ -207,6 +206,24 @@ class SX1272: public SX127x {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power, bool useRfo);
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm, assumes PA_BOOST pin.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param useRfo Whether to use the RFO (true) or the PA_BOOST (false) pin for the RF output.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool useRfo);
|
||||
|
||||
/*!
|
||||
\brief Sets gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
|
@ -232,13 +249,20 @@ class SX1272: public SX127x {
|
|||
*/
|
||||
int16_t setDataShapingOOK(uint8_t sh);
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator.
|
||||
Overload with packet mode enabled for PhysicalLayer compatibility.
|
||||
\returns RSSI value in dBm.
|
||||
*/
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator.
|
||||
\param packet Whether to read last packet RSSI, or the current value. LoRa mode only, ignored for FSK.
|
||||
\param skipReceive Set to true to skip putting radio in receive mode for the RSSI measurement in FSK/OOK mode.
|
||||
\returns RSSI value in dBm.
|
||||
*/
|
||||
float getRSSI(bool packet = true, bool skipReceive = false);
|
||||
float getRSSI(bool packet, bool skipReceive = false);
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
|
@ -287,7 +311,7 @@ class SX1272: public SX127x {
|
|||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
int16_t configFSK();
|
||||
void errataFix(bool rx);
|
||||
void errataFix(bool rx) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class SX1273: public SX1272 {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1273(Module* mod);
|
||||
SX1273(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class SX1276: public SX1278 {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1276(Module* mod);
|
||||
SX1276(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ class SX1276: public SX1278 {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class SX1277: public SX1278 {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1277(Module* mod);
|
||||
SX1277(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ class SX1277: public SX1278 {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link spreading factor. Allowed values range from 6 to 9. Only available in %LoRa mode.
|
||||
|
|
|
|||
|
|
@ -294,19 +294,12 @@ int16_t SX1278::setOutputPower(int8_t power) {
|
|||
}
|
||||
|
||||
int16_t SX1278::setOutputPower(int8_t power, bool useRfo) {
|
||||
// check allowed power range
|
||||
if(useRfo) {
|
||||
// RFO output
|
||||
RADIOLIB_CHECK_RANGE(power, -3, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
} else {
|
||||
// PA_BOOST output, check high-power operation
|
||||
if(power != 20) {
|
||||
RADIOLIB_CHECK_RANGE(power, 2, 17, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
}
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL, useRfo);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = SX127x::standby();
|
||||
state = SX127x::standby();
|
||||
Module* mod = this->getMod();
|
||||
|
||||
if(useRfo) {
|
||||
|
|
@ -342,6 +335,34 @@ int16_t SX1278::setOutputPower(int8_t power, bool useRfo) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
return(checkOutputPower(power, clipped, false));
|
||||
}
|
||||
|
||||
int16_t SX1278::checkOutputPower(int8_t power, int8_t* clipped, bool useRfo) {
|
||||
// check allowed power range
|
||||
if(useRfo) {
|
||||
// RFO output
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-3, RADIOLIB_MIN(15, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -3, 15, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
} else {
|
||||
// PA_BOOST output, check high-power operation
|
||||
if(clipped) {
|
||||
if(power != 20) {
|
||||
*clipped = RADIOLIB_MAX(2, RADIOLIB_MIN(17, power));
|
||||
} else {
|
||||
*clipped = 20;
|
||||
}
|
||||
}
|
||||
if(power != 20) {
|
||||
RADIOLIB_CHECK_RANGE(power, 2, 17, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
}
|
||||
}
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX1278::setGain(uint8_t gain) {
|
||||
// check allowed range
|
||||
if(gain > 6) {
|
||||
|
|
@ -448,6 +469,10 @@ int16_t SX1278::setDataShapingOOK(uint8_t sh) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
float SX1278::getRSSI() {
|
||||
return(SX1278::getRSSI(true, false));
|
||||
}
|
||||
|
||||
float SX1278::getRSSI(bool packet, bool skipReceive) {
|
||||
int16_t offset = -157;
|
||||
if(frequency < 868.0) {
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class SX1278: public SX127x {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1278(Module* mod);
|
||||
SX1278(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ class SX1278: public SX127x {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets %LoRa link bandwidth. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz. Only available in %LoRa mode.
|
||||
|
|
@ -218,6 +218,24 @@ class SX1278: public SX127x {
|
|||
*/
|
||||
int16_t setOutputPower(int8_t power, bool useRfo);
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
This method is needed for compatibility with PhysicalLayer::checkOutputPower.
|
||||
\param power Output power in dBm, assumes PA_BOOST pin.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\param useRfo Whether to use the RFO (true) or the PA_BOOST (false) pin for the RF output.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped, bool useRfo);
|
||||
|
||||
/*!
|
||||
\brief Sets gain of receiver LNA (low-noise amplifier). Can be set to any integer in range 1 to 6 where 1 is the highest gain.
|
||||
Set to 0 to enable automatic gain control (recommended).
|
||||
|
|
@ -243,13 +261,20 @@ class SX1278: public SX127x {
|
|||
*/
|
||||
int16_t setDataShapingOOK(uint8_t sh);
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator.
|
||||
Overload with packet mode enabled for PhysicalLayer compatibility.
|
||||
\returns RSSI value in dBm.
|
||||
*/
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator.
|
||||
\param packet Whether to read last packet RSSI, or the current value. LoRa mode only, ignored for FSK.
|
||||
\param skipReceive Set to true to skip putting radio in receive mode for the RSSI measurement in FSK/OOK mode.
|
||||
\returns RSSI value in dBm.
|
||||
*/
|
||||
float getRSSI(bool packet = true, bool skipReceive = false);
|
||||
float getRSSI(bool packet, bool skipReceive = false);
|
||||
|
||||
/*!
|
||||
\brief Enables/disables CRC check of received packets.
|
||||
|
|
@ -298,7 +323,7 @@ class SX1278: public SX127x {
|
|||
int16_t setHeaderType(uint8_t headerType, size_t len = 0xFF);
|
||||
|
||||
int16_t configFSK();
|
||||
void errataFix(bool rx);
|
||||
void errataFix(bool rx) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class SX1279: public SX1278 {
|
|||
\brief Default constructor. Called from Arduino sketch when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX1279(Module* mod);
|
||||
SX1279(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ class SX1279: public SX1278 {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -147,15 +147,16 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
int16_t modem = getActiveModem();
|
||||
uint32_t start = 0;
|
||||
uint32_t timeout = 0;
|
||||
RadioLibTime_t start = 0;
|
||||
RadioLibTime_t timeout = 0;
|
||||
RadioLibTime_t toa = getTimeOnAir(len);
|
||||
if(modem == RADIOLIB_SX127X_LORA) {
|
||||
// calculate timeout (150 % of expected time-on-air)
|
||||
timeout = getTimeOnAir(len) * 1.5;
|
||||
// calculate timeout in ms (150 % of expected time-on-air)
|
||||
timeout = (toa * 1.5) / 1000;
|
||||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
// calculate timeout (5ms + 500 % of expected time-on-air)
|
||||
timeout = 5000 + getTimeOnAir(len) * 5;
|
||||
// calculate timeout in ms (5ms + 500 % of expected time-on-air)
|
||||
timeout = 5 + (toa * 5) / 1000;
|
||||
|
||||
} else {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
|
|
@ -163,22 +164,23 @@ int16_t SX127x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
}
|
||||
|
||||
// start transmission
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
|
||||
state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
start = this->mod->hal->micros();
|
||||
start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
// update data rate
|
||||
uint32_t elapsed = this->mod->hal->micros() - start;
|
||||
this->dataRate = (len*8.0)/((float)elapsed/1000000.0);
|
||||
RadioLibTime_t elapsed = this->mod->hal->millis() - start;
|
||||
this->dataRate = (len*8.0)/((float)elapsed/1000.0);
|
||||
|
||||
return(finishTransmit());
|
||||
}
|
||||
|
|
@ -195,20 +197,20 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// if no DIO1 is provided, use software timeout (100 LoRa symbols, same as hardware timeout)
|
||||
uint32_t timeout = 0;
|
||||
RadioLibTime_t timeout = 0;
|
||||
if(this->mod->getGpio() == RADIOLIB_NC) {
|
||||
float symbolLength = (float) (uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
|
||||
timeout = (uint32_t)(symbolLength * 100.0 * 1000.0);
|
||||
timeout = (RadioLibTime_t)(symbolLength * 100.0);
|
||||
}
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
|
||||
if(this->mod->getGpio() == RADIOLIB_NC) {
|
||||
// no GPIO pin provided, use software timeout
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -223,18 +225,18 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
|
|||
}
|
||||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
// calculate timeout (500 % of expected time-on-air)
|
||||
uint32_t timeout = getTimeOnAir(len) * 5;
|
||||
// calculate timeout in ms (500 % of expected time-on-air)
|
||||
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
|
||||
|
||||
// set mode to receive
|
||||
state = startReceive(len, RADIOLIB_SX127X_RX);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet reception or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
clearIRQFlags();
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -417,7 +419,7 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
|||
return(setMode(mode));
|
||||
}
|
||||
|
||||
int16_t SX127x::startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t SX127x::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)irqFlags;
|
||||
(void)irqMask;
|
||||
uint8_t mode = RADIOLIB_SX127X_RXCONTINUOUS;
|
||||
|
|
@ -903,13 +905,13 @@ int16_t SX127x::setBitRateCommon(float br, uint8_t fracRegAddr) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set bit rate
|
||||
uint16_t bitRate = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / br;
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_MSB, (bitRate & 0xFF00) >> 8, 7, 0);
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_LSB, bitRate & 0x00FF, 7, 0);
|
||||
uint16_t bitRateRaw = (RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / br;
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_MSB, (bitRateRaw & 0xFF00) >> 8, 7, 0);
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_BITRATE_LSB, bitRateRaw & 0x00FF, 7, 0);
|
||||
|
||||
// set fractional part of bit rate
|
||||
if(!ookEnabled) {
|
||||
float bitRateRem = ((RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / (float)br) - (float)bitRate;
|
||||
float bitRateRem = ((RADIOLIB_SX127X_CRYSTAL_FREQ * 1000.0) / (float)br) - (float)bitRateRaw;
|
||||
uint8_t bitRateFrac = bitRateRem * 16;
|
||||
state |= this->mod->SPIsetRegValue(fracRegAddr, bitRateFrac, 7, 0);
|
||||
}
|
||||
|
|
@ -1242,7 +1244,7 @@ float SX127x::getNumSymbols(size_t len) {
|
|||
return(n_pre + n_pay + 4.25f);
|
||||
}
|
||||
|
||||
uint32_t SX127x::getTimeOnAir(size_t len) {
|
||||
RadioLibTime_t SX127x::getTimeOnAir(size_t len) {
|
||||
// check active modem
|
||||
uint8_t modem = getActiveModem();
|
||||
if (modem == RADIOLIB_SX127X_LORA) {
|
||||
|
|
@ -1252,43 +1254,42 @@ uint32_t SX127x::getTimeOnAir(size_t len) {
|
|||
// get number of symbols
|
||||
float n_sym = getNumSymbols(len);
|
||||
|
||||
// Get time-on-air in us
|
||||
// get time-on-air in us
|
||||
return ceil((double)symbolLength * (double)n_sym) * 1000;
|
||||
|
||||
} else if(modem == RADIOLIB_SX127X_FSK_OOK) {
|
||||
// Get number of bits preamble
|
||||
// get number of bits preamble
|
||||
float n_pre = (float) ((this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PREAMBLE_MSB_FSK) << 8) | this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PREAMBLE_LSB_FSK)) * 8;
|
||||
//Get the number of bits of the sync word
|
||||
// get the number of bits of the sync word
|
||||
float n_syncWord = (float) (this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_SYNC_CONFIG, 2, 0) + 1) * 8;
|
||||
//Get CRC bits
|
||||
// get CRC bits
|
||||
float crc = (this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PACKET_CONFIG_1, 4, 4) == RADIOLIB_SX127X_CRC_ON) * 16;
|
||||
|
||||
if (this->packetLengthConfig == RADIOLIB_SX127X_PACKET_FIXED) {
|
||||
//If Packet size fixed -> len = fixed packet length
|
||||
// if packet size fixed -> len = fixed packet length
|
||||
len = this->mod->SPIgetRegValue(RADIOLIB_SX127X_REG_PAYLOAD_LENGTH_FSK);
|
||||
} else {
|
||||
//if packet variable -> Add 1 extra byte for payload length
|
||||
// if packet variable -> Add 1 extra byte for payload length
|
||||
len += 1;
|
||||
}
|
||||
|
||||
// Calculate time-on-air in us {[(length in bytes) * (8 bits / 1 byte)] / [(Bit Rate in kbps) * (1000 bps / 1 kbps)]} * (1000000 us in 1 sec)
|
||||
return (uint32_t) (((crc + n_syncWord + n_pre + (float) (len * 8)) / (this->bitRate * 1000.0)) * 1000000.0);
|
||||
} else {
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
// calculate time-on-air in us {[(length in bytes) * (8 bits / 1 byte)] / [(Bit Rate in kbps) * (1000 bps / 1 kbps)]} * (1000000 us in 1 sec)
|
||||
return((uint32_t) (((crc + n_syncWord + n_pre + (float) (len * 8)) / (this->bitRate * 1000.0)) * 1000000.0));
|
||||
}
|
||||
|
||||
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
}
|
||||
|
||||
uint32_t SX127x::calculateRxTimeout(uint32_t timeoutUs) {
|
||||
RadioLibTime_t SX127x::calculateRxTimeout(RadioLibTime_t timeoutUs) {
|
||||
// the timeout is given as the number of symbols
|
||||
// the calling function should provide some extra width, as this number of symbols is truncated to integer
|
||||
// the order of operators is swapped here to decrease the effects of this truncation error
|
||||
float symbolLength = (float) (uint32_t(1) << this->spreadingFactor) / (float) this->bandwidth;
|
||||
uint32_t numSymbols = (timeoutUs / symbolLength) / 1000;
|
||||
RadioLibTime_t numSymbols = (timeoutUs / symbolLength) / 1000;
|
||||
return(numSymbols);
|
||||
}
|
||||
|
||||
int16_t SX127x::irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask) {
|
||||
int16_t SX127x::irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) {
|
||||
// IRQ flags/masks are inverted to what seems logical for SX127x (0 being activated, 1 being deactivated)
|
||||
irqFlags = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DEFAULT;
|
||||
irqMask = RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_DONE & RADIOLIB_SX127X_MASK_IRQ_FLAG_RX_TIMEOUT;
|
||||
|
|
@ -1334,8 +1335,14 @@ int16_t SX127x::setRSSIConfig(uint8_t smoothingSamples, int8_t offset) {
|
|||
|
||||
RADIOLIB_CHECK_RANGE(offset, -16, 15, RADIOLIB_ERR_INVALID_RSSI_OFFSET);
|
||||
|
||||
// calculate the two's complement
|
||||
uint8_t offsetRaw = RADIOLIB_ABS(offset);
|
||||
offsetRaw ^= 0x1F;
|
||||
offsetRaw += 1;
|
||||
offsetRaw &= 0x1F;
|
||||
|
||||
// set new register values
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RSSI_CONFIG, offset << 3, 7, 3);
|
||||
state = this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RSSI_CONFIG, offsetRaw << 3, 7, 3);
|
||||
state |= this->mod->SPIsetRegValue(RADIOLIB_SX127X_REG_RSSI_CONFIG, smoothingSamples, 2, 0);
|
||||
return(state);
|
||||
}
|
||||
|
|
@ -1537,7 +1544,7 @@ int16_t SX127x::setPacketMode(uint8_t mode, uint8_t len) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
bool SX127x::findChip(uint8_t* vers, uint8_t num) {
|
||||
bool SX127x::findChip(const uint8_t* vers, uint8_t num) {
|
||||
uint8_t i = 0;
|
||||
bool flagFound = false;
|
||||
while((i < 10) && !flagFound) {
|
||||
|
|
@ -1546,8 +1553,8 @@ bool SX127x::findChip(uint8_t* vers, uint8_t num) {
|
|||
|
||||
// check version register
|
||||
int16_t version = getChipVersion();
|
||||
for(uint8_t i = 0; i < num; i++) {
|
||||
if(version == vers[i]) {
|
||||
for(uint8_t j = 0; j < num; j++) {
|
||||
if(version == vers[j]) {
|
||||
flagFound = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -594,13 +594,13 @@ class SX127x: public PhysicalLayer {
|
|||
\brief Default constructor. Called internally when creating new LoRa instance.
|
||||
\param mod Instance of Module that will be used to communicate with the %LoRa chip.
|
||||
*/
|
||||
SX127x(Module* mod);
|
||||
explicit SX127x(Module* mod);
|
||||
|
||||
// basic methods
|
||||
|
||||
/*!
|
||||
\brief Initialization method. Will be called with appropriate parameters when calling initialization method from derived class.
|
||||
\param chipVersion Array of possible values in SPI version register. Used to verify the connection and hardware version.
|
||||
\param chipVersions Array of possible values in SPI version register. Used to verify the connection and hardware version.
|
||||
\param numVersions Number of possible chip versions.
|
||||
\param syncWord %LoRa sync word.
|
||||
\param preambleLength Length of %LoRa transmission preamble in symbols.
|
||||
|
|
@ -615,7 +615,7 @@ class SX127x: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Initialization method for FSK modem. Will be called with appropriate parameters when calling FSK initialization method from derived class.
|
||||
\param chipVersion Array of possible values in SPI version register. Used to verify the connection and hardware version.
|
||||
\param chipVersions Array of possible values in SPI version register. Used to verify the connection and hardware version.
|
||||
\param numVersions Number of possible chip versions.
|
||||
\param freqDev Frequency deviation of the FSK transmission in kHz.
|
||||
\param rxBw Receiver bandwidth in kHz.
|
||||
|
|
@ -655,7 +655,7 @@ class SX127x: public PhysicalLayer {
|
|||
%Module will wake up automatically when methods like transmit or receive are called.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t sleep();
|
||||
int16_t sleep() override;
|
||||
|
||||
/*!
|
||||
\brief Sets the %LoRa module to standby.
|
||||
|
|
@ -721,34 +721,34 @@ class SX127x: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a channel scan is finished.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setChannelScanAction(void (*func)(void));
|
||||
void setChannelScanAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a channel scan is finished.
|
||||
*/
|
||||
void clearChannelScanAction();
|
||||
void clearChannelScanAction() override;
|
||||
|
||||
/*!
|
||||
\brief Set interrupt service routine function to call when FIFO is empty.
|
||||
|
|
@ -810,7 +810,7 @@ class SX127x: public PhysicalLayer {
|
|||
Implemented for compatibility with PhysicalLayer.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method. DIO0 will be activated when full valid packet is received.
|
||||
|
|
@ -832,7 +832,7 @@ class SX127x: public PhysicalLayer {
|
|||
\param len Expected length of packet to be received. Required for LoRa spreading factor 6.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint32_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len);
|
||||
int16_t startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Reads data that was received after calling startReceive method. When the packet length is not known in advance,
|
||||
|
|
@ -904,7 +904,7 @@ class SX127x: public PhysicalLayer {
|
|||
\brief Gets signal-to-noise ratio of the latest received packet. Only available in LoRa mode.
|
||||
\returns Last packet signal-to-noise ratio (SNR).
|
||||
*/
|
||||
float getSNR();
|
||||
float getSNR() override;
|
||||
|
||||
/*!
|
||||
\brief Get data rate of the latest transmitted packet.
|
||||
|
|
@ -928,7 +928,7 @@ class SX127x: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Sets FSK automatic frequency correction bandwidth. Allowed values range from 2.6 to 250 kHz. Only available in FSK mode.
|
||||
\param rxBw Receiver AFC bandwidth to be set (in kHz).
|
||||
\param afcBw Receiver AFC bandwidth to be set (in kHz).
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setAFCBandwidth(float afcBw);
|
||||
|
|
@ -1038,7 +1038,7 @@ class SX127x: public PhysicalLayer {
|
|||
|
||||
/*!
|
||||
\brief Set modem in variable packet length mode. Available in FSK mode only.
|
||||
\param len Maximum packet length.
|
||||
\param maxLen Maximum packet length.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t variablePacketLengthMode(uint8_t maxLen = RADIOLIB_SX127X_MAX_PACKET_LENGTH_FSK);
|
||||
|
|
@ -1055,14 +1055,14 @@ class SX127x: public PhysicalLayer {
|
|||
\param len Payload length in bytes.
|
||||
\returns Expected time-on-air in microseconds.
|
||||
*/
|
||||
uint32_t getTimeOnAir(size_t len) override;
|
||||
RadioLibTime_t getTimeOnAir(size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Calculate the timeout value for this specific module / series (in number of symbols or units of time)
|
||||
\param timeoutUs Timeout in microseconds to listen for
|
||||
\returns Timeout value in a unit that is specific for the used module
|
||||
*/
|
||||
uint32_t calculateRxTimeout(uint32_t timeoutUs);
|
||||
RadioLibTime_t calculateRxTimeout(RadioLibTime_t timeoutUs) override;
|
||||
|
||||
/*!
|
||||
\brief Create the flags that make up RxDone and RxTimeout used for receiving downlinks
|
||||
|
|
@ -1070,13 +1070,13 @@ class SX127x: public PhysicalLayer {
|
|||
\param irqMask Mask indicating which IRQ triggers a DIO
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t irqRxDoneRxTimeout(uint16_t &irqFlags, uint16_t &irqMask);
|
||||
int16_t irqRxDoneRxTimeout(uint32_t &irqFlags, uint32_t &irqMask) override;
|
||||
|
||||
/*!
|
||||
\brief Check whether the IRQ bit for RxTimeout is set
|
||||
\returns \ref RxTimeout IRQ is set
|
||||
\returns Whether RxTimeout IRQ is set
|
||||
*/
|
||||
bool isRxTimeout();
|
||||
bool isRxTimeout() override;
|
||||
|
||||
/*!
|
||||
\brief Enable CRC filtering and generation.
|
||||
|
|
@ -1133,7 +1133,7 @@ class SX127x: public PhysicalLayer {
|
|||
\brief Get one truly random byte from RSSI noise.
|
||||
\returns TRNG byte.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Read version SPI register. Should return SX1278_CHIP_VERSION (0x12) or SX1272_CHIP_VERSION (0x22) if SX127x is connected and working.
|
||||
|
|
@ -1153,13 +1153,13 @@ class SX127x: public PhysicalLayer {
|
|||
\brief Set interrupt service routine function to call when data bit is received in direct mode.
|
||||
\param func Pointer to interrupt service routine.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Function to read and process data bit in direct reception mode.
|
||||
\param pin Pin on which to read.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
|
@ -1192,7 +1192,7 @@ class SX127x: public PhysicalLayer {
|
|||
\param value The value that indicates which function to place on that pin. See chip datasheet for details.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value);
|
||||
int16_t setDIOMapping(uint32_t pin, uint32_t value) override;
|
||||
|
||||
/*!
|
||||
\brief Configure DIO mapping to use RSSI or Preamble Detect for pins that support it.
|
||||
|
|
@ -1201,14 +1201,6 @@ class SX127x: public PhysicalLayer {
|
|||
*/
|
||||
int16_t setDIOPreambleDetect(bool usePreambleDetect);
|
||||
|
||||
/*!
|
||||
\brief Gets recorded signal strength indicator.
|
||||
\param packet Whether to read last packet RSSI, or the current value. LoRa mode only, ignored for FSK.
|
||||
\param skipReceive Set to true to skip putting radio in receive mode for the RSSI measurement in FSK/OOK mode.
|
||||
\returns RSSI value in dBm.
|
||||
*/
|
||||
float getRSSI(bool packet, bool skipReceive, int16_t offset);
|
||||
|
||||
/*!
|
||||
\brief Sets the RSSI value above which the RSSI interrupt is signaled
|
||||
\param dbm A dBm value between -127.5 and 0 inclusive
|
||||
|
|
@ -1229,7 +1221,7 @@ class SX127x: public PhysicalLayer {
|
|||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
protected:
|
||||
|
|
@ -1246,6 +1238,7 @@ class SX127x: public PhysicalLayer {
|
|||
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);
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
@ -1261,7 +1254,7 @@ class SX127x: public PhysicalLayer {
|
|||
int16_t config();
|
||||
int16_t directMode();
|
||||
int16_t setPacketMode(uint8_t mode, uint8_t len);
|
||||
bool findChip(uint8_t* vers, uint8_t num);
|
||||
bool findChip(const uint8_t* vers, uint8_t num);
|
||||
int16_t setMode(uint8_t mode);
|
||||
int16_t setActiveModem(uint8_t modem);
|
||||
void clearIRQFlags();
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ int16_t SX1280::range(bool master, uint32_t addr, uint16_t calTable[3][6]) {
|
|||
|
||||
// wait until ranging is finished
|
||||
Module* mod = this->getMod();
|
||||
uint32_t start = mod->hal->millis();
|
||||
RadioLibTime_t start = mod->hal->millis();
|
||||
while(!mod->hal->digitalRead(mod->getIrq())) {
|
||||
mod->hal->yield();
|
||||
if(mod->hal->millis() - start > 10000) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class SX1280: public SX1281 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1280(Module* mod);
|
||||
SX1280(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
/*!
|
||||
\brief Blocking ranging method.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class SX1281: public SX128x {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1281(Module* mod);
|
||||
SX1281(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class SX1282: public SX1280 {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX1282(Module* mod);
|
||||
SX1282(Module* mod); // cppcheck-suppress noExplicitConstructor
|
||||
|
||||
#if !RADIOLIB_GODMODE
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -11,12 +11,15 @@ int16_t SX128x::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX128x");
|
||||
|
||||
// initialize LoRa modulation variables
|
||||
|
|
@ -72,12 +75,15 @@ int16_t SX128x::beginGFSK(float freq, uint16_t br, float freqDev, int8_t pwr, ui
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX128x");
|
||||
|
||||
// initialize GFSK modulation variables
|
||||
|
|
@ -141,12 +147,15 @@ int16_t SX128x::beginBLE(float freq, uint16_t br, float freqDev, int8_t pwr, uin
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX128x");
|
||||
|
||||
// initialize BLE modulation variables
|
||||
|
|
@ -196,12 +205,15 @@ int16_t SX128x::beginFLRC(float freq, uint16_t br, uint8_t cr, int8_t pwr, uint1
|
|||
this->mod->init();
|
||||
this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput);
|
||||
this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput);
|
||||
this->mod->SPIreadCommand = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->SPIwriteCommand = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->SPInopCommand = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->SPIstatusCommand = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->SPIstreamType = true;
|
||||
this->mod->SPIparseStatusCb = SPIparseStatus;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16;
|
||||
this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8;
|
||||
this->mod->spiConfig.statusPos = 1;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX128X_CMD_READ_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX128X_CMD_WRITE_REGISTER;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX128X_CMD_NOP;
|
||||
this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX128X_CMD_GET_STATUS;
|
||||
this->mod->spiConfig.stream = true;
|
||||
this->mod->spiConfig.parseStatusCb = SPIparseStatus;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX128x");
|
||||
|
||||
// initialize FLRC modulation variables
|
||||
|
|
@ -269,7 +281,7 @@ int16_t SX128x::reset(bool verify) {
|
|||
}
|
||||
|
||||
// set mode to standby
|
||||
uint32_t start = this->mod->hal->millis();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(true) {
|
||||
// try to set mode to standby
|
||||
int16_t state = standby();
|
||||
|
|
@ -305,20 +317,19 @@ int16_t SX128x::transmit(uint8_t* data, size_t len, uint8_t addr) {
|
|||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// calculate timeout (500% of expected time-on-air)
|
||||
uint32_t timeout = getTimeOnAir(len) * 5;
|
||||
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
|
||||
// calculate timeout in ms (500% of expected time-on-air)
|
||||
RadioLibTime_t timeout = (getTimeOnAir(len) * 5) / 1000;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
|
||||
|
||||
// start transmission
|
||||
state = startTransmit(data, len, addr);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for packet transmission or timeout
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
finishTransmit();
|
||||
return(RADIOLIB_ERR_TX_TIMEOUT);
|
||||
}
|
||||
|
|
@ -339,9 +350,8 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
|
|||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// calculate timeout (1000% of expected time-on-air)
|
||||
uint32_t timeout = getTimeOnAir(len) * 10;
|
||||
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu us", timeout);
|
||||
RadioLibTime_t timeout = getTimeOnAir(len) * 10;
|
||||
RADIOLIB_DEBUG_BASIC_PRINTLN("Timeout in %lu ms", timeout);
|
||||
|
||||
// start reception
|
||||
uint32_t timeoutValue = (uint32_t)((float)timeout / 15.625);
|
||||
|
|
@ -350,11 +360,11 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
|
|||
|
||||
// wait for packet reception or timeout
|
||||
bool softTimeout = false;
|
||||
uint32_t start = this->mod->hal->micros();
|
||||
RadioLibTime_t start = this->mod->hal->millis();
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
// safety check, the timeout should be done by the radio
|
||||
if(this->mod->hal->micros() - start > timeout) {
|
||||
if(this->mod->hal->millis() - start > timeout) {
|
||||
softTimeout = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -401,28 +411,8 @@ int16_t SX128x::receiveDirect() {
|
|||
}
|
||||
|
||||
int16_t SX128x::scanChannel() {
|
||||
// check active modem
|
||||
if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
|
||||
return(RADIOLIB_ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO pin mapping
|
||||
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE, RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
state = clearIrqStatus();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set RF switch (if present)
|
||||
this->mod->setRfSwitchState(Module::MODE_RX);
|
||||
|
||||
// set mode to CAD
|
||||
state = setCad();
|
||||
int16_t state = startChannelScan();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// wait for channel activity detected or timeout
|
||||
|
|
@ -431,18 +421,7 @@ int16_t SX128x::scanChannel() {
|
|||
}
|
||||
|
||||
// check CAD result
|
||||
uint16_t cadResult = getIrqStatus();
|
||||
if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DETECTED) {
|
||||
// detected some LoRa activity
|
||||
clearIrqStatus();
|
||||
return(RADIOLIB_LORA_DETECTED);
|
||||
} else if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DONE) {
|
||||
// channel is free
|
||||
clearIrqStatus();
|
||||
return(RADIOLIB_CHANNEL_FREE);
|
||||
}
|
||||
|
||||
return(RADIOLIB_ERR_UNKNOWN);
|
||||
return(getChannelScanResult());
|
||||
}
|
||||
|
||||
int16_t SX128x::sleep(bool retainConfig) {
|
||||
|
|
@ -578,7 +557,7 @@ int16_t SX128x::startReceive() {
|
|||
return(this->startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT, RADIOLIB_SX128X_IRQ_RX_DONE, 0));
|
||||
}
|
||||
|
||||
int16_t SX128x::startReceive(uint16_t timeout, uint16_t irqFlags, uint16_t irqMask, size_t len) {
|
||||
int16_t SX128x::startReceive(uint16_t timeout, uint32_t irqFlags, uint32_t irqMask, size_t len) {
|
||||
(void)len;
|
||||
|
||||
// check active modem
|
||||
|
|
@ -654,6 +633,52 @@ int16_t SX128x::readData(uint8_t* data, size_t len) {
|
|||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX128x::startChannelScan() {
|
||||
// check active modem
|
||||
if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
|
||||
return(RADIOLIB_ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// set mode to standby
|
||||
int16_t state = standby();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set DIO pin mapping
|
||||
state = setDioIrqParams(RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE, RADIOLIB_SX128X_IRQ_CAD_DETECTED | RADIOLIB_SX128X_IRQ_CAD_DONE);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// clear interrupt flags
|
||||
state = clearIrqStatus();
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set RF switch (if present)
|
||||
this->mod->setRfSwitchState(Module::MODE_RX);
|
||||
|
||||
// set mode to CAD
|
||||
return(setCad());
|
||||
}
|
||||
|
||||
int16_t SX128x::getChannelScanResult() {
|
||||
// check active modem
|
||||
if(getPacketType() != RADIOLIB_SX128X_PACKET_TYPE_LORA) {
|
||||
return(RADIOLIB_ERR_WRONG_MODEM);
|
||||
}
|
||||
|
||||
// check CAD result
|
||||
uint16_t cadResult = getIrqStatus();
|
||||
int16_t state = RADIOLIB_ERR_UNKNOWN;
|
||||
if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DETECTED) {
|
||||
// detected some LoRa activity
|
||||
state = RADIOLIB_LORA_DETECTED;
|
||||
} else if(cadResult & RADIOLIB_SX128X_IRQ_CAD_DONE) {
|
||||
// channel is free
|
||||
state = RADIOLIB_CHANNEL_FREE;
|
||||
}
|
||||
|
||||
clearIrqStatus();
|
||||
return(state);
|
||||
}
|
||||
|
||||
int16_t SX128x::setFrequency(float freq) {
|
||||
RADIOLIB_CHECK_RANGE(freq, 2400.0, 2500.0, RADIOLIB_ERR_INVALID_FREQUENCY);
|
||||
|
||||
|
|
@ -755,11 +780,22 @@ int16_t SX128x::setCodingRate(uint8_t cr, bool longInterleaving) {
|
|||
}
|
||||
|
||||
int16_t SX128x::setOutputPower(int8_t pwr) {
|
||||
RADIOLIB_CHECK_RANGE(pwr, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
// check if power value is configurable
|
||||
int16_t state = checkOutputPower(power, NULL);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
this->power = pwr + 18;
|
||||
return(setTxParams(this->power));
|
||||
}
|
||||
|
||||
int16_t SX128x::checkOutputPower(int8_t power, int8_t* clipped) {
|
||||
if(clipped) {
|
||||
*clipped = RADIOLIB_MAX(-18, RADIOLIB_MIN(13, power));
|
||||
}
|
||||
RADIOLIB_CHECK_RANGE(power, -18, 13, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||
return(RADIOLIB_ERR_NONE);
|
||||
}
|
||||
|
||||
int16_t SX128x::setPreambleLength(uint32_t preambleLength) {
|
||||
uint8_t modem = getPacketType();
|
||||
if((modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) || (modem == RADIOLIB_SX128X_PACKET_TYPE_RANGING)) {
|
||||
|
|
@ -888,13 +924,13 @@ int16_t SX128x::setFrequencyDeviation(float freqDev) {
|
|||
}
|
||||
|
||||
// update modulation parameters
|
||||
uint8_t modIndex = (uint8_t)((8.0 * (newFreqDev / (float)this->bitRateKbps)) - 1.0);
|
||||
if(modIndex > RADIOLIB_SX128X_BLE_GFSK_MOD_IND_4_00) {
|
||||
uint8_t modInd = (uint8_t)((8.0 * (newFreqDev / (float)this->bitRateKbps)) - 1.0);
|
||||
if(modInd > RADIOLIB_SX128X_BLE_GFSK_MOD_IND_4_00) {
|
||||
return(RADIOLIB_ERR_INVALID_MODULATION_PARAMETERS);
|
||||
}
|
||||
|
||||
// update modulation parameters
|
||||
this->modIndex = modIndex;
|
||||
this->modIndex = modInd;
|
||||
return(setModulationParams(this->bitRate, this->modIndex, this->shaping));
|
||||
}
|
||||
|
||||
|
|
@ -928,7 +964,7 @@ int16_t SX128x::setDataShaping(uint8_t sh) {
|
|||
}
|
||||
}
|
||||
|
||||
int16_t SX128x::setSyncWord(uint8_t* syncWord, uint8_t len) {
|
||||
int16_t SX128x::setSyncWord(const uint8_t* syncWord, uint8_t len) {
|
||||
// check active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(!((modem == RADIOLIB_SX128X_PACKET_TYPE_GFSK) || (modem == RADIOLIB_SX128X_PACKET_TYPE_FLRC))) {
|
||||
|
|
@ -1225,7 +1261,7 @@ size_t SX128x::getPacketLength(bool update) {
|
|||
return((size_t)rxBufStatus[0]);
|
||||
}
|
||||
|
||||
uint32_t SX128x::getTimeOnAir(size_t len) {
|
||||
RadioLibTime_t SX128x::getTimeOnAir(size_t len) {
|
||||
// check active modem
|
||||
uint8_t modem = getPacketType();
|
||||
if(modem == RADIOLIB_SX128X_PACKET_TYPE_LORA) {
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ class SX128x: public PhysicalLayer {
|
|||
\brief Default constructor.
|
||||
\param mod Instance of Module that will be used to communicate with the radio.
|
||||
*/
|
||||
SX128x(Module* mod);
|
||||
explicit SX128x(Module* mod);
|
||||
|
||||
// basic methods
|
||||
|
||||
|
|
@ -455,7 +455,7 @@ class SX128x: public PhysicalLayer {
|
|||
\brief Performs scan for LoRa transmission in the current channel. Detects both preamble and payload.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t scanChannel();
|
||||
int16_t scanChannel() override;
|
||||
|
||||
/*!
|
||||
\brief Sets the module to sleep mode. To wake the device up, call standby().
|
||||
|
|
@ -497,23 +497,23 @@ class SX128x: public PhysicalLayer {
|
|||
\brief Sets interrupt service routine to call when a packet is received.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketReceivedAction(void (*func)(void));
|
||||
void setPacketReceivedAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is received.
|
||||
*/
|
||||
void clearPacketReceivedAction();
|
||||
void clearPacketReceivedAction() override;
|
||||
|
||||
/*!
|
||||
\brief Sets interrupt service routine to call when a packet is sent.
|
||||
\param func ISR to call.
|
||||
*/
|
||||
void setPacketSentAction(void (*func)(void));
|
||||
void setPacketSentAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Clears interrupt service routine to call when a packet is sent.
|
||||
*/
|
||||
void clearPacketSentAction();
|
||||
void clearPacketSentAction() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven binary transmit method.
|
||||
|
|
@ -537,7 +537,7 @@ class SX128x: public PhysicalLayer {
|
|||
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive();
|
||||
int16_t startReceive() override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven receive method. DIO1 will be activated when full packet is received.
|
||||
|
|
@ -551,7 +551,7 @@ class SX128x: public PhysicalLayer {
|
|||
\param len Only for PhysicalLayer compatibility, not used.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startReceive(uint16_t timeout, uint16_t irqFlags = RADIOLIB_SX128X_IRQ_RX_DEFAULT, uint16_t irqMask = RADIOLIB_SX128X_IRQ_RX_DONE, size_t len = 0);
|
||||
int16_t startReceive(uint16_t timeout, uint32_t irqFlags = RADIOLIB_SX128X_IRQ_RX_DEFAULT, uint32_t irqMask = RADIOLIB_SX128X_IRQ_RX_DONE, size_t len = 0);
|
||||
|
||||
/*!
|
||||
\brief Reads the current IRQ status.
|
||||
|
|
@ -568,6 +568,19 @@ class SX128x: public PhysicalLayer {
|
|||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t readData(uint8_t* data, size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Interrupt-driven channel activity detection method. DIO1 will be activated
|
||||
when LoRa preamble is detected, or upon timeout. Defaults to CAD parameter values recommended by AN1200.48.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t startChannelScan() override;
|
||||
|
||||
/*!
|
||||
\brief Read the channel scan result
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t getChannelScanResult() override;
|
||||
|
||||
// configuration methods
|
||||
|
||||
|
|
@ -576,7 +589,7 @@ class SX128x: public PhysicalLayer {
|
|||
\param freq Carrier frequency to be set in MHz.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setFrequency(float freq);
|
||||
int16_t setFrequency(float freq) override;
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa bandwidth. Allowed values are 203.125, 406.25, 812.5 and 1625.0 kHz.
|
||||
|
|
@ -606,7 +619,15 @@ class SX128x: public PhysicalLayer {
|
|||
\param pwr Output power to be set in dBm.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setOutputPower(int8_t pwr);
|
||||
int16_t setOutputPower(int8_t pwr) override;
|
||||
|
||||
/*!
|
||||
\brief Check if output power is configurable.
|
||||
\param power Output power in dBm.
|
||||
\param clipped Clipped output power value to what is possible within the module's range.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t checkOutputPower(int8_t power, int8_t* clipped) override;
|
||||
|
||||
/*!
|
||||
\brief Sets preamble length for currently active modem. Allowed values range from 1 to 65535.
|
||||
|
|
@ -621,7 +642,7 @@ class SX128x: public PhysicalLayer {
|
|||
\param br FSK/FLRC bit rate to be set in kbps.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setBitRate(float br);
|
||||
int16_t setBitRate(float br) override;
|
||||
|
||||
/*!
|
||||
\brief Sets FSK frequency deviation. Allowed values range from 0.0 to 3200.0 kHz.
|
||||
|
|
@ -645,7 +666,7 @@ class SX128x: public PhysicalLayer {
|
|||
\param len Sync word length in bytes.
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t setSyncWord(uint8_t* syncWord, uint8_t len);
|
||||
int16_t setSyncWord(const uint8_t* syncWord, uint8_t len);
|
||||
|
||||
/*!
|
||||
\brief Sets LoRa sync word.
|
||||
|
|
@ -696,13 +717,13 @@ class SX128x: public PhysicalLayer {
|
|||
\brief Gets RSSI (Recorded Signal Strength Indicator) of the last received packet.
|
||||
\returns RSSI of the last received packet in dBm.
|
||||
*/
|
||||
float getRSSI();
|
||||
float getRSSI() override;
|
||||
|
||||
/*!
|
||||
\brief Gets SNR (Signal to Noise Ratio) of the last received packet. Only available for LoRa or ranging modem.
|
||||
\returns SNR of the last received packet in dB.
|
||||
*/
|
||||
float getSNR();
|
||||
float getSNR() override;
|
||||
|
||||
/*!
|
||||
\brief Gets frequency error of the latest received packet.
|
||||
|
|
@ -722,7 +743,7 @@ class SX128x: public PhysicalLayer {
|
|||
\param len Payload length in bytes.
|
||||
\returns Expected time-on-air in microseconds.
|
||||
*/
|
||||
uint32_t getTimeOnAir(size_t len);
|
||||
RadioLibTime_t getTimeOnAir(size_t len) override;
|
||||
|
||||
/*!
|
||||
\brief Set implicit header mode for future reception/transmission.
|
||||
|
|
@ -754,33 +775,33 @@ class SX128x: public PhysicalLayer {
|
|||
\brief Dummy random method, to ensure PhysicalLayer compatibility.
|
||||
\returns Always returns 0.
|
||||
*/
|
||||
uint8_t randomByte();
|
||||
uint8_t randomByte() override;
|
||||
|
||||
/*!
|
||||
\brief Enable/disable inversion of the I and Q signals
|
||||
\param enable QI inversion enabled (true) or disabled (false);
|
||||
\returns \ref status_codes
|
||||
*/
|
||||
int16_t invertIQ(bool enable);
|
||||
int16_t invertIQ(bool enable) override;
|
||||
|
||||
#if !RADIOLIB_EXCLUDE_DIRECT_RECEIVE
|
||||
/*!
|
||||
\brief Dummy method, to ensure PhysicalLayer compatibility.
|
||||
\param func Ignored.
|
||||
*/
|
||||
void setDirectAction(void (*func)(void));
|
||||
void setDirectAction(void (*func)(void)) override;
|
||||
|
||||
/*!
|
||||
\brief Dummy method, to ensure PhysicalLayer compatibility.
|
||||
\param pin Ignored.
|
||||
*/
|
||||
void readBit(uint32_t pin);
|
||||
void readBit(uint32_t pin) override;
|
||||
#endif
|
||||
|
||||
#if !RADIOLIB_GODMODE && !RADIOLIB_LOW_LEVEL
|
||||
protected:
|
||||
#endif
|
||||
Module* getMod();
|
||||
Module* getMod() override;
|
||||
|
||||
// cached LoRa parameters
|
||||
float bandwidthKhz = 0;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue