Compare commits
24 Commits
549bce479a
...
937850c90a
Author | SHA1 | Date | |
---|---|---|---|
937850c90a | |||
b0c1bcaa65 | |||
7cbb156b66 | |||
0a7334e448 | |||
29aa47177e | |||
7ac681002e | |||
36edb94ff0 | |||
d396b68191 | |||
c1cfb693d3 | |||
34d5aa6496 | |||
781954d7f1 | |||
73b8d162c7 | |||
62549e73bf | |||
3018bc6375 | |||
1cd94ac4ae | |||
b8f39410c9 | |||
711719921a | |||
6ba2854a8d | |||
aa11f5ed8a | |||
fa5f1c8816 | |||
b5c99c320b | |||
96e144f96b | |||
792354e371 | |||
571ae26c25 |
62
README.md
@ -14,26 +14,26 @@ nice-looking LED matrix everytime you want to update the software.
|
||||
|
||||
|
||||
| Name | Description | Image |
|
||||
| -------- | -------- | -------- |
|
||||
| bell | An example for a blinking sprite. Can be used for home automation, for example. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/bell.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| big_clock | A big clock. Seconds are moving around the edge. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/big_clock.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| big_dynamic | Big squares appearing in sequential colors. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/big_dynamic.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| clock | The small clock at the bottom. Usually used by other effects to integrate a clock. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/clock.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| cycle | Meta effect: Cycles through some of the other effects. | - |
|
||||
| confetti | Random pixels lighting up in sequential colors and fading out again. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/confetti.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| dvd | The bouncing-around dvd logo we all know and love. High chance of hitting cordners because of the low resolution of the LED panel. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/dvd.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| fire | Fireplace-like effect. Needs more tweaking. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/fire.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| firework | Firework-like effect. Needs more work. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/firework.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| gol | Conway's Game of Life. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/gol.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| matrix | That green effect from The Matrix. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/matrix.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| multi_dynamic | Space is divided in 2x2 squares which are changing their color random-sequentially. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/multi_dynamic.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| pixel_clock | A clock using single pixels to display the current time. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/pixel_clock.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| rainbow_matrix | Like matrix, but not just green but displaying a rainbow across the columns. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/rainbow_matrix.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| random_matrix | Like matrix, but with random colors and random directions. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/random_matrix.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| sinematrix3 | Colorful pastel images, slowly moving about. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/sinematrix3.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| single_dynamic | 2x2 squares random-sequentially changing their color one after another. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/single_dynamic.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| snake | Snake. Without self-collision detection or AI. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/snake.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| twirl | A colorful twirl. | <img src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/twirl.gif" width="128" style="image-rendering: crisp-edges;border-radius: 0;border: 4px solid black;" /> |
|
||||
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| bell | An example for a blinking sprite. Can be used for home automation, for example. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/bell.gif" /> |
|
||||
| big_clock | A big clock. Seconds are moving around the edge. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/big_clock.gif" /> |
|
||||
| big_dynamic | Big squares appearing in sequential colors. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/big_dynamic.gif" /> |
|
||||
| clock | The small clock at the bottom. Usually used by other effects to integrate a clock. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/clock.gif" /> |
|
||||
| cycle | Meta effect: Cycles through some of the other effects. | - |
|
||||
| confetti | Random pixels lighting up in sequential colors and fading out again. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/confetti.gif" /> |
|
||||
| dvd | The bouncing-around dvd logo we all know and love. High chance of hitting cordners because of the low resolution of the LED panel. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/dvd.gif" /> |
|
||||
| fire | Fireplace-like effect. Needs more tweaking. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/fire.gif" /> |
|
||||
| firework | Firework-like effect. Needs more work. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/firework.gif" /> |
|
||||
| gol | Conway's Game of Life. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/gol.gif" /> |
|
||||
| matrix | That green effect from The Matrix. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/matrix.gif" /> |
|
||||
| multi_dynamic | Space is divided in 2x2 squares which are changing their color random-sequentially. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/multi_dynamic.gif" /> |
|
||||
| pixel_clock | A clock using single pixels to display the current time. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/pixel_clock.gif" /> |
|
||||
| rainbow_matrix | Like matrix, but not just green but displaying a rainbow across the columns. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/rainbow_matrix.gif" /> |
|
||||
| random_matrix | Like matrix, but with random colors and random directions. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/random_matrix.gif" /> |
|
||||
| sinematrix3 | Colorful pastel images, slowly moving about. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/sinematrix3.gif" /> |
|
||||
| single_dynamic | 2x2 squares random-sequentially changing their color one after another. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/single_dynamic.gif" /> |
|
||||
| snake | Snake. Without self-collision detection or AI. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/snake.gif" /> |
|
||||
| twirl | A colorful twirl. | <img width="128" height="128" src="https://git.schle.nz/fabian/pitrix/raw/branch/master/docs/effects/twirl.gif" /> |
|
||||
|
||||
|
||||
|
||||
@ -84,3 +84,25 @@ seconds:
|
||||
If you enabled HTTP server, you can always make GET requests to `/free_heap`, `/uptime` or `/fps` to get those values.
|
||||
|
||||
If you enabled `DEBUG`, log messages will be sent to `MQTT_TOPIC/log`.
|
||||
|
||||
## Aknowledgements
|
||||
|
||||
### Libraries
|
||||
|
||||
| Library | Author | Link |
|
||||
| ------- | ------ | ---- |
|
||||
| PubSubClient | knolleary | https://pubsubclient.knolleary.net/
|
||||
| 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
|
||||
* This whole project was inspired by
|
||||
https://github.com/orithena/Arduino-LED-experiments/tree/master/Ribba16x16_v2_ESP32.
|
||||
The sinematrix3 effect was also taken from there.
|
||||
* The firework effect was heavily inspired (aka copied) from
|
||||
https://gist.github.com/kriegsman/68929cbd1d6de4535b20
|
||||
* The sines effect is based upon
|
||||
https://github.com/atuline/FastLED-Demos/blob/master/sinelon/sinelon.ino
|
||||
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 190 KiB |
@ -1,5 +1,4 @@
|
||||
#ifndef Effect_H
|
||||
#define Effect_H
|
||||
#pragma once
|
||||
|
||||
#include "Window.h"
|
||||
#include "config.h"
|
||||
@ -11,6 +10,7 @@ protected:
|
||||
public:
|
||||
virtual ~Effect() {};
|
||||
virtual void loop() = 0;
|
||||
virtual String get_name() = 0;
|
||||
boolean supports_window = false;
|
||||
virtual boolean can_be_shown_with_clock() { return false; };
|
||||
virtual boolean clock_as_mask() { return false; };
|
||||
@ -20,4 +20,3 @@ public:
|
||||
virtual void apply_option(String key, String value) {};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@ public:
|
||||
void clear();
|
||||
void clear(CRGB* color);
|
||||
void setPixel(uint8_t x, uint8_t y, CRGB* color);
|
||||
void setSubPixel(accum88 x, accum88 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);
|
||||
@ -27,7 +28,19 @@ public:
|
||||
void circle(uint8_t x, uint8_t y, uint8_t r, CRGB* color);
|
||||
uint16_t coordsToGlobalIndex(uint8_t x, uint8_t y);
|
||||
uint16_t localToGlobalIndex(uint16_t);
|
||||
void drawChar(Font* f, uint8_t x, uint8_t y, const char c, CRGB* color, bool mask=false);
|
||||
void drawChar(Font* f, accum88 x, accum88 y, const char c, CRGB* color, bool mask=false);
|
||||
void drawText(Font* f, uint16_t x, uint16_t y, String s, CRGB* color);
|
||||
void drawSubText(Font* f, accum88 x, accum88 y, String s, CRGB* color);
|
||||
void addPixelColor(uint16_t index, CRGB* color);
|
||||
void addPixelColor(uint8_t x, uint8_t y, CRGB* color);
|
||||
CRGB get_pixel(uint8_t x, uint8_t y);
|
||||
void fadeToBlackBy(fract8 speed);
|
||||
void shift_down();
|
||||
void shift_down_and_blur();
|
||||
void clear_row(uint8_t y);
|
||||
void blur(fract8 intensity);
|
||||
void blur_rows(fract8 intensity);
|
||||
void blur_row(uint8_t y, fract8 intensity);
|
||||
void blur_columns(fract8 intensity);
|
||||
void blur_column(uint8_t x, fract8 intensity);
|
||||
};
|
||||
|
@ -81,6 +81,8 @@
|
||||
#define EFFECT_DVD_WIDTH 3
|
||||
#define EFFECT_DVD_HEIGHT 2
|
||||
|
||||
#define EFFECT_SINES_COUNT 5
|
||||
|
||||
// Stop editing here
|
||||
|
||||
#ifdef DEBUG
|
||||
|
9
include/effect_analogclock.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
class AnalogClockEffect : public Effect {
|
||||
public:
|
||||
void loop();
|
||||
String get_name() override { return "analog_clock"; }
|
||||
};
|
@ -8,6 +8,7 @@
|
||||
class AnimationEffect : public Effect {
|
||||
private:
|
||||
Animation *animation;
|
||||
const char* name;
|
||||
uint16_t xOffset;
|
||||
uint16_t yOffset;
|
||||
public:
|
||||
@ -17,4 +18,5 @@ public:
|
||||
~AnimationEffect();
|
||||
AnimationEffect* setFgColor(uint32_t c);
|
||||
void loop();
|
||||
String get_name() override;
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_bell_H
|
||||
#define effect_bell_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "functions.h"
|
||||
@ -11,6 +10,6 @@ private:
|
||||
boolean invert = false;
|
||||
public:
|
||||
void loop();
|
||||
String get_name() override { return "bell"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_big_clock_H
|
||||
#define effect_big_clock_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
@ -9,10 +8,10 @@ private:
|
||||
CRGB _color_seconds = 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();
|
||||
String get_name() override { return "big_clock"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
17
include/effect_blur2d.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class Blur2DEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
public:
|
||||
~Blur2DEffect();
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
String get_name() override { return "blur2d"; }
|
||||
};
|
||||
|
@ -6,11 +6,19 @@
|
||||
#include "Window.h"
|
||||
|
||||
class ClockEffect : public Effect {
|
||||
private:
|
||||
protected:
|
||||
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);
|
||||
virtual void loop();
|
||||
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);
|
||||
};
|
||||
|
||||
class NightClockEffect : public ClockEffect {
|
||||
public:
|
||||
NightClockEffect();
|
||||
void loop() override;
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_confetti_H
|
||||
#define effect_confetti_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "my_fastled.h"
|
||||
@ -10,11 +9,12 @@ protected:
|
||||
public:
|
||||
void loop();
|
||||
boolean can_be_shown_with_clock();
|
||||
String get_name() override { return "confetti"; }
|
||||
};
|
||||
|
||||
class RandomConfettiEffect : public ConfettiEffect {
|
||||
protected:
|
||||
CRGB _getColor() override;
|
||||
String get_name() override { return "random_confetti"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_cycle_H
|
||||
#define effect_cycle_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "effects.h"
|
||||
@ -16,8 +15,7 @@ public:
|
||||
|
||||
boolean can_be_shown_with_clock();
|
||||
boolean clock_as_mask();
|
||||
String get_name() override;
|
||||
|
||||
void loop();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -14,4 +14,5 @@ public:
|
||||
~DvdEffect();
|
||||
void loop() override;
|
||||
bool can_be_shown_with_clock() override;
|
||||
String get_name() override { return "dvd"; }
|
||||
};
|
||||
|
@ -15,11 +15,13 @@ public:
|
||||
boolean can_be_shown_with_clock();
|
||||
virtual void loop();
|
||||
void draw();
|
||||
String get_name() override { return "single_dynamic"; }
|
||||
};
|
||||
|
||||
class MultiDynamicEffect : public SingleDynamicEffect {
|
||||
public:
|
||||
void loop();
|
||||
String get_name() override { return "multi_dynamic"; }
|
||||
};
|
||||
|
||||
class BigDynamicEffect : public Effect {
|
||||
@ -28,4 +30,6 @@ private:
|
||||
public:
|
||||
void loop();
|
||||
~BigDynamicEffect();
|
||||
boolean can_be_shown_with_clock() override;
|
||||
String get_name() override { return "big_dynamic"; }
|
||||
};
|
||||
|
@ -16,4 +16,5 @@ public:
|
||||
FireEffect();
|
||||
~FireEffect();
|
||||
void loop();
|
||||
String get_name() override { return "fire"; }
|
||||
};
|
||||
|
@ -1,7 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class FireworkEffect : public Effect {
|
||||
void loop();
|
||||
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 {
|
||||
private:
|
||||
Window* _window;
|
||||
FireworkEffect* _main;
|
||||
accum88 _x;
|
||||
accum88 _y;
|
||||
saccum78 _xv;
|
||||
saccum78 _yv;
|
||||
accum88 _r;
|
||||
CRGB _color;
|
||||
|
||||
void _screenscale(accum88 a, byte n, byte& screen, byte& screenerr);
|
||||
int16_t _scale15by8_local(int16_t i, fract8 scale);
|
||||
public:
|
||||
byte show;
|
||||
FireworkDotType type;
|
||||
|
||||
FireworkEffectDot(Window* w, FireworkEffect* e);
|
||||
void draw();
|
||||
void move();
|
||||
void ground_launch();
|
||||
void sky_burst(accum88 basex, accum88 basey, saccum78 basedv, CRGB& basecolor);
|
||||
};
|
||||
|
||||
class FireworkEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
bool _skyburst = 0;
|
||||
|
||||
accum88 _burst_x;
|
||||
accum88 _burst_y;
|
||||
saccum78 _burst_xv;
|
||||
saccum78 _burst_yv;
|
||||
CRGB _burst_color;
|
||||
|
||||
FireworkEffectDot* _dot;
|
||||
FireworkEffectDot* _sparks[EFFECT_FIREWORK_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();
|
||||
String get_name() override { return "firework"; }
|
||||
};
|
||||
|
||||
|
@ -19,4 +19,5 @@ public:
|
||||
~GolEffect();
|
||||
void loop();
|
||||
bool can_be_shown_with_clock();
|
||||
String get_name() override { return "gol"; }
|
||||
};
|
||||
|
19
include/effect_marquee.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class MarqueeEffect : public Effect {
|
||||
private:
|
||||
Window* window = new Window(0, 0, LED_WIDTH, LED_HEIGHT-6);
|
||||
String _text = String("No text set +++ ");
|
||||
saccum78 _position = (window->width<<8);
|
||||
public:
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
void apply_option(String key, String value) override;
|
||||
String get_name() override { return "marquee"; }
|
||||
};
|
||||
|
@ -9,7 +9,7 @@
|
||||
class MatrixEffectColumn {
|
||||
protected:
|
||||
Window* window;
|
||||
uint8_t x, y;
|
||||
accum88 x, y;
|
||||
uint8_t length = 1;
|
||||
uint8_t _direction = 2;
|
||||
bool _random_direction = false;
|
||||
@ -56,14 +56,17 @@ public:
|
||||
MatrixEffect();
|
||||
virtual ~MatrixEffect();
|
||||
void loop();
|
||||
String get_name() override { return "matrix"; }
|
||||
};
|
||||
|
||||
class RainbowMatrixEffect : public MatrixEffect {
|
||||
public:
|
||||
RainbowMatrixEffect();
|
||||
String get_name() override { return "rainbow_matrix"; }
|
||||
};
|
||||
|
||||
class RandomMatrixEffect : public MatrixEffect {
|
||||
public:
|
||||
RandomMatrixEffect();
|
||||
String get_name() override { return "random_matrix"; }
|
||||
};
|
||||
|
@ -12,4 +12,5 @@ public:
|
||||
~PixelClockEffect();
|
||||
void loop();
|
||||
bool can_be_shown_with_clock();
|
||||
String get_name() override { return "pixel_clock"; }
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_sinematrix3_H
|
||||
#define effect_sinematrix3_H
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
@ -32,6 +31,6 @@ public:
|
||||
boolean can_be_shown_with_clock();
|
||||
boolean clock_as_mask();
|
||||
void loop();
|
||||
String get_name() override { return "sinematrix3"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
33
include/effect_sines.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "prototypes.h"
|
||||
#include "functions.h"
|
||||
#include "Effect.h"
|
||||
|
||||
class SinesEffectSinus {
|
||||
private:
|
||||
uint8_t _value;
|
||||
uint8_t _frequency;
|
||||
uint8_t _amplitude;
|
||||
uint8_t _x;
|
||||
uint8_t _step;
|
||||
Window* _window;
|
||||
CRGB _color;
|
||||
public:
|
||||
SinesEffectSinus(Window* w);
|
||||
void loop();
|
||||
};
|
||||
|
||||
class SinesEffect : public Effect {
|
||||
private:
|
||||
SinesEffectSinus* _sinus[EFFECT_SINES_COUNT];
|
||||
uint8_t _step = 0;
|
||||
public:
|
||||
SinesEffect();
|
||||
~SinesEffect();
|
||||
boolean supports_window = true;
|
||||
boolean can_be_shown_with_clock();
|
||||
void loop();
|
||||
String get_name() override { return "sines"; }
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_snake_H
|
||||
#define effect_snake_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "prototypes.h"
|
||||
@ -22,6 +21,5 @@ public:
|
||||
boolean valid_position(Coords c);
|
||||
Coords update_position(Coords c, uint8_t direction);
|
||||
boolean can_be_shown_with_clock();
|
||||
String get_name() override { return "snake"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_static_H
|
||||
#define effect_static_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include "my_fastled.h"
|
||||
@ -11,6 +10,6 @@ public:
|
||||
StaticEffect(CRGB col);
|
||||
boolean supports_window = true;
|
||||
void loop();
|
||||
String get_name() override { return "static"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef effect_twirl_H
|
||||
#define effect_twirl_H
|
||||
#pragma once
|
||||
|
||||
#include "Effect.h"
|
||||
#include <Arduino.h>
|
||||
@ -12,6 +11,8 @@ private:
|
||||
double _real_center_y = LED_HEIGHT / 2;
|
||||
public:
|
||||
void loop();
|
||||
boolean can_be_shown_with_clock() override;
|
||||
boolean clock_as_mask() override;
|
||||
String get_name() override { return "twirl"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -4,3 +4,4 @@
|
||||
extern Font font_numbers3x5;
|
||||
extern Font font_numbers3x5_blocky;
|
||||
extern Font font_numbers4x7;
|
||||
extern Font font5x7;
|
||||
|
@ -18,6 +18,7 @@ void mqtt_setup();
|
||||
void mqtt_loop();
|
||||
|
||||
void mqtt_publish(const char* topic, int number);
|
||||
void mqtt_publish(const char* topic, const char* message);
|
||||
|
||||
void mqtt_log(const char* message);
|
||||
void mqtt_log(int number);
|
||||
|
@ -14,6 +14,7 @@ private:
|
||||
size_t _buffer_len;
|
||||
char* _buffer;
|
||||
uint16_t _msgid;
|
||||
boolean _skip_next_frame = false;
|
||||
public:
|
||||
Recorder();
|
||||
void loop();
|
||||
|
124
src/Window.cpp
@ -41,7 +41,19 @@ void Window::clear(CRGB* color) {
|
||||
for(int x=0; x<this->width; x++) for(int y=0; y<this->height; y++) this->setPixel(x, y, color);
|
||||
}
|
||||
|
||||
void Window::drawChar(Font* font, uint8_t xPos, uint8_t yPos, const char c, CRGB* color, bool mask) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::drawSubText(Font* font, accum88 x, accum88 y, String text, CRGB* color) {
|
||||
for (int i=0; i<text.length(); i++) {
|
||||
drawChar(font, x+(i*((font->width + 1)<<8)), y, text[i], color);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::drawChar(Font* font, accum88 xPos, accum88 yPos, const char c, CRGB* color, bool mask) {
|
||||
if (!font->isCharAllowed(c)) return;
|
||||
uint16_t position = font->getCharPosition(c);
|
||||
uint8_t* data = new uint8_t[font->width];
|
||||
@ -50,16 +62,87 @@ void Window::drawChar(Font* font, uint8_t xPos, uint8_t yPos, const char c, CRGB
|
||||
for(uint8_t y=0; y<font->height; y++) for(uint8_t x=0; x<font->width; x++) {
|
||||
bool on = (data[x]>>(font->height - 1 - y) & 1) * 255;
|
||||
if (mask) on = !on;
|
||||
if (on) this->setPixel(x + xPos, y + yPos, color);
|
||||
if (on) this->setSubPixel(xPos + (x<<8), yPos + (y<<8), color);
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
void Window::clear_row(uint8_t y) {
|
||||
CRGB black(0x000000);
|
||||
for (uint8_t x=0; x<this->width; x++) this->setPixel(x, y, &black);
|
||||
}
|
||||
|
||||
void Window::shift_down() {
|
||||
for (uint8_t y=this->height-1; y>=1; y--) {
|
||||
for (uint8_t x=0; x<this->width; x++) {
|
||||
leds[coordsToGlobalIndex(x, y)] = leds[coordsToGlobalIndex(x, y-1)];
|
||||
}
|
||||
}
|
||||
|
||||
clear_row(0);
|
||||
}
|
||||
|
||||
void Window::shift_down_and_blur() {
|
||||
shift_down();
|
||||
for (uint8_t y=1; y<this->height; y++) {
|
||||
blur_row(y, 128);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::blur(fract8 intensity) {
|
||||
blur_rows(intensity);
|
||||
blur_columns(intensity);
|
||||
}
|
||||
|
||||
void Window::blur_rows(fract8 intensity) {
|
||||
for (uint8_t y=0; y<this->height; y++) {
|
||||
blur_row(y, intensity);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::blur_columns(fract8 intensity) {
|
||||
for (uint8_t x=0; x<this->width; x++) {
|
||||
blur_column(x, intensity);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::blur_row(uint8_t y, fract8 intensity) {
|
||||
uint16_t idx1 = coordsToGlobalIndex(0, y);
|
||||
uint16_t idx2 = coordsToGlobalIndex(this->width - 1, y);
|
||||
blur1d(&(leds[idx1 < idx2 ? idx1 : idx2]), this->width, intensity);
|
||||
}
|
||||
|
||||
void Window::blur_column(uint8_t x, fract8 intensity) {
|
||||
// Reimplementation from FastLEDs blurColumns
|
||||
uint8_t keep = 255 - intensity;
|
||||
uint8_t seep = intensity >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
|
||||
for (uint8_t y=0; y<this->height; y++) {
|
||||
CRGB cur = leds[coordsToGlobalIndex(x, y)];
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if (y>0) leds[coordsToGlobalIndex(x, y-1)] += part;
|
||||
leds[coordsToGlobalIndex(x, y)] = cur;
|
||||
carryover = part;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::addPixelColor(uint16_t index, CRGB* color) {
|
||||
leds[localToGlobalIndex(index)] += *color;
|
||||
}
|
||||
|
||||
void Window::addPixelColor(uint8_t x, uint8_t y, CRGB* color) {
|
||||
leds[coordsToGlobalIndex(x, y)] += *color;
|
||||
}
|
||||
|
||||
CRGB Window::get_pixel(uint8_t x, uint8_t y) {
|
||||
return leds[coordsToGlobalIndex(x, y)];
|
||||
}
|
||||
|
||||
void Window::fadeToBlackBy(fract8 speed) {
|
||||
for (uint8_t x=0; x<this->width; x++) for(uint8_t y=0; y<this->height; y++) {
|
||||
leds[coordsToGlobalIndex(x, y)].nscale8(255 - speed);
|
||||
@ -135,3 +218,40 @@ void Window::lineWithAngle(uint8_t x, uint8_t y, uint8_t angle, uint8_t startdis
|
||||
|
||||
line(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
void Window::setSubPixel(accum88 x, accum88 y, CRGB* color) {
|
||||
uint8_t px, py;
|
||||
// px = Part of next pixel to fill
|
||||
// x = "Origin pixel"
|
||||
px = x & 0xFF;
|
||||
py = y & 0xFF;
|
||||
x = x >> 8;
|
||||
y = y >> 8;
|
||||
|
||||
CRGB c;
|
||||
c = CRGB(scale8( scale8( color->r, 255-py), 255-px),
|
||||
scale8( scale8( color->g, 255-py), 255-px),
|
||||
scale8( scale8( color->b, 255-py), 255-px));
|
||||
this->addPixelColor(x, y, &c);
|
||||
|
||||
if (px) {
|
||||
c = CRGB(scale8( scale8( color->r, 255-py), px),
|
||||
scale8( scale8( color->g, 255-py), px),
|
||||
scale8( scale8( color->b, 255-py), px));
|
||||
this->addPixelColor(x+1, y, &c);
|
||||
}
|
||||
|
||||
if (py) {
|
||||
c = CRGB(scale8( scale8( color->r, py), 255-px),
|
||||
scale8( scale8( color->g, py), 255-px),
|
||||
scale8( scale8( color->b, py), 255-px));
|
||||
this->addPixelColor(x, y+1, &c);
|
||||
}
|
||||
|
||||
if (px || py) {
|
||||
c = CRGB(scale8( scale8( color->r, py), px),
|
||||
scale8( scale8( color->g, py), px),
|
||||
scale8( scale8( color->b, py), px));
|
||||
this->addPixelColor(x+1, y+1, &c);
|
||||
}
|
||||
}
|
||||
|
23
src/effect_analogclock.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "effect_analogclock.h"
|
||||
#include "my_fastled.h"
|
||||
#include "ntp.h"
|
||||
|
||||
void AnalogClockEffect::loop() {
|
||||
window->clear();
|
||||
CRGB white(0xFFFFFF);
|
||||
CRGB red(0xFF0000);
|
||||
window->circle(8, 8, 7, &white);
|
||||
|
||||
uint8_t seconds = ntpClient.getSeconds();
|
||||
uint8_t angle = 6 * seconds;
|
||||
window->lineWithAngle(8, 8, angle, 0, 10, &red);
|
||||
/*for (uint8_t i=0; i<=12; i++) {
|
||||
window->lineWithAngle(8, 8, 255/12*i, 5, 2, &white);
|
||||
}
|
||||
|
||||
uint8_t minutes = ntpClient.getMinutes();
|
||||
uint8_t hours = ntpClient.getHours();
|
||||
|
||||
window->lineWithAngle(8, 8, 255/60*minutes, 6, &white);
|
||||
window->lineWithAngle(8, 8, 255/12*(hours % 12), 4, &white);*/
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include "functions.h"
|
||||
|
||||
AnimationEffect::AnimationEffect(const char* name, uint32_t bg, int x, int y) {
|
||||
this->name = name;
|
||||
this->xOffset = x;
|
||||
this->yOffset = y;
|
||||
|
||||
@ -23,3 +24,9 @@ void AnimationEffect::loop() {
|
||||
this->animation->drawFrame();
|
||||
this->animation->advance();
|
||||
}
|
||||
|
||||
String AnimationEffect::get_name() {
|
||||
String s = "animation/";
|
||||
s += this->name;
|
||||
return s;
|
||||
}
|
||||
|
@ -6,12 +6,12 @@
|
||||
void BigClockEffect::loop() {
|
||||
window->clear();
|
||||
uint8_t h = ntpClient.getHours();
|
||||
window->drawChar(&font_numbers3x5_blocky, 6, 2, '0' + (h / 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 11, 2, '0' + (h % 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 6<<8, 2<<8, '0' + (h / 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 11<<8, 2<<8, '0' + (h % 10), &_color_font);
|
||||
|
||||
uint8_t m = ntpClient.getMinutes();
|
||||
window->drawChar(&font_numbers3x5_blocky, 6, 9, '0' + (m / 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 11, 9, '0' + (m % 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 6<<8, 9<<8, '0' + (m / 10), &_color_font);
|
||||
window->drawChar(&font_numbers3x5_blocky, 11<<8, 9<<8, '0' + (m % 10), &_color_font);
|
||||
|
||||
uint8_t s = ntpClient.getSeconds();
|
||||
if (s & 1) {
|
||||
@ -25,32 +25,33 @@ 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, &_color_seconds);
|
||||
}
|
||||
uint16_t millis = ntpClient.getEpochMillis() % 1000;
|
||||
if (millis > 0) {
|
||||
uint8_t part = 60 - ((60 - seconds) * millis / 1000);
|
||||
_draw_border_pixel(part, &_color_seconds);
|
||||
uint16_t position = ((60 - (60 - seconds) * millis) << 8) / 1000;
|
||||
//uint8_t position = 60 - ((60 - seconds) * millis / 1000);
|
||||
_draw_border_pixel(position>>8, position&0xFF, &_color_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
accum88 x, y;
|
||||
if (i<=8) {
|
||||
x = 7 + i;
|
||||
x = (7 + i)<<8 | part;
|
||||
y = 0;
|
||||
} else if (i<=23) {
|
||||
x = 15;
|
||||
y = i - 8;
|
||||
x = 15 << 8;
|
||||
y = (i - 8) << 8 | (255 - part);
|
||||
} else if (i<= 38) {
|
||||
x = 15 - i + 23;
|
||||
y = 15;
|
||||
x = (15 - i + 23) << 8 | (255 - part);
|
||||
y = 15 << 8;
|
||||
} else if (i <= 53) {
|
||||
x = 0;
|
||||
y = 15 - i + 38;
|
||||
y = (15 - i + 38) << 8 | part;
|
||||
} else {
|
||||
x = i - 53;
|
||||
x = (i - 53) << 8 | part;
|
||||
y = 0;
|
||||
}
|
||||
window->setPixel(x, y, color);
|
||||
window->setSubPixel(x, y, color);
|
||||
}
|
||||
|
31
src/effect_blur2d.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "effect_blur2d.h"
|
||||
|
||||
boolean Blur2DEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Blur2DEffect::loop() {
|
||||
uint8_t blur_amount = dim8_raw(beatsin8(3, 64, 192));
|
||||
window->blur(blur_amount);
|
||||
|
||||
uint8_t x1 = beatsin8(5, 0, window->width-1);
|
||||
uint8_t y1 = beatsin8(8, 0, window->height-1);
|
||||
|
||||
uint8_t x2 = beatsin8(8, 0, window->width-1);
|
||||
uint8_t y2 = beatsin8(3, 0, window->height-1);
|
||||
|
||||
uint8_t x3 = beatsin8(4, 0, window->width-1);
|
||||
uint8_t y3 = beatsin8(7, 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);
|
||||
window->addPixelColor(x1, y1, &c1);
|
||||
window->addPixelColor(x2, y2, &c2);
|
||||
window->addPixelColor(x3, y3, &c3);
|
||||
}
|
||||
|
||||
Blur2DEffect::~Blur2DEffect() {
|
||||
delete window;
|
||||
}
|
@ -4,23 +4,41 @@
|
||||
#include "fonts.h"
|
||||
#include "ntp.h"
|
||||
|
||||
void ClockEffect::loop() {
|
||||
loop(false, CRGB(0xFFFFFF), CRGB(0x000000));
|
||||
NightClockEffect::NightClockEffect() {
|
||||
window = Window::getFullWindow();
|
||||
}
|
||||
|
||||
void ClockEffect::loop(boolean invert, CRGB fg_color, CRGB bg_color) {
|
||||
void NightClockEffect::loop() {
|
||||
uint16_t minutes = minutes16();
|
||||
//uint8_t y = minutes % ((window->height - 5) * 2 - 2);
|
||||
//if (y > window->height - 5) y = 2*window->height - 2*y;
|
||||
uint8_t y = minutes % 10;
|
||||
ClockEffect::loop(false, CRGB(0x880000), CRGB(0x000000), y);
|
||||
}
|
||||
|
||||
void ClockEffect::loop() {
|
||||
loop_with_invert(false);
|
||||
}
|
||||
|
||||
void ClockEffect::loop_with_invert(bool invert) {
|
||||
// Clear the first line to have a bit of space to the other stuff on screen
|
||||
CRGB bg_color(0x000000);
|
||||
for(int i=0; i<window->width; i++) window->setPixel(i, 0, &bg_color);
|
||||
loop(invert, CRGB(0xFFFFFF), bg_color, 1);
|
||||
}
|
||||
|
||||
void ClockEffect::loop(boolean invert, CRGB fg_color, CRGB bg_color, uint8_t yPos) {
|
||||
if (!invert) {
|
||||
window->clear(&bg_color);
|
||||
} else {
|
||||
// Manually clear the needed parts
|
||||
for(int i=0; i<window->width; i++) window->setPixel(i, 0, &bg_color);
|
||||
for(int y=0; y<6; y++) {
|
||||
window->setPixel(3, y, &bg_color);
|
||||
window->setPixel(3, yPos+y, &bg_color);
|
||||
if (y!=2 && y!=4) {
|
||||
window->setPixel(7, y, &bg_color);
|
||||
window->setPixel(7, yPos+y, &bg_color);
|
||||
}
|
||||
window->setPixel(8, y, &bg_color);
|
||||
window->setPixel(12, y, &bg_color);
|
||||
window->setPixel(8, yPos+y, &bg_color);
|
||||
window->setPixel(12, yPos+y, &bg_color);
|
||||
}
|
||||
fg_color = bg_color;
|
||||
}
|
||||
@ -30,14 +48,14 @@ void ClockEffect::loop(boolean invert, CRGB fg_color, CRGB bg_color) {
|
||||
}
|
||||
int h = ntpClient.getHours();
|
||||
//void drawChar(Font f, uint8_t x, uint8_t y, const char c, CRGB* color, bool mask=false);
|
||||
window->drawChar(&font_numbers3x5, 0, 1, '0' + (h / 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 4, 1, '0' + (h % 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 0<<8, yPos<<8, '0' + (h / 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 4<<8, yPos<<8, '0' + (h % 10), &fg_color, invert);
|
||||
int m = ntpClient.getMinutes();
|
||||
window->drawChar(&font_numbers3x5, 9, 1, '0' + (m / 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 13, 1, '0' + (m % 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 9<<8, yPos<<8, '0' + (m / 10), &fg_color, invert);
|
||||
window->drawChar(&font_numbers3x5, 13<<8, yPos<<8, '0' + (m % 10), &fg_color, invert);
|
||||
if (ntpClient.getSeconds() & 1) {
|
||||
window->setPixel(7, 2, &fg_color);
|
||||
window->setPixel(7, 4, &fg_color);
|
||||
window->setPixel(7, yPos+1, &fg_color);
|
||||
window->setPixel(7, yPos+3, &fg_color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,13 @@ void CycleEffect::changeEffect() {
|
||||
LOGln("CycleEffect * Searching for new effect '%s'", cycle_effects[new_id]);
|
||||
delay(25);
|
||||
effect = select_effect( crc32String(cycle_effects[new_id]) );
|
||||
effect_id = new_id;
|
||||
effectSince = millis();
|
||||
if (effect) {
|
||||
effect_id = new_id;
|
||||
effectSince = millis();
|
||||
LOGln("CycleEffect * Effect %s found", effect->get_name().c_str());
|
||||
} else {
|
||||
LOGln("CycleEffect * Effect NOT found");
|
||||
}
|
||||
}
|
||||
|
||||
boolean CycleEffect::can_be_shown_with_clock() {
|
||||
@ -47,3 +52,9 @@ void CycleEffect::loop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String CycleEffect::get_name() {
|
||||
String s = "cycle/";
|
||||
s += effect->get_name();
|
||||
return s;
|
||||
}
|
||||
|
@ -59,3 +59,7 @@ void BigDynamicEffect::loop() {
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
boolean BigDynamicEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
@ -1,13 +1,183 @@
|
||||
// Based on https://gist.github.com/kriegsman/68929cbd1d6de4535b20
|
||||
#include "effect_firework.h"
|
||||
#include "my_fastled.h"
|
||||
#include "functions.h"
|
||||
#include "config.h"
|
||||
|
||||
FireworkEffectDot::FireworkEffectDot(Window* w, FireworkEffect* e) {
|
||||
_window = w;
|
||||
_main = e;
|
||||
show = 0;
|
||||
type = FIREWORK_DOT_NONE;
|
||||
_x = 0;
|
||||
_y = 0;
|
||||
_xv = 0;
|
||||
_yv = 0;
|
||||
_r = 0;
|
||||
_color.setRGB(0, 0, 0);
|
||||
}
|
||||
|
||||
void FireworkEffectDot::_screenscale(accum88 a, byte n, byte& screen, byte& screenerr) {
|
||||
byte ia = a >> 8;
|
||||
screen = scale8(ia, n);
|
||||
byte m = screen * (256 / n);
|
||||
screenerr = (ia - m) * scale8(255, n);
|
||||
}
|
||||
|
||||
int16_t FireworkEffectDot::_scale15by8_local(int16_t i, fract8 scale) {
|
||||
int16_t result;
|
||||
result = (int32_t)((int32_t) i*scale)/256;
|
||||
return result;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::draw() {
|
||||
if (!show) return;
|
||||
byte ix, xe, xc;
|
||||
byte iy, ye, yc;
|
||||
_screenscale(_x, _window->width, ix, xe);
|
||||
_screenscale(_y, _window->height, iy, ye);
|
||||
xc = 255 - xe;
|
||||
yc = 255 - ye;
|
||||
|
||||
CRGB c00 = CRGB(dim8_video( scale8( scale8( _color.r, yc), xc)),
|
||||
dim8_video( scale8( scale8( _color.g, yc), xc)),
|
||||
dim8_video( scale8( scale8( _color.b, yc), xc)));
|
||||
CRGB c01 = CRGB(dim8_video( scale8( scale8( _color.r, ye), xc)),
|
||||
dim8_video( scale8( scale8( _color.g, ye), xc)),
|
||||
dim8_video( scale8( scale8( _color.b, ye), xc)));
|
||||
CRGB c10 = CRGB(dim8_video( scale8( scale8( _color.r, yc), xe)),
|
||||
dim8_video( scale8( scale8( _color.g, yc), xe)),
|
||||
dim8_video( scale8( scale8( _color.b, yc), xe)));
|
||||
CRGB c11 = CRGB(dim8_video( scale8( scale8( _color.r, ye), xe)),
|
||||
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+1, iy, &c10);
|
||||
_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);
|
||||
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
_xv = _scale15by8_local(_xv, EFFECT_FIREWORK_DRAG);
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_DRAG);
|
||||
_color.nscale8(255);
|
||||
if (!_color) {
|
||||
show = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Bounce if we hit the ground
|
||||
if (_xv < 0 && _y < (-_yv)) {
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
show = 0;
|
||||
} else {
|
||||
_yv = -_yv;
|
||||
_yv = _scale15by8_local(_yv, EFFECT_FIREWORK_BOUNCE);
|
||||
if (_yv < 500) {
|
||||
show = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_yv < 300) {
|
||||
if (type == FIREWORK_DOT_SHELL) {
|
||||
if (_y > (uint16_t)0x8000) {
|
||||
// boom
|
||||
CRGB white(0xFFFFFF);
|
||||
_window->clear(&white);
|
||||
}
|
||||
show = 0;
|
||||
_main->skyburst(_x, _y, _xv, _yv, _color);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == FIREWORK_DOT_SPARK) {
|
||||
if ((_xv > 0 && _x>_xv) || (_xv < 0 && _x<(0xFFFF+_xv))) {
|
||||
_x += _xv;
|
||||
} else {
|
||||
show = 0;
|
||||
}
|
||||
} else {
|
||||
_x += _xv;
|
||||
}
|
||||
_y += _yv;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::ground_launch() {
|
||||
_xv = (int16_t)random16(600) - (int16_t)300;
|
||||
_yv = 600 + random16(300 + (25 * _window->height));
|
||||
_x = 0x8000;
|
||||
_y = 0;
|
||||
hsv2rgb_rainbow(CHSV(random8(), 240, 200), _color);
|
||||
show = 1;
|
||||
}
|
||||
|
||||
void FireworkEffectDot::sky_burst(accum88 basex, accum88 basey, saccum78 basedv, CRGB& basecolor) {
|
||||
_xv = basedv + (int16_t)random16(2000) - (int16_t)1000;
|
||||
_yv = (int16_t)random16(1500) - (int16_t)500;
|
||||
_x = basex;
|
||||
_y = basey;
|
||||
_color = basecolor;
|
||||
_color *= 4;
|
||||
type = FIREWORK_DOT_SPARK;
|
||||
show = 1;
|
||||
}
|
||||
|
||||
void FireworkEffect::skyburst(accum88 x, accum88 y, saccum78 xv, saccum78 yv, CRGB c) {
|
||||
_skyburst = 1;
|
||||
_burst_x = x;
|
||||
_burst_y = y;
|
||||
_burst_xv = xv;
|
||||
_burst_yv = yv;
|
||||
_burst_color = c;
|
||||
}
|
||||
|
||||
boolean FireworkEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FireworkEffect::loop() {
|
||||
blur(EFFECT_FIREWORK_BLUR);
|
||||
fadeToBlackBy(leds, LED_COUNT, EFFECT_FIREWORK_FADEOUT_SPEED);
|
||||
|
||||
if (random8(EFFECT_FIREWORK_SHOT_CHANCE)==0) {
|
||||
leds[random16(LED_COUNT)] = CHSV(random8(), 255, 255);
|
||||
window->clear();
|
||||
_dot->move();
|
||||
_dot->draw();
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
_sparks[i]->move();
|
||||
_sparks[i]->draw();
|
||||
}
|
||||
static uint16_t launch_countdown = 0;
|
||||
if (_dot->show == 0) {
|
||||
if (launch_countdown == 0) {
|
||||
_dot->ground_launch();
|
||||
_dot->type = FIREWORK_DOT_SHELL;
|
||||
launch_countdown = random16(350) + 1;
|
||||
} else {
|
||||
launch_countdown--;
|
||||
}
|
||||
}
|
||||
|
||||
if (_skyburst) {
|
||||
int nsparks = random8(EFFECT_FIREWORK_SPARKS / 2, EFFECT_FIREWORK_SPARKS + 1);
|
||||
for (int i=0; i<nsparks; i++) {
|
||||
_sparks[i]->sky_burst(_burst_x, _burst_y, _burst_yv, _burst_color);
|
||||
_skyburst = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FireworkEffect::FireworkEffect() {
|
||||
_dot = new FireworkEffectDot(window, this);
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
_sparks[i] = new FireworkEffectDot(window, this);
|
||||
}
|
||||
}
|
||||
|
||||
FireworkEffect::~FireworkEffect() {
|
||||
delete window;
|
||||
for (int i=0; i<EFFECT_FIREWORK_SPARKS; i++) {
|
||||
delete _sparks[i];
|
||||
}
|
||||
delete _dot;
|
||||
}
|
||||
|
26
src/effect_marquee.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "effect_marquee.h"
|
||||
#include "fonts.h"
|
||||
|
||||
boolean MarqueeEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MarqueeEffect::loop() {
|
||||
static int loop_counter = 0;
|
||||
window->clear();
|
||||
CRGB color = CHSV(0, 255, 255);
|
||||
uint16_t width = _text.length() * 6;
|
||||
window->drawSubText(&font5x7, _position, 0, _text, &color);
|
||||
_position-=100;
|
||||
if ((_position>>8) <= -width) { // Font is out of the window
|
||||
_position = 0;
|
||||
}
|
||||
if ((_position>>8) + width < window->width) { // Text isn't filling the window up any more
|
||||
window->drawSubText(&font5x7, _position + (width<<8), 0, _text, &color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MarqueeEffect::apply_option(String key, String value) {
|
||||
if (key.equals("text")) _text = value;
|
||||
}
|
@ -15,25 +15,25 @@ void MatrixEffectColumn::restart(bool completely_random) {
|
||||
}
|
||||
|
||||
if (completely_random) {
|
||||
x = random8(window->width);
|
||||
y = random8(window->height);
|
||||
x = random8(window->width)<<8;
|
||||
y = random8(window->height)<<8;
|
||||
} else {
|
||||
switch(_direction) {
|
||||
case DIR_NORTH:
|
||||
x = random8(window->width);
|
||||
y = window->height - 1;
|
||||
x = random8(window->width)<<8;
|
||||
y = (window->height - 1)<<8;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
x = 0;
|
||||
y = random8(window->height);
|
||||
y = random8(window->height)<<8;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
x = random8(window->width);
|
||||
x = random8(window->width)<<8;
|
||||
y = 0;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
x = window->width - 1;
|
||||
y = random8(window->height);
|
||||
x = (window->width - 1)<<8;
|
||||
y = random8(window->height)<<8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -46,36 +46,36 @@ void MatrixEffectColumn::restart(bool completely_random) {
|
||||
void MatrixEffectColumn::advance() {
|
||||
switch(_direction) {
|
||||
case DIR_NORTH:
|
||||
y--;
|
||||
if (y > window->height && y + length > window->height) running=false;
|
||||
y-=speed;
|
||||
if ((y>>8) > window->height && (y>>8) + length > window->height) running=false;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
x++;
|
||||
if (x - length > window->width) running=false;
|
||||
x+=speed;
|
||||
if ((x>>8) - length > window->width) running=false;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
y++;
|
||||
if (y - length > window->height) running=false;
|
||||
y+=speed;
|
||||
if ((y>>8) - length > window->height) running=false;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
x--;
|
||||
if (x > window->width && y + length > window->width) running=false;
|
||||
x-=speed;
|
||||
if ((x>>8) > window->width && (y>>8) + length > window->width) running=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MatrixEffectColumn::draw() {
|
||||
int8_t xdir = 0;
|
||||
int8_t ydir = 0;
|
||||
int16_t xdir = 0;
|
||||
int16_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;
|
||||
case DIR_NORTH: ydir = 0xFF; break;
|
||||
case DIR_EAST: xdir = -0xFF; break;
|
||||
case DIR_SOUTH: ydir = -0xFF; break;
|
||||
case DIR_WEST: xdir = 0xFF; break;
|
||||
}
|
||||
for(int i=0; i<length; i++) {
|
||||
CRGB color = _getColor(i);
|
||||
window->raisePixel(x+(xdir*i), y+(ydir*i), &color);
|
||||
window->setSubPixel(x+(xdir*i), y+(ydir*i), &color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,13 +85,9 @@ void MatrixEffectColumn::loop() {
|
||||
// Start the column again.
|
||||
restart(false);
|
||||
}
|
||||
} else {
|
||||
if (millis() - last_move > speed) {
|
||||
advance();
|
||||
last_move = millis();
|
||||
}
|
||||
|
||||
draw();
|
||||
} else {
|
||||
advance();
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
48
src/effect_sines.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "effect_sines.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
SinesEffect::SinesEffect() {
|
||||
for (int i=0; i<EFFECT_SINES_COUNT; i++) {
|
||||
_sinus[i] = new SinesEffectSinus(window);
|
||||
}
|
||||
}
|
||||
|
||||
SinesEffect::~SinesEffect() {
|
||||
for (int i=0; i<EFFECT_SINES_COUNT; i++) { delete _sinus[i]; }
|
||||
}
|
||||
|
||||
boolean SinesEffect::can_be_shown_with_clock() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SinesEffect::loop() {
|
||||
// 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();
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
#include "effect_twirl.h"
|
||||
#include "functions.h"
|
||||
|
||||
boolean TwirlEffect::can_be_shown_with_clock() { return true; };
|
||||
boolean TwirlEffect::clock_as_mask() { return true; };
|
||||
|
||||
void TwirlEffect::loop() {
|
||||
double center_x = _real_center_x; // - (cos8(_center_offset_angle)>>6);
|
||||
double center_y = _real_center_y; // + (sin8(_center_offset_angle)>>6);
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include "effect_gol.h"
|
||||
#include "effect_pixelclock.h"
|
||||
#include "effect_dvd.h"
|
||||
#include "effect_analogclock.h"
|
||||
#include "effect_sines.h"
|
||||
#include "effect_marquee.h"
|
||||
#include "effect_blur2d.h"
|
||||
|
||||
Effect* current_effect;
|
||||
|
||||
@ -51,6 +55,11 @@ Effect* select_effect(uint32_t code) {
|
||||
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;
|
||||
};
|
||||
}
|
||||
@ -100,8 +109,11 @@ const char* cycle_effects[] = {
|
||||
"single_dynamic",
|
||||
"snake",
|
||||
"gol",
|
||||
"twirl"};
|
||||
uint8_t cycle_effects_count = 11;
|
||||
"twirl",
|
||||
"sines",
|
||||
"blur2d",
|
||||
"firework"};
|
||||
uint8_t cycle_effects_count = 14;
|
||||
|
||||
void setup_effects() {
|
||||
current_effect = new CycleEffect();
|
||||
|
205
src/fonts.cpp
@ -50,105 +50,112 @@ uint16_t font_numbers4x7_get(const char c) { return c - '0'; }
|
||||
|
||||
Font font_numbers4x7 = {4, 7, &font_numbers4x7_data[0], font_numbers4x7_check, font_numbers4x7_get};
|
||||
|
||||
/*
|
||||
const unsigned char font5x7[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,// (space)
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,// !
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,// "
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,// #
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,// %
|
||||
0x36, 0x49, 0x55, 0x22, 0x50,// &
|
||||
0x00, 0x05, 0x03, 0x00, 0x00,// '
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,// (
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,// )
|
||||
0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,// +
|
||||
0x00, 0x50, 0x30, 0x00, 0x00,// ,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,// -
|
||||
0x00, 0x60, 0x60, 0x00, 0x00,// .
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,// /
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,// 1
|
||||
0x42, 0x61, 0x51, 0x49, 0x46,// 2
|
||||
0x21, 0x41, 0x45, 0x4B, 0x31,// 3
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,// 4
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,// 5
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
|
||||
0x01, 0x71, 0x09, 0x05, 0x03,// 7
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,// 8
|
||||
0x06, 0x49, 0x49, 0x29, 0x1E,// 9
|
||||
0x00, 0x36, 0x36, 0x00, 0x00,// :
|
||||
0x00, 0x56, 0x36, 0x00, 0x00,// ;
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,// <
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,// =
|
||||
0x41, 0x22, 0x14, 0x08, 0x00,// >
|
||||
0x02, 0x01, 0x51, 0x09, 0x06,// ?
|
||||
0x32, 0x49, 0x79, 0x41, 0x3E,// @
|
||||
0x7E, 0x11, 0x11, 0x11, 0x7E,// A
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,// B
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,// C
|
||||
0x7F, 0x41, 0x41, 0x22, 0x1C,// D
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,// E
|
||||
0x7F, 0x09, 0x09, 0x01, 0x01,// F
|
||||
0x3E, 0x41, 0x41, 0x51, 0x32,// G
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,// H
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,// I
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,// J
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,// K
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,// L
|
||||
0x7F, 0x02, 0x04, 0x02, 0x7F,// M
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,// N
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,// O
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,// P
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,// R
|
||||
0x46, 0x49, 0x49, 0x49, 0x31,// S
|
||||
0x01, 0x01, 0x7F, 0x01, 0x01,// T
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,// U
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,// V
|
||||
0x7F, 0x20, 0x18, 0x20, 0x7F,// W
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,// X
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,// Y
|
||||
0x61, 0x51, 0x49, 0x45, 0x43,// Z
|
||||
0x00, 0x00, 0x7F, 0x41, 0x41,// [
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,// "\"
|
||||
0x41, 0x41, 0x7F, 0x00, 0x00,// ]
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,// ^
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,// _
|
||||
0x00, 0x01, 0x02, 0x04, 0x00,// `
|
||||
0x20, 0x54, 0x54, 0x54, 0x78,// a
|
||||
0x7F, 0x48, 0x44, 0x44, 0x38,// b
|
||||
0x38, 0x44, 0x44, 0x44, 0x20,// c
|
||||
0x38, 0x44, 0x44, 0x48, 0x7F,// d
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,// e
|
||||
0x08, 0x7E, 0x09, 0x01, 0x02,// f
|
||||
0x08, 0x14, 0x54, 0x54, 0x3C,// g
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,// h
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,// i
|
||||
0x20, 0x40, 0x44, 0x3D, 0x00,// j
|
||||
0x00, 0x7F, 0x10, 0x28, 0x44,// k
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,// l
|
||||
0x7C, 0x04, 0x18, 0x04, 0x78,// m
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,// n
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,// o
|
||||
0x7C, 0x14, 0x14, 0x14, 0x08,// p
|
||||
0x08, 0x14, 0x14, 0x18, 0x7C,// q
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,// r
|
||||
0x48, 0x54, 0x54, 0x54, 0x20,// s
|
||||
0x04, 0x3F, 0x44, 0x40, 0x20,// t
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,// u
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,// v
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,// w
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,// x
|
||||
0x0C, 0x50, 0x50, 0x50, 0x3C,// y
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,// z
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,// {
|
||||
0x00, 0x00, 0x7F, 0x00, 0x00,// |
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,// }
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
|
||||
|
||||
|
||||
const uint8_t font5x7_data[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // (space)
|
||||
0x00, 0x00, 0x7D, 0x00, 0x00, // !
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, // "
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14, // #
|
||||
0x12, 0x2A, 0x7F, 0x2A, 0x24, // $
|
||||
0x62, 0x64, 0x08, 0x13, 0x23, // %
|
||||
0x36, 0x49, 0x55, 0x22, 0x05, // &
|
||||
0x00, 0x50, 0x60, 0x00, 0x00, // '
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00, // (
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00, // )
|
||||
0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08, // +
|
||||
0x00, 0x05, 0x06, 0x00, 0x00, // ,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, // -
|
||||
0x00, 0x03, 0x03, 0x00, 0x00, // .
|
||||
0x02, 0x04, 0x08, 0x10, 0x20, // /
|
||||
0x3E, 0x45, 0x49, 0x51, 0x3E, // 0
|
||||
0x00, 0x21, 0x7F, 0x01, 0x00, // 1
|
||||
0x21, 0x43, 0x45, 0x49, 0x31, // 2
|
||||
0x42, 0x41, 0x51, 0x69, 0x46, // 3
|
||||
0x0C, 0x14, 0x24, 0x7F, 0x04, // 4
|
||||
0x72, 0x51, 0x51, 0x51, 0x4E, // 5
|
||||
0x1E, 0x29, 0x49, 0x49, 0x06, // 6
|
||||
0x40, 0x47, 0x48, 0x50, 0x60, // 7
|
||||
0x36, 0x49, 0x49, 0x49, 0x36, // 8
|
||||
0x30, 0x49, 0x49, 0x4A, 0x3C, // 9
|
||||
0x00, 0x36, 0x36, 0x00, 0x00, // :
|
||||
0x00, 0x35, 0x36, 0x00, 0x00, // ;
|
||||
0x00, 0x08, 0x14, 0x22, 0x41, // <
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, // =
|
||||
0x41, 0x22, 0x14, 0x08, 0x00, // >
|
||||
0x20, 0x40, 0x45, 0x48, 0x30, // ?
|
||||
0x26, 0x49, 0x4F, 0x41, 0x3E, // @
|
||||
0x3F, 0x44, 0x44, 0x44, 0x3F, // A
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36, // B
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22, // C
|
||||
0x7F, 0x41, 0x41, 0x22, 0x1C, // D
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41, // E
|
||||
0x7F, 0x48, 0x48, 0x40, 0x40, // F
|
||||
0x3E, 0x41, 0x41, 0x45, 0x26, // G
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F, // H
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00, // I
|
||||
0x02, 0x01, 0x41, 0x7E, 0x40, // J
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41, // K
|
||||
0x7F, 0x01, 0x01, 0x01, 0x01, // L
|
||||
0x7F, 0x20, 0x10, 0x20, 0x7F, // M
|
||||
0x7F, 0x10, 0x08, 0x04, 0x7F, // N
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E, // O
|
||||
0x7F, 0x48, 0x48, 0x48, 0x30, // P
|
||||
0x3E, 0x41, 0x45, 0x42, 0x3D, // Q
|
||||
0x7F, 0x48, 0x4C, 0x4A, 0x31, // R
|
||||
0x31, 0x49, 0x49, 0x49, 0x46, // S
|
||||
0x40, 0x40, 0x7F, 0x40, 0x40, // T
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E, // U
|
||||
0x7C, 0x02, 0x01, 0x02, 0x7C, // V
|
||||
0x7F, 0x02, 0x0C, 0x02, 0x7F, // W
|
||||
0x63, 0x14, 0x08, 0x14, 0x63, // X
|
||||
0x60, 0x10, 0x0F, 0x10, 0x60, // Y
|
||||
0x43, 0x45, 0x49, 0x51, 0x61, // Z
|
||||
0x00, 0x00, 0x7F, 0x41, 0x41, // [
|
||||
0x20, 0x10, 0x08, 0x04, 0x02, // backslash
|
||||
0x41, 0x41, 0x7F, 0x00, 0x00, // ]
|
||||
0x10, 0x20, 0x40, 0x20, 0x10, // ^
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, // _
|
||||
0x00, 0x40, 0x20, 0x10, 0x00, // `
|
||||
0x02, 0x15, 0x15, 0x15, 0x0F, // a
|
||||
0x7F, 0x09, 0x11, 0x11, 0x0E, // b
|
||||
0x0E, 0x11, 0x11, 0x11, 0x02, // c
|
||||
0x0E, 0x11, 0x11, 0x09, 0x7F, // d
|
||||
0x0E, 0x15, 0x15, 0x15, 0x0C, // e
|
||||
0x08, 0x3F, 0x48, 0x40, 0x20, // f
|
||||
0x08, 0x14, 0x15, 0x15, 0x1E, // g
|
||||
0x7F, 0x08, 0x10, 0x10, 0x0F, // h
|
||||
0x00, 0x11, 0x5F, 0x01, 0x00, // i
|
||||
0x02, 0x01, 0x11, 0x5E, 0x00, // j
|
||||
0x00, 0x7F, 0x04, 0x0A, 0x11, // k
|
||||
0x00, 0x41, 0x7F, 0x01, 0x00, // l
|
||||
0x1F, 0x10, 0x0C, 0x10, 0x0F, // m
|
||||
0x1F, 0x08, 0x10, 0x10, 0x0F, // n
|
||||
0x0E, 0x11, 0x11, 0x11, 0x0E, // o
|
||||
0x1F, 0x14, 0x14, 0x14, 0x08, // p
|
||||
0x08, 0x14, 0x14, 0x0C, 0x1F, // q
|
||||
0x1F, 0x08, 0x10, 0x10, 0x08, // r
|
||||
0x09, 0x15, 0x15, 0x15, 0x02, // s
|
||||
0x10, 0x7E, 0x11, 0x01, 0x02, // t
|
||||
0x1E, 0x01, 0x01, 0x02, 0x1F, // u
|
||||
0x1C, 0x02, 0x01, 0x02, 0x1C, // v
|
||||
0x1E, 0x01, 0x06, 0x01, 0x1E, // w
|
||||
0x11, 0x0A, 0x04, 0x0A, 0x11, // x
|
||||
0x18, 0x05, 0x05, 0x05, 0x1E, // y
|
||||
0x11, 0x13, 0x15, 0x19, 0x11, // z
|
||||
0x00, 0x08, 0x36, 0x41, 0x00, // {
|
||||
0x00, 0x00, 0x7F, 0x00, 0x00, // |
|
||||
0x00, 0x41, 0x36, 0x08, 0x00, // }
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08, // <-
|
||||
};
|
||||
|
||||
bool font5x7_check(const char c) { return c>=' ' && c<='}'; }
|
||||
|
||||
*/
|
||||
uint16_t font5x7_get(const char c) { return c - ' '; }
|
||||
|
||||
Font font5x7 = {5, 7, &font5x7_data[0], font5x7_check, font5x7_get};
|
||||
|
||||
|
||||
|
||||
|
20
src/mqtt.cpp
@ -23,7 +23,10 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) {
|
||||
pl[length] = '\0';
|
||||
String payload((char*)pl);
|
||||
String topic (original_topic);
|
||||
if (topic.compareTo(MQTT_TOPIC "log")==0) return;
|
||||
if (topic.equals(MQTT_TOPIC "log") || topic.equals(MQTT_TOPIC "status") || topic.equals(MQTT_TOPIC "metrics")) {
|
||||
// Return our own messages
|
||||
return;
|
||||
}
|
||||
LOGln("MQTT * In: %s = %s", topic.c_str(), payload.c_str());
|
||||
if (topic.startsWith(MQTT_TOPIC_WEATHER)) {
|
||||
// Weather stuff
|
||||
@ -51,11 +54,6 @@ void mqtt_callback(char* original_topic, byte* pl, unsigned int length) {
|
||||
|
||||
topic.remove(0, strlen(MQTT_TOPIC)); // Strip MQTT_TOPIC from the beginning
|
||||
|
||||
if (topic.compareTo("free_heap")==0 || topic.compareTo("uptime")==0 || topic.compareTo("status")==0 || topic.compareTo("fps")==0) {
|
||||
// Ignore our own messages.
|
||||
return;
|
||||
}
|
||||
|
||||
if(topic.compareTo("mode")==0) {
|
||||
LOGln("MQTT * Changing mode...");
|
||||
bool result = change_current_effect(payload);
|
||||
@ -125,11 +123,15 @@ void mqtt_loop() {
|
||||
String mqtt_log_str = String();
|
||||
|
||||
void mqtt_publish(const char* topic, int number) {
|
||||
char t[127];
|
||||
sprintf(t, MQTT_TOPIC "%s", topic);
|
||||
char b[32];
|
||||
sprintf(b, "%d", number);
|
||||
mqtt_client.publish(t, b);
|
||||
mqtt_publish(topic, b);
|
||||
}
|
||||
|
||||
void mqtt_publish(const char* topic, const char* message) {
|
||||
char t[127];
|
||||
sprintf(t, MQTT_TOPIC "%s", topic);
|
||||
mqtt_client.publish(t, message);
|
||||
}
|
||||
|
||||
void mqtt_log(const char* message) {
|
||||
|
@ -19,6 +19,10 @@ char hostname[30]; // defined as extern in prototypes.h
|
||||
#ifdef RECORDER_ENABLE
|
||||
Recorder* recorder;
|
||||
#endif
|
||||
#ifdef MQTT_REPORT_METRICS
|
||||
uint16_t metrics_frame_count = 0;
|
||||
unsigned long metrics_frame_time = 0;
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(74880);
|
||||
@ -88,9 +92,13 @@ void loop() {
|
||||
//LOGln("Core * loop ran");
|
||||
|
||||
if (current_effect->can_be_shown_with_clock()) {
|
||||
effect_clock.loop(current_effect->clock_as_mask(), CRGB(0xFFFFFF), CRGB(0x000000));
|
||||
effect_clock.loop_with_invert(current_effect->clock_as_mask());
|
||||
}
|
||||
FastLED.show();
|
||||
#ifdef MQTT_REPORT_METRICS
|
||||
metrics_frame_count++;
|
||||
metrics_frame_time += (millis() - loop_started_at);
|
||||
#endif
|
||||
|
||||
#ifdef RECORDER_ENABLE
|
||||
recorder->loop();
|
||||
@ -99,9 +107,11 @@ void loop() {
|
||||
|
||||
#if defined(MQTT_ENABLE) && defined(MQTT_REPORT_METRICS)
|
||||
EVERY_N_SECONDS(15) {
|
||||
mqtt_publish("free_heap", ESP.getFreeHeap());
|
||||
mqtt_publish("uptime", millis()/1000);
|
||||
mqtt_publish("fps", FastLED.getFPS());
|
||||
char json[120];
|
||||
snprintf(json, 120, "{\"effect\":\"%s\",\"heap\":%u, \"up\":%lu, \"fps\":%d, \"frametime\":%lu}", current_effect->get_name().c_str(), ESP.getFreeHeap(), millis()/1000, FastLED.getFPS(), metrics_frame_time / metrics_frame_count);
|
||||
mqtt_publish("metrics", json);
|
||||
metrics_frame_count = 0;
|
||||
metrics_frame_time = 0;
|
||||
}
|
||||
#endif // MQTT_REPORT_METRICS
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "my_fastled.h"
|
||||
#include "functions.h"
|
||||
#include "effects.h"
|
||||
#include "Window.h"
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifdef RECORDER_ENABLE
|
||||
@ -37,6 +38,7 @@ Recorder::Recorder() {
|
||||
} else if (*(char*)data == 'E') {
|
||||
String effect = String(((char*)(data+1)));
|
||||
LOGln("Recorder * Setting effect %s", effect.c_str());
|
||||
Window::getFullWindow()->clear();
|
||||
change_current_effect(effect);
|
||||
}
|
||||
}, NULL);
|
||||
@ -47,6 +49,8 @@ Recorder::Recorder() {
|
||||
|
||||
void Recorder::loop() {
|
||||
if (_client && _client_port) {
|
||||
_skip_next_frame = !_skip_next_frame;
|
||||
if (_skip_next_frame == false) return;
|
||||
_buffer[0] = _msgid >> 8;
|
||||
_buffer[1] = _msgid & 0xFF;
|
||||
for (uint8_t y=0; y<LED_HEIGHT; y++) for(uint8_t x=0; x<LED_WIDTH; x++) {
|
||||
|
@ -15,7 +15,8 @@ for effect in $EFFECTS; do
|
||||
echo " + ./recorder.rb $IP /tmp/effect.gif $effect"
|
||||
./recorder.rb $IP /tmp/effect.gif $effect
|
||||
echo
|
||||
#echo " + gifsicle /tmp/effect.gif -o ../../docs/effects/$effect.gif"
|
||||
#gifsicle /tmp/effect.gif -o ../../docs/effects/$effect.gif
|
||||
mv /tmp/effect.gif ../../docs/effects/$effect.gif
|
||||
echo " + gifsicle /tmp/effect.gif -O -o ../../docs/effects/$effect.gif"
|
||||
gifsicle /tmp/effect.gif -O -o ../../docs/effects/$effect.gif
|
||||
#mv /tmp/effect.gif ../../docs/effects/$effect.gif
|
||||
#ffmpeg -i /tmp/effect.gif -y -c vp9 -b:v 0 -crf 41 ../../docs/effects/$effect.webm
|
||||
done
|
||||
|
@ -10,7 +10,7 @@ PORT = 2122
|
||||
FILE = ARGV[1] or raise "No filename given"
|
||||
EFFECT = ARGV[2]
|
||||
FRAMES = 125
|
||||
FACTOR = 1
|
||||
FACTOR = 2
|
||||
delay = 50
|
||||
|
||||
puts "Connecting to #{IP}:#{PORT}..."
|
||||
@ -59,7 +59,6 @@ while gif.length < FRAMES do
|
||||
last_id = id
|
||||
|
||||
img = Image.new(dim_x, dim_y)
|
||||
img.delay = 1
|
||||
gc = Draw.new
|
||||
|
||||
#next
|
||||
@ -81,6 +80,7 @@ s.close
|
||||
puts
|
||||
puts "Generating gif..."
|
||||
gif.ticks_per_second = 100
|
||||
gif.delay = 4
|
||||
gif.write(FILE)
|
||||
puts
|
||||
puts
|
||||
|