[ld2420] Extract command frame builders from the blocking senders

Behavior free refactor: split the frame serialization out of
send_cmd_from_array, split the frame construction out of the blocking
command functions into build helpers, name the ack timeout and retry
constants, remove the unused CmdFrameT length field and the unused
get_reg_value_ method. No functional change.
This commit is contained in:
J. Nick Koston
2026-08-16 21:12:28 -05:00
parent e9d940aca4
commit 61d2632851
2 changed files with 102 additions and 89 deletions
+96 -87
View File
@@ -64,6 +64,8 @@ static const char *const TAG = "ld2420";
// Local const's
static constexpr uint16_t REFRESH_RATE_MS = 1000;
static constexpr uint32_t CMD_ACK_TIMEOUT_MS = 1000;
static constexpr uint8_t CMD_MAX_RETRIES = 3;
// Command sets
static constexpr uint16_t CMD_DISABLE_CONF = 0x00FE;
@@ -631,37 +633,39 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
}
}
void LD2420Component::write_cmd_frame_(const CmdFrameT &frame) {
uint8_t cmd_buffer[MAX_LINE_LENGTH];
uint16_t length = 0;
const uint16_t frame_data_bytes = frame.data_length + 2; // Always add two bytes for the cmd size
memcpy(&cmd_buffer[length], &frame.header, sizeof(frame.header));
length += sizeof(frame.header);
memcpy(&cmd_buffer[length], &frame_data_bytes, sizeof(frame.data_length));
length += sizeof(frame.data_length);
memcpy(&cmd_buffer[length], &frame.command, sizeof(frame.command));
length += sizeof(frame.command);
memcpy(&cmd_buffer[length], frame.data, frame.data_length);
length += frame.data_length;
memcpy(&cmd_buffer[length], &frame.footer, sizeof(frame.footer));
length += sizeof(frame.footer);
this->write_array(cmd_buffer, length);
}
int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
uint32_t start_millis = millis();
uint8_t error = 0;
uint8_t ack_buffer[MAX_LINE_LENGTH];
uint8_t cmd_buffer[MAX_LINE_LENGTH];
this->cmd_reply_.ack = false;
if (frame.command != CMD_RESTART) {
this->cmd_active_ = true;
} // Restart does not reply, thus no ack state required
uint8_t retry = 3;
uint8_t retry = CMD_MAX_RETRIES;
while (retry) {
frame.length = 0;
uint16_t frame_data_bytes = frame.data_length + 2; // Always add two bytes for the cmd size
memcpy(&cmd_buffer[frame.length], &frame.header, sizeof(frame.header));
frame.length += sizeof(frame.header);
memcpy(&cmd_buffer[frame.length], &frame_data_bytes, sizeof(frame.data_length));
frame.length += sizeof(frame.data_length);
memcpy(&cmd_buffer[frame.length], &frame.command, sizeof(frame.command));
frame.length += sizeof(frame.command);
for (uint16_t index = 0; index < frame.data_length; index++) {
memcpy(&cmd_buffer[frame.length], &frame.data[index], sizeof(frame.data[index]));
frame.length += sizeof(frame.data[index]);
}
memcpy(cmd_buffer + frame.length, &frame.footer, sizeof(frame.footer));
frame.length += sizeof(frame.footer);
this->write_array(cmd_buffer, frame.length);
this->write_cmd_frame_(frame);
error = 0;
if (frame.command == CMD_RESTART) {
@@ -674,7 +678,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
}
delay_microseconds_safe(1450);
// Wait on an Rx from the LD2420 for up to 3 1 second loops, otherwise it could trigger a WDT.
if ((millis() - start_millis) > 1000) {
if ((millis() - start_millis) > CMD_ACK_TIMEOUT_MS) {
start_millis = millis();
error = LD2420_ERROR_TIMEOUT;
retry--;
@@ -691,16 +695,20 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
return error;
}
void LD2420Component::build_config_mode_frame_(CmdFrameT &frame, bool enable) {
frame.data_length = 0;
frame.header = CMD_FRAME_HEADER;
frame.command = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
if (enable) {
memcpy(&frame.data[0], &CMD_PROTOCOL_VER, sizeof(CMD_PROTOCOL_VER));
frame.data_length += sizeof(CMD_PROTOCOL_VER);
}
frame.footer = CMD_FRAME_FOOTER;
}
uint8_t LD2420Component::set_config_mode(bool enable) {
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
if (enable) {
memcpy(&cmd_frame.data[0], &CMD_PROTOCOL_VER, sizeof(CMD_PROTOCOL_VER));
cmd_frame.data_length += sizeof(CMD_PROTOCOL_VER);
}
cmd_frame.footer = CMD_FRAME_FOOTER;
this->build_config_mode_frame_(cmd_frame, enable);
ESP_LOGV(TAG, "Sending set config %s command: %2X", enable ? "enable" : "disable", cmd_frame.command);
return this->send_cmd_from_array(cmd_frame);
}
@@ -718,18 +726,6 @@ void LD2420Component::ld2420_restart() {
this->send_cmd_from_array(cmd_frame);
}
void LD2420Component::get_reg_value_(uint16_t reg) {
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = CMD_READ_REGISTER;
cmd_frame.data[1] = reg;
cmd_frame.data_length += 2;
cmd_frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read register %4X command: %2X", reg, cmd_frame.command);
this->send_cmd_from_array(cmd_frame);
}
void LD2420Component::set_reg_value(uint16_t reg, uint16_t value) {
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
@@ -753,19 +749,22 @@ void LD2420Component::handle_cmd_error(uint16_t error) {
}
}
void LD2420Component::build_gate_threshold_frame_(CmdFrameT &frame, uint8_t gate) {
frame.data_length = 0;
frame.header = CMD_FRAME_HEADER;
frame.command = CMD_READ_ABD_PARAM;
memcpy(&frame.data[frame.data_length], &CMD_GATE_MOVE_THRESH[gate], sizeof(CMD_GATE_MOVE_THRESH[gate]));
frame.data_length += 2;
memcpy(&frame.data[frame.data_length], &CMD_GATE_STILL_THRESH[gate], sizeof(CMD_GATE_STILL_THRESH[gate]));
frame.data_length += 2;
frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read gate %d high/low threshold command: %2X", gate, frame.command);
}
int LD2420Component::get_gate_threshold_(uint8_t gate) {
uint8_t error;
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = CMD_READ_ABD_PARAM;
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_GATE_MOVE_THRESH[gate], sizeof(CMD_GATE_MOVE_THRESH[gate]));
cmd_frame.data_length += 2;
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_GATE_STILL_THRESH[gate], sizeof(CMD_GATE_STILL_THRESH[gate]));
cmd_frame.data_length += 2;
cmd_frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read gate %d high/low threshold command: %2X", gate, cmd_frame.command);
error = this->send_cmd_from_array(cmd_frame);
this->build_gate_threshold_frame_(cmd_frame, gate);
uint8_t error = this->send_cmd_from_array(cmd_frame);
if (error == 0) {
this->current_config.move_thresh[gate] = cmd_reply_.data[0];
this->current_config.still_thresh[gate] = cmd_reply_.data[1];
@@ -773,24 +772,27 @@ int LD2420Component::get_gate_threshold_(uint8_t gate) {
return error;
}
int LD2420Component::get_min_max_distances_timeout_() {
uint8_t error;
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = CMD_READ_ABD_PARAM;
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_MIN_GATE_REG,
void LD2420Component::build_min_max_timeout_frame_(CmdFrameT &frame) {
frame.data_length = 0;
frame.header = CMD_FRAME_HEADER;
frame.command = CMD_READ_ABD_PARAM;
memcpy(&frame.data[frame.data_length], &CMD_MIN_GATE_REG,
sizeof(CMD_MIN_GATE_REG)); // Register: global min detect gate number
cmd_frame.data_length += sizeof(CMD_MIN_GATE_REG);
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_MAX_GATE_REG,
frame.data_length += sizeof(CMD_MIN_GATE_REG);
memcpy(&frame.data[frame.data_length], &CMD_MAX_GATE_REG,
sizeof(CMD_MAX_GATE_REG)); // Register: global max detect gate number
cmd_frame.data_length += sizeof(CMD_MAX_GATE_REG);
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_TIMEOUT_REG,
frame.data_length += sizeof(CMD_MAX_GATE_REG);
memcpy(&frame.data[frame.data_length], &CMD_TIMEOUT_REG,
sizeof(CMD_TIMEOUT_REG)); // Register: global delay time
cmd_frame.data_length += sizeof(CMD_TIMEOUT_REG);
cmd_frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read gate min max and timeout command: %2X", cmd_frame.command);
error = this->send_cmd_from_array(cmd_frame);
frame.data_length += sizeof(CMD_TIMEOUT_REG);
frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read gate min max and timeout command: %2X", frame.command);
}
int LD2420Component::get_min_max_distances_timeout_() {
CmdFrameT cmd_frame;
this->build_min_max_timeout_frame_(cmd_frame);
uint8_t error = this->send_cmd_from_array(cmd_frame);
if (error == 0) {
this->current_config.min_gate = (uint16_t) cmd_reply_.data[0];
this->current_config.max_gate = (uint16_t) cmd_reply_.data[1];
@@ -799,33 +801,40 @@ int LD2420Component::get_min_max_distances_timeout_() {
return error;
}
void LD2420Component::build_system_mode_frame_(CmdFrameT &frame, uint16_t mode) {
uint16_t unknown_parm = 0x0000;
frame.data_length = 0;
frame.header = CMD_FRAME_HEADER;
frame.command = CMD_WRITE_SYS_PARAM;
memcpy(&frame.data[frame.data_length], &CMD_SYSTEM_MODE, sizeof(CMD_SYSTEM_MODE));
frame.data_length += sizeof(CMD_SYSTEM_MODE);
memcpy(&frame.data[frame.data_length], &mode, sizeof(mode));
frame.data_length += sizeof(mode);
memcpy(&frame.data[frame.data_length], &unknown_parm, sizeof(unknown_parm));
frame.data_length += sizeof(unknown_parm);
frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending write system mode command: %2X", frame.command);
}
void LD2420Component::set_system_mode(uint16_t mode) {
CmdFrameT cmd_frame;
uint16_t unknown_parm = 0x0000;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = CMD_WRITE_SYS_PARAM;
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_SYSTEM_MODE, sizeof(CMD_SYSTEM_MODE));
cmd_frame.data_length += sizeof(CMD_SYSTEM_MODE);
memcpy(&cmd_frame.data[cmd_frame.data_length], &mode, sizeof(mode));
cmd_frame.data_length += sizeof(mode);
memcpy(&cmd_frame.data[cmd_frame.data_length], &unknown_parm, sizeof(unknown_parm));
cmd_frame.data_length += sizeof(unknown_parm);
cmd_frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending write system mode command: %2X", cmd_frame.command);
this->build_system_mode_frame_(cmd_frame, mode);
if (this->send_cmd_from_array(cmd_frame) == 0) {
this->set_mode_(mode);
}
}
void LD2420Component::build_version_frame_(CmdFrameT &frame) {
frame.data_length = 0;
frame.header = CMD_FRAME_HEADER;
frame.command = CMD_READ_VERSION;
frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read firmware version command: %2X", frame.command);
}
void LD2420Component::get_firmware_version_() {
CmdFrameT cmd_frame;
cmd_frame.data_length = 0;
cmd_frame.header = CMD_FRAME_HEADER;
cmd_frame.command = CMD_READ_VERSION;
cmd_frame.footer = CMD_FRAME_FOOTER;
ESP_LOGV(TAG, "Sending read firmware version command: %2X", cmd_frame.command);
this->build_version_frame_(cmd_frame);
this->send_cmd_from_array(cmd_frame);
}
+6 -2
View File
@@ -45,7 +45,6 @@ class LD2420Component final : public Component, public uart::UARTDevice {
struct CmdFrameT {
uint32_t header{0};
uint32_t footer{0};
uint16_t length{0};
uint16_t command{0};
uint16_t data_length{0};
uint8_t data[18];
@@ -155,8 +154,13 @@ class LD2420Component final : public Component, public uart::UARTDevice {
void get_firmware_version_();
int get_gate_threshold_(uint8_t gate);
void get_reg_value_(uint16_t reg);
int get_min_max_distances_timeout_();
void write_cmd_frame_(const CmdFrameT &frame);
void build_config_mode_frame_(CmdFrameT &frame, bool enable);
void build_min_max_timeout_frame_(CmdFrameT &frame);
void build_gate_threshold_frame_(CmdFrameT &frame, uint8_t gate);
void build_version_frame_(CmdFrameT &frame);
void build_system_mode_frame_(CmdFrameT &frame, uint16_t mode);
uint16_t get_mode_() { return this->system_mode_; };
void set_mode_(uint16_t mode) { this->system_mode_ = mode; };
bool get_presence_() { return this->presence_; };