mode settings, RC35 temperature factor, UART modes

This commit is contained in:
MichaelDvP
2020-07-02 16:46:41 +02:00
parent 1b00a4405b
commit 51e52846f0
7 changed files with 144 additions and 177 deletions

View File

@@ -304,7 +304,7 @@ void Thermostat::thermostat_cmd(const char * message) {
}
if (nullptr != doc["building"]) {
std::string bds = doc["building"];
uint8_t bd = doc["building"];
uint8_t bd = doc["building"];
if (strcmp(bds.c_str(), "light") == 0) {
bd = 0;
} else if (strcmp(bds.c_str(), "medium") == 0) {
@@ -821,21 +821,21 @@ uint8_t Thermostat::HeatingCircuit::get_mode_type(uint8_t flags) const {
if (flags == EMS_DEVICE_FLAG_JUNKERS) {
if (mode_type == 3) {
return HeatingCircuit::Mode::HEAT;
} else if (mode == 2) {
} else if (mode_type == 2) {
return HeatingCircuit::Mode::ECO;
} else if (mode == 1) {
} else if (mode_type == 1) {
return HeatingCircuit::Mode::NOFROST;
}
} else if ((flags == EMS_DEVICE_FLAG_RC35) || (flags == EMS_DEVICE_FLAG_RC30_1)) {
if (mode_type == 0) {
return HeatingCircuit::Mode::NIGHT;
} else if (mode == 1) {
} else if (mode_type == 1) {
return HeatingCircuit::Mode::DAY;
}
} else if (flags == EMS_DEVICE_FLAG_RC300) {
if (mode_type == 0) {
return HeatingCircuit::Mode::ECO;
} else if (mode == 1) {
} else if (mode_type == 1) {
return HeatingCircuit::Mode::COMFORT;
}
} else if (flags == EMS_DEVICE_FLAG_RC100) {
@@ -1012,7 +1012,7 @@ void Thermostat::show_values(uuid::console::Shell & shell) {
}
if (Helpers::hasValue(hc->summer_mode) && hc->summer_mode) {
shell.printfln(F(" Program is set to Summer mode"));
shell.printfln(F(" Program is set to Summer mode"));
} else if (Helpers::hasValue(hc->holiday_mode) && hc->holiday_mode) {
shell.printfln(F(" Program is set to Holiday mode"));
}
@@ -1146,8 +1146,8 @@ void Thermostat::process_JunkersMonitor(std::shared_ptr<const Telegram> telegram
telegram->read_value(hc->curr_roomTemp, 4); // value is * 10
telegram->read_value(hc->setpoint_roomTemp, 2); // value is * 10
telegram->read_value(hc->mode_type, 0); // 1 = nofrost, 2 = eco, 3 = heat
telegram->read_value(hc->mode, 1); // 1 = manual, 2 = auto
telegram->read_value(hc->mode_type, 0); // 1 = nofrost, 2 = eco, 3 = heat
telegram->read_value(hc->mode, 1); // 1 = manual, 2 = auto
}
// type 0x02A5 - data from the Nefit RC1010/3000 thermostat (0x18) and RC300/310s on 0x10
@@ -1356,13 +1356,13 @@ void Thermostat::set_control(const uint8_t ctrl, const uint8_t hc_num) {
// sets the thermostat ww working mode, where mode is a string
void Thermostat::set_ww_mode(const std::string & mode) {
if (strcasecmp("off",mode.c_str()) == 0) {
if (strcasecmp("off", mode.c_str()) == 0) {
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
write_command(EMS_TYPE_wwSettings, 2, 0);
} else if (strcasecmp("on",mode.c_str()) == 0) {
} else if (strcasecmp("on", mode.c_str()) == 0) {
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
write_command(EMS_TYPE_wwSettings, 2, 1);
} else if (strcasecmp("auto",mode.c_str()) == 0) {
} else if (strcasecmp("auto", mode.c_str()) == 0) {
LOG_INFO(F("Setting thermostat warm water mode to %s"), mode.c_str());
write_command(EMS_TYPE_wwSettings, 2, 2);
} else {
@@ -1388,8 +1388,8 @@ void Thermostat::set_mode(const std::string & mode, const uint8_t hc_num) {
set_mode(HeatingCircuit::Mode::NOFROST, hc_num);
} else if (mode_tostring(HeatingCircuit::Mode::ECO) == mode) {
set_mode(HeatingCircuit::Mode::ECO, hc_num);
} else if (mode_tostring(HeatingCircuit::Mode::HOLIDAY) == mode) {
set_mode(HeatingCircuit::Mode::HOLIDAY, hc_num);
// } else if (mode_tostring(HeatingCircuit::Mode::HOLIDAY) == mode) {
// set_mode(HeatingCircuit::Mode::HOLIDAY, hc_num);
} else if (mode_tostring(HeatingCircuit::Mode::COMFORT) == mode) {
set_mode(HeatingCircuit::Mode::COMFORT, hc_num);
} else {
@@ -1413,7 +1413,7 @@ void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
uint8_t set_mode_value, offset;
uint16_t validate_typeid = 0;
uint8_t hc_p = hc->hc_num();
uint8_t hc_p = hc->hc_num() - 1;
// set the value to send via EMS depending on the mode type
switch (mode) {
@@ -1431,7 +1431,7 @@ void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
default:
case HeatingCircuit::Mode::AUTO:
case HeatingCircuit::Mode::HOLIDAY:
// case HeatingCircuit::Mode::HOLIDAY:
case HeatingCircuit::Mode::ECO:
set_mode_value = 2;
break;
@@ -1453,7 +1453,7 @@ void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
case EMSdevice::EMS_DEVICE_FLAG_RC35:
case EMSdevice::EMS_DEVICE_FLAG_RC30_1:
offset = EMS_OFFSET_RC35Set_mode;
validate_typeid = set_typeids[hc_p];
validate_typeid = monitor_typeids[hc_p];
break;
case EMSdevice::EMS_DEVICE_FLAG_RC300:
case EMSdevice::EMS_DEVICE_FLAG_RC100:
@@ -1491,7 +1491,7 @@ void Thermostat::set_mode(const uint8_t mode, const uint8_t hc_num) {
// add the write command to the Tx queue
// post validate is the corresponding monitor or set type IDs as they can differ per model
write_command(set_typeids[hc->hc_num() - 1], offset, set_mode_value, validate_typeid);
write_command(set_typeids[hc_p], offset, set_mode_value, validate_typeid);
}
// sets the thermostat temp, where mode is a string
@@ -1539,6 +1539,7 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
uint8_t model = flags() & 0x0F;
int8_t offset = -1; // we use -1 to check if there is a value
uint8_t factor = 2; // some temperatures only use 1
if (model == EMS_DEVICE_FLAG_RC10) {
offset = EMS_OFFSET_RC10Set_temp;
@@ -1584,12 +1585,15 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
break;
case HeatingCircuit::Mode::DESIGN:
offset = EMS_OFFSET_RC35Set_temp_design;
factor = 1;
break;
case HeatingCircuit::Mode::SUMMER:
offset = EMS_OFFSET_RC35Set_temp_summer;
factor = 1;
break;
case HeatingCircuit::Mode::NOFROST:
offset = EMS_OFFSET_RC35Set_temp_nofrost;
factor = 1;
break;
default:
case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code
@@ -1629,7 +1633,8 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
default:
case HeatingCircuit::Mode::AUTO: // automatic selection, if no type is defined, we use the standard code
uint8_t mode_type = hc->get_mode_type(flags());
offset = (mode_type == HeatingCircuit::Mode::NIGHT || mode_type == HeatingCircuit::Mode::ECO) ? EMS_OFFSET_JunkersSetMessage_night_temp : EMS_OFFSET_JunkersSetMessage_day_temp;
offset = (mode_type == HeatingCircuit::Mode::NIGHT || mode_type == HeatingCircuit::Mode::ECO) ? EMS_OFFSET_JunkersSetMessage_night_temp
: EMS_OFFSET_JunkersSetMessage_day_temp;
break;
}
@@ -1661,9 +1666,8 @@ void Thermostat::set_temperature(const float temperature, const uint8_t mode, co
mode_tostring(mode).c_str());
// add the write command to the Tx queue
// value is *2
// post validate is the corresponding monitor type_id
write_command(set_typeids[hc->hc_num() - 1], offset, (uint8_t)((float)temperature * (float)2), monitor_typeids[hc->hc_num() - 1]);
write_command(set_typeids[hc->hc_num() - 1], offset, (uint8_t)((float)temperature * (float)factor), monitor_typeids[hc->hc_num() - 1]);
}
}
@@ -1720,7 +1724,7 @@ void Thermostat::console_commands(Shell & shell, unsigned int context) {
flash_string_vector{F_(change), F_(mode)},
flash_string_vector{F_(mode_mandatory), F_(hc_optional)},
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
uint8_t hc = (arguments.size() == 2) ? arguments[1].at(0) - '0' : DEFAULT_HEATING_CIRCUIT;
uint8_t hc = (arguments.size() == 2) ? arguments[1].at(0) - '0' : AUTO_HEATING_CIRCUIT;
set_mode(arguments.front(), hc);
},
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
@@ -1731,7 +1735,7 @@ void Thermostat::console_commands(Shell & shell, unsigned int context) {
read_flash_string(F("eco")),
read_flash_string(F("comfort")),
read_flash_string(F("heat")),
read_flash_string(F("holiday")),
// read_flash_string(F("holiday")),
read_flash_string(F("nofrost")),
read_flash_string(F("auto"))
@@ -1743,14 +1747,10 @@ void Thermostat::console_commands(Shell & shell, unsigned int context) {
CommandFlags::ADMIN,
flash_string_vector{F_(change), F_(wwmode)},
flash_string_vector{F_(mode_mandatory)},
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) {
set_ww_mode(arguments.front());
},
[=](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments) { set_ww_mode(arguments.front()); },
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
return std::vector<std::string>{read_flash_string(F("off")),
read_flash_string(F("on")),
read_flash_string(F("auto"))
return std::vector<std::string>{read_flash_string(F("off")), read_flash_string(F("on")), read_flash_string(F("auto"))
};
});

View File

@@ -585,7 +585,7 @@ void EMSESP::send_write_request(const uint16_t type_id,
// the CRC check is not done here, only when it's added to the Rx queue with add()
void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
#ifdef EMSESP_DEBUG
static uint32_t tx_time_ = 0;
static uint32_t rx_time_ = 0;
#endif
// check first for echo
uint8_t first_value = data[0];
@@ -593,8 +593,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
// 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
// get_uptime is only updated once per loop, does not give the right time
LOG_DEBUG(F("[DEBUG] Echo after %d ms: %s"), ::millis() - tx_time_, Helpers::data_to_hex(data, length).c_str());
LOG_TRACE(F("[DEBUG] Echo after %d ms: %s"), ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
#endif
return; // it's an echo
}
@@ -642,19 +641,29 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
// check for poll
if (length == 1) {
#ifdef EMSESP_DEBUG
char s[4];
if(first_value & 0x80) {
LOG_TRACE(F("[DEBUG] next Poll %s after %d ms"), Helpers::hextoa(s, first_value), ::millis() - rx_time_);
// time measurement starts here, use millis because get_uptime is only updated once per loop
rx_time_ = ::millis();
} else {
LOG_TRACE(F("[DEBUG] Poll ack %s after %d ms"), Helpers::hextoa(s, first_value), ::millis() - rx_time_);
}
#endif
// check for poll to us, if so send top message from Tx queue immediately and quit
// if ht3 poll must be ems_bus_id else if Buderus poll must be (ems_bus_id | 0x80)
if ((first_value ^ 0x80 ^ rxservice_.ems_mask()) == txservice_.ems_bus_id()) {
EMSbus::last_bus_activity(uuid::get_uptime()); // set the flag indication the EMS bus is active
#ifdef EMSESP_DEBUG
tx_time_ = ::millis(); // get_uptime is only updated once per loop, does not give the right time
#endif
txservice_.send();
}
// send remote room temperature if active
Roomctrl::send(first_value ^ 0x80 ^ rxservice_.ems_mask());
return;
} else {
#ifdef EMSESP_DEBUG
LOG_TRACE(F("[DEBUG] Reply after %d ms: %s"), ::millis() - rx_time_, Helpers::data_to_hex(data, length).c_str());
#endif
// check if there is a message for the roomcontroller
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
// add to RxQueue, what ever it is.

View File

@@ -88,7 +88,7 @@ class Telegram {
// reads a bit value from a given telegram position
void read_bitvalue(uint8_t & value, const uint8_t index, const uint8_t bit) const {
uint8_t abs_index = (index - offset);
if (abs_index >= message_length) {
if (abs_index >= message_length - 1) {
return; // out of bounds
}
@@ -104,7 +104,7 @@ class Telegram {
// s is to override number of bytes read (e.g. use 3 to simulat a uint24_t)
void read_value(Value & value, const uint8_t index, uint8_t s = 0) const {
uint8_t size = (!s) ? sizeof(Value) : s;
int8_t abs_index = ((index - offset + size - 1) >= message_length) ? -1 : (index - offset);
int8_t abs_index = ((index - offset + size - 1) >= message_length - 1) ? -1 : (index - offset);
if (abs_index < 0) {
return; // out of bounds, we don't change the value
}

View File

@@ -61,20 +61,9 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
static uint8_t rxbuf[EMS_MAXBUFFERSIZE];
static uint8_t length;
if (EMS_UART.int_st.rxfifo_full) {
EMS_UART.int_clr.rxfifo_full = 1;
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
EMS_UART.conf1.rxfifo_full_thrhd = emsTxBufIdx + 1;
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
} else if (emsTxBufIdx == emsTxBufLen) {
EMS_UART.conf0.txd_brk = 1; // <brk> after send
EMS_UART.int_ena.rxfifo_full = 0;
EMS_UART.conf1.rxfifo_full_thrhd = 0x7F;
}
}
if (EMS_UART.int_st.brk_det) {
EMS_UART.int_clr.brk_det = 1; // clear flag
EMS_UART.conf0.txd_brk = 0; // disable <brk>
if (emsTxBufIdx < emsTxBufLen) { // timer tx_mode is interrupted by <brk>
emsTxBufIdx = emsTxBufLen; // stop timer mode
drop_next_rx = true; // we have trash in buffer
@@ -98,26 +87,32 @@ void IRAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
void IRAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
if (emsTxBufIdx > EMS_MAXBUFFERSIZE) {
return;
}
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
timerAlarmWrite(timer, emsTxWait, false);
timerAlarmEnable(timer);
} else if (emsTxBufIdx == emsTxBufLen) {
if(tx_mode_ > 50) {
for (uint8_t i = 0; i< emsTxBufLen, i++) {
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
}
EMS_UART.conf0.txd_brk = 1; // <brk> after send
timerAlarmDisable(timer);
} else {
if (emsTxBufIdx < emsTxBufLen) {
EMS_UART.fifo.rw_byte = emsTxBuf[emsTxBufIdx];
} else if (emsTxBufIdx == emsTxBufLen) {
EMS_UART.conf0.txd_brk = 1; // <brk> after send
timerAlarmDisable(timer);
}
emsTxBufIdx++;
}
}
/*
* init UART driver
*/
void EMSuart::start(uint8_t tx_mode) {
emsTxWait = EMSUART_TX_BIT_TIME * (tx_mode + 10);
void EMSuart::start(const uint8_t tx_mode) {
if(tx_mode > 50) {
emsTxWait = EMSUART_TX_BIT_TIME * (tx_mode - 50);
} else if (tx_mode > 5) {
emsTxWait = EMSUART_TX_BIT_TIME * (tx_mode + 10);
}
if (tx_mode_ != 0xFF) { // uart already initialized
tx_mode_ = tx_mode;
restart();
@@ -137,12 +132,13 @@ void EMSuart::start(uint8_t tx_mode) {
EMS_UART.int_ena.val = 0; // disable all intr.
EMS_UART.int_clr.val = 0xFFFFFFFF; // clear all intr. flags
EMS_UART.idle_conf.tx_brk_num = 11; // breaklength 11 bit
EMS_UART.idle_conf.rx_idle_thrhd = 256;
// EMS_UART.idle_conf.rx_idle_thrhd = 0;
drop_next_rx = true;
buf_handle = xRingbufferCreate(128, RINGBUF_TYPE_NOSPLIT);
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
// EMS_UART.int_ena.frm_err = 1;
emsTxBufIdx = 0;
emsTxBufLen = 0;
@@ -174,44 +170,18 @@ void EMSuart::restart() {
/*
* Sends a 1-byte poll, ending with a <BRK>
*/
void EMSuart::send_poll(uint8_t data) {
// if (tx_mode_ >= 6 || tx_mode_ < 4) { // modes 1, 2, 3 also here
if (tx_mode_ >= 5) {
EMS_UART.fifo.rw_byte = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
timerAlarmWrite(timer, emsTxWait, false);
timerAlarmEnable(timer);
} else if (tx_mode_ == 5) {
EMS_UART.fifo.rw_byte = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
EMS_UART.conf1.rxfifo_full_thrhd = 1;
EMS_UART.int_ena.rxfifo_full = 1;
} else if (tx_mode_ == EMS_TXMODE_NEW) {
EMS_UART.fifo.rw_byte = data;
EMS_UART.conf0.txd_brk = 1; // <brk> after send
} else if (tx_mode_ == EMS_TXMODE_HT3) {
EMS_UART.fifo.rw_byte = data;
delayMicroseconds(EMSUART_TX_WAIT_HT3);
EMS_UART.conf0.txd_brk = 1; // <brk>
// delayMicroseconds(EMSUART_TX_WAIT_BRK);
// EMS_UART.conf0.txd_brk = 0;
} else if (tx_mode_ == EMS_TXMODE_EMSPLUS) {
EMS_UART.fifo.rw_byte = data;
void EMSuart::send_poll(const uint8_t data) {
EMS_UART.conf0.txd_brk = 0;
EMS_UART.fifo.rw_byte = data;
if (tx_mode_ == EMS_TXMODE_EMSPLUS) {
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
EMS_UART.conf0.txd_brk = 1; // <brk>
// delayMicroseconds(EMSUART_TX_WAIT_BRK);
// EMS_UART.conf0.txd_brk = 0;
} else {
volatile uint8_t _usrxc = EMS_UART.status.rxfifo_cnt;
EMS_UART.fifo.rw_byte = data;
uint16_t timeoutcnt = EMSUART_TX_TIMEOUT;
while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) {
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
}
EMS_UART.conf0.txd_brk = 1; // <brk>
} else if (tx_mode_ == EMS_TXMODE_HT3) {
delayMicroseconds(EMSUART_TX_WAIT_HT3);
} else if (tx_mode_ == 1) {
delayMicroseconds(EMSUART_TX_WAIT_BRK);
}
EMS_UART.conf0.txd_brk = 1; // <brk> after send
return;
}
/*
@@ -219,36 +189,32 @@ void EMSuart::send_poll(uint8_t data) {
* buf contains the CRC and len is #bytes including the CRC
* returns code, 1=success
*/
uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
uint16_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
if (len == 0 || len >= EMS_MAXBUFFERSIZE) {
return EMS_TX_STATUS_ERR;
}
// needs to be disabled for the delayed modes otherwise the uart makes a <brk> after every byte
EMS_UART.conf0.txd_brk = 0;
// if (tx_mode_ >= 6 || tx_mode_ < 4) { // timer controlled modes, also modes 1, 2, 3 because delays not working
if (tx_mode_ >= 5) { // timer controlled modes
if (tx_mode_ > 5) { // timer controlled modes
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);
emsTxBufIdx = 0;
emsTxBufLen = len;
timerAlarmWrite(timer, emsTxWait, true);
timerAlarmEnable(timer);
return EMS_TX_STATUS_OK;
}
if (tx_mode_ == 5) {
if (tx_mode_ == 5) { // wait before sending
vTaskDelay(3 / portTICK_PERIOD_MS);
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
EMS_UART.fifo.rw_byte = buf[i];
}
EMS_UART.fifo.rw_byte = buf[0];
emsTxBufIdx = 0;
emsTxBufLen = len;
EMS_UART.conf1.rxfifo_full_thrhd = 1;
EMS_UART.int_ena.rxfifo_full = 1;
EMS_UART.conf0.txd_brk = 1; // <brk> after send
return EMS_TX_STATUS_OK;
}
if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes
for (uint8_t i = 0; i < len; i++) {
EMS_UART.fifo.rw_byte = buf[i];
@@ -263,19 +229,16 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
}
EMS_UART.conf0.txd_brk = 1; // <brk> after send, cleard by hardware after send
// delayMicroseconds(EMSUART_TX_WAIT_BRK);
// EMS_UART.conf0.txd_brk = 0;
return EMS_TX_STATUS_OK;
}
if (tx_mode_ == EMS_TXMODE_HT3) { // HT3 with 7 bittimes delay
for (uint8_t i = 0; i < len; i++) {
for (uint8_t i = 0; i < len - 1; i++) {
EMS_UART.fifo.rw_byte = buf[i];
delayMicroseconds(EMSUART_TX_WAIT_HT3);
}
EMS_UART.fifo.rw_byte = buf[len - 1];
EMS_UART.conf0.txd_brk = 1; // <brk> after send, cleard by hardware after send
// delayMicroseconds(EMSUART_TX_WAIT_BRK);
// EMS_UART.conf0.txd_brk = 0;
return EMS_TX_STATUS_OK;
}
@@ -288,12 +251,10 @@ uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
EMS_UART.fifo.rw_byte = buf[i]; // send each Tx byte
uint16_t timeoutcnt = EMSUART_TX_TIMEOUT;
while ((EMS_UART.status.rxfifo_cnt == _usrxc) && (--timeoutcnt > 0)) {
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
delayMicroseconds(EMSUART_TX_BUSY_WAIT); // burn CPU cycles...
}
}
EMS_UART.conf0.txd_brk = 1; // <brk> after send, cleard by hardware after send
// delayMicroseconds(EMSUART_TX_WAIT_BRK);
// EMS_UART.conf0.txd_brk = 0;
return EMS_TX_STATUS_OK;
}

View File

@@ -32,6 +32,7 @@
#include "freertos/ringbuf.h"
#include "freertos/queue.h"
#include <driver/uart.h>
#include <driver/timer.h>
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
@@ -79,11 +80,11 @@ class EMSuart {
EMSuart() = default;
~EMSuart() = default;
static void start(uint8_t tx_mode);
static void send_poll(uint8_t data);
static void start(const uint8_t tx_mode);
static void send_poll(const uint8_t data);
static void stop();
static void restart();
static uint16_t transmit(uint8_t * buf, uint8_t len);
static uint16_t transmit(const uint8_t * buf, const uint8_t len);
private:
static void emsuart_recvTask(void * para);

View File

@@ -44,18 +44,6 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
static uint8_t length = 0;
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2];
if (USIS(EMSUART_UART) & ((1 << UIFF))) { // Fifo full, sending in Mode 5
USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo interrupt
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx]; // send next byte
USC1(EMSUART_UART) = ((emsTxBufIdx + 1) << UCFFT); // increase fifo full
} else if (emsTxBufIdx == emsTxBufLen) {
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
USIE(EMSUART_UART) &= ~(1 << UIFF); // disable fifo-full irq
USC1(EMSUART_UART) = (0x7F << UCFFT); // fifo full to max
}
}
if (USIS(EMSUART_UART) & ((1 << UIBD))) { // BREAK detection = End of EMS data block
USC0(EMSUART_UART) &= ~(1 << UCBRK); // reset tx-brk
if (emsTxBufIdx < emsTxBufLen) { // irq tx_mode is interrupted by <brk>
@@ -110,15 +98,22 @@ 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 > EMS_MAXBUFFERSIZE) {
return;
}
emsTxBufIdx++;
if (emsTxBufIdx < emsTxBufLen) {
USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx];
timer1_write(emsTxWait);
} else if (emsTxBufIdx == emsTxBufLen) {
if ( tx_mode_ > 50) {
for (uint8_t i = 0; i < emsTxBufLen; i++) {
USF(EMSUART_UART) = emsTxBuf[i];
}
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
} else {
if (emsTxBufIdx > emsTxBufLen) {
return;
}
if (emsTxBufIdx < emsTxBufLen) {
USF(EMSUART_UART) = emsTxBuf[emsTxBufIdx];
timer1_write(emsTxWait);
} else if (emsTxBufIdx == emsTxBufLen) {
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
}
emsTxBufIdx++;
}
}
@@ -126,8 +121,10 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
* init UART0 driver
*/
void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
if (tx_mode >= 5) {
emsTxWait = 5 * EMSUART_TX_BIT_TIME * (tx_mode + 10); // bittimes for tx_mode
if (tx_mode > 50) {
emsTxWait = 5 * EMSUART_TX_BIT_TIME * (tx_mode - 50); // bittimes wait before sending
} else if (tx_mode > 5) {
emsTxWait = 5 * EMSUART_TX_BIT_TIME * (tx_mode + 10); // bittimes wait between bytes
}
if (tx_mode_ != 0xFF) { // it's a restart no need to configure uart
tx_mode_ = tx_mode;
@@ -222,12 +219,6 @@ void ICACHE_FLASH_ATTR EMSuart::restart() {
emsTxBufIdx = 0;
emsTxBufLen = 0;
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
if (tx_mode_ == 5) {
USC0(EMSUART_UART) = 0x2C; // 8N1.5
} else {
USC0(EMSUART_UART) = EMSUART_CONFIG; // 8N1
}
}
/*
@@ -260,21 +251,22 @@ void EMSuart::send_poll(uint8_t data) {
USC0(EMSUART_UART) &= ~(1 << UCBRK);
sending_ = true;
if (tx_mode_ > 5) { // timer controlled modes
USF(EMSUART_UART) = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
if (tx_mode_ > 50) { // timer controlled modes
emsTxBuf[0] = data;
emsTxBufLen = 1;
timer1_write(emsTxWait);
} else if (tx_mode_ == 5) { // reload sendbuffer in irq
USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo-full irq
USC1(EMSUART_UART) = (0x01 << UCFFT); // fifo full to 1
USF(EMSUART_UART) = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
USIE(EMSUART_UART) |= (1 << UIFF); // enable fifo-full irq
} else if (tx_mode_ > 5) { // timer controlled modes
emsTxBuf[0] = data;
emsTxBufIdx = 0;
emsTxBufLen = 1;
timer1_write(emsTxWait);
}else if (tx_mode_ == 5) {
delayMicroseconds(3000);
USF(EMSUART_UART) = data;
USC0(EMSUART_UART) |= (1 << UCBRK);
} else if (tx_mode_ == EMS_TXMODE_NEW) { // hardware controlled modes
USF(EMSUART_UART) = data;
USC0(EMSUART_UART) |= (1 << UCBRK); // brk after sendout
USC0(EMSUART_UART) |= (1 << UCBRK);
} else if (tx_mode_ == EMS_TXMODE_HT3) {
USF(EMSUART_UART) = data;
delayMicroseconds(EMSUART_TX_WAIT_HT3);
@@ -316,28 +308,32 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
USC0(EMSUART_UART) &= ~(1 << UCBRK);
sending_ = true;
// all at once after a inititial timer delay
if (tx_mode_ > 50) {
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
}
emsTxBufLen = len;
timer1_write(emsTxWait);
return EMS_TX_STATUS_OK;
}
// 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];
emsTxBufIdx = 0;
emsTxBufLen = len;
timer1_write(emsTxWait);
return EMS_TX_STATUS_OK;
}
// interrupt controlled mode: readback in rx-irq and send next byte
// fixed dealy before sending
if (tx_mode_ == 5) {
delayMicroseconds(3000);
for (uint8_t i = 0; i < len; i++) {
emsTxBuf[i] = buf[i];
USF(EMSUART_UART) = buf[i];
}
USIC(EMSUART_UART) |= (1 << UIFF); // clear fifo-full irq
emsTxBufIdx = 0;
emsTxBufLen = len;
USC1(EMSUART_UART) = (0x01 << UCFFT); // fifo full to 1
USIE(EMSUART_UART) |= (1 << UIFF); // enable fifo-full irq
USF(EMSUART_UART) = buf[0];
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
return EMS_TX_STATUS_OK;
}

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "2.0.0a30"
#define EMSESP_APP_VERSION "2.0.0a31"