Merge pull request from matthijskooijman/add-stm32wl

Add support for STM32WL integrated transceivers
This commit is contained in:
Jan Gromeš 2023-01-14 18:52:37 +01:00 committed by GitHub
commit 7267e5ffc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1400 additions and 123 deletions

View file

@ -27,7 +27,8 @@ jobs:
- esp8266:esp8266:generic
- Intel:arc32:arduino_101
- SparkFun:apollo3:sfe_artemis
- STMicroelectronics:stm32:GenF3
- STMicroelectronics:stm32:GenF3:pnum=BLACKPILL_F303CC
- STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_WL55JC1
- stm32duino:STM32F1:mapleMini
- MegaCoreX:megaavr:4809
- arduino:mbed_rp2040:pico
@ -63,9 +64,9 @@ jobs:
id: prep
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=skip-pattern::''"
echo "::set-output name=skip-pattern::'STM32WL'"
echo "::set-output name=warnings::'all'"
# 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
# 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"
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
# STM32 (unofficial core)
echo "::set-output name=options:::bootloader_version=original,cpu_speed=speed_72mhz"

View file

@ -2172,7 +2172,8 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# 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
# tag can be used to specify a list of macro names that should be expanded. The

View file

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

View file

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

View 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);
}
}

View file

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

View 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);
}

View file

@ -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);
*/
}
}

View file

@ -38,6 +38,8 @@ SX1279 KEYWORD1
SX1280 KEYWORD1
SX1281 KEYWORD1
SX1282 KEYWORD1
STM32WLx KEYWORD1
STM32WLx_Module KEYWORD1
# protocols
RTTYClient KEYWORD1
@ -70,7 +72,7 @@ PasokonP7 KEYWORD1
# RadioLib
ModuleA KEYWORD2
ModuleB KEYWORD2
Module KEYWORD2
setRfSwitchTable KEYWORD2
# SX127x/RFM9x + RF69 + CC1101
begin KEYWORD2
@ -256,6 +258,7 @@ setInterruptSetup KEYWORD2
RADIOLIB_NC LITERAL1
RADIOLIB_VERSION LITERAL1
RADIOLIB_PIN_TYPE LITERAL1
RADIOLIB_SHAPING_NONE LITERAL1
RADIOLIB_SHAPING_0_3 LITERAL1

View file

@ -96,6 +96,7 @@
//#define RADIOLIB_EXCLUDE_SX127X
//#define RADIOLIB_EXCLUDE_RFM9X // dependent on RADIOLIB_EXCLUDE_SX127X
//#define RADIOLIB_EXCLUDE_SX126X
//#define RADIOLIB_EXCLUDE_STM32WLX // dependent on RADIOLIB_EXCLUDE_SX126X
//#define RADIOLIB_EXCLUDE_SX128X
//#define RADIOLIB_EXCLUDE_AFSK
//#define RADIOLIB_EXCLUDE_AX25
@ -1009,6 +1010,13 @@
#define RADIOLIB_STATIC_ARRAY_SIZE (256)
#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_BUILD_ARDUINO)
#define RADIOLIB_DEBUG_PRINT(...) { RADIOLIB_DEBUG_PORT.print(__VA_ARGS__); }

View file

@ -551,20 +551,50 @@ void Module::regdump(uint8_t start, uint8_t len) {
}
void Module::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE txEn) {
_useRfSwitch = true;
_rxEn = rxEn;
_txEn = txEn;
this->pinMode(rxEn, OUTPUT);
this->pinMode(txEn, OUTPUT);
// This can be on the stack, setRfSwitchTable copies the contents
const RADIOLIB_PIN_TYPE pins[] = {
rxEn, txEn, RADIOLIB_NC,
};
// 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) {
// check RF switch control is enabled
if(!_useRfSwitch) {
void Module::setRfSwitchTable(const RADIOLIB_PIN_TYPE (&pins)[3], const RfSwitchMode_t table[]) {
memcpy(_rfSwitchPins, pins, sizeof(_rfSwitchPins));
_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;
}
// set pins
this->digitalWrite(_rxEn, rxPinState);
this->digitalWrite(_txEn, txPinState);
const RADIOLIB_PIN_STATUS *value = &row->values[0];
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;
}
}

View file

