diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index f211bb7df..9a8c2d502 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -471,6 +471,9 @@ void RadioInterface::applyModemConfig() saveChannelNum(channel_num); saveFreq(freq + loraConfig.frequency_offset); + preambleTimeMsec = getPacketTime((uint32_t)0); + maxPacketTimeMsec = getPacketTime(meshtastic_Constants_DATA_PAYLOAD_LEN + sizeof(PacketHeader)); + LOG_INFO("Radio freq=%.3f, config.lora.frequency_offset=%.3f\n", freq, loraConfig.frequency_offset); LOG_INFO("Set radio: region=%s, name=%s, config=%u, ch=%d, power=%d\n", myRegion->name, channelName, loraConfig.modem_preset, channel_num, power); diff --git a/src/mesh/RadioInterface.h b/src/mesh/RadioInterface.h index 68dbf3522..b5fb5fcd3 100644 --- a/src/mesh/RadioInterface.h +++ b/src/mesh/RadioInterface.h @@ -63,7 +63,9 @@ class RadioInterface - Tx/Rx turnaround time (maximum of SX126x and SX127x); - MAC processing time (measured on T-beam) */ uint32_t slotTimeMsec = 8.5 * pow(2, sf) / bw + 0.2 + 0.4 + 7; - uint16_t preambleLength = 16; // 8 is default, but we use longer to increase the amount of sleep time when receiving + 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 diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 54bc70a73..c4145a30c 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -180,6 +180,7 @@ template void SX126xInterface::setStandby() assert(err == RADIOLIB_ERR_NONE); isReceiving = false; // If we were receiving, not any more + activeReceiveStart = 0; disableInterrupt(); completeSending(); // If we were sending, not anymore } @@ -213,9 +214,10 @@ template void SX126xInterface::startReceive() setStandby(); // We use a 16 bit preamble so this should save some power by letting radio sit in standby mostly. - // Furthermore, we need the HEADER_VALID IRQ flag to detect whether we are actively receiving - int err = - lora.startReceiveDutyCycleAuto(preambleLength, 8, RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_HEADER_VALID); + // Furthermore, we need the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving + int err = lora.startReceiveDutyCycleAuto(preambleLength, 8, + RADIOLIB_SX126X_IRQ_RX_DEFAULT | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED | + RADIOLIB_SX126X_IRQ_HEADER_VALID); assert(err == RADIOLIB_ERR_NONE); isReceiving = true; @@ -248,10 +250,27 @@ template bool SX126xInterface::isActivelyReceiving() // received and handled the interrupt for reading the packet/handling errors. uint16_t irq = lora.getIrqStatus(); - bool headerValid = (irq & RADIOLIB_SX126X_IRQ_HEADER_VALID); + bool detected = (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | RADIOLIB_SX126X_IRQ_RADIOLIB_PREAMBLE_DETECTED)); + // Handle false detections + if (detected) { + uint32_t now = millis(); + if (!activeReceiveStart) { + activeReceiveStart = now; + } else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX126X_IRQ_HEADER_VALID)) { + // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false preamble detection.\n"); + return false; + } else if (now - activeReceiveStart > maxPacketTimeMsec) { + // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false header detection.\n"); + return false; + } + } - // if (headerValid) LOG_DEBUG("rx headerValid\n"); - return headerValid; + // if (detected) LOG_DEBUG("rx detected\n"); + return detected; } template bool SX126xInterface::sleep() diff --git a/src/mesh/SX126xInterface.h b/src/mesh/SX126xInterface.h index a773fd71f..f7ed270d4 100644 --- a/src/mesh/SX126xInterface.h +++ b/src/mesh/SX126xInterface.h @@ -68,4 +68,5 @@ template class SX126xInterface : public RadioLibInterface virtual void setStandby() override; private: + uint32_t activeReceiveStart = 0; }; diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 308e4a52a..aff4c1253 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -157,6 +157,7 @@ template void SX128xInterface::setStandby() #endif isReceiving = false; // If we were receiving, not any more + activeReceiveStart = 0; disableInterrupt(); completeSending(); // If we were sending, not anymore } @@ -203,9 +204,10 @@ template void SX128xInterface::startReceive() digitalWrite(SX128X_TXEN, LOW); #endif - // We use the HEADER_VALID IRQ flag to detect whether we are actively receiving - int err = - lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | RADIOLIB_SX128X_IRQ_HEADER_VALID); + // We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving + int err = lora.startReceive(RADIOLIB_SX128X_RX_TIMEOUT_INF, RADIOLIB_SX128X_IRQ_RX_DEFAULT | + RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED | + RADIOLIB_SX128X_IRQ_HEADER_VALID); assert(err == RADIOLIB_ERR_NONE); @@ -236,8 +238,27 @@ template bool SX128xInterface::isChannelActive() template bool SX128xInterface::isActivelyReceiving() { uint16_t irq = lora.getIrqStatus(); - bool hasHeader = (irq & RADIOLIB_SX128X_IRQ_HEADER_VALID); - return hasHeader; + bool detected = (irq & (RADIOLIB_SX128X_IRQ_HEADER_VALID | RADIOLIB_SX128X_IRQ_RADIOLIB_PREAMBLE_DETECTED)); + + // Handle false detections + if (detected) { + uint32_t now = millis(); + if (!activeReceiveStart) { + activeReceiveStart = now; + } else if ((now - activeReceiveStart > 2 * preambleTimeMsec) && !(irq & RADIOLIB_SX128X_IRQ_HEADER_VALID)) { + // The HEADER_VALID flag should be set by now if it was really a packet, so ignore PREAMBLE_DETECTED flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false preamble detection.\n"); + return false; + } else if (now - activeReceiveStart > maxPacketTimeMsec) { + // We should have gotten an RX_DONE IRQ by now if it was really a packet, so ignore HEADER_VALID flag + activeReceiveStart = 0; + LOG_DEBUG("Ignore false header detection.\n"); + return false; + } + } + + return detected; } template bool SX128xInterface::sleep() diff --git a/src/mesh/SX128xInterface.h b/src/mesh/SX128xInterface.h index 235d39ee0..434d4b1d9 100644 --- a/src/mesh/SX128xInterface.h +++ b/src/mesh/SX128xInterface.h @@ -68,4 +68,5 @@ template class SX128xInterface : public RadioLibInterface virtual void setStandby() override; private: + uint32_t activeReceiveStart = 0; }; diff --git a/variants/rak4631/variant.h b/variants/rak4631/variant.h index 68b2b1172..69a77a029 100644 --- a/variants/rak4631/variant.h +++ b/variants/rak4631/variant.h @@ -126,7 +126,6 @@ static const uint8_t SCK = PIN_SPI_SCK; * eink display pins */ -#define PIN_EINK_EN (32 + 2) // (0 + 2) Note: this is really just backlight power #define PIN_EINK_CS (0 + 26) #define PIN_EINK_BUSY (0 + 4) #define PIN_EINK_DC (0 + 17) diff --git a/variants/rak4631_epaper/variant.h b/variants/rak4631_epaper/variant.h index 3d597d3d1..a43229088 100644 --- a/variants/rak4631_epaper/variant.h +++ b/variants/rak4631_epaper/variant.h @@ -126,7 +126,6 @@ static const uint8_t SCK = PIN_SPI_SCK; * eink display pins */ -#define PIN_EINK_EN (32 + 2) // (0 + 2) Note: this is really just backlight power #define PIN_EINK_CS (0 + 26) #define PIN_EINK_BUSY (0 + 4) #define PIN_EINK_DC (0 + 17) diff --git a/version.properties b/version.properties index e5586844b..b282100fe 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 1 -build = 1 +build = 2