Files
gunner47-GyverLamp/firmware/GyverLamp_v1.4/EepromManager.h

244 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
/*
* Схема использования EEPROM памяти:
* Используются адреса:
* Начало Длина Описание
* массив alarm
* 0 1 будильник пн вкл/выкл
* 1-2 2 будильник пн время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 3 1 будильник вт вкл/выкл
* 4-5 2 будильник вт время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 6 1 будильник ср вкл/выкл
* 7-8 2 будильник ср время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 9 1 будильник чт вкл/выкл
* 10-11 2 будильник чт время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 12 1 будильник пт вкл/выкл
* 13-14 2 будильник пт время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 15 1 будильник сб вкл/выкл
* 16-17 2 будильник сб время в минутах от начала суток (0 - 1440), должно быть 2 байта
* 18 1 будильник вс вкл/выкл
* 19-20 2 будильник вс время в минутах от начала суток (0 - 1440), должно быть 2 байта
* массив modes
* 21-23 3 режим №1: яркость, скорость, масштаб (по одному байту)
* 24-26 3 режим №2: яркость, скорость, масштаб (по одному байту)
* 27-29 3 режим №3: яркость, скорость, масштаб (по одному байту)
* 30-32 3 режим №4: яркость, скорость, масштаб (по одному байту)
* 33-35 3 режим №5: яркость, скорость, масштаб (по одному байту)
* 36-38 3 режим №6: яркость, скорость, масштаб (по одному байту)
* 39-41 3 режим №7: яркость, скорость, масштаб (по одному байту)
* 42-44 3 режим №8: яркость, скорость, масштаб (по одному байту)
* 45-47 3 режим №9: яркость, скорость, масштаб (по одному байту)
* 48-50 3 режим №10: яркость, скорость, масштаб (по одному байту)
* 51-53 3 режим №11: яркость, скорость, масштаб (по одному байту)
* 54-56 3 режим №12: яркость, скорость, масштаб (по одному байту)
* 57-59 3 режим №13: яркость, скорость, масштаб (по одному байту)
* 60-62 3 режим №14: яркость, скорость, масштаб (по одному байту)
* 63-65 3 режим №15: яркость, скорость, масштаб (по одному байту)
* 66-68 3 режим №16: яркость, скорость, масштаб (по одному байту)
* 69-71 3 режим №17: яркость, скорость, масштаб (по одному байту)
* 72-74 3 режим №18: яркость, скорость, масштаб (по одному байту)
* 75-77 3 режим №19: яркость, скорость, масштаб (по одному байту)
* 78-80 3 режим №20: яркость, скорость, масштаб (по одному байту)
* 81-83 3 режим №21: яркость, скорость, масштаб (по одному байту)
* 84-86 3 режим №22: яркость, скорость, масштаб (по одному байту)
* 87-89 3 режим №23: яркость, скорость, масштаб (по одному байту)
* 90-92 3 режим №24: яркость, скорость, масштаб (по одному байту)
* 93-95 3 режим №25: яркость, скорость, масштаб (по одному байту)
*
* 111-134 24 настройки режима избранных эффектов (интервал - 2 байта; разброс - 2 байта; вкл/выкл каждого эффекта - 20 (MODE_AMOUNT) байт; вкл/выкл не хранится в EEPROM)
*
* 198 1 признак первого запуска (определяет необходимость первоначальной записи всех хранимых настроек)
* 199 1 время до "рассвета" (dawnMode)
* 200 1 текущий режим (currentMode)
*
* Не используются адреса:
* 96-110 15 резерв, можно добавить ещё 5 эффектов
* 135-197 63 если добавить ещё 10 эффектов, начальный адрес неиспользуемой памяти сдвинется с 135 на 145
*/
#include <EEPROM.h>
#include "Types.h"
#define EEPROM_TOTAL_BYTES_USED (201U) // общий размер используемой EEPROM памяти (сумма всех хранимых настроек + 1 байт)
#define EEPROM_ALARM_START_ADDRESS (0U) // начальный адрес в EEPROM памяти для записи настроек будильников
#define EEPROM_MODES_START_ADDRESS (21U) // начальный адрес в EEPROM памяти для записи настроек эффектов (яркость, скорость, масштаб)
#define EEPROM_FAVORITES_START_ADDRESS (111U) // начальный адрес в EEPROM памяти для записи настроек режима избранных эффектов
#define EEPROM_FIRST_RUN_ADDRESS (198U) // адрес в EEPROM памяти для записи признака первого запуска (определяет необходимость первоначальной записи всех хранимых настроек)
#define EEPROM_DAWN_MODE_ADDRESS (199U) // адрес в EEPROM памяти для записи времени до "рассвета"
#define EEPROM_CURRENT_MODE_ADDRESS (200U) // адрес в EEPROM памяти для записи номера текущего эффекта лампы
#define EEPROM_ALARM_STRUCT_SIZE (3U) // 1 байт - вкл/выкл; 2 байта - время от начала суток в минутах (0 - 1440)
#define EEPROM_MODE_STRUCT_SIZE (3U) // 1 байт - яркость; 1 байт - скорость; 1 байт - масштаб
#define EEPROM_FIRST_RUN_MARK (22U) // счисло-метка, если ещё не записно в EEPROM_FIRST_RUN_ADDRESS, значит нужно проинициализировать EEPROM и записать все первоначальные настройки
#define EEPROM_WRITE_DELAY (30000UL) // отсрочка записи в EEPROM после последнего изменения хранимых настроек, позволяет уменьшить количество операций записи в EEPROM
class EepromManager
{
public:
static void InitEepromSettings(ModeType modes[], AlarmType alarms[], uint8_t* dawnMode, int8_t* currentMode,
void (*readFavoritesSettings)(), void (*saveFavoritesSettings)())
{
// записываем в EEPROM начальное состояние настроек, если их там ещё нет
EEPROM.begin(EEPROM_TOTAL_BYTES_USED);
delay(50);
if (EEPROM.read(EEPROM_FIRST_RUN_ADDRESS) != EEPROM_FIRST_RUN_MARK)
{
EEPROM.write(EEPROM_FIRST_RUN_ADDRESS, EEPROM_FIRST_RUN_MARK);
EEPROM.commit();
for (uint8_t i = 0; i < MODE_AMOUNT; i++)
{
EEPROM.put(EEPROM_MODES_START_ADDRESS + EEPROM_ALARM_STRUCT_SIZE * i, modes[i]);
EEPROM.commit();
}
for (uint8_t i = 0; i < 7; i++)
{
EEPROM.write(EEPROM_ALARM_START_ADDRESS + EEPROM_ALARM_STRUCT_SIZE * i, alarms[i].State);
WriteUint16(EEPROM_ALARM_START_ADDRESS + EEPROM_ALARM_STRUCT_SIZE * i + 1, alarms[i].Time);
EEPROM.commit();
}
EEPROM.write(EEPROM_DAWN_MODE_ADDRESS, 0);
EEPROM.write(EEPROM_CURRENT_MODE_ADDRESS, 0);
saveFavoritesSettings();
EEPROM.commit();
}
// инициализируем настройки лампы значениями из EEPROM
for (uint8_t i = 0; i < MODE_AMOUNT; i++)
{
EEPROM.get(EEPROM_MODES_START_ADDRESS + EEPROM_MODE_STRUCT_SIZE * i, modes[i]);
}
for (uint8_t i = 0; i < 7; i++)
{
alarms[i].State = EEPROM.read(EEPROM_ALARM_START_ADDRESS + EEPROM_ALARM_STRUCT_SIZE * i);
alarms[i].Time = ReadInt16(EEPROM_ALARM_START_ADDRESS + EEPROM_ALARM_STRUCT_SIZE * i + 1);
}
readFavoritesSettings();
*dawnMode = EEPROM.read(EEPROM_DAWN_MODE_ADDRESS);
*currentMode = EEPROM.read(EEPROM_CURRENT_MODE_ADDRESS);
}
static void SaveModesSettings(int8_t* currentMode, ModeType modes[])
{
EEPROM.put(3 * (*currentMode) + EEPROM_MODES_START_ADDRESS, modes[*currentMode]);
EEPROM.commit();
}
static void HandleEepromTick(bool* settChanged, uint32_t* eepromTimeout, int8_t* currentMode, ModeType modes[], void (*saveFavoritesSettings)())
{
if (*settChanged && millis() - *eepromTimeout > EEPROM_WRITE_DELAY)
{
*settChanged = false;
*eepromTimeout = millis();
SaveModesSettings(currentMode, modes);
if (EEPROM.read(EEPROM_CURRENT_MODE_ADDRESS) != *currentMode)
{
EEPROM.write(EEPROM_CURRENT_MODE_ADDRESS, *currentMode);
}
saveFavoritesSettings();
EEPROM.commit();
}
}
static void SaveAlarmsSettings(uint8_t* alarmNumber, AlarmType alarms[])
{
EEPROM.write(5 * (*alarmNumber), alarms[*alarmNumber].State);
WriteUint16((uint16_t)(5 * (*alarmNumber) + 1), alarms[*alarmNumber].Time);
EEPROM.commit();
}
static void SaveDawnMode(uint8_t* dawnMode)
{
EEPROM.write(EEPROM_DAWN_MODE_ADDRESS, *dawnMode);
EEPROM.commit();
}
static uint16_t ReadUint16(uint16_t address)
{
uint16_t val;
uint8_t* p = (uint8_t*)&val;
*p = EEPROM.read(address);
*(p + 1) = EEPROM.read(address + 1);
return val;
}
static void WriteUint16(uint16_t address, uint16_t val)
{
uint8_t* p = (uint8_t*)&val;
EEPROM.write(address, *p);
EEPROM.write(address + 1, *(p + 1));
EEPROM.commit();
}
static int16_t ReadInt16(uint16_t address)
{
int16_t val;
uint8_t* p = (uint8_t*)&val;
*p = EEPROM.read(address);
*(p + 1) = EEPROM.read(address + 1);
return val;
}
static void WriteInt16(uint16_t address, int16_t val)
{
uint8_t* p = (uint8_t*)&val;
EEPROM.write(address, *p);
EEPROM.write(address + 1, *(p + 1));
EEPROM.commit();
}
static uint32_t ReadUint32(uint16_t address)
{
uint32_t val;
uint8_t* p = (uint8_t*)&val;
*p = EEPROM.read(address);
*(p + 1) = EEPROM.read(address + 1);
*(p + 2) = EEPROM.read(address + 2);
*(p + 3) = EEPROM.read(address + 3);
return val;
}
static void WriteUint32(uint16_t address, uint32_t val)
{
uint8_t* p = (uint8_t*)&val;
EEPROM.write(address, *p);
EEPROM.write(address + 1, *(p + 1));
EEPROM.write(address + 2, *(p + 2));
EEPROM.write(address + 3, *(p + 3));
EEPROM.commit();
}
static int32_t ReadInt32(uint16_t address)
{
int32_t val;
uint8_t* p = (uint8_t*)&val;
*p = EEPROM.read(address);
*(p + 1) = EEPROM.read(address + 1);
*(p + 2) = EEPROM.read(address + 2);
*(p + 3) = EEPROM.read(address + 3);
return val;
}
static void WriteInt32(uint16_t address, int32_t val)
{
uint8_t* p = (uint8_t*)&val;
EEPROM.write(address, *p);
EEPROM.write(address + 1, *(p + 1));
EEPROM.write(address + 2, *(p + 2));
EEPROM.write(address + 3, *(p + 3));
EEPROM.commit();
}
private:
};