Compare commits

..

6 Commits

14 changed files with 170 additions and 259 deletions

25
diagram.json Normal file
View File

@ -0,0 +1,25 @@
{
"version": 1,
"author": "Uri Shaked",
"editor": "wokwi",
"parts": [
{ "type": "board-xiao-esp32-s3", "id": "esp", "top": 1000, "left": 13.78, "attrs": {} },
{
"id": "neopixels",
"type": "wokwi-neopixel-canvas",
"top": 0,
"left": 0,
"attrs": {
"rows": "32",
"cols": "32",
"matrixBrightness": "10"
}
}
],
"connections": [
["esp:GND", "neopixels:VSS", "black"],
["esp:D5", "neopixels:DIN", "green"],
["esp:5V", "neopixels:VDD", "red"]
],
"dependencies": {}
}

View File

@ -1,33 +0,0 @@
#ifndef ACTION_H
#define ACTION_H
#include "Arduino.h"
#include "functional"
#include "StreamEvent.h"
template <typename T>
class Action {
public:
Action(function<bool(StreamEvent*)> _funcEventMatchesAction, function<T*(StreamEvent*)> _funcInvokeAction,
function<void(Print*)> _funcDescribeAction) : funcEventMatchesAction(_funcEventMatchesAction),
funcInvokeAction(_funcInvokeAction), funcDescribeAction(_funcDescribeAction) {}
bool eventMatchesAction(StreamEvent* event) {
return funcEventMatchesAction(event);
}
void describeAction(Print* printStream) {
funcDescribeAction(printStream);
}
T* invokeAction(StreamEvent* event) {
return funcInvokeAction(event);
}
private:
function<bool(StreamEvent*)> funcEventMatchesAction;
function<T*(StreamEvent*)> funcInvokeAction;
function<void(Print*)> funcDescribeAction;
};
#endif

View File

@ -60,7 +60,7 @@ class CLEDControllerPhysicalMatrix : public LEDHAL2D {
protected: protected:
void updateLEDs() { void updateLEDs() {
controller->showLeds(); controller->showLeds(255);
} }
private: private:

View File

@ -13,7 +13,7 @@ class CLEDControllerPhysicalStrip : public LEDHAL {
void setColor(int16_t pixel, CRGB color) { controller->leds()[pixel] = color; } void setColor(int16_t pixel, CRGB color) { controller->leds()[pixel] = color; }
protected: protected:
void updateLEDs() { controller->showLeds(); } void updateLEDs() { controller->showLeds(255); }
private: private:

View File

@ -23,9 +23,9 @@ class CycloneHelper {
for(uint8_t i = 0; i < numberOfTails; i++) { for(uint8_t i = 0; i < numberOfTails; i++) {
tailColors[i] = CRGB( tailColors[i] = CRGB(
min(round(redScaler * (i + 1)), color.red), min(round(redScaler * (i + 1)), (float)color.red),
min(round(greenScaler * (i + 1)), color.green), min(round(greenScaler * (i + 1)), (float)color.green),
min(round(blueScaler * (i + 1)), color.blue) min(round(blueScaler * (i + 1)), (float)color.blue)
); );
} }

View File

@ -1,41 +0,0 @@
#ifndef GULLSMANAGER_H
#define GULLSMANAGER_H
#include "Arduino.h"
#include "Action.h"
#include "LEDHAL.h"
#include "AnimationBase.h"
class GULLSManager {
public:
GULLSManager(Stream* _stream, uint16_t _maxHALs, uint16_t _maxAnimations,
uint16_t _maxResponseActions, uint16_t _maxAnimationBuilderActions);
bool addLEDHAL(LEDHAL* hal);
bool addAnimation(AnimationBase* animation);
bool addResponseAction(Action<char>* action);
bool addAnimationBuilderAction(Action<AnimationBase>* action);
void update();
private:
uint16_t
maxHALs,
maxAnimations,
maxResponseActions,
maxAnimationBuilderActions;
Stream*
stream;
LEDHAL**
hals;
AnimationBase**
animations;
Action<char>**
responseActions;
Action<AnimationBase>**
animationBuilderActions;
};
#endif

View File

@ -6,38 +6,11 @@
class PlasmaMatrix : public MatrixAnimation { class PlasmaMatrix : public MatrixAnimation {
public: public:
PlasmaMatrix(LEDHAL2D* _matrix, char* _refName, long _updateTime) : PlasmaMatrix(LEDHAL2D* _matrix, char* _refName, long _updateTime);
MatrixAnimation(_matrix, _refName, _updateTime), paletteShift(0), palette(new CRGB[256]) {
plasma = new uint8_t*[matrix->getWidth()];
for(uint16_t i = 0; i < matrix->getWidth(); i++) { virtual ~PlasmaMatrix();
plasma[i] = new uint8_t[matrix->getHeight()];
}
for(uint16_t x = 0; x < matrix->getWidth(); x++) { void initialize();
for(uint16_t y = 0; y < matrix->getHeight(); y++) {
plasma[x][y] = (uint8_t) ((128.0 + (128 * sinf(x / 8.0)) + 128 + (128.0 * sinf(y / 8.0))) / 2);
}
}
for(uint16_t i = 0; i < 256; i++) {
palette[i] = CRGB(CHSV(i, 255, 255));
}
}
virtual ~PlasmaMatrix() {
delete[] palette;
for(uint16_t i = 0; i < matrix->getWidth(); i++) {
delete[] plasma[i];
}
delete[] plasma;
}
void initialize() {
paletteShift = 0;
}
void execute(); void execute();

View File

@ -1,6 +1,9 @@
#ifndef SMARTMATRIXPHYSICALMATRIX_H #ifndef SMARTMATRIXPHYSICALMATRIX_H
#define SMARTMATRIXPHYSICALMATRIX_H #define SMARTMATRIXPHYSICALMATRIX_H
#ifdef CORE_TEENSY
#ifdef ENABLE_TEENSY_SMARTMATRIX
#include "SmartMatrix.h" #include "SmartMatrix.h"
#include "LEDHAL2D.h" #include "LEDHAL2D.h"
@ -43,4 +46,6 @@ class SmartMatrixPhysicalMatrix : public LEDHAL2D {
SMLayerBackground<rgb24, 0>* layer; SMLayerBackground<rgb24, 0>* layer;
}; };
#endif
#endif
#endif #endif

View File

@ -10,6 +10,7 @@ class StreamEvent
handled = false; handled = false;
code = _readFrom->read(); code = _readFrom->read();
subCode = _readFrom->read();
flags = _readFrom->read(); flags = _readFrom->read();
if (flags & 0x01 == 1) { if (flags & 0x01 == 1) {
@ -32,6 +33,8 @@ class StreamEvent
uint8_t getCode() { return code; } uint8_t getCode() { return code; }
uint8_t getSubCode() { return subCode; }
uint16_t getPayloadSize() { return payloadSize; } uint16_t getPayloadSize() { return payloadSize; }
byte* getPayload() { return payload; } byte* getPayload() { return payload; }
@ -40,7 +43,7 @@ class StreamEvent
bool isResponse() { return flags & 0x02 == 2; } bool isResponse() { return flags & 0x02 == 2; }
bool isDescribeRequest() { return flags & 0x04 == 4; } bool isDescribeRequest() { return flags & 0x04 == 4; }
virtual ~StreamEvent() { delete[] payload; } ~StreamEvent() { delete[] payload; }
private: private:
byte* byte*
@ -49,6 +52,7 @@ class StreamEvent
payloadSize; payloadSize;
uint8_t uint8_t
code, code,
subCode,
flags; flags;
bool bool
handled; handled;

View File

@ -9,16 +9,45 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
default_envs = teensy36 default_envs =
esp32
[common] [common]
[env:teensy36] [env:teensy36]
platform = teensy platform = teensy
framework = arduino
board = teensy36 board = teensy36
framework = arduino
lib_deps = lib_deps =
fastled/FastLED@^3.7.0 fastled/FastLED@3.10.1
pixelmatix/SmartMatrix@^4.0.3 pfeerick/elapsedMillis@^1.0.6
adafruit/Adafruit GFX Library@^1.11.9
[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_deps =
fastled/FastLED@3.10.1
pfeerick/elapsedMillis@^1.0.6
adafruit/Adafruit GFX Library@^1.11.9
arduino-libraries/SD@^1.3.0
[env:mega2560]
platform = atmelavr
board = megaatmega2560
framework = arduino
lib_deps =
fastled/FastLED@3.10.1
pfeerick/elapsedMillis@^1.0.6
adafruit/Adafruit GFX Library@^1.11.9
arduino-libraries/SD@^1.3.0
[env:esp32]
platform = espressif32
board = adafruit_feather_esp32s3_nopsram
framework = arduino
lib_deps =
fastled/FastLED@3.10.1
pfeerick/elapsedMillis@^1.0.6 pfeerick/elapsedMillis@^1.0.6
adafruit/Adafruit GFX Library@^1.11.9 adafruit/Adafruit GFX Library@^1.11.9

View File

@ -1,127 +0,0 @@
#include "GULLSManager.h"
GULLSManager::GULLSManager(Stream* _stream, uint16_t _maxHALs, uint16_t _maxAnimations,
uint16_t _maxResponseActions, uint16_t _maxAnimationBuilderActions) {
stream = _stream;
maxHALs = _maxHALs;
maxAnimations = _maxAnimations;
maxResponseActions = _maxResponseActions;
maxAnimationBuilderActions = _maxAnimationBuilderActions;
hals = new LEDHAL*[maxHALs];
for(uint16_t i = 0; i < maxHALs; i++) {
hals[i] = nullptr;
}
animations = new AnimationBase*[maxAnimations];
for(uint16_t i = 0; i < maxAnimations; i++) {
animations[i] = nullptr;
}
responseActions = new Action<char>*[maxResponseActions];
for(uint16_t i = 0; i < maxResponseActions; i++) {
responseActions[i] = nullptr;
}
animationBuilderActions = new Action<AnimationBase>*[maxAnimationBuilderActions];
for(uint16_t i = 0; i < maxAnimationBuilderActions; i++) {
animationBuilderActions[i] = nullptr;
}
}
bool GULLSManager::addLEDHAL(LEDHAL* hal) {
for(uint16_t i = 0; i < maxHALs; i++) {
if(hals[i] == nullptr) {
hals[i] = hal;
return true;
}
}
return false;
}
bool GULLSManager::addAnimation(AnimationBase* animation) {
for(uint16_t i = 0; i < maxAnimations; i++) {
if(animations[i] == nullptr) {
animations[i] = animation;
return true;
}
}
return false;
}
bool GULLSManager::addResponseAction(Action<char>* action) {
for(uint16_t i = 0; i < maxResponseActions; i++) {
if(responseActions[i] == nullptr) {
responseActions[i] = action;
return true;
}
}
return false;
}
bool GULLSManager::addAnimationBuilderAction(Action<AnimationBase>* action) {
for(uint16_t i = 0; i < maxAnimationBuilderActions; i++) {
if(animationBuilderActions[i] == nullptr) {
animationBuilderActions[i] = action;
return true;
}
}
return false;
}
void GULLSManager::update() {
if(stream->available()) {
StreamEvent event(stream);
for(uint16_t i = 0; i < maxResponseActions; i++) {
if(responseActions[i] != nullptr) {
if(responseActions[i]->eventMatchesAction(&event)) {
stream->write(responseActions[i]->invokeAction(&event));
event.markHandled();
break;
}
}
}
if(!event.isHandled()) {
for(uint16_t i = 0; i < maxAnimationBuilderActions; i++) {
if(animationBuilderActions[i] != nullptr) {
if(animationBuilderActions[i]->eventMatchesAction(&event)) {
this->addAnimation(animationBuilderActions[i]->invokeAction(&event));
event.markHandled();
break;
}
}
}
}
if(!event.isHandled()) {
stream->print(F("ERROR: An event with code "));
stream->print(event.getCode());
stream->println(F(" was registered but went unprocessed by any actions!"));
}
}
for(uint16_t i = 0; i < maxAnimations; i++) {
if(animations[i] != nullptr) {
animations[i]->update();
}
}
for(uint16_t i = 0; i < maxHALs; i++) {
if(hals[i] != nullptr) {
hals[i]->show();
}
}
}

View File

@ -1,5 +1,38 @@
#include "PlasmaMatrix.h" #include "PlasmaMatrix.h"
PlasmaMatrix::PlasmaMatrix(LEDHAL2D* _matrix, char* _refName, long _updateTime):
MatrixAnimation(_matrix, _refName, _updateTime), paletteShift(0), palette(new CRGB[256]) {
plasma = new uint8_t*[matrix->getWidth()];
for(uint16_t i = 0; i < matrix->getWidth(); i++) {
plasma[i] = new uint8_t[matrix->getHeight()];
}
for(uint16_t x = 0; x < matrix->getWidth(); x++) {
for(uint16_t y = 0; y < matrix->getHeight(); y++) {
plasma[x][y] = (uint8_t) ((128.0 + (128 * sinf(x / 8.0)) + 128 + (128.0 * sinf(y / 8.0))) / 2);
}
}
for(uint16_t i = 0; i < 256; i++) {
palette[i] = CRGB(CHSV(i, 255, 255));
}
}
PlasmaMatrix::~PlasmaMatrix() {
delete[] palette;
for(uint16_t i = 0; i < matrix->getWidth(); i++) {
delete[] plasma[i];
}
delete[] plasma;
}
void PlasmaMatrix::initialize() {
paletteShift = 0;
}
void PlasmaMatrix::execute() { void PlasmaMatrix::execute() {
for(uint16_t x = 0; x < matrix->getWidth(); x++) { for(uint16_t x = 0; x < matrix->getWidth(); x++) {
for(uint16_t y = 0; y < matrix->getHeight(); y++) { for(uint16_t y = 0; y < matrix->getHeight(); y++) {
@ -9,5 +42,7 @@ void PlasmaMatrix::execute() {
} }
} }
paletteShift++;
matrix->requestShow(); matrix->requestShow();
} }

View File

@ -1,17 +1,33 @@
#include <Arduino.h> #include <Arduino.h>
#ifdef CORE_TEENSY
#ifdef ENABLE_TEENSY_SMARTMATRIX
#include "MatrixHardware_Teensy3_ShieldV1toV3.h" #include "MatrixHardware_Teensy3_ShieldV1toV3.h"
#include "SmartMatrix.h" #include "SmartMatrix.h"
#endif
#endif
#include "FastLED.h" #include "FastLED.h"
#include "LEDHAL.h" #include "LEDHAL.h"
#include "LEDHAL2D.h" #include "LEDHAL2D.h"
#include "MatrixAnimation.h"
#include "AlternateMatrix.h"
#include "CollisionMatrix.h"
#include "ColorRandomizerMatrix.h"
#include "CycleLightMatrix.h"
#include "FireworksMatrix.h"
#include "FluidColorMatrix.h"
#include "RicochetMatrix.h"
#include "CycloneMatrix.h"
#include "PlasmaMatrix.h"
#include "CLEDControllerPhysicalStrip.h" #include "CLEDControllerPhysicalStrip.h"
#include "CLEDControllerPhysicalMatrix.h" #include "CLEDControllerPhysicalMatrix.h"
#include "SmartMatrixPhysicalMatrix.h" #include "SmartMatrixPhysicalMatrix.h"
#define NUMLEDS 24 #define NUMLEDS 1024
#ifdef CORE_TEENSY
#ifdef ENABLE_TEENSY_SMARTMATRIX
#define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24 #define COLOR_DEPTH 24 // known working: 24, 48 - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24
const uint8_t kMatrixWidth = 96; // known working: 32, 64, 96, 128 const uint8_t kMatrixWidth = 96; // known working: 32, 64, 96, 128
@ -25,35 +41,56 @@ const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);
SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions); SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth, kMatrixHeight, kRefreshDepth, kDmaBufferRows, kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kBackgroundLayerOptions); SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer, kMatrixWidth, kMatrixHeight, COLOR_DEPTH, kBackgroundLayerOptions);
#endif
#endif
CRGB leds[NUMLEDS]; CRGB leds[NUMLEDS];
CRGB leds2[NUMLEDS]; CRGB rainbow[] = {CRGB::Red, CRGB(255, 45, 0), CRGB::Yellow, CRGB::Green, CRGB::Blue, CRGB::Purple};
CRGB leds3[NUMLEDS];
CRGB someColor(255, 255, 255);
LEDHAL* hal;
LEDHAL2D* hal2D; LEDHAL2D* hal2D;
LEDHAL2D* smHAL;
rgb24 canRGB24Translate(rgb24 color) { MatrixAnimation* animation;
color.red = 0;
return color; int animationCode = 8;
}
void setup() { void setup() {
CLEDController* controller = &FastLED.addLeds<NEOPIXEL, 6>(leds, NUMLEDS); CLEDController* controller = &FastLED.addLeds<NEOPIXEL, 6>(leds, NUMLEDS);
CLEDController* controller2d = &FastLED.addLeds<NEOPIXEL, 7>(leds2, NUMLEDS); controller->setCorrection(TypicalLEDStrip);
hal = new CLEDControllerPhysicalStrip(controller, "Test Strip"); hal2D = new CLEDControllerPhysicalMatrix(controller, "Matrix", ArrangementType::HORIZONTALSCAN, 32, 32);
hal2D = new CLEDControllerPhysicalMatrix(controller2d, "Test Matrix", ArrangementType::COLUMNSERPENTINE, 6, 4);
smHAL = new SmartMatrixPhysicalMatrix(&backgroundLayer, "Test SM Matrix", kMatrixWidth, kMatrixHeight); if(animationCode == 0) {
animation = new PlasmaMatrix(hal2D, "Plasma Matrix", 10);
canRGB24Translate(someColor); } else if(animationCode == 1) {
animation = new AlternateMatrix(hal2D, "Alternate Matrix", 125, rainbow, 6, AlternateType::HORIZONTAL_ALTERNATE);
} else if(animationCode == 2) {
animation = new CollisionMatrix(hal2D, "Collision Matrix", 125, CRGB(255, 45, 0), CRGB::Green, CollisionType::HORIZONTAL_COLLISION);
} else if(animationCode == 3) {
//Doesn't work, causing heap corruption
animation = new ColorRandomizerMatrix(hal2D, "Color Randomizer Matrix",
40, true, 6, rainbow, ColorRandomizerType::HORIZONTAL_COLORRANDOMIZER);
} else if(animationCode == 4) {
animation = new CycleLightMatrix(hal2D, "Cycle Light Matrix", 100, rainbow, 6, CycleLightType::HORIZONTAL_CYCLELIGHT);
} else if(animationCode == 5) {
//Doesn't work, unhandled exception?
animation = new FireworksMatrix(hal2D, "Fireworks Matrix", 40, rainbow, 6, 6, 15);
} else if(animationCode == 6) {
//Sort of works, mathematical issues exist when using anything other than full color resolution
animation = new FluidColorMatrix(hal2D, "Fluid Color Matrix", 20, FluidColorType::HORIZONTAL_FLUIDCOLOR, FluidColorResolution::QUATER_FLUIDCOLOR);
} else if(animationCode == 7) {
//Doesn't work, causing heap corruption
animation = new RicochetMatrix(hal2D, "Ricochet Matrix", 50, 16, rainbow, 6);
} else if(animationCode == 8) {
//It works, kinda? It doesn't look like the original version of the animation
animation = new CycloneMatrix(hal2D, "Cyclone Matrix", 100, 16, 16, 4, 16, 6, rainbow);
}
animation->enable();
} }
void loop() { void loop() {
// put your main code here, to run repeatedly: animation->update();
hal2D->show();
} }

4
wokwi.toml Normal file
View File

@ -0,0 +1,4 @@
[wokwi]
version = 1
firmware = '.pio/build/esp32/firmware.bin'
elf = '.pio/build/esp32/firmware.elf'