[SX127x] Added interrupt-driven CAD (#396)

This commit is contained in:
jgromes 2021-10-28 15:44:25 +02:00
parent 81e8de8324
commit ebc4852fc2
4 changed files with 173 additions and 22 deletions

View file

@ -0,0 +1,136 @@
/*
RadioLib SX127x Channel Activity Detection with Interrupts Example
This example scans the current LoRa channel and detects
valid LoRa preambles. Preamble is the first part of
LoRa transmission, so this can be used to check
if the LoRa channel is free, or if you should start
receiving a message.
Other modules from SX127x/RFM9x family can also be used.
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx127xrfm9x---lora-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
// SX1278 has the following connections:
// NSS pin: 10
// DIO0 pin: 2
// RESET pin: 9
// DIO1 pin: 3
SX1278 radio = new Module(10, 2, 9, 3);
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1278 radio = RadioShield.ModuleA;
// save state between loops
int scanState = ERR_NONE;
void setup() {
Serial.begin(9600);
// initialize SX1278 with default settings
Serial.print(F("[SX1278] Initializing ... "));
int state = radio.begin();
if (state == 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 preamble is not detected within CAD timeout period
radio.setDio0Action(setFlagTimeout);
// set the function that will be called
// when LoRa preamble is detected
radio.setDio1Action(setFlagDetected);
// start scanning the channel
Serial.print(F("[SX1278] Starting scan for LoRa preamble ... "));
state = radio.startChannelScan();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
}
}
// flag to indicate that a preamble was not detected
volatile bool timeoutFlag = false;
// flag to indicate that a preamble was detected
volatile bool detectedFlag = false;
// disable interrupt when it's not needed
volatile bool enableInterrupt = true;
// this function is called when no preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlagTimeout(void) {
// check if the interrupt is enabled
if(!enableInterrupt) {
return;
}
// we timed out, set the flag
timeoutFlag = true;
}
// this function is called when LoRa preamble
// is detected within timeout period
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlagDetected(void) {
// check if the interrupt is enabled
if(!enableInterrupt) {
return;
}
// we got a preamble, set the flag
detectedFlag = true;
}
void loop() {
// check if we got a preamble
if(detectedFlag) {
// disable the interrupt service routine while
// processing the data
enableInterrupt = false;
// reset flag
detectedFlag = false;
// LoRa preamble was detected
Serial.print(F("[SX1278] Preamble detected!"));
}
// check if we need to restart channel activity detection
if(detectedFlag || timeoutFlag) {
// start scanning the channel
Serial.print(F("[SX1278] Starting scan for LoRa preamble ... "));
// start scanning current channel
int state = radio.startChannelScan();
if (state == ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
}
}
}

View file

@ -96,6 +96,8 @@ clearDio1Action KEYWORD2
startTransmit KEYWORD2
startReceive KEYWORD2
readData KEYWORD2
startChannelScan KEYWORD2
getChannelScanResult KEYWORD2
setBandwidth KEYWORD2
setSpreadingFactor KEYWORD2
setCodingRate KEYWORD2

View file

@ -247,27 +247,8 @@ int16_t SX127x::receive(uint8_t* data, size_t len) {
}
int16_t SX127x::scanChannel() {
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIRQFlags();
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
// set mode to CAD
state = setMode(SX127X_CAD);
// start CAD
int16_t state = startChannelScan();
RADIOLIB_ASSERT(state);
// wait for channel activity detected or timeout
@ -566,6 +547,31 @@ int16_t SX127x::readData(uint8_t* data, size_t len) {
return(ERR_NONE);
}
int16_t SX127x::startChannelScan() {
// check active modem
if(getActiveModem() != SX127X_LORA) {
return(ERR_WRONG_MODEM);
}
// set mode to standby
int16_t state = setMode(SX127X_STANDBY);
RADIOLIB_ASSERT(state);
// set DIO pin mapping
state = _mod->SPIsetRegValue(SX127X_REG_DIO_MAPPING_1, SX127X_DIO0_CAD_DONE | SX127X_DIO1_CAD_DETECTED, 7, 4);
RADIOLIB_ASSERT(state);
// clear interrupt flags
clearIRQFlags();
// set RF switch (if present)
_mod->setRfSwitchState(HIGH, LOW);
// set mode to CAD
state = setMode(SX127X_CAD);
return(state);
}
int16_t SX127x::setSyncWord(uint8_t syncWord) {
// check active modem
if(getActiveModem() != SX127X_LORA) {

View file

@ -734,6 +734,13 @@ class SX127x: public PhysicalLayer {
*/
int16_t readData(uint8_t* data, size_t len) override;
/*!
\brief Interrupt-driven channel activity detection method. DIO0 will be activated when LoRa preamble is detected.
DIO1 will be activated if there's no preamble detected before timeout.
\returns \ref status_codes
*/
int16_t startChannelScan();
// configuration methods
@ -1085,7 +1092,7 @@ class SX127x: public PhysicalLayer {
* \returns bandwidth in manitsa and exponent format
*/
static uint8_t calculateBWManExp(float bandwidth);
virtual void errataFix(bool rx) = 0;
};