Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce IRAM consumption of HDMI CEC to 1453 bytes #19452

Merged
merged 2 commits into from
Sep 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.

### Changed
- Berry fast_loop is now called every 5ms whatever the Sleep value
- Reduce IRAM consumption of HDMI CEC to 1453 bytes

### Fixed
- PCF8574 mode 1 with base relays exception 3/28 regression from v12.4.0.4 (#19408)
Expand Down
2 changes: 1 addition & 1 deletion tasmota/my_user_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@
#endif // USE_SPI

// -- One wire sensors ----------------------------
// #define USE_HDMI_CEC // Add support for HDMI CEC bus (+7k code)
// #define USE_HDMI_CEC // Add support for HDMI CEC bus (+7k code, 1456 bytes IRAM)

// -- Serial sensors ------------------------------
//#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
Expand Down
46 changes: 21 additions & 25 deletions tasmota/tasmota_xdrv_driver/xdrv_70_0_hdmi_cec.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#endif

volatile uint32_t cec_isr_count = 0;
volatile uint32_t cec_isr_rcv_count = 0;

/*********************************************************************************************\
* Ring buffer class that allows the ISR to publish logs and messages to the main event loop
Expand Down Expand Up @@ -91,31 +90,35 @@ public:
// returns true if ok, false if full
bool IRAM_ATTR push(const volatile uint8_t *buf, uint8_t len, CEC_MSG_TYPE type, bool ack) {
// AddLog(LOG_LEVEL_INFO, ">>>: push len=%i type=%i ack=%i", len, type, ack);
if (_msg[_cur_idx].type != MSG_EMPTY) {
uint32_t cur_idx = _cur_idx; // read only once the volatile value
CEC_msg_t *msg = &_msg[cur_idx];
if (msg->type != MSG_EMPTY) {
return false;
}
memmove(_msg[_cur_idx].buf, (uint8_t*) buf, CEC_BUF_SIZE);
_msg[_cur_idx].ack = ack;
_msg[_cur_idx].len = len;
_msg[_cur_idx].type = type;
_cur_idx = (_cur_idx + 1) % CEC_RING_SIZE;
memmove(&msg->buf, (uint8_t*) buf, CEC_BUF_SIZE);
msg->ack = ack;
msg->len = len;
msg->type = type;
_cur_idx = (cur_idx + 1) % CEC_RING_SIZE;
return true;
}

// returns true if ok, false if full
bool IRAM_ATTR log(uint32_t timing_expected_low, uint32_t timing_expected_high, uint32_t timing, uint16_t code, uint8_t state, bool line) {
#ifdef HDMI_DEBUG
if (_msg[_cur_idx].type != MSG_EMPTY) {
uint32_t cur_idx = _cur_idx; // read only once the volatile value
CEC_msg_t *msg = &_msg[cur_idx];
if (msg->type != MSG_EMPTY) {
return false;
}
_msg[_cur_idx].type = MSG_LOG;
_msg[_cur_idx].timing_expected_low = timing_expected_low;
_msg[_cur_idx].timing_expected_high = timing_expected_high;
_msg[_cur_idx].timing = timing;
_msg[_cur_idx].code = code;
_msg[_cur_idx].state = state;
_msg[_cur_idx].line = line;
_cur_idx = (_cur_idx + 1) % CEC_RING_SIZE;
msg->type = MSG_LOG;
msg->timing_expected_low = timing_expected_low;
msg->timing_expected_high = timing_expected_high;
msg->timing = timing;
msg->code = code;
msg->state = state;
msg->line = line;
_cur_idx = (cur_idx + 1) % CEC_RING_SIZE;
#endif
return true;
}
Expand Down Expand Up @@ -248,7 +251,7 @@ public:
void checkMessages(); // check regularly for mailbox
// signal to Tasmota to exit the normal sleep and trigger a new tick event in the next millisecond
void enableISR(void);
void IRAM_ATTR serviceGpioISR(void); // handle the ISR on the CEC GPIO
inline void IRAM_ATTR serviceGpioISR(void) { runReceiveISR(); }; // handle the ISR on the CEC GPIO
bool transmitRaw(const unsigned char* buffer, unsigned int count);

// Getters
Expand Down Expand Up @@ -474,7 +477,7 @@ void CEC_Device::start(void) {
///
/// The state machine works in blocking mode
///
void IRAM_ATTR CEC_Device::runTransmit() {
void CEC_Device::runTransmit() {
if (!_xmit_wait_ms) {
// we haven't waited for the signal to stabilize yet
// compute the number of milliseconds to wait for in fast loop
Expand Down Expand Up @@ -716,7 +719,6 @@ void IRAM_ATTR CEC_Device::runTransmit() {
void IRAM_ATTR CEC_Device::runReceiveISR() {
if (isTransmitting()) { return; } // ignore any interrupt caused or during active transmission

cec_isr_rcv_count += 1;
// update timing information for new iteration
uint32_t now = micros();
if (!now) { now = 1; } // avoid now == 0 which has a special meaning
Expand Down Expand Up @@ -1055,12 +1057,6 @@ void CEC_Device::enableISR(void) {
}
}

// Service gpio ISR
void IRAM_ATTR CEC_Device::serviceGpioISR(void) {
cec_isr_count += 1;
runReceiveISR();
}

/*********************************************************************************************\
* General methods
\*********************************************************************************************/
Expand Down