Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Validate pattern/palette index with hash #234

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions esp8266-fastled-webserver/MurmurHash3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "common.h"

// based on public domain implementation
// at https://github.com/aappleby/smhasher/

inline namespace {
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
inline uint32_t getblock32 ( const uint32_t * p, int i ) {
return p[i];
}
inline uint32_t rotl32(uint32_t x, int8_t r) {
return (x << r) | (x >> (32 - r));
}
inline uint32_t ROTL32(uint32_t x, int8_t r) {
return rotl32(x,r);
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
inline uint32_t fmix32(uint32_t h) {
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return h;
}
//-----------------------------------------------------------------------------
uint32_t MurmurHash3_32(const void * key, int len, uint32_t seed) {
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 4;

uint32_t h1 = seed;

const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;

//----------
// body

const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);

for(int i = -nblocks; i; i++) {
uint32_t k1 = getblock32(blocks,i);

k1 *= c1;
k1 = ROTL32(k1,15);
k1 *= c2;

h1 ^= k1;
h1 = ROTL32(h1,13);
h1 = h1*5+0xe6546b64;
}

//----------
// tail

const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
uint32_t k1 = 0;
switch(len & 3) {
case 3:
k1 ^= tail[2] << 16;
// FALLTHRU
case 2:
k1 ^= tail[1] << 8;
// FALLTHRU
case 1:
k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
// FALLTHRU
case 0:
break;
};

//----------
// finalization

h1 ^= len;
h1 = fmix32(h1);
return h1;
}
}

uint32_t MurmurHash3_32(const String & s) {
return MurmurHash3_32(s.begin(), s.length(), 0);
}

3 changes: 3 additions & 0 deletions esp8266-fastled-webserver/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ void pridePlaygroundFibonacci();
void colorWavesPlaygroundFibonacci();
#endif

// MurmurHash3
uint32_t MurmurHash3_32(const String & s);



#endif // ESP8266_FASTLED_WEBSERVER_COMMON_H
4 changes: 2 additions & 2 deletions esp8266-fastled-webserver/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@
#if !defined(FRAMES_PER_SECOND)
#error "FRAMES_PER_SECOND must be defined by product"
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#error "DEFAULT_PATTERN_INDEX must be defined by product"
#if !defined(DEFAULT_PATTERN_FUNCTION)
#error "DEFAULT_PATTERN_FUNCTION must be defined by product"
#endif
#if !defined(DEFAULT_COLOR_CORRECTION)
#error "DEFAULT_COLOR_CORRECTION must be defined by product"
Expand Down
174 changes: 132 additions & 42 deletions esp8266-fastled-webserver/esp8266-fastled-webserver.ino
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,33 @@ uint8_t speed = 30;

///////////////////////////////////////////////////////////////////////

// function prototypes for the locally-defined effects functions
void pride();
void colorWaves();
void wheel();
void rainbow();
void rainbowWithGlitter();
void rainbowSolid();
void confetti();
void sinelon();
void bpm();
void juggle();
void fire();
void water();
void strandTest();
void showSolidColor();

uint8_t gCurrentPaletteNumber = 0;

CRGBPalette16 gCurrentPalette( CRGB::Black);
CRGBPalette16 gTargetPalette( gGradientPalettes[0] );

CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);

uint8_t currentPatternIndex = DEFAULT_PATTERN_INDEX; // Index number of which pattern is current
uint8_t autoplay = 0;

uint8_t autoplayDuration = 10;
unsigned long autoPlayTimeout = 0;

uint8_t showClock = 0;
uint8_t clockBackgroundFade = 160;
uint8_t utcOffsetIndex = 24; // map(-6, -12, 14, 0, 104); -12 to 14 in 15 minute increments, mapped to 0 to 104

uint8_t currentPaletteIndex = 0;

uint8_t gHue = 0; // rotating "base color" used by many of the patterns

CRGB solidColor = CRGB::Blue;

// scale the brightness of all pixels down
void dimAll(byte value)
{
for (auto led : leds) {
led.nscale8(value);
}
}

// List of patterns to cycle through. Each is defined as a separate function below.

