Added proper eeprom addressing and complete TRACK commands

This commit is contained in:
Hector van der Aa
2026-03-27 14:42:39 +01:00
parent 3a396d6a42
commit 992b76cbd2
8 changed files with 248 additions and 27 deletions

View File

@@ -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 {

25
src/data/eeprom_layout.h Normal file
View File

@@ -0,0 +1,25 @@
// Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <inttypes.h>
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

View File

@@ -2,6 +2,7 @@
// Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
// 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;
}

View File

@@ -6,6 +6,7 @@
#include <string.h>
#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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -12,6 +12,7 @@
#include <EEPROM.h>
#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;

View File

@@ -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));