Remove cmtProocess method and move RF logic into the cmt2300wrapper class
This commit is contained in:
parent
f5767e61ef
commit
e2aa29f117
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user