diff --git a/src/hm/Communication.h b/src/hm/Communication.h index 23ffe158..9219bb8e 100644 --- a/src/hm/Communication.h +++ b/src/hm/Communication.h @@ -139,8 +139,10 @@ class Communication : public CommQueue<> { } if(!q->iv->mGotFragment) { if(INV_RADIO_TYPE_CMT == q->iv->ivRadioType) { - q->iv->radio->switchFrequency(q->iv, HOY_BOOT_FREQ_KHZ, (q->iv->config->frequency*FREQ_STEP_KHZ + HOY_BASE_FREQ_KHZ)); + #if defined(ESP32) + q->iv->radio->switchFrequency(q->iv, q->iv->radio->getBootFreqMhz() * 1000, (q->iv->config->frequency*FREQ_STEP_KHZ + q->iv->radio->getBaseFreqMhz() * 1000)); mWaitTime.startTimeMonitor(1000); + #endif } else { mHeu.setIvRetriesBad(q->iv); if(IV_MI == q->iv->ivGen) @@ -526,7 +528,6 @@ class Communication : public CommQueue<> { int8_t rssi = -127; uint8_t len = 0; - DPRINT_IVID(DBG_INFO, q->iv->id); for(uint8_t i = 0; i < mMaxFrameId; i++) { if(mLocalBuf[i].len + len > MAX_BUFFER) { DPRINTLN(DBG_ERROR, F("payload buffer to small!")); @@ -541,7 +542,7 @@ class Communication : public CommQueue<> { len -= 2; - //DPRINT_IVID(DBG_INFO, q->iv->id); // it's already above "for"-loop + DPRINT_IVID(DBG_INFO, q->iv->id); DBGPRINT(F("Payload (")); DBGPRINT(String(len)); if(*mPrintWholeTrace) { diff --git a/src/hm/HeuristicInv.h b/src/hm/HeuristicInv.h index fc782a7b..e9c7084e 100644 --- a/src/hm/HeuristicInv.h +++ b/src/hm/HeuristicInv.h @@ -14,7 +14,7 @@ class HeuristicInv { public: HeuristicInv() { - memset(txRfQuality, -6, RF_MAX_CHANNEL_ID); + memset(txRfQuality, 0, RF_MAX_CHANNEL_ID); } public: diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 6bd66e66..4705c061 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -78,14 +78,6 @@ 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_RADIO_TYPE_NRF = 0, INV_RADIO_TYPE_CMT}; -#define WORK_FREQ_KHZ 865000 // desired work frequency between DTU and - // inverter in kHz -#define HOY_BASE_FREQ_KHZ 860000 // in kHz -#define HOY_MAX_FREQ_KHZ 923500 // 0xFE * 250kHz + Base_freq -#define HOY_BOOT_FREQ_KHZ 868000 // Hoymiles boot/init frequency after power up inverter -#define FREQ_STEP_KHZ 250 // channel step size in kHz -#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 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) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 00f05c79..a74ad02f 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -180,7 +180,6 @@ class Inverter { tsMaxAcPower = 0; memset(&radioStatistics, 0, sizeof(statistics_t)); - memset(mOffYD, 0, sizeof(float) * 6); memset(mLastYD, 0, sizeof(float) * 6); } diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index fbb23b57..e759576c 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -118,7 +118,7 @@ class HmRadio : public Radio { // otherwise switch to next RX channel mTimeslotStart = millis(); - if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME+DURATION_ONEFRAME))) + if(!mNRFloopChannels && ((mTimeslotStart - mLastIrqTime) > (DURATION_TXFRAME))) //(DURATION_TXFRAME+DURATION_ONEFRAME))) mNRFloopChannels = true; rxPendular = !rxPendular; @@ -163,7 +163,7 @@ class HmRadio : public Radio { mNRFloopChannels = (mLastIv->ivGen == IV_MI); //innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_TXFRAME : DURATION_ONEFRAME; - innerLoopTimeout = DURATION_LISTEN_MIN; + innerLoopTimeout = mLastIv->ivGen != IV_MI ? DURATION_LISTEN_MIN : 4; } if(rx_ready) { @@ -324,7 +324,13 @@ class HmRadio : public Radio { if(mLastIv->mIsSingleframeReq) // we only expect one frame here... isRetransmitAnswer = true; if(isLastPackage) - mFramesExpected = p.packet[9] - ALL_FRAMES; + setExpectedFrames(p.packet[9] - ALL_FRAMES); + 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; + } } if(IV_MI == mLastIv->ivGen) { @@ -332,6 +338,8 @@ 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 + if(p.packet[9] == 0x00 && p.millis < DURATION_ONEFRAME) + mLastIv->rxOffset = (RF_CHANNELS + mTxChIdx - tempRxChIdx - 1) % RF_CHANNELS; } rx_ready = true; //reset in case we first read messages from other inverter or ACK zero payloads } diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 1e8641cb..26d0ea5d 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -28,8 +28,7 @@ class HmSystem { iv->config = &mInverter[0].generalConfig->iv[id]; DPRINT(DBG_VERBOSE, "SERIAL: " + String(iv->config->serial.b[5], HEX)); DPRINTLN(DBG_VERBOSE, " " + String(iv->config->serial.b[4], HEX)); - //iv->rxOffset = 5 - (iv->config->serial.b[2] % 5); //RF_CHANNELS; - iv->rxOffset = (iv->config->serial.b[1] % 5); //RF_CHANNELS; + iv->rxOffset = 13; // effective 3, but can easily be recognized as default setting if((iv->config->serial.b[5] == 0x11) || (iv->config->serial.b[5] == 0x10)) { switch(iv->config->serial.b[4]) { case 0x24: // HMS-500 diff --git a/src/hm/radio.h b/src/hm/radio.h index ea6d8c05..9702c304 100644 --- a/src/hm/radio.h +++ b/src/hm/radio.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://github.com/lumpapu/ahoy +// 2024 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -28,6 +28,9 @@ 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) const { return false; } + virtual uint16_t getBaseFreqMhz() { return 0; } + virtual uint16_t getBootFreqMhz() { return 0; } + virtual std::pair getFreqRangeMhz(void) { return std::make_pair(0, 0); } virtual bool loop(void) = 0; void handleIntr(void) { @@ -115,6 +118,7 @@ class Radio { chipID = ESP.getChipId(); #endif + mDtuSn = 0; uint8_t t; for(int i = 0; i < (7 << 2); i += 4) { t = (chipID >> i) & 0x0f; @@ -125,6 +129,7 @@ class Radio { mDtuSn |= 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal } + uint32_t mDtuSn; volatile bool mIrqRcvd; bool *mSerialDebug, *mPrivacyMode, *mPrintWholeTrace; diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 1ff112e2..3cdc2660 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2023 Ahoy, https://github.com/lumpapu/ahoy +// 2024 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- @@ -12,8 +12,23 @@ #include "esp32_3wSpi.h" #endif -// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf +#include + +enum class RegionCfg : uint8_t { + EUROPE, USA, BRAZIL, NUM +}; + +enum class CmtStatus : uint8_t { + SUCCESS = 0, + ERR_SWITCH_STATE, + ERR_TX_PENDING, + FIFO_EMPTY, + ERR_RX_IN_FIFO +}; + +#define FREQ_STEP_KHZ 250 // channel step size in kHz +// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf #define CMT2300A_MASK_CFG_RETAIN 0x10 #define CMT2300A_MASK_RSTN_IN_EN 0x20 #define CMT2300A_MASK_LOCKING_EN 0x20 @@ -152,67 +167,6 @@ #define CMT2300A_MASK_TX_DONE_FLG 0x08 #define CMT2300A_MASK_PKT_OK_FLG 0x01 -// this list and the TX5, TX10 registers were compiled from the output of -// HopeRF RFPDK Tool v1.54 -static uint8_t paLevelList[31][2] PROGMEM = { - {0x17, 0x01}, // -10dBm - {0x1a, 0x01}, // -09dBm - {0x1d, 0x01}, // -08dBm - {0x21, 0x01}, // -07dBm - {0x25, 0x01}, // -06dBm - {0x29, 0x01}, // -05dBm - {0x2d, 0x01}, // -04dBm - {0x33, 0x01}, // -03dBm - {0x39, 0x02}, // -02dBm - {0x41, 0x02}, // -01dBm - {0x4b, 0x02}, // 00dBm - {0x56, 0x03}, // 01dBm - {0x63, 0x03}, // 02dBm - {0x71, 0x04}, // 03dBm - {0x80, 0x04}, // 04dBm - {0x22, 0x01}, // 05dBm - {0x27, 0x04}, // 06dBm - {0x2c, 0x05}, // 07dBm - {0x31, 0x06}, // 08dBm - {0x38, 0x06}, // 09dBm - {0x3f, 0x07}, // 10dBm - {0x48, 0x08}, // 11dBm - {0x52, 0x09}, // 12dBm - {0x5d, 0x0b}, // 13dBm - {0x6a, 0x0c}, // 14dBm - {0x79, 0x0d}, // 15dBm - {0x46, 0x10}, // 16dBm - {0x51, 0x10}, // 17dBm - {0x60, 0x12}, // 18dBm - {0x71, 0x14}, // 19dBm - {0x8c, 0x1c} // 20dBm -}; - -// default CMT parameters -static uint8_t cmtConfig[0x60] PROGMEM { - // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm - 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, - 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, - // 0x10 - 0x1f - 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, - 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default - // 0x20 - 0x2f - 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, - 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, - // 0x30 - 0x3f - 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, - // 0x40 - 0x4f - 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, - // 0x50 - 0x5f - 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, - 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // - TX 13dBm -}; - - -enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO}; - class Cmt2300a { public: Cmt2300a() {} @@ -234,12 +188,12 @@ class Cmt2300a { } } - uint8_t goRx(void) { + CmtStatus goRx(void) { if(mTxPending) - return CMT_ERR_TX_PENDING; + return CmtStatus::ERR_TX_PENDING; if(mInRxMode) - return CMT_SUCCESS; + return CmtStatus::SUCCESS; mSpi.readReg(CMT2300A_CUS_INT1_CTL); mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); @@ -260,47 +214,47 @@ class Cmt2300a { mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; mInRxMode = true; - return CMT_SUCCESS; + return CmtStatus::SUCCESS; } - uint8_t getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) { + CmtStatus getRx(uint8_t buf[], uint8_t *rxLen, uint8_t maxlen, int8_t *rssi) { if(mTxPending) - return CMT_ERR_TX_PENDING; + return CmtStatus::ERR_TX_PENDING; if(0x1b != (mSpi.readReg(CMT2300A_CUS_INT_FLAG) & 0x1b)) - return CMT_FIFO_EMPTY; + return CmtStatus::FIFO_EMPTY; // receive ok (pream, sync, node, crc) if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; mSpi.readFifo(buf, rxLen, maxlen); *rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128; if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; mInRxMode = false; mCusIntFlag = mSpi.readReg(CMT2300A_CUS_INT_FLAG); - return CMT_SUCCESS; + return CmtStatus::SUCCESS; } - uint8_t tx(uint8_t buf[], uint8_t len) { + CmtStatus tx(uint8_t buf[], uint8_t len) { if(mTxPending) - return CMT_ERR_TX_PENDING; + return CmtStatus::ERR_TX_PENDING; if(mInRxMode) { mInRxMode = false; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; } mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); @@ -325,16 +279,17 @@ class Cmt2300a { } if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) - return CMT_ERR_SWITCH_STATE; + return CmtStatus::ERR_SWITCH_STATE; // wait for tx done mTxPending = true; - return CMT_SUCCESS; + return CmtStatus::SUCCESS; } // initialize CMT2300A, returns true on success - bool reset(void) { + bool reset(RegionCfg region) { + mRegionCfg = region; mSpi.writeReg(0x7f, 0xff); // soft reset delay(30); @@ -346,10 +301,19 @@ class Cmt2300a { if(mSpi.readReg(0x62) != 0x20) return false; // not connected! - for(uint8_t i = 0; i < 0x60; i++) { + for(uint8_t i = 0; i < 0x18; i++) { + mSpi.writeReg(i, cmtConfig[i]); + } + for(uint8_t i = 0; i < 8; i++) { + mSpi.writeReg(0x18 + i, mBaseFreqCfg[static_cast(region)][i]); + } + for(uint8_t i = 0x20; i < 0x60; i++) { mSpi.writeReg(i, cmtConfig[i]); } + if(RegionCfg::EUROPE != region) + mSpi.writeReg(0x27, 0x0B); + mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 @@ -389,23 +353,14 @@ class Cmt2300a { } inline uint8_t freq2Chan(const uint32_t freqKhz) { - if((freqKhz % FREQ_STEP_KHZ) != 0) { - DPRINT(DBG_WARN, F("switch frequency to ")); - DBGPRINT(String(freqKhz)); - DBGPRINT(F("kHz not possible!")); + if((freqKhz % FREQ_STEP_KHZ) != 0) return 0xff; // error - // apply the nearest frequency - //freqKhz = (freqKhz + FREQ_STEP_KHZ/2) / FREQ_STEP_KHZ; - //freqKhz *= FREQ_STEP_KHZ; - } - if((freqKhz < HOY_BASE_FREQ_KHZ) || (freqKhz > HOY_MAX_FREQ_KHZ)) + std::pair range = getFreqRangeMhz(); + if((freqKhz < range.first) || (freqKhz > range.second)) return 0xff; // error - if((freqKhz < FREQ_WARN_MIN_KHZ) || (freqKhz > FREQ_WARN_MAX_KHZ)) - DPRINTLN(DBG_WARN, F("Desired frequency is out of EU legal range! (863 - 870MHz)")); - - return (freqKhz - HOY_BASE_FREQ_KHZ) / FREQ_STEP_KHZ; + return (freqKhz - getBaseFreqMhz() * 1000) / FREQ_STEP_KHZ; } inline void switchChannel(uint8_t ch) { @@ -414,9 +369,9 @@ class Cmt2300a { inline uint32_t getFreqKhz(void) { if(0xff != mRqstCh) - return HOY_BASE_FREQ_KHZ + (mRqstCh * FREQ_STEP_KHZ); + return getBaseFreqMhz() * 1000 + (mRqstCh * FREQ_STEP_KHZ); else - return HOY_BASE_FREQ_KHZ + (mCurCh * FREQ_STEP_KHZ); + return getBaseFreqMhz() * 1000 + (mCurCh * FREQ_STEP_KHZ); } uint8_t getCurrentChannel(void) { @@ -443,6 +398,114 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_TX9, paLevelList[level][1]); } + public: + uint16_t getBaseFreqMhz(void) { + switch(mRegionCfg) { + default: + [[fallthrough]]; + case RegionCfg::EUROPE: + break; + case RegionCfg::USA: + return 905; + case RegionCfg::BRAZIL: + return 915; + } + return 860; + } + + uint16_t getBootFreqMhz(void) { + switch(mRegionCfg) { + default: + [[fallthrough]]; + case RegionCfg::EUROPE: + break; + case RegionCfg::USA: + return 915; + case RegionCfg::BRAZIL: + return 915; + } + return 868; + } + + std::pair getFreqRangeMhz(void) { + switch(mRegionCfg) { + default: + [[fallthrough]]; + case RegionCfg::EUROPE: + break; + case RegionCfg::USA: + return std::make_pair(905, 925); + case RegionCfg::BRAZIL: + return std::make_pair(915, 928); + } + return std::make_pair(860, 870); // Europe + } + + private: + // this list and the TX5, TX10 registers were compiled from the output of + // HopeRF RFPDK Tool v1.54 + constexpr static uint8_t paLevelList[31][2] PROGMEM = { + {0x17, 0x01}, // -10dBm + {0x1a, 0x01}, // -09dBm + {0x1d, 0x01}, // -08dBm + {0x21, 0x01}, // -07dBm + {0x25, 0x01}, // -06dBm + {0x29, 0x01}, // -05dBm + {0x2d, 0x01}, // -04dBm + {0x33, 0x01}, // -03dBm + {0x39, 0x02}, // -02dBm + {0x41, 0x02}, // -01dBm + {0x4b, 0x02}, // 00dBm + {0x56, 0x03}, // 01dBm + {0x63, 0x03}, // 02dBm + {0x71, 0x04}, // 03dBm + {0x80, 0x04}, // 04dBm + {0x22, 0x01}, // 05dBm + {0x27, 0x04}, // 06dBm + {0x2c, 0x05}, // 07dBm + {0x31, 0x06}, // 08dBm + {0x38, 0x06}, // 09dBm + {0x3f, 0x07}, // 10dBm + {0x48, 0x08}, // 11dBm + {0x52, 0x09}, // 12dBm + {0x5d, 0x0b}, // 13dBm + {0x6a, 0x0c}, // 14dBm + {0x79, 0x0d}, // 15dBm + {0x46, 0x10}, // 16dBm + {0x51, 0x10}, // 17dBm + {0x60, 0x12}, // 18dBm + {0x71, 0x14}, // 19dBm + {0x8c, 0x1c} // 20dBm + }; + + // default CMT parameters + constexpr static uint8_t cmtConfig[0x60] PROGMEM { + // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm + 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, + 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, + // 0x10 - 0x1f + 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, + 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default + // 0x20 - 0x2f + 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, + 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + // 0x30 - 0x3f + 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, + // 0x40 - 0x4f + 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, + // 0x50 - 0x5f + 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, + 0x00, 0x07, 0x50, 0x00, 0x5D, 0x0B, 0x3F, 0x7F // TX 13dBm + }; + + constexpr static uint8_t mBaseFreqCfg[static_cast(RegionCfg::NUM)][8] { + {0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12}, // 860MHz + {0x45, 0xA8, 0x31, 0x8A, 0x45, 0x9D, 0xD8, 0x19}, // 905MHz (USA, Indonesia) + {0x46, 0x6D, 0x80, 0x86, 0x46, 0x62, 0x27, 0x16} // 915MHz (Brazil) + }; + private: void init() { mTxPending = false; @@ -480,6 +543,7 @@ class Cmt2300a { return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA; } + private: #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL) cmtHal mSpi; #else @@ -490,6 +554,7 @@ class Cmt2300a { bool mInRxMode; uint8_t mCusIntFlag; uint8_t mRqstCh, mCurCh; + RegionCfg mRegionCfg = RegionCfg::EUROPE; }; #endif /*__CMT2300A_H__*/ diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 33b6a75c..07afd4b8 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -17,9 +17,9 @@ class CmtRadio : public Radio { mDtuSn = DTU_SN; } - void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) { + void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t pinSclk, uint8_t pinSdio, uint8_t pinCsb, uint8_t pinFcsb, uint8_t region = 0, bool genDtuSn = true) { mCmt.setup(pinSclk, pinSdio, pinCsb, pinFcsb); - reset(genDtuSn); + reset(genDtuSn, static_cast(region)); mPrivacyMode = privacyMode; mSerialDebug = serialDebug; mPrintWholeTrace = printWholeTrace; @@ -30,7 +30,7 @@ class CmtRadio : public Radio { if((!mIrqRcvd) && (!mRqstGetRx)) return false; getRx(); - if(CMT_SUCCESS == mCmt.goRx()) { + if(CmtStatus::SUCCESS == mCmt.goRx()) { mIrqRcvd = false; mRqstGetRx = false; } @@ -76,6 +76,18 @@ class CmtRadio : public Radio { return true; } +uint16_t getBaseFreqMhz(void) override { + return mCmt.getBaseFreqMhz(); + } + + uint16_t getBootFreqMhz(void) override { + return mCmt.getBootFreqMhz(); + } + + std::pair getFreqRangeMhz(void) override { + return mCmt.getFreqRangeMhz(); + } + private: void sendPacket(Inverter<> *iv, uint8_t len, bool isRetransmit, bool appendCrc16=true) { @@ -104,12 +116,12 @@ class CmtRadio : public Radio { } } - uint8_t status = mCmt.tx(mTxBuf, len); + CmtStatus status = mCmt.tx(mTxBuf, len); mMillis = millis(); - if(CMT_SUCCESS != status) { + if(CmtStatus::SUCCESS != status) { DPRINT(DBG_WARN, F("CMT TX failed, code: ")); - DBGPRINTLN(String(status)); - if(CMT_ERR_RX_IN_FIFO == status) + DBGPRINTLN(String(static_cast(status))); + if(CmtStatus::ERR_RX_IN_FIFO == status) mIrqRcvd = true; } iv->mDtuTxCnt++; @@ -123,10 +135,10 @@ class CmtRadio : public Radio { return iv->ivGen; } - inline void reset(bool genDtuSn) { + inline void reset(bool genDtuSn, RegionCfg region) { if(genDtuSn) generateDtuSn(); - if(!mCmt.reset()) { + if(!mCmt.reset(region)) { mCmtAvail = false; DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); } else { @@ -160,8 +172,8 @@ class CmtRadio : public Radio { inline void getRx(void) { packet_t p; p.millis = millis() - mMillis; - uint8_t status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi); - if(CMT_SUCCESS == status) + CmtStatus status = mCmt.getRx(p.packet, &p.len, 28, &p.rssi); + if(CmtStatus::SUCCESS == status) mBufCtrl.push(p); if(p.packet[9] > ALL_FRAMES) // indicates last frame @@ -171,7 +183,7 @@ class CmtRadio : public Radio { } CmtType mCmt; - bool mCmtAvail; + bool mCmtAvail = false; bool mRqstGetRx = false; uint32_t mMillis; };