Compare commits
12 Commits
cb4afa5043
...
5b70511570
Author | SHA1 | Date | |
---|---|---|---|
5b70511570 | |||
77fdba213a | |||
ead076f9a3 | |||
82fbc7be43 | |||
90c0df093e | |||
26df11fc47 | |||
0163bbef6c | |||
9eeb4b50fd | |||
d2c0268dce | |||
e897c6bdcd | |||
f1821b0b85 | |||
41af01ee0b |
@ -41,7 +41,7 @@ protected:
|
||||
unsigned long currentFrameSince;
|
||||
uint8_t currentFrame = 0;
|
||||
uint8_t* animation_data;
|
||||
CRGB** _colors;
|
||||
CRGB** _colors = NULL;
|
||||
CRGB* fgColor = NULL;
|
||||
CRGB* bgColor = new CRGB(0x000000);
|
||||
int8_t xOffset = 0;
|
||||
@ -51,22 +51,22 @@ protected:
|
||||
Window* _window;
|
||||
uint8_t _width;
|
||||
uint8_t _height;
|
||||
uint8_t _frame_count;
|
||||
uint8_t _color_count;
|
||||
uint16_t* _frame_times;
|
||||
uint16_t* _frame_data_lengths;
|
||||
uint8_t** _frame_data;
|
||||
uint8_t _frame_count = 0;
|
||||
uint8_t _color_count = 0;
|
||||
uint16_t* _frame_times = NULL;
|
||||
uint16_t* _frame_data_lengths = NULL;
|
||||
uint8_t** _frame_data = NULL;
|
||||
bool _data_valid = false;
|
||||
|
||||
virtual CRGB* getColor(uint8_t color_index);
|
||||
|
||||
|
||||
void drawPixel(int index, CRGB* color);
|
||||
uint16_t getFrameDelay(int frame);
|
||||
bool _load_from_file(const char* c);
|
||||
public:
|
||||
Animation(const char* filename, Window* win);
|
||||
void setFgColor(CRGB*);
|
||||
void setBgColor(CRGB* bg_color);
|
||||
void setFgColor(uint32_t c);
|
||||
void setBgColor(uint32_t c);
|
||||
bool invert();
|
||||
void setOffsets(int8_t x, int8_t y);
|
||||
void setStartFrame(uint8_t sf);
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
void setWindow(Window* win) {
|
||||
window = win;
|
||||
};
|
||||
virtual void apply_option(String key, String value) {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@ public:
|
||||
const uint8_t width, height;
|
||||
uint16_t count;
|
||||
static Window* getFullWindow();
|
||||
|
||||
|
||||
Window(): Window(0, 0, LED_WIDTH, LED_HEIGHT) {};
|
||||
Window(uint8_t x, uint8_t y) : Window(x, y, LED_WIDTH-x, LED_HEIGHT-y) {};
|
||||
Window(uint8_t x, uint8_t y, uint8_t width, uint8_t height) : x(x), y(y), width(width), height(height) { count = width*height; };
|
||||
@ -18,6 +18,7 @@ public:
|
||||
void clear(CRGB* color);
|
||||
void setPixel(uint8_t x, uint8_t y, CRGB* color);
|
||||
void setPixelByIndex(uint16_t index, CRGB* color);
|
||||
void raisePixel(uint8_t x, uint8_t y, CRGB* color);
|
||||
void line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, CRGB* color);
|
||||
void lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t length, CRGB* color);
|
||||
void lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t startdist, uint8_t length, CRGB* color);
|
||||
|
@ -56,6 +56,8 @@
|
||||
|
||||
#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
|
||||
|
||||
#define EFFECT_CONFETTI_PIXELS_PER_LOOP 2
|
||||
|
||||
@ -73,6 +75,9 @@
|
||||
#define EFFECT_GOL_BLEND_SPEED 10
|
||||
#define EFFECT_GOL_RESTART_AFTER_STEPS 100
|
||||
|
||||
#define EFFECT_DVD_WIDTH 3
|
||||
#define EFFECT_DVD_HEIGHT 2
|
||||
|
||||
// Stop editing here
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -8,13 +8,13 @@
|
||||
class AnimationEffect : public Effect {
|
||||
private:
|
||||
Animation *animation;
|
||||
CRGB *bg_color;
|
||||
uint16_t xOffset;
|
||||
uint16_t yOffset;
|
||||
public:
|
||||
AnimationEffect(const char* name) : AnimationEffect(name, new CRGB(0x000000), 0, 0) {}
|
||||
AnimationEffect(const char* name, CRGB* background_color) : AnimationEffect(name, background_color, 0, 0) {}
|
||||
AnimationEffect(const char* name, CRGB* bg_color, int x, int y);
|
||||
AnimationEffect(const char* name) : AnimationEffect(name, 0x000000, 0, 0) {}
|
||||
AnimationEffect(const char* name, uint32_t bg_color) : AnimationEffect(name, bg_color, 0, 0) {}
|
||||
AnimationEffect(const char* name, uint32_t bg_color, int x, int y);
|
||||
~AnimationEffect();
|
||||
AnimationEffect* setFgColor(uint32_t c);
|
||||
void loop();
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ private:
|
||||
Window* window = new Window(0, LED_HEIGHT - 6, LED_WIDTH, 6);
|
||||
|
||||
public:
|
||||
~ClockEffect();
|
||||
void loop();
|
||||
void loop(boolean invert, CRGB fg_color, CRGB bg_color);
|
||||
};
|
||||
|
@ -5,8 +5,16 @@
|
||||
#include "my_fastled.h"
|
||||
|
||||
class ConfettiEffect : public Effect {
|
||||
protected:
|
||||
virtual CRGB _getColor();
|
||||
public:
|
||||
void loop();
|
||||
boolean can_be_shown_with_clock();
|
||||
};
|
||||
|
||||
class RandomConfettiEffect : public ConfettiEffect {
|
||||
protected:
|
||||
CRGB _getColor() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
17
include/effect_dvd.h
Normal file
17
include/effect_dvd.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "Effect.h"
|
||||
|
||||
class DvdEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
uint8_t _x = 0;
|
||||
uint8_t _y = 0;
|
||||
int8_t _x_dir = 1;
|
||||
int8_t _y_dir = 1;
|
||||
CRGB _color;
|
||||
public:
|
||||
DvdEffect();
|
||||
~DvdEffect();
|
||||
void loop() override;
|
||||
bool can_be_shown_with_clock() override;
|
||||
};
|
@ -21,3 +21,11 @@ class MultiDynamicEffect : public SingleDynamicEffect {
|
||||
public:
|
||||
void loop();
|
||||
};
|
||||
|
||||
class BigDynamicEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
public:
|
||||
void loop();
|
||||
~BigDynamicEffect();
|
||||
};
|
||||
|
@ -9,16 +9,23 @@
|
||||
class MatrixEffectColumn {
|
||||
protected:
|
||||
Window* window;
|
||||
int x, y;
|
||||
int length = 1;
|
||||
uint8_t x, y;
|
||||
uint8_t length = 1;
|
||||
uint8_t _direction = 2;
|
||||
bool _random_direction = false;
|
||||
virtual CRGB _getColor(uint8_t height);
|
||||
virtual void restart();
|
||||
virtual void restart(bool completely_random);
|
||||
private:
|
||||
uint16_t speed;
|
||||
boolean running;
|
||||
unsigned long last_move = 0;
|
||||
public:
|
||||
MatrixEffectColumn(Window* win, int xPos);
|
||||
static const uint8_t DIR_NORTH = 0;
|
||||
static const uint8_t DIR_EAST = 1;
|
||||
static const uint8_t DIR_SOUTH = 2;
|
||||
static const uint8_t DIR_WEST = 3;
|
||||
|
||||
MatrixEffectColumn(Window* win, uint8_t direction=0, bool random_direction=false);
|
||||
virtual ~MatrixEffectColumn() {};
|
||||
void advance();
|
||||
void draw();
|
||||
@ -29,16 +36,16 @@ class RainbowMatrixEffectColumn : public MatrixEffectColumn {
|
||||
protected:
|
||||
CRGB _getColor(uint8_t height) override;
|
||||
public:
|
||||
RainbowMatrixEffectColumn(Window* win, int xPos) : MatrixEffectColumn(win, xPos) {};
|
||||
RainbowMatrixEffectColumn(Window* win, uint8_t dir, bool rnd=false) : MatrixEffectColumn(win, dir, rnd) {};
|
||||
};
|
||||
|
||||
class RandomMatrixEffectColumn : public MatrixEffectColumn {
|
||||
protected:
|
||||
uint8_t _hue = 42;
|
||||
CRGB _getColor(uint8_t height) override;
|
||||
void restart() override;
|
||||
void restart(bool completely_random) override;
|
||||
public:
|
||||
RandomMatrixEffectColumn(Window* win, int xPos) : MatrixEffectColumn(win, xPos) {};
|
||||
RandomMatrixEffectColumn(Window* win, uint8_t dir, bool rnd=false) : MatrixEffectColumn(win, dir, rnd) {};
|
||||
};
|
||||
|
||||
class MatrixEffect : public Effect {
|
||||
|
@ -17,6 +17,7 @@ private:
|
||||
bool is_direction_okay(uint8_t direction);
|
||||
public:
|
||||
SnakeEffect();
|
||||
~SnakeEffect();
|
||||
void loop();
|
||||
boolean valid_position(Coords c);
|
||||
Coords update_position(Coords c, uint8_t direction);
|
||||
|
@ -11,7 +11,7 @@ extern uint8_t cycle_effects_count;
|
||||
extern Effect* current_effect;
|
||||
extern ClockEffect effect_clock;
|
||||
|
||||
Effect* string_to_effect(String s);
|
||||
Effect* select_effect(uint32_t c);
|
||||
bool change_current_effect(String s);
|
||||
void setup_effects();
|
||||
|
||||
|
6
include/tests.h
Normal file
6
include/tests.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
namespace tests {
|
||||
void run();
|
||||
void test_effects_for_memory_leaks();
|
||||
}
|
@ -143,7 +143,7 @@ bool Animation::_load_from_file(const char* filename) {
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
|
||||
LOGln("Animation * Loading completed successfully.");
|
||||
|
||||
return true;
|
||||
@ -160,12 +160,14 @@ Animation::Animation(const char* filename, Window* win) {
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::setFgColor(CRGB* fg_color) {
|
||||
this->fgColor = fg_color;
|
||||
void Animation::setFgColor(uint32_t c) {
|
||||
if (this->fgColor) delete this->fgColor;
|
||||
this->fgColor = new CRGB(c);
|
||||
}
|
||||
|
||||
void Animation::setBgColor(CRGB* bg_color) {
|
||||
this->bgColor = bg_color;
|
||||
void Animation::setBgColor(uint32_t c) {
|
||||
if (this->bgColor) delete this->bgColor;
|
||||
this->bgColor = new CRGB(c);
|
||||
}
|
||||
|
||||
bool Animation::invert() {
|
||||
@ -205,15 +207,27 @@ void Animation::setSingleFrame(uint8_t frame) {
|
||||
|
||||
Animation::~Animation() {
|
||||
for (int i=0; i<_color_count; i++) delete _colors[i];
|
||||
delete [] _colors;
|
||||
if (fgColor) delete fgColor;
|
||||
delete bgColor;
|
||||
delete [] _frame_data_lengths;
|
||||
delete [] _frame_times;
|
||||
LOGln("Deleting _colors...");
|
||||
if (_colors) delete [] _colors;
|
||||
LOGln("Deleting fgColor...");
|
||||
|
||||
if (fgColor != NULL) delete fgColor;
|
||||
LOGln("Deleting bgColor...");
|
||||
|
||||
if (bgColor != NULL) delete bgColor;
|
||||
LOGln("Deleting _frame_data_lengths...");
|
||||
|
||||
if (_frame_data_lengths) delete [] _frame_data_lengths;
|
||||
LOGln("Deleting _frame_times...");
|
||||
|
||||
if (_frame_times) delete [] _frame_times;
|
||||
for (int i=0; i<_frame_count; i++) {
|
||||
delete [] _frame_data[i];
|
||||
}
|
||||
delete [] _frame_data;
|
||||
LOGln("Deleting _frame_data...");
|
||||
|
||||
if (_frame_data) delete [] _frame_data;
|
||||
LOGln("Deleteion done.");
|
||||
}
|
||||
|
||||
void Animation::draw() {
|
||||
@ -230,7 +244,7 @@ void Animation::drawFrame(uint8_t frame_index) {
|
||||
CRGB red(0xFF0000);
|
||||
CRGB black(0x000000);
|
||||
for (int x=0; x<_window->width; x++) for (int y=0; y<_window->height; y++) {
|
||||
_window->setPixel(x, y, (y*_window->width+x) % 2 ? &red : &black);
|
||||
_window->setPixel(x, y, (y*_window->width+x + y) % 2 ? &red : &black);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -11,6 +11,11 @@ void Window::setPixel(uint8_t x, uint8_t y, CRGB* color) {
|
||||
leds[this->coordsToGlobalIndex(x, y)] = *color;
|
||||
}
|
||||
|
||||
void Window::raisePixel(uint8_t x, uint8_t y, CRGB* color) {
|
||||
if (x>=this->width || y>=this->height) return;
|
||||
leds[this->coordsToGlobalIndex(x, y)] |= *color;
|
||||
}
|
||||
|
||||
void Window::setPixelByIndex(uint16_t index, CRGB* color) {
|
||||
uint8_t x = index % this->width;
|
||||
uint8_t y = index / this->width;
|
||||
@ -69,7 +74,7 @@ void Window::line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, CRGB* color) {
|
||||
int8_t sy = y1<y2 ? 1 : -1;
|
||||
int16_t err = dx + dy;
|
||||
int16_t e2;
|
||||
|
||||
|
||||
while (1) {
|
||||
setPixel(x1, y1, color);
|
||||
if (x1==x2 && y1==y2) break;
|
||||
@ -86,12 +91,12 @@ void Window::circle(uint8_t x0, uint8_t y0, uint8_t radius, CRGB* color) {
|
||||
int16_t ddF_y = -2 * radius;
|
||||
uint8_t x = 0;
|
||||
uint8_t y = radius;
|
||||
|
||||
|
||||
setPixel(x0, y0 + radius, color);
|
||||
setPixel(x0, y0 - radius, color);
|
||||
setPixel(x0 + radius, y0, color);
|
||||
setPixel(x0 - radius, y0, color);
|
||||
|
||||
|
||||
while (x < y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
@ -101,12 +106,12 @@ void Window::circle(uint8_t x0, uint8_t y0, uint8_t radius, CRGB* color) {
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x + 1;
|
||||
|
||||
|
||||
setPixel(x0 + x, y0 + y, color);
|
||||
setPixel(x0 - x, y0 + y, color);
|
||||
setPixel(x0 + x, y0 - y, color);
|
||||
setPixel(x0 - x, y0 - y, color);
|
||||
|
||||
|
||||
setPixel(x0 + y, y0 + x, color);
|
||||
setPixel(x0 - y, y0 + x, color);
|
||||
setPixel(x0 + y, y0 - x, color);
|
||||
@ -121,14 +126,14 @@ void Window::lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t length,
|
||||
void Window::lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t startdist, uint8_t length, CRGB* color) {
|
||||
int16_t x1 = x;
|
||||
int16_t y1 = y;
|
||||
|
||||
|
||||
if (startdist > 0) {
|
||||
x1 = x + scale8(startdist, cos8(angle));
|
||||
y1 = y + scale8(startdist, sin8(angle));
|
||||
}
|
||||
|
||||
|
||||
int16_t x2 = x + scale8(startdist + length, cos8(angle));
|
||||
int16_t y2 = y + scale8(startdist + length, sin8(angle));
|
||||
|
||||
|
||||
line(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
@ -1,16 +1,20 @@
|
||||
#include "effect_animation.h"
|
||||
#include "functions.h"
|
||||
|
||||
AnimationEffect::AnimationEffect(const char* name, CRGB* bg, int x, int y) {
|
||||
this->bg_color = bg;
|
||||
AnimationEffect::AnimationEffect(const char* name, uint32_t bg, int x, int y) {
|
||||
this->xOffset = x;
|
||||
this->yOffset = y;
|
||||
|
||||
this->animation = new Animation(name, window);
|
||||
this->animation->setBgColor(this->bg_color);
|
||||
this->animation->setBgColor(bg);
|
||||
this->animation->setOffsets(this->xOffset, this->yOffset);
|
||||
}
|
||||
|
||||
AnimationEffect* AnimationEffect::setFgColor(uint32_t c) {
|
||||
animation->setFgColor(c);
|
||||
return this;
|
||||
}
|
||||
|
||||
AnimationEffect::~AnimationEffect() {
|
||||
delete this->animation;
|
||||
}
|
||||
|
@ -40,3 +40,7 @@ void ClockEffect::loop(boolean invert, CRGB fg_color, CRGB bg_color) {
|
||||
window->setPixel(7, 4, &fg_color);
|
||||
}
|
||||
}
|
||||
|
||||
ClockEffect::~ClockEffect() {
|
||||
delete window;
|
||||
}
|
||||
|
@ -6,9 +6,17 @@
|
||||
void ConfettiEffect::loop() {
|
||||
window->fadeToBlackBy(3);
|
||||
for (int i=0; i<EFFECT_CONFETTI_PIXELS_PER_LOOP; i++) {
|
||||
CRGB color(CHSV(baseHue + random8(64), 200, 255));
|
||||
CRGB color = _getColor();
|
||||
window->addPixelColor(random16(LED_COUNT), &color);
|
||||
}
|
||||
}
|
||||
|
||||
CRGB ConfettiEffect::_getColor() {
|
||||
return CHSV(baseHue + random8(64), 255, 255);
|
||||
}
|
||||
|
||||
CRGB RandomConfettiEffect::_getColor() {
|
||||
return CHSV(random8(), 255, 255);
|
||||
}
|
||||
|
||||
boolean ConfettiEffect::can_be_shown_with_clock() { return true; };
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "effect_cycle.h"
|
||||
#include "effects.h"
|
||||
#include <ErriezCRC32.h>
|
||||
|
||||
CycleEffect::CycleEffect() {
|
||||
changeEffect();
|
||||
@ -23,7 +24,7 @@ void CycleEffect::changeEffect() {
|
||||
if (effect) delete effect;
|
||||
LOGln("CycleEffect * Searching for new effect '%s'", cycle_effects[new_id]);
|
||||
delay(25);
|
||||
effect = string_to_effect(cycle_effects[new_id]);
|
||||
effect = select_effect( crc32String(cycle_effects[new_id]) );
|
||||
effect_id = new_id;
|
||||
effectSince = millis();
|
||||
}
|
||||
|
37
src/effect_dvd.cpp
Normal file
37
src/effect_dvd.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "effect_dvd.h"
|
||||
#include "my_fastled.h"
|
||||
|
||||
void DvdEffect::loop() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool DvdEffect::can_be_shown_with_clock() { return true; }
|
||||
|
||||
DvdEffect::DvdEffect() {
|
||||
_color = CHSV(random8(), 255, 255);
|
||||
}
|
||||
|
||||
DvdEffect::~DvdEffect() {
|
||||
delete window;
|
||||
}
|
@ -34,3 +34,28 @@ void MultiDynamicEffect::loop() {
|
||||
}
|
||||
this->draw();
|
||||
}
|
||||
|
||||
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);
|
||||
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++) {
|
||||
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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
GolEffect::GolEffect() {
|
||||
this->window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
|
||||
|
||||
_data = new uint8_t[this->window->count];
|
||||
_old = new uint8_t[this->window->count];
|
||||
for(uint16_t i=0; i<this->window->count; i++) {
|
||||
@ -26,6 +26,7 @@ void GolEffect::_initialize() {
|
||||
GolEffect::~GolEffect() {
|
||||
delete[] _data;
|
||||
delete[] _old;
|
||||
delete window;
|
||||
}
|
||||
|
||||
void GolEffect::loop() {
|
||||
@ -35,7 +36,7 @@ void GolEffect::loop() {
|
||||
} else {
|
||||
_blend += EFFECT_GOL_BLEND_SPEED;
|
||||
}
|
||||
|
||||
|
||||
_draw();
|
||||
}
|
||||
|
||||
@ -52,14 +53,14 @@ void GolEffect::_advance() {
|
||||
uint16_t changes = 0;
|
||||
for(uint8_t x=0; x<this->window->width; x++) for(uint8_t y=0; y<this->window->height; y++) {
|
||||
uint16_t index = y*w + x;
|
||||
uint8_t count =
|
||||
uint8_t count =
|
||||
(x>0 && y>0 && _old[index - w - 1]) +
|
||||
(y>0 && _old[index - w]) +
|
||||
(x<this->window->width-1 && y>0 && _old[index - w + 1]) +
|
||||
|
||||
|
||||
(x>0 && _old[index - 1]) +
|
||||
(x<this->window->width-1 && _old[index + 1]) +
|
||||
|
||||
|
||||
(x>0 && y<this->window->height-1 && _old[index + w - 1]) +
|
||||
(y<this->window->height-1 && _old[index + w]) +
|
||||
(x<this->window->width-1 && y<this->window->height-1 && _old[index + w + 1]);
|
||||
@ -79,7 +80,7 @@ void GolEffect::_advance() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (changes == 0) {
|
||||
_initialize();
|
||||
}
|
||||
|
@ -2,29 +2,80 @@
|
||||
#include "my_color_palettes.h"
|
||||
#include "functions.h"
|
||||
|
||||
MatrixEffectColumn::MatrixEffectColumn(Window* win, int xPos) {
|
||||
MatrixEffectColumn::MatrixEffectColumn(Window* win, uint8_t dir, bool rand) {
|
||||
window = win;
|
||||
x = xPos;
|
||||
restart();
|
||||
y = random8(0, window->height);
|
||||
_direction = dir;
|
||||
_random_direction = rand;
|
||||
restart(true);
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::restart() {
|
||||
y=-1;
|
||||
void MatrixEffectColumn::restart(bool completely_random) {
|
||||
if (_random_direction) {
|
||||
_direction = random8(4);
|
||||
}
|
||||
|
||||
if (completely_random) {
|
||||
x = random8(window->width);
|
||||
y = random8(window->height);
|
||||
} else {
|
||||
switch(_direction) {
|
||||
case DIR_NORTH:
|
||||
x = random8(window->width);
|
||||
y = window->height - 1;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
x = 0;
|
||||
y = random8(window->height);
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
x = random8(window->width);
|
||||
y = 0;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
x = window->width - 1;
|
||||
y = random8(window->height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
length = random8(EFFECT_MATRIX_LENGTH_MIN, EFFECT_MATRIX_LENGTH_MAX);
|
||||
running = true;
|
||||
speed = random8(EFFECT_MATRIX_SPEED_MIN, EFFECT_MATRIX_SPEED_MAX);
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::advance() {
|
||||
y++;
|
||||
if (y-length > window->height) running = false;
|
||||
switch(_direction) {
|
||||
case DIR_NORTH:
|
||||
y--;
|
||||
if (y > window->height && y + length > window->height) running=false;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
x++;
|
||||
if (x - length > window->width) running=false;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
y++;
|
||||
if (y - length > window->height) running=false;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
x--;
|
||||
if (x > window->width && y + length > window->width) running=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::draw() {
|
||||
int8_t xdir = 0;
|
||||
int8_t ydir = 0;
|
||||
switch (_direction) {
|
||||
case DIR_NORTH: ydir = 1; break;
|
||||
case DIR_EAST: xdir = 1; break;
|
||||
case DIR_SOUTH: ydir = -1; break;
|
||||
case DIR_WEST: xdir = -1; break;
|
||||
}
|
||||
for(int i=0; i<length; i++) {
|
||||
CRGB color = _getColor(i);
|
||||
window->setPixel(x, y-i, &color);
|
||||
window->raisePixel(x+(xdir*i), y+(ydir*i), &color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +83,7 @@ void MatrixEffectColumn::loop() {
|
||||
if (!running) {
|
||||
if (random8() < 20) {
|
||||
// Start the column again.
|
||||
restart();
|
||||
restart(false);
|
||||
}
|
||||
} else {
|
||||
if (millis() - last_move > speed) {
|
||||
@ -75,8 +126,8 @@ CRGB RandomMatrixEffectColumn::_getColor(uint8_t i) {
|
||||
return color;
|
||||
}
|
||||
|
||||
void RandomMatrixEffectColumn::restart() {
|
||||
MatrixEffectColumn::restart();
|
||||
void RandomMatrixEffectColumn::restart(bool completely_random) {
|
||||
MatrixEffectColumn::restart(completely_random);
|
||||
_hue = random8();
|
||||
}
|
||||
|
||||
@ -97,15 +148,15 @@ MatrixEffect::MatrixEffect() {
|
||||
}
|
||||
|
||||
void MatrixEffect::_init() {
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new MatrixEffectColumn(window, i);
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new MatrixEffectColumn(window, MatrixEffectColumn::DIR_SOUTH);
|
||||
}
|
||||
|
||||
void RandomMatrixEffect::_init() {
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RandomMatrixEffectColumn(window, i);
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RandomMatrixEffectColumn(window, random8(4), true);
|
||||
}
|
||||
|
||||
void RainbowMatrixEffect::_init() {
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RainbowMatrixEffectColumn(window, i);
|
||||
for (int i=0; i<window->width; i++) _columns[i] = new RainbowMatrixEffectColumn(window, MatrixEffectColumn::DIR_SOUTH);
|
||||
}
|
||||
|
||||
MatrixEffect::~MatrixEffect() {
|
||||
|
@ -10,6 +10,7 @@ PixelClockEffect::PixelClockEffect() {
|
||||
PixelClockEffect::~PixelClockEffect() {
|
||||
delete _color_seconds;
|
||||
delete _color_minutes;
|
||||
delete window;
|
||||
}
|
||||
|
||||
void PixelClockEffect::loop() {
|
||||
|
@ -6,6 +6,10 @@ SnakeEffect::SnakeEffect() {
|
||||
this->window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -17,46 +17,77 @@
|
||||
#include "effect_firework.h"
|
||||
#include "effect_gol.h"
|
||||
#include "effect_pixelclock.h"
|
||||
#include "effect_dvd.h"
|
||||
|
||||
Effect* current_effect;
|
||||
|
||||
ClockEffect effect_clock;
|
||||
|
||||
Effect* string_to_effect(String name) {
|
||||
uint32_t crc = crc32String(name.c_str());
|
||||
switch (crc) {
|
||||
Effect* select_effect(uint32_t code) {
|
||||
switch (code) {
|
||||
// use e.g. https://crccalc.com/ for the conversion of name to crc.
|
||||
case 0xD682E3C8 /* sinematrix3 */ : return new Sinematrix3Effect();
|
||||
case 0x90A887DA /* big_clock */ : return new BigClockEffect();
|
||||
case 0xBE7BBE92 /* clock */ : return new ClockEffect();
|
||||
case 0x733BE087 /* bell */ : return new BellEffect();
|
||||
case 0x2BBC5D43 /* off */ : return new StaticEffect(0x000000);
|
||||
case 0x1D84F231 /* koopa */ : return new AnimationEffect("/koopa.pia", new CRGB(0x000000), 0, 0);
|
||||
case 0xAC43BCF1 /* couple_rain */ : return new AnimationEffect("/couple_rain.pia", new CRGB(0x000000), -8, -16);
|
||||
case 0xF1B117F7 /* single_dynamic */ : return new SingleDynamicEffect();
|
||||
case 0xF52F2804 /* multi_dynamic */ : return new MultiDynamicEffect();
|
||||
case 0xF83341CF /* matrix */ : return new MatrixEffect();
|
||||
case 0xD2B79DD0 /* rainbow_matrix */ : return new RainbowMatrixEffect();
|
||||
case 0xE8DD3433 /* random_matrix */ : return new RandomMatrixEffect();
|
||||
case 0xB086D193 /* cycle */ : return new CycleEffect();
|
||||
case 0x2293EF9F /* twirl */ : return new TwirlEffect();
|
||||
case 0x60ECC3E6 /* heart */ : return new AnimationEffect("/heart.pia", new CRGB(0x000000), 0, 0);
|
||||
case 0x42090A49 /* confetti */ : return new ConfettiEffect();
|
||||
case 0x516D6B9E /* snake */ : return new SnakeEffect();
|
||||
case 0x58DE09CF /* fire */ : return new FireEffect();
|
||||
case 0x08BA9C08 /* firework */ : return new FireworkEffect();
|
||||
case 0x14B85EAC /* gol */ : return new GolEffect();
|
||||
case 0xFA13015D /* cake */ : return new AnimationEffect("/cake.pia", new CRGB(0x000000), 0, 0);
|
||||
case 0xA2B0D68B /* pixel_clock */ : return new PixelClockEffect();
|
||||
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();
|
||||
default : return NULL;
|
||||
};
|
||||
}
|
||||
|
||||
bool change_current_effect(String name) {
|
||||
Effect* new_effect = string_to_effect(name);
|
||||
if (new_effect == NULL) return false;
|
||||
bool change_current_effect(String payload) {
|
||||
int pos = payload.indexOf(",");
|
||||
String options = "";
|
||||
if (pos != -1) {
|
||||
LOGln("Effects * Effect comes with options.");
|
||||
options = payload.substring(pos+1);
|
||||
payload.remove(pos);
|
||||
LOGln("Effects * Cleaned effect name: %s", payload.c_str());
|
||||
}
|
||||
|
||||
Effect* new_effect = select_effect( crc32String(payload.c_str()) );
|
||||
if (new_effect == NULL) {
|
||||
LOGln("Effects * Could not find effect with name %s", payload.c_str());
|
||||
return false;
|
||||
}
|
||||
delete current_effect;
|
||||
current_effect = new_effect;
|
||||
|
||||
if (options.length() > 0) {
|
||||
LOGln("Effects * Parsing options: %s", options.c_str());
|
||||
options += ",";
|
||||
int p_colon;
|
||||
while ((p_colon = options.indexOf(",")) >= 0) {
|
||||
int p_equal = options.indexOf("=");
|
||||
if (p_equal >= 0 && p_equal < p_colon) {
|
||||
String key = options.substring(0, p_equal);
|
||||
String value = options.substring(p_equal + 1, p_colon);
|
||||
LOGln("Effects * Applying option: %s = %s", key.c_str(), value.c_str());
|
||||
current_effect->apply_option(key, value);
|
||||
}
|
||||
options.remove(0, p_colon + 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
17
src/mqtt.cpp
17
src/mqtt.cpp
@ -10,6 +10,7 @@
|
||||
#include "Effect.h"
|
||||
#include "effects.h"
|
||||
#include "functions.h"
|
||||
#include "tests.h"
|
||||
|
||||
WiFiClient wifi;
|
||||
PubSubClient mqtt_client(wifi);
|
||||
@ -57,12 +58,20 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) {
|
||||
|
||||
if(topic.compareTo("mode")==0) {
|
||||
LOGln("MQTT * Changing mode...");
|
||||
change_current_effect(payload);
|
||||
bool result = change_current_effect(payload);
|
||||
if (result) {
|
||||
LOGln("MQTT * Effect changed.");
|
||||
} else {
|
||||
LOGln("MQTT * Could not change effect.");
|
||||
}
|
||||
return;
|
||||
} else if (topic.compareTo("reboot")==0) {
|
||||
LOGln("MQTT * Rebooting");
|
||||
ESP.restart();
|
||||
return; // Will never be reached, but anyway...
|
||||
} else if (topic.compareTo("run_tests")==0) {
|
||||
tests::run();
|
||||
return;
|
||||
}
|
||||
long value = payload.toInt();
|
||||
LOGln("MQTT * Payload as number: %d", value);
|
||||
@ -81,10 +90,12 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) {
|
||||
}
|
||||
|
||||
boolean mqtt_connect() {
|
||||
LOG("MQTT * Connecting to MQTT server with client id %s", hostname);
|
||||
LOGln("MQTT * Connecting to MQTT server with client id %s", hostname);
|
||||
if (mqtt_client.connect(hostname, MQTT_USER, MQTT_PASS, MQTT_TOPIC "status", 0, true, "OFFLINE", true)) {
|
||||
LOGln("MQTT * Connected.");
|
||||
mqtt_client.publish(MQTT_TOPIC "status", "ONLINE", true);
|
||||
char buffer[40];
|
||||
snprintf(buffer, 40, "ONLINE %s %s", hostname, WiFi.localIP().toString().c_str());
|
||||
mqtt_client.publish(MQTT_TOPIC "status", buffer, true);
|
||||
mqtt_client.subscribe(MQTT_TOPIC "+");
|
||||
mqtt_client.subscribe(MQTT_TOPIC_WEATHER "#");
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <Arduino.h>
|
||||
#include <SimpleList.h>
|
||||
|
||||
#include "ntp.h"
|
||||
#include "config.h"
|
||||
@ -20,7 +19,7 @@ char hostname[30]; // defined as extern in prototypes.h
|
||||
void setup() {
|
||||
Serial.begin(74880);
|
||||
LOGln("Core * Starting");
|
||||
|
||||
|
||||
int chipid;
|
||||
#if defined( ESP8266 )
|
||||
chipid = ESP.getChipId();
|
||||
@ -28,7 +27,7 @@ void setup() {
|
||||
chipid = ESP.getEfuseMac() & 0xFFFFFF;
|
||||
#endif
|
||||
snprintf(hostname, 30, HOSTNAME, chipid);
|
||||
|
||||
|
||||
setup_effects();
|
||||
wifi_setup();
|
||||
ntp_setup();
|
||||
|
28
src/tests.cpp
Normal file
28
src/tests.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "tests.h"
|
||||
#include "effects.h"
|
||||
|
||||
namespace tests {
|
||||
void run() {
|
||||
LOGln("Tests * Running test for memory leaks...");
|
||||
test_effects_for_memory_leaks();
|
||||
}
|
||||
|
||||
void test_effects_for_memory_leaks() {
|
||||
int i=0;
|
||||
Effect* effect;
|
||||
int32_t diffs[3] = {0, 0, 0};
|
||||
int32_t usage = 0;
|
||||
while (1) {
|
||||
for (int j=0; j<3; j++) {
|
||||
int free_at_start = ESP.getFreeHeap();
|
||||
effect = select_effect(i);
|
||||
if (j==0) usage = free_at_start - ESP.getFreeHeap();
|
||||
if (effect == NULL) return;
|
||||
delete effect;
|
||||
diffs[j] = free_at_start - ESP.getFreeHeap();
|
||||
}
|
||||
LOGln("Tests * Memory usage of effect #%d: %d, leakage %d, %d, %d", i, usage, diffs[0], diffs[1], diffs[2]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user