mirror of
https://github.com/sandeepmistry/arduino-LoRa.git
synced 2025-04-20 23:47:47 +03:00
Merge pull request #637 from sandeepmistry/w-ockham-cad
Channel Activity Detection from @w-ockham
This commit is contained in:
commit
92862ebfde
23
API.md
23
API.md
@ -40,7 +40,7 @@ To save further pins one could connect the reset pin of the MCU with reset pin o
|
|||||||
|
|
||||||
#### Pin dio0 interrupt callbacks
|
#### Pin dio0 interrupt callbacks
|
||||||
|
|
||||||
The dio0 pin can be used for transmission finish callback and/or receiving callback, check `onTxDone` and `onReceive`.
|
The dio0 pin can be used for channel activity detection callback, transmission finish callback and/or receiving callback, check `onCadDone` , `onTxDone`, and `onReceive`.
|
||||||
|
|
||||||
### Set SPI interface
|
### Set SPI interface
|
||||||
|
|
||||||
@ -250,6 +250,27 @@ Returns the next byte in the packet or `-1` if no bytes are available.
|
|||||||
|
|
||||||
**Note:** Other Arduino [`Stream` API's](https://www.arduino.cc/en/Reference/Stream) can also be used to read data from the packet
|
**Note:** Other Arduino [`Stream` API's](https://www.arduino.cc/en/Reference/Stream) can also be used to read data from the packet
|
||||||
|
|
||||||
|
## Channel Activity Detection
|
||||||
|
**WARNING**: Channel activity detection callback uses the interrupt pin on the `dio0`, check `setPins` function!
|
||||||
|
|
||||||
|
### Register callback
|
||||||
|
|
||||||
|
Register a callback function for when channel activity detection has done.
|
||||||
|
```arduino
|
||||||
|
LoRa.onCadDone(onCadDone);
|
||||||
|
|
||||||
|
void onCadDone(boolean signalDetected) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
* `onCadDone` - function to call when channel activity detection has done.
|
||||||
|
* `signalDetected` - if `true`, the radio detects the presence of other LoRa signals.
|
||||||
|
|
||||||
|
### Channel Activity detection mode
|
||||||
|
Puts the radio in channel activity detection mode.
|
||||||
|
```arduino
|
||||||
|
LoRa.channelActivityDetection();
|
||||||
|
```
|
||||||
## Other radio modes
|
## Other radio modes
|
||||||
|
|
||||||
### Idle mode
|
### Idle mode
|
||||||
|
58
examples/LoRaCADCallback/LoRaCADCallback.ino
Normal file
58
examples/LoRaCADCallback/LoRaCADCallback.ino
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include "LoRa.h"
|
||||||
|
|
||||||
|
#ifdef ARDUINO_SAMD_MKRWAN1300
|
||||||
|
#error "This example is not compatible with the Arduino MKR WAN 1300 board!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial);
|
||||||
|
|
||||||
|
Serial.println("LoRa Receiver Callback");
|
||||||
|
|
||||||
|
if (!LoRa.begin(915E6)) {
|
||||||
|
Serial.println("Starting LoRa failed!");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the channel activity dectection callback
|
||||||
|
LoRa.onCadDone(onCadDone);
|
||||||
|
// register the receive callback
|
||||||
|
LoRa.onReceive(onReceive);
|
||||||
|
// put the radio into CAD mode
|
||||||
|
LoRa.channelActivityDetection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
void onCadDone(boolean signalDetected) {
|
||||||
|
// detect preamble
|
||||||
|
if (signalDetected) {
|
||||||
|
Serial.println("Signal detected");
|
||||||
|
// put the radio into continuous receive mode
|
||||||
|
LoRa.receive();
|
||||||
|
} else {
|
||||||
|
// try next activity dectection
|
||||||
|
LoRa.channelActivityDetection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onReceive(int packetSize) {
|
||||||
|
// received a packet
|
||||||
|
Serial.print("Received packet '");
|
||||||
|
|
||||||
|
// read packet
|
||||||
|
for (int i = 0; i < packetSize; i++) {
|
||||||
|
Serial.print((char)LoRa.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
// print RSSI of packet
|
||||||
|
Serial.print("' with RSSI ");
|
||||||
|
Serial.println(LoRa.packetRssi());
|
||||||
|
|
||||||
|
// put the radio into CAD mode
|
||||||
|
LoRa.channelActivityDetection();
|
||||||
|
}
|
@ -34,6 +34,8 @@ flush KEYWORD2
|
|||||||
|
|
||||||
onReceive KEYWORD2
|
onReceive KEYWORD2
|
||||||
onTxDone KEYWORD2
|
onTxDone KEYWORD2
|
||||||
|
onCadDone KEYWORD2
|
||||||
|
channelActivityDetection KEYWORD2
|
||||||
receive KEYWORD2
|
receive KEYWORD2
|
||||||
idle KEYWORD2
|
idle KEYWORD2
|
||||||
sleep KEYWORD2
|
sleep KEYWORD2
|
||||||
|
37
src/LoRa.cpp
37
src/LoRa.cpp
@ -47,6 +47,7 @@
|
|||||||
#define MODE_TX 0x03
|
#define MODE_TX 0x03
|
||||||
#define MODE_RX_CONTINUOUS 0x05
|
#define MODE_RX_CONTINUOUS 0x05
|
||||||
#define MODE_RX_SINGLE 0x06
|
#define MODE_RX_SINGLE 0x06
|
||||||
|
#define MODE_CAD 0x07
|
||||||
|
|
||||||
// PA config
|
// PA config
|
||||||
#define PA_BOOST 0x80
|
#define PA_BOOST 0x80
|
||||||
@ -55,6 +56,8 @@
|
|||||||
#define IRQ_TX_DONE_MASK 0x08
|
#define IRQ_TX_DONE_MASK 0x08
|
||||||
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
|
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
|
||||||
#define IRQ_RX_DONE_MASK 0x40
|
#define IRQ_RX_DONE_MASK 0x40
|
||||||
|
#define IRQ_CAD_DONE_MASK 0x04
|
||||||
|
#define IRQ_CAD_DETECTED_MASK 0x01
|
||||||
|
|
||||||
#define RF_MID_BAND_THRESHOLD 525E6
|
#define RF_MID_BAND_THRESHOLD 525E6
|
||||||
#define RSSI_OFFSET_HF_PORT 157
|
#define RSSI_OFFSET_HF_PORT 157
|
||||||
@ -76,6 +79,7 @@ LoRaClass::LoRaClass() :
|
|||||||
_packetIndex(0),
|
_packetIndex(0),
|
||||||
_implicitHeaderMode(0),
|
_implicitHeaderMode(0),
|
||||||
_onReceive(NULL),
|
_onReceive(NULL),
|
||||||
|
_onCadDone(NULL),
|
||||||
_onTxDone(NULL)
|
_onTxDone(NULL)
|
||||||
{
|
{
|
||||||
// overide Stream timeout value
|
// overide Stream timeout value
|
||||||
@ -377,6 +381,24 @@ void LoRaClass::onReceive(void(*callback)(int))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRaClass::onCadDone(void(*callback)(boolean))
|
||||||
|
{
|
||||||
|
_onCadDone = callback;
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
pinMode(_dio0, INPUT);
|
||||||
|
#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
||||||
|
SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
|
#endif
|
||||||
|
attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
|
||||||
|
} else {
|
||||||
|
detachInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
|
#ifdef SPI_HAS_NOTUSINGINTERRUPT
|
||||||
|
SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoRaClass::onTxDone(void(*callback)())
|
void LoRaClass::onTxDone(void(*callback)())
|
||||||
{
|
{
|
||||||
_onTxDone = callback;
|
_onTxDone = callback;
|
||||||
@ -410,6 +432,12 @@ void LoRaClass::receive(int size)
|
|||||||
|
|
||||||
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
|
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRaClass::channelActivityDetection(void)
|
||||||
|
{
|
||||||
|
writeRegister(REG_DIO_MAPPING_1, 0x80);// DIO0 => CADDONE
|
||||||
|
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_CAD);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void LoRaClass::idle()
|
void LoRaClass::idle()
|
||||||
@ -696,7 +724,11 @@ void LoRaClass::handleDio0Rise()
|
|||||||
// clear IRQ's
|
// clear IRQ's
|
||||||
writeRegister(REG_IRQ_FLAGS, irqFlags);
|
writeRegister(REG_IRQ_FLAGS, irqFlags);
|
||||||
|
|
||||||
if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
|
if ((irqFlags & IRQ_CAD_DONE_MASK) != 0) {
|
||||||
|
if (_onCadDone) {
|
||||||
|
_onCadDone((irqFlags & IRQ_CAD_DETECTED_MASK) != 0);
|
||||||
|
}
|
||||||
|
} else if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
|
||||||
|
|
||||||
if ((irqFlags & IRQ_RX_DONE_MASK) != 0) {
|
if ((irqFlags & IRQ_RX_DONE_MASK) != 0) {
|
||||||
// received a packet
|
// received a packet
|
||||||
@ -711,8 +743,7 @@ void LoRaClass::handleDio0Rise()
|
|||||||
if (_onReceive) {
|
if (_onReceive) {
|
||||||
_onReceive(packetLength);
|
_onReceive(packetLength);
|
||||||
}
|
}
|
||||||
}
|
} else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) {
|
||||||
else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) {
|
|
||||||
if (_onTxDone) {
|
if (_onTxDone) {
|
||||||
_onTxDone();
|
_onTxDone();
|
||||||
}
|
}
|
||||||
|
@ -59,9 +59,11 @@ public:
|
|||||||
|
|
||||||
#ifndef ARDUINO_SAMD_MKRWAN1300
|
#ifndef ARDUINO_SAMD_MKRWAN1300
|
||||||
void onReceive(void(*callback)(int));
|
void onReceive(void(*callback)(int));
|
||||||
|
void onCadDone(void(*callback)(boolean));
|
||||||
void onTxDone(void(*callback)());
|
void onTxDone(void(*callback)());
|
||||||
|
|
||||||
void receive(int size = 0);
|
void receive(int size = 0);
|
||||||
|
void channelActivityDetection(void);
|
||||||
#endif
|
#endif
|
||||||
void idle();
|
void idle();
|
||||||
void sleep();
|
void sleep();
|
||||||
@ -122,6 +124,7 @@ private:
|
|||||||
int _packetIndex;
|
int _packetIndex;
|
||||||
int _implicitHeaderMode;
|
int _implicitHeaderMode;
|
||||||
void (*_onReceive)(int);
|
void (*_onReceive)(int);
|
||||||
|
void (*_onCadDone)(boolean);
|
||||||
void (*_onTxDone)();
|
void (*_onTxDone)();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user