added functionality for LoRa Alliance TR-13 Enabling CSMA for LoRaWAN
This commit is contained in:
parent
556f37f608
commit
da57f1cdef
3 changed files with 98 additions and 11 deletions
|
@ -1702,27 +1702,47 @@ int16_t SX126x::setRx(uint32_t timeout) {
|
|||
return(this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX, data, 3, true, false));
|
||||
}
|
||||
|
||||
|
||||
int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
|
||||
// default CAD parameters for assigned SF as per Semtech AN1200.48, Rev 2.1, Page 50
|
||||
uint8_t detPeakValues[8] = { 22, 22, 22, 22, 23, 24, 25, 28};
|
||||
uint8_t symbolNumValues[8] = { RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
// default CAD parameters are shown in Semtech AN1200.48, page 41.
|
||||
uint8_t detPeakValues[6] = { 22, 22, 24, 25, 26, 30};
|
||||
uint8_t symbolNumValues[6] = { RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_4_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_4_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_4_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_4_SYMB };
|
||||
RADIOLIB_SX126X_CAD_ON_2_SYMB,
|
||||
RADIOLIB_SX126X_CAD_ON_2_SYMB };
|
||||
|
||||
// CAD parameters aren't available for SF-6. Just to be safe.
|
||||
if(this->spreadingFactor < 7) {
|
||||
this->spreadingFactor = 7;
|
||||
} else if(this->spreadingFactor > 12) {
|
||||
this->spreadingFactor = 12;
|
||||
}
|
||||
|
||||
// build the packet
|
||||
uint8_t data[7];
|
||||
data[0] = symbolNumValues[this->spreadingFactor - 5];
|
||||
data[1] = detPeakValues[this->spreadingFactor - 5];
|
||||
data[0] = symbolNumValues[this->spreadingFactor - 7];
|
||||
data[1] = detPeakValues[this->spreadingFactor - 7];
|
||||
data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
|
||||
data[3] = RADIOLIB_SX126X_CAD_GOTO_STDBY;
|
||||
data[4] = 0x00;
|
||||
data[5] = 0x00;
|
||||
data[6] = 0x00;
|
||||
|
||||
|
||||
/*
|
||||
CAD Configuration Note:
|
||||
The default CAD configuration applied by `scanChannel` overrides the optimal SF-specific configurations, leading to suboptimal detection.
|
||||
I.e., anything that is not RADIOLIB_SX126X_CAD_PARAM_DEFAULT is overridden. But CAD settings are SF specific.
|
||||
To address this, the user override has been commented out, ensuring consistent application of the optimal CAD settings as
|
||||
per Semtech's Application Note AN1200.48 (page 41) for the 125KHz setting. This approach significantly reduces false CAD occurrences.
|
||||
Testing has shown that there is no reason for a user to change CAD settings for anything other than most optimal ones described in AN1200.48 .
|
||||
However, this change deos not respect CAD configs from the LoRaWAN layer. Future considerations or use cases might require revisiting this decision.
|
||||
Hence this note.
|
||||
*/
|
||||
|
||||
/*
|
||||
// set user-provided values
|
||||
if(symbolNum != RADIOLIB_SX126X_CAD_PARAM_DEFAULT) {
|
||||
data[0] = symbolNum;
|
||||
|
@ -1736,6 +1756,9 @@ int16_t SX126x::setCad(uint8_t symbolNum, uint8_t detPeak, uint8_t detMin) {
|
|||
data[2] = detMin;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// configure parameters
|
||||
int16_t state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_CAD_PARAMS, data, 7);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
@ -2030,7 +2053,7 @@ int16_t SX126x::config(uint8_t modem) {
|
|||
state = this->mod->SPIwriteStream(RADIOLIB_SX126X_CMD_SET_RX_TX_FALLBACK_MODE, data, 1);
|
||||
RADIOLIB_ASSERT(state);
|
||||
|
||||
// set some CAD parameters - will be overwritten whel calling CAD anyway
|
||||
// set some CAD parameters - will be overwritten when calling CAD anyway
|
||||
data[0] = RADIOLIB_SX126X_CAD_ON_8_SYMB;
|
||||
data[1] = this->spreadingFactor + 13;
|
||||
data[2] = RADIOLIB_SX126X_CAD_PARAM_DET_MIN;
|
||||
|
|
|
@ -637,6 +637,11 @@ int16_t LoRaWANNode::uplink(uint8_t* data, size_t len, uint8_t port) {
|
|||
LoRaWANNode::hton<uint32_t>(&uplinkMsg[uplinkMsgLen - sizeof(uint32_t)], micF);
|
||||
}
|
||||
|
||||
// perform CSMA if enabled.
|
||||
if (CSMA_ENABLE) {
|
||||
performCSMA();
|
||||
}
|
||||
|
||||
RADIOLIB_DEBUG_PRINTLN("uplinkMsg:");
|
||||
RADIOLIB_DEBUG_HEXDUMP(uplinkMsg, uplinkMsgLen);
|
||||
|
||||
|
@ -1762,4 +1767,52 @@ void LoRaWANNode::hton(uint8_t* buff, T val, size_t size) {
|
|||
}
|
||||
}
|
||||
|
||||
// The following function enables LMAC, a CSMA scheme for LoRa as specified in the LoRa Alliance Technical Reccomendation #13.
|
||||
// A user may enable CSMA to provide frames an additional layer of protection from interference.
|
||||
// https://resources.lora-alliance.org/technical-recommendations/tr013-1-0-0-csma
|
||||
void LoRaWANNode::performCSMA() {
|
||||
|
||||
// Compute initial random back-off.
|
||||
// When BO is reduced to zero, the function returns and the frame is transmitted.
|
||||
uint32_t BO = random(1, BO_MAX + 1);
|
||||
|
||||
while (BO > 0) {
|
||||
// DIFS: Check channel for DIFS_slots
|
||||
bool channelFreeDuringDIFS = true;
|
||||
for (uint8_t i = 0; i < DIFS_SLOTS; i++) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING DIFS");
|
||||
channelFreeDuringDIFS = false;
|
||||
// Channel is occupied during DIFS, hop to another.
|
||||
this->setupChannels();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Start reducing BO counter if DIFS slot was free.
|
||||
if (channelFreeDuringDIFS) {
|
||||
// Continue decrementing BO with per each CAD reporting free channel.
|
||||
while (BO > 0) {
|
||||
if (performCAD()) {
|
||||
RADIOLIB_DEBUG_PRINTLN("OCCUPIED CHANNEL DURING BO");
|
||||
// Channel is busy during CAD, hop to another and return to DIFS state again.
|
||||
this->setupChannels();
|
||||
break; // Exit loop. Go back to DIFS state.
|
||||
}
|
||||
BO--; // Decrement BO by one if channel is free
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LoRaWANNode::performCAD() {
|
||||
int16_t state = this->phyLayer->scanChannel();
|
||||
|
||||
if ((state == RADIOLIB_PREAMBLE_DETECTED) || (state == RADIOLIB_LORA_DETECTED)) {
|
||||
return true; // Channel is busy
|
||||
}
|
||||
return false; // Channel is free
|
||||
}
|
||||
|
||||
#endif
|
|
@ -176,6 +176,11 @@
|
|||
// the maximum number of simultaneously available channels
|
||||
#define RADIOLIB_LORAWAN_NUM_AVAILABLE_CHANNELS (8)
|
||||
|
||||
// CSMA definitions
|
||||
#define DIFS_SLOTS (2) // Number of CADs to estimate a clear channel.
|
||||
#define BO_MAX (6) // Number of maximum CADs to back-off. Set to 0 to disable.
|
||||
#define CSMA_ENABLE (true) // Enables/disables CSMA functionality.
|
||||
|
||||
/*!
|
||||
\struct LoRaWANChannelSpan_t
|
||||
\brief Structure to save information about LoRaWAN channels.
|
||||
|
@ -502,6 +507,12 @@ class LoRaWANNode {
|
|||
// host-to-network conversion method - takes data from host variable and and converts it to network packet endians
|
||||
template<typename T>
|
||||
static void hton(uint8_t* buff, T val, size_t size = 0);
|
||||
|
||||
// perform a single CAD operation for the under SF/CH combination. Returns either busy or otherwise.
|
||||
bool performCAD();
|
||||
|
||||
// Performs CSMA as per LoRa Alliance Technical Reccomendation 13 (TR-013).
|
||||
void performCSMA();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue