diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index c0610b7f..ef5358b8 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -191,20 +191,24 @@ bool Dispatcher::tryParsePacket(Packet* pkt, const uint8_t* raw, int len) { void Dispatcher::checkRecv() { Packet* pkt; float score; + float snr; + float rssi; uint32_t air_time; { uint8_t raw[MAX_TRANS_UNIT+1]; int len = _radio->recvRaw(raw, MAX_TRANS_UNIT); if (len > 0) { - logRxRaw(_radio->getLastSNR(), _radio->getLastRSSI(), raw, len); + snr = _radio->getLastSNR(); + rssi = _radio->getLastRSSI(); + logRxRaw(snr, rssi, raw, len); pkt = _mgr->allocNew(); if (pkt == NULL) { MESH_DEBUG_PRINTLN("%s Dispatcher::checkRecv(): WARNING: received data, no unused packets available!", getLogDateTime()); } else { if (tryParsePacket(pkt, raw, len)) { - pkt->_snr = _radio->getLastSNR() * 4.0f; - score = _radio->packetScore(_radio->getLastSNR(), len); + pkt->_snr = snr * 4.0f; + score = _radio->packetScore(snr, len); air_time = _radio->getEstAirtimeFor(len); rx_air_time += air_time; } else { @@ -221,7 +225,7 @@ void Dispatcher::checkRecv() { Serial.print(getLogDateTime()); Serial.printf(": RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d time=%d", pkt->getRawLength(), pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, - (int)pkt->getSNR(), (int)_radio->getLastRSSI(), (int)(score*1000), air_time); + (int)pkt->getSNR(), (int)rssi, (int)(score*1000), air_time); static uint8_t packet_hash[MAX_HASH_SIZE]; pkt->calculatePacketHash(packet_hash); @@ -256,6 +260,7 @@ void Dispatcher::checkRecv() { processRecvPacket(pkt); } } + _radio->onReceiveProcessed(); } void Dispatcher::processRecvPacket(Packet* pkt) { @@ -387,4 +392,4 @@ unsigned long Dispatcher::futureMillis(int millis_from_now) const { return _ms->getMillis() + millis_from_now; } -} \ No newline at end of file +} diff --git a/src/Dispatcher.h b/src/Dispatcher.h index 3adf283e..de949b04 100644 --- a/src/Dispatcher.h +++ b/src/Dispatcher.h @@ -31,6 +31,9 @@ public: */ virtual int recvRaw(uint8_t* bytes, int sz) = 0; + /** Called after the received packet and its radio metadata have been processed. */ + virtual void onReceiveProcessed() { } + /** * \returns estimated transmit air-time needed for packet of 'len_bytes', in milliseconds. */ diff --git a/src/helpers/radiolib/CustomLLCC68Wrapper.h b/src/helpers/radiolib/CustomLLCC68Wrapper.h index 8861f76d..e61d8a97 100644 --- a/src/helpers/radiolib/CustomLLCC68Wrapper.h +++ b/src/helpers/radiolib/CustomLLCC68Wrapper.h @@ -22,9 +22,6 @@ public: float getCurrentRSSI() override { return ((CustomLLCC68 *)_radio)->getRSSI(false); } - float getLastRSSI() const override { return ((CustomLLCC68 *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomLLCC68 *)_radio)->getSNR(); } - float packetScore(float snr, int packet_len) override { int sf = ((CustomLLCC68 *)_radio)->spreadingFactor; return packetScoreInt(snr, sf, packet_len); diff --git a/src/helpers/radiolib/CustomLR1110Wrapper.h b/src/helpers/radiolib/CustomLR1110Wrapper.h index 5482d7df..73e31e8a 100644 --- a/src/helpers/radiolib/CustomLR1110Wrapper.h +++ b/src/helpers/radiolib/CustomLR1110Wrapper.h @@ -69,9 +69,6 @@ protected: } public: - float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomLR1110 *)_radio)->getSNR(); } - uint8_t getSpreadingFactor() const override { return ((CustomLR1110 *)_radio)->getSpreadingFactor(); } void setRxBoostedGainMode(bool en) override { diff --git a/src/helpers/radiolib/CustomSTM32WLxWrapper.h b/src/helpers/radiolib/CustomSTM32WLxWrapper.h index 97bf6820..a5f51520 100644 --- a/src/helpers/radiolib/CustomSTM32WLxWrapper.h +++ b/src/helpers/radiolib/CustomSTM32WLxWrapper.h @@ -23,9 +23,6 @@ public: float getCurrentRSSI() override { return ((CustomSTM32WLx *)_radio)->getRSSI(false); } - float getLastRSSI() const override { return ((CustomSTM32WLx *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomSTM32WLx *)_radio)->getSNR(); } - float packetScore(float snr, int packet_len) override { int sf = ((CustomSTM32WLx *)_radio)->spreadingFactor; return packetScoreInt(snr, sf, packet_len); diff --git a/src/helpers/radiolib/CustomSX1262Wrapper.h b/src/helpers/radiolib/CustomSX1262Wrapper.h index eb8c3980..1c9c0ab6 100644 --- a/src/helpers/radiolib/CustomSX1262Wrapper.h +++ b/src/helpers/radiolib/CustomSX1262Wrapper.h @@ -30,9 +30,6 @@ public: float getCurrentRSSI() override { return ((CustomSX1262 *)_radio)->getRSSI(false); } - float getLastRSSI() const override { return ((CustomSX1262 *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomSX1262 *)_radio)->getSNR(); } - float packetScore(float snr, int packet_len) override { int sf = ((CustomSX1262 *)_radio)->spreadingFactor; return packetScoreInt(snr, sf, packet_len); diff --git a/src/helpers/radiolib/CustomSX1268Wrapper.h b/src/helpers/radiolib/CustomSX1268Wrapper.h index 9ddea78f..bf842628 100644 --- a/src/helpers/radiolib/CustomSX1268Wrapper.h +++ b/src/helpers/radiolib/CustomSX1268Wrapper.h @@ -26,9 +26,6 @@ public: float getCurrentRSSI() override { return ((CustomSX1268 *)_radio)->getRSSI(false); } - float getLastRSSI() const override { return ((CustomSX1268 *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomSX1268 *)_radio)->getSNR(); } - float packetScore(float snr, int packet_len) override { int sf = ((CustomSX1268 *)_radio)->spreadingFactor; return packetScoreInt(snr, sf, packet_len); diff --git a/src/helpers/radiolib/CustomSX1276Wrapper.h b/src/helpers/radiolib/CustomSX1276Wrapper.h index 9d75ce12..bba8412f 100644 --- a/src/helpers/radiolib/CustomSX1276Wrapper.h +++ b/src/helpers/radiolib/CustomSX1276Wrapper.h @@ -25,9 +25,6 @@ public: float getCurrentRSSI() override { return ((CustomSX1276 *)_radio)->getRSSI(false); } - float getLastRSSI() const override { return ((CustomSX1276 *)_radio)->getRSSI(); } - float getLastSNR() const override { return ((CustomSX1276 *)_radio)->getSNR(); } - float packetScore(float snr, int packet_len) override { int sf = ((CustomSX1276 *)_radio)->spreadingFactor; return packetScoreInt(snr, sf, packet_len); diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index 07e2136e..297aa367 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -314,9 +314,14 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) { int len = 0; if (state & STATE_INT_READY) { if (isPacketReady()) { + if (_rx_ps_armed) { + stopReceiveDutyCycle(); + } len = _radio->getPacketLength(); if (len > 0) { if (len > sz) { len = sz; } + _last_snr = _radio->getSNR(); + _last_rssi = _radio->getRSSI(); int err = _radio->readData(bytes, len); if (err != RADIOLIB_ERR_NONE) { MESH_DEBUG_PRINTLN("RadioLibWrapper: error: readData(%d)", err); @@ -331,12 +336,44 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) { state = STATE_IDLE; // need another startReceive() } + if (len > 0 && _rx_ps_enabled) { + _rx_hold_continuous = true; + int err = _radio->startReceive(); + if (err == RADIOLIB_ERR_NONE) { + state = STATE_RX; + if (_nf_calib_active) { + _nf_sample_from = millis() + NF_CALIB_SETTLE_MS; + } + } else { + MESH_DEBUG_PRINTLN("RadioLibWrapper: error: startReceive after packet (%d)", err); + } + return len; + } + if (state != STATE_RX) { startRecv(); } return len; } +void RadioLibWrapper::onReceiveProcessed() { + if (!_rx_hold_continuous) return; + + if ((state & ~STATE_INT_READY) == STATE_TX_WAIT) { + _rx_hold_continuous = false; + return; + } + if ((state & STATE_INT_READY) != 0 || isReceivingPacket()) { + return; + } + + _rx_hold_continuous = false; + if (!_rx_ps_enabled || _nf_calib_active) return; + + state = STATE_IDLE; + startRecv(); +} + uint32_t RadioLibWrapper::getEstAirtimeFor(int len_bytes) { return _radio->getTimeOnAir(len_bytes) / 1000; } @@ -403,10 +440,10 @@ bool RadioLibWrapper::isChannelActive() { } float RadioLibWrapper::getLastRSSI() const { - return _radio->getRSSI(); + return _last_rssi; } float RadioLibWrapper::getLastSNR() const { - return _radio->getSNR(); + return _last_snr; } // Approximate SNR threshold per SF for successful reception (based on Semtech datasheets) diff --git a/src/helpers/radiolib/RadioLibWrappers.h b/src/helpers/radiolib/RadioLibWrappers.h index e4eaaa99..24f6da71 100644 --- a/src/helpers/radiolib/RadioLibWrappers.h +++ b/src/helpers/radiolib/RadioLibWrappers.h @@ -16,12 +16,14 @@ protected: mesh::MainBoard* _board; uint32_t n_recv, n_sent, n_recv_errors; int16_t _noise_floor, _threshold; + float _last_rssi, _last_snr; bool _cad_enabled; uint16_t _num_floor_samples; int32_t _floor_sample_sum; uint8_t _preamble_sf; bool _rx_ps_enabled; bool _rx_ps_armed; // radio is currently in RX duty-cycle mode + bool _rx_hold_continuous; uint32_t _rx_ps_rx_us; uint32_t _rx_ps_sleep_us; @@ -81,16 +83,18 @@ protected: public: RadioLibWrapper(PhysicalLayer& radio, mesh::MainBoard& board) : _radio(&radio), _board(&board), _preamble_sf(0), _rx_ps_enabled(false), _rx_ps_armed(false), + _rx_hold_continuous(false), _rx_ps_rx_us(RX_PS_FALLBACK_RX_US), _rx_ps_sleep_us(RX_PS_FALLBACK_SLEEP_US), _wd_last_busy(false), _wd_stage(0), _wd_strikes(0), _startrx_fails(0), _wd_last_transition(0), _wd_stuck_thresh(0), _wd_observe_until(0), _wd_observe_ms(0), _params_valid(false), _dbm_valid(false), _nf_calib_active(false), _nf_last_calib(0), _nf_calib_deadline(0), _nf_sample_from(0) - { n_recv = n_sent = n_recv_errors = n_wd_soft = n_wd_hard = 0; } + { n_recv = n_sent = n_recv_errors = n_wd_soft = n_wd_hard = 0; _last_rssi = _last_snr = 0; } void begin() override; virtual void powerOff() { _radio->sleep(); } int recvRaw(uint8_t* bytes, int sz) override; + void onReceiveProcessed() override; uint32_t getEstAirtimeFor(int len_bytes) override; bool startSendRaw(const uint8_t* bytes, int len) override; bool isSendComplete() override; @@ -136,8 +140,8 @@ public: bool isCalibratingNoiseFloor() const { return _nf_calib_active; } void resetStats() { n_recv = n_sent = n_recv_errors = 0; } - virtual float getLastRSSI() const override; - virtual float getLastSNR() const override; + float getLastRSSI() const override final; + float getLastSNR() const override final; float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10