Split platform files. Reading via interrupt

This commit is contained in:
Your Name 2023-02-12 18:54:47 +01:00
parent e3f2ca70dc
commit aafaf474d3
8 changed files with 342 additions and 351 deletions

View File

@ -3,33 +3,6 @@
#include "esphome/core/log.h"
#include "helpers.h"
#ifdef USE_ESP32
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include "soc/uart_reg.h"
#endif
#ifdef USE_ESP8266
#include "esphome/components/uart/uart_component_esp8266.h"
#endif
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include "esphome/components/uart/truma_uart_component_esp32_arduino.h"
#include "esphome/components/uart/uart_component_esp32_arduino.h"
#endif
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
#include "esphome/components/uart/truma_uart_component_esp_idf.h"
#include "esphome/components/uart/uart_component_esp_idf.h"
#endif
#ifdef USE_RP2040
#include "esphome/components/uart/truma_uart_component_rp2040.h"
#include "esphome/components/uart/uart_component_rp2040.h"
#endif
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
// For method `xTaskCreateUniversal`
#include <esp32-hal.h>
#endif
namespace esphome {
namespace truma_inetbox {
@ -54,52 +27,8 @@ void LinBusListener::setup() {
this->time_per_first_byte_ = this->time_per_baud_ * this->frame_length_ * 3.0;
this->time_per_byte_ = this->time_per_baud_ * this->frame_length_ * 1.1;
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
auto uartComp = static_cast<esphome::uart::truma_ESP32ArduinoUARTComponent *>(this->parent_);
auto uart_num = uartComp->get_hw_serial_number();
// Tweak the fifo settings so data is available as soon as the first byte is recieved.
// If not it will wait either until fifo is filled or a certain time has passed.
uart_intr_config_t uart_intr;
uart_intr.intr_enable_mask =
UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M; // only these IRQs - no BREAK, PARITY or OVERFLOW
// UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M |
// UART_RXFIFO_OVF_INT_ENA_M | UART_BRK_DET_INT_ENA_M | UART_PARITY_ERR_INT_ENA_M;
uart_intr.rxfifo_full_thresh =
1; // UART_FULL_THRESH_DEFAULT, //120 default!! aghh! need receive 120 chars before we see them
uart_intr.rx_timeout_thresh =
10; // UART_TOUT_THRESH_DEFAULT, //10 works well for my short messages I need send/receive
uart_intr.txfifo_empty_intr_thresh = 10; // UART_EMPTY_THRESH_DEFAULT
uart_intr_config(uart_num, &uart_intr);
#elif USE_ESP32_FRAMEWORK_ESP_IDF
// uartSetFastReading
auto uartComp = ((*uart::truma_IDFUARTComponent) this->parent_);
// Tweak the fifo settings so data is available as soon as the first byte is recieved.
// If not it will wait either until fifo is filled or a certain time has passed.
uart_intr_config_t uart_intr;
uart_intr.intr_enable_mask = 0; // UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M |
// UART_RXFIFO_OVF_INT_ENA_M | UART_BRK_DET_INT_ENA_M | UART_PARITY_ERR_INT_ENA_M;
uart_intr.rxfifo_full_thresh =
1; // UART_FULL_THRESH_DEFAULT, //120 default!! aghh! need receive 120 chars before we see them
uart_intr.rx_timeout_thresh =
1; // UART_TOUT_THRESH_DEFAULT, //10 works well for my short messages I need send/receive
uart_intr.txfifo_empty_intr_thresh = 10; // UART_EMPTY_THRESH_DEFAULT
uart_intr_config(uartComp->get_hw_serial_number(), &uart_intr);
#else
// truma_RP2040UartComponent
#error Only ESP32 Arduino is supported.
#endif
xTaskCreateUniversal(LinBusListener::read_task,
"read_task", // name
4096, // stack size (in words)
this, // input params
1, // priority
&this->read_task_handle, // handle
0 // core
);
// call device specific function
this->setup_framework();
if (this->cs_pin_ != nullptr) {
this->cs_pin_->digital_write(true);
@ -117,19 +46,6 @@ void LinBusListener::write_lin_answer_(const u_int8_t *data, size_t len) {
return;
}
int64_t wait_time = 0;
// Was data read from FIFO and the master is awaiting an answer.
if (this->total_wait_ > 1000) {
// I am up to date and should not answer too quickly.
auto current = esp_timer_get_time();
auto wait_time_in_us = (int64_t) this->time_per_baud_ - (current - this->last_data_recieved_);
wait_time = wait_time_in_us;
if (wait_time_in_us > 1000 || wait_time_in_us < 0) {
wait_time_in_us = 0;
}
delayMicroseconds(wait_time_in_us);
}
u_int8_t data_CRC = 0;
if (this->lin_checksum_ == LIN_CHECKSUM::LIN_CHECKSUM_VERSION_1 || this->current_PID_ == DIAGNOSTIC_FRAME_SLAVE) {
// LIN checksum V1
@ -144,57 +60,18 @@ void LinBusListener::write_lin_answer_(const u_int8_t *data, size_t len) {
this->write(data_CRC);
this->flush();
}
ESP_LOGV(TAG, "RESPONSE %02x %s %02x T %lli", this->current_PID_, format_hex_pretty(data, len).c_str(), data_CRC,
wait_time);
}
void LinBusListener::read_task(void *params) {
LinBusListener *instance = (LinBusListener *) params;
while (true) {
// Check if Lin Bus is faulty.
if (instance->fault_pin_ != nullptr) {
if (!instance->fault_pin_->digital_read()) {
if (!instance->fault_on_lin_bus_reported_) {
instance->fault_on_lin_bus_reported_ = true;
ESP_LOGE(TAG, "Fault on LIN BUS detected.");
}
// Ignore any data present in buffer
instance->clear_uart_buffer_();
} else if (instance->fault_on_lin_bus_reported_) {
instance->fault_on_lin_bus_reported_ = false;
ESP_LOGI(TAG, "Fault on LIN BUS fixed.");
}
}
if (!instance->fault_on_lin_bus_reported_) {
while (instance->available()) {
instance->read_lin_frame_();
}
}
// Check if CP Plus is inactive mode. In inactive mode it checks the bus every ~15 seconds for ~5 seconds. At the
// start it send a Break to notify devices to wake up.
auto time_since_last_activity = esp_timer_get_time() - instance->last_data_recieved_;
if (time_since_last_activity > 100 * 1000 /* 100 ms*/) {
// CP Plus is inactive.
delay(500); // NOLINT
} else {
// CP Plus is active.
// 1'000'000 ns / 9600 baud = 104 ns/baud * (8 bit + start bit + 2 stop bit) = 1144 ns/byte * 3 (BREAK,SYNC,PID) =
// ~3.5ms per preamble till I should answer. It is still working with 50ms. But thats the upper limit. CP Plus
// waits 50ms when ordering for an answer. With higher polling the number of CRC errors increases and I cannot
// answer lin orders.
delay(10); // NOLINT
}
}
ESP_LOGV(TAG, "RESPONSE %02x %s %02x", this->current_PID_, format_hex_pretty(data, len).c_str(), data_CRC);
}
void LinBusListener::read_lin_frame_() {
u_int8_t buf;
bool dataRecieved;
u_int8_t data_length, data_CRC, data_CRC_master, data_CRC_slave;
bool message_source_know, message_from_master;
switch (this->current_state_) {
case READ_STATE_BREAK:
// Check if there was an unanswered message before break.
if (this->current_PID_with_parity_ != 0x00 && this->current_PID_ != 0x00 && this->current_data_valid &&
this->current_data_count_ == 0) {
ESP_LOGV(TAG, "PID %02x (%02x) order no answer", this->current_PID_, this->current_PID_with_parity_);
}
// Reset current state
{
@ -203,69 +80,61 @@ void LinBusListener::read_lin_frame_() {
this->current_data_valid = true;
this->current_data_count_ = 0;
memset(this->current_data_, 0, sizeof(this->current_data_));
this->total_wait_ = 0;
}
// First is Break expected
if (!this->read_byte(&buf) || buf != LIN_BREAK) {
// Update I recieved garbage
this->last_data_recieved_ = esp_timer_get_time();
ESP_LOGVV(TAG, "Expected BREAK not received.");
return;
} else {
this->current_state_ = READ_STATE_SYNC;
}
// Update I recieved a break
this->last_data_recieved_ = esp_timer_get_time();
if (!this->wait_for_data_available_with_timeout_(this->time_per_lin_break_)) {
ESP_LOGV(TAG, "Timeout waiting for Sync");
return;
}
break;
case READ_STATE_SYNC:
// Second is Sync expected
if (!this->read_byte(&buf) || buf != LIN_SYNC) {
// No data present on UART
ESP_LOGVV(TAG, "Expected SYNC not found.");
return;
this->current_state_ = READ_STATE_BREAK;
} else {
this->current_state_ = READ_STATE_SID;
}
if (!this->wait_for_data_available_with_timeout_(this->time_per_pid_)) {
ESP_LOGVV(TAG, "Timeout waiting for PID.");
return;
}
break;
case READ_STATE_SID:
this->read_byte(&(this->current_PID_with_parity_));
this->current_PID_ = this->current_PID_with_parity_ & 0x3F;
if (this->lin_checksum_ == LIN_CHECKSUM::LIN_CHECKSUM_VERSION_2) {
if (this->current_PID_with_parity_ != (this->current_PID_ | (addr_parity(this->current_PID_) << 6))) {
ESP_LOGW(TAG, "LIN CRC error");
ESP_LOGW(TAG, "LIN CRC error on SID.");
this->current_data_valid = false;
}
}
if (this->current_data_valid) {
this->can_write_lin_answer_ = true;
// Should I response to this PID order? Ask the handling class.
this->answer_lin_order_(this->current_PID_);
this->can_write_lin_answer_ = false;
}
dataRecieved = wait_for_data_available_with_timeout_(this->time_per_first_byte_);
while (dataRecieved) {
// Even on error read data.
this->current_state_ = READ_STATE_DATA;
break;
case READ_STATE_DATA:
this->read_byte(&buf);
if (this->current_data_count_ < sizeof(this->current_data_)) {
this->current_data_[this->current_data_count_] = buf;
this->current_data_count_++;
dataRecieved = wait_for_data_available_with_timeout_(this->time_per_byte_);
} else {
// end of data reached. There cannot be more than 9 bytes in a LIN frame.
dataRecieved = false;
if (this->current_data_count_ >= sizeof(this->current_data_)) {
// End of data reached. There cannot be more than 9 bytes in a LIN frame.
this->current_state_ = READ_STATE_ACT;
}
break;
}
if (this->current_data_count_ > 1) {
data_length = this->current_data_count_ - 1;
data_CRC = this->current_data_[this->current_data_count_ - 1];
message_source_know = false;
message_from_master = true;
if (this->current_state_ == READ_STATE_ACT && this->current_data_count_ > 1) {
u_int8_t data_length = this->current_data_count_ - 1;
u_int8_t data_CRC = this->current_data_[this->current_data_count_ - 1];
bool message_source_know = false;
bool message_from_master = true;
if (this->lin_checksum_ == LIN_CHECKSUM::LIN_CHECKSUM_VERSION_1 ||
(this->current_PID_ == DIAGNOSTIC_FRAME_MASTER || this->current_PID_ == DIAGNOSTIC_FRAME_SLAVE)) {
@ -281,8 +150,8 @@ void LinBusListener::read_lin_frame_() {
message_from_master = false;
}
} else {
data_CRC_master = data_checksum(this->current_data_, data_length, this->current_PID_);
data_CRC_slave = data_checksum(this->current_data_, data_length, this->current_PID_with_parity_);
u_int8_t data_CRC_master = data_checksum(this->current_data_, data_length, this->current_PID_);
u_int8_t data_CRC_slave = data_checksum(this->current_data_, data_length, this->current_PID_with_parity_);
if (data_CRC != data_CRC_master && data_CRC != data_CRC_slave) {
ESP_LOGW(TAG, "LIN v2 CRC error");
this->current_data_valid = false;
@ -309,8 +178,7 @@ void LinBusListener::read_lin_frame_() {
if (this->current_data_valid && message_from_master) {
this->lin_message_recieved_(this->current_PID_, this->current_data_, data_length);
}
} else {
ESP_LOGV(TAG, "PID %02x (%02x) order no answer", this->current_PID_, this->current_PID_with_parity_);
this->current_state_ = READ_STATE_BREAK;
}
}
@ -320,21 +188,5 @@ void LinBusListener::clear_uart_buffer_() {
}
}
bool LinBusListener::wait_for_data_available_with_timeout_(u_int32_t timeout) {
int64_t start = esp_timer_get_time();
int64_t current = esp_timer_get_time();
int64_t latest_end = start + timeout;
while (current < latest_end) {
current = esp_timer_get_time();
if (this->available()) {
this->total_wait_ += current - start;
this->last_data_recieved_ = current;
return true;
}
NOP();
}
return false;
}
} // namespace truma_inetbox
} // namespace esphome

View File

@ -4,11 +4,6 @@
#include "esphome/core/component.h"
#include "esphome/components/uart/uart.h"
#ifdef USE_ESP32
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#endif
namespace esphome {
namespace truma_inetbox {
@ -56,23 +51,26 @@ class LinBusListener : public PollingComponent, public uart::UARTDevice {
bool fault_on_lin_bus_reported_ = false;
bool can_write_lin_answer_ = false;
enum read_state {
READ_STATE_BREAK,
READ_STATE_SYNC,
READ_STATE_SID,
READ_STATE_DATA,
READ_STATE_ACT,
};
read_state current_state_ = READ_STATE_BREAK;
u_int8_t current_PID_with_parity_ = 0x00;
u_int8_t current_PID_ = 0x00;
bool current_data_valid = true;
u_int8_t current_data_count_ = 0;
// up to 8 byte data frame + CRC
u_int8_t current_data_[9] = {};
// Total wait time for this LIN Frame (Break, SYNC, Data, CRC)
u_int32_t total_wait_;
// Time when the last LIN data was available.
int64_t last_data_recieved_;
TaskHandle_t read_task_handle = NULL;
static void read_task(void *params);
// // Time when the last LIN data was available.
// int64_t last_data_recieved_;
void read_lin_frame_();
void clear_uart_buffer_();
bool wait_for_data_available_with_timeout_(u_int32_t timeout);
void setup_framework();
};
} // namespace truma_inetbox

View File

@ -0,0 +1,85 @@
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
#include "LinBusListener.h"
#include "esphome/core/log.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include "soc/uart_reg.h"
#include "esphome/components/uart/truma_uart_component_esp32_arduino.h"
#include "esphome/components/uart/uart_component_esp32_arduino.h"
namespace esphome {
namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.LinBusListener";
void LinBusListener::setup_framework() {
auto uartComp = static_cast<esphome::uart::truma_ESP32ArduinoUARTComponent *>(this->parent_);
auto uart_num = uartComp->get_hw_serial_number();
auto hwSerial = uartComp->get_hw_serial();
// Extract from `uartSetFastReading` - Can't call it because I don't have access to `uart_t` object.
// Tweak the fifo settings so data is available as soon as the first byte is recieved.
// If not it will wait either until fifo is filled or a certain time has passed.
uart_intr_config_t uart_intr;
uart_intr.intr_enable_mask =
UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M; // only these IRQs - no BREAK, PARITY or OVERFLOW
// UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M |
// UART_RXFIFO_OVF_INT_ENA_M | UART_BRK_DET_INT_ENA_M | UART_PARITY_ERR_INT_ENA_M;
uart_intr.rxfifo_full_thresh =
1; // UART_FULL_THRESH_DEFAULT, //120 default!! aghh! need receive 120 chars before we see them
uart_intr.rx_timeout_thresh =
10; // UART_TOUT_THRESH_DEFAULT, //10 works well for my short messages I need send/receive
uart_intr.txfifo_empty_intr_thresh = 10; // UART_EMPTY_THRESH_DEFAULT
uart_intr_config(uart_num, &uart_intr);
hwSerial->onReceive(
[this]() {
// Check if Lin Bus is faulty.
if (this->fault_pin_ != nullptr) {
if (!this->fault_pin_->digital_read()) {
if (!this->fault_on_lin_bus_reported_) {
this->fault_on_lin_bus_reported_ = true;
ESP_LOGE(TAG, "Fault on LIN BUS detected.");
}
// Ignore any data present in buffer
this->clear_uart_buffer_();
} else if (this->fault_on_lin_bus_reported_) {
this->fault_on_lin_bus_reported_ = false;
ESP_LOGI(TAG, "Fault on LIN BUS fixed.");
}
}
if (!this->fault_on_lin_bus_reported_) {
while (this->available()) {
// this->last_data_recieved_ = esp_timer_get_time();
this->read_lin_frame_();
}
}
},
false);
hwSerial->onReceiveError([this](hardwareSerial_error_t val) {
if (val == UART_BREAK_ERROR) {
// If the break is valid the `onReceive` is called first and the break is handeld. Therfore the expectation is
// that the state should be in waiting for `SYNC`.
if (this->current_state_ != READ_STATE_SYNC) {
this->current_state_ = READ_STATE_BREAK;
}
return;
} else if (val == UART_BUFFER_FULL_ERROR) {
ESP_LOGW(TAG, "UART_BUFFER_FULL_ERROR");
} else if (val == UART_FIFO_OVF_ERROR) {
ESP_LOGW(TAG, "UART_FIFO_OVF_ERROR");
} else if (val == UART_FRAME_ERROR) {
ESP_LOGW(TAG, "UART_FRAME_ERROR");
} else if (val == UART_PARITY_ERROR) {
ESP_LOGW(TAG, "UART_PARITY_ERROR");
}
});
}
} // namespace truma_inetbox
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ARDUINO

View File

@ -0,0 +1,31 @@
#ifdef USE_ESP32_FRAMEWORK_ESP_IDF
#include "LinBusListener.h"
#include "esphome/core/log.h"
#include "esphome/components/uart/truma_uart_component_esp_idf.h"
#include "esphome/components/uart/uart_component_esp_idf.h"
namespace esphome {
namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.LinBusListener";
void LinBusListener::setup_framework() {
// uartSetFastReading
auto uartComp = ((*uart::truma_IDFUARTComponent) this->parent_);
// Tweak the fifo settings so data is available as soon as the first byte is recieved.
// If not it will wait either until fifo is filled or a certain time has passed.
uart_intr_config_t uart_intr;
uart_intr.intr_enable_mask = 0; // UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M |
// UART_RXFIFO_OVF_INT_ENA_M | UART_BRK_DET_INT_ENA_M | UART_PARITY_ERR_INT_ENA_M;
uart_intr.rxfifo_full_thresh =
1; // UART_FULL_THRESH_DEFAULT, //120 default!! aghh! need receive 120 chars before we see them
uart_intr.rx_timeout_thresh =
1; // UART_TOUT_THRESH_DEFAULT, //10 works well for my short messages I need send/receive
uart_intr.txfifo_empty_intr_thresh = 10; // UART_EMPTY_THRESH_DEFAULT
uart_intr_config(uartComp->get_hw_serial_number(), &uart_intr);
}
} // namespace truma_inetbox
} // namespace esphome
#endif // USE_ESP32_FRAMEWORK_ESP_IDF

View File

@ -0,0 +1,18 @@
#ifdef USE_RP2040
#include "LinBusListener.h"
#include "esphome/core/log.h"
#include "esphome/components/uart/truma_uart_component_rp2040.h"
#include "esphome/components/uart/uart_component_rp2040.h"
namespace esphome {
namespace truma_inetbox {
static const char *const TAG = "truma_inetbox.LinBusListener";
void LinBusListener::setup_framework() {
// truma_RP2040UartComponent
}
} // namespace truma_inetbox
} // namespace esphome
#endif // USE_RP2040

View File

@ -54,33 +54,15 @@ void LinBusProtocol::lin_message_recieved_(const u_int8_t pid, const u_int8_t *m
// this->prepare_update_msg_(response);
// }
this->lin_message_recieved_diagnostic_(message, length);
} else if (pid == this->lin_node_address_) {
ESP_LOGW(TAG, "Unhandled message for me.");
}
}
void LinBusProtocol::prepare_update_msg_(const std::array<u_int8_t, 8> message) {
this->updates_to_send_.push(message);
}
bool LinBusProtocol::is_matching_identifier_(const u_int8_t *message) {
auto lin_identifier = this->lin_identifier();
return message[0] == lin_identifier[0] && message[1] == lin_identifier[1] && message[2] == lin_identifier[2] &&
message[3] == lin_identifier[3];
}
void LinBusProtocol::lin_message_recieved_diagnostic_(const u_int8_t *message, u_int8_t length) {
u_int8_t node_address = message[0];
bool my_node_address = node_address == this->lin_node_address_;
bool broadcast_address = node_address == LIN_NAD_BROADCAST;
{
// auto node_address = message[0];
bool my_node_address = message[0] == this->lin_node_address_;
bool broadcast_address = message[0] == LIN_NAD_BROADCAST;
if (!my_node_address && !broadcast_address) {
return;
}
}
u_int8_t protocol_control_information = message[1];
u_int16_t message_length = 0;
u_int8_t service_identifier = 0;
if ((protocol_control_information & 0xF0) == 0x00) {
// Single Frame mode
{
@ -89,56 +71,42 @@ void LinBusProtocol::lin_message_recieved_diagnostic_(const u_int8_t *message, u
this->multi_pdu_message_len_ = 0;
this->multi_pdu_message_frame_counter_ = 0;
}
message_length = protocol_control_information;
service_identifier = message[2];
this->lin_msg_diag_single_(message, length);
} else if ((protocol_control_information & 0xF0) == 0x10) {
// First Frame of multi PDU message
this->lin_msg_diag_first_(message, length);
} else if ((protocol_control_information & 0xF0) == 0x20) {
// Consecutive Frames
this->lin_msg_diag_consecutive_(message, length);
// Check if this was the last consecutive message.
if (this->multi_pdu_message_len_ == this->multi_pdu_message_expected_size_) {
this->lin_msg_diag_multi_();
}
}
} else if (pid == this->lin_node_address_) {
ESP_LOGW(TAG, "Unhandled message for me.");
}
}
bool LinBusProtocol::is_matching_identifier_(const u_int8_t *message) {
auto lin_identifier = this->lin_identifier();
return message[0] == lin_identifier[0] && message[1] == lin_identifier[1] && message[2] == lin_identifier[2] &&
message[3] == lin_identifier[3];
}
void LinBusProtocol::lin_msg_diag_single_(const u_int8_t *message, u_int8_t length) {
// auto node_address = message[0];
bool my_node_address = message[0] == this->lin_node_address_;
bool broadcast_address = message[0] == LIN_NAD_BROADCAST;
u_int8_t message_length = message[1];
u_int8_t service_identifier = message[2];
if (message_length > 6) {
ESP_LOGE(TAG, "LIN Protocol issue: Single frame message too long.");
// ignore invalid message
return;
}
} else if ((protocol_control_information & 0xF0) == 0x10) {
// First Frame of multi PDU message
message_length = (protocol_control_information & 0x0F << 8) + message[2];
service_identifier = message[3];
if (message_length < 7) {
ESP_LOGE(TAG, "LIN Protocol issue: Multi frame message too short.");
// ignore invalid message
return;
}
if (message_length > sizeof(this->multi_pdu_message_)) {
ESP_LOGE(TAG, "LIN Protocol issue: Multi frame message too long.");
// ignore invalid message
return;
}
this->multi_pdu_message_expected_size_ = message_length;
this->multi_pdu_message_len_ = 0;
this->multi_pdu_message_frame_counter_ = 1;
for (size_t i = 3; i < 8; i++) {
this->multi_pdu_message_[this->multi_pdu_message_len_++] = message[i];
}
// Message is handeld
return;
} else if ((protocol_control_information & 0xF0) == 0x20) {
// Consecutive Frames
if (this->multi_pdu_message_len_ >= this->multi_pdu_message_expected_size_) {
// ignore, because i don't await a consecutive frame
return;
}
u_int8_t frame_counter = protocol_control_information & 0x0F;
if (frame_counter != this->multi_pdu_message_frame_counter_) {
// ignore, because i don't await this consecutive frame
return;
}
this->multi_pdu_message_frame_counter_++;
if (this->multi_pdu_message_frame_counter_ > 0x0F) {
// Frame counter has only 4 bit and wraps around.
this->multi_pdu_message_frame_counter_ = 0x00;
}
this->lin_message_recieved_diagnostic_multi_(message, length, protocol_control_information);
// Message is handeld
return;
}
if (service_identifier == LIN_SID_READ_BY_IDENTIFIER && message_length == 6) {
if (this->is_matching_identifier_(&message[4])) {
@ -201,16 +169,55 @@ void LinBusProtocol::lin_message_recieved_diagnostic_(const u_int8_t *message, u
}
}
void LinBusProtocol::lin_message_recieved_diagnostic_multi_(const u_int8_t *message, u_int8_t length,
u_int8_t protocol_control_information) {
void LinBusProtocol::lin_msg_diag_first_(const u_int8_t *message, u_int8_t length) {
u_int8_t protocol_control_information = message[1];
u_int16_t message_length = (protocol_control_information & 0x0F << 8) + message[2];
if (message_length < 7) {
ESP_LOGE(TAG, "LIN Protocol issue: Multi frame message too short.");
// ignore invalid message
return;
}
if (message_length > sizeof(this->multi_pdu_message_)) {
ESP_LOGE(TAG, "LIN Protocol issue: Multi frame message too long.");
// ignore invalid message
return;
}
this->multi_pdu_message_expected_size_ = message_length;
this->multi_pdu_message_len_ = 0;
this->multi_pdu_message_frame_counter_ = 1;
// Copy recieved message over to `multi_pdu_message_` buffer.
for (size_t i = 3; i < 8; i++) {
this->multi_pdu_message_[this->multi_pdu_message_len_++] = message[i];
}
}
void LinBusProtocol::lin_msg_diag_consecutive_(const u_int8_t *message, u_int8_t length) {
if (this->multi_pdu_message_len_ >= this->multi_pdu_message_expected_size_) {
// ignore, because i don't await a consecutive frame
return;
}
u_int8_t protocol_control_information = message[1];
u_int8_t frame_counter = protocol_control_information & 0x0F;
if (frame_counter != this->multi_pdu_message_frame_counter_) {
// ignore, because i don't await this consecutive frame
return;
}
this->multi_pdu_message_frame_counter_++;
if (this->multi_pdu_message_frame_counter_ > 0x0F) {
// Frame counter has only 4 bit and wraps around.
this->multi_pdu_message_frame_counter_ = 0x00;
}
// Copy recieved message over to `multi_pdu_message_` buffer.
for (u_int8_t i = 2; i < 8; i++) {
if (this->multi_pdu_message_len_ < this->multi_pdu_message_expected_size_) {
this->multi_pdu_message_[this->multi_pdu_message_len_++] = message[i];
}
}
}
if (this->multi_pdu_message_len_ == this->multi_pdu_message_expected_size_) {
void LinBusProtocol::lin_msg_diag_multi_() {
ESP_LOGD(TAG, "Multi package request %s",
format_hex_pretty(this->multi_pdu_message_, this->multi_pdu_message_len_).c_str());
@ -258,11 +265,6 @@ void LinBusProtocol::lin_message_recieved_diagnostic_multi_(const u_int8_t *mess
}
}
}
}
}
void LinBusProtocol::lin_message_recieved_diagnostic_single_(const u_int8_t *message, u_int8_t length) {
// TODO: Split up `lin_message_recieved_diagnostic_` method.
}
} // namespace truma_inetbox

View File

@ -26,17 +26,17 @@ class LinBusProtocol : public LinBusListener {
private:
u_int8_t lin_node_address_ = /*LIN initial node address*/ 0x03;
void prepare_update_msg_(const std::array<u_int8_t, 8> message);
void prepare_update_msg_(const std::array<u_int8_t, 8> message) { this->updates_to_send_.push(std::move(message)); }
bool is_matching_identifier_(const u_int8_t *message);
u_int16_t multi_pdu_message_expected_size_ = 0;
u_int8_t multi_pdu_message_len_ = 0;
u_int8_t multi_pdu_message_frame_counter_ = 0;
u_int8_t multi_pdu_message_[64];
void lin_message_recieved_diagnostic_(const u_int8_t *message, u_int8_t length);
void lin_message_recieved_diagnostic_multi_(const u_int8_t *message, u_int8_t length,
u_int8_t protocol_control_information);
void lin_message_recieved_diagnostic_single_(const u_int8_t *message, u_int8_t length);
void lin_msg_diag_single_(const u_int8_t *message, u_int8_t length);
void lin_msg_diag_first_(const u_int8_t *message, u_int8_t length);
void lin_msg_diag_consecutive_(const u_int8_t *message, u_int8_t length);
void lin_msg_diag_multi_();
};
} // namespace truma_inetbox

View File

@ -325,6 +325,11 @@ async def truma_inetbox_timer_disable_to_code(config, action_id, template_arg, a
),
)
async def truma_inetbox_timer_activate_to_code(config, action_id, template_arg, args):
# Run interrupt on core 0. ESP Home runs on core 1.
cg.add_build_flag("-DARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE=0")
# Default Stack Size is 2048. Not enough for my operation.
cg.add_build_flag("-DARDUINO_SERIAL_EVENT_TASK_STACK_SIZE=4096")
var = cg.new_Pvariable(action_id, template_arg)
await cg.register_parented(var, config[CONF_ID])