Merge pull request #649 from matthijskooijman/add-stm32wl
Add support for STM32WL integrated transceivers
This commit is contained in:
commit
7267e5ffc9
30 changed files with 1400 additions and 123 deletions
13
.github/workflows/main.yml
vendored
13
.github/workflows/main.yml
vendored
|
@ -27,7 +27,8 @@ jobs:
|
||||||
- esp8266:esp8266:generic
|
- esp8266:esp8266:generic
|
||||||
- Intel:arc32:arduino_101
|
- Intel:arc32:arduino_101
|
||||||
- SparkFun:apollo3:sfe_artemis
|
- SparkFun:apollo3:sfe_artemis
|
||||||
- STMicroelectronics:stm32:GenF3
|
- STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
|
||||||
|
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
|
||||||
- stm32duino:STM32F1:mapleMini
|
- stm32duino:STM32F1:mapleMini
|
||||||
- MegaCoreX:megaavr:4809
|
- MegaCoreX:megaavr:4809
|
||||||
- arduino:mbed_rp2040:pico
|
- arduino:mbed_rp2040:pico
|
||||||
|
@ -63,9 +64,9 @@ jobs:
|
||||||
id: prep
|
id: prep
|
||||||
run:
|
run:
|
||||||
|
|
|
|
||||||
# common settings - no extra options, skip nothing, all warnings
|
# common settings - no extra options, skip STM32WL examples, all warnings
|
||||||
echo "::set-output name=options::"
|
echo "::set-output name=options::"
|
||||||
echo "::set-output name=skip-pattern::''"
|
echo "::set-output name=skip-pattern::'STM32WL'"
|
||||||
echo "::set-output name=warnings::'all'"
|
echo "::set-output name=warnings::'all'"
|
||||||
|
|
||||||
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
|
# platform-dependent settings - extra board options, board index URLs, skip patterns etc.
|
||||||
|
@ -109,9 +110,13 @@ jobs:
|
||||||
|
|
||||||
elif [[ "${{ contains(matrix.board, 'STMicroelectronics:stm32') }}" == "true" ]]; then
|
elif [[ "${{ contains(matrix.board, 'STMicroelectronics:stm32') }}" == "true" ]]; then
|
||||||
# STM32 (official core)
|
# STM32 (official core)
|
||||||
echo "::set-output name=options:::pnum=BLACKPILL_F303CC"
|
|
||||||
echo "::set-output name=index-url::--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json"
|
echo "::set-output name=index-url::--additional-urls https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json"
|
||||||
|
|
||||||
|
if [[ "${{ contains(matrix.board, 'NUCLEO_WL55') }}" == "true" ]]; then
|
||||||
|
# Do *not* skip STM32WL examples
|
||||||
|
echo "::set-output name=skip-pattern::''"
|
||||||
|
fi
|
||||||
|
|
||||||
elif [[ "${{ contains(matrix.board, 'stm32duino:STM32F1') }}" == "true" ]]; then
|
elif [[ "${{ contains(matrix.board, 'stm32duino:STM32F1') }}" == "true" ]]; then
|
||||||
# STM32 (unofficial core)
|
# STM32 (unofficial core)
|
||||||
echo "::set-output name=options:::bootloader_version=original,cpu_speed=speed_72mhz"
|
echo "::set-output name=options:::bootloader_version=original,cpu_speed=speed_72mhz"
|
||||||
|
|
3
Doxyfile
3
Doxyfile
|
@ -2172,7 +2172,8 @@ INCLUDE_FILE_PATTERNS =
|
||||||
# recursively expanded use the := operator instead of the = operator.
|
# recursively expanded use the := operator instead of the = operator.
|
||||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||||
|
|
||||||
PREDEFINED = protected=private
|
PREDEFINED = protected=private \
|
||||||
|
DOXYGEN
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||||
# tag can be used to specify a list of macro names that should be expanded. The
|
# tag can be used to specify a list of macro names that should be expanded. The
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx Channel Activity Detection Example
|
||||||
|
|
||||||
|
This example uses STM32WLx to scan the current LoRa
|
||||||
|
channel and detect ongoing LoRa transmissions.
|
||||||
|
Unlike SX127x CAD, SX126x/STM32WLx can detect any part
|
||||||
|
of LoRa transmission, not just the preamble.
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// initialize STM32WLx with default settings
|
||||||
|
Serial.print(F("[STM32WLx] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
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("[STM32WLx] 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,98 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx Channel Activity Detection Example
|
||||||
|
|
||||||
|
This example uses STM32WLx to scan the current LoRa
|
||||||
|
channel and detect ongoing LoRa transmissions.
|
||||||
|
Unlike SX127x CAD, SX126x/STM32WLx can detect any part
|
||||||
|
of LoRa transmission, not just the preamble.
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// initialize STM32WLx with default settings
|
||||||
|
Serial.print(F("[STM32WLx] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
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("[STM32WLx] 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!
|
||||||
|
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("[STM32WLx] Packet detected!"));
|
||||||
|
|
||||||
|
} else if (state == RADIOLIB_CHANNEL_FREE) {
|
||||||
|
// channel is free
|
||||||
|
Serial.println(F("[STM32WLx] Channel is free!"));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// some other error occurred
|
||||||
|
Serial.print(F("[STM32WLx] Failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// start scanning the channel again
|
||||||
|
Serial.print(F("[STM32WLx] 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
124
examples/STM32WLx/STM32WLx_Receive/STM32WLx_Receive.ino
Normal file
124
examples/STM32WLx/STM32WLx_Receive/STM32WLx_Receive.ino
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx Receive Example
|
||||||
|
|
||||||
|
This example listens for LoRa transmissions using STM32WL MCU with
|
||||||
|
integrated (SX126x) LoRa radio.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||||
|
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||||
|
RF switch control may have to be adjusted.
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
// set RF switch configuration for Nucleo WL55JC1
|
||||||
|
// NOTE: other boards may be different!
|
||||||
|
static const RADIOLIB_PIN_TYPE rfswitch_pins[] =
|
||||||
|
{PC3, PC4, PC5};
|
||||||
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
|
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||||
|
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||||
|
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||||
|
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||||
|
STM32WLx::END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// set RF switch control configuration
|
||||||
|
// this has to be done prior to calling begin()
|
||||||
|
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
|
||||||
|
// initialize STM32WL with default settings, except frequency
|
||||||
|
Serial.print(F("[STM32WL] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
if (state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||||
|
state = radio.setTCXO(1.7);
|
||||||
|
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("[STM32WL] Waiting for incoming transmission ... "));
|
||||||
|
|
||||||
|
// you can receive data as an Arduino String
|
||||||
|
// NOTE: receive() is a blocking method!
|
||||||
|
// See example ReceiveInterrupt for details
|
||||||
|
// on non-blocking reception method.
|
||||||
|
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("[STM32WL] Data:\t\t"));
|
||||||
|
Serial.println(str);
|
||||||
|
|
||||||
|
// print the RSSI (Received Signal Strength Indicator)
|
||||||
|
// of the last received packet
|
||||||
|
Serial.print(F("[STM32WL] 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("[STM32WL] 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,158 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx 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
|
||||||
|
|
||||||
|
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||||
|
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||||
|
RF switch control may have to be adjusted.
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
// set RF switch configuration for Nucleo WL55JC1
|
||||||
|
// NOTE: other boards may be different!
|
||||||
|
static const RADIOLIB_PIN_TYPE rfswitch_pins[] =
|
||||||
|
{PC3, PC4, PC5};
|
||||||
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
|
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||||
|
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||||
|
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||||
|
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||||
|
STM32WLx::END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// set RF switch control configuration
|
||||||
|
// this has to be done prior to calling begin()
|
||||||
|
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
|
||||||
|
// initialize STM32WL with default settings, except frequency
|
||||||
|
Serial.print(F("[STM32WL] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
if (state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||||
|
state = radio.setTCXO(1.7);
|
||||||
|
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.setDio1Action(setFlag);
|
||||||
|
|
||||||
|
// start listening for LoRa packets
|
||||||
|
Serial.print(F("[STM32WL] 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.readData();
|
||||||
|
// radio.scanChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag to indicate that a packet was received
|
||||||
|
volatile bool receivedFlag = false;
|
||||||
|
|
||||||
|
// this function is called when a complete packet
|
||||||
|
// is received by the module
|
||||||
|
// IMPORTANT: this function MUST be 'void' type
|
||||||
|
// and MUST NOT have any arguments!
|
||||||
|
void setFlag(void) {
|
||||||
|
// we got a packet, set the flag
|
||||||
|
receivedFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// check if the flag is set
|
||||||
|
if(receivedFlag) {
|
||||||
|
// 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 state = radio.readData(byteArr, 8);
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (state == RADIOLIB_ERR_NONE) {
|
||||||
|
// packet was successfully received
|
||||||
|
Serial.println(F("[STM32WL] Received packet!"));
|
||||||
|
|
||||||
|
// print data of the packet
|
||||||
|
Serial.print(F("[STM32WL] Data:\t\t"));
|
||||||
|
Serial.println(str);
|
||||||
|
|
||||||
|
// print RSSI (Received Signal Strength Indicator)
|
||||||
|
Serial.print(F("[STM32WL] RSSI:\t\t"));
|
||||||
|
Serial.print(radio.getRSSI());
|
||||||
|
Serial.println(F(" dBm"));
|
||||||
|
|
||||||
|
// print SNR (Signal-to-Noise Ratio)
|
||||||
|
Serial.print(F("[STM32WL] 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// put module back to listen mode
|
||||||
|
radio.startReceive();
|
||||||
|
}
|
||||||
|
}
|
112
examples/STM32WLx/STM32WLx_Transmit/STM32WLx_Transmit.ino
Normal file
112
examples/STM32WLx/STM32WLx_Transmit/STM32WLx_Transmit.ino
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx Transmit Example
|
||||||
|
|
||||||
|
This example transmits packets using STM32WL MCU with integrated
|
||||||
|
(SX126x) LoRa radio.
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
|
||||||
|
or standalone STM32WL, some configuration such as TCXO voltage and
|
||||||
|
RF switch control may have to be adjusted.
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
// set RF switch configuration for Nucleo WL55JC1
|
||||||
|
// NOTE: other boards may be different!
|
||||||
|
static const RADIOLIB_PIN_TYPE rfswitch_pins[] =
|
||||||
|
{PC3, PC4, PC5};
|
||||||
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
|
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||||
|
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||||
|
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||||
|
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||||
|
STM32WLx::END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// set RF switch control configuration
|
||||||
|
// this has to be done prior to calling begin()
|
||||||
|
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
|
||||||
|
// initialize STM32WL with default settings, except frequency
|
||||||
|
Serial.print(F("[STM32WL] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
if (state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||||
|
state = radio.setTCXO(1.7);
|
||||||
|
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("[STM32WL] Transmitting packet ... "));
|
||||||
|
|
||||||
|
// you can transmit C-string or Arduino string up to
|
||||||
|
// 256 characters long
|
||||||
|
// NOTE: transmit() is a blocking method!
|
||||||
|
// See example STM32WLx_Transmit_Interrupt for details
|
||||||
|
// on non-blocking transmission method.
|
||||||
|
int state = radio.transmit("Hello World!");
|
||||||
|
|
||||||
|
// 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("[STM32WL] 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,140 @@
|
||||||
|
/*
|
||||||
|
RadioLib STM32WLx 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)
|
||||||
|
|
||||||
|
For default module settings, see the wiki page
|
||||||
|
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
|
||||||
|
|
||||||
|
For full API reference, see the GitHub Pages
|
||||||
|
https://jgromes.github.io/RadioLib/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// include the library
|
||||||
|
#include <RadioLib.h>
|
||||||
|
|
||||||
|
// no need to configure pins, signals are routed to the radio internally
|
||||||
|
STM32WLx radio = new STM32WLx_Module();
|
||||||
|
|
||||||
|
// set RF switch configuration for Nucleo WL55JC1
|
||||||
|
// NOTE: other boards may be different!
|
||||||
|
static const RADIOLIB_PIN_TYPE rfswitch_pins[] =
|
||||||
|
{PC3, PC4, PC5};
|
||||||
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
|
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
|
||||||
|
{STM32WLx::MODE_RX, {HIGH, HIGH, LOW}},
|
||||||
|
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
|
||||||
|
{STM32WLx::MODE_TX_HP, {HIGH, LOW, HIGH}},
|
||||||
|
STM32WLx::END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// save transmission state between loops
|
||||||
|
int transmissionState = RADIOLIB_ERR_NONE;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
|
||||||
|
// set RF switch control configuration
|
||||||
|
// this has to be done prior to calling begin()
|
||||||
|
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
|
||||||
|
// initialize STM32WL with default settings, except frequency
|
||||||
|
Serial.print(F("[STM32WL] Initializing ... "));
|
||||||
|
int state = radio.begin(868.0);
|
||||||
|
if (state == RADIOLIB_ERR_NONE) {
|
||||||
|
Serial.println(F("success!"));
|
||||||
|
} else {
|
||||||
|
Serial.print(F("failed, code "));
|
||||||
|
Serial.println(state);
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set appropriate TCXO voltage for Nucleo WL55JC1
|
||||||
|
state = radio.setTCXO(1.7);
|
||||||
|
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.setDio1Action(setFlag);
|
||||||
|
|
||||||
|
// start transmitting the first packet
|
||||||
|
Serial.print(F("[STM32WL] 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!
|
||||||
|
void setFlag(void) {
|
||||||
|
// we sent a packet, set the flag
|
||||||
|
transmittedFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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("[STM32WL] Sending another 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};
|
||||||
|
int state = radio.startTransmit(byteArr, 8);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,8 @@ SX1279 KEYWORD1
|
||||||
SX1280 KEYWORD1
|
SX1280 KEYWORD1
|
||||||
SX1281 KEYWORD1
|
SX1281 KEYWORD1
|
||||||
SX1282 KEYWORD1
|
SX1282 KEYWORD1
|
||||||
|
STM32WLx KEYWORD1
|
||||||
|
STM32WLx_Module KEYWORD1
|
||||||
|
|
||||||
# protocols
|
# protocols
|
||||||
RTTYClient KEYWORD1
|
RTTYClient KEYWORD1
|
||||||
|
@ -70,7 +72,7 @@ PasokonP7 KEYWORD1
|
||||||
# RadioLib
|
# RadioLib
|
||||||
ModuleA KEYWORD2
|
ModuleA KEYWORD2
|
||||||
ModuleB KEYWORD2
|
ModuleB KEYWORD2
|
||||||
Module KEYWORD2
|
setRfSwitchTable KEYWORD2
|
||||||
|
|
||||||
# SX127x/RFM9x + RF69 + CC1101
|
# SX127x/RFM9x + RF69 + CC1101
|
||||||
begin KEYWORD2
|
begin KEYWORD2
|
||||||
|
@ -256,6 +258,7 @@ setInterruptSetup KEYWORD2
|
||||||
|
|
||||||
RADIOLIB_NC LITERAL1
|
RADIOLIB_NC LITERAL1
|
||||||
RADIOLIB_VERSION LITERAL1
|
RADIOLIB_VERSION LITERAL1
|
||||||
|
RADIOLIB_PIN_TYPE LITERAL1
|
||||||
|
|
||||||
RADIOLIB_SHAPING_NONE LITERAL1
|
RADIOLIB_SHAPING_NONE LITERAL1
|
||||||
RADIOLIB_SHAPING_0_3 LITERAL1
|
RADIOLIB_SHAPING_0_3 LITERAL1
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
//#define RADIOLIB_EXCLUDE_SX127X
|
//#define RADIOLIB_EXCLUDE_SX127X
|
||||||
//#define RADIOLIB_EXCLUDE_RFM9X // dependent on RADIOLIB_EXCLUDE_SX127X
|
//#define RADIOLIB_EXCLUDE_RFM9X // dependent on RADIOLIB_EXCLUDE_SX127X
|
||||||
//#define RADIOLIB_EXCLUDE_SX126X
|
//#define RADIOLIB_EXCLUDE_SX126X
|
||||||
|
//#define RADIOLIB_EXCLUDE_STM32WLX // dependent on RADIOLIB_EXCLUDE_SX126X
|
||||||
//#define RADIOLIB_EXCLUDE_SX128X
|
//#define RADIOLIB_EXCLUDE_SX128X
|
||||||
//#define RADIOLIB_EXCLUDE_AFSK
|
//#define RADIOLIB_EXCLUDE_AFSK
|
||||||
//#define RADIOLIB_EXCLUDE_AX25
|
//#define RADIOLIB_EXCLUDE_AX25
|
||||||
|
@ -1009,6 +1010,13 @@
|
||||||
#define RADIOLIB_STATIC_ARRAY_SIZE (256)
|
#define RADIOLIB_STATIC_ARRAY_SIZE (256)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// This only compiles on STM32 boards with SUBGHZ module, but also
|
||||||
|
// include when generating docs
|
||||||
|
#if (!defined(ARDUINO_ARCH_STM32) || !defined(SUBGHZSPI_BASE)) && !defined(DOXYGEN)
|
||||||
|
#define RADIOLIB_EXCLUDE_STM32WLX
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(RADIOLIB_DEBUG)
|
#if defined(RADIOLIB_DEBUG)
|
||||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||||
#define RADIOLIB_DEBUG_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }
|
#define RADIOLIB_DEBUG_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }
|
||||||
|
|
|
@ -551,20 +551,50 @@ void Module::regdump(uint8_t start, uint8_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_useRfSwitch = true;
|
// This can be on the stack, setRfSwitchTable copies the contents
|
||||||
_rxEn = rxEn;
|
const RADIOLIB_PIN_TYPE pins[] = {
|
||||||
_txEn = txEn;
|
rxEn, txEn, RADIOLIB_NC,
|
||||||
this->pinMode(rxEn, OUTPUT);
|
};
|
||||||
this->pinMode(txEn, OUTPUT);
|
// This must be static, since setRfSwitchTable stores a reference.
|
||||||
|
static constexpr RfSwitchMode_t table[] = {
|
||||||
|
{MODE_IDLE, {LOW, LOW}},
|
||||||
|
{MODE_RX, {HIGH, LOW}},
|
||||||
|
{MODE_TX, {LOW, HIGH}},
|
||||||
|
END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
setRfSwitchTable(pins, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState) {
|
void Module::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[3], const RfSwitchMode_t table[]) {
|
||||||
// check RF switch control is enabled
|
memcpy(_rfSwitchPins, pins, sizeof(_rfSwitchPins));
|
||||||
if(!_useRfSwitch) {
|
_rfSwitchTable = table;
|
||||||
|
for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++)
|
||||||
|
this->pinMode(pins[i], OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Module::RfSwitchMode_t *Module::findRfSwitchMode(uint8_t mode) const {
|
||||||
|
const RfSwitchMode_t *row = _rfSwitchTable;
|
||||||
|
while (row && row->mode != MODE_END_OF_TABLE) {
|
||||||
|
if (row->mode == mode)
|
||||||
|
return row;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::setRfSwitchState(uint8_t mode) {
|
||||||
|
const RfSwitchMode_t *row = findRfSwitchMode(mode);
|
||||||
|
if(!row) {
|
||||||
|
// RF switch control is disabled or does not have this mode
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set pins
|
// set pins
|
||||||
this->digitalWrite(_rxEn, rxPinState);
|
const RADIOLIB_PIN_STATUS *value = &row->values[0];
|
||||||
this->digitalWrite(_txEn, txPinState);
|
for(size_t i = 0; i < RFSWITCH_MAX_PINS; i++) {
|
||||||
|
RADIOLIB_PIN_TYPE pin = _rfSwitchPins[i];
|
||||||
|
if (pin != RADIOLIB_NC)
|
||||||
|
this->digitalWrite(pin, *value);
|
||||||
|
++value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
149
src/Module.h
149
src/Module.h
|
@ -15,6 +15,54 @@
|
||||||
*/
|
*/
|
||||||
class Module {
|
class Module {
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
* \brief The maximum number of pins supported by the RF switch
|
||||||
|
* code.
|
||||||
|
*
|
||||||
|
* Note: It is not recommended to use this constant in your sketch
|
||||||
|
* when defining a rfswitch pins array, to prevent issues when this
|
||||||
|
* value is ever increased and such an array gets extra zero
|
||||||
|
* elements (that will be interpreted as pin 0).
|
||||||
|
*/
|
||||||
|
static const size_t RFSWITCH_MAX_PINS = 3;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Description of RF switch pin states for a single mode.
|
||||||
|
*
|
||||||
|
* See setRfSwitchTable() for details.
|
||||||
|
*/
|
||||||
|
struct RfSwitchMode_t {
|
||||||
|
uint8_t mode;
|
||||||
|
RADIOLIB_PIN_STATUS 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 {
|
||||||
|
/*! 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 */
|
||||||
|
MODE_IDLE,
|
||||||
|
/*! Receive mode */
|
||||||
|
MODE_RX,
|
||||||
|
/*! Transmission mode */
|
||||||
|
MODE_TX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Value to use as the last element in a mode table to indicate the
|
||||||
|
* end of the table.
|
||||||
|
*
|
||||||
|
* See setRfSwitchTable() for details.
|
||||||
|
*/
|
||||||
|
static constexpr RfSwitchMode_t END_OF_MODE_TABLE = {MODE_END_OF_TABLE, {}};
|
||||||
|
|
||||||
#if defined(RADIOLIB_BUILD_ARDUINO)
|
#if defined(RADIOLIB_BUILD_ARDUINO)
|
||||||
|
|
||||||
|
@ -242,23 +290,103 @@ class Module {
|
||||||
RADIOLIB_PIN_TYPE getGpio() const { return(_gpio); }
|
RADIOLIB_PIN_TYPE getGpio() const { return(_gpio); }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
\brief Some modules contain external RF switch controlled by pins.
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
This function gives RadioLib control over those pins to
|
||||||
|
automatically switch between various modes: When idle both pins
|
||||||
|
will be LOW, during TX the `txEn` pin will be HIGH, during RX the
|
||||||
|
`rxPin` will be HIGH.
|
||||||
|
|
||||||
|
Radiolib will automatically set the pin mode and value of these
|
||||||
|
pins, so do not control them from the sketch.
|
||||||
|
|
||||||
|
When more than two pins or more control over the output values are
|
||||||
|
needed, use the setRfSwitchTable() function.
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
\param rxEn RX enable pin.
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
\param txEn TX enable pin.
|
||||||
*/
|
*/
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Set RF switch state.
|
\brief Some modules contain external RF switch controlled by pins.
|
||||||
|
This function gives RadioLib control over those pins to
|
||||||
|
automatically switch between various modes.
|
||||||
|
|
||||||
\param rxPinState Pin state to set on Tx enable pin (usually high to transmit).
|
Radiolib will automatically set the pin mode and value of these
|
||||||
|
pins, so do not control them from the sketch.
|
||||||
|
|
||||||
\param txPinState Pin state to set on Rx enable pin (usually high to receive).
|
|
||||||
|
\param pins A reference to an array of pins to control. This
|
||||||
|
should always be an array of 3 elements. If you need less pins,
|
||||||
|
use RADIOLIB_NC for the unused elements.
|
||||||
|
|
||||||
|
\param table A reference to an array of pin values to use for each
|
||||||
|
supported mode. Each element is an RfSwitchMode_T struct that
|
||||||
|
lists the mode for which it applies and the values for each of the
|
||||||
|
pins passed in the pins argument respectively.
|
||||||
|
|
||||||
|
The `pins` array will be copied into the Module object, so the
|
||||||
|
original array can be deallocated after this call. However,
|
||||||
|
a reference to the `table` array will be stored, so that array
|
||||||
|
must remain valid as long RadioLib is being used.
|
||||||
|
|
||||||
|
The `mode` field in each table row should normally use any of the
|
||||||
|
`MODE_*` constants from the Module::OpMode_t enum. However, some
|
||||||
|
radios support additional modes and will define their own OpMode_t
|
||||||
|
enum.
|
||||||
|
|
||||||
|
The length of the table is variable (to support radios that add
|
||||||
|
additional modes), so the table must always be terminated with the
|
||||||
|
special END_OF_MODE_TABLE value.
|
||||||
|
|
||||||
|
Normally all modes should be listed in the table, but for some
|
||||||
|
radios, modes can be omitted to indicate they are not supported
|
||||||
|
(e.g. when a radio has a high power and low power TX mode but
|
||||||
|
external circuitry only supports low power). If applicable, this
|
||||||
|
is documented in the radio class itself.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
For example, on a board that has an RF switch with an enable pin
|
||||||
|
connected to PA0 and a TX/RX select pin connected to PA1:
|
||||||
|
|
||||||
|
\code
|
||||||
|
// In global scope, define the pin array and mode table
|
||||||
|
static const RADIOLIB_PIN_TYPE rfswitch_pins[] =
|
||||||
|
{PA0, PA1, RADIOLIB_NC};
|
||||||
|
static const Module::RfSwitchMode_t rfswitch_table[] = {
|
||||||
|
{Module::MODE_IDLE, {LOW, LOW}},
|
||||||
|
{Module::MODE_RX, {HIGH, LOW}},
|
||||||
|
{Module::MODE_TX, {HIGH, HIGH}},
|
||||||
|
Module::END_OF_MODE_TABLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
...
|
||||||
|
// Then somewhere in setup, pass them to radiolib
|
||||||
|
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
|
||||||
|
...
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
*/
|
*/
|
||||||
void setRfSwitchState(RADIOLIB_PIN_STATUS rxPinState, RADIOLIB_PIN_STATUS txPinState);
|
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[RFSWITCH_MAX_PINS], const RfSwitchMode_t table[]);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find a mode in the RfSwitchTable.
|
||||||
|
*
|
||||||
|
* \param 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.
|
||||||
|
*/
|
||||||
|
const RfSwitchMode_t *findRfSwitchMode(uint8_t mode) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Set RF switch state.
|
||||||
|
\param mode The mode to set. This must be one of the MODE_ constants, or a radio-specific constant.
|
||||||
|
*/
|
||||||
|
void setRfSwitchState(uint8_t mode);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Wait for time to elapse, either using the microsecond timer, or the TimerFlag.
|
\brief Wait for time to elapse, either using the microsecond timer, or the TimerFlag.
|
||||||
|
@ -446,10 +574,9 @@ class Module {
|
||||||
bool _initInterface = false;
|
bool _initInterface = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// RF switch presence and pins
|
// RF switch pins and table
|
||||||
bool _useRfSwitch = false;
|
RADIOLIB_PIN_TYPE _rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
|
||||||
RADIOLIB_PIN_TYPE _rxEn = RADIOLIB_NC;
|
const RfSwitchMode_t *_rfSwitchTable = nullptr;
|
||||||
RADIOLIB_PIN_TYPE _txEn = RADIOLIB_NC;
|
|
||||||
|
|
||||||
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
#if defined(RADIOLIB_INTERRUPT_TIMING)
|
||||||
uint32_t _prevTimingLen = 0;
|
uint32_t _prevTimingLen = 0;
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
#include "modules/SX126x/SX1261.h"
|
#include "modules/SX126x/SX1261.h"
|
||||||
#include "modules/SX126x/SX1262.h"
|
#include "modules/SX126x/SX1262.h"
|
||||||
#include "modules/SX126x/SX1268.h"
|
#include "modules/SX126x/SX1268.h"
|
||||||
|
#include "modules/SX126x/STM32WLx.h"
|
||||||
#include "modules/SX127x/SX1272.h"
|
#include "modules/SX127x/SX1272.h"
|
||||||
#include "modules/SX127x/SX1273.h"
|
#include "modules/SX127x/SX1273.h"
|
||||||
#include "modules/SX127x/SX1276.h"
|
#include "modules/SX127x/SX1276.h"
|
||||||
|
|
|
@ -162,7 +162,7 @@ int16_t CC1101::standby() {
|
||||||
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
return(RADIOLIB_ERR_NONE);
|
return(RADIOLIB_ERR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ int16_t CC1101::transmitDirectAsync(uint32_t frf) {
|
||||||
|
|
||||||
int16_t CC1101::transmitDirect(bool sync, uint32_t frf) {
|
int16_t CC1101::transmitDirect(bool sync, uint32_t frf) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
if(frf != 0) {
|
if(frf != 0) {
|
||||||
|
@ -206,7 +206,7 @@ int16_t CC1101::receiveDirectAsync() {
|
||||||
|
|
||||||
int16_t CC1101::receiveDirect(bool sync) {
|
int16_t CC1101::receiveDirect(bool sync) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// activate direct mode
|
// activate direct mode
|
||||||
int16_t state = directMode(sync);
|
int16_t state = directMode(sync);
|
||||||
|
@ -291,7 +291,7 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
dataSent += initialWrite;
|
dataSent += initialWrite;
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// set mode to transmit
|
// set mode to transmit
|
||||||
SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
|
SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
|
||||||
|
@ -344,7 +344,7 @@ int16_t CC1101::startReceive() {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to receive
|
// set mode to receive
|
||||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
||||||
|
@ -902,6 +902,10 @@ void CC1101::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CC1101::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t CC1101::randomByte() {
|
uint8_t CC1101::randomByte() {
|
||||||
// set mode to Rx
|
// set mode to Rx
|
||||||
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
|
||||||
|
|
|
@ -928,16 +928,12 @@ class CC1101: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int16_t setEncoding(uint8_t encoding) override;
|
int16_t setEncoding(uint8_t encoding) override;
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Get one truly random byte from RSSI noise.
|
\brief Get one truly random byte from RSSI noise.
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ int16_t RF69::receive(uint8_t* data, size_t len) {
|
||||||
|
|
||||||
int16_t RF69::sleep() {
|
int16_t RF69::sleep() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
// set module to sleep
|
// set module to sleep
|
||||||
return(setMode(RADIOLIB_RF69_SLEEP));
|
return(setMode(RADIOLIB_RF69_SLEEP));
|
||||||
|
@ -167,7 +167,7 @@ int16_t RF69::sleep() {
|
||||||
|
|
||||||
int16_t RF69::standby() {
|
int16_t RF69::standby() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
// set module to standby
|
// set module to standby
|
||||||
return(setMode(RADIOLIB_RF69_STANDBY));
|
return(setMode(RADIOLIB_RF69_STANDBY));
|
||||||
|
@ -175,7 +175,7 @@ int16_t RF69::standby() {
|
||||||
|
|
||||||
int16_t RF69::transmitDirect(uint32_t frf) {
|
int16_t RF69::transmitDirect(uint32_t frf) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
if(frf != 0) {
|
if(frf != 0) {
|
||||||
|
@ -196,7 +196,7 @@ int16_t RF69::transmitDirect(uint32_t frf) {
|
||||||
|
|
||||||
int16_t RF69::receiveDirect() {
|
int16_t RF69::receiveDirect() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// activate direct mode
|
// activate direct mode
|
||||||
int16_t state = directMode();
|
int16_t state = directMode();
|
||||||
|
@ -254,7 +254,7 @@ int16_t RF69::startReceive() {
|
||||||
clearIRQFlags();
|
clearIRQFlags();
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to receive
|
// set mode to receive
|
||||||
state = _mod->SPIsetRegValue(RADIOLIB_RF69_REG_OCP, RADIOLIB_RF69_OCP_ON | RADIOLIB_RF69_OCP_TRIM);
|
state = _mod->SPIsetRegValue(RADIOLIB_RF69_REG_OCP, RADIOLIB_RF69_OCP_ON | RADIOLIB_RF69_OCP_TRIM);
|
||||||
|
@ -414,7 +414,7 @@ int16_t RF69::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// set mode to transmit
|
// set mode to transmit
|
||||||
state = setMode(RADIOLIB_RF69_TX);
|
state = setMode(RADIOLIB_RF69_TX);
|
||||||
|
@ -916,6 +916,10 @@ void RF69::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RF69::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t RF69::randomByte() {
|
uint8_t RF69::randomByte() {
|
||||||
// set mode to Rx
|
// set mode to Rx
|
||||||
setMode(RADIOLIB_RF69_RX);
|
setMode(RADIOLIB_RF69_RX);
|
||||||
|
|
|
@ -1010,16 +1010,12 @@ class RF69: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int16_t setRSSIThreshold(float dbm);
|
int16_t setRSSIThreshold(float dbm);
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Get one truly random byte from RSSI noise.
|
\brief Get one truly random byte from RSSI noise.
|
||||||
|
|
||||||
|
|
106
src/modules/SX126x/STM32WLx.cpp
Normal file
106
src/modules/SX126x/STM32WLx.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2018 Jan Gromeš
|
||||||
|
Copyright (c) 2022 STMicroelectronics
|
||||||
|
|
||||||
|
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "STM32WLx.h"
|
||||||
|
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||||
|
|
||||||
|
#include <SubGhz.h>
|
||||||
|
|
||||||
|
STM32WLx::STM32WLx(STM32WLx_Module* mod) : SX1262(mod) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t STM32WLx::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t syncWord, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||||
|
// Execute common part
|
||||||
|
int16_t state = SX1262::begin(freq, bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// This overrides the value in SX126x::begin()
|
||||||
|
// On STM32WL, DIO2 is hardwired to the radio IRQ on the MCU, so it
|
||||||
|
// should really not be used as RfSwitch control output.
|
||||||
|
state = setDio2AsRfSwitch(false);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t STM32WLx::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t power, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) {
|
||||||
|
// Execute common part
|
||||||
|
int16_t state = SX1262::beginFSK(freq, br, freqDev, rxBw, power, preambleLength, tcxoVoltage, useRegulatorLDO);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// This overrides the value in SX126x::beginFSK()
|
||||||
|
// On STM32WL, DIO2 is hardwired to the radio IRQ on the MCU, so it
|
||||||
|
// should really not be used as RfSwitch control output.
|
||||||
|
state = setDio2AsRfSwitch(false);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t STM32WLx::setOutputPower(int8_t power) {
|
||||||
|
// get current OCP configuration
|
||||||
|
uint8_t ocp = 0;
|
||||||
|
int16_t state = readRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// Use HP only if available and needed for the requested power
|
||||||
|
bool hp_supported = _mod->findRfSwitchMode(MODE_TX_HP);
|
||||||
|
bool use_hp = power > 14 && hp_supported;
|
||||||
|
|
||||||
|
// set PA config.
|
||||||
|
if(use_hp) {
|
||||||
|
RADIOLIB_CHECK_RANGE(power, -9, 22, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||||
|
state = SX126x::setPaConfig(0x04, 0x00, 0x07); // HP output up to 22dBm
|
||||||
|
_tx_mode = MODE_TX_HP;
|
||||||
|
} else {
|
||||||
|
RADIOLIB_CHECK_RANGE(power, -17, 14, RADIOLIB_ERR_INVALID_OUTPUT_POWER);
|
||||||
|
state = SX126x::setPaConfig(0x04, 0x01, 0x00); // LP output up to 14dBm
|
||||||
|
_tx_mode = MODE_TX_LP;
|
||||||
|
}
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// Apply workaround for HP only
|
||||||
|
state = SX126x::fixPaClamping(use_hp);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// set output power
|
||||||
|
/// \todo power ramp time configuration
|
||||||
|
state = SX126x::setTxParams(power);
|
||||||
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
|
// restore OCP configuration
|
||||||
|
return(writeRegister(RADIOLIB_SX126X_REG_OCP_CONFIGURATION, &ocp, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t STM32WLx::clearIrqStatus(uint16_t clearIrqParams) {
|
||||||
|
int16_t res = SX126x::clearIrqStatus(clearIrqParams);
|
||||||
|
// The NVIC interrupt is level-sensitive, so clear away any pending
|
||||||
|
// flag that is only set because the radio IRQ status was not cleared
|
||||||
|
// in the interrupt (to prevent each IRQ triggering twice and allow
|
||||||
|
// reading the irq status through the pending flag).
|
||||||
|
SubGhz.clearPendingInterrupt();
|
||||||
|
if(SubGhz.hasInterrupt())
|
||||||
|
SubGhz.enableInterrupt();
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void STM32WLx::setDio1Action(void (*func)(void)) {
|
||||||
|
SubGhz.attachInterrupt([func]() {
|
||||||
|
// Because the interrupt is level-triggered, we disable it in the
|
||||||
|
// NVIC (otherwise we would need an SPI command to clear the IRQ in
|
||||||
|
// the radio, or it would trigger over and over again).
|
||||||
|
SubGhz.disableInterrupt();
|
||||||
|
func();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void STM32WLx::clearDio1Action() {
|
||||||
|
SubGhz.detachInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
139
src/modules/SX126x/STM32WLx.h
Normal file
139
src/modules/SX126x/STM32WLx.h
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2018 Jan Gromeš
|
||||||
|
Copyright (c) 2022 STMicroelectronics
|
||||||
|
|
||||||
|
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_RADIOLIB_STM32WLx_H)
|
||||||
|
#define _RADIOLIB_STM32WLx_H
|
||||||
|
|
||||||
|
#include "../../TypeDef.h"
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||||
|
|
||||||
|
#include "../../Module.h"
|
||||||
|
#include "SX1262.h"
|
||||||
|
#include "STM32WLx_Module.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class STM32WLx
|
||||||
|
|
||||||
|
\brief Derived class for STM32WL modules.
|
||||||
|
|
||||||
|
The radio integrated into these modules is essentially the same as the
|
||||||
|
Semtech %SX126x external radio chips, so most of the documentation for
|
||||||
|
those also applies here.
|
||||||
|
|
||||||
|
One notable difference with the %SX126x radios is that this radio
|
||||||
|
essentially combines the %SX1261 and %SX1262 by integrating both the
|
||||||
|
low-power (LP) and high-power (HP) amplifier. See setOutputPower() and
|
||||||
|
setRfSwitchTable() for details on how this is handled.
|
||||||
|
*/
|
||||||
|
class STM32WLx : public SX1262 {
|
||||||
|
// NOTE: This class could not be named STM32WL (or STM32WLxx), since
|
||||||
|
// those are macros defined by
|
||||||
|
// system/Drivers/CMSIS/Device/ST/STM32WLxxx/Include/stm32wlxx.h
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
\brief Default constructor.
|
||||||
|
|
||||||
|
\param mod Instance of STM32WLx_Module that will be used to communicate with the radio.
|
||||||
|
*/
|
||||||
|
STM32WLx(STM32WLx_Module* mod);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Custom operation modes for STMWLx.
|
||||||
|
*
|
||||||
|
* This splits the TX mode into two modes: Low-power and high-power.
|
||||||
|
* These constants can be used with the setRfSwitchTable() method,
|
||||||
|
* instead of the Module::OpMode_t constants.
|
||||||
|
*/
|
||||||
|
enum OpMode_t {
|
||||||
|
/*! End of table marker, use \ref END_OF_MODE_TABLE constant instead */
|
||||||
|
MODE_END_OF_TABLE = Module::MODE_END_OF_TABLE,
|
||||||
|
/*! Idle mode */
|
||||||
|
MODE_IDLE = Module::MODE_IDLE,
|
||||||
|
/*! Receive mode */
|
||||||
|
MODE_RX = Module::MODE_RX,
|
||||||
|
/*! Low power transmission mode */
|
||||||
|
MODE_TX_LP = Module::MODE_TX,
|
||||||
|
/*! High power transmission mode */
|
||||||
|
MODE_TX_HP,
|
||||||
|
};
|
||||||
|
/*! \copydoc Module::END_OF_MODE_TABLE */
|
||||||
|
static constexpr auto END_OF_MODE_TABLE = Module::END_OF_MODE_TABLE;
|
||||||
|
|
||||||
|
// basic methods
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\copydoc SX1262::begin
|
||||||
|
*/
|
||||||
|
int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\copydoc SX1262::beginFSK
|
||||||
|
*/
|
||||||
|
int16_t beginFSK(float freq = 434.0, float br = 4.8, float freqDev = 5.0, float rxBw = 156.2, int8_t power = 10, uint16_t preambleLength = 16, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
|
||||||
|
|
||||||
|
// configuration methods
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Sets output power. Allowed values are in range from -17 to 22 dBm.
|
||||||
|
|
||||||
|
This automatically switches between the low-power (LP) and high-power (HP) amplifier.
|
||||||
|
|
||||||
|
LP is preferred and supports -17 to +14dBm. When a higher power is
|
||||||
|
requested (or the LP amplifier is marked as unvailable using
|
||||||
|
setRfSwitchTable()), HP is used, which supports -9 to +22dBm.
|
||||||
|
|
||||||
|
\param power Output power to be set in dBm.
|
||||||
|
|
||||||
|
\returns \ref status_codes
|
||||||
|
*/
|
||||||
|
virtual int16_t setOutputPower(int8_t power) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\copybrief Module::setRfSwitchTable
|
||||||
|
|
||||||
|
This method works like Module::setRfSwitchTable(), except that you
|
||||||
|
should use STM32WLx::OpMode_t constants for modes, which
|
||||||
|
distinguishes between a low-power (LP) and high-power (HP) TX mode.
|
||||||
|
|
||||||
|
For boards that do not support both modes, just omit the
|
||||||
|
unsupported mode from the table and it will not be used (and the
|
||||||
|
valid power range is adjusted by setOutputPower() accordingly).
|
||||||
|
|
||||||
|
Note that the setRfSwitchTable() method should be called *before* the
|
||||||
|
begin() method, to ensure the radio knows which modes are supported
|
||||||
|
during initialization.
|
||||||
|
*/
|
||||||
|
// Note: This explicitly inherits this method only to override docs
|
||||||
|
using SX126x::setRfSwitchTable;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Sets interrupt service routine to call when DIO1/2/3 activates.
|
||||||
|
|
||||||
|
\param func ISR to call.
|
||||||
|
*/
|
||||||
|
void setDio1Action(void (*func)(void));
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\brief Clears interrupt service routine to call when DIO1/2/3 activates.
|
||||||
|
*/
|
||||||
|
void clearDio1Action();
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_GODMODE)
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
virtual int16_t clearIrqStatus(uint16_t clearIrqParams) override;
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_GODMODE)
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(RADIOLIB_EXCLUDE_SX126X)
|
||||||
|
|
||||||
|
#endif // _RADIOLIB_STM32WLX_MODULE_H
|
108
src/modules/SX126x/STM32WLx_Module.cpp
Normal file
108
src/modules/SX126x/STM32WLx_Module.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2022 STMicroelectronics
|
||||||
|
|
||||||
|
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "STM32WLx_Module.h"
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||||
|
|
||||||
|
#include <SubGhz.h>
|
||||||
|
|
||||||
|
// This defines some dummy pin numbers (starting at NUM_DIGITAL_PINS to
|
||||||
|
// guarantee these are not valid regular pin numbers) that can be passed
|
||||||
|
// to the parent Module class, to be stored here and then passed back to
|
||||||
|
// the overridden callbacks when these are used.
|
||||||
|
enum {
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS = NUM_DIGITAL_PINS,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
STM32WLx_Module::STM32WLx_Module():
|
||||||
|
Module(
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET,
|
||||||
|
RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY,
|
||||||
|
SubGhz.SPI,
|
||||||
|
SubGhz.spi_settings
|
||||||
|
)
|
||||||
|
{
|
||||||
|
setCb_pinMode(virtualPinMode);
|
||||||
|
setCb_digitalWrite(virtualDigitalWrite);
|
||||||
|
setCb_digitalRead(virtualDigitalRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void STM32WLx_Module::virtualPinMode(uint32_t dwPin, uint32_t dwMode) {
|
||||||
|
switch(dwPin) {
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||||
|
// Nothing to do
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
::pinMode(dwPin, dwMode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void STM32WLx_Module::virtualDigitalWrite(uint32_t dwPin, uint32_t dwVal) {
|
||||||
|
switch (dwPin) {
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||||
|
SubGhz.setNssActive(dwVal == LOW);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||||
|
SubGhz.setResetActive(dwVal == LOW);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||||
|
// Should not (and cannot) be written, just ignore
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
::digitalWrite(dwPin, dwVal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int STM32WLx_Module::virtualDigitalRead(uint32_t ulPin) {
|
||||||
|
switch (ulPin) {
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_BUSY:
|
||||||
|
return(SubGhz.isBusy() ? HIGH : LOW);
|
||||||
|
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_IRQ:
|
||||||
|
// We cannot use the radio IRQ output directly, but since:
|
||||||
|
// - the pending flag will be set whenever the IRQ output is set,
|
||||||
|
// and
|
||||||
|
// - the pending flag will be cleared (by
|
||||||
|
// STM32WLx::clearIrqStatus()) whenever the radio IRQ output is
|
||||||
|
// cleared,
|
||||||
|
// the pending flag should always reflect the current radio IRQ
|
||||||
|
// output. There is one exception: when the ISR starts the pending
|
||||||
|
// flag is cleared by hardware and not set again until after the
|
||||||
|
// ISR finishes, so the value is incorrect *inside* the ISR, but
|
||||||
|
// running RadioLib code inside the ISR (especially code that
|
||||||
|
// polls the IRQ flag) is not supported and probably broken in
|
||||||
|
// other ways too.
|
||||||
|
return(SubGhz.isInterruptPending() ? HIGH : LOW);
|
||||||
|
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_NSS:
|
||||||
|
return(SubGhz.isNssActive() ? LOW : HIGH);
|
||||||
|
|
||||||
|
case RADIOLIB_STM32WLx_VIRTUAL_PIN_RESET:
|
||||||
|
return(SubGhz.isResetActive() ? LOW : HIGH);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return(::digitalRead(ulPin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
49
src/modules/SX126x/STM32WLx_Module.h
Normal file
49
src/modules/SX126x/STM32WLx_Module.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2022 STMicroelectronics
|
||||||
|
|
||||||
|
This file is licensed under the MIT License: https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_RADIOLIB_STM32WLX_MODULE_H)
|
||||||
|
#define _RADIOLIB_STM32WLX_MODULE_H
|
||||||
|
|
||||||
|
#include "../../TypeDef.h"
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||||
|
|
||||||
|
#include "../../Module.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \class STM32WLx_Module
|
||||||
|
*
|
||||||
|
* This is a subclass of Module to be used with the STM32WLx driver.
|
||||||
|
*
|
||||||
|
* It is used to override some callbacks, allowing access to some of the
|
||||||
|
* radio control signals that are wired to internal registers instead of
|
||||||
|
* actual GPIO pins.
|
||||||
|
*/
|
||||||
|
class STM32WLx_Module : public Module {
|
||||||
|
// Note: We cannot easily override any methods here, since most calls
|
||||||
|
// are non-virtual and made through a Module*, so they would not be
|
||||||
|
// calling any overridden methods. This means this class works by
|
||||||
|
// overriding some of the callbacks in its constructor.
|
||||||
|
|
||||||
|
public:
|
||||||
|
STM32WLx_Module();
|
||||||
|
|
||||||
|
#if !defined(RADIOLIB_GODMODE)
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Replacement callbacks to handle virtual pins. These are static,
|
||||||
|
// since they replace global functions that cannot take any this
|
||||||
|
// pointer for context.
|
||||||
|
static void virtualPinMode(uint32_t dwPin, uint32_t dwMode);
|
||||||
|
static void virtualDigitalWrite(uint32_t dwPin, uint32_t dwVal);
|
||||||
|
static int virtualDigitalRead(uint32_t ulPin);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !defined(RADIOLIB_EXCLUDE_STM32WLX)
|
||||||
|
|
||||||
|
#endif // _RADIOLIB_STM32WLX_MODULE_H
|
|
@ -20,10 +20,10 @@ int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
|
||||||
state = setFrequency(freq);
|
state = setFrequency(freq);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
state = setOutputPower(power);
|
state = SX126x::fixPaClamping();
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
state = SX126x::fixPaClamping();
|
state = setOutputPower(power);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
return(state);
|
return(state);
|
||||||
|
@ -38,10 +38,10 @@ int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
|
||||||
state = setFrequency(freq);
|
state = setFrequency(freq);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
state = setOutputPower(power);
|
state = SX126x::fixPaClamping();
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
state = SX126x::fixPaClamping();
|
state = setOutputPower(power);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
return(state);
|
return(state);
|
||||||
|
|
|
@ -299,7 +299,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
|
||||||
|
|
||||||
int16_t SX126x::transmitDirect(uint32_t frf) {
|
int16_t SX126x::transmitDirect(uint32_t frf) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(_tx_mode);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
int16_t state = RADIOLIB_ERR_NONE;
|
int16_t state = RADIOLIB_ERR_NONE;
|
||||||
|
@ -315,7 +315,7 @@ int16_t SX126x::transmitDirect(uint32_t frf) {
|
||||||
|
|
||||||
int16_t SX126x::receiveDirect() {
|
int16_t SX126x::receiveDirect() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// SX126x is unable to output received data directly
|
// SX126x is unable to output received data directly
|
||||||
return(RADIOLIB_ERR_UNKNOWN);
|
return(RADIOLIB_ERR_UNKNOWN);
|
||||||
|
@ -337,7 +337,7 @@ int16_t SX126x::scanChannel(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin)
|
||||||
|
|
||||||
int16_t SX126x::sleep(bool retainConfig) {
|
int16_t SX126x::sleep(bool retainConfig) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
uint8_t sleepMode = RADIOLIB_SX126X_SLEEP_START_WARM | RADIOLIB_SX126X_SLEEP_RTC_OFF;
|
uint8_t sleepMode = RADIOLIB_SX126X_SLEEP_START_WARM | RADIOLIB_SX126X_SLEEP_RTC_OFF;
|
||||||
if(!retainConfig) {
|
if(!retainConfig) {
|
||||||
|
@ -357,7 +357,7 @@ int16_t SX126x::standby() {
|
||||||
|
|
||||||
int16_t SX126x::standby(uint8_t mode) {
|
int16_t SX126x::standby(uint8_t mode) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
uint8_t data[] = {mode};
|
uint8_t data[] = {mode};
|
||||||
return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_STANDBY, data, 1));
|
return(SPIwriteCommand(RADIOLIB_SX126X_CMD_SET_STANDBY, data, 1));
|
||||||
|
@ -418,7 +418,7 @@ int16_t SX126x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(_tx_mode);
|
||||||
|
|
||||||
// start transmission
|
// start transmission
|
||||||
state = setTx(RADIOLIB_SX126X_TX_TIMEOUT_NONE);
|
state = setTx(RADIOLIB_SX126X_TX_TIMEOUT_NONE);
|
||||||
|
@ -445,7 +445,7 @@ int16_t SX126x::startReceive(uint32_t timeout) {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to receive
|
// set mode to receive
|
||||||
state = setRx(timeout);
|
state = setRx(timeout);
|
||||||
|
@ -600,7 +600,7 @@ int16_t SX126x::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set DIO pin mapping
|
// set DIO pin mapping
|
||||||
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE, RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE);
|
state = setDioIrqParams(RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE, RADIOLIB_SX126X_IRQ_CAD_DETECTED | RADIOLIB_SX126X_IRQ_CAD_DONE);
|
||||||
|
@ -1199,6 +1199,10 @@ void SX126x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SX126x::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
int16_t SX126x::forceLDRO(bool enable) {
|
int16_t SX126x::forceLDRO(bool enable) {
|
||||||
// check active modem
|
// check active modem
|
||||||
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
|
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
|
||||||
|
@ -1571,7 +1575,7 @@ int16_t SX126x::fixSensitivity() {
|
||||||
return(writeRegister(RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1));
|
return(writeRegister(RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t SX126x::fixPaClamping() {
|
int16_t SX126x::fixPaClamping(bool enable) {
|
||||||
// fixes overly eager PA clamping
|
// fixes overly eager PA clamping
|
||||||
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for details
|
// see SX1262/SX1268 datasheet, chapter 15 Known Limitations, section 15.2 for details
|
||||||
|
|
||||||
|
@ -1580,8 +1584,12 @@ int16_t SX126x::fixPaClamping() {
|
||||||
int16_t state = readRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1);
|
int16_t state = readRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1);
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// update with the new value
|
// apply or undo workaround
|
||||||
|
if (enable)
|
||||||
clampConfig |= 0x1E;
|
clampConfig |= 0x1E;
|
||||||
|
else
|
||||||
|
clampConfig = (clampConfig & ~0x1E) | 0x08;
|
||||||
|
|
||||||
return(writeRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1));
|
return(writeRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -914,16 +914,12 @@ class SX126x: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int16_t setEncoding(uint8_t encoding) override;
|
int16_t setEncoding(uint8_t encoding) override;
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Forces LoRa low data rate optimization. Only available in LoRa mode. After calling this method, LDRO will always be set to
|
\brief Forces LoRa low data rate optimization. Only available in LoRa mode. After calling this method, LDRO will always be set to
|
||||||
the provided value, regardless of symbol length. To re-enable automatic LDRO configuration, call SX126x::autoLDRO()
|
the provided value, regardless of symbol length. To re-enable automatic LDRO configuration, call SX126x::autoLDRO()
|
||||||
|
@ -986,7 +982,7 @@ class SX126x: public PhysicalLayer {
|
||||||
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
|
int16_t writeBuffer(uint8_t* data, uint8_t numBytes, uint8_t offset = 0x00);
|
||||||
int16_t readBuffer(uint8_t* data, uint8_t numBytes);
|
int16_t readBuffer(uint8_t* data, uint8_t numBytes);
|
||||||
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX126X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX126X_IRQ_NONE);
|
int16_t setDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask = RADIOLIB_SX126X_IRQ_NONE, uint16_t dio3Mask = RADIOLIB_SX126X_IRQ_NONE);
|
||||||
int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
|
virtual int16_t clearIrqStatus(uint16_t clearIrqParams = RADIOLIB_SX126X_IRQ_ALL);
|
||||||
int16_t setRfFrequency(uint32_t frf);
|
int16_t setRfFrequency(uint32_t frf);
|
||||||
int16_t calibrateImage(uint8_t* data);
|
int16_t calibrateImage(uint8_t* data);
|
||||||
uint8_t getPacketType();
|
uint8_t getPacketType();
|
||||||
|
@ -1009,7 +1005,7 @@ class SX126x: public PhysicalLayer {
|
||||||
|
|
||||||
// fixes to errata
|
// fixes to errata
|
||||||
int16_t fixSensitivity();
|
int16_t fixSensitivity();
|
||||||
int16_t fixPaClamping();
|
int16_t fixPaClamping(bool enable = true);
|
||||||
int16_t fixImplicitTimeout();
|
int16_t fixImplicitTimeout();
|
||||||
int16_t fixInvertedIQ(uint8_t iqConfig);
|
int16_t fixInvertedIQ(uint8_t iqConfig);
|
||||||
|
|
||||||
|
@ -1047,6 +1043,9 @@ class SX126x: public PhysicalLayer {
|
||||||
|
|
||||||
int16_t _lastError = RADIOLIB_ERR_NONE;
|
int16_t _lastError = RADIOLIB_ERR_NONE;
|
||||||
|
|
||||||
|
// Allow subclasses to define different TX modes
|
||||||
|
uint8_t _tx_mode = Module::MODE_TX;
|
||||||
|
|
||||||
int16_t config(uint8_t modem);
|
int16_t config(uint8_t modem);
|
||||||
int16_t checkCommandResult();
|
int16_t checkCommandResult();
|
||||||
};
|
};
|
||||||
|
|
|
@ -275,7 +275,7 @@ int16_t SX127x::scanChannel() {
|
||||||
|
|
||||||
int16_t SX127x::sleep() {
|
int16_t SX127x::sleep() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
// set mode to sleep
|
// set mode to sleep
|
||||||
return(setMode(RADIOLIB_SX127X_SLEEP));
|
return(setMode(RADIOLIB_SX127X_SLEEP));
|
||||||
|
@ -283,7 +283,7 @@ int16_t SX127x::sleep() {
|
||||||
|
|
||||||
int16_t SX127x::standby() {
|
int16_t SX127x::standby() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
// set mode to standby
|
// set mode to standby
|
||||||
return(setMode(RADIOLIB_SX127X_STANDBY));
|
return(setMode(RADIOLIB_SX127X_STANDBY));
|
||||||
|
@ -296,7 +296,7 @@ int16_t SX127x::transmitDirect(uint32_t frf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
if(frf != 0) {
|
if(frf != 0) {
|
||||||
|
@ -325,7 +325,7 @@ int16_t SX127x::receiveDirect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// activate direct mode
|
// activate direct mode
|
||||||
int16_t state = directMode();
|
int16_t state = directMode();
|
||||||
|
@ -405,13 +405,13 @@ int16_t SX127x::startReceive(uint8_t len, uint8_t mode) {
|
||||||
// FSK modem does not distinguish between Rx single and continuous
|
// FSK modem does not distinguish between Rx single and continuous
|
||||||
if(mode == RADIOLIB_SX127X_RXCONTINUOUS) {
|
if(mode == RADIOLIB_SX127X_RXCONTINUOUS) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
return(setMode(RADIOLIB_SX127X_RX));
|
return(setMode(RADIOLIB_SX127X_RX));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to receive
|
// set mode to receive
|
||||||
return(setMode(mode));
|
return(setMode(mode));
|
||||||
|
@ -570,7 +570,7 @@ int16_t SX127x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
_mod->SPIwriteRegisterBurst(RADIOLIB_SX127X_REG_FIFO, data, packetLen);
|
_mod->SPIwriteRegisterBurst(RADIOLIB_SX127X_REG_FIFO, data, packetLen);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// start transmission
|
// start transmission
|
||||||
state |= setMode(RADIOLIB_SX127X_TX);
|
state |= setMode(RADIOLIB_SX127X_TX);
|
||||||
|
@ -659,7 +659,7 @@ int16_t SX127x::startChannelScan() {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to CAD
|
// set mode to CAD
|
||||||
state = setMode(RADIOLIB_SX127X_CAD);
|
state = setMode(RADIOLIB_SX127X_CAD);
|
||||||
|
@ -1258,6 +1258,10 @@ void SX127x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SX127x::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t SX127x::randomByte() {
|
uint8_t SX127x::randomByte() {
|
||||||
// check active modem
|
// check active modem
|
||||||
uint8_t rssiValueReg = RADIOLIB_SX127X_REG_RSSI_WIDEBAND;
|
uint8_t rssiValueReg = RADIOLIB_SX127X_REG_RSSI_WIDEBAND;
|
||||||
|
|
|
@ -1141,16 +1141,12 @@ class SX127x: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int8_t getTempRaw();
|
int8_t getTempRaw();
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Get one truly random byte from RSSI noise.
|
\brief Get one truly random byte from RSSI noise.
|
||||||
|
|
||||||
|
|
|
@ -348,7 +348,7 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
|
||||||
|
|
||||||
int16_t SX128x::transmitDirect(uint32_t frf) {
|
int16_t SX128x::transmitDirect(uint32_t frf) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
int16_t state = RADIOLIB_ERR_NONE;
|
int16_t state = RADIOLIB_ERR_NONE;
|
||||||
|
@ -363,7 +363,7 @@ int16_t SX128x::transmitDirect(uint32_t frf) {
|
||||||
|
|
||||||
int16_t SX128x::receiveDirect() {
|
int16_t SX128x::receiveDirect() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// SX128x is unable to output received data directly
|
// SX128x is unable to output received data directly
|
||||||
return(RADIOLIB_ERR_UNKNOWN);
|
return(RADIOLIB_ERR_UNKNOWN);
|
||||||
|
@ -388,7 +388,7 @@ int16_t SX128x::scanChannel() {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to CAD
|
// set mode to CAD
|
||||||
state = setCad();
|
state = setCad();
|
||||||
|
@ -416,7 +416,7 @@ int16_t SX128x::scanChannel() {
|
||||||
|
|
||||||
int16_t SX128x::sleep(bool retainConfig) {
|
int16_t SX128x::sleep(bool retainConfig) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
uint8_t sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_RETAIN | RADIOLIB_SX128X_SLEEP_DATA_RAM_RETAIN;
|
uint8_t sleepConfig = RADIOLIB_SX128X_SLEEP_DATA_BUFFER_RETAIN | RADIOLIB_SX128X_SLEEP_DATA_RAM_RETAIN;
|
||||||
if(!retainConfig) {
|
if(!retainConfig) {
|
||||||
|
@ -436,7 +436,7 @@ int16_t SX128x::standby() {
|
||||||
|
|
||||||
int16_t SX128x::standby(uint8_t mode) {
|
int16_t SX128x::standby(uint8_t mode) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
uint8_t data[] = { mode };
|
uint8_t data[] = { mode };
|
||||||
return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_STANDBY, data, 1));
|
return(SPIwriteCommand(RADIOLIB_SX128X_CMD_SET_STANDBY, data, 1));
|
||||||
|
@ -500,7 +500,7 @@ int16_t SX128x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
RADIOLIB_ASSERT(state);
|
RADIOLIB_ASSERT(state);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// start transmission
|
// start transmission
|
||||||
state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE);
|
state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE);
|
||||||
|
@ -553,7 +553,7 @@ int16_t SX128x::startReceive(uint16_t timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set mode to receive
|
// set mode to receive
|
||||||
state = setRx(timeout);
|
state = setRx(timeout);
|
||||||
|
@ -1243,6 +1243,10 @@ void SX128x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SX128x::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t SX128x::randomByte() {
|
uint8_t SX128x::randomByte() {
|
||||||
// it's unclear whether SX128x can measure RSSI while not receiving a packet
|
// it's unclear whether SX128x can measure RSSI while not receiving a packet
|
||||||
// this method is implemented only for PhysicalLayer compatibility
|
// this method is implemented only for PhysicalLayer compatibility
|
||||||
|
|
|
@ -809,16 +809,12 @@ class SX128x: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int16_t setEncoding(uint8_t encoding) override;
|
int16_t setEncoding(uint8_t encoding) override;
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Dummy random method, to ensure PhysicalLayer compatibility.
|
\brief Dummy random method, to ensure PhysicalLayer compatibility.
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ int16_t Si443x::receive(uint8_t* data, size_t len) {
|
||||||
|
|
||||||
int16_t Si443x::sleep() {
|
int16_t Si443x::sleep() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
// disable wakeup timer interrupt
|
// disable wakeup timer interrupt
|
||||||
int16_t state = _mod->SPIsetRegValue(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, 0x00);
|
int16_t state = _mod->SPIsetRegValue(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, 0x00);
|
||||||
|
@ -135,14 +135,14 @@ int16_t Si443x::sleep() {
|
||||||
|
|
||||||
int16_t Si443x::standby() {
|
int16_t Si443x::standby() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, LOW);
|
_mod->setRfSwitchState(Module::MODE_IDLE);
|
||||||
|
|
||||||
return(_mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_XTAL_ON, 7, 0, 10));
|
return(_mod->SPIsetRegValue(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_XTAL_ON, 7, 0, 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t Si443x::transmitDirect(uint32_t frf) {
|
int16_t Si443x::transmitDirect(uint32_t frf) {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// user requested to start transmitting immediately (required for RTTY)
|
// user requested to start transmitting immediately (required for RTTY)
|
||||||
if(frf != 0) {
|
if(frf != 0) {
|
||||||
|
@ -184,7 +184,7 @@ int16_t Si443x::transmitDirect(uint32_t frf) {
|
||||||
|
|
||||||
int16_t Si443x::receiveDirect() {
|
int16_t Si443x::receiveDirect() {
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// activate direct mode
|
// activate direct mode
|
||||||
int16_t state = directMode();
|
int16_t state = directMode();
|
||||||
|
@ -239,7 +239,7 @@ int16_t Si443x::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
|
||||||
_mod->SPIwriteRegisterBurst(RADIOLIB_SI443X_REG_FIFO_ACCESS, data, len);
|
_mod->SPIwriteRegisterBurst(RADIOLIB_SI443X_REG_FIFO_ACCESS, data, len);
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(LOW, HIGH);
|
_mod->setRfSwitchState(Module::MODE_TX);
|
||||||
|
|
||||||
// set interrupt mapping
|
// set interrupt mapping
|
||||||
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_PACKET_SENT_ENABLED);
|
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_PACKET_SENT_ENABLED);
|
||||||
|
@ -272,7 +272,7 @@ int16_t Si443x::startReceive() {
|
||||||
clearIRQFlags();
|
clearIRQFlags();
|
||||||
|
|
||||||
// set RF switch (if present)
|
// set RF switch (if present)
|
||||||
_mod->setRfSwitchState(HIGH, LOW);
|
_mod->setRfSwitchState(Module::MODE_RX);
|
||||||
|
|
||||||
// set interrupt mapping
|
// set interrupt mapping
|
||||||
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_VALID_PACKET_RECEIVED_ENABLED | RADIOLIB_SI443X_CRC_ERROR_ENABLED);
|
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_VALID_PACKET_RECEIVED_ENABLED | RADIOLIB_SI443X_CRC_ERROR_ENABLED);
|
||||||
|
@ -568,6 +568,10 @@ void Si443x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
|
||||||
_mod->setRfSwitchPins(rxEn, txEn);
|
_mod->setRfSwitchPins(rxEn, txEn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Si443x::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]) {
|
||||||
|
_mod->setRfSwitchTable(pins, table);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Si443x::randomByte() {
|
uint8_t Si443x::randomByte() {
|
||||||
// set mode to Rx
|
// set mode to Rx
|
||||||
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_RX_ON | RADIOLIB_SI443X_XTAL_ON);
|
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_RX_ON | RADIOLIB_SI443X_XTAL_ON);
|
||||||
|
|
|
@ -785,16 +785,12 @@ class Si443x: public PhysicalLayer {
|
||||||
*/
|
*/
|
||||||
int16_t setDataShaping(uint8_t sh) override;
|
int16_t setDataShaping(uint8_t sh) override;
|
||||||
|
|
||||||
/*!
|
/*! \copydoc Module::setRfSwitchPins */
|
||||||
\brief Some modules contain external RF switch controlled by two pins. This function gives RadioLib control over those two pins to automatically switch Rx and Tx state.
|
|
||||||
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
|
|
||||||
|
|
||||||
\param rxEn RX enable pin.
|
|
||||||
|
|
||||||
\param txEn TX enable pin.
|
|
||||||
*/
|
|
||||||
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
void setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn);
|
||||||
|
|
||||||
|
/*! \copydoc Module::setRfSwitchTable */
|
||||||
|
void setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[Module::RFSWITCH_MAX_PINS], const Module::RfSwitchMode_t table[]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Get one truly random byte from RSSI noise.
|
\brief Get one truly random byte from RSSI noise.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue