#ifndef STORAGE_H #define STORAGE_H #include #include "esp_err.h" // TODO: Sanity check that the EEPROM is working (sacrifice sector 0?) // ============================================================================ // FLASH LAYOUT CONSTANTS // ============================================================================ #define FLASH_SECTOR_SIZE 4096 // ============================================================================ // LOG ENTRY TYPE DEFINITIONS (Magic values 0xC0-0xCF) // ============================================================================ #define LOG_TYPE_DATA 0xC0 // Generic data log #define LOG_TYPE_EVENT 0xC1 // Event marker #define LOG_TYPE_ERROR 0xC2 // Error log #define LOG_TYPE_DEBUG 0xC3 // Debug message #define LOG_TYPE_SENSOR 0xC4 // Sensor reading #define LOG_TYPE_COMMAND 0xC5 // Command executed #define LOG_TYPE_STATUS 0xC6 // Status update #define LOG_TYPE_CUSTOM_1 0xC7 // Custom type 1 #define LOG_TYPE_CUSTOM_2 0xC8 // Custom type 2 #define LOG_TYPE_CUSTOM_3 0xC9 // Custom type 3 // 0xCA-0xCF reserved for future use // Maximum payload size per log entry (255 max due to 1-byte size field) #define LOG_MAX_PAYLOAD 200 // Helper macro to check if a byte is a valid log type #define IS_VALID_LOG_TYPE(x) ((x) >= 0xC0 && (x) <= 0xCF) // ============================================================================ // LOG ENTRY STRUCTURE // ============================================================================ // Variable-length log entry format: // [0]: Type/Magic (0xC0-0xCF) // [1]: Payload size (0-255 bytes) // [2-N]: Payload data typedef struct { uint8_t size; // Payload size in bytes (0-255) uint8_t data[]; // Flexible array member for payload } __attribute__((packed)) log_entry_header_t; #define LOG_HEADER_SIZE (sizeof(log_entry_header_t)) // 2 bytes // ============================================================================ // PARAMETER SYSTEM // ============================================================================ // PARAM_DEF(name, type, default, unit, min, max) // min == max → skip bounds validation (used for keycodes, strings, informational params) // Division-critical params have min > 0 to prevent div-by-zero // NaN/Inf floats are always reset to default regardless of bounds #define PARAM_LIST \ PARAM_DEF(BOOT_TIME, i32, 0, "us", 0, 0) /* informational, skip */ \ PARAM_DEF(NUM_MOVES, u32, 0, "", 0, 1000) \ PARAM_DEF(MOVE_START, u32, 0, "s", 0, 86400) \ PARAM_DEF(MOVE_END, u32, 0, "s", 0, 86400) \ PARAM_DEF(DRIVE_DIST, f32, 10, "ft", 0.0, 100.0) \ PARAM_DEF(JACK_DIST, f32, 5, "in", 0.0, 10.0) \ PARAM_DEF(DRIVE_KE, f32, 29.2, "n/ft", 1.0, 1e9) \ PARAM_DEF(DRIVE_KT, f32, 2880000, "us/ft", 1.0, 1e9) /* div-critical */ \ PARAM_DEF(JACK_KT, f32, 1428571, "ms/in", 1.0, 1e9) /* div-critical */ \ PARAM_DEF(KEYCODE_0, u32, 0, "", 0, 0) /* skip */ \ PARAM_DEF(KEYCODE_1, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_2, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_3, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_4, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_5, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_6, u32, 0, "", 0, 0) \ PARAM_DEF(KEYCODE_7, u32, 0, "", 0, 0) \ PARAM_DEF(ADC_ALPHA_BATTERY, f32, 0.5, "-", 0.0, 1.0) \ PARAM_DEF(ADC_ALPHA_ISENS, f32, 0.6, "-", 0.0, 1.0) \ PARAM_DEF(ADC_ALPHA_IAZ, f32, 0.005, "-", 0.0, 1.0) \ PARAM_DEF(ADC_DB_IAZ, f32, 5.0, "A", 0.0, 200.0) \ PARAM_DEF(EFUSE_INOM_1, f32, 40.0, "A", 0.0, 200.0) \ PARAM_DEF(EFUSE_INOM_2, f32, 14.0, "A", 0.0, 200.0) \ PARAM_DEF(EFUSE_INOM_3, f32, 4.0, "A", 0.0, 200.0) \ PARAM_DEF(EFUSE_HEAT_THRESH, f32, 60.0, "i/i^2-s", 0.0, 1e9) \ PARAM_DEF(EFUSE_KINST, f32, 2.0, "i/i", 0.01, 100.0) /* div-critical */ \ PARAM_DEF(EFUSE_TAUCOOL, f32, 0.2, "i", 0.0, 100.0) \ PARAM_DEF(EFUSE_TCOOL, u32, 5000000, "us", 0, 60000000) \ PARAM_DEF(LOW_PROTECTION_V, f32, 10.0, "V", 0.0, 100.0) \ PARAM_DEF(LOW_PROTECTION_S, u32, 10, "s", 0, 3600) \ PARAM_DEF(CHG_LOW_V, f32, 5.0, "V", 0.0, 100.0) \ PARAM_DEF(CHG_LOW_S, u32, 5, "s", 0, 3600) \ PARAM_DEF(CHG_BULK_S, u32, 20, "s", 0, 3600) \ PARAM_DEF(RF_PULSE_LENGTH, u32, 350000, "us", 0, 10000000) \ PARAM_DEF(V_SENS_OFFSET, f32, 0.4, "V", -10.0, 10.0) \ PARAM_DEF(NET_SSID, str, "", "", "", "") \ PARAM_DEF(NET_PASS, str, "", "", "", "") \ PARAM_DEF(WIFI_CHANNEL, u16, 6, "", 1, 14) \ PARAM_DEF(WIFI_SSID, str, "sc.local", "", "", "") \ PARAM_DEF(WIFI_PASS, str, "password", "", "", "") \ PARAM_DEF(EFUSE_INRUSH_US, u32, 250000, "us", 0, 10000000) \ PARAM_DEF(JACK_I_UP, f32, 8.0, "A", 0.0, 200.0) \ PARAM_DEF(JACK_I_DOWN, f32, 15.0, "A", 0.0, 200.0) \ PARAM_DEF(V_SENS_K, f32, 0.00766666666, "V/mV", 0.0, 1.0) \ PARAM_DEF(BUILD_VERSION, str, "undefined", "", "", "") \ PARAM_DEF(SAFETY_BREAK_US, u32, 300000, "", 0, 10000000) \ PARAM_DEF(SAFETY_MAKE_US, u32, 1000000, "", 0, 10000000) \ PARAM_DEF(JACK_IS_DOWN, f32, 8.0, "A", 0.0, 200.0) /* deprecated: may duplicate JACK_I_DOWN */ // Generate enum for parameter indices #define PARAM_DEF(name, type, default_val, unit, min, max) PARAM_##name, typedef enum { PARAM_LIST NUM_PARAMS } param_idx_t; #undef PARAM_DEF #define PARAM_STR_SIZE 16 // Parameter value union (16 bytes max to fit in storage efficiently) typedef union { uint16_t u16; int16_t i16; uint32_t u32; int32_t i32; float f32; double f64; char str[PARAM_STR_SIZE]; } param_value_t; // Parameter types typedef enum { PARAM_TYPE_u16, PARAM_TYPE_i16, PARAM_TYPE_u32, PARAM_TYPE_i32, PARAM_TYPE_f32, PARAM_TYPE_f64, PARAM_TYPE_str } param_type_e; // Stored parameter format (includes CRC) typedef struct { uint8_t data[16]; // Raw parameter data uint32_t crc; // CRC32 checksum } __attribute__((packed)) param_stored_t; #define PARAM_CRC_SALT 0x12345678 // ============================================================================ // FUNCTION DECLARATIONS // ============================================================================ // Initialization esp_err_t storage_init(void); esp_err_t storage_post(void); void storage_deinit(void); // Parameter access param_value_t get_param_value_t(param_idx_t id); esp_err_t set_param_value_t(param_idx_t id, param_value_t val); esp_err_t set_param_string(param_idx_t id, const char* str); char* get_param_string(param_idx_t id); param_type_e get_param_type(param_idx_t id); const char* get_param_name(param_idx_t id); param_value_t get_param_default(param_idx_t id); const char* get_param_unit(param_idx_t id); const char* get_param_json_string(param_idx_t id, char* buffer, size_t buf_size); // Parameter commit to flash esp_err_t commit_params(void); // Logging functions esp_err_t log_init(void); esp_err_t log_write(const uint8_t* buf, uint8_t len, uint8_t type); uint32_t log_get_head(void); uint32_t log_get_tail(void); uint32_t log_get_offset(void); uint32_t log_get_size(void); esp_err_t factory_reset(); // Test/debug functions esp_err_t write_dummy_log_1(void); esp_err_t write_dummy_log_2(void); esp_err_t write_dummy_log_3(void); esp_err_t log_read(uint8_t* len, uint8_t* buf, uint8_t* type); esp_err_t log_erase_all_sectors(void); esp_err_t log_simulate_power_cycle(void); void log_read_reset(void); esp_err_t log_write_blocking_test(const uint8_t* buf, uint8_t len, uint8_t type); #endif // STORAGE_H