Skip to content

Commit 92862eb

Browse files
authored
Merge pull request #637 from sandeepmistry/w-ockham-cad
Channel Activity Detection from @w-ockham
2 parents 55d49c5 + 934fe8b commit 92862eb

File tree

5 files changed

+119
-4
lines changed

5 files changed

+119
-4
lines changed

API.md

+22-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ To save further pins one could connect the reset pin of the MCU with reset pin o
4040

4141
#### Pin dio0 interrupt callbacks
4242

43-
The dio0 pin can be used for transmission finish callback and/or receiving callback, check `onTxDone` and `onReceive`.
43+
The dio0 pin can be used for channel activity detection callback, transmission finish callback and/or receiving callback, check `onCadDone` , `onTxDone`, and `onReceive`.
4444

4545
### Set SPI interface
4646

@@ -250,6 +250,27 @@ Returns the next byte in the packet or `-1` if no bytes are available.
250250

251251
**Note:** Other Arduino [`Stream` API's](https://www.arduino.cc/en/Reference/Stream) can also be used to read data from the packet
252252

253+
## Channel Activity Detection
254+
**WARNING**: Channel activity detection callback uses the interrupt pin on the `dio0`, check `setPins` function!
255+
256+
### Register callback
257+
258+
Register a callback function for when channel activity detection has done.
259+
```arduino
260+
LoRa.onCadDone(onCadDone);
261+
262+
void onCadDone(boolean signalDetected) {
263+
// ...
264+
}
265+
```
266+
* `onCadDone` - function to call when channel activity detection has done.
267+
* `signalDetected` - if `true`, the radio detects the presence of other LoRa signals.
268+
269+
### Channel Activity detection mode
270+
Puts the radio in channel activity detection mode.
271+
```arduino
272+
LoRa.channelActivityDetection();
273+
```
253274
## Other radio modes
254275

255276
### Idle mode
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <SPI.h>
2+
#include "LoRa.h"
3+
4+
#ifdef ARDUINO_SAMD_MKRWAN1300
5+
#error "This example is not compatible with the Arduino MKR WAN 1300 board!"
6+
#endif
7+
8+
void setup() {
9+
Serial.begin(9600);
10+
while (!Serial);
11+
12+
Serial.println("LoRa Receiver Callback");
13+
14+
if (!LoRa.begin(915E6)) {
15+
Serial.println("Starting LoRa failed!");
16+
while (1);
17+
}
18+
19+
// register the channel activity dectection callback
20+
LoRa.onCadDone(onCadDone);
21+
// register the receive callback
22+
LoRa.onReceive(onReceive);
23+
// put the radio into CAD mode
24+
LoRa.channelActivityDetection();
25+
}
26+
27+
void loop() {
28+
// do nothing
29+
}
30+
31+
void onCadDone(boolean signalDetected) {
32+
// detect preamble
33+
if (signalDetected) {
34+
Serial.println("Signal detected");
35+
// put the radio into continuous receive mode
36+
LoRa.receive();
37+
} else {
38+
// try next activity dectection
39+
LoRa.channelActivityDetection();
40+
}
41+
}
42+
43+
void onReceive(int packetSize) {
44+
// received a packet
45+
Serial.print("Received packet '");
46+
47+
// read packet
48+
for (int i = 0; i < packetSize; i++) {
49+
Serial.print((char)LoRa.read());
50+
}
51+
52+
// print RSSI of packet
53+
Serial.print("' with RSSI ");
54+
Serial.println(LoRa.packetRssi());
55+
56+
// put the radio into CAD mode
57+
LoRa.channelActivityDetection();
58+
}

keywords.txt

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ flush KEYWORD2
3434

3535
onReceive KEYWORD2
3636
onTxDone KEYWORD2
37+
onCadDone KEYWORD2
38+
channelActivityDetection KEYWORD2
3739
receive KEYWORD2
3840
idle KEYWORD2
3941
sleep KEYWORD2

src/LoRa.cpp

+34-3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#define MODE_TX 0x03
4848
#define MODE_RX_CONTINUOUS 0x05
4949
#define MODE_RX_SINGLE 0x06
50+
#define MODE_CAD 0x07
5051

5152
// PA config
5253
#define PA_BOOST 0x80
@@ -55,6 +56,8 @@
5556
#define IRQ_TX_DONE_MASK 0x08
5657
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
5758
#define IRQ_RX_DONE_MASK 0x40
59+
#define IRQ_CAD_DONE_MASK 0x04
60+
#define IRQ_CAD_DETECTED_MASK 0x01
5861

5962
#define RF_MID_BAND_THRESHOLD 525E6
6063
#define RSSI_OFFSET_HF_PORT 157
@@ -76,6 +79,7 @@ LoRaClass::LoRaClass() :
7679
_packetIndex(0),
7780
_implicitHeaderMode(0),
7881
_onReceive(NULL),
82+
_onCadDone(NULL),
7983
_onTxDone(NULL)
8084
{
8185
// overide Stream timeout value
@@ -377,6 +381,24 @@ void LoRaClass::onReceive(void(*callback)(int))
377381
}
378382
}
379383

