diff --git a/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino b/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino new file mode 100644 index 00000000..9d65ab24 --- /dev/null +++ b/examples/SX126x/SX126x_Channel_Activity_Detection_Interrupt/SX126x_Channel_Activity_Detection_Interrupt.ino @@ -0,0 +1,123 @@ +/* + RadioLib SX126x Channel Activity Detection Example + + This example uses SX1262 to scan the current LoRa + channel and detect ongoing LoRa transmissions. + Unlike SX127x CAD, SX126x can detect any part + of LoRa transmission, not just the preamble. + + Other modules from SX126x family can also be used. + + 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 + +// SX1262 has the following connections: +// NSS pin: 10 +// DIO1 pin: 2 +// NRST pin: 3 +// BUSY pin: 9 +SX1262 radio = new Module(10, 2, 3, 9); + +// or using RadioShield +// https://github.com/jgromes/RadioShield +//SX1262 radio = RadioShield.ModuleA; + +void setup() { + Serial.begin(9600); + + // initialize SX1262 with default settings + Serial.print(F("[SX1262] 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 packet or timeout is detected + radio.setDio1Action(setFlag); + + // start scanning the channel + Serial.print(F("[SX1262] 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 packet was detected or CAD timed out +volatile bool scanFlag = false; + +// disable interrupt when it's not needed +volatile bool enableInterrupt = true; + +// 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) { + // check if the interrupt is enabled + if(!enableInterrupt) { + return; + } + + // something happened, set the flag + scanFlag = true; +} + +void loop() { + // check if the flag is set + if(scanFlag) { + // disable the interrupt service routine while + // processing the data + enableInterrupt = false; + + // reset flag + scanFlag = false; + + // check CAD result + int state = radio.getChannelScanResult(); + + if (state == LORA_DETECTED) { + // LoRa packet was detected + Serial.println(F("[SX1262] Packet detected!")); + + } else if (state == CHANNEL_FREE) { + // channel is free + Serial.println(F("[SX1262] Channel is free!")); + + } else { + // some other error occurred + Serial.print(F("[SX1262] Failed, code ")); + Serial.println(state); + + } + + // start scanning the channel again + Serial.print(F("[SX1262] 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); + } + + // enable interrupt service routine + enableInterrupt = true; + } + +} diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 92cfe2a3..2c8dd3a0 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -331,28 +331,8 @@ int16_t SX126x::receiveDirect() { } int16_t SX126x::scanChannel() { - // check active modem - if(getPacketType() != SX126X_PACKET_TYPE_LORA) { - return(ERR_WRONG_MODEM); - } - - // set mode to standby - int16_t state = standby(); - RADIOLIB_ASSERT(state); - - // set RF switch (if present) - _mod->setRfSwitchState(HIGH, LOW); - - // set DIO pin mapping - state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE); - RADIOLIB_ASSERT(state); - - // clear interrupt flags - state = clearIrqStatus(); - RADIOLIB_ASSERT(state); - // set mode to CAD - state = setCad(); + int state = startChannelScan(); RADIOLIB_ASSERT(state); // wait for channel activity detected or timeout @@ -361,18 +341,7 @@ int16_t SX126x::scanChannel() { } // check CAD result - uint16_t cadResult = getIrqStatus(); - if(cadResult & SX126X_IRQ_CAD_DETECTED) { - // detected some LoRa activity - clearIrqStatus(); - return(LORA_DETECTED); - } else if(cadResult & SX126X_IRQ_CAD_DONE) { - // channel is free - clearIrqStatus(); - return(CHANNEL_FREE); - } - - return(ERR_UNKNOWN); + return(getChannelScanResult()); } int16_t SX126x::sleep(bool retainConfig) { @@ -608,6 +577,53 @@ int16_t SX126x::readData(uint8_t* data, size_t len) { return(state); } +int16_t SX126x::startChannelScan() { + // check active modem + if(getPacketType() != SX126X_PACKET_TYPE_LORA) { + return(ERR_WRONG_MODEM); + } + + // set mode to standby + int16_t state = standby(); + RADIOLIB_ASSERT(state); + + // set RF switch (if present) + _mod->setRfSwitchState(HIGH, LOW); + + // set DIO pin mapping + state = setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE); + RADIOLIB_ASSERT(state); + + // clear interrupt flags + state = clearIrqStatus(); + RADIOLIB_ASSERT(state); + + // set mode to CAD + state = setCad(); + return(state); +} + +int16_t SX126x::getChannelScanResult() { + // check active modem + if(getPacketType() != SX126X_PACKET_TYPE_LORA) { + return(ERR_WRONG_MODEM); + } + + // check CAD result + uint16_t cadResult = getIrqStatus(); + if(cadResult & SX126X_IRQ_CAD_DETECTED) { + // detected some LoRa activity + clearIrqStatus(); + return(LORA_DETECTED); + } else if(cadResult & SX126X_IRQ_CAD_DONE) { + // channel is free + clearIrqStatus(); + return(CHANNEL_FREE); + } + + return(ERR_UNKNOWN); +} + int16_t SX126x::setBandwidth(float bw) { // check active modem if(getPacketType() != SX126X_PACKET_TYPE_LORA) { diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index 775aeb9f..97fb05fe 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -554,6 +554,20 @@ class SX126x: 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, or upon timeout. + + \returns \ref status_codes + */ + int16_t startChannelScan(); + + /*! + \brief Read the channel scan result + + \returns \ref status_codes + */ + int16_t getChannelScanResult(); + // configuration methods /*!