Remove cmtProocess method and move RF logic into the cmt2300wrapper class

This commit is contained in:
Thomas Basler 2023-04-11 21:58:14 +02:00
parent f5767e61ef
commit e2aa29f117
4 changed files with 155 additions and 155 deletions

View File

@ -25,6 +25,46 @@ 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();
@ -70,6 +110,18 @@ 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;
@ -183,6 +235,18 @@ bool CMT2300A::setPALevel(int8_t level)
return true;
}
bool CMT2300A::rxFifoAvailable()
{
return (
CMT2300A_MASK_PKT_OK_FLG
) & CMT2300A_ReadReg(CMT2300A_CUS_INT_FLAG);
}
void CMT2300A::flush_rx(void)
{
CMT2300A_ClearRxFifo();
}
bool CMT2300A::_init_pins()
{
CMT2300A_InitSpi(_pin_sdio, _pin_clk, _pin_cs, _pin_fcs, _spi_speed);

View File

@ -19,6 +19,43 @@ public:
*/
bool isChipConnected();
bool startListening(void);
bool stopListening(void);
/**
* Check whether there are bytes available to be read
* @code
* if(radio.available()){
* radio.read(&data,sizeof(data));
* }
* @endcode
*
* @see available(uint8_t*)
*
* @return True if there is a payload available, false if none is
*/
bool available(void);
/**
* Read payload data from the RX FIFO buffer(s).
*
* The length of data read is usually the next available payload's length
* @see
* - getDynamicPayloadSize()
*
* @note I specifically chose `void*` as a data type to make it easier
* for beginners to use. No casting needed.
*
* @param buf Pointer to a buffer where the data should be written
* @param len Maximum number of bytes to read into the buffer. This
* value should match the length of the object referenced using the
* `buf` parameter. The absolute maximum number of bytes that can be read
* in one call is 32 (for dynamic payload lengths) or whatever number was
* previously passed to setPayloadSize() (for static payload lengths).
*/
void read(void* buf, uint8_t len);
bool write(const uint8_t* buf, uint8_t len);
/**
@ -33,8 +70,27 @@ public:
*/
uint8_t getChannel(void);
/**
* Get Dynamic Payload Size
*
* For dynamic payloads, this pulls the size of the payload off
* the chip
*
* @return Payload length of last-received dynamic payload
*/
uint8_t getDynamicPayloadSize(void);
int getRssiDBm();
bool setPALevel(int8_t level);
bool rxFifoAvailable();
/**
* Empty the RX (receive) FIFO buffers.
*/
void flush_rx(void);
private:
/**
* initialize the GPIO pins

View File

@ -6,7 +6,6 @@
#include "Hoymiles.h"
#include "crc.h"
#include <FunctionalInterrupt.h>
#include <cmt2300a.h>
#define HOY_BOOT_FREQ 868000000 // Hoymiles boot/init frequency after power up inverter or connection lost for 15 min
#define HOY_BASE_FREQ 860000000
@ -54,128 +53,6 @@ bool HoymilesRadio_CMT::cmtSwitchDtuFreq(const uint32_t to_freq_kHz)
return true;
}
enumCMTresult HoymilesRadio_CMT::cmtProcess(void)
{
enumCMTresult nRes = CMT_BUSY;
switch (cmtNextState) {
case CMT_STATE_IDLE:
nRes = CMT_IDLE;
break;
case CMT_STATE_RX_START:
CMT2300A_GoStby();
CMT2300A_ClearInterruptFlags();
/* Must clear FIFO after enable SPI to read or write the FIFO */
CMT2300A_EnableReadFifo();
CMT2300A_ClearRxFifo();
if (!CMT2300A_GoRx()) {
cmtNextState = CMT_STATE_ERROR;
} else {
cmtNextState = CMT_STATE_RX_WAIT;
}
cmtRxTimeCount = CMT2300A_GetTickCount();
cmtRxTimeout = 200;
break;
case CMT_STATE_RX_WAIT:
if (!_gpio3_configured) {
if (CMT2300A_MASK_PKT_OK_FLG & CMT2300A_ReadReg(CMT2300A_CUS_INT_FLAG)) { // read INT2, PKT_OK flag
_packetReceived = true;
}
}
if (_packetReceived)
{
Hoymiles.getMessageOutput()->println("Interrupt 2 received");
_packetReceived = false; // reset interrupt 2
cmtNextState = CMT_STATE_RX_DONE;
}
if ((CMT2300A_GetTickCount() - cmtRxTimeCount) > cmtRxTimeout) {
cmtNextState = CMT_STATE_RX_TIMEOUT;
}
break;
case CMT_STATE_RX_DONE: {
CMT2300A_GoStby();
bool isLastFrame = false;
uint8_t state = CMT2300A_ReadReg(CMT2300A_CUS_INT_FLAG);
if ((state & 0x1b) == 0x1b) {
if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) {
fragment_t f;
memset(f.fragment, 0xcc, MAX_RF_PAYLOAD_SIZE);
CMT2300A_ReadFifo(&f.len, 1); // first byte in FiFo is length
f.channel = _radio->getChannel();
f.rssi = CMT2300A_GetRssiDBm();
if (f.len > MAX_RF_PAYLOAD_SIZE) {
f.len = MAX_RF_PAYLOAD_SIZE;
}
CMT2300A_ReadFifo(f.fragment, f.len);
if (f.fragment[9] & 0x80) { // last frame detection for end Rx
isLastFrame = true;
}
_rxBuffer.push(f);
} else {
Hoymiles.getMessageOutput()->println("Buffer full");
}
} else if ((state & 0x19) == 0x19) {
Hoymiles.getMessageOutput()->printf("[CMT_STATE_RX_DONE] state: %x (CRC_ERROR)\r\n", state);
} else {
Hoymiles.getMessageOutput()->printf("[CMT_STATE_RX_DONE] wrong state: %x\r\n", state);
}
CMT2300A_ClearInterruptFlags();
CMT2300A_GoSleep();
if (isLastFrame) { // last frame received
cmtNextState = CMT_STATE_IDLE;
} else {
cmtNextState = CMT_STATE_RX_START; // receive next frame(s)
}
nRes = CMT_RX_DONE;
break;
}
case CMT_STATE_RX_TIMEOUT:
CMT2300A_GoSleep();
Hoymiles.getMessageOutput()->println("RX timeout!");
cmtNextState = CMT_STATE_IDLE;
nRes = CMT_RX_TIMEOUT;
break;
case CMT_STATE_ERROR:
CMT2300A_SoftReset();
CMT2300A_DelayMs(20);
CMT2300A_GoStby();
_radio->begin();
cmtNextState = CMT_STATE_IDLE;
nRes = CMT_ERROR;
break;
default:
break;
}
return nRes;
}
void HoymilesRadio_CMT::init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio2, int8_t pin_gpio3)
{
_dtuSerial.u64 = 0;
@ -210,9 +87,37 @@ void HoymilesRadio_CMT::loop()
if (!_isInitialized) {
return;
}
enumCMTresult mCMTstate = cmtProcess();
if (mCMTstate != CMT_RX_DONE) { // Perform package parsing only if no packages are received
if (!_gpio3_configured) {
if (_radio->rxFifoAvailable()) { // read INT2, PKT_OK flag
_packetReceived = true;
}
}
if (_packetReceived) {
Hoymiles.getMessageOutput()->println("Interrupt received");
while (_radio->available()) {
if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) {
fragment_t f;
memset(f.fragment, 0xcc, MAX_RF_PAYLOAD_SIZE);
f.len = _radio->getDynamicPayloadSize();
f.channel = _radio->getChannel();
f.rssi = _radio->getRssiDBm();
if (f.len > MAX_RF_PAYLOAD_SIZE) {
f.len = MAX_RF_PAYLOAD_SIZE;
}
_radio->read(f.fragment, f.len);
_rxBuffer.push(f);
} else {
Hoymiles.getMessageOutput()->println("Buffer full");
_radio->flush_rx();
}
}
_radio->flush_rx();
_packetReceived = false;
} else {
// Perform package parsing only if no packages are received
if (!_rxBuffer.empty()) {
fragment_t f = _rxBuffer.back();
if (checkFragmentCrc(&f)) {
@ -360,6 +265,8 @@ void HoymilesRadio_CMT::sendEsbPacket(CommandAbstract* cmd)
cmd->setRouterAddress(DtuSerial().u64);
_radio->stopListening();
uint8_t oldChannel;
oldChannel = _radio->getChannel();
if (cmd->getDataPayload()[0] == 0x56) { // @todo(tbnobody) Bad hack to identify ChannelChange Command
@ -370,13 +277,11 @@ void HoymilesRadio_CMT::sendEsbPacket(CommandAbstract* cmd)
cmd->getCommandName().c_str(), getFrequencyFromChannel(_radio->getChannel()));
cmd->dumpDataPayload(Hoymiles.getMessageOutput());
if (_radio->write(cmd->getDataPayload(), cmd->getDataSize())) {
cmtNextState = CMT_STATE_RX_START;
} else {
if (!_radio->write(cmd->getDataPayload(), cmd->getDataSize())) {
Hoymiles.getMessageOutput()->println("TX SPI Timeout");
}
_radio->setChannel(oldChannel);
_radio->startListening();
_busyFlag = true;
_rxTimeout.set(cmd->getTimeout());
}

View File

@ -6,9 +6,9 @@
#include "commands/CommandAbstract.h"
#include "types.h"
#include <Arduino.h>
#include <cmt2300wrapper.h>
#include <memory>
#include <queue>
#include <cmt2300wrapper.h>
// number of fragments hold in buffer
#define FRAGMENT_BUFFER_SIZE 30
@ -17,25 +17,6 @@
#define HOYMILES_CMT_WORK_FREQ 865000
#endif
/* CMT states */
typedef enum {
CMT_STATE_IDLE = 0,
CMT_STATE_RX_START,
CMT_STATE_RX_WAIT,
CMT_STATE_RX_DONE,
CMT_STATE_RX_TIMEOUT,
CMT_STATE_ERROR,
} enumCMTstate;
/* CMT process function results */
typedef enum {
CMT_IDLE = 0,
CMT_BUSY,
CMT_RX_DONE,
CMT_RX_TIMEOUT,
CMT_ERROR,
} enumCMTresult;
class HoymilesRadio_CMT : public HoymilesRadio {
public:
void init(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8_t pin_fcs, int8_t pin_gpio2, int8_t pin_gpio3);
@ -73,10 +54,4 @@ private:
uint32_t _inverterTargetFrequency = HOYMILES_CMT_WORK_FREQ;
bool cmtSwitchDtuFreq(const uint32_t to_freq_kHz);
enumCMTresult cmtProcess(void);
enumCMTstate cmtNextState = CMT_STATE_IDLE;
uint32_t cmtRxTimeout = 200;
uint32_t cmtRxTimeCount = 0;
};