From c0d2c5173006c552e8ce61400cdb02c9c9dab666 Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Wed, 15 Mar 2017 10:10:55 +0100 Subject: [PATCH] Rework how the whole thing operates Allows other plugins to request a slice of EEPROM, and returns the starting location of their area. Makes a CRC out of the slice sizes, so that it can detect when the EEPROM and the Sketch become out of sync. Handling that case is left up to the user. As a consequence, we no longer reserve a big chunk of EEPROM for the keymap, that just becomes another slice of it, which can be anywhere. This makes it a bit harder to adjust the size of it, but as far as this plugin goes, playing with the EEPROM layout will usually mean having to update its contents from scratch, anyway. Signed-off-by: Gergely Nagy --- examples/EEPROM-Settings/EEPROM-Settings.ino | 5 +- src/Kaleidoscope/EEPROM-Settings-Focus.cpp | 8 +++ src/Kaleidoscope/EEPROM-Settings-Focus.h | 5 +- src/Kaleidoscope/EEPROM-Settings.cpp | 45 ++++++++++--- src/Kaleidoscope/EEPROM-Settings.h | 14 ++-- src/Kaleidoscope/crc.cpp | 71 ++++++++++++++++++++ src/Kaleidoscope/crc.h | 45 +++++++++++++ 7 files changed, 174 insertions(+), 19 deletions(-) create mode 100644 src/Kaleidoscope/crc.cpp create mode 100644 src/Kaleidoscope/crc.h 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;