Browse Source

Merge branch 'development03' of https://github.com/rejoe2/ahoy into rejoe2-development03

pull/1376/head
lumapu 1 year ago
parent
commit
8a7d6a0297
  1. 2
      src/app.cpp
  2. 1
      src/app.h
  3. 4
      src/hm/CommQueue.h
  4. 100
      src/hm/Communication.h
  5. 7
      src/hm/hmDefines.h
  6. 9
      src/hm/hmInverter.h
  7. 130
      src/hm/hmRadio.h
  8. 16
      src/hm/hmSystem.h
  9. 9
      src/hm/radio.h
  10. 5
      src/hms/hmsRadio.h

2
src/app.cpp

@ -7,8 +7,6 @@
#include "app.h" #include "app.h"
#include "utils/sun.h" #include "utils/sun.h"
#define WDT_TIMEOUT_SECONDS 8 // Watchdog Timeout 8s
#if !defined(ESP32) #if !defined(ESP32)
void esp_task_wdt_reset() {} void esp_task_wdt_reset() {}
#endif #endif

1
src/app.h

@ -10,6 +10,7 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#if defined(ESP32) #if defined(ESP32)
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
#define WDT_TIMEOUT_SECONDS 8 // Watchdog Timeout 8s
#endif #endif
#include "config/settings.h" #include "config/settings.h"

4
src/hm/CommQueue.h

