1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 00:31:58 +00:00

dfplayer: batch UART reads to reduce per-loop overhead

This commit is contained in:
J. Nick Koston
2026-02-07 00:38:54 +01:00
parent 86f91eed2f
commit 2a17592d57

View File

@@ -1,4 +1,5 @@
#include "dfplayer.h" #include "dfplayer.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
namespace esphome { namespace esphome {
@@ -132,139 +133,151 @@ void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) {
void DFPlayer::loop() { void DFPlayer::loop() {
// Read message // Read message
while (this->available()) { int avail = this->available();
uint8_t byte; if (avail <= 0)
this->read_byte(&byte); return;
if (this->read_pos_ == DFPLAYER_READ_BUFFER_LENGTH) uint8_t buf[64];
this->read_pos_ = 0; while (avail > 0) {
size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf));
switch (this->read_pos_) { if (!this->read_array(buf, to_read)) {
case 0: // Start mark break;
if (byte != 0x7E) }
continue; avail -= to_read;
break; for (size_t bi = 0; bi < to_read; bi++) {
case 1: // Version uint8_t byte = buf[bi];
if (byte != 0xFF) {
ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte); if (this->read_pos_ == DFPLAYER_READ_BUFFER_LENGTH)
this->read_pos_ = 0; this->read_pos_ = 0;
continue;
} switch (this->read_pos_) {
break; case 0: // Start mark
case 2: // Buffer length if (byte != 0x7E)
if (byte != 0x06) { continue;
ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte); break;
this->read_pos_ = 0; case 1: // Version
continue; if (byte != 0xFF) {
} ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte);
break; this->read_pos_ = 0;
case 9: // End byte continue;
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE }
char byte_sequence[100]; break;
byte_sequence[0] = '\0'; case 2: // Buffer length
for (size_t i = 0; i < this->read_pos_ + 1; ++i) { if (byte != 0x06) {
snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ", ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte);
this->read_buffer_[i]); this->read_pos_ = 0;
} continue;
ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence); }
#endif break;
if (byte != 0xEF) { case 9: // End byte
ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte); #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
this->read_pos_ = 0; char byte_sequence[100];
continue; byte_sequence[0] = '\0';
} for (size_t i = 0; i < this->read_pos_ + 1; ++i) {
// Parse valid received command snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ",
uint8_t cmd = this->read_buffer_[3]; this->read_buffer_[i]);
uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6]; }
ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence);
ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument); #endif
if (byte != 0xEF) {
switch (cmd) { ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte);
case 0x3A: this->read_pos_ = 0;
if (argument == 1) { continue;
ESP_LOGI(TAG, "USB loaded"); }
} else if (argument == 2) { // Parse valid received command
ESP_LOGI(TAG, "TF Card loaded"); uint8_t cmd = this->read_buffer_[3];
} uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6];
break;
case 0x3B: ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument);
if (argument == 1) {
ESP_LOGI(TAG, "USB unloaded"); switch (cmd) {
} else if (argument == 2) { case 0x3A:
ESP_LOGI(TAG, "TF Card unloaded"); if (argument == 1) {
} ESP_LOGI(TAG, "USB loaded");
break; } else if (argument == 2) {
case 0x3F: ESP_LOGI(TAG, "TF Card loaded");
if (argument == 1) { }
ESP_LOGI(TAG, "USB available"); break;
} else if (argument == 2) { case 0x3B:
ESP_LOGI(TAG, "TF Card available"); if (argument == 1) {
} else if (argument == 3) { ESP_LOGI(TAG, "USB unloaded");
ESP_LOGI(TAG, "USB, TF Card available"); } else if (argument == 2) {
} ESP_LOGI(TAG, "TF Card unloaded");
break; }
case 0x40: break;
ESP_LOGV(TAG, "Nack"); case 0x3F:
this->ack_set_is_playing_ = false; if (argument == 1) {
this->ack_reset_is_playing_ = false; ESP_LOGI(TAG, "USB available");
switch (argument) { } else if (argument == 2) {
case 0x01: ESP_LOGI(TAG, "TF Card available");
ESP_LOGE(TAG, "Module is busy or uninitialized"); } else if (argument == 3) {
break; ESP_LOGI(TAG, "USB, TF Card available");
case 0x02: }
ESP_LOGE(TAG, "Module is in sleep mode"); break;
break; case 0x40:
case 0x03: ESP_LOGV(TAG, "Nack");
ESP_LOGE(TAG, "Serial receive error"); this->ack_set_is_playing_ = false;
break; this->ack_reset_is_playing_ = false;
case 0x04: switch (argument) {
ESP_LOGE(TAG, "Checksum incorrect"); case 0x01:
break; ESP_LOGE(TAG, "Module is busy or uninitialized");
case 0x05: break;
ESP_LOGE(TAG, "Specified track is out of current track scope"); case 0x02:
this->is_playing_ = false; ESP_LOGE(TAG, "Module is in sleep mode");
break; break;
case 0x06: case 0x03:
ESP_LOGE(TAG, "Specified track is not found"); ESP_LOGE(TAG, "Serial receive error");
this->is_playing_ = false; break;
break; case 0x04:
case 0x07: ESP_LOGE(TAG, "Checksum incorrect");
ESP_LOGE(TAG, "Insertion error (an inserting operation only can be done when a track is being played)"); break;
break; case 0x05:
case 0x08: ESP_LOGE(TAG, "Specified track is out of current track scope");
ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)"); this->is_playing_ = false;
break; break;
case 0x09: case 0x06:
ESP_LOGE(TAG, "Entered into sleep mode"); ESP_LOGE(TAG, "Specified track is not found");
this->is_playing_ = false; this->is_playing_ = false;
break; break;
} case 0x07:
break; ESP_LOGE(TAG,
case 0x41: "Insertion error (an inserting operation only can be done when a track is being played)");
ESP_LOGV(TAG, "Ack ok"); break;
this->is_playing_ |= this->ack_set_is_playing_; case 0x08:
this->is_playing_ &= !this->ack_reset_is_playing_; ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)");
this->ack_set_is_playing_ = false; break;
this->ack_reset_is_playing_ = false; case 0x09:
break; ESP_LOGE(TAG, "Entered into sleep mode");
case 0x3C: this->is_playing_ = false;
ESP_LOGV(TAG, "Playback finished (USB drive)"); break;
this->is_playing_ = false; }
this->on_finished_playback_callback_.call(); break;
case 0x3D: case 0x41:
ESP_LOGV(TAG, "Playback finished (SD card)"); ESP_LOGV(TAG, "Ack ok");
this->is_playing_ = false; this->is_playing_ |= this->ack_set_is_playing_;
this->on_finished_playback_callback_.call(); this->is_playing_ &= !this->ack_reset_is_playing_;
break; this->ack_set_is_playing_ = false;
default: this->ack_reset_is_playing_ = false;
ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument); break;
} case 0x3C:
this->sent_cmd_ = 0; ESP_LOGV(TAG, "Playback finished (USB drive)");
this->read_pos_ = 0; this->is_playing_ = false;
continue; this->on_finished_playback_callback_.call();
case 0x3D:
ESP_LOGV(TAG, "Playback finished (SD card)");
this->is_playing_ = false;
this->on_finished_playback_callback_.call();
break;
default:
ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument);
}
this->sent_cmd_ = 0;
this->read_pos_ = 0;
continue;
}
this->read_buffer_[this->read_pos_] = byte;
this->read_pos_++;
} }
this->read_buffer_[this->read_pos_] = byte;
this->read_pos_++;
} }
} }
void DFPlayer::dump_config() { void DFPlayer::dump_config() {