|
@ -78,7 +78,7 @@ class HmRadio : public Radio { |
|
|
#else |
|
|
#else |
|
|
mNrf24->begin(mSpi.get(), ce, cs); |
|
|
mNrf24->begin(mSpi.get(), ce, cs); |
|
|
#endif |
|
|
#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->setChannel(mRfChLst[mRxChIdx]); |
|
|
mNrf24->startListening(); |
|
|
mNrf24->startListening(); |
|
@ -89,10 +89,7 @@ class HmRadio : public Radio { |
|
|
mNrf24->setCRCLength(RF24_CRC_16); |
|
|
mNrf24->setCRCLength(RF24_CRC_16); |
|
|
mNrf24->setAddressWidth(5); |
|
|
mNrf24->setAddressWidth(5); |
|
|
mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&DTU_RADIO_ID)); |
|
|
mNrf24->openReadingPipe(1, reinterpret_cast<uint8_t*>(&DTU_RADIO_ID)); |
|
|
|
|
|
mNrf24->maskIRQ(false, false, false); // enable all receiving interrupts
|
|
|
// enable all receiving interrupts
|
|
|
|
|
|
mNrf24->maskIRQ(false, false, false); |
|
|
|
|
|
|
|
|
|
|
|
mNrf24->setPALevel(1); // low is default
|
|
|
mNrf24->setPALevel(1); // low is default
|
|
|
|
|
|
|
|
|
if(mNrf24->isChipConnected()) { |
|
|
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")); |
|
|
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) |
|
|
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!
|
|
|
if(NULL == mLastIv) // prevent reading on NULL object!
|
|
|
return; |
|
|
return false; |
|
|
|
|
|
|
|
|
if(!mIrqRcvd) { // no news from nRF, check timers
|
|
|
if(!mIrqRcvd) { // no news from nRF, check timers
|
|
|
|
|
|
if ((millis() - mTimeslotStart) < innerLoopTimeout) |
|
|
|
|
|
return true; // nothing to do, still waiting
|
|
|
|
|
|
|
|
|
if (mRadioWaitTime.isTimeout()) { // timeout reached!
|
|
|
if (mRadioWaitTime.isTimeout()) { // timeout reached!
|
|
|
mNRFisInRX = false; |
|
|
mNRFisInRX = false; |
|
|
// add stop listening?
|
|
|
return false; |
|
|
return; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
yield(); |
|
|
|
|
|
|
|
|
|
|
|
if ((millis() - mTimeslotStart) < innerLoopTimeout) |
|
|
|
|
|
return; // nothing to do
|
|
|
|
|
|
|
|
|
|
|
|
// otherwise switch to next RX channel
|
|
|
// otherwise switch to next RX channel
|
|
|
mTimeslotStart = millis(); |
|
|
mTimeslotStart = millis(); |
|
|
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME))) |
|
|
if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME))) |
|
@ -140,21 +135,20 @@ class HmRadio : public Radio { |
|
|
mNrf24->setChannel(mRfChLst[tempRxChIdx]); |
|
|
mNrf24->setChannel(mRfChLst[tempRxChIdx]); |
|
|
isRxInit = false; |
|
|
isRxInit = false; |
|
|
|
|
|
|
|
|
return; |
|
|
return true; // communicating, but changed RX channel
|
|
|
} |
|
|
} else { |
|
|
|
|
|
|
|
|
// here we got news from the nRF
|
|
|
// 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; |
|
|
|
|
|
mNrf24->whatHappened(tx_ok, tx_fail, rx_ready); // resets the IRQ pin to HIGH
|
|
|
mLastIrqTime = millis(); |
|
|
mLastIrqTime = millis(); |
|
|
|
|
|
|
|
|
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
|
|
|
if(tx_ok || tx_fail) { // tx related interrupt, basically we should start listening
|
|
|
mNrf24->flush_tx(); // empty TX FIFO
|
|
|
mNrf24->flush_tx(); // empty TX FIFO
|
|
|
|
|
|
mTxSetupTime = millis() - mMillis; |
|
|
|
|
|
|
|
|
if(mNRFisInRX) { |
|
|
if(mNRFisInRX) { |
|
|
DPRINTLN(DBG_WARN, F("unexpected tx irq!")); |
|
|
DPRINTLN(DBG_WARN, F("unexpected tx irq!")); |
|
|
return; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
mNRFisInRX = true; |
|
|
mNRFisInRX = true; |
|
@ -162,13 +156,27 @@ class HmRadio : public Radio { |
|
|
mLastIv->mAckCount++; |
|
|
mLastIv->mAckCount++; |
|
|
|
|
|
|
|
|
// start listening
|
|
|
// start listening
|
|
|
mRxChIdx = (mTxChIdx + 2 ) % RF_CHANNELS; |
|
|
if(!mIsRetransmit) { |
|
|
|
|
|
if(mTxSetupTime < 30) { |
|
|
|
|
|
mRxChIdx = (mTxChIdx + 4) % RF_CHANNELS; |
|
|
|
|
|
mNrf24->setChannel(mRfChLst[mRxChIdx]); |
|
|
|
|
|
mNrf24->startListening(); |
|
|
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
|
yield(); |
|
|
|
|
|
} while((millis() - mMillis) < 37); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
mIsRetransmit = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mRxChIdx = (mTxChIdx + 2) % RF_CHANNELS; |
|
|
mNrf24->setChannel(mRfChLst[mRxChIdx]); |
|
|
mNrf24->setChannel(mRfChLst[mRxChIdx]); |
|
|
mNrf24->startListening(); |
|
|
mNrf24->startListening(); |
|
|
mTimeslotStart = millis(); |
|
|
mTimeslotStart = millis(); |
|
|
tempRxChIdx = mRxChIdx; |
|
|
tempRxChIdx = mRxChIdx; |
|
|
rxPendular = false; |
|
|
rxPendular = false; |
|
|
mNRFloopChannels = mLastIv->ivGen == IV_MI; |
|
|
mNRFloopChannels = (mLastIv->ivGen == IV_MI); |
|
|
|
|
|
|
|
|
innerLoopTimeout = DURATION_TXFRAME; |
|
|
innerLoopTimeout = DURATION_TXFRAME; |
|
|
} |
|
|
} |
|
@ -191,9 +199,14 @@ class HmRadio : public Radio { |
|
|
mRxChIdx = tempRxChIdx; |
|
|
mRxChIdx = tempRxChIdx; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
return; |
|
|
return mNRFisInRX; |
|
|
|
|
|
} /*else if(tx_fail) {
|
|
|
|
|
|
mNRFisInRX = false; |
|
|
|
|
|
return false; |
|
|
|
|
|
}*/ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool isChipConnected(void) { |
|
|
bool isChipConnected(void) { |
|
@ -283,6 +296,7 @@ class HmRadio : public Radio { |
|
|
} |
|
|
} |
|
|
cnt++; |
|
|
cnt++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen)); |
|
|
sendPacket(iv, cnt, isRetransmit, (IV_MI != iv->ivGen)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -298,12 +312,12 @@ class HmRadio : public Radio { |
|
|
|
|
|
|
|
|
private: |
|
|
private: |
|
|
inline bool getReceived(void) { |
|
|
inline bool getReceived(void) { |
|
|
|
|
|
|
|
|
bool isLastPackage = false; |
|
|
bool isLastPackage = false; |
|
|
rx_ready = false; // reset for ACK case
|
|
|
rx_ready = false; // reset for ACK case
|
|
|
|
|
|
|
|
|
while(mNrf24->available()) { |
|
|
while(mNrf24->available()) { |
|
|
uint8_t len; |
|
|
uint8_t len = mNrf24->getDynamicPayloadSize(); // payload size > 32 -> corrupt payload
|
|
|
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[tempRxChIdx]; |
|
|
p.ch = mRfChLst[tempRxChIdx]; |
|
@ -311,23 +325,25 @@ class HmRadio : public Radio { |
|
|
p.rssi = mNrf24->testRPD() ? -64 : -75; |
|
|
p.rssi = mNrf24->testRPD() ? -64 : -75; |
|
|
p.millis = millis() - mMillis; |
|
|
p.millis = millis() - mMillis; |
|
|
mNrf24->read(p.packet, p.len); |
|
|
mNrf24->read(p.packet, p.len); |
|
|
|
|
|
|
|
|
if (p.packet[0] != 0x00) { |
|
|
if (p.packet[0] != 0x00) { |
|
|
if(!checkIvSerial(p.packet, mLastIv)) { |
|
|
if(!checkIvSerial(p.packet, mLastIv)) { |
|
|
DPRINT(DBG_WARN, "RX other inverter "); |
|
|
DPRINT(DBG_WARN, "RX other inverter "); |
|
|
if(*mPrivacyMode) |
|
|
if(!*mPrivacyMode) |
|
|
ah::dumpBuf(p.packet, p.len, 1, 4); |
|
|
|
|
|
else |
|
|
|
|
|
ah::dumpBuf(p.packet, p.len); |
|
|
ah::dumpBuf(p.packet, p.len); |
|
|
//return false;
|
|
|
|
|
|
} else { |
|
|
} 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
|
|
|
isLastPackage = (p.packet[9] > ALL_FRAMES); // > ALL_FRAMES indicates last packet received
|
|
|
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
|
|
|
|
|
|
|
|
|
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
|
|
|
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
|
|
|
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; |
|
|
mTxChIdx = iv->heuristics.txRfChId; |
|
|
|
|
|
|
|
|
if(*mSerialDebug) { |
|
|
if(*mSerialDebug) { |
|
|
|
|
|
if(!isRetransmit) { |
|
|
|
|
|
DPRINT(DBG_INFO, "last tx setup: "); |
|
|
|
|
|
DBGPRINT(String(mTxSetupTime)); |
|
|
|
|
|
DBGPRINTLN("ms"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DPRINT_IVID(DBG_INFO, iv->id); |
|
|
DBGPRINT(F("TX ")); |
|
|
DBGPRINT(F("TX ")); |
|
|
DBGPRINT(String(len)); |
|
|
DBGPRINT(String(len)); |
|
@ -376,7 +398,7 @@ class HmRadio : public Radio { |
|
|
mLastIv = iv; |
|
|
mLastIv = iv; |
|
|
iv->mDtuTxCnt++; |
|
|
iv->mDtuTxCnt++; |
|
|
mNRFisInRX = false; |
|
|
mNRFisInRX = false; |
|
|
mRqstGetRx = true; // preparation only
|
|
|
mIsRetransmit = isRetransmit; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint64_t getIvId(Inverter<> *iv) { |
|
|
uint64_t getIvId(Inverter<> *iv) { |
|
@ -410,6 +432,8 @@ class HmRadio : public Radio { |
|
|
bool isRxInit = true; |
|
|
bool isRxInit = true; |
|
|
bool rxPendular = false; |
|
|
bool rxPendular = false; |
|
|
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; |
|
|
uint32_t innerLoopTimeout = DURATION_LISTEN_MIN; |
|
|
|
|
|
uint8_t mTxSetupTime = 0; |
|
|
|
|
|
bool mIsRetransmit = false; |
|
|
|
|
|
|
|
|
std::unique_ptr<SPIClass> mSpi; |
|
|
std::unique_ptr<SPIClass> mSpi; |
|
|
std::unique_ptr<RF24> mNrf24; |
|
|
std::unique_ptr<RF24> mNrf24; |
|
|