@ -12,8 +12,8 @@
#include "../utils/dbg.h" #include "../utils/dbg.h"
#define DEFAULT_ATTEMPS 5 #define DEFAULT_ATTEMPS 5
#define MORE_ATTEMPS_ALARMDATA 15 #define MORE_ATTEMPS_ALARMDATA 8
#define MORE_ATTEMPS_GRIDONPROFILEPARA 15 #define MORE_ATTEMPS_GRIDONPROFILEPARA 5
template <uint8_t N=100> template <uint8_t N=100>
class CommQueue { class CommQueue {

100
src/hm/Communication.h

@ -12,10 +12,6 @@
#include "../utils/timemonitor.h" #include "../utils/timemonitor.h"
#include "Heuristic.h" #include "Heuristic.h"
#define MI_TIMEOUT 250 // timeout for MI type requests
#define FRSTMSG_TIMEOUT 150 // how long to wait for first msg to be received
#define DEFAULT_TIMEOUT 500 // timeout for regular requests
#define SINGLEFR_TIMEOUT 100 // timeout for single frame requests
#define MAX_BUFFER 250 #define MAX_BUFFER 250
typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType; typedef std::function<void(uint8_t, Inverter<> *)> payloadListenerType;
@ -65,8 +61,6 @@ class Communication : public CommQueue<> {
mLastEmptyQueueMillis = millis(); mLastEmptyQueueMillis = millis();
mPrintSequenceDuration = true; mPrintSequenceDuration = true;
uint16_t timeout = (q->iv->ivGen == IV_MI) ? MI_TIMEOUT : (((q->iv->mGotFragment && q->iv->mGotLastMsg) || mIsRetransmit) ? SINGLEFR_TIMEOUT : ((q->cmd != AlarmData) && (q->cmd != GridOnProFilePara) ? DEFAULT_TIMEOUT : (1.5 * DEFAULT_TIMEOUT)));
/*if(mDebugState != mState) { /*if(mDebugState != mState) {
DPRINT(DBG_INFO, F("State: ")); DPRINT(DBG_INFO, F("State: "));
DBGHEXLN((uint8_t)(mState)); DBGHEXLN((uint8_t)(mState));
@ -94,12 +88,15 @@ class Communication : public CommQueue<> {
mFirstTry = q->iv->isAvailable(); mFirstTry = q->iv->isAvailable();
q->iv->mCmd = q->cmd; q->iv->mCmd = q->cmd;
q->iv->mIsSingleframeReq = false; 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; mState = States::START;
break; break;
case States::START: case States::START:
setTs(mTimestamp); setTs(mTimestamp);
if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) { if(q->iv->ivRadioType == INV_RADIO_TYPE_CMT) {
// frequency was changed during runtime // frequency was changed during runtime
if(q->iv->curCmtFreq != q->iv->config->frequency) { if(q->iv->curCmtFreq != q->iv->config->frequency) {
if(q->iv->radio->switchFrequencyCh(q->iv, q->iv->curCmtFreq, q->iv->config->frequency)) if(q->iv->radio->switchFrequencyCh(q->iv, q->iv->curCmtFreq, q->iv->config->frequency))
@ -115,7 +112,8 @@ class Communication : public CommQueue<> {
q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false); q->iv->radio->prepareDevInformCmd(q->iv, q->cmd, q->ts, q->iv->alarmLastId, false);
q->iv->radioStatistics.txCnt++; q->iv->radioStatistics.txCnt++;
mWaitTime.startTimeMonitor(timeout); q->iv->radio->mRadioWaitTime.startTimeMonitor(mTimeout);
mIsRetransmit = false; mIsRetransmit = false;
setAttempt(); setAttempt();
if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara)) if((q->cmd == AlarmData) || (q->cmd == GridOnProFilePara))
@ -124,7 +122,7 @@ class Communication : public CommQueue<> {
break; break;
case States::WAIT: case States::WAIT:
if (!mWaitTime.isTimeout()) if (!q->iv->radio->mRadioWaitTime.isTimeout())
return; return;
mState = States::CHECK_FRAMES; mState = States::CHECK_FRAMES;
break; break;
@ -134,11 +132,11 @@ class Communication : public CommQueue<> {
if(*mSerialDebug) { if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id); DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("request timeout: ")); DBGPRINT(F("request timeout: "));
DBGPRINT(String(mWaitTime.getRunTime())); DBGPRINT(String(q->iv->radio->mRadioWaitTime.getRunTime()));
DBGPRINTLN(F("ms")); DBGPRINTLN(F("ms"));
} }
if(!q->iv->mGotFragment) { if(!q->iv->mGotFragment) {
if((IV_HMS == q->iv->ivGen) || (IV_HMT == q->iv->ivGen)) { 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)); q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ));
mWaitTime.startTimeMonitor(1000); mWaitTime.startTimeMonitor(1000);
} else { } else {
@ -150,13 +148,9 @@ class Communication : public CommQueue<> {
mHeu.evalTxChQuality(q->iv, false, 0, 0); mHeu.evalTxChQuality(q->iv, false, 0, 0);
//q->iv->radioStatistics.rxFailNoAnser++; //q->iv->radioStatistics.rxFailNoAnser++;
q->iv->radioStatistics.retransmits++; q->iv->radioStatistics.retransmits++;
mWaitTime.stopTimeMonitor(); q->iv->radio->mRadioWaitTime.stopTimeMonitor();
mState = States::START; mState = States::START;
/*if(*mSerialDebug) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINTLN(F("second try"));
}*/
return; return;
} }
} }
@ -196,18 +190,13 @@ class Communication : public CommQueue<> {
yield(); yield();
} }
/*if(0 == q->attempts) {
DPRINT_IVID(DBG_INFO, q->iv->id);
DBGPRINT(F("no attempts left"));
closeRequest(q, false);
} else {*/
if(q->iv->ivGen != IV_MI) { if(q->iv->ivGen != IV_MI) {
mState = States::CHECK_PACKAGE; mState = States::CHECK_PACKAGE;
} else { } else {
bool fastNext = true; bool fastNext = true;
if(q->iv->miMultiParts < 6) { if(q->iv->miMultiParts < 6) {
mState = States::WAIT; mState = States::WAIT;
if((mWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) { if((q->iv->radio->mRadioWaitTime.isTimeout() && mIsRetransmit) || !mIsRetransmit) {
miRepeatRequest(q); miRepeatRequest(q);
return; return;
} }
@ -225,7 +214,6 @@ class Communication : public CommQueue<> {
closeRequest(q, true); closeRequest(q, true);
} }
} }
//}
} }
break; break;
@ -296,7 +284,7 @@ class Communication : public CommQueue<> {
DBGPRINT(String(p->millis)); DBGPRINT(String(p->millis));
DBGPRINT(F("ms | ")); DBGPRINT(F("ms | "));
DBGPRINT(String(p->len)); DBGPRINT(String(p->len));
if((IV_HM == q->iv->ivGen) || (IV_MI == q->iv->ivGen)) { if(q->iv->ivRadioType == INV_RADIO_TYPE_NRF) {
DBGPRINT(F(" CH")); DBGPRINT(F(" CH"));
if(3 == p->ch) if(3 == p->ch)
DBGPRINT(F("0")); DBGPRINT(F("0"));
@ -321,6 +309,51 @@ class Communication : public CommQueue<> {
} }
} }
inline uint8_t getFramesExpected(const queue_s *q) {
if(q->isDevControl)
return 1;
if(q->iv->ivGen != IV_MI) {
if (q->cmd == RealTimeRunData_Debug) {
uint8_t framecnt[4] = {2, 3, 4, 7};
return framecnt[q->iv->type];
}
switch (q->cmd) {
case InverterDevInform_All:
case GetLossRate:
case SystemConfigPara:
return 1;
case AlarmData: return 0x0c;
case GridOnProFilePara: return 6;
/*HardWareConfig = 3, // 0x03
SimpleCalibrationPara = 4, // 0x04
RealTimeRunData_Reality = 12, // 0x0c
RealTimeRunData_A_Phase = 13, // 0x0d
RealTimeRunData_B_Phase = 14, // 0x0e
RealTimeRunData_C_Phase = 15, // 0x0f
AlarmUpdate = 18, // 0x12, Alarm data - all pending alarms
RecordData = 19, // 0x13
InternalData = 20, // 0x14
GetSelfCheckState = 30, // 0x1e
*/
default: return 8; // for the moment, this should result in sth. like a default timeout of 500ms
}
} else { //MI
switch (q->cmd) {
case MI_REQ_CH1:
case MI_REQ_CH2:
return 2;
case 0x0f: return 3;
default: return 1;
}
}
}
inline bool validateIvSerial(uint8_t buf[], Inverter<> *iv) { inline bool validateIvSerial(uint8_t buf[], Inverter<> *iv) {
uint8_t tmp[4]; uint8_t tmp[4];
CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8); CP_U32_BigEndian(tmp, iv->radioId.u64 >> 8);
@ -540,15 +573,13 @@ class Communication : public CommQueue<> {
} }
void sendRetransmit(const queue_s *q, uint8_t i) { void sendRetransmit(const queue_s *q, uint8_t i) {
//if(q->attempts) { mFramesExpected = 1;
q->iv->radio->setExpectedFrames(mFramesExpected);
q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true); q->iv->radio->sendCmdPacket(q->iv, TX_REQ_INFO, (SINGLE_FRAME + i), true);
q->iv->radioStatistics.retransmits++; q->iv->radioStatistics.retransmits++;
mWaitTime.startTimeMonitor(SINGLEFR_TIMEOUT); // timeout q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
mState = States::WAIT; mState = States::WAIT;
/*} else {
//add(q, true);
closeRequest(q, false);
}*/
} }
private: private:
@ -787,9 +818,11 @@ class Communication : public CommQueue<> {
if(q->iv->miMultiParts == 7) if(q->iv->miMultiParts == 7)
q->iv->radioStatistics.rxSuccess++; q->iv->radioStatistics.rxSuccess++;
mFramesExpected = getFramesExpected(q);
q->iv->radio->setExpectedFrames(mFramesExpected);
q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true); q->iv->radio->sendCmdPacket(q->iv, cmd, 0x00, true);
mWaitTime.startTimeMonitor(MI_TIMEOUT); q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
q->iv->miMultiParts = 0; q->iv->miMultiParts = 0;
q->iv->mGotFragment = 0; q->iv->mGotFragment = 0;
mIsRetransmit = true; mIsRetransmit = true;
@ -809,8 +842,7 @@ class Communication : public CommQueue<> {
q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true); q->iv->radio->sendCmdPacket(q->iv, q->cmd, 0x00, true);
mWaitTime.startTimeMonitor(MI_TIMEOUT); q->iv->radio->mRadioWaitTime.startTimeMonitor(DURATION_TXFRAME + DURATION_ONEFRAME + duration_reserve[q->iv->ivRadioType]);
//mState = States::WAIT;
mIsRetransmit = false; mIsRetransmit = false;
} }
@ -965,6 +997,8 @@ class Communication : public CommQueue<> {
bool mFirstTry = false; // see, if we should do a second try bool mFirstTry = false; // see, if we should do a second try
bool mIsRetransmit = false; // we already had waited one complete cycle bool mIsRetransmit = false; // we already had waited one complete cycle
uint8_t mMaxFrameId; uint8_t mMaxFrameId;
uint8_t mFramesExpected = 12; // 0x8c was highest last frame for alarm data
uint16_t mTimeout = 0; // calculating that once should be ok
uint8_t mPayload[MAX_BUFFER]; uint8_t mPayload[MAX_BUFFER];
payloadListenerType mCbPayload = NULL; payloadListenerType mCbPayload = NULL;
powerLimitAckListenerType mCbPwrAck = NULL; powerLimitAckListenerType mCbPwrAck = NULL;

7
src/hm/hmDefines.h

@ -76,6 +76,7 @@ enum {CMD_CALC = 0xffff};
enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6}; enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6};
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH}; enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
enum {INV_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT};
#define WORK_FREQ_KHZ 865000 // desired work frequency between DTU and #define WORK_FREQ_KHZ 865000 // desired work frequency between DTU and
// inverter in kHz // inverter in kHz
@ -86,6 +87,12 @@ enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH};
#define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed #define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed
#define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed #define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed
#define DURATION_ONEFRAME 50 // timeout parameter for each expected frame (ms)
//#define DURATION_RESERVE {90,120} // timeout parameter to still wait after last expected frame (ms)
#define DURATION_TXFRAME 85 // timeout parameter for first transmission and first expected frame (time to first channel switch from tx start!) (ms)
#define DURATION_LISTEN_MIN 5 // time to stay at least on a listening channel (ms)
#define DURATION_PAUSE_LASTFR 45 // how long to pause after last frame (ms)
const uint8_t duration_reserve[2] = {115,115};
typedef struct { typedef struct {
uint8_t fieldId; // field id uint8_t fieldId; // field id

9
src/hm/hmInverter.h

@ -114,6 +114,7 @@ template <class REC_TYP>
class Inverter { class Inverter {
public: public:
uint8_t ivGen; // generation of inverter (HM / MI) uint8_t ivGen; // generation of inverter (HM / MI)
uint8_t ivRadioType; // refers to used radio (nRF24 / CMT)
cfgIv_t *config; // stored settings cfgIv_t *config; // stored settings
uint8_t id; // unique id uint8_t id; // unique id
uint8_t type; // integer which refers to inverter type uint8_t type; // integer which refers to inverter type
@ -639,6 +640,12 @@ class Inverter {
DBGPRINT(F(", DTU loss: ")); DBGPRINT(F(", DTU loss: "));
DBGPRINT(String(radioStatistics.dtuLoss)); DBGPRINT(String(radioStatistics.dtuLoss));
DBGPRINT(F(" of ")); DBGPRINT(F(" of "));
if(mAckCount) {
DBGPRINT(String(radioStatistics.dtuSent));
DBGPRINT(F(". ACKs: "));
DBGPRINTLN(String(mAckCount));
mAckCount = 0;
} else
DBGPRINTLN(String(radioStatistics.dtuSent)); DBGPRINTLN(String(radioStatistics.dtuSent));
} }
@ -849,7 +856,7 @@ class Inverter {
uint8_t mGetLossInterval = 0; // request iv every AHOY_GET_LOSS_INTERVAL RealTimeRunData_Debug uint8_t mGetLossInterval = 0; // request iv every AHOY_GET_LOSS_INTERVAL RealTimeRunData_Debug
uint16_t mIvRxCnt = 0; uint16_t mIvRxCnt = 0;
uint16_t mIvTxCnt = 0; uint16_t mIvTxCnt = 0;
uint16_t mAckCount = 0;
}; };
template <class REC_TYP> template <class REC_TYP>

130
src/hm/hmRadio.h

@ -105,61 +105,95 @@ class HmRadio : public Radio {
} }
void loop(void) { void loop(void) {
if (!mIrqRcvd) if (!mIrqRcvd && !mNRFisInRX)
return; // nothing to do return; // first quick check => nothing to do at all here
mIrqRcvd = false;
bool tx_ok, tx_fail, rx_ready;
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
mNrf24->flush_tx(); // empty TX FIFO
// start listening
uint8_t chOffset = 2;
mRxChIdx = (mTxChIdx + chOffset) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
if(NULL == mLastIv) // prevent reading on NULL object! if(NULL == mLastIv) // prevent reading on NULL object!
return; return;
uint32_t innerLoopTimeout = 55000; if(!mIrqRcvd) { // no news from nRF, check timers
uint32_t loopMillis = millis(); if (mRadioWaitTime.isTimeout()) { // timeout reached!
uint32_t outerLoopTimeout = (mLastIv->mIsSingleframeReq) ? 100 : ((mLastIv->mCmd != AlarmData) && (mLastIv->mCmd != GridOnProFilePara)) ? 400 : 600; mNRFisInRX = false;
bool isRxInit = true; // add stop listening?
return;
}
yield();
while ((millis() - loopMillis) < outerLoopTimeout) { if (millis() - mTimeslotStart < innerLoopTimeout)
uint32_t startMicros = micros(); return; // nothing to do
while ((micros() - startMicros) < innerLoopTimeout) { // listen (4088us or?) 5110us to each channel
if (mIrqRcvd) { // otherwise switch to next RX channel
mTimeslotStart = millis();
if(!mNRFloopChannels && (mTimeslotStart - mLastIrqTime > (DURATION_TXFRAME+DURATION_ONEFRAME)))
mNRFloopChannels = true;
rxPendular = !rxPendular;
//innerLoopTimeout = (rxPendular ? 1 : 2)*DURATION_LISTEN_MIN;
innerLoopTimeout = DURATION_LISTEN_MIN;
tempRxChIdx = mNRFloopChannels ?
(tempRxChIdx + 4) % RF_CHANNELS :
(mRxChIdx + rxPendular*4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[tempRxChIdx]);
isRxInit = false;
return;
}
// here we got news from the nRF
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
mIrqRcvd = false; mIrqRcvd = false;
mLastIrqTime = millis();
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
mNrf24->flush_tx(); // empty TX FIFO
if (getReceived()) { // everything received if(mNRFisInRX) {
DPRINTLN(DBG_WARN, F("unexpected tx irq!"));
return; return;
} }
innerLoopTimeout = 4088*5; mNRFisInRX = true;
if (isRxInit) { if(tx_ok)
isRxInit = false; mLastIv->mAckCount++;
if (micros() - startMicros < 42000) {
innerLoopTimeout = 4088*12; // start listening
mRxChIdx = (mRxChIdx + 4) % RF_CHANNELS; mRxChIdx = (mTxChIdx + 2 ) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->setChannel(mRfChLst[mRxChIdx]);
mNrf24->startListening();
mTimeslotStart = millis();
tempRxChIdx = mRxChIdx;
rxPendular = false;
mNRFloopChannels = mLastIv->ivGen == IV_MI;
innerLoopTimeout = DURATION_TXFRAME;
} }
}
startMicros = micros(); 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;
} }
yield();
} }
// switch to next RX channel return;
mRxChIdx = (mRxChIdx + 4) % RF_CHANNELS;
mNrf24->setChannel(mRfChLst[mRxChIdx]);
innerLoopTimeout = 4088;
isRxInit = false;
} }
// not finished but time is over
return;
} }
bool isChipConnected(void) { bool isChipConnected(void) {
@ -264,16 +298,15 @@ class HmRadio : public Radio {
private: private:
inline bool getReceived(void) { inline bool getReceived(void) {
bool tx_ok, tx_fail, rx_ready;
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
bool isLastPackage = false; bool isLastPackage = false;
rx_ready = false; // reset for ACK case
while(mNrf24->available()) { while(mNrf24->available()) {
uint8_t len; uint8_t len;
len = mNrf24->getDynamicPayloadSize(); // if payload size > 32, corrupt payload has been flushed len = mNrf24->getDynamicPayloadSize(); // if payload size > 32, corrupt payload has been flushed
if (len > 0) { if (len > 0) {
packet_t p; packet_t p;
p.ch = mRfChLst[mRxChIdx]; p.ch = mRfChLst[tempRxChIdx];
p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len; p.len = (len > MAX_RF_PAYLOAD_SIZE) ? MAX_RF_PAYLOAD_SIZE : len;
p.rssi = mNrf24->testRPD() ? -64 : -75; p.rssi = mNrf24->testRPD() ? -64 : -75;
p.millis = millis() - mMillis; p.millis = millis() - mMillis;
@ -285,8 +318,8 @@ class HmRadio : public Radio {
ah::dumpBuf(p.packet, p.len, 1, 4); ah::dumpBuf(p.packet, p.len, 1, 4);
else else
ah::dumpBuf(p.packet, p.len); ah::dumpBuf(p.packet, p.len);
return false; //return false;
} } else {
mLastIv->mGotFragment = true; mLastIv->mGotFragment = true;
mBufCtrl.push(p); mBufCtrl.push(p);
if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command if (p.packet[0] == (TX_REQ_INFO + ALL_FRAMES)) // response from get information command
@ -295,6 +328,8 @@ class HmRadio : public Radio {
isLastPackage = (p.packet[9] > 0x10); // > 0x10 indicates last packet received 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 && 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 isLastPackage = true; // response from dev control command
rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads
}
} }
} }
yield(); yield();
@ -340,6 +375,8 @@ class HmRadio : public Radio {
mLastIv = iv; mLastIv = iv;
iv->mDtuTxCnt++; iv->mDtuTxCnt++;
mNRFisInRX = false;
mRqstGetRx = true; // preparation only
} }
uint64_t getIvId(Inverter<> *iv) { uint64_t getIvId(Inverter<> *iv) {
@ -362,8 +399,17 @@ class HmRadio : public Radio {
uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz uint8_t mRfChLst[RF_CHANNELS] = {03, 23, 40, 61, 75}; // channel List:2403, 2423, 2440, 2461, 2475MHz
uint8_t mTxChIdx = 0; uint8_t mTxChIdx = 0;
uint8_t mRxChIdx = 0; uint8_t mRxChIdx = 0;
uint8_t tempRxChIdx = mRxChIdx;
bool mGotLastMsg = false; bool mGotLastMsg = false;
uint32_t mMillis; uint32_t mMillis;
bool tx_ok, tx_fail, rx_ready = false;
unsigned long mTimeslotStart = 0;
unsigned long mLastIrqTime = 0;
bool mNRFloopChannels = false;
bool mNRFisInRX = false;
bool isRxInit = true;
bool rxPendular = false;
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN;
std::unique_ptr<SPIClass> mSpi; std::unique_ptr<SPIClass> mSpi;
std::unique_ptr<RF24> mNrf24; std::unique_ptr<RF24> mNrf24;

16
src/hm/hmSystem.h

@ -51,15 +51,21 @@ class HmSystem {
} }
if(iv->config->serial.b[5] == 0x11) { if(iv->config->serial.b[5] == 0x11) {
if((iv->config->serial.b[4] & 0x0f) == 0x04) if((iv->config->serial.b[4] & 0x0f) == 0x04) {
iv->ivGen = IV_HMS; iv->ivGen = IV_HMS;
else iv->ivRadioType = INV_RADIO_TYPE_CMT;
} else {
iv->ivGen = IV_HM; iv->ivGen = IV_HM;
iv->ivRadioType = INV_RADIO_TYPE_NRF;
} }
else if((iv->config->serial.b[4] & 0x03) == 0x02) // MI 3rd Gen -> same as HM }
else if((iv->config->serial.b[4] & 0x03) == 0x02) { // MI 3rd Gen -> same as HM
iv->ivGen = IV_HM; iv->ivGen = IV_HM;
else // MI 2nd Gen iv->ivRadioType = INV_RADIO_TYPE_NRF;
} else { // MI 2nd Gen
iv->ivGen = IV_MI; iv->ivGen = IV_MI;
iv->ivRadioType = INV_RADIO_TYPE_NRF;
}
} else if(iv->config->serial.b[5] == 0x13) { } else if(iv->config->serial.b[5] == 0x13) {
iv->ivGen = IV_HMT; iv->ivGen = IV_HMT;
iv->type = INV_TYPE_6CH; iv->type = INV_TYPE_6CH;
@ -87,7 +93,7 @@ class HmSystem {
DBGPRINTLN(String(iv->config->serial.u64, HEX)); DBGPRINTLN(String(iv->config->serial.u64, HEX));
if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01)) if((iv->config->serial.b[5] == 0x10) && ((iv->config->serial.b[4] & 0x03) == 0x01))
DPRINTLN(DBG_WARN, F("MI Inverter are not fully supported now!!!")); DPRINTLN(DBG_WARN, F("MI Inverter, has some restrictions!"));
cb(iv); cb(iv);
} }

9
src/hm/radio.h

@ -13,6 +13,7 @@
#include "../utils/dbg.h" #include "../utils/dbg.h"
#include "../utils/crc.h" #include "../utils/crc.h"
#include "../utils/timemonitor.h"
enum { IRQ_UNKNOWN = 0, IRQ_OK, IRQ_ERROR }; enum { IRQ_UNKNOWN = 0, IRQ_OK, IRQ_ERROR };
@ -68,9 +69,14 @@ class Radio {
return mDtuSn; return mDtuSn;
} }
void setExpectedFrames(uint8_t framesExpected) {
mFramesExpected = framesExpected;
}
public: public:
std::queue<packet_t> mBufCtrl; std::queue<packet_t> mBufCtrl;
uint8_t mIrqOk = IRQ_UNKNOWN; uint8_t mIrqOk = IRQ_UNKNOWN;
TimeMonitor mRadioWaitTime = TimeMonitor(0, true); // start as expired (due to code in RESET state)
protected: protected:
virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0; virtual void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) = 0;
@ -120,9 +126,10 @@ class Radio {
uint32_t mDtuSn; uint32_t mDtuSn;
volatile bool mIrqRcvd; volatile bool mIrqRcvd;
bool mRqstGetRx;
bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace; bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
uint8_t mFramesExpected = 0x0c;
}; };
#endif /*__RADIO_H__*/ #endif /*__RADIO_H__*/

5
src/hms/hmsRadio.h

@ -163,10 +163,13 @@ class CmtRadio : public Radio {
uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi); uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi);
if(CMT_SUCCESS == status) if(CMT_SUCCESS == status)
mBufCtrl.push(p); mBufCtrl.push(p);
//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; CmtType mCmt;
bool mRqstGetRx; //bool mRqstGetRx;
bool mCmtAvail; bool mCmtAvail;
uint32_t mMillis; uint32_t mMillis;
}; };

Loading…
Cancel
Save