From d15e75dbabe222f206bf16b6d29b5f3d1e27c1aa Mon Sep 17 00:00:00 2001 From: rejoe2 Date: Fri, 9 Feb 2024 11:53:20 +0100 Subject: [PATCH] simplify rxOffset logic - Code cleanup - fix "nRF CE keep high" code (missing argument) --- src/hm/Communication.h | 91 +++++++++++++++++++++--------------------- src/hm/hmDefines.h | 2 +- src/hm/hmInverter.h | 1 - src/hm/hmRadio.h | 42 ++++--------------- src/hm/hmSystem.h | 10 +---- 5 files changed, 55 insertions(+), 91 deletions(-) diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 21b78405..a37bcdb2 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -13,7 +13,7 @@ #include "../utils/timemonitor.h" #include "Heuristic.h" -#define MAX_BUFFER 250 +#define MAX_BUFFER 200 typedef std::function *)> payloadListenerType; typedef std::function *)> powerLimitAckListenerType; @@ -92,6 +92,8 @@ class Communication : public CommQueue<> { q->iv->mIsSingleframeReq = false; mFramesExpected = getFramesExpected(q); // function to get expected frame count. mTimeout = DURATION_TXFRAME + mFramesExpected*DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]; + if((q->iv->ivGen == IV_MI) && ((q->cmd == MI_REQ_CH1) || (q->cmd == MI_REQ_4CH))) + incrAttempt(q->iv->channels); // 2 more attempts for 2ch, 4 more for 4ch mState = States::START; break; @@ -209,7 +211,7 @@ class Communication : public CommQueue<> { } else { if(q->iv->miMultiParts < 6) { mState = States::WAIT; - if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) { + if(q->iv->radio->mRadioWaitTime.isTimeout() && q->attempts) { miRepeatRequest(q); return; } @@ -220,6 +222,10 @@ class Communication : public CommQueue<> { || ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) { miComplete(q->iv); } + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINTLN(F("Payload (MI got all)")); + } closeRequest(q, true); } } @@ -443,9 +449,8 @@ class Communication : public CommQueue<> { || (p->packet[0] == MI_REQ_CH2 + ALL_FRAMES) || ((p->packet[0] >= (MI_REQ_4CH + ALL_FRAMES)) && (p->packet[0] < (0x39 + SINGLE_FRAME)) - )) { //&& (p->packet[0] != (0x0f + ALL_FRAMES)))) { + )) { // small MI or MI 1500 data responses to 0x09, 0x11, 0x36, 0x37, 0x38 and 0x39 - //mPayload[iv->id].txId = p->packet[0]; miDataDecode(p, q); } else if (p->packet[0] == (0x0f + ALL_FRAMES)) { miHwDecode(p, q); @@ -541,14 +546,16 @@ class Communication : public CommQueue<> { len -= 2; - DPRINT_IVID(DBG_INFO, q->iv->id); - DBGPRINT(F("Payload (")); - DBGPRINT(String(len)); - if(*mPrintWholeTrace) { - DBGPRINT(F("): ")); - ah::dumpBuf(mPayload.data(), len); - } else - DBGPRINTLN(F(")")); + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("Payload (")); + DBGPRINT(String(len)); + if(*mPrintWholeTrace) { + DBGPRINT(F("): ")); + ah::dumpBuf(mPayload.data(), len); + } else + DBGPRINTLN(F(")")); + } if(GridOnProFilePara == q->cmd) { q->iv->addGridProfile(mPayload.data(), len); @@ -813,35 +820,21 @@ class Communication : public CommQueue<> { miStsConsolidate(q, datachan, rec, p->packet[23], p->packet[24]); if (p->packet[0] < (0x39 + ALL_FRAMES) ) { - mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), 1); miNextRequest((p->packet[0] - ALL_FRAMES + 1), q); } else { q->iv->miMultiParts = 7; // indicate we are ready } } else if((p->packet[0] == (MI_REQ_CH1 + ALL_FRAMES)) && (q->iv->type == INV_TYPE_2CH)) { - //addImportant(q->iv, MI_REQ_CH2); miNextRequest(MI_REQ_CH2, q); - mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt); - q->iv->mIvRxCnt++; // statistics workaround... + q->iv->mIvRxCnt++; // statistics workaround... - } else { // first data msg for 1ch, 2nd for 2ch + } else // first data msg for 1ch, 2nd for 2ch q->iv->miMultiParts += 6; // indicate we are ready - - } } void miNextRequest(uint8_t cmd, const queue_s *q) { - incrAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types... - if(*mSerialDebug) { - DPRINT_IVID(DBG_WARN, q->iv->id); - DBGPRINT(F("next request (")); - DBGPRINT(String(q->attempts)); - DBGPRINT(F(" attempts left): 0x")); - DBGHEXLN(cmd); - } - - /*if(q->iv->miMultiParts > 5) //if(q->iv->miMultiParts == 7) - q->iv->radioStatistics.rxSuccess++;*/ + mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt); + mHeu.getTxCh(q->iv); q->iv->radioStatistics.ivSent++; mFramesExpected = getFramesExpected(q); @@ -851,6 +844,13 @@ class Communication : public CommQueue<> { q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]); q->iv->miMultiParts = 0; q->iv->mGotFragment = 0; + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("next: (")); + DBGPRINT(String(q->attempts)); + DBGPRINT(F(" attempts left): 0x")); + DBGHEXLN(cmd); + } mIsRetransmit = true; chgCmd(cmd); //mState = States::WAIT; @@ -858,19 +858,17 @@ class Communication : public CommQueue<> { void miRepeatRequest(const queue_s *q) { setAttempt(); // if function is called, we got something, and we necessarily need more transmissions for MI types... + q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true); + q->iv->radioStatistics.retransmits++; + q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]); if(*mSerialDebug) { - DPRINT_IVID(DBG_WARN, q->iv->id); + DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("resend request (")); DBGPRINT(String(q->attempts)); DBGPRINT(F(" attempts left): 0x")); DBGHEXLN(q->cmd); } - - q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true); - q->iv->radioStatistics.retransmits++; - - q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]); - mIsRetransmit = false; + //mIsRetransmit = false; } void miStsConsolidate(const queue_s *q, uint8_t stschan, record_t<> *rec, uint8_t uState, uint8_t uEnum, uint8_t lState = 0, uint8_t lEnum = 0) { @@ -953,11 +951,6 @@ class Communication : public CommQueue<> { void miComplete(Inverter<> *iv) { - if (*mSerialDebug) { - DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINTLN(F("got all data msgs")); - } - if (iv->mGetLossInterval >= AHOY_GET_LOSS_INTERVAL) { // initially mIvRxCnt = mIvTxCnt = 0 iv->mGetLossInterval = 1; iv->radioStatistics.ivSent = iv->mIvRxCnt + iv->mDtuTxCnt; // iv->mIvRxCnt is the nr. of additional answer frames, default we expect one frame per request @@ -966,10 +959,16 @@ class Communication : public CommQueue<> { iv->radioStatistics.dtuSent = iv->mDtuTxCnt; if (*mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINTLN("DTU loss: " + - String (iv->radioStatistics.ivLoss) + "/" + - String (iv->radioStatistics.ivSent) + " frames for " + - String (iv->radioStatistics.dtuSent) + " requests"); + DBGPRINT(F("DTU loss: ") + + String (iv->radioStatistics.ivLoss) + F("/") + + String (iv->radioStatistics.ivSent) + F(" frames for ") + + String (iv->radioStatistics.dtuSent) + F(" requests")); + if(iv->mAckCount) { + DBGPRINT(F(". ACKs: ")); + DBGPRINTLN(String(iv->mAckCount)); + iv->mAckCount = 0; + } else + DBGPRINTLN(F("")); } iv->mIvRxCnt = 0; // start new interval, iVRxCnt is abused to collect additional possible frames iv->mIvTxCnt = 0; // start new interval, iVTxCnt is abused to collect nr. of unanswered requests diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 8fc4f71f..6ba92774 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -89,7 +89,7 @@ const uint8_t duration_reserve[2] = {65, 115}; #define LIMIT_FAST_IV 85 // time limit to qualify an inverter as very fast answering inverter #define LIMIT_VERYFAST_IV 70 // time limit to qualify an inverter as very fast answering inverter #define LIMIT_FAST_IV_MI 35 // time limit to qualify a MI type inverter as fast answering inverter -#define LIMIT_VERYFAST_IV_MI 22 // time limit to qualify a MI type inverter as very fast answering inverter +#define LIMIT_VERYFAST_IV_MI 25 // time limit to qualify a MI type inverter as very fast answering inverter #define RETRIES_FAST_IV 12 // how often shall a message be automatically retransmitted by the nRF (fast answering inverter) #define RETRIES_VERYFAST_IV 9 // how often shall a message be automatically retransmitted by the nRF (very fast answering inverter) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 51cb0d6d..b6dc93fa 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -132,7 +132,6 @@ class Inverter { record_t recordAlarm; // structure for alarm values InverterStatus status = InverterStatus::OFF; // indicates the current inverter status std::array lastAlarm; // holds last 10 alarms - uint8_t rxOffset = 0; // holds the default channel offset between tx and rx channel (nRF only) int8_t rssi = 0; // RSSI uint16_t alarmCnt = 0; // counts the total number of occurred alarms uint16_t alarmLastId = 0; // lastId which was received diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 09500826..b01df277 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -152,31 +152,22 @@ class HmRadio : public Radio { if(tx_ok) mLastIv->mAckCount++; - //#ifdef DYNAMIC_OFFSET - mRxChIdx = (mTxChIdx + mLastIv->rxOffset) % RF_CHANNELS; - /*#else - mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; - #endif*/ + rxOffset = mLastIv->ivGen == IV_HM ? 3 : 2; // holds the default channel offset between tx and rx channel (nRF only) + mRxChIdx = (mTxChIdx + rxOffset) % RF_CHANNELS; mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->startListening(); mTimeslotStart = millis(); tempRxChIdx = mRxChIdx; // might be better to start off with one channel less? mRxPendular = false; - mNRFloopChannels = (mLastIv->ivGen == IV_MI); - - //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME; - //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4; - //innerLoopTimeout = (mLastIv->mIsSingleframeReq || mLastIv->ivGen == IV_MI) ? DURATION_LISTEN_MIN : DURATION_TXFRAME; + mNRFloopChannels = (mLastIv->mCmd == MI_REQ_CH1 || mLastIv->mCmd == MI_REQ_CH1); innerLoopTimeout = DURATION_LISTEN_MIN; } if(rx_ready) { if (getReceived()) { // check what we got, returns true for last package or success for single frame request mNRFisInRX = false; - rx_ready = false; mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions mNrf24->stopListening(); - return false; } else { innerLoopTimeout = DURATION_LISTEN_MIN; mTimeslotStart = millis(); @@ -188,7 +179,6 @@ class HmRadio : public Radio { } else mRxChIdx = tempRxChIdx; } - return true; } rx_ready = false; // reset return mNRFisInRX; @@ -317,9 +307,11 @@ class HmRadio : public Radio { if (p.packet[0] != 0x00) { if(!checkIvSerial(p.packet, mLastIv)) { - DPRINT(DBG_WARN, "RX other inverter "); + DPRINT(DBG_WARN, F("RX other inverter ")); if(!*mPrivacyMode) ah::dumpBuf(p.packet, p.len); + else + DBGPRINTLN(F("")); } else { mLastIv->mGotFragment = true; mBufCtrl.push(p); @@ -331,14 +323,6 @@ class HmRadio : public Radio { if(isLastPackage) setExpectedFrames(p.packet[9] - ALL_FRAMES); - #ifdef DYNAMIC_OFFSET - if((p.packet[9] == 1) && (p.millis < DURATION_ONEFRAME)) - mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + 1) % RF_CHANNELS; - else if(mNRFloopChannels && (mLastIv->rxOffset > RF_CHANNELS)) { // unsure setting? - mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx + (isLastPackage ? mFramesExpected : p.packet[9])); // make clear it's not sure, start with one more offset - mNRFloopChannels = false; - } - #endif } if(IV_MI == mLastIv->ivGen) { @@ -346,10 +330,6 @@ class HmRadio : public Radio { isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received else if ((p.packet[0] != 0x88) && (p.packet[0] != 0x92)) // ignore MI status messages //#0 was p.packet[0] != 0x00 && isLastPackage = true; // response from dev control command - #ifdef DYNAMIC_OFFSET - if((p.packet[9] == 0x00) && (p.millis < DURATION_ONEFRAME)) - mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS; - #endif } rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads } @@ -385,14 +365,7 @@ class HmRadio : public Radio { DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(F(", ")); DBGPRINT(String(mTxRetriesNext)); - //DBGPRINT(F(" retries | ")); - //#ifdef DYNAMIC_OFFSET - DBGPRINT(F(" ret., rx offset: ")); - DBGPRINT(String(iv->rxOffset)); - DBGPRINT(F(" | ")); - /*#else DBGPRINT(F(" ret. | ")); - #endif*/ if(*mPrintWholeTrace) { if(*mPrivacyMode) ah::dumpBuf(mTxBuf.data(), len, 1, 4); @@ -415,7 +388,7 @@ class HmRadio : public Radio { } mNrf24->setChannel(mRfChLst[mTxChIdx]); mNrf24->openWritingPipe(reinterpret_cast(&iv->radioId.u64)); - mNrf24->startFastWrite(mTxBuf.data(), len, false); // false = request ACK response + mNrf24->startFastWrite(mTxBuf.data(), len, false, true); // false (3) = request ACK response; true (4) reset CE to high after transmission mMillis = millis(); mLastIv = iv; @@ -455,6 +428,7 @@ class HmRadio : public Radio { bool mRxPendular = false; uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; uint8_t mTxRetries = 15; // memorize last setting for mNrf24->setRetries(3, 15); + uint8_t rxOffset = 3; // holds the channel offset between tx and rx channel used for actual inverter std::unique_ptr mSpi; std::unique_ptr mNrf24; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 22318347..7e79f30a 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -93,16 +93,8 @@ class HmSystem { DBGPRINTLN(String(iv->config->serial.u64, HEX)); - if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01)) + if(IV_MI == iv->ivGen) DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!")); - - #ifdef DYNAMIC_OFFSET - iv->rxOffset = (iv->ivGen == IV_HM) ? 13 : 12; // effective 3 (or 2), but can easily be recognized as default setting - #else - //iv->rxOffset = ((iv->ivGen == IV_HM) && (iv->type == INV_TYPE_4CH)) ? 3 : 2; - iv->rxOffset = (iv->ivGen == IV_HM) ? 3 : 2; - #endif - cb(iv); }