From 6cbcbbafc55bb51e8b47fd91daf02a2af5556c2a Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 21 Jan 2024 13:55:02 +0100 Subject: [PATCH] 0.8.61 - 2024-01-21 * add favicon to header * improved NRF communication --- src/CHANGES.md | 4 + src/app.cpp | 25 +- src/app.h | 1 + src/defines.h | 2 +- src/hm/Communication.h | 369 +++++++++++++++--------------- src/hm/hmRadio.h | 172 ++++++++------ src/hm/radio.h | 4 +- src/hms/hmsRadio.h | 16 +- src/utils/timemonitor.h | 15 +- src/web/html/includes/header.html | 1 + 10 files changed, 321 insertions(+), 288 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 3aea07d3..2c52b991 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.8.61 - 2024-01-21 +* add favicon to header +* improved NRF communication + ## 0.8.60 - 2024-01-20 * merge PR: non blocking nRF loop #1371 * merge PR: fixed millis in serial log #1373 diff --git a/src/app.cpp b/src/app.cpp index c53efa3b..feeffc57 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -143,19 +143,22 @@ void app::loop(void) { esp_task_wdt_reset(); if(mConfig->nrf.enabled) - mNrfRadio.loop(); - #if defined(ESP32) - if(mConfig->cmt.enabled) - mCmtRadio.loop(); - #endif + mNrfActive = mNrfRadio.loop(); - ah::Scheduler::loop(); - mCommunication.loop(); + if(!mNrfActive) { + #if defined(ESP32) + if(mConfig->cmt.enabled) + mNrfActive = mCmtRadio.loop(); + #endif - #if defined(ENABLE_MQTT) - if (mMqttEnabled && mNetworkConnected) - mMqtt.loop(); - #endif + ah::Scheduler::loop(); + mCommunication.loop(); + + #if defined(ENABLE_MQTT) + if (mMqttEnabled && mNetworkConnected) + mMqtt.loop(); + #endif + } yield(); } diff --git a/src/app.h b/src/app.h index ab7f2dac..7922edfb 100644 --- a/src/app.h +++ b/src/app.h @@ -405,6 +405,7 @@ class app : public IApp, public ah::Scheduler { uint8_t mSendLastIvId; bool mSendFirst; bool mAllIvNotAvail; + bool mNrfActive = false; bool mNetworkConnected; diff --git a/src/defines.h b/src/defines.h index 8f3195f4..8d6a3086 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 8 -#define VERSION_PATCH 60 +#define VERSION_PATCH 61 //------------------------------------- typedef struct { diff --git a/src/hm/Communication.h b/src/hm/Communication.h index d13ca158..59f21d2b 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -61,221 +61,220 @@ class Communication : public CommQueue<> { mLastEmptyQueueMillis = millis(); mPrintSequenceDuration = true; - /*if(mDebugState != mState) { - DPRINT(DBG_INFO, F("State: ")); - DBGHEXLN((uint8_t)(mState)); - mDebugState = mState; - }*/ - switch(mState) { - case States::RESET: - if (!mWaitTime.isTimeout()) - return; + innerLoop(q); + }); + } - mMaxFrameId = 0; - for(uint8_t i = 0; i < MAX_PAYLOAD_ENTRIES; i++) { - mLocalBuf[i].len = 0; - } + private: + inline void innerLoop(const queue_s *q) { + switch(mState) { + case States::RESET: + if (!mWaitTime.isTimeout()) + return; + + mMaxFrameId = 0; + for(uint8_t i = 0; i < MAX_PAYLOAD_ENTRIES; i++) { + mLocalBuf[i].len = 0; + } - if(*mSerialDebug) - mHeu.printStatus(q->iv); - mHeu.getTxCh(q->iv); - q->iv->mGotFragment = false; - q->iv->mGotLastMsg = false; - q->iv->curFrmCnt = 0; - mIsRetransmit = false; - if(NULL == q->iv->radio) - cmdDone(false); // can't communicate while radio is not defined! - mFirstTry = q->iv->isAvailable(); - q->iv->mCmd = q->cmd; - q->iv->mIsSingleframeReq = false; - mFramesExpected = getFramesExpected(q); // function to get expected frame count. - mTimeout = DURATION_TXFRAME + mFramesExpected*DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]; - - mState = States::START; - break; + if(*mSerialDebug) + mHeu.printStatus(q->iv); + mHeu.getTxCh(q->iv); + q->iv->mGotFragment = false; + q->iv->mGotLastMsg = false; + q->iv->curFrmCnt = 0; + mIsRetransmit = false; + if(NULL == q->iv->radio) + cmdDone(false); // can't communicate while radio is not defined! + mFirstTry = q->iv->isAvailable(); + q->iv->mCmd = q->cmd; + q->iv->mIsSingleframeReq = false; + mFramesExpected = getFramesExpected(q); // function to get expected frame count. + mTimeout = DURATION_TXFRAME + mFramesExpected*DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]; + + mState = States::START; + break; - case States::START: - setTs(mTimestamp); - if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) { - // frequency was changed during runtime - if(q->iv->curCmtFreq != q->iv->config->frequency) { - if(q->iv->radio->switchFrequencyCh(q->iv, q->iv->curCmtFreq, q->iv->config->frequency)) - q->iv->curCmtFreq = q->iv->config->frequency; - } + case States::START: + setTs(mTimestamp); + if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) { + // frequency was changed during runtime + if(q->iv->curCmtFreq != q->iv->config->frequency) { + if(q->iv->radio->switchFrequencyCh(q->iv, q->iv->curCmtFreq, q->iv->config->frequency)) + q->iv->curCmtFreq = q->iv->config->frequency; } + } - if(q->isDevControl) { - if(ActivePowerContr == q->cmd) - q->iv->powerLimitAck = false; - q->iv->radio->sendControlPacket(q->iv, q->cmd, q->iv->powerLimit, false); - } else - q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); + if(q->isDevControl) { + if(ActivePowerContr == q->cmd) + q->iv->powerLimitAck = false; + q->iv->radio->sendControlPacket(q->iv, q->cmd, q->iv->powerLimit, false); + } else + q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); + + q->iv->radioStatistics.txCnt++; + q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout); + + mIsRetransmit = false; + setAttempt(); + if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara)) + incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA); + mState = States::WAIT; + break; - q->iv->radioStatistics.txCnt++; - q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout); + case States::WAIT: + if (!q->iv->radio->mRadioWaitTime.isTimeout()) + return; + mState = States::CHECK_FRAMES; + break; - mIsRetransmit = false; - setAttempt(); - if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara)) - incrAttempt(q->cmd == AlarmData? MORE_ATTEMPS_ALARMDATA : MORE_ATTEMPS_GRIDONPROFILEPARA); - mState = States::WAIT; + case States::CHECK_FRAMES: { + if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) || (0 == q->attempts)) { // radio buffer empty or no more answers + if(*mSerialDebug) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("request timeout: ")); + DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime())); + DBGPRINTLN(F("ms")); + } + if(!q->iv->mGotFragment) { + if(q->iv->ivRadioType == INV_RADIO_TYPE_CMT) { + q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ)); + mWaitTime.startTimeMonitor(1000); + } else { + if(IV_MI == q->iv->ivGen) + q->iv->mIvTxCnt++; + if(mFirstTry) { + mFirstTry = false; + setAttempt(); + mHeu.evalTxChQuality(q->iv, false, 0, 0); + //q->iv->radioStatistics.rxFailNoAnser++; + q->iv->radioStatistics.retransmits++; + q->iv->radio->mRadioWaitTime.stopTimeMonitor(); + mState = States::START; + + return; + } + } + } + closeRequest(q, false); break; + } + mFirstTry = false; // for correct reset + if((IV_MI != q->iv->ivGen) || (0 == q->attempts)) + mIsRetransmit = false; - case States::WAIT: - if (!q->iv->radio->mRadioWaitTime.isTimeout()) - return; - mState = States::CHECK_FRAMES; - break; + while(!q->iv->radio->mBufCtrl.empty()) { + packet_t *p = &q->iv->radio->mBufCtrl.front(); - case States::CHECK_FRAMES: { - if((q->iv->radio->mBufCtrl.empty() && !mIsRetransmit) || (0 == q->attempts)) { // radio buffer empty or no more answers - if(*mSerialDebug) { - DPRINT_IVID(DBG_INFO, q->iv->id); - DBGPRINT(F("request timeout: ")); - DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime())); - DBGPRINTLN(F("ms")); - } - if(!q->iv->mGotFragment) { - if(q->iv->ivRadioType == INV_RADIO_TYPE_CMT) { - q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ)); - mWaitTime.startTimeMonitor(1000); - } else { - if(IV_MI == q->iv->ivGen) - q->iv->mIvTxCnt++; - if(mFirstTry) { - mFirstTry = false; - setAttempt(); - mHeu.evalTxChQuality(q->iv, false, 0, 0); - //q->iv->radioStatistics.rxFailNoAnser++; - q->iv->radioStatistics.retransmits++; - q->iv->radio->mRadioWaitTime.stopTimeMonitor(); - mState = States::START; - - return; - } - } + if(validateIvSerial(&p->packet[1], q->iv)) { + printRxInfo(q, p); + q->iv->radioStatistics.frmCnt++; + q->iv->mDtuRxCnt++; + + if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command + if(parseFrame(p)) + q->iv->curFrmCnt++; + } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command + if(parseDevCtrl(p, q)) + closeRequest(q, true); + else + closeRequest(q, false); + q->iv->radio->mBufCtrl.pop(); + return; // don't wait for empty buffer + } else if(IV_MI == q->iv->ivGen) { + if(parseMiFrame(p, q)) + q->iv->curFrmCnt++; } - closeRequest(q, false); - break; - } - mFirstTry = false; // for correct reset - if((IV_MI != q->iv->ivGen) || (0 == q->attempts)) - mIsRetransmit = false; - - while(!q->iv->radio->mBufCtrl.empty()) { - packet_t *p = &q->iv->radio->mBufCtrl.front(); - - if(validateIvSerial(&p->packet[1], q->iv)) { - printRxInfo(q, p); - q->iv->radioStatistics.frmCnt++; - q->iv->mDtuRxCnt++; - - if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command - if(parseFrame(p)) - q->iv->curFrmCnt++; - } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command - if(parseDevCtrl(p, q)) - closeRequest(q, true); - else - closeRequest(q, false); - q->iv->radio->mBufCtrl.pop(); - return; // don't wait for empty buffer - } else if(IV_MI == q->iv->ivGen) { - if(parseMiFrame(p, q)) - q->iv->curFrmCnt++; - } - } //else -> serial does not match + } //else -> serial does not match - q->iv->radio->mBufCtrl.pop(); - yield(); - } + q->iv->radio->mBufCtrl.pop(); + yield(); + } - if(q->iv->ivGen != IV_MI) { - mState = States::CHECK_PACKAGE; + if(q->iv->ivGen != IV_MI) { + mState = States::CHECK_PACKAGE; + } else { + bool fastNext = true; + if(q->iv->miMultiParts < 6) { + mState = States::WAIT; + if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) { + miRepeatRequest(q); + return; + } } else { - bool fastNext = true; - if(q->iv->miMultiParts < 6) { - mState = States::WAIT; - if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) { - miRepeatRequest(q); - return; - } - } else { - mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt); - if(((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH)) - || ((q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH)) - || ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) { - miComplete(q->iv); - fastNext = false; - } - if(fastNext) - miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q); - else - closeRequest(q, true); + mHeu.evalTxChQuality(q->iv, true, (q->attemptsMax - 1 - q->attempts), q->iv->curFrmCnt); + if(((q->cmd == 0x39) && (q->iv->type == INV_TYPE_4CH)) + || ((q->cmd == MI_REQ_CH2) && (q->iv->type == INV_TYPE_2CH)) + || ((q->cmd == MI_REQ_CH1) && (q->iv->type == INV_TYPE_1CH))) { + miComplete(q->iv); + fastNext = false; } + if(fastNext) + miNextRequest(q->iv->type == INV_TYPE_4CH ? MI_REQ_4CH : MI_REQ_CH1, q); + else + closeRequest(q, true); } + } - } - break; + } + break; - case States::CHECK_PACKAGE: - uint8_t framnr = 0; - if(0 == mMaxFrameId) { - uint8_t i = 0; - while(i < MAX_PAYLOAD_ENTRIES) { - if(mLocalBuf[i].len == 0) { - framnr = i+1; - break; - } - i++; + case States::CHECK_PACKAGE: + uint8_t framnr = 0; + if(0 == mMaxFrameId) { + uint8_t i = 0; + while(i < MAX_PAYLOAD_ENTRIES) { + if(mLocalBuf[i].len == 0) { + framnr = i+1; + break; } + i++; } + } - if(!framnr) { - for(uint8_t i = 0; i < mMaxFrameId; i++) { - if(mLocalBuf[i].len == 0) { - framnr = i+1; - break; - } + if(!framnr) { + for(uint8_t i = 0; i < mMaxFrameId; i++) { + if(mLocalBuf[i].len == 0) { + framnr = i+1; + break; } } + } - if(framnr) { - if(0 == q->attempts) { - DPRINT_IVID(DBG_INFO, q->iv->id); - DBGPRINT(F("no attempts left")); - closeRequest(q, false); - return; - } - setAttempt(); - - if(*mSerialDebug) { - DPRINT_IVID(DBG_WARN, q->iv->id); - DBGPRINT(F("frame ")); - DBGPRINT(String(framnr)); - DBGPRINT(F(" missing: request retransmit (")); - DBGPRINT(String(q->attempts)); - DBGPRINTLN(F(" attempts left)")); - } - if (!mIsRetransmit) - q->iv->mIsSingleframeReq = true; - sendRetransmit(q, (framnr-1)); - mIsRetransmit = true; + if(framnr) { + if(0 == q->attempts) { + DPRINT_IVID(DBG_INFO, q->iv->id); + DBGPRINT(F("no attempts left")); + closeRequest(q, false); return; } + setAttempt(); + + if(*mSerialDebug) { + DPRINT_IVID(DBG_WARN, q->iv->id); + DBGPRINT(F("frame ")); + DBGPRINT(String(framnr)); + DBGPRINT(F(" missing: request retransmit (")); + DBGPRINT(String(q->attempts)); + DBGPRINTLN(F(" attempts left)")); + } + if (!mIsRetransmit) + q->iv->mIsSingleframeReq = true; + sendRetransmit(q, (framnr-1)); + mIsRetransmit = true; + return; + } - compilePayload(q); + compilePayload(q); - if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd) && (GetLossRate != q->cmd)) - (mCbPayload)(q->cmd, q->iv); + if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd) && (GetLossRate != q->cmd)) + (mCbPayload)(q->cmd, q->iv); - closeRequest(q, true); - break; - } - }); + closeRequest(q, true); + break; + } } - private: inline void printRxInfo(const queue_s *q, packet_t *p) { DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("RX ")); @@ -1006,8 +1005,6 @@ class Communication : public CommQueue<> { Heuristic mHeu; uint32_t mLastEmptyQueueMillis = 0; bool mPrintSequenceDuration = false; - - //States mDebugState = States::START; }; #endif /*__COMMUNICATION_H__*/ diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 8bb3a2a1..d298afd3 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -48,8 +48,8 @@ class HmRadio : public Radio { pinMode(irq, INPUT_PULLUP); - mSerialDebug = serialDebug; - mPrivacyMode = privacyMode; + mSerialDebug = serialDebug; + mPrivacyMode = privacyMode; mPrintWholeTrace = printWholeTrace; generateDtuSn(); @@ -78,7 +78,7 @@ class HmRadio : public Radio { #else mNrf24->begin(mSpi.get(), ce, cs); #endif - mNrf24->setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms + mNrf24->setRetries(3, 15); // 3*250us + 250us and 16 loops -> 15.25ms mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->startListening(); @@ -89,10 +89,7 @@ class HmRadio : public Radio { mNrf24->setCRCLength(RF24_CRC_16); mNrf24->setAddressWidth(5); mNrf24->openReadingPipe(1, reinterpret_cast(&DTU_RADIO_ID)); - - // enable all receiving interrupts - mNrf24->maskIRQ(false, false, false); - + mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts mNrf24->setPALevel(1); // low is default if(mNrf24->isChipConnected()) { @@ -104,25 +101,23 @@ class HmRadio : public Radio { DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); } - void loop(void) { + // returns true if communication is active + bool loop(void) { if (!mIrqRcvd && !mNRFisInRX) - return; // first quick check => nothing to do at all here + return false; // first quick check => nothing to do at all here if(NULL == mLastIv) // prevent reading on NULL object! - return; + return false; if(!mIrqRcvd) { // no news from nRF, check timers + if ((millis() - mTimeslotStart) < innerLoopTimeout) + return true; // nothing to do, still waiting + if (mRadioWaitTime.isTimeout()) { // timeout reached! mNRFisInRX = false; - // add stop listening? - return; + return false; } - yield(); - - if ((millis() - mTimeslotStart) < innerLoopTimeout) - return; // nothing to do - // otherwise switch to next RX channel mTimeslotStart = millis(); if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME))) @@ -140,60 +135,78 @@ class HmRadio : public Radio { mNrf24->setChannel(mRfChLst[tempRxChIdx]); isRxInit = false; - return; - } + return true; // communicating, but changed RX channel + } else { + // here we got news from the nRF + mIrqRcvd = false; + mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH + mLastIrqTime = millis(); - // here we got news from the nRF + if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening + mNrf24->flush_tx(); // empty TX FIFO + mTxSetupTime = millis() - mMillis; - mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH - mIrqRcvd = false; - mLastIrqTime = millis(); + if(mNRFisInRX) { + DPRINTLN(DBG_WARN, F("unexpected tx irq!")); + return false; + } - if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening - mNrf24->flush_tx(); // empty TX FIFO + mNRFisInRX = true; + if(tx_ok) + mLastIv->mAckCount++; - if(mNRFisInRX) { - DPRINTLN(DBG_WARN, F("unexpected tx irq!")); - return; - } + // start listening + if(!mIsRetransmit) { + if(mTxSetupTime < 30) { + mRxChIdx = (mTxChIdx + 4) % RF_CHANNELS; + mNrf24->setChannel(mRfChLst[mRxChIdx]); + mNrf24->startListening(); - mNRFisInRX = true; - if(tx_ok) - mLastIv->mAckCount++; - - // start listening - mRxChIdx = (mTxChIdx + 2 ) % RF_CHANNELS; - mNrf24->setChannel(mRfChLst[mRxChIdx]); - mNrf24->startListening(); - mTimeslotStart = millis(); - tempRxChIdx = mRxChIdx; - rxPendular = false; - mNRFloopChannels = mLastIv->ivGen == IV_MI; + do { + yield(); + } while((millis() - mMillis) < 37); + } + } + mIsRetransmit = false; - innerLoopTimeout = DURATION_TXFRAME; - } - if(rx_ready) { - if (getReceived()) { // check what we got, returns true for last package - mNRFisInRX = false; - mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions - // add stop listening? - } else { - innerLoopTimeout = DURATION_LISTEN_MIN; + mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; + mNrf24->setChannel(mRfChLst[mRxChIdx]); + mNrf24->startListening(); mTimeslotStart = millis(); - if (!mNRFloopChannels) { - //rxPendular = true; // stay longer on the next rx channel - if (isRxInit) { - isRxInit = false; - tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS; - mNrf24->setChannel(mRfChLst[tempRxChIdx]); - } else - mRxChIdx = tempRxChIdx; - } + tempRxChIdx = mRxChIdx; + rxPendular = false; + mNRFloopChannels = (mLastIv->ivGen == IV_MI); + + innerLoopTimeout = DURATION_TXFRAME; } - return; + + if(rx_ready) { + if (getReceived()) { // check what we got, returns true for last package + mNRFisInRX = false; + mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first end his transmissions + // add stop listening? + } else { + innerLoopTimeout = DURATION_LISTEN_MIN; + mTimeslotStart = millis(); + if (!mNRFloopChannels) { + //rxPendular = true; // stay longer on the next rx channel + if (isRxInit) { + isRxInit = false; + tempRxChIdx = (mRxChIdx + 4) % RF_CHANNELS; + mNrf24->setChannel(mRfChLst[tempRxChIdx]); + } else + mRxChIdx = tempRxChIdx; + } + } + return mNRFisInRX; + } /*else if(tx_fail) { + mNRFisInRX = false; + return false; + }*/ } + return false; } bool isChipConnected(void) { @@ -283,6 +296,7 @@ class HmRadio : public Radio { } cnt++; } + sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen)); } @@ -298,36 +312,38 @@ class HmRadio : public Radio { private: inline bool getReceived(void) { - bool isLastPackage = false; rx_ready = false; // reset for ACK case + while(mNrf24->available()) { - uint8_t len; - len = mNrf24->getDynamicPayloadSize(); // if payload size > 32, corrupt payload has been flushed + uint8_t len = mNrf24->getDynamicPayloadSize(); // payload size > 32 -> corrupt payload + if (len > 0) { packet_t p; - p.ch = mRfChLst[tempRxChIdx]; - p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len; + p.ch = mRfChLst[tempRxChIdx]; + p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len; p.rssi = mNrf24->testRPD() ? -64 : -75; p.millis = millis() - mMillis; mNrf24->read(p.packet, p.len); + if (p.packet[0] != 0x00) { if(!checkIvSerial(p.packet, mLastIv)) { DPRINT(DBG_WARN, "RX other inverter "); - if(*mPrivacyMode) - ah::dumpBuf(p.packet, p.len, 1, 4); - else + if(!*mPrivacyMode) ah::dumpBuf(p.packet, p.len); - //return false; } else { mLastIv->mGotFragment = true; mBufCtrl.push(p); + if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received - else if (p.packet[0] == ( 0x0f + ALL_FRAMES) ) // response from MI get information command - 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 + + if(IV_MI == mLastIv->ivGen) { + if (p.packet[0] == (0x0f + ALL_FRAMES)) // response from MI get information command + 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 + } rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads } } @@ -347,6 +363,12 @@ class HmRadio : public Radio { mTxChIdx = iv->heuristics.txRfChId; if(*mSerialDebug) { + if(!isRetransmit) { + DPRINT(DBG_INFO, "last tx setup: "); + DBGPRINT(String(mTxSetupTime)); + DBGPRINTLN("ms"); + } + DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F("TX ")); DBGPRINT(String(len)); @@ -376,7 +398,7 @@ class HmRadio : public Radio { mLastIv = iv; iv->mDtuTxCnt++; mNRFisInRX = false; - mRqstGetRx = true; // preparation only + mIsRetransmit = isRetransmit; } uint64_t getIvId(Inverter<> *iv) { @@ -410,6 +432,8 @@ class HmRadio : public Radio { bool isRxInit = true; bool rxPendular = false; uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; + uint8_t mTxSetupTime = 0; + bool mIsRetransmit = false; std::unique_ptr mSpi; std::unique_ptr mNrf24; diff --git a/src/hm/radio.h b/src/hm/radio.h index 1db0b361..09bd9134 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -28,8 +28,7 @@ class Radio { virtual bool switchFrequency(Inverter<> *iv, uint32_t fromkHz, uint32_t tokHz) { return true; } virtual bool switchFrequencyCh(Inverter<> *iv, uint8_t fromCh, uint8_t toCh) { return true; } virtual bool isChipConnected(void) { return false; } - - virtual void loop(void) {}; + virtual bool loop(void) = 0; void handleIntr(void) { mIrqRcvd = true; @@ -126,7 +125,6 @@ class Radio { uint32_t mDtuSn; volatile bool mIrqRcvd; - bool mRqstGetRx; bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; uint8_t mFramesExpected = 0x0c; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 1506f3fa..48ff3750 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -26,15 +26,16 @@ class CmtRadio : public Radio { mPrintWholeTrace = printWholeTrace; } - void loop() { + bool loop() { mCmt.loop(); if((!mIrqRcvd) && (!mRqstGetRx)) - return; + return false; getRx(); if(CMT_SUCCESS == mCmt.goRx()) { mIrqRcvd = false; mRqstGetRx = false; } + return false; } bool isChipConnected(void) { @@ -134,8 +135,8 @@ class CmtRadio : public Radio { mCmt.goRx(); } - mIrqRcvd = false; - mRqstGetRx = false; + mIrqRcvd = false; + mRqstGetRx = false; } inline void sendSwitchChCmd(Inverter<> *iv, uint8_t ch) { @@ -163,11 +164,16 @@ class CmtRadio : public Radio { uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi); if(CMT_SUCCESS == status) mBufCtrl.push(p); + + // this code completly stops communication! + //if(p.packet[9] > ALL_FRAMES) // indicates last frame + // mRadioWaitTime.stopTimeMonitor(); // we got everything we expected and can exit rx mode... + //optionally instead: mRadioWaitTime.startTimeMonitor(DURATION_PAUSE_LASTFR); // let the inverter first get back to rx mode? } CmtType mCmt; - //bool mRqstGetRx; bool mCmtAvail; + bool mRqstGetRx = false; uint32_t mMillis; }; diff --git a/src/utils/timemonitor.h b/src/utils/timemonitor.h index 798077d5..9f99cc92 100644 --- a/src/utils/timemonitor.h +++ b/src/utils/timemonitor.h @@ -20,16 +20,14 @@ class TimeMonitor { public: /** - * A constructor for initializing a TimeMonitor - * @note TimeMonitor witch default constructor is stopped + * A constructor for creating a TimeMonitor object */ TimeMonitor(void) {} /** - * A constructor for initializing a TimeMonitor + * A constructor for initializing a TimeMonitor object * @param timeout timeout in ms * @param start (optional) if true, start TimeMonitor immediately - * @note TimeMonitor witch default constructor is stopped */ TimeMonitor(uint32_t timeout, bool start = false) { if (start) @@ -50,7 +48,8 @@ class TimeMonitor { /** * Restart the TimeMonitor with already set timeout configuration - * @note returns nothing + * @note a timeout has to be set before, no need to call + * 'startTimeMonitor' before */ void reStartTimeMonitor(void) { mStartTime = millis(); @@ -82,7 +81,7 @@ class TimeMonitor { * false: TimeMonitor still in time or TimeMonitor was stopped */ bool isTimeout(void) { - if ((mStarted) && (millis() - mStartTime >= mTimeout)) + if ((mStarted) && ((millis() - mStartTime) >= mTimeout)) return true; else return false; @@ -104,7 +103,7 @@ class TimeMonitor { */ uint32_t getResidualTime(void) const { uint32_t delayed = millis() - mStartTime; - return(mStarted ? (delayed < mTimeout ? mTimeout - delayed : 0UL) : 0xFFFFFFFFUL); + return(mStarted ? (delayed < mTimeout ? (mTimeout - delayed) : 0UL) : 0xFFFFFFFFUL); } /** @@ -123,4 +122,4 @@ class TimeMonitor { bool mStarted = false; // start/stop state of the TimeMonitor }; -#endif \ No newline at end of file +#endif diff --git a/src/web/html/includes/header.html b/src/web/html/includes/header.html index c363304c..e02b3f42 100644 --- a/src/web/html/includes/header.html +++ b/src/web/html/includes/header.html @@ -4,3 +4,4 @@ +