384+
void LoRaClass::onCadDone(void(*callback)(boolean))
385+
{
386+
_onCadDone = callback;
387+
388+
if (callback) {
389+
pinMode(_dio0, INPUT);
390+
#ifdef SPI_HAS_NOTUSINGINTERRUPT
391+
SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
392+
#endif
393+
attachInterrupt(digitalPinToInterrupt(_dio0), LoRaClass::onDio0Rise, RISING);
394+
} else {
395+
detachInterrupt(digitalPinToInterrupt(_dio0));
396+
#ifdef SPI_HAS_NOTUSINGINTERRUPT
397+
SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
398+
#endif
399+
}
400+
}
401+
380402
void LoRaClass::onTxDone(void(*callback)())
381403
{
382404
_onTxDone = callback;
@@ -410,6 +432,12 @@ void LoRaClass::receive(int size)
410432

411433
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
412434
}
435+
436+
void LoRaClass::channelActivityDetection(void)
437+
{
438+
writeRegister(REG_DIO_MAPPING_1, 0x80);// DIO0 => CADDONE
439+
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_CAD);
440+
}
413441
#endif
414442

415443
void LoRaClass::idle()
@@ -696,7 +724,11 @@ void LoRaClass::handleDio0Rise()
696724
// clear IRQ's
697725
writeRegister(REG_IRQ_FLAGS, irqFlags);
698726

699-
if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
727+
if ((irqFlags & IRQ_CAD_DONE_MASK) != 0) {
728+
if (_onCadDone) {
729+
_onCadDone((irqFlags & IRQ_CAD_DETECTED_MASK) != 0);
730+
}
731+
} else if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
700732

701733
if ((irqFlags & IRQ_RX_DONE_MASK) != 0) {
702734
// received a packet
@@ -711,8 +743,7 @@ void LoRaClass::handleDio0Rise()
711743
if (_onReceive) {
712744
_onReceive(packetLength);
713745
}
714-
}
715-
else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) {
746+
} else if ((irqFlags & IRQ_TX_DONE_MASK) != 0) {
716747
if (_onTxDone) {
717748
_onTxDone();
718749
}

src/LoRa.h

+3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,11 @@ class LoRaClass : public Stream {
5959

6060
#ifndef ARDUINO_SAMD_MKRWAN1300
6161
void onReceive(void(*callback)(int));
62+
void onCadDone(void(*callback)(boolean));
6263
void onTxDone(void(*callback)());
6364

6465
void receive(int size = 0);
66+
void channelActivityDetection(void);
6567
#endif
6668
void idle();
6769
void sleep();
@@ -122,6 +124,7 @@ class LoRaClass : public Stream {
122124
int _packetIndex;
123125
int _implicitHeaderMode;
124126
void (*_onReceive)(int);
127+
void (*_onCadDone)(boolean);
125128
void (*_onTxDone)();
126129
};
127130

0 commit comments

Comments
 (0)