new tx modes with selectable delay

This commit is contained in:
MichaelDvP
2020-06-14 08:37:24 +02:00
parent b75eea44a1
commit 11ac08c869
6 changed files with 192 additions and 113 deletions

View File

@@ -568,9 +568,9 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
if (((first_value & 0x7F) == txservice_.ems_bus_id()) && (length > 1)) {
// if we ask ourself at roomcontrol for version e.g. 0B 98 02 00 20
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
#ifdef EMSESP_DEBUG
//#ifdef EMSESP_DEBUG
LOG_DEBUG(F("Echo: %s"), Helpers::data_to_hex(data, length).c_str());
#endif
//#endif
return; // it's an echo
}
@@ -725,8 +725,9 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) {
flash_string_vector{F_(set), F_(tx_mode)},
flash_string_vector{F_(n_mandatory)},
[](Shell & shell, const std::vector<std::string> & arguments) {
uint8_t tx_mode = (arguments[0]).at(0) - '0';
if ((tx_mode > 0) && (tx_mode <= 4)) {
// uint8_t tx_mode = (arguments[0]).at(0) - '0';
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
if ((tx_mode > 0) && (tx_mode <= 30)) {
Settings settings;
settings.ems_tx_mode(tx_mode);
settings.commit();

View File

@@ -487,13 +487,13 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
}
// send the telegram to the UART Tx
EMSUART_STATUS status = EMSuart::transmit(telegram_raw, length);
uint16_t status = EMSuart::transmit(telegram_raw, length);
#ifdef EMSESP_DEBUG
LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
#endif
if (status != EMS_TX_STATUS_OK) {
LOG_ERROR(F("Failed to transmit Tx via UART. Error: %s"), status == EMS_TX_WTD_TIMEOUT ? F("Timeout") : F("BRK"));
LOG_ERROR(F("Failed to transmit Tx via UART."));
tx_waiting(false); // nothing send, tx not in wait state
return;
}
@@ -515,10 +515,10 @@ void TxService::send_telegram(const uint8_t * data, const uint8_t length) {
LOG_DEBUG(F("Sending Raw telegram: %s (length=%d)"), Helpers::data_to_hex(telegram_raw, length).c_str(), length);
// send the telegram to the UART Tx
EMSUART_STATUS status = EMSuart::transmit(telegram_raw, length);
uint16_t status = EMSuart::transmit(telegram_raw, length);
//LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
if (status != EMS_TX_STATUS_OK) {
LOG_ERROR(F("Failed to transmit Tx via UART. Error: %s"), status == EMS_TX_WTD_TIMEOUT ? F("Timeout") : F("BRK"));
LOG_ERROR(F("Failed to transmit Tx via UART"));
}
}

View File

@@ -30,8 +30,14 @@ namespace emsesp {
static intr_handle_t uart_handle;
static RingbufHandle_t buf_handle = NULL;
static bool drop_next_rx = true;
static uint8_t tx_mode_ = 0xFF;
static hw_timer_t * timer = NULL;
bool drop_next_rx = true;
uint8_t tx_mode_ = 0xFF;
//portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
uint8_t emsTxBuf[EMS_MAXBUFFERSIZE];
uint8_t emsTxBufIdx;
uint8_t emsTxBufLen;
uint32_t emsTxWait;
/*
* Task to handle the incoming data
@@ -73,11 +79,39 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
drop_next_rx = false;
}
}
void IRAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
if (emsTxBufIdx > 32) {
return;
}
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
timerAlarmWrite(timer, emsTxWait, false);
timerAlarmEnable(timer);
} else if (emsTxBufIdx == emsTxBufLen) {
EMS_UART.conf0.txd_brk = 1; // <brk> after send
}
}
/*
* init UART driver
*/
void EMSuart::start(uint8_t tx_mode) {
if (tx_mode == EMS_TXMODE_DEFAULT) {
emsTxWait = EMSUART_BIT_TIME * 11;
} else if (tx_mode == EMS_TXMODE_EMSPLUS) {
emsTxWait = EMSUART_BIT_TIME * 20;
} else if (tx_mode == EMS_TXMODE_HT3) {
emsTxWait = EMSUART_BIT_TIME * 17;
} else if(tx_mode > 10 ) {
emsTxWait = EMSUART_BIT_TIME * tx_mode;
} else if(tx_mode > 5 ) {
emsTxWait = EMSUART_BIT_TIME * tx_mode * 2;
}
if (tx_mode_ != 0xFF) { // uart already initialized
tx_mode_ = tx_mode;
restart();
return;
}
@@ -101,6 +135,11 @@ void EMSuart::start(uint8_t tx_mode) {
ESP_ERROR_CHECK(uart_isr_register(EMSUART_UART, emsuart_rx_intr_handler, NULL, ESP_INTR_FLAG_IRAM, &uart_handle));
xTaskCreate(emsuart_recvTask, "emsuart_recvTask", 2048, NULL, configMAX_PRIORITIES - 1, NULL);
EMS_UART.int_ena.brk_det = 1; // activate only break
emsTxBufIdx = 0;
emsTxBufLen = 0;
timer = timerBegin(1, 80, true); // timer prescale to 1 µs, countup
timerAttachInterrupt(timer, &emsuart_tx_timer_intr_handler, true); // Timer with edge interrupt
}
/*
@@ -108,6 +147,7 @@ void EMSuart::start(uint8_t tx_mode) {
*/
void EMSuart::stop() {
EMS_UART.int_ena.val = 0; // disable all intr.
// timerAlarmDisable(timer);
};
/*
@@ -119,14 +159,24 @@ void EMSuart::restart() {
drop_next_rx = true; // and drop first frame
}
EMS_UART.int_ena.brk_det = 1; // activate only break
emsTxBufIdx = 0;
emsTxBufLen = 0;
};
/*
* Sends a 1-byte poll, ending with a <BRK>
*/
void EMSuart::send_poll(uint8_t data) {
EMS_UART.fifo.rw_byte = data;
EMS_UART.conf0.txd_brk = 1; // <brk> after send
if (tx_mode_ == EMS_TXMODE_NEW || tx_mode_ == 5) {
EMS_UART.fifo.rw_byte = data;
EMS_UART.conf0.txd_brk = 1; // <brk> after send
} else {
EMS_UART.fifo.rw_byte = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
timerAlarmWrite(timer, emsTxWait, false);
timerAlarmEnable(timer);
}
}
/*
@@ -134,12 +184,24 @@ void EMSuart::send_poll(uint8_t data) {
* buf contains the CRC and len is #bytes including the CRC
* returns code, 1=success
*/
EMSUART_STATUS EMSuart::transmit(uint8_t * buf, uint8_t len) {
if (len > 0) {
uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
if (len == 0 || len > 32) {
return EMS_TX_STATUS_ERROR;
}
if (tx_mode_ == EMS_TXMODE_NEW || tx_mode_ == 5) {
for (uint8_t i = 0; i < len; i++) {
EMS_UART.fifo.rw_byte = buf[i];
}
EMS_UART.conf0.txd_brk = 1; // <brk> after send
} else {
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
}
EMS_UART.fifo.rw_byte = buf[0];
emsTxBufIdx = 0;
emsTxBufLen = len;
timerAlarmWrite(timer, emsTxWait, false);
timerAlarmEnable(timer);
}
return EMS_TX_STATUS_OK;
}

View File

@@ -38,6 +38,13 @@
#define EMSUART_UART UART_NUM_2 // on the ESP32 we're using UART2
#define EMS_UART UART2 // for intr setting
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
#define EMS_TXMODE_DEFAULT 1
#define EMS_TXMODE_EMSPLUS 2
#define EMS_TXMODE_HT3 3
#define EMS_TXMODE_NEW 4 // for michael's testing
// customize the GPIO pins for RX and TX here
#ifdef WEMOS_D1_32
@@ -50,11 +57,8 @@
namespace emsesp {
typedef enum {
EMS_TX_STATUS_OK = 1,
EMS_TX_WTD_TIMEOUT, // watchdog timeout during send
EMS_TX_BRK_DETECT, // incoming BRK during Tx
} EMSUART_STATUS;
#define EMS_TX_STATUS_OK 1
#define EMS_TX_STATUS_ERROR 0
class EMSuart {
public:
@@ -65,11 +69,13 @@ class EMSuart {
static void send_poll(uint8_t data);
static void stop();
static void restart();
static EMSUART_STATUS transmit(uint8_t * buf, uint8_t len);
static uint16_t transmit(uint8_t * buf, uint8_t len);
private:
static void emsuart_recvTask(void * para);
static void IRAM_ATTR emsuart_rx_intr_handler(void * para);
static void IRAM_ATTR emsuart_tx_timer_intr_handler();
};
} // namespace emsesp

View File

@@ -50,13 +50,11 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2];
if (USIS(EMSUART_UART) & ((1 << UIBD))) { // BREAK detection = End of EMS data block
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
// just for testing if break isn't finished yet
// while((USS(EMSUART_UART) >> USRXD) == 0); // wait for idle state of pin
// if((USS(EMSUART_UART) >> USRXD) == 0) { // if rx is not idle wait one bittime
// delayMicroseconds(EMSUART_BIT_TIME);
// }
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
length = 0;
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
length = 0;
while ((USS(EMSUART_UART) >> USRXC) & 0x0FF) { // read fifo into buffer
uint8_t rx = USF(EMSUART_UART);
if (length < EMS_MAXBUFFERSIZE) {
@@ -116,22 +114,40 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() {
// ISR to Fire when Timer is triggered
void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
if (emsTxBufIdx > 32) {
return;
}
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx];
timer1_write(emsTxWait);
} else if (emsTxBufIdx == emsTxBufLen) {
timer1_write(emsTxWait);
} else if (emsTxBufIdx == emsTxBufLen) {
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
// timer1_write(emsTxWait);
// } else {
// USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
if (tx_mode_ > 5 || tx_mode_ < 11) {
timer1_write(5 * EMSUART_TX_BIT_TIME * 11);
USIE(EMSUART_UART) &= ~(1 << UIBD); // disable break interrupt
}
} else if (USC0(EMSUART_UART) & (1 << UCBRK)) {
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
USIE(EMSUART_UART) |= (1 << UIBD); // enable break interrupt
}
}
/*
* init UART0 driver
*/
void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
if (tx_mode_ != 0xFF) { // it's a restart no need to configure rx
if (tx_mode > 10) {
emsTxWait = 5 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode
} else if (tx_mode > 5) {
emsTxWait = 10 * EMSUART_TX_BIT_TIME * tx_mode; // bittimes for tx_mode
}
if (tx_mode == 5) {
USC0(EMSUART_UART) = 0x2C; // 8N1,5
} else {
USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1
}
if (tx_mode_ != 0xFF) { // it's a restart no need to configure uart
tx_mode_ = tx_mode;
restart();
return;
@@ -140,6 +156,7 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
// allocate and preset EMS Receive buffers
for (int i = 0; i < EMS_MAXBUFFERS; i++) {
EMSRxBuf_t * p = (EMSRxBuf_t *)malloc(sizeof(EMSRxBuf_t));
p->length = 0;
paEMSRxBuf[i] = p;
}
pEMSRxBuf = paEMSRxBuf[0]; // reset EMS Rx Buffer
@@ -155,7 +172,6 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
// set 9600, 8 bits, no parity check, 1 stop bit
USD(EMSUART_UART) = (UART_CLK_FREQ / EMSUART_BAUD);
USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1
emsuart_flush_fifos();
@@ -168,9 +184,9 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
// change: we set UCFFT to 1 to get an immediate indicator about incoming traffic.
// Otherwise, we're only noticed by UCTOT or RxBRK!
// change: don't care, we do not use these interrupts
// USC1(EMSUART_UART) = 0; // reset config first
USC1(EMSUART_UART) = 0; // reset config first
// USC1(EMSUART_UART) = (0x7F << UCFFT) | (0x04 << UCTOT) | (1 << UCTOE); // enable interupts
// set interrupts for triggers
USIC(EMSUART_UART) = 0xFFFF; // clear all interupts
USIE(EMSUART_UART) = 0; // disable all interrupts
@@ -194,11 +210,10 @@ void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
ETS_UART_INTR_ENABLE();
drop_next_rx = true;
// LOG_INFO(F("UART service for Rx/Tx started"));
// for sending with large delay in EMS+ mode we use a timer interrupt
timer1_attachInterrupt(emsuart_tx_timer_intr_handler); // Add ISR Function
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); // 5 MHz timer
emsTxWait = 5 * EMSUART_BIT_TIME * 20; // 20 bittimes for tx_mode 2
timer1_attachInterrupt(emsuart_tx_timer_intr_handler); // Add ISR Function
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); // 5 MHz timer
}
/*
@@ -229,28 +244,28 @@ void ICACHE_FLASH_ATTR EMSuart::restart() {
* Which is a 11-bit set of zero's (11 cycles)
*/
void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
uint32_t tmp;
// must make sure Tx FIFO is empty
while (((USS(EMSUART_UART) >> USTXC) & 0xFF))
;
tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask
USC0(EMSUART_UART) |= (tmp); // set bits
USC0(EMSUART_UART) &= ~(tmp); // clear bits
// do not clear buffers to get a echo back
// tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask
// USC0(EMSUART_UART) |= (tmp); // set bits
// USC0(EMSUART_UART) &= ~(tmp); // clear bits
// To create a 11-bit <BRK> we set TXD_BRK bit so the break signal will
// automatically be sent when the tx fifo is empty
tmp = (1 << UCBRK);
USC0(EMSUART_UART) |= (tmp); // set bit
ETS_UART_INTR_DISABLE();
USC0(EMSUART_UART) |= (1 << UCBRK); // set bit
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode
delayMicroseconds(EMSUART_TX_BRK_WAIT);
} else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode
delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits)
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode
delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070
} else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode
delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3); // 1144
}
USC0(EMSUART_UART) &= ~(tmp); // clear bit
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear BRK bit
ETS_UART_INTR_ENABLE();
}
/*
@@ -258,16 +273,18 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
* It's a bit dirty. there is no special wait logic per tx_mode type, fifo flushes or error checking
*/
void EMSuart::send_poll(uint8_t data) {
if (tx_mode_ == EMS_TXMODE_NEW) {
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
USF(EMSUART_UART) = data;
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
} else if (tx_mode_ == EMS_TXMODE_EMSPLUS) {
// reset tx-brk, just in case it is accidently set
USC0(EMSUART_UART) &= ~(1 << UCBRK);
if (tx_mode_ > 5) { // timer controlled modes
USF(EMSUART_UART) = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
timer1_write(emsTxWait);
} else {
} else if (tx_mode_ >= EMS_TXMODE_NEW) { // hardware controlled modes
USF(EMSUART_UART) = data;
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
} else { // software controlled modes
// EMS1.0, EMS+ and HT3
USF(EMSUART_UART) = data;
delayMicroseconds(EMSUART_TX_BRK_WAIT);
tx_brk(); // send <BRK>
@@ -279,20 +296,33 @@ void EMSuart::send_poll(uint8_t data) {
* buf contains the CRC and len is #bytes including the CRC
* returns code, 0=success, 1=brk error, 2=watchdog timeout
*/
EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
if (len == 0) {
return EMS_TX_STATUS_OK; // nothing to send
uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
if (len == 0 || len > 32) {
return EMS_TX_STATUS_ERR; // nothing or to much to send
}
#ifdef EMSESP_DEBUG
LOG_INFO(F("(debug) UART Response time: %d ms"), uuid::get_uptime() - emsRxTime);
// LOG_INFO(F("[DEBUG] UART Response time: %d ms"), uuid::get_uptime() - emsRxTime);
#endif
// if ((uuid::get_uptime() - emsRxTime) > EMS_RX_TO_TX_TIMEOUT)) { // send allowed within 20 ms
// return EMS_TX_WTD_TIMEOUT;
// return EMS_TX_STATUS_ERR;
// }
// reset tx-brk, just in case it is accidently set
USC0(EMSUART_UART) &= ~(1 << UCBRK);
// timer controlled modes with extra delay
if (tx_mode_ > 5) {
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
}
emsTxBufIdx = 0;
emsTxBufLen = len;
USF(EMSUART_UART) = buf[0];
timer1_write(emsTxWait);
return EMS_TX_STATUS_OK;
}
// new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380
if (tx_mode_ == EMS_TXMODE_NEW) {
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
if (tx_mode_ >= EMS_TXMODE_NEW) {
for (uint8_t i = 0; i < len; i++) {
USF(EMSUART_UART) = buf[i];
}
@@ -303,15 +333,10 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
// EMS+ https://github.com/proddy/EMS-ESP/issues/23#
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // With extra tx delay for EMS+
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
// USF(EMSUART_UART) = buf[i];
// delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070
USF(EMSUART_UART) = buf[i];
delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070
}
emsTxBufIdx = 0;
emsTxBufLen = len;
USF(EMSUART_UART) = buf[0];
timer1_write(emsTxWait);
// tx_brk(); // send <BRK>
tx_brk(); // send <BRK>
return EMS_TX_STATUS_OK;
}
@@ -325,14 +350,14 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
;
// wait until bits are sent on wire
delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP); // 1760
delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3);
}
tx_brk(); // send <BRK>
return EMS_TX_STATUS_OK;
}
/*
* Logic for tx_mode of 0 (EMS_TXMODE_DEFAULT)
* Logic for tx_mode of 1
* based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
*
* Logic:
@@ -347,7 +372,7 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
* 2. Busmaster cancel telegram by sending a BRK
*
* Case 1. is handled by a watchdog counter which is reset on each
* Tx attempt. The timeout should be 20x EMSUART_BIT_TIME plus
* Tx attempt. The timeout should be 20x EMSUART_TX_BIT_TIME plus
* some smart guess for processing time on targeted EMS device.
* We set Status to EMS_TX_WTD_TIMEOUT and return
*
@@ -365,23 +390,11 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
// send the bytes along the serial line
for (uint8_t i = 0; i < len; i++) {
uint16_t wdc = EMS_TX_TO_COUNT; // 1760
volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF;
USF(EMSUART_UART) = buf[i]; // send each Tx byte
// wait for echo from the busmaster
while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) {
delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles...
if (--wdc == 0) {
// interrupts();
ETS_UART_INTR_ENABLE();
return EMS_TX_WTD_TIMEOUT;
}
if (USIR(EMSUART_UART) & (1 << UIBD)) {
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
// interrupts();
ETS_UART_INTR_ENABLE();
return EMS_TX_BRK_DETECT;
}
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
}
}
@@ -392,16 +405,18 @@ EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
// neither bus collision nor timeout - send terminating BRK signal
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
// no bus collision - send terminating BRK signal
USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set <BRK>
// USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set <BRK>
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
// wait until BRK detected...
while (!(USIR(EMSUART_UART) & (1 << UIBD))) {
delayMicroseconds(EMSUART_BIT_TIME);
delayMicroseconds(EMSUART_TX_BIT_TIME);
}
USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear <BRK>
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
phantomBreak = 1;
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
// USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear <BRK>
// USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
// phantomBreak = 1;
}
// interrupts();

View File

@@ -26,7 +26,7 @@
#include <uuid/log.h>
#define EMSUART_UART 0 // UART 0
#define EMSUART_CONFIG 0x1C // 8N1 (8 bits, no stop bits, 1 parity)
#define EMSUART_CONFIG 0x1C // 8N1 (8 bits, no parity, 1 stop bit)
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMS_MAXBUFFERS 3 // buffers for circular filling to avoid collisions
@@ -41,34 +41,30 @@
#define EMS_TXMODE_NEW 4 // for michael's testing
// LEGACY
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
#define EMSUART_TX_BIT_TIME 104 // bit time @9600 baud
#define EMSUART_TX_BRK_WAIT 2070 // the BRK from Boiler master is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag)
#define EMSUART_TX_WAIT_BYTE (EMSUART_BIT_TIME * 10) // Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit)
#define EMSUART_TX_WAIT_BRK (EMSUART_BIT_TIME * 11) // Time to send a BRK Signal (11 Bit)
#define EMSUART_TX_WAIT_GAP (EMSUART_BIT_TIME * 7) // Gap between to Bytes
#define EMSUART_TX_LAG 8
#define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8)
#define EMS_TX_TO_CHARS (2 + 20)
#define EMS_TX_TO_COUNT ((EMS_TX_TO_CHARS)*8)
// EMS 1.0
#define EMSUART_TX_BUSY_WAIT (EMSUART_TX_BIT_TIME / 8) // 13
// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit). The -8 is for lag compensation.
#define EMSUART_TX_BRK_WAIT_HT3 (EMSUART_TX_BIT_TIME * 11) - 8 // 1136
namespace emsesp {
typedef enum {
EMS_TX_STATUS_OK = 1,
EMS_TX_WTD_TIMEOUT, // watchdog timeout during send
EMS_TX_BRK_DETECT, // incoming BRK during Tx
} EMSUART_STATUS;
#define EMS_TX_STATUS_ERR 0
#define EMS_TX_STATUS_OK 1
class EMSuart {
public:
EMSuart() = default;
~EMSuart() = default;
static void ICACHE_FLASH_ATTR start(uint8_t tx_mode);
static void ICACHE_FLASH_ATTR stop();
static void ICACHE_FLASH_ATTR restart();
static void ICACHE_FLASH_ATTR send_poll(uint8_t data);
static EMSUART_STATUS ICACHE_FLASH_ATTR transmit(uint8_t * buf, uint8_t len);
static void ICACHE_FLASH_ATTR start(uint8_t tx_mode);
static void ICACHE_FLASH_ATTR stop();
static void ICACHE_FLASH_ATTR restart();
static void ICACHE_FLASH_ATTR send_poll(uint8_t data);
static uint16_t ICACHE_FLASH_ATTR transmit(uint8_t * buf, uint8_t len);
typedef struct {
uint8_t length;
@@ -83,7 +79,6 @@ class EMSuart {
static void ICACHE_FLASH_ATTR emsuart_flush_fifos();
static void ICACHE_FLASH_ATTR tx_brk();
static void ICACHE_RAM_ATTR emsuart_tx_timer_intr_handler();
};
} // namespace emsesp