// 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(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() { switch (_countryMode) { case CountryFrequency_t::MODE_900: return CMT_BASE_FREQ_900; break; default: return CMT_BASE_FREQ_860; break; } } CountryFrequency_t CMT2300A::getCountryMode() const { return _countryMode; } void CMT2300A::setCountryMode(const CountryFrequency_t mode) { _countryMode = 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 (_countryMode) { case CountryFrequency_t::MODE_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; }