arduino-photometrics/lib/storage/storage_interface.cpp
2025-11-26 16:30:22 +01:00

263 lines
8.7 KiB
C++

#include "storage_interface.h"
#include <Arduino.h>
#include <EEPROM.h>
// Manual implements of EEPROM.put() for few uint type
uint16_t inline read_eeprom_uint16(uint8_t idx){
uint8_t tmp;
tmp = EEPROM.read(idx); // read high byte
return EEPROM.read(idx + 1) | (tmp << 8); // read low byte
}
void inline write_eeprom_uint16(uint8_t idx, uint16_t value){
EEPROM.write(idx, value >> 8); // write high byte
EEPROM.write(idx + 1, value & 0xFF); // write low byte
}
uint32_t inline read_eeprom_uint32(uint8_t idx) {
uint32_t result = 0;
// Byte 1 (High level : MSB)
result |= (uint32_t)EEPROM.read(idx) << 24;
// Byte 2
result |= (uint32_t)EEPROM.read(idx + 1) << 16;
// Byte 3
result |= (uint32_t)EEPROM.read(idx + 2) << 8;
// Byte 4 (Low level : LSB)
result |= (uint32_t)EEPROM.read(idx + 3);
return result;
}
void inline write_eeprom_uint32(uint8_t idx, uint32_t value) {
// Byte 1 (High level : MSB)
EEPROM.write(idx, (uint8_t)(value >> 24));
// Byte 2
EEPROM.write(idx + 1, (uint8_t)(value >> 16));
// Byte 3
EEPROM.write(idx + 2, (uint8_t)(value >> 8));
// Byte 4 (Low level : LSB)
EEPROM.write(idx + 3, (uint8_t)(value & 0xFF));
}
Storage_interface::Storage_interface(){}
Storage_interface::~Storage_interface(){}
void Storage_interface::clear_eeprom(){
for (uint16_t i = 0 ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);
}
}
void Storage_interface::clear_eeprom_at(uint16_t idx){
for (uint16_t i = idx ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);
}
}
// legacy function (don't finished and never tested)
/*
uint16_t get_nb_package_legacy(){
uint8_t flags, nb_photo_sensor, nb_temp_sensor, temp_size_t, photo_size_t, schedule, tmp, timestamp_size_t;
uint16_t nb_package = 0, nb_measure, start_package = 0, timestamp_sum_size, next_position;
bool timestamp;
flags = EEPROM.read(start_package);
while ((flags & 0b1) != 0){
nb_package++;
nb_photo_sensor = EEPROM.read(start_package + OFFSET_NB_PHOTO_SENSOR);
photo_size_t = EEPROM.read(start_package + OFFSET_PHOTO_MEASURES_SIZE);
nb_temp_sensor = EEPROM.read(start_package + OFFSET_NB_TEMP_SENSOR);
temp_size_t = EEPROM.read(start_package + OFFSET_TEMP_MEASURES_SIZE);
tmp = EEPROM.read(start_package + OFFSET_NB_TEMP_SENSOR); // read high byte
nb_measure = EEPROM.read(start_package + OFFSET_NB_TEMP_SENSOR + 1) | (tmp << 8); // read low byte
timestamp = false;
timestamp_size_t = EEPROM.read(start_package + OFFSET_timestamp_SIZE);
if ((flags & 0b001) != 0 ){
timestamp = true;
schedule = EEPROM.read(start_package + OFFSET_MEASURES_SCH);
timestamp_sum_size = (nb_measure/schedule) * timestamp_size_t;
}else if ((flags & 0b01) != 0){
timestamp = true;
timestamp_sum_size = nb_measure * timestamp_size_t;
}else{
timestamp_sum_size = 0;
}
}
return nb_package;
}*/
/**
* @brief get_last_header_nbpackage
* *
*
* * @param last_header_idx @c uint16_t EEPROM index of the last header
* @return @c uint16_t EEPROM stored package number
*/
uint16_t Storage_interface::get_last_header_nbpackage(uint16_t* last_header_idx){
uint8_t flags;
uint16_t start_package = 0, nb_package = 0;
*last_header_idx = 0;
flags = EEPROM.read(start_package);
while ((flags & 0b1) != 0){
nb_package++;
*last_header_idx = start_package;
start_package = read_eeprom_uint16(start_package + OFFSET_NEXT_PACKAGE);
flags = EEPROM.read(start_package);
nb_package++;
}
return nb_package;
}
// factorise reused code implementation and keep level acces
uint16_t Storage_interface::get_nb_package(){
uint16_t pointer;
return get_last_header_nbpackage(&pointer);
}
void Storage_interface::get_store_struct(uint16_t offset, bool* timestamp, bool* is_final_set, bool* photo_sensor, bool* temp_sensor, uint8_t* timestamp_schedule, uint8_t* nb_photo_sensor, uint8_t* nb_temp_sensor, uint8_t* photo_size, uint8_t* temp_size, uint16_t* p_next_package, uint16_t* nb_measures){
uint8_t flags;
flags = EEPROM.read(offset);
// Checking there if a struct is possibly at the index
if ((flags & 0b1) == 0){
Serial.println("Missing struct index or bad index");
return;
}
// timestamps reads
*timestamp = false;
if ((flags & 0b001) != 0 ){
*timestamp = true;
*timestamp_schedule = EEPROM.read(offset + OFFSET_MEASURES_SCH);
}
*timestamp_schedule = 0;
if (flags & 0b01){
*timestamp = true;
if (EEPROM.read(offset + OFFSET_MEASURES_SCH) != 0)
Serial.println("Incoherent timestamp parameter in the header.");
}
// photo res reads
*photo_sensor = false;
if (flags & 0b0001){
*photo_sensor = true;
*nb_photo_sensor = EEPROM.read(offset + OFFSET_NB_PHOTO_SENSOR);
}
// temp res reads
*temp_sensor = false;
if (flags & 0b00001){
*temp_sensor = true;
*nb_temp_sensor = EEPROM.read(offset + OFFSET_NB_TEMP_SENSOR);
}
// gather the index of the next package in the EEPROM
*p_next_package = read_eeprom_uint16(offset + OFFSET_NEXT_PACKAGE);
// gather the number of measures
*nb_measures = read_eeprom_uint16(offset + OFFSET_NB_TEMP_SENSOR);
}
void Storage_interface::set_store_struct(uint16_t offset, bool timestamp, bool is_final_set, bool photo_sensor, bool temp_sensor, uint8_t timestamp_schedule, uint8_t nb_photo_sensor, uint8_t nb_temp_sensor, uint8_t photo_size, uint8_t temp_size){
uint8_t flags = 0;
// Existing package flag for function package searcher
flags = flags | 0b10000000;
// Timestamp init struct
if(timestamp_schedule != 0){
flags = flags | 0b00100000;
EEPROM.write(offset + OFFSET_MEASURES_SCH, timestamp_schedule);
if(!timestamp)
Serial.println("Bad timestamp parameter for header writer.");
}else{
EEPROM.write(offset + OFFSET_MEASURES_SCH, 0);
if (timestamp)
flags = flags | 0b01000000;
}
// Sensor part
if (photo_sensor){
flags = flags | 0b00010000;
EEPROM.write(offset + OFFSET_NB_PHOTO_SENSOR, nb_photo_sensor);
}else{
EEPROM.write(offset + OFFSET_NB_PHOTO_SENSOR, 0);
if (nb_photo_sensor != 0)
Serial.println("Bad photo sensor parameter for header writer.");
}
if (temp_sensor){
flags = flags | 0b00001000;
EEPROM.write(offset + OFFSET_NB_TEMP_SENSOR, nb_temp_sensor);
}else{
EEPROM.write(offset + OFFSET_NB_TEMP_SENSOR, 0);
if (nb_temp_sensor != 0)
Serial.println("Bad temperature sensor parameter for header writer.");
}
// TODO Analyse if is_final_set just be remove from parameter
if (is_final_set){
flags = flags | 0b00000100;
}
// uint16_t next package pointer set at 0
write_eeprom_uint16(offset + OFFSET_NEXT_PACKAGE, offset + OFFSET_START_DATA_MEASURES);
// set number of measures to 0
write_eeprom_uint16(offset + OFFSET_NB_MEASURES, 0);
// write flags header
EEPROM.write(offset , flags);
clear_eeprom_at(offset + OFFSET_START_DATA_MEASURES);
}
void Storage_interface::add_last_package(bool timestamp, bool is_final_set, bool photo_sensor, bool temp_sensor, uint8_t timestamp_schedule, uint8_t nb_photo_sensor, uint8_t nb_temp_sensor, uint8_t photo_size, uint8_t temp_size, uint16_t nb_measures){
uint16_t p_last_header, free_space;
uint8_t flags;
get_last_header_nbpackage(&p_last_header);
flags = EEPROM.read(p_last_header);
// change is_last_package flag
flags = flags & 0b11111011;
EEPROM.write(p_last_header , flags);
free_space = EEPROM.read(p_last_header + OFFSET_NEXT_PACKAGE);
set_store_struct(free_space, timestamp, is_final_set, photo_sensor, temp_sensor, timestamp_schedule, nb_photo_sensor, nb_temp_sensor, photo_size, temp_size);
}
// Dont check if the stored measure structure match with the header
void Storage_interface::add_measure(uint8_t* photo_values, uint8_t* temp_values, uint32_t timestamp, uint8_t nb_photo, uint8_t nb_temp){
uint16_t p_last_header, free_space, idx;
get_last_header_nbpackage(&p_last_header);
free_space = EEPROM.read(p_last_header + OFFSET_NEXT_PACKAGE);
EEPROM.write(p_last_header + OFFSET_NB_MEASURES, EEPROM.read(p_last_header + OFFSET_NB_MEASURES) + 1);
EEPROM.put(free_space, timestamp);
idx = p_last_header + int32_size;
for(int i = 0; i < nb_photo; i++, idx += int8_size){
EEPROM.put(idx, photo_values[i]);
}
for(int i = 0; i < nb_temp; i++, idx += int8_size){
EEPROM.put(idx, temp_values[i]);
}
}