@ -15,6 +15,54 @@
*/
class Module {
public:
/*!
* \brief The maximum number of pins supported by the RF switch
* code.
*
* Note: It is not recommended to use this constant in your sketch
* when defining a rfswitch pins array, to prevent issues when this
* value is ever increased and such an array gets extra zero
* elements (that will be interpreted as pin 0).
*/
static const size_t RFSWITCH_MAX_PINS = 3;
/*!
* 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)
@ -242,23 +290,103 @@ class Module {
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.
When using automatic RF switch control, DO NOT change the pin mode of rxEn or txEn from Arduino sketch!
\brief Some modules contain external RF switch controlled by pins.
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 txEn TX enable pin.
*/
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.
@ -446,10 +574,9 @@ class Module {
bool _initInterface = false;
#endif
// RF switch presence and pins
bool _useRfSwitch = false;
RADIOLIB_PIN_TYPE _rxEn = RADIOLIB_NC;
RADIOLIB_PIN_TYPE _txEn = RADIOLIB_NC;
// RF switch pins and table
RADIOLIB_PIN_TYPE _rfSwitchPins[RFSWITCH_MAX_PINS] = { RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC };
const RfSwitchMode_t *_rfSwitchTable = nullptr;
#if defined(RADIOLIB_INTERRUPT_TIMING)
uint32_t _prevTimingLen = 0;

View file

@ -78,6 +78,7 @@
#include "modules/SX126x/SX1261.h"
#include "modules/SX126x/SX1262.h"
#include "modules/SX126x/SX1268.h"
#include "modules/SX126x/STM32WLx.h"
#include "modules/SX127x/SX1272.h"
#include "modules/SX127x/SX1273.h"
#include "modules/SX127x/SX1276.h"

View file

@ -162,7 +162,7 @@ int16_t CC1101::standby() {
SPIsendCommand(RADIOLIB_CC1101_CMD_IDLE);
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
return(RADIOLIB_ERR_NONE);
}
@ -176,7 +176,7 @@ int16_t CC1101::transmitDirectAsync(uint32_t frf) {
int16_t CC1101::transmitDirect(bool sync, uint32_t frf) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// user requested to start transmitting immediately (required for RTTY)
if(frf != 0) {
@ -206,7 +206,7 @@ int16_t CC1101::receiveDirectAsync() {
int16_t CC1101::receiveDirect(bool sync) {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// activate direct mode
int16_t state = directMode(sync);
@ -291,7 +291,7 @@ int16_t CC1101::startTransmit(uint8_t* data, size_t len, uint8_t addr) {
dataSent += initialWrite;
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// set mode to transmit
SPIsendCommand(RADIOLIB_CC1101_CMD_TX);
@ -344,7 +344,7 @@ int16_t CC1101::startReceive() {
RADIOLIB_ASSERT(state);
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);
@ -902,6 +902,10 @@ void CC1101::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE 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() {
// set mode to Rx
SPIsendCommand(RADIOLIB_CC1101_CMD_RX);

View file

@ -928,16 +928,12 @@ class CC1101: public PhysicalLayer {
*/
int16_t setEncoding(uint8_t encoding) override;
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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.

View file

@ -159,7 +159,7 @@ int16_t RF69::receive(uint8_t* data, size_t len) {
int16_t RF69::sleep() {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
// set module to sleep
return(setMode(RADIOLIB_RF69_SLEEP));
@ -167,7 +167,7 @@ int16_t RF69::sleep() {
int16_t RF69::standby() {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
// set module to standby
return(setMode(RADIOLIB_RF69_STANDBY));
@ -175,7 +175,7 @@ int16_t RF69::standby() {
int16_t RF69::transmitDirect(uint32_t frf) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// user requested to start transmitting immediately (required for RTTY)
if(frf != 0) {
@ -196,7 +196,7 @@ int16_t RF69::transmitDirect(uint32_t frf) {
int16_t RF69::receiveDirect() {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// activate direct mode
int16_t state = directMode();
@ -254,7 +254,7 @@ int16_t RF69::startReceive() {
clearIRQFlags();
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
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)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// set mode to transmit
state = setMode(RADIOLIB_RF69_TX);
@ -916,6 +916,10 @@ void RF69::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE 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() {
// set mode to Rx
setMode(RADIOLIB_RF69_RX);

View file

@ -1010,16 +1010,12 @@ class RF69: public PhysicalLayer {
*/
int16_t setRSSIThreshold(float dbm);
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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.

View 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)

View 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

View 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)

View 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

View file

@ -20,10 +20,10 @@ int16_t SX1262::begin(float freq, float bw, uint8_t sf, uint8_t cr, uint8_t sync
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
state = setOutputPower(power);
state = SX126x::fixPaClamping();
RADIOLIB_ASSERT(state);
state = SX126x::fixPaClamping();
state = setOutputPower(power);
RADIOLIB_ASSERT(state);
return(state);
@ -38,10 +38,10 @@ int16_t SX1262::beginFSK(float freq, float br, float freqDev, float rxBw, int8_t
state = setFrequency(freq);
RADIOLIB_ASSERT(state);
state = setOutputPower(power);
state = SX126x::fixPaClamping();
RADIOLIB_ASSERT(state);
state = SX126x::fixPaClamping();
state = setOutputPower(power);
RADIOLIB_ASSERT(state);
return(state);

View file

@ -299,7 +299,7 @@ int16_t SX126x::receive(uint8_t* data, size_t len) {
int16_t SX126x::transmitDirect(uint32_t frf) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(_tx_mode);
// user requested to start transmitting immediately (required for RTTY)
int16_t state = RADIOLIB_ERR_NONE;
@ -315,7 +315,7 @@ int16_t SX126x::transmitDirect(uint32_t frf) {
int16_t SX126x::receiveDirect() {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// SX126x is unable to output received data directly
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) {
// 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;
if(!retainConfig) {
@ -357,7 +357,7 @@ int16_t SX126x::standby() {
int16_t SX126x::standby(uint8_t mode) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
uint8_t data[] = {mode};
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);
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(_tx_mode);
// start transmission
state = setTx(RADIOLIB_SX126X_TX_TIMEOUT_NONE);
@ -445,7 +445,7 @@ int16_t SX126x::startReceive(uint32_t timeout) {
RADIOLIB_ASSERT(state);
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
state = setRx(timeout);
@ -600,7 +600,7 @@ int16_t SX126x::startChannelScan(uint8_t symbolNum, uint8_t detPeak, uint8_t det
RADIOLIB_ASSERT(state);
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// 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);
@ -1199,6 +1199,10 @@ void SX126x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE 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) {
// check active modem
if(getPacketType() != RADIOLIB_SX126X_PACKET_TYPE_LORA) {
@ -1571,7 +1575,7 @@ int16_t SX126x::fixSensitivity() {
return(writeRegister(RADIOLIB_SX126X_REG_SENSITIVITY_CONFIG, &sensitivityConfig, 1));
}
int16_t SX126x::fixPaClamping() {
int16_t SX126x::fixPaClamping(bool enable) {
// fixes overly eager PA clamping
// 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);
RADIOLIB_ASSERT(state);
// update with the new value
clampConfig |= 0x1E;
// apply or undo workaround
if (enable)
clampConfig |= 0x1E;
else
clampConfig = (clampConfig & ~0x1E) | 0x08;
return(writeRegister(RADIOLIB_SX126X_REG_TX_CLAMP_CONFIG, &clampConfig, 1));
}

View file

@ -914,16 +914,12 @@ class SX126x: public PhysicalLayer {
*/
int16_t setEncoding(uint8_t encoding) override;
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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
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 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 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 calibrateImage(uint8_t* data);
uint8_t getPacketType();
@ -1009,7 +1005,7 @@ class SX126x: public PhysicalLayer {
// fixes to errata
int16_t fixSensitivity();
int16_t fixPaClamping();
int16_t fixPaClamping(bool enable = true);
int16_t fixImplicitTimeout();
int16_t fixInvertedIQ(uint8_t iqConfig);
@ -1047,6 +1043,9 @@ class SX126x: public PhysicalLayer {
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 checkCommandResult();
};

View file

@ -275,7 +275,7 @@ int16_t SX127x::scanChannel() {
int16_t SX127x::sleep() {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
// set mode to sleep
return(setMode(RADIOLIB_SX127X_SLEEP));
@ -283,7 +283,7 @@ int16_t SX127x::sleep() {
int16_t SX127x::standby() {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
// set mode to standby
return(setMode(RADIOLIB_SX127X_STANDBY));
@ -296,7 +296,7 @@ int16_t SX127x::transmitDirect(uint32_t frf) {
}
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// user requested to start transmitting immediately (required for RTTY)
if(frf != 0) {
@ -325,7 +325,7 @@ int16_t SX127x::receiveDirect() {
}
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// activate direct mode
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
if(mode == RADIOLIB_SX127X_RXCONTINUOUS) {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
return(setMode(RADIOLIB_SX127X_RX));
}
}
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
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);
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state |= setMode(RADIOLIB_SX127X_TX);
@ -659,7 +659,7 @@ int16_t SX127x::startChannelScan() {
RADIOLIB_ASSERT(state);
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to 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);
}
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() {
// check active modem
uint8_t rssiValueReg = RADIOLIB_SX127X_REG_RSSI_WIDEBAND;

View file

@ -1141,16 +1141,12 @@ class SX127x: public PhysicalLayer {
*/
int8_t getTempRaw();
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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.

View file

@ -348,7 +348,7 @@ int16_t SX128x::receive(uint8_t* data, size_t len) {
int16_t SX128x::transmitDirect(uint32_t frf) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// user requested to start transmitting immediately (required for RTTY)
int16_t state = RADIOLIB_ERR_NONE;
@ -363,7 +363,7 @@ int16_t SX128x::transmitDirect(uint32_t frf) {
int16_t SX128x::receiveDirect() {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// SX128x is unable to output received data directly
return(RADIOLIB_ERR_UNKNOWN);
@ -388,7 +388,7 @@ int16_t SX128x::scanChannel() {
RADIOLIB_ASSERT(state);
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to CAD
state = setCad();
@ -416,7 +416,7 @@ int16_t SX128x::scanChannel() {
int16_t SX128x::sleep(bool retainConfig) {
// 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;
if(!retainConfig) {
@ -436,7 +436,7 @@ int16_t SX128x::standby() {
int16_t SX128x::standby(uint8_t mode) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
uint8_t data[] = { mode };
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);
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// start transmission
state = setTx(RADIOLIB_SX128X_TX_TIMEOUT_NONE);
@ -553,7 +553,7 @@ int16_t SX128x::startReceive(uint16_t timeout) {
}
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set mode to receive
state = setRx(timeout);
@ -1243,6 +1243,10 @@ void SX128x::setRfSwitchPins(RADIOLIB_PIN_TYPE rxEn, RADIOLIB_PIN_TYPE 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() {
// it's unclear whether SX128x can measure RSSI while not receiving a packet
// this method is implemented only for PhysicalLayer compatibility

View file

@ -809,16 +809,12 @@ class SX128x: public PhysicalLayer {
*/
int16_t setEncoding(uint8_t encoding) override;
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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.

View file

@ -119,7 +119,7 @@ int16_t Si443x::receive(uint8_t* data, size_t len) {
int16_t Si443x::sleep() {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, LOW);
_mod->setRfSwitchState(Module::MODE_IDLE);
// disable wakeup timer interrupt
int16_t state = _mod->SPIsetRegValue(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, 0x00);
@ -135,14 +135,14 @@ int16_t Si443x::sleep() {
int16_t Si443x::standby() {
// 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));
}
int16_t Si443x::transmitDirect(uint32_t frf) {
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// user requested to start transmitting immediately (required for RTTY)
if(frf != 0) {
@ -184,7 +184,7 @@ int16_t Si443x::transmitDirect(uint32_t frf) {
int16_t Si443x::receiveDirect() {
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// activate direct mode
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);
// set RF switch (if present)
_mod->setRfSwitchState(LOW, HIGH);
_mod->setRfSwitchState(Module::MODE_TX);
// set interrupt mapping
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_INTERRUPT_ENABLE_1, RADIOLIB_SI443X_PACKET_SENT_ENABLED);
@ -272,7 +272,7 @@ int16_t Si443x::startReceive() {
clearIRQFlags();
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
_mod->setRfSwitchState(Module::MODE_RX);
// set interrupt mapping
_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);
}
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() {
// set mode to Rx
_mod->SPIwriteRegister(RADIOLIB_SI443X_REG_OP_FUNC_CONTROL_1, RADIOLIB_SI443X_RX_ON | RADIOLIB_SI443X_XTAL_ON);

View file

@ -785,16 +785,12 @@ class Si443x: public PhysicalLayer {
*/
int16_t setDataShaping(uint8_t sh) override;
/*!
\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.
*/
/*! \copydoc Module::setRfSwitchPins */
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.