diff --git a/examples/EEPROM-Settings/EEPROM-Settings.ino b/examples/EEPROM-Settings/EEPROM-Settings.ino index 08e474d0..7ca1700a 100644 --- a/examples/EEPROM-Settings/EEPROM-Settings.ino +++ b/examples/EEPROM-Settings/EEPROM-Settings.ino @@ -50,8 +50,9 @@ void setup () { while (!Serial) { } - Serial.println (EEPROMSettings.isValid () ? "valid EEPROM settings" : "invalid EEPROM settings"); - Serial.println (EEPROMSettings.endOfSettings ()); + Serial.println (EEPROMSettings.isValid () ? F("valid EEPROM settings") : F("invalid EEPROM settings")); + Serial.println (EEPROMSettings.crc (), HEX); + Serial.println (EEPROMSettings.version ()); } void loop () { diff --git a/src/Kaleidoscope/EEPROM-Settings-Focus.cpp b/src/Kaleidoscope/EEPROM-Settings-Focus.cpp index d7193b14..1be66f6e 100644 --- a/src/Kaleidoscope/EEPROM-Settings-Focus.cpp +++ b/src/Kaleidoscope/EEPROM-Settings-Focus.cpp @@ -17,12 +17,14 @@ */ #include +#include "crc.h" namespace FocusHooks { bool settings (const char *command) { enum { ISVALID, GETVERSION, + CRC, } subCommand; if (strncmp_P (command, PSTR ("settings."), 9) != 0) @@ -32,6 +34,8 @@ namespace FocusHooks { subCommand = ISVALID; else if (strcmp_P (command + 9, PSTR ("version")) == 0) subCommand = GETVERSION; + else if (strcmp_P (command + 9, PSTR ("crc")) == 0) + subCommand = CRC; else return false; @@ -41,6 +45,10 @@ namespace FocusHooks { break; case GETVERSION: Serial.println (EEPROMSettings.version ()); + case CRC: + Serial.print (::CRC.crc, HEX); + Serial.print (F("/")); + Serial.println (EEPROMSettings.crc (), HEX); break; } diff --git a/src/Kaleidoscope/EEPROM-Settings-Focus.h b/src/Kaleidoscope/EEPROM-Settings-Focus.h index 67667e82..de5af745 100644 --- a/src/Kaleidoscope/EEPROM-Settings-Focus.h +++ b/src/Kaleidoscope/EEPROM-Settings-Focus.h @@ -30,4 +30,7 @@ namespace FocusHooks { "Return whether the EEPROM settings are valid, or not.\n\n" \ "settings.version\n" \ "----------------\n" \ - "Return the version of the EEPROM settings.") + "Return the version of the EEPROM settings.\n\n" \ + "settings.crc\n" \ + "------------\n" \ + "Return the CRC of the settings.") diff --git a/src/Kaleidoscope/EEPROM-Settings.cpp b/src/Kaleidoscope/EEPROM-Settings.cpp index bf221395..1c384596 100644 --- a/src/Kaleidoscope/EEPROM-Settings.cpp +++ b/src/Kaleidoscope/EEPROM-Settings.cpp @@ -17,41 +17,64 @@ */ #include +#include "crc.h" namespace KaleidoscopePlugins { struct EEPROMSettings::settings EEPROMSettings::settings; bool EEPROMSettings::_isValid; + bool EEPROMSettings::sealed; + uint16_t EEPROMSettings::nextStart = sizeof (EEPROMSettings::settings); EEPROMSettings::EEPROMSettings (void) { } void EEPROMSettings::begin (void) { - _isValid = true; EEPROM.get (0, settings); + } + + bool + EEPROMSettings::isValid (void) { + return _isValid; + } + + uint16_t + EEPROMSettings::crc (void) { + if (sealed) + return settings.crc; + return 0; + } + + void + EEPROMSettings::seal (void) { + sealed = true; + + CRC.finalize (); if (settings.magic[0] != 'K' || settings.magic[1] != 'S') { settings.magic[0] = 'K'; settings.magic[1] = 'S'; - settings.endOfSettings = EEPROM_SETTINGS_RESERVED - 1; + settings.version = 0; + settings.crc = CRC.crc; return update (); } - if (settings.endOfSettings != EEPROM_SETTINGS_RESERVED - 1) + if (settings.crc != CRC.crc) _isValid = false; } uint16_t - EEPROMSettings::endOfSettings (void) { - if (!isValid ()) + EEPROMSettings::requestSlice (uint16_t size) { + if (sealed) return 0; - return settings.endOfSettings; - } - bool - EEPROMSettings::isValid (void) { - return _isValid; + uint16_t start = nextStart; + nextStart += size; + + CRC.update ((const void *)&size, sizeof (size)); + + return start; } void @@ -61,6 +84,8 @@ namespace KaleidoscopePlugins { void EEPROMSettings::update (void) { + settings.crc = CRC.crc; + EEPROM.put (0, settings); _isValid = true; } diff --git a/src/Kaleidoscope/EEPROM-Settings.h b/src/Kaleidoscope/EEPROM-Settings.h index cdaf9a7a..02cc7d54 100644 --- a/src/Kaleidoscope/EEPROM-Settings.h +++ b/src/Kaleidoscope/EEPROM-Settings.h @@ -21,10 +21,6 @@ #include #include -#ifndef EEPROM_SETTINGS_RESERVED -#define EEPROM_SETTINGS_RESERVED ((E2END + 1) / 2) -#endif - namespace KaleidoscopePlugins { class EEPROMSettings : public KaleidoscopePlugin { public: @@ -32,19 +28,25 @@ namespace KaleidoscopePlugins { virtual void begin (void) final; - static uint16_t endOfSettings (void); static void update (void); static bool isValid (void); static void invalidate (void); static uint8_t version (void); static void version (uint8_t ver); + static uint16_t requestSlice (uint16_t size); + static void seal (void); + static uint16_t crc (void); + private: + static uint16_t nextStart; static bool _isValid; + static bool sealed; + static struct settings { char magic[2]; uint8_t version; - uint16_t endOfSettings; + uint16_t crc; } settings; }; }; diff --git a/src/Kaleidoscope/crc.cpp b/src/Kaleidoscope/crc.cpp new file mode 100644 index 00000000..f8403548 --- /dev/null +++ b/src/Kaleidoscope/crc.cpp @@ -0,0 +1,71 @@ +/* -*- mode: c++ -*- + * Kaleidoscope-EEPROM-Settings -- Basic EEPROM settings plugin for Kaleidoscope. + * Copyright (C) 2017 Gergely Nagy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Originally generated by pycrc v0.9, https://pycrc.org + * + * using the configuration: + * Width = 16 + * Poly = 0x8005 + * Xor_In = 0x0000 + * ReflectIn = True + * Xor_Out = 0x0000 + * ReflectOut = True + * Algorithm = bit-by-bit-fast + */ + +#include "crc.h" + +void +CRC_::reflect (uint8_t len) { + uint8_t i; + uint16_t newCRC; + + newCRC = crc & 0x01; + for (i = 1; i < len; i++) { + crc >>= 1; + newCRC = (newCRC << 1) | (crc & 0x01); + } + + crc = newCRC; +} + +void +CRC_::update (const void *data, uint8_t len) +{ + const uint8_t *d = (const uint8_t *)data; + uint8_t i; + bool bit; + uint8_t c; + + while (len--) { + c = *d++; + for (i = 0x01; i & 0xff; i <<= 1) { + bit = crc & 0x8000; + if (c & i) { + bit = !bit; + } + crc <<= 1; + if (bit) { + crc ^= 0x8005; + } + } + crc &= 0xffff; + } + crc &= 0xffff; +} + +CRC_ CRC; diff --git a/src/Kaleidoscope/crc.h b/src/Kaleidoscope/crc.h new file mode 100644 index 00000000..f3db42a9 --- /dev/null +++ b/src/Kaleidoscope/crc.h @@ -0,0 +1,45 @@ +/* -*- mode: c++ -*- + * Kaleidoscope-EEPROM-Settings -- Basic EEPROM settings plugin for Kaleidoscope. + * Copyright (C) 2017 Gergely Nagy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Originally generated by pycrc v0.9, https://pycrc.org + * + * using the configuration: + * Width = 16 + * Poly = 0x8005 + * Xor_In = 0x0000 + * ReflectIn = True + * Xor_Out = 0x0000 + * ReflectOut = True + * Algorithm = bit-by-bit-fast + */ + +#pragma once + +#include + +class CRC_ { + public: + uint16_t crc = 0; + + CRC_ (void) {}; + + void update (const void *data, uint8_t len); + void finalize (void) { reflect (16); }; + void reflect (uint8_t len); +}; + +extern CRC_ CRC;