diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index ce4f912ba..6a4e7404e 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -256,10 +256,17 @@ template void LR11x0Interface::startReceive() template bool LR11x0Interface::isChannelActive() { // check if we can detect a LoRa preamble on the current channel + ChannelScanConfig_t cfg = {.cad = {.symNum = NUM_SYM_CAD, + .detPeak = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, + .detMin = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, + .exitMode = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, + .timeout = 0, + .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS, + .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}}; int16_t result; setStandby(); - result = lora.scanChannel(); + result = lora.scanChannel(cfg); if (result == RADIOLIB_LORA_DETECTED) return true; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index b1403f3b6..c51ad8144 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -261,7 +261,7 @@ uint8_t RadioInterface::getCWsize(float snr) const uint32_t SNR_MIN = -20; // The maximum value for a LoRa SNR - const uint32_t SNR_MAX = 15; + const uint32_t SNR_MAX = 10; return map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax); } @@ -566,7 +566,7 @@ void RadioInterface::applyModemConfig() saveChannelNum(channel_num); saveFreq(freq + loraConfig.frequency_offset); - slotTimeMsec = computeSlotTimeMsec(bw, sf); + slotTimeMsec = computeSlotTimeMsec(); preambleTimeMsec = getPacketTime((uint32_t)0); maxPacketTimeMsec = getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN + sizeof(PacketHeader)); @@ -581,6 +581,25 @@ void RadioInterface::applyModemConfig() LOG_INFO("Slot time: %u msec", slotTimeMsec); } +/** Slottime is the time to detect a transmission has started, consisting of: + - CAD duration; + - roundtrip air propagation time (assuming max. 30km between nodes); + - Tx/Rx turnaround time (maximum of SX126x and SX127x); + - MAC processing time (measured on T-beam) */ +uint32_t RadioInterface::computeSlotTimeMsec() +{ + float sumPropagationTurnaroundMACTime = 0.2 + 0.4 + 7; // in milliseconds + float symbolTime = pow(2, sf) / bw; // in milliseconds + + if (myRegion->wideLora) { + // CAD duration derived from AN1200.22 of SX1280 + return (NUM_SYM_CAD_24GHZ + (2 * sf + 3) / 32) * symbolTime + sumPropagationTurnaroundMACTime; + } else { + // CAD duration for SX127x is max. 2.25 symbols, for SX126x it is number of symbols + 0.5 symbol + return max(2.25, NUM_SYM_CAD + 0.5) * symbolTime + sumPropagationTurnaroundMACTime; + } +} + /** * Some regulatory regions limit xmit power. * This function should be called by subclasses after setting their desired power. It might lower it @@ -637,4 +656,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p) sendingPacket = p; return p->encrypted.size + sizeof(PacketHeader); -} +} \ No newline at end of file diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 652b2269c..41ab0393d 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -83,24 +83,22 @@ class RadioInterface float bw = 125; uint8_t sf = 9; uint8_t cr = 5; - /** Slottime is the minimum time to wait, consisting of: - - CAD duration (maximum of SX126x and SX127x); - - roundtrip air propagation time (assuming max. 30km between nodes); - - Tx/Rx turnaround time (maximum of SX126x and SX127x); - - MAC processing time (measured on T-beam) */ - uint32_t slotTimeMsec = computeSlotTimeMsec(bw, sf); + + const uint8_t NUM_SYM_CAD = 2; // Number of symbols used for CAD, 2 is the default since RadioLib 6.3.0 as per AN1200.48 + const uint8_t NUM_SYM_CAD_24GHZ = 4; // Number of symbols used for CAD in 2.4 GHz, 4 is recommended in AN1200.22 of SX1280 + uint32_t slotTimeMsec = computeSlotTimeMsec(); uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving uint32_t preambleTimeMsec = 165; // calculated on startup, this is the default for LongFast uint32_t maxPacketTimeMsec = 3246; // calculated on startup, this is the default for LongFast const uint32_t PROCESSING_TIME_MSEC = 4500; // time to construct, process and construct a packet again (empirically determined) - const uint8_t CWmin = 2; // minimum CWsize - const uint8_t CWmax = 7; // maximum CWsize + const uint8_t CWmin = 3; // minimum CWsize + const uint8_t CWmax = 8; // maximum CWsize meshtastic_MeshPacket *sendingPacket = NULL; // The packet we are currently sending uint32_t lastTxStart = 0L; - uint32_t computeSlotTimeMsec(float bw, float sf) { return 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7; } + uint32_t computeSlotTimeMsec(); /** * A temporary buffer used for sending/receiving packets, sized to hold the biggest buffer we might need diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index ed0267c5b..59ba139bf 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -299,10 +299,17 @@ template void SX126xInterface::startReceive() template bool SX126xInterface::isChannelActive() { // check if we can detect a LoRa preamble on the current channel + ChannelScanConfig_t cfg = {.cad = {.symNum = NUM_SYM_CAD, + .detPeak = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, + .detMin = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, + .exitMode = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, + .timeout = 0, + .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS, + .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}}; int16_t result; setStandby(); - result = lora.scanChannel(); + result = lora.scanChannel(cfg); if (result == RADIOLIB_LORA_DETECTED) return true; if (result != RADIOLIB_CHANNEL_FREE) diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 013164bca..1ae26db91 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -275,10 +275,17 @@ template void SX128xInterface::startReceive() template bool SX128xInterface::isChannelActive() { // check if we can detect a LoRa preamble on the current channel + ChannelScanConfig_t cfg = {.cad = {.symNum = NUM_SYM_CAD_24GHZ, + .detPeak = 0, + .detMin = 0, + .exitMode = 0, + .timeout = 0, + .irqFlags = RADIOLIB_IRQ_CAD_DEFAULT_FLAGS, + .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK}}; int16_t result; setStandby(); - result = lora.scanChannel(); + result = lora.scanChannel(cfg); if (result == RADIOLIB_LORA_DETECTED) return true; if (result != RADIOLIB_CHANNEL_FREE)