Compare commits
15 Commits
096d13438a
...
205a0df842
Author | SHA1 | Date | |
---|---|---|---|
205a0df842 | |||
8bcee1871f | |||
ef57c5ea2e | |||
0f1d4abe04 | |||
2b50691067 | |||
af1314632e | |||
2b7033b685 | |||
97dd6de280 | |||
54d357e6df | |||
ac1f758b87 | |||
85aee53462 | |||
f42b5e1034 | |||
083564caef | |||
3f6d4cb0be | |||
382631d7d7 |
@ -95,7 +95,6 @@ If you enabled `DEBUG`, log messages will be sent to `MQTT_TOPIC/log`.
|
||||
| FastLED (with small modifications) | Daniel Garcia & Mark Kriegsman | https://fastled.io
|
||||
| NTPClient (with modifications) | | https://github.com/arduino-libraries/NTPClient
|
||||
| ESP8266WebServer | | https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer
|
||||
| ErriezCRC32 | Erriez | https://github.com/Erriez/ErriezCRC32
|
||||
| ESPAsyncTCP | me-no-dev | https://github.com/me-no-dev/ESPAsyncTCP
|
||||
|
||||
### Inspirations and stuff
|
||||
|
@ -9,7 +9,7 @@ protected:
|
||||
Window* window = Window::getFullWindow(); // Use a full screen window per default.
|
||||
public:
|
||||
virtual ~Effect() {};
|
||||
virtual void loop() = 0;
|
||||
virtual void loop(uint16_t ms) = 0;
|
||||
virtual String get_name() = 0;
|
||||
boolean supports_window = false;
|
||||
virtual boolean can_be_shown_with_clock() { return false; };
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <Arduino.h>
|
||||
#define FASTLED_INTERNAL
|
||||
#include <FastLED.h>
|
||||
#include "settings.h"
|
||||
|
||||
//#define DEBUG // Uncomment this to enable Debug messages via Serial and, if enabled, MQTT.
|
||||
//#define CONFIG_USABLE // Uncomment this by removing the // at the beginning!
|
||||
@ -49,39 +50,35 @@
|
||||
#define MONITOR_LOOP_TIME_THRESHOLD 500
|
||||
#define MONITOR_LOOP_TIME_COUNT_MAX 10
|
||||
|
||||
#define EFFECT_CYCLE_TIME 300 // Time in seconds between cycling effects.
|
||||
#define EFFECT_CYCLE_RANDOM true
|
||||
// settings.effects.cycle.time = 300; // Time in seconds between cycling effects.
|
||||
// settings.effects.cycle.random = true;
|
||||
|
||||
#define EFFECT_MATRIX_LENGTH_MIN 4
|
||||
#define EFFECT_MATRIX_LENGTH_MAX 20
|
||||
#define EFFECT_MATRIX_SPEED_MIN 50
|
||||
#define EFFECT_MATRIX_SPEED_MAX 135
|
||||
// settings.effects.matrix.length_min = 4;
|
||||
// settings.effects.matrix.length_max = 20;
|
||||
// settings.effects.matrix.speed_min = 1;
|
||||
// settings.effects.matrix.speed_max = 10;
|
||||
|
||||
#define EFFECT_SINGLE_DYNAMIC_LOOP_TIME 40
|
||||
#define EFFECT_MULTI_DYNAMIC_LOOP_TIME 1400
|
||||
#define EFFECT_BIG_DYNAMIC_LOOP_TIME 50
|
||||
#define EFFECT_BIG_DYNAMIC_SIZE 3
|
||||
// .dynamic.single_loop_time = 40;
|
||||
// .dynamic.multi_loop_time = 1400;
|
||||
// .dynamic.big_loop_time = 50;
|
||||
// .dynamic.big_size = 3;
|
||||
|
||||
#define EFFECT_CONFETTI_PIXELS_PER_LOOP 2
|
||||
// .fire.cooldown = 192;
|
||||
// .fire.spark_chance = 5;
|
||||
|
||||
#define EFFECT_SNAKE_DIRECTION_CHANGE 10
|
||||
#define EFFECT_SNAKE_SLOWDOWN 2
|
||||
// .firework.drag = 255;
|
||||
// .firework.bounce = 200;
|
||||
// .firework.gravity = 10;
|
||||
// .firework.sparks = 12;
|
||||
|
||||
#define EFFECT_FIRE_COOLDOWN 192
|
||||
#define EFFECT_FIRE_SPARK_CHANCE 5
|
||||
// .gol.start_percentage = 90;
|
||||
// .gol.blend_speed = 10;
|
||||
// .gol.restart_after_steps = 100;
|
||||
|
||||
#define EFFECT_FIREWORK_SHOT_CHANCE 200
|
||||
#define EFFECT_FIREWORK_BLUR 200
|
||||
#define EFFECT_FIREWORK_FADEOUT_SPEED 5
|
||||
// .sines.count = 5;
|
||||
|
||||
#define EFFECT_GOL_START_PERCENTAGE 90
|
||||
#define EFFECT_GOL_BLEND_SPEED 10
|
||||
#define EFFECT_GOL_RESTART_AFTER_STEPS 100
|
||||
|
||||
#define EFFECT_DVD_WIDTH 3
|
||||
#define EFFECT_DVD_HEIGHT 2
|
||||
|
||||
#define EFFECT_SINES_COUNT 5
|
||||
// .snake.direction_change = 5;
|
||||
// .snake.slowdown = 2;
|
||||
|
||||
// Stop editing here
|
||||
|
||||
|
@ -4,6 +4,6 @@
|
||||
|
||||
class AnalogClockEffect : public Effect {
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "analog_clock"; }
|
||||
};
|
||||
|
@ -17,6 +17,6 @@ public:
|
||||
AnimationEffect(const char* name, uint32_t bg_color, int x, int y);
|
||||
~AnimationEffect();
|
||||
AnimationEffect* setFgColor(uint32_t c);
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override;
|
||||
};
|
||||
|
@ -9,7 +9,7 @@ private:
|
||||
CRGB color_off = CRGB(0x000000);
|
||||
boolean invert = false;
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "bell"; }
|
||||
};
|
||||
|
||||
|
@ -5,12 +5,13 @@
|
||||
class BigClockEffect : public Effect {
|
||||
private:
|
||||
CRGB _color_font = CRGB(0xAAAAAA);
|
||||
CRGB _color_seconds = CRGB(0xFF0000);
|
||||
CRGB _color_seconds_light = CRGB(0xFFFF00);
|
||||
CRGB _color_seconds_dark = CRGB(0xFF0000);
|
||||
|
||||
void _draw_seconds();
|
||||
void _draw_border_pixel(uint8_t second, CRGB* color);
|
||||
void _draw_border_pixel(uint8_t second, uint8_t part, CRGB* color);
|
||||
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "big_clock"; }
|
||||
};
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
~Blur2DEffect();
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "blur2d"; }
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ protected:
|
||||
|
||||
public:
|
||||
~ClockEffect();
|
||||
virtual void loop();
|
||||
virtual void loop(uint16_t ms);
|
||||
String get_name() override { return "clock"; }
|
||||
void loop_with_invert(bool invert);
|
||||
void loop(boolean invert, CRGB fg_color, CRGB bg_color, uint8_t y);
|
||||
@ -20,5 +20,5 @@ public:
|
||||
class NightClockEffect : public ClockEffect {
|
||||
public:
|
||||
NightClockEffect();
|
||||
void loop() override;
|
||||
void loop(uint16_t ms) override;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ class ConfettiEffect : public Effect {
|
||||
protected:
|
||||
virtual CRGB _getColor();
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
boolean can_be_shown_with_clock();
|
||||
String get_name() override { return "confetti"; }
|
||||
};
|
||||
|
@ -8,6 +8,8 @@ private:
|
||||
Effect* effect = NULL;
|
||||
uint16_t effect_id = -1;
|
||||
unsigned long effectSince = 0;
|
||||
uint16_t _heap_free = 0;
|
||||
uint8_t _effects_count;
|
||||
public:
|
||||
CycleEffect();
|
||||
~CycleEffect();
|
||||
@ -17,5 +19,5 @@ public:
|
||||
boolean clock_as_mask();
|
||||
String get_name() override;
|
||||
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
};
|
||||
|
@ -4,15 +4,15 @@
|
||||
class DvdEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
uint8_t _x = 0;
|
||||
uint8_t _y = 0;
|
||||
saccum78 _x = 0;
|
||||
saccum78 _y = 0;
|
||||
int8_t _x_dir = 1;
|
||||
int8_t _y_dir = 1;
|
||||
CRGB _color;
|
||||
public:
|
||||
DvdEffect();
|
||||
~DvdEffect();
|
||||
void loop() override;
|
||||
void loop(uint16_t ms) override;
|
||||
bool can_be_shown_with_clock() override;
|
||||
String get_name() override { return "dvd"; }
|
||||
};
|
||||
|
@ -13,14 +13,14 @@ public:
|
||||
SingleDynamicEffect();
|
||||
void init();
|
||||
boolean can_be_shown_with_clock();
|
||||
virtual void loop();
|
||||
virtual void loop(uint16_t ms);
|
||||
void draw();
|
||||
String get_name() override { return "single_dynamic"; }
|
||||
};
|
||||
|
||||
class MultiDynamicEffect : public SingleDynamicEffect {
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "multi_dynamic"; }
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@ class BigDynamicEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
~BigDynamicEffect();
|
||||
boolean can_be_shown_with_clock() override;
|
||||
String get_name() override { return "big_dynamic"; }
|
||||
|
@ -15,6 +15,6 @@ private:
|
||||
public:
|
||||
FireEffect();
|
||||
~FireEffect();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "fire"; }
|
||||
};
|
||||
|
@ -6,11 +6,6 @@
|
||||
|
||||
enum FireworkDotType { FIREWORK_DOT_NONE, FIREWORK_DOT_SHELL, FIREWORK_DOT_SPARK };
|
||||
|
||||
#define EFFECT_FIREWORK_DRAG 255
|
||||
#define EFFECT_FIREWORK_BOUNCE 200
|
||||
#define EFFECT_FIREWORK_GRAVITY 10
|
||||
#define EFFECT_FIREWORK_SPARKS 12
|
||||
|
||||
class FireworkEffect;
|
||||
|
||||
class FireworkEffectDot {
|
||||
@ -49,14 +44,14 @@ private:
|
||||
CRGB _burst_color;
|
||||
|
||||
FireworkEffectDot* _dot;
|
||||
FireworkEffectDot* _sparks[EFFECT_FIREWORK_SPARKS];
|
||||
FireworkEffectDot** _sparks;
|
||||
public:
|
||||
FireworkEffect();
|
||||
~FireworkEffect();
|
||||
void skyburst(accum88 x, accum88 y, saccum78 xv, saccum78 yv, CRGB c);
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "firework"; }
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ private:
|
||||
public:
|
||||
GolEffect();
|
||||
~GolEffect();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
bool can_be_shown_with_clock();
|
||||
String get_name() override { return "gol"; }
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ private:
|
||||
public:
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
void apply_option(String key, String value) override;
|
||||
String get_name() override { return "marquee"; }
|
||||
};
|
||||
|
@ -27,9 +27,9 @@ public:
|
||||
|
||||
MatrixEffectColumn(Window* win, uint8_t direction=0, bool random_direction=false);
|
||||
virtual ~MatrixEffectColumn() {};
|
||||
void advance();
|
||||
void advance(uint16_t ms);
|
||||
void draw();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
};
|
||||
|
||||
class RainbowMatrixEffectColumn : public MatrixEffectColumn {
|
||||
@ -55,7 +55,7 @@ public:
|
||||
boolean can_be_shown_with_clock();
|
||||
MatrixEffect();
|
||||
virtual ~MatrixEffect();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "matrix"; }
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@ private:
|
||||
public:
|
||||
PixelClockEffect();
|
||||
~PixelClockEffect();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
bool can_be_shown_with_clock();
|
||||
String get_name() override { return "pixel_clock"; }
|
||||
};
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
boolean clock_as_mask();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "sinematrix3"; }
|
||||
};
|
||||
|
||||
|
@ -6,28 +6,29 @@
|
||||
|
||||
class SinesEffectSinus {
|
||||
private:
|
||||
uint8_t _value;
|
||||
uint8_t _frequency;
|
||||
uint8_t _amplitude;
|
||||
uint8_t _x;
|
||||
uint8_t _step;
|
||||
uint16_t _frequency;
|
||||
uint16_t _color_frequency;
|
||||
uint16_t _amplitude;
|
||||
uint16_t _x;
|
||||
uint16_t _offset;
|
||||
Window* _window;
|
||||
CRGB _color;
|
||||
public:
|
||||
SinesEffectSinus(Window* w);
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
};
|
||||
|
||||
class SinesEffect : public Effect {
|
||||
private:
|
||||
SinesEffectSinus* _sinus[EFFECT_SINES_COUNT];
|
||||
uint8_t _step = 0;
|
||||
SinesEffectSinus** _sinus;
|
||||
uint8_t _count;
|
||||
void _init();
|
||||
void _delete();
|
||||
public:
|
||||
SinesEffect();
|
||||
~SinesEffect();
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "sines"; }
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ private:
|
||||
public:
|
||||
SnakeEffect();
|
||||
~SnakeEffect();
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
boolean valid_position(Coords c);
|
||||
Coords update_position(Coords c, uint8_t direction);
|
||||
boolean can_be_shown_with_clock();
|
||||
|
@ -9,7 +9,7 @@ private:
|
||||
public:
|
||||
StaticEffect(CRGB col);
|
||||
boolean supports_window = true;
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
String get_name() override { return "static"; }
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@ private:
|
||||
double _real_center_x = LED_WIDTH / 2;
|
||||
double _real_center_y = LED_HEIGHT / 2;
|
||||
public:
|
||||
void loop();
|
||||
void loop(uint16_t ms);
|
||||
boolean can_be_shown_with_clock() override;
|
||||
boolean clock_as_mask() override;
|
||||
String get_name() override { return "twirl"; }
|
||||
|
@ -1,17 +1,20 @@
|
||||
#ifndef effects_H
|
||||
#define effects_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "effect_clock.h"
|
||||
|
||||
extern const char* cycle_effects[];
|
||||
extern uint8_t cycle_effects_count;
|
||||
struct EffectEntry {
|
||||
const char* name;
|
||||
bool use_in_cycle;
|
||||
std::function<Effect*()> create;
|
||||
};
|
||||
extern const EffectEntry effects[];
|
||||
extern const uint8_t effects_size;
|
||||
|
||||
extern Effect* current_effect;
|
||||
extern ClockEffect effect_clock;
|
||||
|
||||
Effect* select_effect(uint32_t c);
|
||||
Effect* select_effect(char* name);
|
||||
Effect* select_effect(uint8_t id);
|
||||
bool change_current_effect(String s);
|
||||
void setup_effects();
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
extern uint8_t baseHue;
|
||||
extern char hostname[30];
|
||||
|
||||
typedef struct {
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
@ -26,6 +29,3 @@ typedef struct {
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} Coords;
|
||||
|
||||
extern uint8_t baseHue;
|
||||
extern char hostname[30];
|
||||
|
83
include/settings.h
Normal file
83
include/settings.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
enum SettingType {
|
||||
TYPE_UINT8,
|
||||
TYPE_UINT16,
|
||||
TYPE_BOOL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
uint16_t* value;
|
||||
SettingType type;
|
||||
} Setting;
|
||||
|
||||
struct Settings {
|
||||
uint16_t fps = 50;
|
||||
|
||||
struct /* effects */ {
|
||||
struct /* cycle */ {
|
||||
uint16_t time = 300;
|
||||
uint16_t random = 1;
|
||||
} cycle ;
|
||||
|
||||
struct /* matrix */ {
|
||||
uint16_t length_min = 4;
|
||||
uint16_t length_max = 20;
|
||||
uint16_t speed_min = 1;
|
||||
uint16_t speed_max = 10;
|
||||
} matrix;
|
||||
|
||||
struct /* confetti */ {
|
||||
uint16_t pixels_per_loop = 2;
|
||||
} confetti;
|
||||
|
||||
struct /* dvd */ {
|
||||
uint16_t width = 3;
|
||||
uint16_t height = 2;
|
||||
uint16_t speed = 50;
|
||||
} dvd;
|
||||
|
||||
struct /* dynamic */ {
|
||||
uint16_t single_loop_time = 40;
|
||||
uint16_t multi_loop_time = 1400;
|
||||
uint16_t big_loop_time = 50;
|
||||
uint16_t big_size = 3;
|
||||
} dynamic;
|
||||
|
||||
struct /* fire */ {
|
||||
uint16_t cooldown = 192;
|
||||
uint16_t spark_chance = 5;
|
||||
} fire;
|
||||
|
||||
struct /* firework */ {
|
||||
uint16_t drag = 255;
|
||||
uint16_t bounce = 200;
|
||||
uint16_t gravity = 10;
|
||||
uint16_t sparks = 12;
|
||||
} firework;
|
||||
|
||||
struct /* gol */ {
|
||||
uint16_t start_percentage = 90;
|
||||
uint16_t blend_speed = 10;
|
||||
uint16_t restart_after_steps = 100;
|
||||
} gol;
|
||||
|
||||
struct /* sines */ {
|
||||
uint16_t count = 5;
|
||||
} sines;
|
||||
|
||||
struct /* snake */ {
|
||||
uint16_t direction_change = 5;
|
||||
uint16_t slowdown = 2;
|
||||
} snake;
|
||||
} effects;
|
||||
};
|
||||
|
||||
extern Settings settings;
|
||||
extern Setting all_settings[];
|
||||
extern const uint8_t all_settings_size;
|
||||
|
||||
bool change_setting(const char* key, uint16_t new_value);
|
@ -18,7 +18,6 @@ lib_deps =
|
||||
https://github.com/fabianonline/FastLED.git
|
||||
https://github.com/fabianonline/NTPClient.git
|
||||
ESP8266WebServer
|
||||
ErriezCRC32
|
||||
ESPAsyncTCP
|
||||
|
||||
[env:ota]
|
||||
|
@ -75,7 +75,7 @@ bool Animation::_load_from_file(const char* filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.available() != size - 6) {
|
||||
if (file.available() < 0 || file.available() + 6 != size) {
|
||||
LOGln("Animation * Expected file to have %d bytes available, but found %d bytes available.", size - 6, file.available());
|
||||
file.close();
|
||||
return false;
|
||||
@ -207,27 +207,29 @@ void Animation::setSingleFrame(uint8_t frame) {
|
||||
|
||||
Animation::~Animation() {
|
||||
for (int i=0; i<_color_count; i++) delete _colors[i];
|
||||
LOGln("Deleting _colors...");
|
||||
|
||||
LOGln("Animation * Deleting _colors...");
|
||||
if (_colors) delete [] _colors;
|
||||
LOGln("Deleting fgColor...");
|
||||
|
||||
LOGln("Animation * Deleting fgColor...");
|
||||
if (fgColor != NULL) delete fgColor;
|
||||
LOGln("Deleting bgColor...");
|
||||
|
||||
LOGln("Animation * Deleting bgColor...");
|
||||
if (bgColor != NULL) delete bgColor;
|
||||
LOGln("Deleting _frame_data_lengths...");
|
||||
|
||||
LOGln("Animation * Deleting _frame_data_lengths...");
|
||||
if (_frame_data_lengths) delete [] _frame_data_lengths;
|
||||
LOGln("Deleting _frame_times...");
|
||||
|
||||
LOGln("Animation * Deleting _frame_times...");
|
||||
if (_frame_times) delete [] _frame_times;
|
||||
for (int i=0; i<_frame_count; i++) {
|
||||
delete [] _frame_data[i];
|
||||
}
|
||||
LOGln("Deleting _frame_data...");
|
||||
|
||||
LOGln("Animation * Deleting _frame_data...");
|
||||
if (_frame_data) delete [] _frame_data;
|
||||
LOGln("Deleteion done.");
|
||||
|
||||
LOGln("Animation * Deletion done.");
|
||||
}
|
||||
|
||||
void Animation::draw() {
|
||||
|
@ -42,13 +42,13 @@ void Window::clear(CRGB* color) {
|
||||
}
|
||||
|
||||
void Window::drawText(Font* font, uint16_t x, uint16_t y, String text, CRGB* color) {
|
||||
for (int i=0; i<text.length(); i++) {
|
||||
drawChar(font, (x+(i*(font->width + 1))<<8), (y<<8), text[i], color);
|
||||
for (uint16_t i=0; i<text.length(); i++) {
|
||||
drawChar(font, (x+((i*(font->width + 1))<<8)), (y<<8), text[i], color);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::drawSubText(Font* font, accum88 x, accum88 y, String text, CRGB* color) {
|
||||
for (int i=0; i<text.length(); i++) {
|
||||
for (uint16_t i=0; i<text.length(); i++) {
|
||||
drawChar(font, x+(i*((font->width + 1)<<8)), y, text[i], color);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "my_fastled.h"
|
||||
#include "ntp.h"
|
||||
|
||||
void AnalogClockEffect::loop() {
|
||||
void AnalogClockEffect::loop(uint16_t ms) {
|
||||
window->clear();
|
||||
CRGB white(0xFFFFFF);
|
||||
CRGB red(0xFF0000);
|
||||
|
@ -20,7 +20,7 @@ AnimationEffect::~AnimationEffect() {
|
||||
delete this->animation;
|
||||
}
|
||||
|
||||
void AnimationEffect::loop() {
|
||||
void AnimationEffect::loop(uint16_t ms) {
|
||||
this->animation->drawFrame();
|
||||
this->animation->advance();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "effect_bell.h"
|
||||
#include "sprites.h"
|
||||
|
||||
void BellEffect::loop() {
|
||||
void BellEffect::loop(uint16_t ms) {
|
||||
Serial.println("This is Bell.loop()");
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int x = 0; x < 2; x++) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "fonts.h"
|
||||
#include "ntp.h"
|
||||
|
||||
void BigClockEffect::loop() {
|
||||
void BigClockEffect::loop(uint16_t ms) {
|
||||
window->clear();
|
||||
uint8_t h = ntpClient.getHours();
|
||||
window->drawChar(&font_numbers3x5_blocky, 6<<8, 2<<8, '0' + (h / 10), &_color_font);
|
||||
@ -25,17 +25,28 @@ void BigClockEffect::loop() {
|
||||
void BigClockEffect::_draw_seconds() {
|
||||
uint8_t seconds = ntpClient.getSeconds();
|
||||
for (int i=1; i<=seconds; i++) {
|
||||
_draw_border_pixel(i, &_color_seconds);
|
||||
_draw_border_pixel(i, 0, (i%5==0) ? &_color_seconds_light : &_color_seconds_dark);
|
||||
}
|
||||
|
||||
uint16_t millis = ntpClient.getEpochMillis() % 1000;
|
||||
/*
|
||||
// Enable this to have the next pixel move smoothly to its position
|
||||
if (millis > 0) {
|
||||
uint8_t part = 60 - ((60 - seconds) * millis / 1000);
|
||||
_draw_border_pixel(part, &_color_seconds);
|
||||
}
|
||||
*/
|
||||
uint8_t offset = 5 - ((millis % 1000) / 200);
|
||||
uint8_t part = scale8(millis % 200, 200);
|
||||
uint8_t number_to_show = (60 - seconds - offset) / 5 + 1;
|
||||
for(uint8_t i = 0; i<number_to_show; i++) {
|
||||
uint8_t pos = seconds + offset + i*5;
|
||||
_draw_border_pixel(pos, part, (seconds + i + 1)%5==0 ? &_color_seconds_light : &_color_seconds_dark);
|
||||
}
|
||||
}
|
||||
|
||||
void BigClockEffect::_draw_border_pixel(uint8_t i, CRGB* color) {
|
||||
uint8_t x, y;
|
||||
void BigClockEffect::_draw_border_pixel(uint8_t i, uint8_t part, CRGB* color) {
|
||||
/*uint8_t x, y;
|
||||
if (i<=8) {
|
||||
x = 7 + i;
|
||||
y = 0;
|
||||
@ -48,9 +59,31 @@ void BigClockEffect::_draw_border_pixel(uint8_t i, CRGB* color) {
|
||||
} else if (i <= 53) {
|
||||
x = 0;
|
||||
y = 15 - i + 38;
|
||||
} else {
|
||||
} else if (i <= 60) {
|
||||
x = i - 53;
|
||||
y = 0;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
window->setPixel(x, y, color);
|
||||
window->setPixel(x, y, color);*/
|
||||
accum88 x, y;
|
||||
if (i<=8) {
|
||||
x = ((7+i)<<8) + part;
|
||||
y = 0;
|
||||
} else if (i<=23) {
|
||||
x = 15<<8;
|
||||
y = ((i-8)<<8) + part;
|
||||
} else if (i<=38) {
|
||||
x = ((38-i)<<8) - part;
|
||||
y = 15<<8;
|
||||
} else if (i<=53) {
|
||||
x = 0;
|
||||
y = ((53-i)<<8) - part;
|
||||
} else if (i<=60) {
|
||||
x = ((i-53)<<8) + part;
|
||||
y = 0;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
window->setSubPixel(x, y, color);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ boolean Blur2DEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Blur2DEffect::loop() {
|
||||
void Blur2DEffect::loop(uint16_t ms) {
|
||||
uint8_t blur_amount = dim8_raw(beatsin8(3, 128, 224));
|
||||
window->blur(blur_amount);
|
||||
|
||||
@ -17,10 +17,10 @@ void Blur2DEffect::loop() {
|
||||
uint8_t x3 = beatsin8(11, 0, window->width-1);
|
||||
uint8_t y3 = beatsin8(13, 0, window->height-1);
|
||||
|
||||
uint16_t ms = millis();
|
||||
CRGB c1 = CHSV(ms / 29, 200, 255);
|
||||
CRGB c2 = CHSV(ms / 41, 200, 255);
|
||||
CRGB c3 = CHSV(ms / 73, 200, 255);
|
||||
uint16_t time = millis();
|
||||
CRGB c1 = CHSV(time / 29, 200, 255);
|
||||
CRGB c2 = CHSV(time / 41, 200, 255);
|
||||
CRGB c3 = CHSV(time / 73, 200, 255);
|
||||
window->addPixelColor(x1, y1, &c1);
|
||||
window->addPixelColor(x2, y2, &c2);
|
||||
window->addPixelColor(x3, y3, &c3);
|
||||
|
@ -8,7 +8,7 @@ NightClockEffect::NightClockEffect() {
|
||||
window = Window::getFullWindow();
|
||||
}
|
||||
|
||||
void NightClockEffect::loop() {
|
||||
void NightClockEffect::loop(uint16_t ms) {
|
||||
uint16_t minutes = minutes16();
|
||||
//uint8_t y = minutes % ((window->height - 5) * 2 - 2);
|
||||
//if (y > window->height - 5) y = 2*window->height - 2*y;
|
||||
@ -16,7 +16,7 @@ void NightClockEffect::loop() {
|
||||
ClockEffect::loop(false, CRGB(0x200000), CRGB(0x000000), y);
|
||||
}
|
||||
|
||||
void ClockEffect::loop() {
|
||||
void ClockEffect::loop(uint16_t ms) {
|
||||
loop_with_invert(false);
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
#include "functions.h"
|
||||
#include "prototypes.h"
|
||||
|
||||
void ConfettiEffect::loop() {
|
||||
void ConfettiEffect::loop(uint16_t ms) {
|
||||
window->fadeToBlackBy(3);
|
||||
for (int i=0; i<EFFECT_CONFETTI_PIXELS_PER_LOOP; i++) {
|
||||
for (int i=0; i<settings.effects.confetti.pixels_per_loop; i++) {
|
||||
CRGB color = _getColor();
|
||||
window->addPixelColor(random16(LED_COUNT), &color);
|
||||
}
|
||||
|
@ -3,6 +3,11 @@
|
||||
#include <ErriezCRC32.h>
|
||||
|
||||
CycleEffect::CycleEffect() {
|
||||
_effects_count = 0;
|
||||
for (uint8_t i=0; i<effects_size; i++) {
|
||||
if (effects[i].use_in_cycle) _effects_count++;
|
||||
}
|
||||
LOGln("Cycle * Found %d effects to use in cycle.", _effects_count);
|
||||
changeEffect();
|
||||
}
|
||||
|
||||
@ -11,20 +16,41 @@ CycleEffect::~CycleEffect() {
|
||||
}
|
||||
|
||||
void CycleEffect::changeEffect() {
|
||||
int new_id;
|
||||
if (EFFECT_CYCLE_RANDOM) {
|
||||
uint8_t new_id;
|
||||
if (settings.effects.cycle.random && _effects_count>1) {
|
||||
do {
|
||||
new_id = random8(cycle_effects_count);
|
||||
new_id = random8(_effects_count);
|
||||
} while (new_id == effect_id);
|
||||
} else {
|
||||
new_id = (effect_id + 1) % cycle_effects_count;
|
||||
new_id = (effect_id + 1) % _effects_count;
|
||||
}
|
||||
LOGln("CycleEffect * Changing effect from #%d to #%d", effect_id, new_id);
|
||||
delay(25);
|
||||
|
||||
if (effect) delete effect;
|
||||
LOGln("CycleEffect * Searching for new effect '%s'", cycle_effects[new_id]);
|
||||
|
||||
int16_t diff;
|
||||
uint16_t old_heap = _heap_free;
|
||||
_heap_free = ESP.getFreeHeap();
|
||||
if (old_heap) {
|
||||
// diff positive = More heap used (baad)
|
||||
// diff negative = Less heap used (good-ish)
|
||||
diff = old_heap - _heap_free;
|
||||
LOGln("CycleEffect * Heap usage: #%d,%d,%+d", effect_id, _heap_free, diff);
|
||||
}
|
||||
|
||||
delay(25);
|
||||
effect = select_effect( crc32String(cycle_effects[new_id]) );
|
||||
LOGln("CycleEffect * Searching for new effect #%d", new_id);
|
||||
uint8_t count = 0;
|
||||
for (uint8_t i=0; i<effects_size; i++) {
|
||||
if (effects[i].use_in_cycle) {
|
||||
if (count == new_id) {
|
||||
effect = effects[i].create();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (effect) {
|
||||
effect_id = new_id;
|
||||
effectSince = millis();
|
||||
@ -41,13 +67,13 @@ boolean CycleEffect::clock_as_mask() {
|
||||
return effect->clock_as_mask();
|
||||
};
|
||||
|
||||
void CycleEffect::loop() {
|
||||
void CycleEffect::loop(uint16_t ms) {
|
||||
if (!effect) changeEffect(); // If this is the first run, we have to select an effect first!
|
||||
effect->loop();
|
||||
effect->loop(ms);
|
||||
// Don't use EVERY_N_SECONDS(config_effect_cycle_time) here because that function isn't relly made
|
||||
// to be used with changing values.
|
||||
EVERY_N_SECONDS(1) {
|
||||
if (effectSince + EFFECT_CYCLE_TIME*1000 < millis()) {
|
||||
if (effectSince + settings.effects.cycle.time*1000 < millis()) {
|
||||
changeEffect();
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,43 @@
|
||||
#include "effect_dvd.h"
|
||||
#include "my_fastled.h"
|
||||
|
||||
void DvdEffect::loop() {
|
||||
void DvdEffect::loop(uint16_t ms) {
|
||||
bool dir_changed = false;
|
||||
EVERY_N_MILLISECONDS( 250 ) {
|
||||
_x += _x_dir;
|
||||
_y += _y_dir;
|
||||
|
||||
if (_x == 0 || _x + EFFECT_DVD_WIDTH >= window->width) {
|
||||
_x_dir = -_x_dir;
|
||||
dir_changed = true;
|
||||
}
|
||||
if (_y == 0 || _y + EFFECT_DVD_HEIGHT >= window->height) {
|
||||
_y_dir = -_y_dir;
|
||||
dir_changed = true;
|
||||
}
|
||||
_x += _x_dir * settings.effects.dvd.speed;
|
||||
_y += _y_dir * settings.effects.dvd.speed;
|
||||
|
||||
if (_x <= 0) {
|
||||
_x = -_x;
|
||||
_x_dir = -_x_dir;
|
||||
dir_changed = true;
|
||||
//LOGln("speed: %d", settings.effects.dvd.speed);
|
||||
} else if (_x + (settings.effects.dvd.width << 8) >= (window->width << 8)) {
|
||||
_x -= 2*settings.effects.dvd.speed;
|
||||
_x_dir = -_x_dir;
|
||||
dir_changed = true;
|
||||
}
|
||||
|
||||
if (_y <= 0) {
|
||||
_y = -_y;
|
||||
_y_dir = -_y_dir;
|
||||
dir_changed = true;
|
||||
} else if (_y + (settings.effects.dvd.height << 8) >= (window->height << 8)) {
|
||||
_y -= 2*settings.effects.dvd.speed;
|
||||
_y_dir = -_y_dir;
|
||||
dir_changed = true;
|
||||
}
|
||||
|
||||
window->clear();
|
||||
|
||||
for (int x=0; x<EFFECT_DVD_WIDTH; x++) for (int y=0; y<EFFECT_DVD_HEIGHT; y++) {
|
||||
window->setPixel(_x + x, _y + y, (CRGB*)&_color);
|
||||
}
|
||||
|
||||
if (dir_changed) _color = (CRGB)CHSV(random8(), 255, 255);
|
||||
|
||||
for (int x=0; x<settings.effects.dvd.width; x++) for (int y=0; y<settings.effects.dvd.height; y++) {
|
||||
window->setSubPixel(_x + (x<<8), _y + (y<<8), (CRGB*)&_color);
|
||||
}
|
||||
for (int x=1; x<settings.effects.dvd.width; x++) for (int y=1; y<settings.effects.dvd.height; y++) {
|
||||
window->setPixel((_x>>8) + x, (_y>>8) + y, (CRGB*)&_color);
|
||||
}
|
||||
}
|
||||
|
||||
bool DvdEffect::can_be_shown_with_clock() { return true; }
|
||||
|
@ -10,8 +10,8 @@ void SingleDynamicEffect::init() {
|
||||
for (int i=0; i<tile_count; i++) tiles[i] = CHSV(baseHue + random8(64), 180, 255);
|
||||
}
|
||||
|
||||
void SingleDynamicEffect::loop() {
|
||||
EVERY_N_MILLISECONDS( EFFECT_SINGLE_DYNAMIC_LOOP_TIME ) {
|
||||
void SingleDynamicEffect::loop(uint16_t ms) {
|
||||
EVERY_N_MILLISECONDS( settings.effects.dynamic.single_loop_time ) {
|
||||
tiles[random8(tile_count)] = CHSV(baseHue + random8(64), 180, 255);
|
||||
}
|
||||
this->draw();
|
||||
@ -28,8 +28,8 @@ boolean SingleDynamicEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MultiDynamicEffect::loop() {
|
||||
EVERY_N_MILLISECONDS( EFFECT_MULTI_DYNAMIC_LOOP_TIME ) {
|
||||
void MultiDynamicEffect::loop(uint16_t ms) {
|
||||
EVERY_N_MILLISECONDS( settings.effects.dynamic.multi_loop_time ) {
|
||||
for (int i=0; i<tile_count; i++) tiles[i] = CHSV(baseHue + random8(64), 180, 255);
|
||||
}
|
||||
this->draw();
|
||||
@ -39,24 +39,16 @@ BigDynamicEffect::~BigDynamicEffect() {
|
||||
delete window;
|
||||
}
|
||||
|
||||
void BigDynamicEffect::loop() {
|
||||
EVERY_N_MILLISECONDS( EFFECT_BIG_DYNAMIC_LOOP_TIME ) {
|
||||
uint8_t x = random8(0, window->width - EFFECT_BIG_DYNAMIC_SIZE + 1);
|
||||
uint8_t y = random8(0, window->height - EFFECT_BIG_DYNAMIC_SIZE + 1);
|
||||
void BigDynamicEffect::loop(uint16_t ms) {
|
||||
EVERY_N_MILLISECONDS( settings.effects.dynamic.big_loop_time ) {
|
||||
uint8_t x = random8(0, window->width - settings.effects.dynamic.big_size + 1);
|
||||
uint8_t y = random8(0, window->height - settings.effects.dynamic.big_size + 1);
|
||||
CRGB color = CHSV(random8(), 255, 255);
|
||||
CRGB black(0x000000);
|
||||
|
||||
for (uint8_t ix=0; ix<EFFECT_BIG_DYNAMIC_SIZE; ix++) for (uint8_t iy=0; iy<EFFECT_BIG_DYNAMIC_SIZE; iy++) {
|
||||
for (uint8_t ix=0; ix<settings.effects.dynamic.big_size; ix++) for (uint8_t iy=0; iy<settings.effects.dynamic.big_size; iy++) {
|
||||
window->setPixel(x+ix, y+iy, &color);
|
||||
}
|
||||
/*for (uint8_t ix=0; ix<EFFECT_BIG_DYNAMIC_SIZE+2; ix++) {
|
||||
window->setPixel(x-1+ix, y-1, &black);
|
||||
window->setPixel(x-1+ix, y+EFFECT_BIG_DYNAMIC_SIZE+1, &black);
|
||||
}
|
||||
for (uint8_t iy=0; iy<EFFECT_BIG_DYNAMIC_SIZE+2; iy++) {
|
||||
window->setPixel(x-1, y-1+iy, &black);
|
||||
window->setPixel(x+EFFECT_BIG_DYNAMIC_SIZE+1, y-1+iy, &black);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ FireEffect::~FireEffect() {
|
||||
delete [] this->data;
|
||||
}
|
||||
|
||||
void FireEffect::loop() {
|
||||
void FireEffect::loop(uint16_t ms) {
|
||||
cooldown();
|
||||
spark();
|
||||
propagate();
|
||||
@ -22,11 +22,11 @@ void FireEffect::loop() {
|
||||
}
|
||||
|
||||
void FireEffect::cooldown() {
|
||||
for(int i=0; i<(this->window->width * this->window->height); i++) this->data[i] = scale8(this->data[i], EFFECT_FIRE_COOLDOWN); // 240 or something
|
||||
for(int i=0; i<(this->window->width * this->window->height); i++) this->data[i] = scale8(this->data[i], settings.effects.fire.cooldown);
|
||||
}
|
||||
|
||||
void FireEffect::spark() {
|
||||
for(int x=0; x<this->window->width; x++) if (random8(EFFECT_FIRE_SPARK_CHANCE)==0) this->data[x] = this->spark_temp();
|
||||
for(int x=0; x<this->window->width; x++) if (random8(settings.effects.fire.spark_chance)==0) this->data[x] = this->spark_temp();
|
||||
}
|
||||
|
||||
inline uint8_t FireEffect::spark_temp() {
|
||||
|
@ -49,20 +49,20 @@ void FireworkEffectDot::draw() {
|
||||
dim8_video( scale8( scale8( _color.g, ye), xe)),
|
||||
dim8_video( scale8( scale8( _color.b, ye), xe)));
|
||||
_window->addPixelColor(ix, iy, &c00);
|
||||
_window->addPixelColor(ix, iy+1, &c01);
|
||||
_window->addPixelColor(ix, iy-1, &c01);
|
||||
_window->addPixelColor(ix+1, iy, &c10);
|
||||
_window->addPixelColor(ix+1, iy+1, &c11);
|
||||
_window->addPixelColor(ix+1, iy-1, &c11);
|
||||
}
|
||||
|
||||
void FireworkEffectDot::move() {
|
||||
if (!show) return;
|
||||
_yv -= EFFECT_FIREWORK_GRAVITY;
|
||||
_xv = _scale15by8_local(_xv, EFFECT_FIREWORK_DRAG);
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_DRAG);
|
||||
_yv -= settings.effects.firework.gravity;
|
||||
_xv = _scale15by8_local(_xv, settings.effects.firework.drag);
|
||||
_yv = _scale15by8_local(_yv, settings.effects.firework.drag);
|
||||
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
_xv = _scale15by8_local(_xv, EFFECT_FIREWORK_DRAG);
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_DRAG);
|
||||
_xv = _scale15by8_local(_xv, settings.effects.firework.drag);
|
||||
_yv = _scale15by8_local(_yv, settings.effects.firework.drag);
|
||||
_color.nscale8(255);
|
||||
if (!_color) {
|
||||
show = 0;
|
||||
@ -70,12 +70,12 @@ void FireworkEffectDot::move() {
|
||||
}
|
||||
|
||||
// Bounce if we hit the ground
|
||||
if (_xv < 0 && _y - _window->height < (-_yv)) {
|
||||
if (_yv < 0 && _y - _window->height < (-_yv)) {
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
show = 0;
|
||||
} else {
|
||||
_yv = -_yv;
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_BOUNCE);
|
||||
_yv = _scale15by8_local(_yv, settings.effects.firework.bounce);
|
||||
if (_yv < 500) {
|
||||
show = 0;
|
||||
}
|
||||
@ -139,11 +139,11 @@ boolean FireworkEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FireworkEffect::loop() {
|
||||
void FireworkEffect::loop(uint16_t ms) {
|
||||
window->clear();
|
||||
_dot->move();
|
||||
_dot->draw();
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
for (int i=0; i<settings.effects.firework.sparks; i++) {
|
||||
_sparks[i]->move();
|
||||
_sparks[i]->draw();
|
||||
}
|
||||
@ -159,7 +159,7 @@ void FireworkEffect::loop() {
|
||||
}
|
||||
|
||||
if (_skyburst) {
|
||||
int nsparks = random8(EFFECT_FIREWORK_SPARKS / 2, EFFECT_FIREWORK_SPARKS + 1);
|
||||
int nsparks = random8(settings.effects.firework.sparks / 2, settings.effects.firework.sparks + 1);
|
||||
for (int i=0; i<nsparks; i++) {
|
||||
_sparks[i]->sky_burst(_burst_x, _burst_y, _burst_yv, _burst_color);
|
||||
_skyburst = 0;
|
||||
@ -169,14 +169,15 @@ void FireworkEffect::loop() {
|
||||
|
||||
FireworkEffect::FireworkEffect() {
|
||||
_dot = new FireworkEffectDot(window, this);
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
_sparks = new FireworkEffectDot*[settings.effects.firework.sparks];
|
||||
for (int i=0; i<settings.effects.firework.sparks; i++) {
|
||||
_sparks[i] = new FireworkEffectDot(window, this);
|
||||
}
|
||||
}
|
||||
|
||||
FireworkEffect::~FireworkEffect() {
|
||||
delete window;
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
for (int i=0; i<settings.effects.firework.sparks; i++) {
|
||||
delete _sparks[i];
|
||||
}
|
||||
delete _dot;
|
||||
|
@ -16,7 +16,7 @@ bool GolEffect::can_be_shown_with_clock() { return true; }
|
||||
|
||||
void GolEffect::_initialize() {
|
||||
for(uint16_t i=0; i<this->window->count; i++) {
|
||||
_data[i] = random8() < EFFECT_GOL_START_PERCENTAGE ? 1 : 0;
|
||||
_data[i] = random8() < settings.effects.gol.start_percentage ? 1 : 0;
|
||||
}
|
||||
_old_hue = _hue;
|
||||
_hue = random8();
|
||||
@ -29,12 +29,12 @@ GolEffect::~GolEffect() {
|
||||
delete window;
|
||||
}
|
||||
|
||||
void GolEffect::loop() {
|
||||
if (EFFECT_GOL_BLEND_SPEED + _blend > 255) {
|
||||
void GolEffect::loop(uint16_t ms) {
|
||||
if (settings.effects.gol.blend_speed + _blend > 255) {
|
||||
_blend = 0;
|
||||
_advance();
|
||||
} else {
|
||||
_blend += EFFECT_GOL_BLEND_SPEED;
|
||||
_blend += settings.effects.gol.blend_speed;
|
||||
}
|
||||
|
||||
_draw();
|
||||
@ -43,7 +43,7 @@ void GolEffect::loop() {
|
||||
void GolEffect::_advance() {
|
||||
_step++;
|
||||
_old_hue = _hue;
|
||||
if (_step >= EFFECT_GOL_RESTART_AFTER_STEPS) {
|
||||
if (_step >= settings.effects.gol.restart_after_steps) {
|
||||
_initialize();
|
||||
} else {
|
||||
for(uint16_t i=0; i<this->window->count; i++) {
|
||||
|
@ -5,8 +5,7 @@ boolean MarqueeEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MarqueeEffect::loop() {
|
||||
static int loop_counter = 0;
|
||||
void MarqueeEffect::loop(uint16_t ms) {
|
||||
window->clear();
|
||||
CRGB color = CHSV(0, 255, 255);
|
||||
uint16_t width = _text.length() * 6;
|
||||
|
@ -38,27 +38,27 @@ void MatrixEffectColumn::restart(bool completely_random) {
|
||||
}
|
||||
}
|
||||
|
||||
length = random8(EFFECT_MATRIX_LENGTH_MIN, EFFECT_MATRIX_LENGTH_MAX);
|
||||
length = random8(settings.effects.matrix.length_min, settings.effects.matrix.length_max);
|
||||
running = true;
|
||||
speed = random8(EFFECT_MATRIX_SPEED_MIN, EFFECT_MATRIX_SPEED_MAX);
|
||||
speed = random8(settings.effects.matrix.speed_min, settings.effects.matrix.speed_max);
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::advance() {
|
||||
void MatrixEffectColumn::advance(uint16_t ms) {
|
||||
switch(_direction) {
|
||||
case DIR_NORTH:
|
||||
y-=speed;
|
||||
y-=speed * ms;
|
||||
if ((y>>8) > window->height && (y>>8) + length > window->height) running=false;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
x+=speed;
|
||||
x+=speed * ms;
|
||||
if ((x>>8) - length > window->width) running=false;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
y+=speed;
|
||||
y+=speed * ms;
|
||||
if ((y>>8) - length > window->height) running=false;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
x-=speed;
|
||||
x-=speed * ms;
|
||||
if ((x>>8) > window->width && (y>>8) + length > window->width) running=false;
|
||||
break;
|
||||
}
|
||||
@ -79,14 +79,14 @@ void MatrixEffectColumn::draw() {
|
||||
}
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::loop() {
|
||||
void MatrixEffectColumn::loop(uint16_t ms) {
|
||||
if (!running) {
|
||||
if (random8() < 20) {
|
||||
// Start the column again.
|
||||
restart(false);
|
||||
}
|
||||
} else {
|
||||
advance();
|
||||
advance(ms);
|
||||
draw();
|
||||
}
|
||||
}
|
||||
@ -144,13 +144,19 @@ MatrixEffect::MatrixEffect() {
|
||||
}
|
||||
|
||||
RandomMatrixEffect::RandomMatrixEffect() {
|
||||
_columns = new MatrixEffectColumn* [window->width];
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RandomMatrixEffectColumn(window, random8(4), true);
|
||||
// No need to initialize _columns, because that will have been done by ctor of MatrixEffect.
|
||||
for (int i=0; i<window->width; i++) {
|
||||
delete _columns[i];
|
||||
_columns[i] = new RandomMatrixEffectColumn(window, random8(4), true);
|
||||
}
|
||||
}
|
||||
|
||||
RainbowMatrixEffect::RainbowMatrixEffect() {
|
||||
_columns = new MatrixEffectColumn* [window->width];
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RainbowMatrixEffectColumn(window, MatrixEffectColumn::DIR_SOUTH);
|
||||
// No need to initialize _columns, because that will have been done by ctor of MatrixEffect.
|
||||
for (int i=0; i<window->width; i++) {
|
||||
delete _columns[i];
|
||||
_columns[i] = new RainbowMatrixEffectColumn(window, MatrixEffectColumn::DIR_SOUTH);
|
||||
}
|
||||
}
|
||||
|
||||
MatrixEffect::~MatrixEffect() {
|
||||
@ -160,7 +166,7 @@ MatrixEffect::~MatrixEffect() {
|
||||
delete[] _columns;
|
||||
}
|
||||
|
||||
void MatrixEffect::loop() {
|
||||
void MatrixEffect::loop(uint16_t ms) {
|
||||
window->clear();
|
||||
for (int i=0; i<window->width; i++) _columns[i]->loop();
|
||||
for (int i=0; i<window->width; i++) _columns[i]->loop(ms);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ PixelClockEffect::~PixelClockEffect() {
|
||||
delete window;
|
||||
}
|
||||
|
||||
void PixelClockEffect::loop() {
|
||||
void PixelClockEffect::loop(uint16_t ms) {
|
||||
uint8_t x, y; // Temporary variables for calculating positions
|
||||
window->clear();
|
||||
// Seconds
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
boolean Sinematrix3Effect::can_be_shown_with_clock() { return true; };
|
||||
boolean Sinematrix3Effect::clock_as_mask() { return true; };
|
||||
void Sinematrix3Effect::loop() {
|
||||
void Sinematrix3Effect::loop(uint16_t ms) {
|
||||
pangle = addmodpi( pangle, 0.0133 + (angle / 256) );
|
||||
angle = cos(pangle) * PI;
|
||||
sx = addmodpi( sx, 0.00673 );
|
||||
|
@ -2,47 +2,56 @@
|
||||
|
||||
SinesEffectSinus::SinesEffectSinus(Window* w) {
|
||||
_window = w;
|
||||
_frequency = random8(40)+8;
|
||||
_amplitude = random(5)+2;
|
||||
_x = random8(_window->width);
|
||||
_step = 0;
|
||||
_color = CHSV(random8(), 255, 255);
|
||||
_frequency = random16(6<<8, 30<<8);
|
||||
_color_frequency = random16(128, 2<<8);
|
||||
_x = random16(1<<8, (_window->width-2)<<8);
|
||||
accum88 diff = (_window->width<<8) - _x;
|
||||
if (_x > diff) diff=_x;
|
||||
_amplitude = random16(1<<8, diff);
|
||||
_offset = random16();
|
||||
}
|
||||
|
||||
void SinesEffectSinus::loop() {
|
||||
_value += _frequency;
|
||||
if ((_value == 0 || _value==128) && random8(16)==0) {
|
||||
int8_t sign = _value == 0 ? -1 : +1;
|
||||
if (_x > 200) sign = -1;
|
||||
else if (_x >= _window->width) sign = 1;
|
||||
_amplitude = random(3)+2;
|
||||
_frequency = random8(40)+8;
|
||||
_color = CHSV(random8(), 255, 255);
|
||||
_x = _x - sign*_amplitude;
|
||||
}
|
||||
uint8_t x = _x + ((sin8(_value) - 128) * _amplitude / 128);
|
||||
_window->setPixel(x, 0, &_color);
|
||||
void SinesEffectSinus::loop(uint16_t ms) {
|
||||
accum88 x = beatsin88(_frequency, _x-_amplitude, _x+_amplitude, _offset);
|
||||
CRGB color = CHSV(beat88(_color_frequency, _offset)>>8, 255, 255);
|
||||
_window->setSubPixel(x, 0, &color);
|
||||
}
|
||||
|
||||
SinesEffect::SinesEffect() {
|
||||
for (int i=0; i<EFFECT_SINES_COUNT; i++) {
|
||||
_init();
|
||||
}
|
||||
|
||||
void SinesEffect::_init() {
|
||||
_count = settings.effects.sines.count;
|
||||
_sinus = new SinesEffectSinus*[_count];
|
||||
for (int i=0; i<_count; i++) {
|
||||
_sinus[i] = new SinesEffectSinus(window);
|
||||
}
|
||||
}
|
||||
|
||||
SinesEffect::~SinesEffect() {
|
||||
for (int i=0; i<EFFECT_SINES_COUNT; i++) { delete _sinus[i]; }
|
||||
_delete();
|
||||
}
|
||||
|
||||
void SinesEffect::_delete() {
|
||||
for (int i=0; i<_count; i++) {
|
||||
delete _sinus[i];
|
||||
}
|
||||
delete [] _sinus;
|
||||
}
|
||||
|
||||
boolean SinesEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SinesEffect::loop() {
|
||||
void SinesEffect::loop(uint16_t ms) {
|
||||
if (settings.effects.sines.count != _count) {
|
||||
_delete();
|
||||
_init();
|
||||
}
|
||||
// do stuff
|
||||
if (_step++ % 4) return; // Skip 3 out of 4 steps.
|
||||
window->shift_down_and_blur();
|
||||
for (int i=0; i<EFFECT_SINES_COUNT; i++) {
|
||||
_sinus[i]->loop();
|
||||
for (int i=0; i<_count; i++) {
|
||||
_sinus[i]->loop(ms);
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ SnakeEffect::~SnakeEffect() {
|
||||
delete window;
|
||||
}
|
||||
|
||||
void SnakeEffect::loop() {
|
||||
if (run++ % EFFECT_SNAKE_SLOWDOWN == 0) { // Change the coordinates only on every n-th run.
|
||||
if (random8(EFFECT_SNAKE_DIRECTION_CHANGE)==0 || is_turn_needed()) turn_random();
|
||||
void SnakeEffect::loop(uint16_t ms) {
|
||||
if (run++ % settings.effects.snake.slowdown == 0) { // Change the coordinates only on every n-th run.
|
||||
if (random8(settings.effects.snake.direction_change)==0 || is_turn_needed()) turn_random();
|
||||
|
||||
this->coords = update_position(this->coords, this->direction);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ StaticEffect::StaticEffect(CRGB col) {
|
||||
color = col;
|
||||
}
|
||||
|
||||
void StaticEffect::loop() {
|
||||
void StaticEffect::loop(uint16_t ms) {
|
||||
EVERY_N_SECONDS(1) {
|
||||
window->clear(&color);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
boolean TwirlEffect::can_be_shown_with_clock() { return true; };
|
||||
boolean TwirlEffect::clock_as_mask() { return true; };
|
||||
|
||||
void TwirlEffect::loop() {
|
||||
void TwirlEffect::loop(uint16_t ms) {
|
||||
double center_x = _real_center_x; // - (cos8(_center_offset_angle)>>6);
|
||||
double center_y = _real_center_y; // + (sin8(_center_offset_angle)>>6);
|
||||
for (int x=0; x<window->width; x++) for (int y=0; y<window->height; y++) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "effects.h"
|
||||
#include "config.h"
|
||||
#include "my_fastled.h"
|
||||
#include <ErriezCRC32.h>
|
||||
#include "effect_bell.h"
|
||||
#include "effect_sinematrix3.h"
|
||||
#include "effect_big_clock.h"
|
||||
@ -27,41 +27,50 @@ Effect* current_effect;
|
||||
|
||||
ClockEffect effect_clock;
|
||||
|
||||
Effect* select_effect(uint32_t code) {
|
||||
switch (code) {
|
||||
// use e.g. https://crccalc.com/ for the conversion of name to crc.
|
||||
case 0: case 0xD682E3C8 /* sinematrix3 */ : return new Sinematrix3Effect();
|
||||
case 1: case 0x90A887DA /* big_clock */ : return new BigClockEffect();
|
||||
case 2: case 0xBE7BBE92 /* clock */ : return new ClockEffect();
|
||||
case 3: case 0x733BE087 /* bell */ : return new BellEffect(); //(new AnimationEffect("/bell.pia", 0x000000, 0, 0))->setFgColor(0xFFFF00);
|
||||
case 4: case 0x2BBC5D43 /* off */ : return new StaticEffect(0x000000);
|
||||
case 5: case 0x1D84F231 /* koopa */ : return new AnimationEffect("/koopa.pia", CRGB(0x000000), 0, 0);
|
||||
case 6: case 0xAC43BCF1 /* couple_rain */ : return new AnimationEffect("/couple_rain.pia", CRGB(0x000000), -8, -16);
|
||||
case 7: case 0xF1B117F7 /* single_dynamic */ : return new SingleDynamicEffect();
|
||||
case 8: case 0xF52F2804 /* multi_dynamic */ : return new MultiDynamicEffect();
|
||||
case 9: case 0xF83341CF /* matrix */ : return new MatrixEffect();
|
||||
case 10: case 0xD2B79DD0 /* rainbow_matrix */ : return new RainbowMatrixEffect();
|
||||
case 11: case 0xE8DD3433 /* random_matrix */ : return new RandomMatrixEffect();
|
||||
case 12: case 0xB086D193 /* cycle */ : return new CycleEffect();
|
||||
case 13: case 0x2293EF9F /* twirl */ : return new TwirlEffect();
|
||||
case 14: case 0x60ECC3E6 /* heart */ : return new AnimationEffect("/heart.pia", CRGB(0x000000), 0, 0);
|
||||
case 15: case 0x42090A49 /* confetti */ : return new ConfettiEffect();
|
||||
case 16: case 0x516D6B9E /* snake */ : return new SnakeEffect();
|
||||
case 17: case 0x58DE09CF /* fire */ : return new FireEffect();
|
||||
case 18: case 0x08BA9C08 /* firework */ : return new FireworkEffect();
|
||||
case 19: case 0x14B85EAC /* gol */ : return new GolEffect();
|
||||
case 20: case 0xFA13015D /* cake */ : return new AnimationEffect("/cake.pia", CRGB(0x000000), 0, 0);
|
||||
case 21: case 0xA2B0D68B /* pixel_clock */ : return new PixelClockEffect();
|
||||
case 22: case 0x2C0E6962 /* big_dynamic */ : return new BigDynamicEffect();
|
||||
case 23: case 0xDA6F31A5 /* random_confetti */ : return new RandomConfettiEffect();
|
||||
case 24: case 0x8325C1DF /* dvd */ : return new DvdEffect();
|
||||
case 25: case 0x8CA97519 /* analog_clock */ : return new AnalogClockEffect();
|
||||
case 26: case 0xADB18CC5 /* sines */ : return new SinesEffect();
|
||||
case 27: case 0x0407881E /* blur2d */ : return new Blur2DEffect();
|
||||
case 28: case 0x935CFA7C /* marquee */ : return new MarqueeEffect();
|
||||
case 29: case 0xE27D739E /* night_clock */ : return new NightClockEffect();
|
||||
default : return NULL;
|
||||
};
|
||||
const EffectEntry effects[] = {
|
||||
/* 0 */ {"sinematrix3", true, [](){ return new Sinematrix3Effect(); }},
|
||||
/* 1 */ {"big_clock", true, [](){ return new BigClockEffect(); }},
|
||||
/* 2 */ {"clock", false, [](){ return new ClockEffect(); }},
|
||||
/* 3 */ {"bell", false, [](){ return new BellEffect(); }},
|
||||
/* 4 */ {"off", false, [](){ return new StaticEffect(0x000000); }},
|
||||
/* 5 */ {"single_dynamic", true, [](){ return new SingleDynamicEffect(); }},
|
||||
/* 6 */ {"multi_dynamic", true, [](){ return new MultiDynamicEffect(); }},
|
||||
/* 7 */ {"big_dynamic", true, [](){ return new BigDynamicEffect(); }},
|
||||
/* 8 */ {"matrix", true, [](){ return new MatrixEffect(); }},
|
||||
/* 9 */ {"random_matrix", true, [](){ return new RandomMatrixEffect(); }},
|
||||
/* 10 */ {"rainbow_matrix", true, [](){ return new RainbowMatrixEffect(); }},
|
||||
/* 11 */ {"cycle", false, [](){ return new CycleEffect(); }},
|
||||
/* 12 */ {"twirl", true, [](){ return new TwirlEffect(); }},
|
||||
/* 13 */ {"confetti", true, [](){ return new ConfettiEffect(); }},
|
||||
/* 14 */ {"random_confetti", true, [](){ return new RandomConfettiEffect(); }},
|
||||
/* 15 */ {"snake", true, [](){ return new SnakeEffect(); }},
|
||||
/* 16 */ {"firework", true, [](){ return new FireworkEffect(); }},
|
||||
/* 17 */ {"gol", true, [](){ return new GolEffect(); }},
|
||||
/* 18 */ {"pixel_clock", false, [](){ return new PixelClockEffect(); }},
|
||||
/* 19 */ {"dvd", false, [](){ return new DvdEffect(); }},
|
||||
/* 20 */ {"analog_clock", false, [](){ return new AnalogClockEffect(); }},
|
||||
/* 21 */ {"sines", true, [](){ return new SinesEffect(); }},
|
||||
/* 22 */ {"blur2d", true, [](){ return new Blur2DEffect(); }},
|
||||
/* 23 */ {"marquee", 0, [](){ return new MarqueeEffect(); }},
|
||||
/* 24 */ {"night_clock", false, [](){ return new NightClockEffect(); }}
|
||||
};
|
||||
const uint8_t effects_size = 25;
|
||||
|
||||
|
||||
Effect* select_effect(const char* name) {
|
||||
for(int i=0; i<effects_size; i++) {
|
||||
if (strcmp(effects[i].name, name)==0) {
|
||||
return effects[i].create();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Effect* select_effect(uint8_t id) {
|
||||
if (id < effects_size) {
|
||||
return effects[id].create();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool change_current_effect(String payload) {
|
||||
@ -74,7 +83,7 @@ bool change_current_effect(String payload) {
|
||||
LOGln("Effects * Cleaned effect name: %s", payload.c_str());
|
||||
}
|
||||
|
||||
Effect* new_effect = select_effect( crc32String(payload.c_str()) );
|
||||
Effect* new_effect = select_effect( payload.c_str() );
|
||||
if (new_effect == NULL) {
|
||||
LOGln("Effects * Could not find effect with name %s", payload.c_str());
|
||||
return false;
|
||||
@ -101,21 +110,6 @@ bool change_current_effect(String payload) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* cycle_effects[] = {
|
||||
"sinematrix3",
|
||||
"single_dynamic", "multi_dynamic", "big_dynamic",
|
||||
"matrix", "rainbow_matrix", "random_matrix",
|
||||
"confetti", "random_confetti",
|
||||
"snake",
|
||||
"gol",
|
||||
"twirl",
|
||||
"sines",
|
||||
"blur2d",
|
||||
"firework",
|
||||
"big_clock",
|
||||
"dvd"};
|
||||
uint8_t cycle_effects_count = 17;
|
||||
|
||||
void setup_effects() {
|
||||
current_effect = new CycleEffect();
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ void http_server_setup() {
|
||||
PGM_P text_plain = PSTR("text/plain");
|
||||
http_server.on("/", HTTP_GET, [&](){
|
||||
LOGln("HTTP * GET /");
|
||||
String message = "<html><head><title>Pitrix</title></head><body><h1>Pitrix</h1><p>Known animations:</p>";
|
||||
String message = "<html><head><title>Pitrix</title></head><body><h1>Pitrix</h1><a href='/settings'>Settings</a><p>Known animations:</p>";
|
||||
if (!SPIFFS.begin()) {
|
||||
message += "<strong>No SPIFFS file system found.</strong>";
|
||||
} else {
|
||||
@ -57,6 +57,32 @@ void http_server_setup() {
|
||||
message += "</body></html>";
|
||||
http_server.send(200, "text/html", message);
|
||||
});
|
||||
http_server.on("/settings", HTTP_GET, [&]() {
|
||||
String message = "<html><head><title>Pitrix settings</title></head><body><h1>Pitrix settings</h1><a href='/'>Back to main page</a><table>";
|
||||
for (int i=0; i<all_settings_size; i++) {
|
||||
message += "<tr><td>";
|
||||
message += all_settings[i].name;
|
||||
message += "</td><td>";
|
||||
message += *all_settings[i].value;
|
||||
message += "</td></tr>";
|
||||
}
|
||||
message += "</table></body></html>";
|
||||
http_server.send(200, "text/html", message);
|
||||
});
|
||||
http_server.on("/settings", HTTP_POST, [&]() {
|
||||
if (!http_server.hasArg("key") || !http_server.hasArg("value")) {
|
||||
http_server.send(400, "text/plain", "Missing argument.");
|
||||
return;
|
||||
}
|
||||
String name = http_server.arg("key");
|
||||
uint16_t value = http_server.arg("value").toInt();
|
||||
|
||||
if (change_setting(name.c_str(), value)) {
|
||||
http_server.send(200, "text/plain", "OK");
|
||||
} else {
|
||||
http_server.send(400, "text/plain", "Could not change setting.");
|
||||
}
|
||||
});
|
||||
http_server.on("/delete", HTTP_GET, [&]() {
|
||||
LOGln("HTTP * GET /delete");
|
||||
if (http_server.args()==0) {
|
||||
|
@ -71,10 +71,15 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) {
|
||||
tests::run();
|
||||
return;
|
||||
}
|
||||
|
||||
long value = payload.toInt();
|
||||
LOGln("MQTT * Payload as number: %d", value);
|
||||
|
||||
if (topic.compareTo("brightness")==0) {
|
||||
if (topic.startsWith("settings.")) {
|
||||
topic.remove(0, 9);
|
||||
change_setting(topic.c_str(), value);
|
||||
return;
|
||||
} else if (topic.compareTo("brightness")==0) {
|
||||
if (value > 0 && value <= 255) {
|
||||
LOGln("MQTT * Changing brightness...");
|
||||
FastLED.setBrightness(value);
|
||||
|
@ -16,6 +16,7 @@ int loop_timeouts = 0;
|
||||
long loop_started_at = 0;
|
||||
uint8_t baseHue = 0; // defined as extern in prototypes.h
|
||||
char hostname[30]; // defined as extern in prototypes.h
|
||||
unsigned long _last_effect_loop_finished_at = 0;
|
||||
#ifdef RECORDER_ENABLE
|
||||
Recorder* recorder;
|
||||
#endif
|
||||
@ -87,9 +88,20 @@ void loop() {
|
||||
}
|
||||
|
||||
EVERY_N_MILLISECONDS(1000 / FPS) {
|
||||
//LOGln("Core * loop running");
|
||||
current_effect->loop();
|
||||
//LOGln("Core * loop ran");
|
||||
// Calculate the delay since the last time loop() was called.
|
||||
// This way, the effect can handle varying frame rates.
|
||||
uint16_t last_loop_ago;
|
||||
unsigned long now = millis();
|
||||
if (now > _last_effect_loop_finished_at && _last_effect_loop_finished_at) {
|
||||
last_loop_ago = now - _last_effect_loop_finished_at;
|
||||
} else {
|
||||
last_loop_ago = 0;
|
||||
}
|
||||
|
||||
current_effect->loop(last_loop_ago);
|
||||
|
||||
// Save the time for the next run.
|
||||
_last_effect_loop_finished_at = now;
|
||||
|
||||
if (current_effect->can_be_shown_with_clock()) {
|
||||
effect_clock.loop_with_invert(current_effect->clock_as_mask());
|
||||
|
@ -36,7 +36,7 @@ Recorder::Recorder() {
|
||||
LOGln("Recorder * Sending data to port %d", _client_port);
|
||||
}
|
||||
} else if (*(char*)data == 'E') {
|
||||
String effect = String(((char*)(data+1)));
|
||||
String effect = String((char*)data+1);
|
||||
LOGln("Recorder * Setting effect %s", effect.c_str());
|
||||
Window::getFullWindow()->clear();
|
||||
change_current_effect(effect);
|
||||
|
74
src/settings.cpp
Normal file
74
src/settings.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "settings.h"
|
||||
#include "config.h"
|
||||
|
||||
Settings settings;
|
||||
|
||||
Setting all_settings[] = {
|
||||
{"fps", &settings.fps, TYPE_UINT8},
|
||||
|
||||
{"effects.confetti.pixels_per_loop", &settings.effects.confetti.pixels_per_loop, TYPE_UINT8},
|
||||
|
||||
{"effects.cycle.random", &settings.effects.cycle.random, TYPE_BOOL},
|
||||
{"effects.cycle.time", &settings.effects.cycle.time, TYPE_UINT16},
|
||||
|
||||
{"effects.dvd.width", &settings.effects.dvd.width, TYPE_UINT8},
|
||||
{"effects.dvd.height", &settings.effects.dvd.height, TYPE_UINT8},
|
||||
{"effects.dvd.speed", &settings.effects.dvd.speed, TYPE_UINT8},
|
||||
|
||||
{"effects.dynamic.single_loop_time", &settings.effects.dynamic.single_loop_time, TYPE_UINT16},
|
||||
{"effects.dynamic.multi_loop_time", &settings.effects.dynamic.multi_loop_time, TYPE_UINT16},
|
||||
{"effects.dynamic.big_loop_time", &settings.effects.dynamic.big_loop_time, TYPE_UINT16},
|
||||
{"effects.dynamic.big_size", &settings.effects.dynamic.big_size, TYPE_UINT8},
|
||||
|
||||
{"effects.fire.cooldown", &settings.effects.fire.cooldown, TYPE_UINT8},
|
||||
{"effects.fire.spark_chance", &settings.effects.fire.spark_chance, TYPE_UINT8},
|
||||
|
||||
{"effects.firework.drag", &settings.effects.firework.drag, TYPE_UINT8},
|
||||
{"effects.firework.bounce", &settings.effects.firework.bounce, TYPE_UINT8},
|
||||
{"effects.firework.gravity", &settings.effects.firework.gravity, TYPE_UINT8},
|
||||
{"effects.firework.sparks", &settings.effects.firework.sparks, TYPE_UINT8},
|
||||
|
||||
{"effects.gol.start_percentage", &settings.effects.gol.start_percentage, TYPE_UINT8},
|
||||
{"effects.gol.blend_speed", &settings.effects.gol.blend_speed, TYPE_UINT8},
|
||||
{"effects.gol.restart_after_steps", &settings.effects.gol.restart_after_steps, TYPE_UINT8},
|
||||
|
||||
{"effects.matrix.length_min", &settings.effects.matrix.length_min, TYPE_UINT8},
|
||||
{"effects.matrix.length_max", &settings.effects.matrix.length_max, TYPE_UINT8},
|
||||
{"effects.matrix.speed_min", &settings.effects.matrix.speed_min, TYPE_UINT8},
|
||||
{"effects.matrix.speed_max", &settings.effects.matrix.speed_max, TYPE_UINT8},
|
||||
|
||||
{"effects.sines.count", &settings.effects.sines.count, TYPE_UINT8},
|
||||
|
||||
{"effects.snake.direction_change", &settings.effects.snake.direction_change, TYPE_UINT8}
|
||||
};
|
||||
|
||||
const uint8_t all_settings_size = 25;
|
||||
|
||||
bool change_setting(const char* key, uint16_t new_value) {
|
||||
LOGln("Settings * Trying to set setting %s to new value %d...", key, new_value);
|
||||
Setting* s = NULL;
|
||||
for (uint8_t i=0; i<all_settings_size; i++) {
|
||||
if (strcmp(key, all_settings[i].name)==0) {
|
||||
s = &all_settings[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s==NULL) {
|
||||
LOGln("Settings * No setting matching the name %s found.", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check data size
|
||||
if (s->type == TYPE_BOOL && new_value > 1) {
|
||||
LOGln("Settings * Data type of %s is boolean, but new value is > 1.", key);
|
||||
return false;
|
||||
}
|
||||
if (s->type == TYPE_UINT8 && new_value>0xFF) {
|
||||
LOGln("Settings * Data type of %s is uint8_t, but new value is > 0xFF.", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
*(s->value) = new_value;
|
||||
LOGln("Settings * Success. New value for %s is %d.", key, new_value);
|
||||
return true;
|
||||
}
|
@ -11,15 +11,18 @@ namespace tests {
|
||||
int i=0;
|
||||
Effect* effect;
|
||||
int32_t diffs[3] = {0, 0, 0};
|
||||
String effect_name;
|
||||
while (1) {
|
||||
for (int j=0; j<3; j++) {
|
||||
int free_at_start = ESP.getFreeHeap();
|
||||
effect = select_effect(i);
|
||||
effect->loop(1);
|
||||
if (effect == NULL) return;
|
||||
effect_name = effect->get_name();
|
||||
delete effect;
|
||||
diffs[i] = ESP.getFreeHeap() - free_at_start;
|
||||
}
|
||||
LOGln("Tests * Memory leakage of effect #%d: %d, %d, %d", i, diffs[0], diffs[1], diffs[2]);
|
||||
LOGln("Tests * Memory leakage of effect %s: %d, %d, %d", effect_name.c_str(), diffs[0], diffs[1], diffs[2]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user