// NOTE: IS_FIBONACCI implies HAS_COORDINATE_MAP
#if IS_FIBONACCI
void colorWavesFibonacci();
void prideFibonacci();
void swirlFibonacci();
void fireFibonacci();
void waterFibonacci();
void emitterFibonacci();
#endif
#if (PARALLEL_OUTPUT_CHANNELS > 1)
void multi_test();
#endif

const PatternAndName patterns[] = {
{ pride, "Pride" },
Expand Down Expand Up @@ -234,6 +226,14 @@ const PatternAndName patterns[] = {

const uint8_t patternCount = ARRAY_SIZE2(patterns);

constexpr uint8_t patternIndexForFunction(Pattern toFind, uint8_t index = 0) {
return
(index >= patternCount ) ? patternCount :
(patterns[index].pattern == toFind) ? index :
patternIndexForFunction(toFind, index+1);
}


const CRGBPalette16 palettes[] = {
RainbowColors_p,
RainbowStripeColors_p,
Expand All @@ -258,6 +258,48 @@ const String paletteNames[paletteCount] = {
"Heat",
};


uint8_t gCurrentPaletteNumber = 0;

CRGBPalette16 gCurrentPalette( CRGB::Black);
CRGBPalette16 gTargetPalette( gGradientPalettes[0] );

CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);

const uint8_t productDefaultPatternIndex =
(patternIndexForFunction(DEFAULT_PATTERN_FUNCTION) <= patternCount) ?
patternIndexForFunction(DEFAULT_PATTERN_FUNCTION) : 0; // Index number of which pattern is current

uint8_t currentPatternIndex = productDefaultPatternIndex;
uint8_t autoplay = 0;

uint8_t autoplayDuration = 10;
unsigned long autoPlayTimeout = 0;

uint8_t showClock = 0;
uint8_t clockBackgroundFade = 160;
uint8_t utcOffsetIndex = 24; // map(-6, -12, 14, 0, 104); -12 to 14 in 15 minute increments, mapped to 0 to 104

uint8_t currentPaletteIndex = 0;

uint8_t gHue = 0; // rotating "base color" used by many of the patterns

CRGB solidColor = CRGB::Blue;

// scale the brightness of all pixels down
void dimAll(byte value)
{
for (auto led : leds) {
led.nscale8(value);
}
}

// List of patterns to cycle through. Each is defined as a separate function below.

// NOTE: HAS_POLAR_COORDS implies HAS_COORDINATE_MAP
// IS_FIBONACCI implies HAS_COORDINATE_MAP


// TODO / BUGBUG -- should this be ESP8266-specific? Is this only for when IR enabled ???
// FIB128 did not have this...
#if defined(PRODUCT_FIBONACCI256)
Expand Down Expand Up @@ -757,21 +799,42 @@ void loop() {

// TODO: Save settings in file system, not EEPROM!

const uint8_t SETTINGS_MAGIC_BYTE = 0x96;

const uint8_t SETTINGS_MAGIC_BYTE = 0x77;
void readSettings()
{
//T &get<T>(int const address, T &t);
//const T &put<T>(int const address, const T &t);

// check for "magic number" so we know settings have been written to EEPROM
// and it's not just full of random bytes

if (EEPROM.read(511) != SETTINGS_MAGIC_BYTE) {
return;
}

brightness = EEPROM.read(0);

currentPatternIndex = EEPROM.read(1);
if (currentPatternIndex >= patternCount) {
currentPatternIndex = patternCount - 1;
if (1) { // get pattern index and verify name's hash matches
uint8_t tmp = EEPROM.read(1);
if (tmp >= patternCount) {
tmp = patternCount - 1;
}

uint32_t expectedHash = 0;
expectedHash = EEPROM.get(20, expectedHash);

uint32_t actualHash = MurmurHash3_32(patterns[tmp].name);
if (expectedHash != actualHash) {
tmp = productDefaultPatternIndex; // use default if no hash match found
for (int i = 0; i < patternCount; i++) {
actualHash = MurmurHash3_32(patterns[i].name);
if (expectedHash == actualHash) {
tmp = i;
break; // out of for loop ... found the index to use
}
}
}
currentPatternIndex = tmp;
}

byte r = EEPROM.read(2);
Expand All @@ -791,9 +854,27 @@ void readSettings()
autoplay = EEPROM.read(6);
autoplayDuration = EEPROM.read(7);

currentPaletteIndex = EEPROM.read(8);
if (currentPaletteIndex >= paletteCount) {
currentPaletteIndex = paletteCount - 1;
if (1) { // get palette index and verify the name's hash matches
uint8_t tmp = EEPROM.read(8);
if (tmp >= paletteCount) {
tmp = paletteCount - 1;
}

uint32_t expectedHash = 0;
expectedHash = EEPROM.get(24, expectedHash);

uint32_t actualHash = MurmurHash3_32(paletteNames[tmp]);
if (expectedHash != actualHash) {
tmp = 0; // use first palette if no hash match found
for (int i = 0; i < paletteCount; i++) {
actualHash = MurmurHash3_32(paletteNames[i]);
if (expectedHash == actualHash) {
tmp = i;
break; // out of for loop ... found the index to use
}
}
}
currentPaletteIndex = tmp;
}

twinkleSpeed = EEPROM.read(9);
Expand Down Expand Up @@ -828,6 +909,15 @@ void writeAndCommitSettings() {
EEPROM.write(14, showClock);
EEPROM.write(15, clockBackgroundFade);
EEPROM.write(16, utcOffsetIndex);
EEPROM.write(17, 0xFF); // reserved for future use
EEPROM.write(18, 0xFF); // reserved for future use
EEPROM.write(19, 0xFF); // reserved for future use

uint32_t currentPatternNameHash = MurmurHash3_32(patterns[currentPatternIndex].name);
uint32_t currentPaletteNameHash = MurmurHash3_32(paletteNames[currentPaletteIndex]);
EEPROM.put(20, currentPatternNameHash);
EEPROM.put(24, currentPaletteNameHash);

EEPROM.write(511, SETTINGS_MAGIC_BYTE);
EEPROM.commit();
}
Expand Down
4 changes: 2 additions & 2 deletions esp8266-fastled-webserver/include/configs/product/1628rings.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#if !defined(FRAMES_PER_SECOND)
#define FRAMES_PER_SECOND 1000 // No enforced delay?
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#define DEFAULT_PATTERN_INDEX 0
#if !defined(DEFAULT_PATTERN_FUNCTION)
#define DEFAULT_PATTERN_FUNCTION pride
#endif
#if !defined(DEFAULT_BRIGHTNESS_INDEX)
#define DEFAULT_BRIGHTNESS_INDEX 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#if !defined(FRAMES_PER_SECOND)
#define FRAMES_PER_SECOND 120
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#define DEFAULT_PATTERN_INDEX 0
#if !defined(DEFAULT_PATTERN_FUNCTION)
#define DEFAULT_PATTERN_FUNCTION pride
#endif
#if !defined(DEFAULT_BRIGHTNESS_INDEX)
#define DEFAULT_BRIGHTNESS_INDEX 3
Expand Down
4 changes: 2 additions & 2 deletions esp8266-fastled-webserver/include/configs/product/default.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#if !defined(FRAMES_PER_SECOND)
#define FRAMES_PER_SECOND 120
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#define DEFAULT_PATTERN_INDEX 0
#if !defined(DEFAULT_PATTERN_FUNCTION)
#define DEFAULT_PATTERN_FUNCTION pride
#endif
#if !defined(DEFAULT_BRIGHTNESS_INDEX)
#define DEFAULT_BRIGHTNESS_INDEX 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
#if !defined(FRAMES_PER_SECOND)
#define FRAMES_PER_SECOND 120
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#define DEFAULT_PATTERN_INDEX 3
#if !defined(DEFAULT_PATTERN_FUNCTION)
#define DEFAULT_PATTERN_FUNCTION colorWavesPlayground
#endif
#if !defined(DEFAULT_BRIGHTNESS_INDEX)
#define DEFAULT_BRIGHTNESS_INDEX 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
#if !defined(FRAMES_PER_SECOND)
#define FRAMES_PER_SECOND 120
#endif
#if !defined(DEFAULT_PATTERN_INDEX)
#define DEFAULT_PATTERN_INDEX 3
#if !defined(DEFAULT_PATTERN_FUNCTION)
#define DEFAULT_PATTERN_FUNCTION colorWavesFibonacci
#endif
#if !defined(DEFAULT_BRIGHTNESS_INDEX)
#define DEFAULT_BRIGHTNESS_INDEX 3
Expand Down
Loading