#include "config.h" #include "debugger.h" I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES); LubeConfig_t LubeConfig; persistenceData_t PersistenceData; const uint16_t eeVersion = 2; // inc boolean eeAvailable = false; const uint16_t startofLubeConfig = 16; const uint16_t startofPersistence = 16 + sizeof(LubeConfig) + (sizeof(LubeConfig) % 16); boolean checkEEPROMavailable(); void InitEEPROM() { ee.begin(); checkEEPROMavailable(); } void EEPROM_Process() { switch (globals.requestEEAction) { case EE_CFG_SAVE: StoreConfig_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Stored EEPROM CFG\n"); break; case EE_CFG_LOAD: GetConfig_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Loaded EEPROM CFG\n"); break; case EE_CFG_FORMAT: FormatConfig_EEPROM(); globals.requestEEAction = EE_IDLE; GetConfig_EEPROM(); Debug_pushMessage("Formated EEPROM CFG\n"); break; case EE_PDS_SAVE: StorePersistence_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Stored EEPROM PDS\n"); break; case EE_PDS_LOAD: GetPersistence_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Loaded EEPROM PDS\n"); break; case EE_PDS_FORMAT: FormatPersistence_EEPROM(); globals.requestEEAction = EE_IDLE; GetPersistence_EEPROM(); Debug_pushMessage("Formated EEPROM PDS\n"); break; case EE_FORMAT_ALL: FormatConfig_EEPROM(); FormatPersistence_EEPROM(); GetConfig_EEPROM(); GetPersistence_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Formated EEPROM ALL\n"); break; case EE_ALL_SAVE: StorePersistence_EEPROM(); StoreConfig_EEPROM(); globals.requestEEAction = EE_IDLE; Debug_pushMessage("Stored EEPROM ALL\n"); break; case EE_IDLE: default: globals.requestEEAction = EE_IDLE; } } void StoreConfig_EEPROM() { LubeConfig.checksum = 0; LubeConfig.checksum = Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)); if (!checkEEPROMavailable()) return; ee.updateBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig)); uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); if (ConfigSanityCheckResult > 0) { MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); } } void GetConfig_EEPROM() { if (!checkEEPROMavailable()) return; ee.readBlock(startofLubeConfig, (uint8_t *)&LubeConfig, sizeof(LubeConfig)); uint32_t checksum = LubeConfig.checksum; LubeConfig.checksum = 0; if (Checksum_EEPROM((uint8_t *)&LubeConfig, sizeof(LubeConfig)) != checksum) { MaintainDTC(DTC_EEPROM_CFG_BAD, true); } LubeConfig.checksum = checksum; uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false); if (ConfigSanityCheckResult > 0) { MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult); } } void StorePersistence_EEPROM() { if (PersistenceData.writeCycleCounter >= 0xFFF0) MovePersistencePage_EEPROM(false); else PersistenceData.writeCycleCounter++; PersistenceData.checksum = 0; PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)); if (!checkEEPROMavailable()) return; ee.updateBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); } void GetPersistence_EEPROM() { if (!checkEEPROMavailable()) return; ee.readBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress)); // if we got the StartAdress of Persistance and it's out of Range - we Reset it and store defaults // otherwise we Read from eeprom and check if everything is correct if (globals.eePersistanceAdress < startofPersistence || globals.eePersistanceAdress > ee.getDeviceSize()) { MovePersistencePage_EEPROM(true); FormatPersistence_EEPROM(); MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true); } else { ee.readBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData)); uint32_t checksum = PersistenceData.checksum; PersistenceData.checksum = 0; if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum) { MaintainDTC(DTC_EEPROM_PDS_BAD, true); } PersistenceData.checksum = checksum; } } void FormatConfig_EEPROM() { Debug_pushMessage("Formatting Config-Partition\n"); LubeConfig = LubeConfig_defaults; LubeConfig.EEPROM_Version = eeVersion; StoreConfig_EEPROM(); } void FormatPersistence_EEPROM() { Debug_pushMessage("Formatting Persistance-Partition\n"); PersistenceData = {0}; // memset(&PersistenceData, 0, sizeof(PersistenceData)); StorePersistence_EEPROM(); } void MovePersistencePage_EEPROM(boolean reset) { if (!checkEEPROMavailable()) return; globals.eePersistanceAdress += sizeof(PersistenceData); PersistenceData.writeCycleCounter = 0; // check if we reached the End of the EEPROM and Startover at the beginning if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset) { globals.eePersistanceAdress = startofPersistence; } ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress)); } uint32_t Checksum_EEPROM(uint8_t const *data, size_t len) { if (data == NULL) return 0; uint32_t crc, mask; crc = 0xFFFFFFFF; while (len--) { crc ^= *data++; for (uint8_t k = 0; k < 8; k++) { mask = -(crc & 1); crc = (crc >> 1) ^ (0xEDB88320 & mask); } } return ~crc; } void dumpEEPROM(uint16_t memoryAddress, uint16_t length) { #define BLOCK_TO_LENGTH 16 if (!checkEEPROMavailable()) return; char ascii_buf[BLOCK_TO_LENGTH + 1]; sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII"); Debug_pushMessage(PSTR("\nAddress ")); for (int x = 0; x < BLOCK_TO_LENGTH; x++) Debug_pushMessage("%3d", x); memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; for (unsigned int i = 0; i < length; i++) { int blockpoint = memoryAddress % BLOCK_TO_LENGTH; if (blockpoint == 0) { ascii_buf[BLOCK_TO_LENGTH] = 0; Debug_pushMessage(" %s", ascii_buf); Debug_pushMessage("\n0x%05X:", memoryAddress); } ascii_buf[blockpoint] = ee.readByte(memoryAddress); Debug_pushMessage(" %02X", ascii_buf[blockpoint]); if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E) ascii_buf[blockpoint] = '.'; memoryAddress++; } Debug_pushMessage("\n"); } boolean checkEEPROMavailable() { if (!ee.isConnected()) { MaintainDTC(DTC_NO_EEPROM_FOUND, true); return false; } MaintainDTC(DTC_NO_EEPROM_FOUND, false); return true; } uint32_t ConfigSanityCheck(bool autocorrect) { uint32_t setting_reset_bits = 0; if (!(LubeConfig.DistancePerLube_Default > 0) || !(LubeConfig.DistancePerLube_Default < 50000)) { SET_BIT(setting_reset_bits, 0); if (autocorrect) LubeConfig.DistancePerLube_Default = LubeConfig_defaults.DistancePerLube_Default; } if (!(LubeConfig.DistancePerLube_Rain > 0) || !(LubeConfig.DistancePerLube_Rain < 50000)) { SET_BIT(setting_reset_bits, 1); if (autocorrect) LubeConfig.DistancePerLube_Rain = LubeConfig_defaults.DistancePerLube_Rain; } if (!(LubeConfig.tankCapacity_ml > 0) || !(LubeConfig.tankCapacity_ml < 5000)) { SET_BIT(setting_reset_bits, 2); if (autocorrect) LubeConfig.tankCapacity_ml = LubeConfig_defaults.tankCapacity_ml; } if (!(LubeConfig.amountPerDose_microL > 0) || !(LubeConfig.amountPerDose_microL < 100)) { SET_BIT(setting_reset_bits, 3); if (autocorrect) LubeConfig.amountPerDose_microL = LubeConfig_defaults.amountPerDose_microL; } if (!(LubeConfig.TankRemindAtPercentage >= 0) || !(LubeConfig.TankRemindAtPercentage <= 100)) { SET_BIT(setting_reset_bits, 4); if (autocorrect) LubeConfig.TankRemindAtPercentage = LubeConfig_defaults.TankRemindAtPercentage; } if (LubeConfig.SpeedSource == SOURCE_IMPULSE) { if (!(LubeConfig.PulsePerRevolution > 0) || !(LubeConfig.PulsePerRevolution < 1000)) { SET_BIT(setting_reset_bits, 5); if (autocorrect) LubeConfig.PulsePerRevolution = LubeConfig_defaults.PulsePerRevolution; } if (!(LubeConfig.TireWidth_mm > 0) || !(LubeConfig.TireWidth_mm < 500)) { SET_BIT(setting_reset_bits, 6); if (autocorrect) LubeConfig.TireWidth_mm = LubeConfig_defaults.TireWidth_mm; } if (!(LubeConfig.TireWidthHeight_Ratio > 0) || !(LubeConfig.TireWidthHeight_Ratio < 150)) { SET_BIT(setting_reset_bits, 7); if (autocorrect) LubeConfig.TireWidthHeight_Ratio = LubeConfig_defaults.TireWidthHeight_Ratio; } if (!(LubeConfig.RimDiameter_Inch > 0) || !(LubeConfig.RimDiameter_Inch < 30)) { SET_BIT(setting_reset_bits, 8); if (autocorrect) LubeConfig.RimDiameter_Inch = LubeConfig_defaults.RimDiameter_Inch; } if (!(LubeConfig.DistancePerRevolution_mm > 0) || !(LubeConfig.DistancePerRevolution_mm < 10000)) { SET_BIT(setting_reset_bits, 9); if (autocorrect) LubeConfig.DistancePerRevolution_mm = LubeConfig_defaults.DistancePerRevolution_mm; } } if (!(LubeConfig.BleedingPulses > 0) || !(LubeConfig.BleedingPulses < 1001)) { SET_BIT(setting_reset_bits, 10); if (autocorrect) LubeConfig.BleedingPulses = LubeConfig_defaults.BleedingPulses; } if (!(LubeConfig.SpeedSource >= 0) || !(LubeConfig.SpeedSource < SpeedSourceString_Elements)) { SET_BIT(setting_reset_bits, 11); if (autocorrect) LubeConfig.SpeedSource = LubeConfig_defaults.SpeedSource; } if (!(LubeConfig.GPSBaudRate >= 0) || !(LubeConfig.GPSBaudRate < GPSBaudRateString_Elements)) { SET_BIT(setting_reset_bits, 12); if (autocorrect) LubeConfig.GPSBaudRate = LubeConfig_defaults.GPSBaudRate; } if (!(LubeConfig.CANSource >= 0) || !(LubeConfig.CANSource < CANSourceString_Elements)) { SET_BIT(setting_reset_bits, 13); if (autocorrect) LubeConfig.CANSource = LubeConfig_defaults.CANSource; } return setting_reset_bits; }