OpenDTU-old/lib/CMT2300a/cmt2300wrapper.cpp
Thomas Basler c20caf8097 Feature: Support HMS/HMT inverters in different countries with different frequency bands
Thanks to @Fribur, @homeautomation2022 and @stefan123t
2024-01-14 16:37:34 +01:00

331 lines
8.2 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2023-2024 Thomas Basler and others
*/
#include "cmt2300wrapper.h"
#include "cmt2300a.h"
#include "cmt2300a_params_860.h"
#include "cmt2300a_params_900.h"
CMT2300A::CMT2300A(uint8_t pin_sdio, uint8_t pin_clk, uint8_t pin_cs, uint8_t pin_fcs, uint32_t spi_speed)
{
_pin_sdio = pin_sdio;
_pin_clk = pin_clk;
_pin_cs = pin_cs;
_pin_fcs = pin_fcs;
_spi_speed = spi_speed;
}
bool CMT2300A::begin(void)
{
return _init_pins() && _init_radio();
}
bool CMT2300A::isChipConnected()
{
return CMT2300A_IsExist();
}
bool CMT2300A::startListening(void)
{
CMT2300A_GoStby();
CMT2300A_ClearInterruptFlags();
/* Must clear FIFO after enable SPI to read or write the FIFO */
CMT2300A_EnableReadFifo();
CMT2300A_ClearRxFifo();
if (!CMT2300A_GoRx()) {
return false;
} else {
return true;
}
}
bool CMT2300A::stopListening(void)
{
CMT2300A_ClearInterruptFlags();
return CMT2300A_GoSleep();
}
bool CMT2300A::available(void)
{
return (
CMT2300A_MASK_PREAM_OK_FLG |
CMT2300A_MASK_SYNC_OK_FLG |
CMT2300A_MASK_CRC_OK_FLG |
CMT2300A_MASK_PKT_OK_FLG
) & CMT2300A_ReadReg(CMT2300A_CUS_INT_FLAG);
}
void CMT2300A::read(void* buf, uint8_t len)
{
// Fetch the payload
CMT2300A_ReadFifo(static_cast<uint8_t*>(buf), len);
CMT2300A_ClearInterruptFlags();
}
bool CMT2300A::write(const uint8_t* buf, uint8_t len)
{
CMT2300A_GoStby();
CMT2300A_ClearInterruptFlags();
/* Must clear FIFO after enable SPI to read or write the FIFO */
CMT2300A_EnableWriteFifo();
CMT2300A_ClearTxFifo();
CMT2300A_WriteReg(CMT2300A_CUS_PKT15, len); // set Tx length
/* The length need be smaller than 32 */
CMT2300A_WriteFifo(buf, len);
if (!(CMT2300A_ReadReg(CMT2300A_CUS_FIFO_FLAG) & CMT2300A_MASK_TX_FIFO_NMTY_FLG)) {
return false;
}
if (!CMT2300A_GoTx()) {
return false;
}
uint32_t timer = millis();
while (!(CMT2300A_MASK_TX_DONE_FLG & CMT2300A_ReadReg(CMT2300A_CUS_INT_CLR1))) {
if (millis() - timer > 95) {
return false;
}
}
CMT2300A_ClearInterruptFlags();
CMT2300A_GoSleep();
return true;
}
void CMT2300A::setChannel(uint8_t channel)
{
CMT2300A_SetFrequencyChannel(channel);
}
uint8_t CMT2300A::getChannel(void)
{
return CMT2300A_ReadReg(CMT2300A_CUS_FREQ_CHNL);
}
uint8_t CMT2300A::getDynamicPayloadSize(void)
{
uint8_t result;
CMT2300A_ReadFifo(&result, 1); // first byte in FiFo is length
return result;
}
int CMT2300A::getRssiDBm()
{
return CMT2300A_GetRssiDBm();
}
bool CMT2300A::setPALevel(int8_t level)
{
uint16_t Tx_dBm_word;
switch (level) {
// for TRx Matching Network Type: 20 dBm
case -10:
Tx_dBm_word = 0x0501;
break;
case -9:
Tx_dBm_word = 0x0601;
break;
case -8:
Tx_dBm_word = 0x0701;
break;
case -7:
Tx_dBm_word = 0x0801;
break;
case -6:
Tx_dBm_word = 0x0901;
break;
case -5:
Tx_dBm_word = 0x0A01;
break;
case -4:
Tx_dBm_word = 0x0B01;
break;
case -3:
Tx_dBm_word = 0x0C01;
break;
case -2:
Tx_dBm_word = 0x0D01;
break;
case -1:
Tx_dBm_word = 0x0E01;
break;
case 0:
Tx_dBm_word = 0x1002;
break;
case 1:
Tx_dBm_word = 0x1302;
break;
case 2:
Tx_dBm_word = 0x1602;
break;
case 3:
Tx_dBm_word = 0x1902;
break;
case 4:
Tx_dBm_word = 0x1C02;
break;
case 5:
Tx_dBm_word = 0x1F03;
break;
case 6:
Tx_dBm_word = 0x2403;
break;
case 7:
Tx_dBm_word = 0x2804;
break;
case 8:
Tx_dBm_word = 0x2D04;
break;
case 9:
Tx_dBm_word = 0x3305;
break;
case 10:
Tx_dBm_word = 0x3906;
break;
case 11:
Tx_dBm_word = 0x4107;
break;
case 12:
Tx_dBm_word = 0x4908;
break;
case 13:
Tx_dBm_word = 0x5309;
break;
case 14:
Tx_dBm_word = 0x5E0B;
break;
case 15:
Tx_dBm_word = 0x6C0C;
break;
case 16:
Tx_dBm_word = 0x7D0C;
break;
// the following values require the double bit:
case 17:
Tx_dBm_word = 0x4A0C;
break;
case 18:
Tx_dBm_word = 0x580F;
break;
case 19:
Tx_dBm_word = 0x6B12;
break;
case 20:
Tx_dBm_word = 0x8A18;
break;
default:
return false;
}
if (level > 16) { // set bit for double Tx value
CMT2300A_WriteReg(CMT2300A_CUS_CMT4, CMT2300A_ReadReg(CMT2300A_CUS_CMT4) | 0x01); // set bit0
} else {
CMT2300A_WriteReg(CMT2300A_CUS_CMT4, CMT2300A_ReadReg(CMT2300A_CUS_CMT4) & 0xFE); // reset bit0
}
CMT2300A_WriteReg(CMT2300A_CUS_TX8, Tx_dBm_word >> 8);
CMT2300A_WriteReg(CMT2300A_CUS_TX9, Tx_dBm_word & 0xFF);
return true;
}
bool CMT2300A::rxFifoAvailable()
{
return (
CMT2300A_MASK_PKT_OK_FLG
) & CMT2300A_ReadReg(CMT2300A_CUS_INT_FLAG);
}
uint32_t CMT2300A::getBaseFrequency() const
{
return getBaseFrequency(_frequencyBand);
}
FrequencyBand_t CMT2300A::getFrequencyBand() const
{
return _frequencyBand;
}
void CMT2300A::setFrequencyBand(const FrequencyBand_t mode)
{
_frequencyBand = mode;
_init_radio();
}
void CMT2300A::flush_rx(void)
{
CMT2300A_ClearRxFifo();
}
bool CMT2300A::_init_pins()
{
CMT2300A_InitSpi(_pin_sdio, _pin_clk, _pin_cs, _pin_fcs, _spi_speed);
return true; // assuming pins are connected properly
}
bool CMT2300A::_init_radio()
{
if (!CMT2300A_Init()) {
return false;
}
/* config registers */
switch (_frequencyBand) {
case FrequencyBand_t::BAND_900:
CMT2300A_ConfigRegBank(CMT2300A_CMT_BANK_ADDR, g_cmt2300aCmtBank_900, CMT2300A_CMT_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_SYSTEM_BANK_ADDR, g_cmt2300aSystemBank_900, CMT2300A_SYSTEM_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_FREQUENCY_BANK_ADDR, g_cmt2300aFrequencyBank_900, CMT2300A_FREQUENCY_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_DATA_RATE_BANK_ADDR, g_cmt2300aDataRateBank_900, CMT2300A_DATA_RATE_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_BASEBAND_BANK_ADDR, g_cmt2300aBasebandBank_900, CMT2300A_BASEBAND_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_TX_BANK_ADDR, g_cmt2300aTxBank_900, CMT2300A_TX_BANK_SIZE);
break;
default:
CMT2300A_ConfigRegBank(CMT2300A_CMT_BANK_ADDR, g_cmt2300aCmtBank_860, CMT2300A_CMT_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_SYSTEM_BANK_ADDR, g_cmt2300aSystemBank_860, CMT2300A_SYSTEM_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_FREQUENCY_BANK_ADDR, g_cmt2300aFrequencyBank_860, CMT2300A_FREQUENCY_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_DATA_RATE_BANK_ADDR, g_cmt2300aDataRateBank_860, CMT2300A_DATA_RATE_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_BASEBAND_BANK_ADDR, g_cmt2300aBasebandBank_860, CMT2300A_BASEBAND_BANK_SIZE);
CMT2300A_ConfigRegBank(CMT2300A_TX_BANK_ADDR, g_cmt2300aTxBank_860, CMT2300A_TX_BANK_SIZE);
break;
}
// xosc_aac_code[2:0] = 2
uint8_t tmp;
tmp = (~0x07) & CMT2300A_ReadReg(CMT2300A_CUS_CMT10);
CMT2300A_WriteReg(CMT2300A_CUS_CMT10, tmp | 0x02);
/* Config GPIOs */
CMT2300A_ConfigGpio(
CMT2300A_GPIO2_SEL_INT1 | CMT2300A_GPIO3_SEL_INT2);
/* Config interrupt */
CMT2300A_ConfigInterrupt(
CMT2300A_INT_SEL_TX_DONE, /* Config INT1 */
CMT2300A_INT_SEL_PKT_OK /* Config INT2 */
);
/* Enable interrupt */
CMT2300A_EnableInterrupt(
CMT2300A_MASK_TX_DONE_EN | CMT2300A_MASK_PREAM_OK_EN | CMT2300A_MASK_SYNC_OK_EN | CMT2300A_MASK_CRC_OK_EN | CMT2300A_MASK_PKT_DONE_EN);
CMT2300A_SetFrequencyStep(FH_OFFSET); // set FH_OFFSET (frequency = base freq + 2.5kHz*FH_OFFSET*FH_CHANNEL)
/* Use a single 64-byte FIFO for either Tx or Rx */
CMT2300A_EnableFifoMerge(true);
/* Go to sleep for configuration to take effect */
if (!CMT2300A_GoSleep()) {
return false; // CMT2300A not switched to sleep mode!
}
return true;
}