From 992b76cbd20f4163196c92e1eeeac8c1158caf5b Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Fri, 27 Mar 2026 14:42:39 +0100 Subject: [PATCH] Added proper eeprom addressing and complete TRACK commands --- src/base/task.h | 2 + src/data/eeprom_layout.h | 25 +++++ src/data/track_store.cpp | 3 +- src/modules/cmd/cmd.cpp | 141 ++++++++++++++++++++++++--- src/modules/cmd/cmd.h | 7 +- src/modules/config/config.cpp | 90 +++++++++++++++-- src/modules/config/config.h | 3 + src/modules/logger/system_logger.cpp | 4 +- 8 files changed, 248 insertions(+), 27 deletions(-) create mode 100644 src/data/eeprom_layout.h diff --git a/src/base/task.h b/src/base/task.h index f38c1c7..42e3abd 100644 --- a/src/base/task.h +++ b/src/base/task.h @@ -22,6 +22,8 @@ enum task_type : uint8_t { TASK_DISPLAY_MSG_CONFIG_NO_TRACKS, TASK_CONFIG_TRACK_DETECT, TASK_CONFIG_WRITE_TEMP_TRACK, + TASK_CONFIG_TRACK_DELETE, + TASK_CONFIG_CFG_RESET, }; struct Task { diff --git a/src/data/eeprom_layout.h b/src/data/eeprom_layout.h new file mode 100644 index 0000000..61b780d --- /dev/null +++ b/src/data/eeprom_layout.h @@ -0,0 +1,25 @@ +// Copyright (C) 2026 Hector van der Aa +// Copyright (C) 2026 Association Exergie +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include + +namespace eeprom_layout { + +static const uint16_t total_bytes = 4096; +static const uint16_t config_addr = 0; +static const uint16_t config_reserved_bytes = 256; +static const uint16_t track_slots = 8; +static const uint16_t track_slot_bytes = 128; +static const uint16_t track_base_addr = config_addr + config_reserved_bytes; +static const uint16_t track_end_addr = track_base_addr + (track_slots * track_slot_bytes); +static const uint16_t free_after_tracks = total_bytes - track_end_addr; + +static_assert(track_end_addr <= total_bytes, "EEPROM layout exceeds physical storage"); + +inline uint16_t track_slot_addr(uint8_t idx) { + return track_base_addr + ((idx - 1) * track_slot_bytes); +} + +} // namespace eeprom_layout diff --git a/src/data/track_store.cpp b/src/data/track_store.cpp index aedf150..cf8077f 100644 --- a/src/data/track_store.cpp +++ b/src/data/track_store.cpp @@ -2,6 +2,7 @@ // Copyright (C) 2026 Association Exergie // SPDX-License-Identifier: GPL-3.0-or-later #include "data/track_store.h" +#include "data/eeprom_layout.h" volatile track_data track_data_global = {}; volatile track_data track_data_temp_global = {}; @@ -15,7 +16,7 @@ volatile track_data track_data_temp_global = {}; return 1; } track_data temp; - EEPROM.get(idx, temp); + EEPROM.get(eeprom_layout::track_slot_addr(idx), temp); if (temp.magic != CONFIG_MAGIC) { return 1; } diff --git a/src/modules/cmd/cmd.cpp b/src/modules/cmd/cmd.cpp index c5f16d2..341f03a 100644 --- a/src/modules/cmd/cmd.cpp +++ b/src/modules/cmd/cmd.cpp @@ -6,6 +6,7 @@ #include #include "data/track_store.h" +#include "data/config_store.h" #include "base/router.h" char *cmd::trim_arg(char *input) { @@ -82,9 +83,66 @@ cmd::command_id cmd::parse_command_name(const char *input) { return CMD_PUT_TRACK; } + if (strcmp(input, "TRACK_DELETE") == 0) { + return CMD_DELETE_TRACK; + } + + if (strcmp(input, "TRACK_DUMP") == 0) { + return CMD_DUMP_TRACK; + } + + if (strcmp(input, "CFG_RESET") == 0) { + return CMD_CFG_RESET; + } + return CMD_UNKNOWN; } +int cmd::parse_track_slot_id(const char *id_str, unsigned short &id_out) { + if (id_str == nullptr || id_str[0] == '\0') { + return 1; + } + + id_out = strtoul(id_str, nullptr, 10); + if (id_out < 1 || id_out > 8) { + return 1; + } + + return 0; +} + +int cmd::dump_track_slot(unsigned short id) { + vehicle_config cfg; + config_global_read(cfg); + bool occupied = cfg.track_slot_occupied[id - 1]; + + track_data track; + int res = track_global_read(id, track); + if (res != 0) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error("Track slot " + String(id) + " has no valid track data"); + } +#endif + return 1; + } + +#ifdef INFO + if (_logger != nullptr) { + _logger->info("Track dump for slot " + String(id)); + _logger->info(String("\tOccupied flag: ") + String(occupied)); + _logger->info(String("\tID: ") + String(track.id)); + _logger->info(String("\tName: ") + String(track.name)); + _logger->info(String("\tPoint A lat: ") + String(track.pt_a.lat, 6)); + _logger->info(String("\tPoint A lng: ") + String(track.pt_a.lng, 6)); + _logger->info(String("\tPoint B lat: ") + String(track.pt_b.lat, 6)); + _logger->info(String("\tPoint B lng: ") + String(track.pt_b.lng, 6)); + } +#endif + + return 0; +} + int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[]) { switch (command) { case CMD_REBOOT: @@ -110,14 +168,21 @@ int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[]) if (argc != 7) { #ifdef ERROR if (_logger != nullptr) { - _logger->error("TRACK_LOAD expects 6 arguments"); + _logger->error("TRACK_PUT expects 6 arguments"); } #endif return 1; } track_data new_track; - new_track.id = strtoul(argv[1], nullptr, 10); + if (parse_track_slot_id(argv[1], new_track.id) != 0) { + #ifdef ERROR + if (_logger != nullptr) { + _logger->error(String("ID out of range: ") + String(argv[1])); + } + #endif + return 1; + } strncpy(new_track.name, argv[2], sizeof(new_track.name) - 1); new_track.name[sizeof(new_track.name) - 1] = '\0'; @@ -132,24 +197,15 @@ int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[]) pt_b.lng = strtod(argv[6], nullptr); new_track.pt_b = pt_b; - if (new_track.id < 1 || new_track.id > 8) { - #ifdef ERROR - if (_logger != nullptr) { - _logger->error(String("ID out of range: ") + String(new_track.id)); - } - #endif - return 1; - } - #ifdef INFO if (_logger != nullptr) { _logger->info("Loading new track"); _logger->info(String("ID: ") + String(new_track.id)); _logger->info(String("Name: ") + new_track.name); _logger->info(String("Point A lat: ") + String(new_track.pt_a.lat)); - _logger->info(String("Point A lng: ") + String(new_track.pt_a.lat)); + _logger->info(String("Point A lng: ") + String(new_track.pt_a.lng)); _logger->info(String("Point B lat: ") + String(new_track.pt_b.lat)); - _logger->info(String("Point B lng: ") + String(new_track.pt_b.lat)); + _logger->info(String("Point B lng: ") + String(new_track.pt_b.lng)); } #endif @@ -158,6 +214,63 @@ int cmd::dispatch_command(command_id command, unsigned short argc, char *argv[]) return 0; + case CMD_DELETE_TRACK: { + if (argc != 2) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error("TRACK_DELETE expects 1 argument"); + } +#endif + return 1; + } + + unsigned short id; + if (parse_track_slot_id(argv[1], id) != 0) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error(String("ID out of range: ") + String(argv[1])); + } +#endif + return 1; + } + + return router::send(MOD_CFG, TASK_CONFIG_TRACK_DELETE, id); + } + + case CMD_DUMP_TRACK: { + if (argc != 2) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error("TRACK_DUMP expects 1 argument"); + } +#endif + return 1; + } + + unsigned short id; + if (parse_track_slot_id(argv[1], id) != 0) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error(String("ID out of range: ") + String(argv[1])); + } +#endif + return 1; + } + + return this->dump_track_slot(id); + } + + case CMD_CFG_RESET: + if (argc != 1) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error("CFG_RESET expects no arguments"); + } +#endif + return 1; + } + return router::send(MOD_CFG, TASK_CONFIG_CFG_RESET); + case CMD_UNKNOWN: default: #ifdef ERROR @@ -255,4 +368,4 @@ int cmd::parse_task(unsigned long timeout_ms) { } return 0; -} \ No newline at end of file +} diff --git a/src/modules/cmd/cmd.h b/src/modules/cmd/cmd.h index aa72cfb..a9f9a16 100644 --- a/src/modules/cmd/cmd.h +++ b/src/modules/cmd/cmd.h @@ -19,6 +19,9 @@ private: CMD_REBOOT, CMD_DUMPCFG, CMD_PUT_TRACK, + CMD_DELETE_TRACK, + CMD_DUMP_TRACK, + CMD_CFG_RESET, }; HardwareSerial *_data_stream; @@ -36,6 +39,8 @@ private: char *trim_arg(char *input); command_id parse_command_name(const char *input); int dispatch_command(command_id command, unsigned short argc, char *argv[]); + int parse_track_slot_id(const char *id_str, unsigned short &id_out); + int dump_track_slot(unsigned short id); public: int push(const Task &task) override; @@ -44,4 +49,4 @@ public: ~cmd(); int init(); int parse_task(unsigned long timeout_ms = 500); -}; \ No newline at end of file +}; diff --git a/src/modules/config/config.cpp b/src/modules/config/config.cpp index 0540631..fa27efe 100644 --- a/src/modules/config/config.cpp +++ b/src/modules/config/config.cpp @@ -29,7 +29,7 @@ int config::write_track(const track_data& in) { #endif return 1; } - EEPROM.put(copy.id, copy); + EEPROM.put(eeprom_layout::track_slot_addr(copy.id), copy); _config.track_slot_occupied[copy.id - 1] = true; this->write_cfg(); #ifdef INFO @@ -46,6 +46,61 @@ int config::write_track_from_temp() { return this->write_track(new_track); } +int config::delete_track(unsigned short idx) { + if (idx < 1 || idx > 8) { +#ifdef ERROR + if (_logger != nullptr) { + _logger->error("Cannot delete track with out of range id, aborting"); + } +#endif + return 1; + } + + if (_config.track_slot_occupied[idx - 1] == false) { +#ifdef WARN + if (_logger != nullptr) { + _logger->warn("Requested delete on empty track slot " + String(idx)); + } +#endif + return 0; + } + + _config.track_slot_occupied[idx - 1] = false; + + if (_is_track_loaded && _loaded_track.id == idx) { + _is_track_loaded = false; + _loaded_track = {}; + track_global_write(_loaded_track); + } + + int write_res = this->write_cfg(); + +#ifdef INFO + if (_logger != nullptr && write_res == 0) { + _logger->info("Succesfully deleted track slot " + String(idx)); + } +#endif + return write_res; +} + +int config::reset_cfg() { + vehicle_config clean_config; + _config = clean_config; + _is_track_loaded = false; + _loaded_track = {}; + _task_memory_stale = true; + _no_tracks_notice_shown = false; + track_global_write(_loaded_track); + +#ifdef INFO + if (_logger != nullptr) { + _logger->info("Resetting configuration to factory defaults"); + } +#endif + + return this->write_cfg(); +} + config::config() : _logger(nullptr), _valid_config(true) {} config::config(system_logger *logger) : _logger(logger), _valid_config(true) {} @@ -53,13 +108,13 @@ config::config(system_logger *logger) : _logger(logger), _valid_config(true) {} config::~config() {} int config::read_cfg() { - EEPROM.get(0, _config); + EEPROM.get(eeprom_layout::config_addr, _config); config_global_write(_config); return 0; } int config::write_cfg() { - EEPROM.put(0, _config); + EEPROM.put(eeprom_layout::config_addr, _config); config_global_write(_config); #ifdef INFO if (_logger != nullptr) { @@ -70,7 +125,8 @@ int config::write_cfg() { } int config::write_cfg(const vehicle_config &new_config) { - EEPROM.put(0, new_config); + _config = new_config; + EEPROM.put(eeprom_layout::config_addr, new_config); config_global_write(new_config); return 0; } @@ -153,16 +209,32 @@ int config::task_config_detect_track(unsigned long timeout_ms) { int config::handle_active_task(unsigned long timeout_ms) { switch (_active_task.type) { - case TASK_CONFIG_TRACK_DETECT: + case TASK_CONFIG_TRACK_DETECT: { if (!_is_track_loaded) { return task_config_detect_track(timeout_ms); } + this->task_complete(); return 0; - - case TASK_CONFIG_WRITE_TEMP_TRACK: + + } + + case TASK_CONFIG_WRITE_TEMP_TRACK: { int res = this->write_track_from_temp(); this->task_complete(); return res; + } + + case TASK_CONFIG_TRACK_DELETE: { + int res = this->delete_track(_active_task.data); + this->task_complete(); + return res; + } + + case TASK_CONFIG_CFG_RESET: { + int res = this->reset_cfg(); + this->task_complete(); + return res; + } default: break; @@ -217,7 +289,7 @@ int config::get_track(unsigned int idx, track_data &t) { return 1; } - EEPROM.get(idx, t); + EEPROM.get(eeprom_layout::track_slot_addr(idx), t); if (t.magic != CONFIG_MAGIC) { return 1; } @@ -235,7 +307,7 @@ int config::load_track(unsigned int idx) { } track_data temp; - EEPROM.get(idx, temp); + EEPROM.get(eeprom_layout::track_slot_addr(idx), temp); if (temp.magic != CONFIG_MAGIC) { return 1; } diff --git a/src/modules/config/config.h b/src/modules/config/config.h index 74c12af..ea1793f 100644 --- a/src/modules/config/config.h +++ b/src/modules/config/config.h @@ -12,6 +12,7 @@ #include #include "data/gps_store.h" #include "data/track_store.h" +#include "data/eeprom_layout.h" #include "base/router.h" struct task_config_track_detect_data { @@ -44,6 +45,8 @@ private: int task_complete(); int write_track(const track_data& in); int write_track_from_temp(); + int delete_track(unsigned short idx); + int reset_cfg(); public: int push(const Task &task) override; diff --git a/src/modules/logger/system_logger.cpp b/src/modules/logger/system_logger.cpp index 0eb1cf0..76831b0 100644 --- a/src/modules/logger/system_logger.cpp +++ b/src/modules/logger/system_logger.cpp @@ -54,7 +54,7 @@ int system_logger::dump_config() { for (size_t i = 0; i < 8; i++) { snprintf(buffer, sizeof(buffer), "\tTrack slot %d: %d", - i, + i + 1, temp.track_slot_occupied[i] ); this->info(String(buffer)); @@ -86,4 +86,4 @@ int system_logger::debug(String message) { int system_logger::deep_debug(String message) { return this->print_message(" [DEEP_DEBUG] ", message); } -#endif \ No newline at end of file +#endif