mirror of
https://github.com/gunner47/GyverLamp.git
synced 2025-08-08 09:20:59 +03:00
240 lines
12 KiB
C++
240 lines
12 KiB
C++
#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: яркость, скорость, масштаб (по одному байту)
|
||
*
|
||
* 111-134 24 настройки режима избранных эффектов (интервал - 2 байта; разброс - 2 байта; вкл/выкл каждого эффекта - 20 (MODE_AMOUNT) байт; вкл/выкл не хранится в EEPROM)
|
||
*
|
||
* 198 1 признак первого запуска (определяет необходимость первоначальной записи всех хранимых настроек)
|
||
* 199 1 время до "рассвета" (dawnMode)
|
||
* 200 1 текущий режим (currentMode)
|
||
*
|
||
* Не используются адреса:
|
||
* 81-110 30 резерв, можно добавить ещё 10 эффектов
|
||
* 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* eepromTimer, int8_t* currentMode, ModeType modes[], void (*saveFavoritesSettings)())
|
||
{
|
||
if (*settChanged && millis() - *eepromTimer > EEPROM_WRITE_DELAY)
|
||
{
|
||
*settChanged = false;
|
||
*eepromTimer = 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:
|
||
};
|