aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorKosso <kosso1@gmail.com>2020-09-13 15:56:29 +0100
committerKosso <kosso1@gmail.com>2020-09-13 15:56:29 +0100
commit0e4e9738b6ecbffa260cc8e5e8e4c4d9f1bf6499 (patch)
treeff2a812bd892cef0ec792b583df3fbab07d67f2b /examples
parenta3aedaefb1326c5781646a8a51c5d83e61dc0a57 (diff)
Kosso: Updated Aurora demo for chained virtual displays. Added a better Fire demo. Removed some old Aurora demos which just didn't work and saves some memory.
Diffstat (limited to 'examples')
-rw-r--r--examples/ChainedPanelsAuroraDemo/Attractor.h50
-rw-r--r--examples/ChainedPanelsAuroraDemo/Boid.h326
-rw-r--r--examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino181
-rw-r--r--examples/ChainedPanelsAuroraDemo/Drawable.h50
-rw-r--r--examples/ChainedPanelsAuroraDemo/Effects.h914
-rw-r--r--examples/ChainedPanelsAuroraDemo/Geometry.h150
-rw-r--r--examples/ChainedPanelsAuroraDemo/PaletteFireKoz.h6
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternAttract.h73
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h116
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternFire.h121
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternFireKoz.h109
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternFlock.h125
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternFlowField.h92
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h51
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternInfinity.h58
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternLife.h129
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternMaze.h264
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternMunch.h74
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h338
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h56
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternPlasma.h66
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternRadar.h56
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h79
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternSnake.h145
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternSpiral.h138
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternSpiro.h107
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternSwirl.h77
-rw-r--r--examples/ChainedPanelsAuroraDemo/PatternWave.h120
-rw-r--r--examples/ChainedPanelsAuroraDemo/Patterns.h259
-rw-r--r--examples/ChainedPanelsAuroraDemo/Playlist.h39
-rw-r--r--examples/ChainedPanelsAuroraDemo/Vector.h169
31 files changed, 4538 insertions, 0 deletions
diff --git a/examples/ChainedPanelsAuroraDemo/Attractor.h b/examples/ChainedPanelsAuroraDemo/Attractor.h
new file mode 100644
index 0000000..5a03511
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Attractor.h
@@ -0,0 +1,50 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from "Attractor" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
+ * Copyright (c) 2014 Daniel Shiffman
+ * http://www.shiffman.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "Vector.h"
+
+class Attractor {
+public:
+ float mass; // Mass, tied to size
+ float G; // Gravitational Constant
+ PVector location; // Location
+
+ Attractor() {
+ location = PVector(MATRIX_CENTRE_X, MATRIX_CENTRE_Y);
+ mass = 8;
+ G = .5;
+ }
+
+ PVector attract(Boid m) {
+ PVector force = location - m.location; // Calculate direction of force
+ float d = force.mag(); // Distance between objects
+ d = constrain(d, 5.0, 32.0); // Limiting the distance to eliminate "extreme" results for very close or very far objects
+ force.normalize(); // Normalize vector (distance doesn't matter here, we just want this vector for direction)
+ float strength = (G * mass * m.mass) / (d * d); // Calculate gravitional force magnitude
+ force *= strength; // Get force vector --> magnitude * direction
+ return force;
+ }
+};
diff --git a/examples/ChainedPanelsAuroraDemo/Boid.h b/examples/ChainedPanelsAuroraDemo/Boid.h
new file mode 100644
index 0000000..fa5a9e6
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Boid.h
@@ -0,0 +1,326 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
+ * Copyright (c) 2014 Daniel Shiffman
+ * http://www.shiffman.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+// Flocking
+// Daniel Shiffman <http://www.shiffman.net>
+// The Nature of Code, Spring 2009
+
+// Boid class
+// Methods for Separation, Cohesion, Alignment added
+
+class Boid {
+ public:
+
+ PVector location;
+ PVector velocity;
+ PVector acceleration;
+ float maxforce; // Maximum steering force
+ float maxspeed; // Maximum speed
+
+ float desiredseparation = 4;
+ float neighbordist = 8;
+ byte colorIndex = 0;
+ float mass;
+
+ boolean enabled = true;
+
+ Boid() {}
+
+ Boid(float x, float y) {
+ acceleration = PVector(0, 0);
+ velocity = PVector(randomf(), randomf());
+ location = PVector(x, y);
+ maxspeed = 1.5;
+ maxforce = 0.05;
+ }
+
+ static float randomf() {
+ return mapfloat(random(0, 255), 0, 255, -.5, .5);
+ }
+
+ static float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
+ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+ }
+
+ void run(Boid boids [], uint8_t boidCount) {
+ flock(boids, boidCount);
+ update();
+ // wrapAroundBorders();
+ // render();
+ }
+
+ // Method to update location
+ void update() {
+ // Update velocity
+ velocity += acceleration;
+ // Limit speed
+ velocity.limit(maxspeed);
+ location += velocity;
+ // Reset acceleration to 0 each cycle
+ acceleration *= 0;
+ }
+
+ void applyForce(PVector force) {
+ // We could add mass here if we want A = F / M
+ acceleration += force;
+ }
+
+ void repelForce(PVector obstacle, float radius) {
+ //Force that drives boid away from obstacle.
+
+ PVector futPos = location + velocity; //Calculate future position for more effective behavior.
+ PVector dist = obstacle - futPos;
+ float d = dist.mag();
+
+ if (d <= radius) {
+ PVector repelVec = location - obstacle;
+ repelVec.normalize();
+ if (d != 0) { //Don't divide by zero.
+ // float scale = 1.0 / d; //The closer to the obstacle, the stronger the force.
+ repelVec.normalize();
+ repelVec *= (maxforce * 7);
+ if (repelVec.mag() < 0) { //Don't let the boids turn around to avoid the obstacle.
+ repelVec.y = 0;
+ }
+ }
+ applyForce(repelVec);
+ }
+ }
+
+ // We accumulate a new acceleration each time based on three rules
+ void flock(Boid boids [], uint8_t boidCount) {
+ PVector sep = separate(boids, boidCount); // Separation
+ PVector ali = align(boids, boidCount); // Alignment
+ PVector coh = cohesion(boids, boidCount); // Cohesion
+ // Arbitrarily weight these forces
+ sep *= 1.5;
+ ali *= 1.0;
+ coh *= 1.0;
+ // Add the force vectors to acceleration
+ applyForce(sep);
+ applyForce(ali);
+ applyForce(coh);
+ }
+
+ // Separation
+ // Method checks for nearby boids and steers away
+ PVector separate(Boid boids [], uint8_t boidCount) {
+ PVector steer = PVector(0, 0);
+ int count = 0;
+ // For every boid in the system, check if it's too close
+ for (int i = 0; i < boidCount; i++) {
+ Boid other = boids[i];
+ if (!other.enabled)
+ continue;
+ float d = location.dist(other.location);
+ // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
+ if ((d > 0) && (d < desiredseparation)) {
+ // Calculate vector pointing away from neighbor
+ PVector diff = location - other.location;
+ diff.normalize();
+ diff /= d; // Weight by distance
+ steer += diff;
+ count++; // Keep track of how many
+ }
+ }
+ // Average -- divide by how many
+ if (count > 0) {
+ steer /= (float) count;
+ }
+
+ // As long as the vector is greater than 0
+ if (steer.mag() > 0) {
+ // Implement Reynolds: Steering = Desired - Velocity
+ steer.normalize();
+ steer *= maxspeed;
+ steer -= velocity;
+ steer.limit(maxforce);
+ }
+ return steer;
+ }
+
+ // Alignment
+ // For every nearby boid in the system, calculate the average velocity
+ PVector align(Boid boids [], uint8_t boidCount) {
+ PVector sum = PVector(0, 0);
+ int count = 0;
+ for (int i = 0; i < boidCount; i++) {
+ Boid other = boids[i];
+ if (!other.enabled)
+ continue;
+ float d = location.dist(other.location);
+ if ((d > 0) && (d < neighbordist)) {
+ sum += other.velocity;
+ count++;
+ }
+ }
+ if (count > 0) {
+ sum /= (float) count;
+ sum.normalize();
+ sum *= maxspeed;
+ PVector steer = sum - velocity;
+ steer.limit(maxforce);
+ return steer;
+ }
+ else {
+ return PVector(0, 0);
+ }
+ }
+
+ // Cohesion
+ // For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
+ PVector cohesion(Boid boids [], uint8_t boidCount) {
+ PVector sum = PVector(0, 0); // Start with empty vector to accumulate all locations
+ int count = 0;
+ for (int i = 0; i < boidCount; i++) {
+ Boid other = boids[i];
+ if (!other.enabled)
+ continue;
+ float d = location.dist(other.location);
+ if ((d > 0) && (d < neighbordist)) {
+ sum += other.location; // Add location
+ count++;
+ }
+ }
+ if (count > 0) {
+ sum /= count;
+ return seek(sum); // Steer towards the location
+ }
+ else {
+ return PVector(0, 0);
+ }
+ }
+
+ // A method that calculates and applies a steering force towards a target
+ // STEER = DESIRED MINUS VELOCITY
+ PVector seek(PVector target) {
+ PVector desired = target - location; // A vector pointing from the location to the target
+ // Normalize desired and scale to maximum speed
+ desired.normalize();
+ desired *= maxspeed;
+ // Steering = Desired minus Velocity
+ PVector steer = desired - velocity;
+ steer.limit(maxforce); // Limit to maximum steering force
+ return steer;
+ }
+
+ // A method that calculates a steering force towards a target
+ // STEER = DESIRED MINUS VELOCITY
+ void arrive(PVector target) {
+ PVector desired = target - location; // A vector pointing from the location to the target
+ float d = desired.mag();
+ // Normalize desired and scale with arbitrary damping within 100 pixels
+ desired.normalize();
+ if (d < 4) {
+ float m = map(d, 0, 100, 0, maxspeed);
+ desired *= m;
+ }
+ else {
+ desired *= maxspeed;
+ }
+
+ // Steering = Desired minus Velocity
+ PVector steer = desired - velocity;
+ steer.limit(maxforce); // Limit to maximum steering force
+ applyForce(steer);
+ //Serial.println(d);
+ }
+
+ void wrapAroundBorders() {
+ if (location.x < 0) location.x = VPANEL_W - 1;
+ if (location.y < 0) location.y = VPANEL_H - 1;
+ if (location.x >= VPANEL_W) location.x = 0;
+ if (location.y >= VPANEL_H) location.y = 0;
+ }
+
+ void avoidBorders() {
+ PVector desired = velocity;
+
+ if (location.x < 8) desired = PVector(maxspeed, velocity.y);
+ if (location.x >= VPANEL_W - 8) desired = PVector(-maxspeed, velocity.y);
+ if (location.y < 8) desired = PVector(velocity.x, maxspeed);
+ if (location.y >= VPANEL_H - 8) desired = PVector(velocity.x, -maxspeed);
+
+ if (desired != velocity) {
+ PVector steer = desired - velocity;
+ steer.limit(maxforce);
+ applyForce(steer);
+ }
+
+ if (location.x < 0) location.x = 0;
+ if (location.y < 0) location.y = 0;
+ if (location.x >= VPANEL_W) location.x = VPANEL_W - 1;
+ if (location.y >= VPANEL_H) location.y = VPANEL_H - 1;
+ }
+
+ bool bounceOffBorders(float bounce) {
+ bool bounced = false;
+
+ if (location.x >= VPANEL_W) {
+ location.x = VPANEL_W - 1;
+ velocity.x *= -bounce;
+ bounced = true;
+ }
+ else if (location.x < 0) {
+ location.x = 0;
+ velocity.x *= -bounce;
+ bounced = true;
+ }
+
+ if (location.y >= VPANEL_H) {
+ location.y = VPANEL_H - 1;
+ velocity.y *= -bounce;
+ bounced = true;
+ }
+ else if (location.y < 0) {
+ location.y = 0;
+ velocity.y *= -bounce;
+ bounced = true;
+ }
+
+ return bounced;
+ }
+
+ void render() {
+ //// Draw a triangle rotated in the direction of velocity
+ //float theta = velocity.heading2D() + radians(90);
+ //fill(175);
+ //stroke(0);
+ //pushMatrix();
+ //translate(location.x,location.y);
+ //rotate(theta);
+ //beginShape(TRIANGLES);
+ //vertex(0, -r*2);
+ //vertex(-r, r*2);
+ //vertex(r, r*2);
+ //endShape();
+ //popMatrix();
+ //matrix.drawBackgroundPixelRGB888(location.x, location.y, CRGB::Blue);
+ }
+};
+
+static const uint8_t AVAILABLE_BOID_COUNT = 40;
+Boid boids[AVAILABLE_BOID_COUNT];
diff --git a/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino b/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino
new file mode 100644
index 0000000..1dddd56
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino
@@ -0,0 +1,181 @@
+/* ------------------------- CUSTOM GPIO PIN MAPPING ------------------------- */
+// Kosso's ESP32 Matrix PCB pins
+#define R1_PIN 2
+#define G1_PIN 15
+#define B1_PIN 4
+#define R2_PIN 16
+#define G2_PIN 13
+#define B2_PIN 17
+#define A_PIN 5
+#define B_PIN 18
+#define C_PIN 19
+#define D_PIN 27
+#define E_PIN -1
+#define LAT_PIN 21
+#define OE_PIN 23
+#define CLK_PIN 22
+
+
+/* -------------------------- Display Config Initialisation -------------------- */
+#define MATRIX_WIDTH 128 // Overall matrix dimensions if laid out end-to-end.
+#define MATRIX_HEIGHT 32
+
+#define PANEL_RES_X 64 // Number of pixels wide of each INDIVIDUAL panel module.
+#define PANEL_RES_Y 32 // Number of pixels tall of each INDIVIDUAL panel module.
+
+#define NUM_ROWS 2 // Number of rows of chained INDIVIDUAL PANELS
+#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW
+
+// Virtual Panl dimensions
+#define VPANEL_W 64 // Kosso: All Pattern files have had the MATRIX_WIDTH and MATRIX_HEIGHT replaced by these.
+#define VPANEL_H 64 //
+
+// Kosso added: Button with debounce
+#define BTN_PIN 0 // Pattern advance. Using EPS32 Boot button.
+int buttonState; // the current reading from the input pin
+int lastButtonState = LOW; // the previous reading from the input pin
+unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
+unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
+
+// The palettes are set to change every 60 seconds.
+
+// Kosso added: Non-volatile memory to save last pattern index.
+#include <Preferences.h>
+Preferences preferences;
+int lastPattern = 0;
+
+
+/* -------------------------- Class Initialisation -------------------------- */
+//#include <ESP32-RGB64x32MatrixPanel-I2S-DMA.h>
+//RGB64x32MatrixPanel_I2S_DMA matrix;
+
+#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
+RGB64x32MatrixPanel_I2S_DMA matrix;
+// Added support for 'Chained' virtual panel configurations.
+VirtualMatrixPanel virtualDisp(matrix, NUM_ROWS, NUM_COLS, PANEL_RES_X, PANEL_RES_Y, true);
+
+#include <FastLED.h> // Used for some mathematics calculations and effects.
+
+#include "Effects.h"
+Effects effects;
+
+#include "Drawable.h"
+#include "Playlist.h"
+//#include "Geometry.h"
+
+#include "Patterns.h"
+Patterns patterns;
+
+/* -------------------------- Some variables -------------------------- */
+unsigned long ms_current = 0;
+unsigned long ms_previous = 0;
+unsigned long ms_animation_max_duration = 60000; // 10 seconds
+unsigned long next_frame = 0;
+
+void setup()
+{
+ // Setup serial interface
+ Serial.begin(115200);
+ delay(250);
+
+ // Added a button to manually advance the pattern index.
+ pinMode(BTN_PIN, INPUT);
+ // For saving last pattern index. TO reboot with same.
+ preferences.begin("RGBMATRIX", false);
+ lastPattern = preferences.getInt("lastPattern", 0);
+
+ matrix.setPanelBrightness(30);
+ matrix.setMinRefreshRate(200);
+
+
+ matrix.begin(R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN ); // setup the LED matrix
+
+ virtualDisp.fillScreen(virtualDisp.color444(0, 0, 0));
+
+ Serial.println("**************** Starting Aurora Effects Demo ****************");
+
+ Serial.println("MATRIX_WIDTH " + String(MATRIX_WIDTH));
+ Serial.println("MATRIX_HEIGHT " + String(MATRIX_HEIGHT));
+
+#ifdef VPANEL_W
+ Serial.println("VIRTUAL PANEL WIDTH " + String(VPANEL_W));
+ Serial.println("VIRTUAL PANEL HEIGHT " + String(VPANEL_H));
+#endif
+
+ // setup the effects generator
+ effects.Setup();
+
+ delay(500);
+ Serial.println("Effects being loaded: ");
+ listPatterns();
+
+ Serial.println("LastPattern index: " + String(lastPattern));
+
+ patterns.setPattern(lastPattern); // // simple noise
+ patterns.start();
+
+ Serial.print("Starting with pattern: ");
+ Serial.println(patterns.getCurrentPatternName());
+
+ preferences.end();
+
+}
+
+
+void patternAdvance(){
+ // Go to next pattern in the list (se Patterns.h)
+ patterns.stop();
+ patterns.move(1);
+ patterns.start();
+ // Select a random palette as well
+ effects.RandomPalette();
+ Serial.print("Changing pattern to: ");
+ Serial.println(patterns.getCurrentPatternName());
+ Serial.println(patterns.getPatternIndex());
+ lastPattern = patterns.getPatternIndex();
+ // Save last index.
+ preferences.begin("RGBMATRIX", false);
+ preferences.putInt("lastPattern", lastPattern);
+ preferences.end();
+
+}
+
+void loop()
+{
+ // Boot button Pattern advance with debounce
+ int reading = digitalRead(BTN_PIN);
+ if (reading != lastButtonState) {
+ lastDebounceTime = millis();
+ }
+
+ if ((millis() - lastDebounceTime) > debounceDelay) {
+ if (reading != buttonState) {
+ buttonState = reading;
+ if (buttonState == LOW) {
+ Serial.println("NEXT PATTERN ...");
+ patternAdvance();
+ }
+ }
+ }
+ lastButtonState = reading;
+ // end button debounce
+
+ ms_current = millis();
+
+ if ( (ms_current - ms_previous) > ms_animation_max_duration )
+ {
+ // patternAdvance();
+ // just auto-change the palette
+ effects.RandomPalette();
+ ms_previous = ms_current;
+ }
+
+ if ( next_frame < ms_current)
+ next_frame = patterns.drawFrame() + ms_current;
+
+}
+
+
+void listPatterns() {
+ patterns.listPatterns();
+}
diff --git a/examples/ChainedPanelsAuroraDemo/Drawable.h b/examples/ChainedPanelsAuroraDemo/Drawable.h
new file mode 100644
index 0000000..6e97098
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Drawable.h
@@ -0,0 +1,50 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Drawable_H
+#define Drawable_H
+
+class Drawable{
+public:
+ char* name;
+
+ virtual bool isRunnable() {
+ return false;
+ }
+
+ virtual bool isPlaylist() {
+ return false;
+ }
+
+ // a single frame should be drawn as fast as possible, without any delay or blocking
+ // return how many millisecond delay is requested before the next call to drawFrame()
+ virtual unsigned int drawFrame() {
+ matrix.fillScreen(0);
+ //backgroundLayer.fillScreen({ 0, 0, 0 });
+ return 0;
+ };
+
+ virtual void start() {};
+ virtual void stop() {};
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/Effects.h b/examples/ChainedPanelsAuroraDemo/Effects.h
new file mode 100644
index 0000000..8ca709e
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Effects.h
@@ -0,0 +1,914 @@
+
+/*
+ Aurora: https://github.com/pixelmatix/aurora
+ Copyright (c) 2014 Jason Coon
+
+ Portions of this code are adapted from "Funky Clouds" by Stefan Petrick: https://gist.github.com/anonymous/876f908333cd95315c35
+ Portions of this code are adapted from "NoiseSmearing" by Stefan Petrick: https://gist.github.com/StefanPetrick/9ee2f677dbff64e3ba7a
+ Copyright (c) 2014 Stefan Petrick
+ http://www.stefan-petrick.de/wordpress_beta
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef Effects_H
+#define Effects_H
+
+/* ---------------------------- GLOBAL CONSTANTS ----------------------------- */
+
+//const int MATRIX_CENTER_X = MATRIX_WIDTH / 2;
+//const int MATRIX_CENTER_Y = MATRIX_HEIGHT / 2;
+//const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1;
+//const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1;
+
+const int MATRIX_CENTER_X = VPANEL_W / 2;
+const int MATRIX_CENTER_Y = VPANEL_H / 2;
+const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1;
+const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1;
+
+const uint16_t NUM_LEDS = (VPANEL_W * VPANEL_H) + 1; // one led spare to capture out of bounds
+
+/* Convert x,y co-ordinate to flat array index.
+ x and y positions start from 0, so must not be >= 'real' panel width or height
+ (i.e. 64 pixels or 32 pixels.). Max value: MATRIX_WIDTH-1 etc.
+*/
+uint16_t XY( uint8_t x, uint8_t y)
+{
+ if ( x >= VPANEL_W || x < 0) return 0;
+ if ( y >= VPANEL_H || y < 0) return 0;
+
+ return (y * VPANEL_W) + x + 1; // everything offset by one to capture out of bounds stuff - never displayed by ShowFrame()
+
+}
+
+/// Some mathematics provided by FastLED
+uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0)
+{
+ uint8_t beat = beat8(beats_per_minute, timebase);
+ uint8_t beatcos = cos8(beat + phase_offset);
+ uint8_t rangewidth = highest - lowest;
+ uint8_t scaledbeat = scale8(beatcos, rangewidth);
+ uint8_t result = lowest + scaledbeat;
+ return result;
+}
+
+uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
+ uint8_t beatsin = sin8(theta);
+ uint8_t rangewidth = highest - lowest;
+ uint8_t scaledbeat = scale8(beatsin, rangewidth);
+ uint8_t result = lowest + scaledbeat;
+ return result;
+}
+
+uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
+ uint8_t beatcos = cos8(theta);
+ uint8_t rangewidth = highest - lowest;
+ uint8_t scaledbeat = scale8(beatcos, rangewidth);
+ uint8_t result = lowest + scaledbeat;
+ return result;
+}
+
+// Array of temperature readings at each simulation cell
+byte heat[NUM_LEDS];
+
+uint32_t noise_x;
+uint32_t noise_y;
+uint32_t noise_z;
+uint32_t noise_scale_x;
+uint32_t noise_scale_y;
+
+uint8_t noise[VPANEL_W][VPANEL_H];
+uint8_t noisesmoothing;
+
+class Effects {
+ public:
+ //CRGB *leds;
+ CRGB leds[NUM_LEDS];
+ CRGB leds2[NUM_LEDS]; // Faptastic: getting rid of this and any dependant effects or algos. to save memory 24*64*32 bytes of ram (50k).
+
+
+ /* The only 'framebuffer' we have is what is contained in the leds and leds2 variables.
+ We don't store what the color a particular pixel might be, other than when it's turned
+ into raw electrical signal output gobbly-gook (i.e. the DMA matrix buffer), but this * is not reversible.
+
+ As such, any time these effects want to write a pixel color, we first have to update
+ the leds or leds2 array, and THEN write it to the RGB panel. This enables us to 'look up' the array to see what a pixel color was previously, each drawFrame().
+ */
+ void drawBackgroundFastLEDPixelCRGB(int16_t x, int16_t y, CRGB color)
+ {
+ leds[XY(x, y)] = color;
+ virtualDisp.drawPixelRGB888(x, y, color.r, color.g, color.b);
+ }
+
+ // write one pixel with the specified color from the current palette to coordinates
+ void Pixel(int x, int y, uint8_t colorIndex) {
+ CRGB temp = ColorFromCurrentPalette(colorIndex);
+ leds[XY(x, y)] = temp;
+ virtualDisp.drawPixelRGB888(x, y, temp.r, temp.g, temp.b); // now draw it?
+ }
+
+ void PrepareFrame() {
+ // leds = (CRGB*) backgroundLayer.backBuffer();
+ }
+
+ void ShowFrame() {
+#if (FASTLED_VERSION >= 3001000)
+ nblendPaletteTowardPalette(currentPalette, targetPalette, 24);
+#else
+ currentPalette = targetPalette;
+#endif
+ // backgroundLayer.swapBuffers();
+ // leds = (CRGB*) backgroundLayer.backBuffer();
+ // LEDS.countFPS();
+ for (int y = 0; y < VPANEL_H; y++) {
+ for (int x = 0; x < VPANEL_W; x++)
+ {
+ CRGB tmp_led = leds[XY(x, y)];
+ virtualDisp.drawPixelRGB888( x, y, tmp_led.r, tmp_led.g, tmp_led.b);
+ } // end loop to copy fast led to the dma matrix
+ }
+ }
+
+
+ // scale the brightness of the screenbuffer down
+ void DimAll(byte value)
+ {
+ for (int i = 0; i < NUM_LEDS; i++)
+ {
+ leds[i].nscale8(value);
+ }
+ }
+
+ void ClearFrame()
+ {
+ memset(leds, 0x00, sizeof(leds)); // flush
+ }
+
+
+
+
+ void CircleStream(uint8_t value) {
+ DimAll(value); ShowFrame();
+
+ for (uint8_t offset = 0; offset < MATRIX_CENTER_X; offset++) {
+ boolean hasprev = false;
+ uint16_t prevxy = 0;
+
+ for (uint8_t theta = 0; theta < 255; theta++) {
+ uint8_t x = mapcos8(theta, offset, (VPANEL_W - 1) - offset);
+ uint8_t y = mapsin8(theta, offset, (VPANEL_H - 1) - offset);
+
+ uint16_t xy = XY(x, y);
+
+ if (hasprev) {
+ leds[prevxy] += leds[xy];
+ }
+
+ prevxy = xy;
+ hasprev = true;
+ }
+ }
+
+ for (uint8_t x = 0; x < VPANEL_W; x++) {
+ for (uint8_t y = 0; y < VPANEL_H; y++) {
+ uint16_t xy = XY(x, y);
+ leds[xy] = leds2[xy];
+ leds[xy].nscale8(value);
+ leds2[xy].nscale8(value);
+ }
+ }
+ }
+
+
+ // palettes
+ static const int paletteCount = 10;
+ int paletteIndex = -1;
+ TBlendType currentBlendType = LINEARBLEND;
+ CRGBPalette16 currentPalette;
+ CRGBPalette16 targetPalette;
+ char* currentPaletteName;
+
+ static const int HeatColorsPaletteIndex = 6;
+ static const int RandomPaletteIndex = 9;
+
+ void Setup() {
+ currentPalette = RainbowColors_p;
+ loadPalette(0);
+ NoiseVariablesSetup();
+ }
+
+ void CyclePalette(int offset = 1) {
+ loadPalette(paletteIndex + offset);
+ }
+
+ void RandomPalette() {
+ loadPalette(RandomPaletteIndex);
+ }
+
+ void loadPalette(int index) {
+ paletteIndex = index;
+
+ if (paletteIndex >= paletteCount)
+ paletteIndex = 0;
+ else if (paletteIndex < 0)
+ paletteIndex = paletteCount - 1;
+
+ switch (paletteIndex) {
+ case 0:
+ targetPalette = RainbowColors_p;
+ currentPaletteName = (char *)"Rainbow";
+ break;
+ case 1:
+ targetPalette = OceanColors_p;
+ currentPaletteName = (char *)"Ocean";
+ break;
+ case 2:
+ targetPalette = CloudColors_p;
+ currentPaletteName = (char *)"Cloud";
+ break;
+ case 3:
+ targetPalette = ForestColors_p;
+ currentPaletteName = (char *)"Forest";
+ break;
+ case 4:
+ targetPalette = PartyColors_p;
+ currentPaletteName = (char *)"Party";
+ break;
+ case 5:
+ setupGrayscalePalette();
+ currentPaletteName = (char *)"Grey";
+ break;
+ case HeatColorsPaletteIndex:
+ targetPalette = HeatColors_p;
+ currentPaletteName = (char *)"Heat";
+ break;
+ case 7:
+ targetPalette = LavaColors_p;
+ currentPaletteName = (char *)"Lava";
+ break;
+ case 8:
+ setupIcePalette();
+ currentPaletteName = (char *)"Ice";
+ break;
+ case RandomPaletteIndex:
+ loadPalette(random(0, paletteCount - 1));
+ paletteIndex = RandomPaletteIndex;
+ currentPaletteName = (char *)"Random";
+ break;
+ }
+ }
+
+ void setPalette(String paletteName) {
+ if (paletteName == "Rainbow")
+ loadPalette(0);
+ else if (paletteName == "Ocean")
+ loadPalette(1);
+ else if (paletteName == "Cloud")
+ loadPalette(2);
+ else if (paletteName == "Forest")
+ loadPalette(3);
+ else if (paletteName == "Party")
+ loadPalette(4);
+ else if (paletteName == "Grayscale")
+ loadPalette(5);
+ else if (paletteName == "Heat")
+ loadPalette(6);
+ else if (paletteName == "Lava")
+ loadPalette(7);
+ else if (paletteName == "Ice")
+ loadPalette(8);
+ else if (paletteName == "Random")
+ RandomPalette();
+ }
+
+ void listPalettes() {
+ Serial.println(F("{"));
+ Serial.print(F(" \"count\": "));
+ Serial.print(paletteCount);
+ Serial.println(",");
+ Serial.println(F(" \"results\": ["));
+
+ String paletteNames [] = {
+ "Rainbow",
+ // "RainbowStripe",
+ "Ocean",
+ "Cloud",
+ "Forest",
+ "Party",
+ "Grayscale",
+ "Heat",
+ "Lava",
+ "Ice",
+ "Random"
+ };
+
+ for (int i = 0; i < paletteCount; i++) {
+ Serial.print(F(" \""));
+ Serial.print(paletteNames[i]);
+ if (i == paletteCount - 1)
+ Serial.println(F("\""));
+ else
+ Serial.println(F("\","));
+ }
+
+ Serial.println(" ]");
+ Serial.println("}");
+ }
+
+ void setupGrayscalePalette() {
+ targetPalette = CRGBPalette16(CRGB::Black, CRGB::White);
+ }
+
+ void setupIcePalette() {
+ targetPalette = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);
+ }
+
+ // Oscillators and Emitters
+
+ // the oscillators: linear ramps 0-255
+ byte osci[6];
+
+ // sin8(osci) swinging between 0 to MATRIX_WIDTH - 1
+ byte p[6];
+
+ // set the speeds (and by that ratios) of the oscillators here
+ void MoveOscillators() {
+ osci[0] = osci[0] + 5;
+ osci[1] = osci[1] + 2;
+ osci[2] = osci[2] + 3;
+ osci[3] = osci[3] + 4;
+ osci[4] = osci[4] + 1;
+ if (osci[4] % 2 == 0)
+ osci[5] = osci[5] + 1; // .5
+ for (int i = 0; i < 4; i++) {
+ p[i] = map8(sin8(osci[i]), 0, VPANEL_W - 1); //why? to keep the result in the range of 0-MATRIX_WIDTH (matrix size)
+ }
+ }
+
+
+ // All the caleidoscope functions work directly within the screenbuffer (leds array).
+ // Draw whatever you like in the area x(0-15) and y (0-15) and then copy it arround.
+
+ // rotates the first 16x16 quadrant 3 times onto a 32x32 (+90 degrees rotation for each one)
+ void Caleidoscope1() {
+ for (int x = 0; x < MATRIX_CENTER_X; x++) {
+ for (int y = 0; y < MATRIX_CENTER_Y; y++) {
+ leds[XY(VPANEL_W - 1 - x, y)] = leds[XY(x, y)];
+ leds[XY(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
+ leds[XY(x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
+ }
+ }
+ }
+
+
+ // mirror the first 16x16 quadrant 3 times onto a 32x32
+ void Caleidoscope2() {
+ for (int x = 0; x < MATRIX_CENTER_X; x++) {
+ for (int y = 0; y < MATRIX_CENTER_Y; y++) {
+ leds[XY(VPANEL_W - 1 - x, y)] = leds[XY(y, x)];
+ leds[XY(x, VPANEL_H - 1 - y)] = leds[XY(y, x)];
+ leds[XY(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY(x, y)];
+ }
+ }
+ }
+
+ // copy one diagonal triangle into the other one within a 16x16
+ void Caleidoscope3() {
+ for (int x = 0; x <= MATRIX_CENTRE_X; x++) {
+ for (int y = 0; y <= x; y++) {
+ leds[XY(x, y)] = leds[XY(y, x)];
+ }
+ }
+ }
+
+ // copy one diagonal triangle into the other one within a 16x16 (90 degrees rotated compared to Caleidoscope3)
+ void Caleidoscope4() {
+ for (int x = 0; x <= MATRIX_CENTRE_X; x++) {
+ for (int y = 0; y <= MATRIX_CENTRE_Y - x; y++) {
+ leds[XY(MATRIX_CENTRE_Y - y, MATRIX_CENTRE_X - x)] = leds[XY(x, y)];
+ }
+ }
+ }
+
+ // copy one diagonal triangle into the other one within a 8x8
+ void Caleidoscope5() {
+ for (int x = 0; x < VPANEL_W / 4; x++) {
+ for (int y = 0; y <= x; y++) {
+ leds[XY(x, y)] = leds[XY(y, x)];
+ }
+ }
+
+ for (int x = VPANEL_W / 4; x < VPANEL_W / 2; x++) {
+ for (int y = VPANEL_H / 4; y >= 0; y--) {
+ leds[XY(x, y)] = leds[XY(y, x)];
+ }
+ }
+ }
+
+ void Caleidoscope6() {
+ for (int x = 1; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 7)] = leds[XY(x, 0)];
+ } //a
+ for (int x = 2; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 6)] = leds[XY(x, 1)];
+ } //b
+ for (int x = 3; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 5)] = leds[XY(x, 2)];
+ } //c
+ for (int x = 4; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 4)] = leds[XY(x, 3)];
+ } //d
+ for (int x = 5; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 3)] = leds[XY(x, 4)];
+ } //e
+ for (int x = 6; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 2)] = leds[XY(x, 5)];
+ } //f
+ for (int x = 7; x < MATRIX_CENTER_X; x++) {
+ leds[XY(7 - x, 1)] = leds[XY(x, 6)];
+ } //g
+ }
+
+ // create a square twister to the left or counter-clockwise
+ // x and y for center, r for radius
+ void SpiralStream(int x, int y, int r, byte dimm) {
+ for (int d = r; d >= 0; d--) { // from the outside to the inside
+ for (int i = x - d; i <= x + d; i++) {
+ leds[XY(i, y - d)] += leds[XY(i + 1, y - d)]; // lowest row to the right
+ leds[XY(i, y - d)].nscale8(dimm);
+ }
+ for (int i = y - d; i <= y + d; i++) {
+ leds[XY(x + d, i)] += leds[XY(x + d, i + 1)]; // right colum up
+ leds[XY(x + d, i)].nscale8(dimm);
+ }
+ for (int i = x + d; i >= x - d; i--) {
+ leds[XY(i, y + d)] += leds[XY(i - 1, y + d)]; // upper row to the left
+ leds[XY(i, y + d)].nscale8(dimm);
+ }
+ for (int i = y + d; i >= y - d; i--) {
+ leds[XY(x - d, i)] += leds[XY(x - d, i - 1)]; // left colum down
+ leds[XY(x - d, i)].nscale8(dimm);
+ }
+ }
+ }
+
+ // expand everything within a circle
+ void Expand(int centerX, int centerY, int radius, byte dimm) {
+ if (radius == 0)
+ return;
+
+ int currentRadius = radius;
+
+ while (currentRadius > 0) {
+ int a = radius, b = 0;
+ int radiusError = 1 - a;
+
+ int nextRadius = currentRadius - 1;
+ int nextA = nextRadius - 1, nextB = 0;
+ int nextRadiusError = 1 - nextA;
+
+ while (a >= b)
+ {
+ // move them out one pixel on the radius
+ leds[XY(a + centerX, b + centerY)] = leds[XY(nextA + centerX, nextB + centerY)];
+ leds[XY(b + centerX, a + centerY)] = leds[XY(nextB + centerX, nextA + centerY)];
+ leds[XY(-a + centerX, b + centerY)] = leds[XY(-nextA + centerX, nextB + centerY)];
+ leds[XY(-b + centerX, a + centerY)] = leds[XY(-nextB + centerX, nextA + centerY)];
+ leds[XY(-a + centerX, -b + centerY)] = leds[XY(-nextA + centerX, -nextB + centerY)];
+ leds[XY(-b + centerX, -a + centerY)] = leds[XY(-nextB + centerX, -nextA + centerY)];
+ leds[XY(a + centerX, -b + centerY)] = leds[XY(nextA + centerX, -nextB + centerY)];
+ leds[XY(b + centerX, -a + centerY)] = leds[XY(nextB + centerX, -nextA + centerY)];
+
+ // dim them
+ leds[XY(a + centerX, b + centerY)].nscale8(dimm);
+ leds[XY(b + centerX, a + centerY)].nscale8(dimm);
+ leds[XY(-a + centerX, b + centerY)].nscale8(dimm);
+ leds[XY(-b + centerX, a + centerY)].nscale8(dimm);
+ leds[XY(-a + centerX, -b + centerY)].nscale8(dimm);
+ leds[XY(-b + centerX, -a + centerY)].nscale8(dimm);
+ leds[XY(a + centerX, -b + centerY)].nscale8(dimm);
+ leds[XY(b + centerX, -a + centerY)].nscale8(dimm);
+
+ b++;
+ if (radiusError < 0)
+ radiusError += 2 * b + 1;
+ else
+ {
+ a--;
+ radiusError += 2 * (b - a + 1);
+ }
+
+ nextB++;
+ if (nextRadiusError < 0)
+ nextRadiusError += 2 * nextB + 1;
+ else
+ {
+ nextA--;
+ nextRadiusError += 2 * (nextB - nextA + 1);
+ }
+ }
+
+ currentRadius--;
+ }
+ }
+
+ // give it a linear tail to the right
+ void StreamRight(byte scale, int fromX = 0, int toX = VPANEL_W, int fromY = 0, int toY = VPANEL_H)
+ {
+ for (int x = fromX + 1; x < toX; x++) {
+ for (int y = fromY; y < toY; y++) {
+ leds[XY(x, y)] += leds[XY(x - 1, y)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ for (int y = fromY; y < toY; y++)
+ leds[XY(0, y)].nscale8(scale);
+ }
+
+ // give it a linear tail to the left
+ void StreamLeft(byte scale, int fromX = VPANEL_W, int toX = 0, int fromY = 0, int toY = VPANEL_H)
+ {
+ for (int x = toX; x < fromX; x++) {
+ for (int y = fromY; y < toY; y++) {
+ leds[XY(x, y)] += leds[XY(x + 1, y)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ for (int y = fromY; y < toY; y++)
+ leds[XY(0, y)].nscale8(scale);
+ }
+
+ // give it a linear tail downwards
+ void StreamDown(byte scale)
+ {
+ for (int x = 0; x < VPANEL_W; x++) {
+ for (int y = 1; y < VPANEL_H; y++) {
+ leds[XY(x, y)] += leds[XY(x, y - 1)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ for (int x = 0; x < VPANEL_W; x++)
+ leds[XY(x, 0)].nscale8(scale);
+ }
+
+ // give it a linear tail upwards
+ void StreamUp(byte scale)
+ {
+ for (int x = 0; x < VPANEL_W; x++) {
+ for (int y = VPANEL_H - 2; y >= 0; y--) {
+ leds[XY(x, y)] += leds[XY(x, y + 1)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ for (int x = 0; x < VPANEL_W; x++)
+ leds[XY(x, VPANEL_H - 1)].nscale8(scale);
+ }
+
+ // give it a linear tail up and to the left
+ void StreamUpAndLeft(byte scale)
+ {
+ for (int x = 0; x < VPANEL_W - 1; x++) {
+ for (int y = VPANEL_H - 2; y >= 0; y--) {
+ leds[XY(x, y)] += leds[XY(x + 1, y + 1)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ for (int x = 0; x < VPANEL_W; x++)
+ leds[XY(x, VPANEL_H - 1)].nscale8(scale);
+ for (int y = 0; y < VPANEL_H; y++)
+ leds[XY(VPANEL_W - 1, y)].nscale8(scale);
+ }
+
+ // give it a linear tail up and to the right
+ void StreamUpAndRight(byte scale)
+ {
+ for (int x = 0; x < VPANEL_W - 1; x++) {
+ for (int y = VPANEL_H - 2; y >= 0; y--) {
+ leds[XY(x + 1, y)] += leds[XY(x, y + 1)];
+ leds[XY(x, y)].nscale8(scale);
+ }
+ }
+ // fade the bottom row
+ for (int x = 0; x < VPANEL_W; x++)
+ leds[XY(x, VPANEL_H - 1)].nscale8(scale);
+
+ // fade the right column
+ for (int y = 0; y < VPANEL_H; y++)
+ leds[XY(VPANEL_W - 1, y)].nscale8(scale);
+ }
+
+ // just move everything one line down
+ void MoveDown() {
+ for (int y = VPANEL_H - 1; y > 0; y--) {
+ for (int x = 0; x < VPANEL_W; x++) {
+ leds[XY(x, y)] = leds[XY(x, y - 1)];
+ }
+ }
+ }
+
+ // just move everything one line down
+ void VerticalMoveFrom(int start, int end) {
+ for (int y = end; y > start; y--) {
+ for (int x = 0; x < VPANEL_W; x++) {
+ leds[XY(x, y)] = leds[XY(x, y - 1)];
+ }
+ }
+ }
+
+ // copy the rectangle defined with 2 points x0, y0, x1, y1
+ // to the rectangle beginning at x2, x3
+ void Copy(byte x0, byte y0, byte x1, byte y1, byte x2, byte y2) {
+ for (int y = y0; y < y1 + 1; y++) {
+ for (int x = x0; x < x1 + 1; x++) {
+ leds[XY(x + x2 - x0, y + y2 - y0)] = leds[XY(x, y)];
+ }
+ }
+ }
+
+ // rotate + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X)
+ void RotateTriangle() {
+ for (int x = 1; x < MATRIX_CENTER_X; x++) {
+ for (int y = 0; y < x; y++) {
+ leds[XY(x, 7 - y)] = leds[XY(7 - x, y)];
+ }
+ }
+ }
+
+ // mirror + copy triangle (MATRIX_CENTER_X*MATRIX_CENTER_X)
+ void MirrorTriangle() {
+ for (int x = 1; x < MATRIX_CENTER_X; x++) {
+ for (int y = 0; y < x; y++) {
+ leds[XY(7 - y, x)] = leds[XY(7 - x, y)];
+ }
+ }
+ }
+
+ // draw static rainbow triangle pattern (MATRIX_CENTER_XxWIDTH / 2)
+ // (just for debugging)
+ void RainbowTriangle() {
+ for (int i = 0; i < MATRIX_CENTER_X; i++) {
+ for (int j = 0; j <= i; j++) {
+ Pixel(7 - i, j, i * j * 4);
+ }
+ }
+ }
+
+ void BresenhamLine(int x0, int y0, int x1, int y1, byte colorIndex)
+ {
+ BresenhamLine(x0, y0, x1, y1, ColorFromCurrentPalette(colorIndex));
+ }
+
+ void BresenhamLine(int x0, int y0, int x1, int y1, CRGB color)
+ {
+ int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
+ int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
+ int err = dx + dy, e2;
+ for (;;) {
+ leds[XY(x0, y0)] += color;
+ if (x0 == x1 && y0 == y1) break;
+ e2 = 2 * err;
+ if (e2 > dy) {
+ err += dy;
+ x0 += sx;
+ }
+ if (e2 < dx) {
+ err += dx;
+ y0 += sy;
+ }
+ }
+ }
+
+ // write one pixel with the specified color from the current palette to coordinates
+ /*
+ void Pixel(int x, int y, uint8_t colorIndex) {
+ leds[XY(x, y)] = ColorFromCurrentPalette(colorIndex);
+ matrix.drawBackgroundPixelRGB888(x,y, leds[XY(x, y)]); // now draw it?
+ }
+ */
+
+ CRGB ColorFromCurrentPalette(uint8_t index = 0, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND) {
+ return ColorFromPalette(currentPalette, index, brightness, currentBlendType);
+ }
+
+ CRGB HsvToRgb(uint8_t h, uint8_t s, uint8_t v) {
+ CHSV hsv = CHSV(h, s, v);
+ CRGB rgb;
+ hsv2rgb_spectrum(hsv, rgb);
+ return rgb;
+ }
+
+ void NoiseVariablesSetup() {
+ noisesmoothing = 200;
+
+ noise_x = random16();
+ noise_y = random16();
+ noise_z = random16();
+ noise_scale_x = 6000;
+ noise_scale_y = 6000;
+ }
+
+ void FillNoise() {
+ for (uint8_t i = 0; i < VPANEL_W; i++) {
+ uint32_t ioffset = noise_scale_x * (i - MATRIX_CENTRE_Y);
+
+ for (uint8_t j = 0; j < VPANEL_H; j++) {
+ uint32_t joffset = noise_scale_y * (j - MATRIX_CENTRE_Y);
+
+ byte data = inoise16(noise_x + ioffset, noise_y + joffset, noise_z) >> 8;
+
+ uint8_t olddata = noise[i][j];
+ uint8_t newdata = scale8(olddata, noisesmoothing) + scale8(data, 256 - noisesmoothing);
+ data = newdata;
+
+ noise[i][j] = data;
+ }
+ }
+ }
+
+ // non leds2 memory version.
+ void MoveX(byte delta)
+ {
+
+ CRGB tmp = 0;
+
+ for (int y = 0; y < VPANEL_H; y++)
+ {
+
+ // Shift Left: https://codedost.com/c/arraypointers-in-c/c-program-shift-elements-array-left-direction/
+ // Computationally heavier but doesn't need an entire leds2 array
+
+ tmp = leds[XY(0, y)];
+ for (int m = 0; m < delta; m++)
+ {
+ // Do this delta time for each row... computationally expensive potentially.
+ for (int x = 0; x < VPANEL_H; x++)
+ {
+ leds[XY(x, y)] = leds [XY(x + 1, y)];
+ }
+
+ leds[XY(VPANEL_W - 1, y)] = tmp;
+ }
+
+
+ /*
+ // Shift
+ for (int x = 0; x < VPANEL_W - delta; x++) {
+ leds2[XY(x, y)] = leds[XY(x + delta, y)];
+ }
+
+ // Wrap around
+ for (int x = VPANEL_W - delta; x < VPANEL_W; x++) {
+ leds2[XY(x, y)] = leds[XY(x + delta - VPANEL_H, y)];
+ }
+ */
+ } // end row loop
+
+ /*
+ // write back to leds
+ for (uint8_t y = 0; y < VPANEL_H; y++) {
+ for (uint8_t x = 0; x < VPANEL_W; x++) {
+ leds[XY(x, y)] = leds2[XY(x, y)];
+ }
+ }
+ */
+ }
+
+ void MoveY(byte delta)
+ {
+
+ CRGB tmp = 0;
+ for (int x = 0; x < VPANEL_W; x++)
+ {
+ tmp = leds[XY(x, 0)];
+ for (int m = 0; m < delta; m++) // moves
+ {
+ // Do this delta time for each row... computationally expensive potentially.
+ for (int y = 0; y < VPANEL_H; y++)
+ {
+ leds[XY(x, y)] = leds [XY(x, y + 1)];
+ }
+
+ leds[XY(x, VPANEL_H - 1)] = tmp;
+ }
+ } // end column loop
+ } /// MoveY
+
+ void MoveFractionalNoiseX(byte amt = 16) {
+ // move delta pixelwise
+ for (int y = 0; y < VPANEL_H; y++) {
+ uint16_t amount = noise[0][y] * amt;
+ byte delta = 31 - (amount / 256);
+
+ for (int x = 0; x < VPANEL_W - delta; x++) {
+ leds2[XY(x, y)] = leds[XY(x + delta, y)];
+ }
+ for (int x = VPANEL_H - delta; x < VPANEL_W; x++) {
+ leds2[XY(x, y)] = leds[XY(x + delta - VPANEL_W, y)];
+ }
+ }
+
+ //move fractions
+ CRGB PixelA;
+ CRGB PixelB;
+
+ for (uint8_t y = 0; y < VPANEL_H; y++) {
+ uint16_t amount = noise[0][y] * amt;
+ byte delta = 31 - (amount / 256);
+ byte fractions = amount - (delta * 256);
+
+ for (uint8_t x = 1; x < VPANEL_W; x++) {
+ PixelA = leds2[XY(x, y)];
+ PixelB = leds2[XY(x - 1, y)];
+
+ PixelA %= 255 - fractions;
+ PixelB %= fractions;
+
+ leds[XY(x, y)] = PixelA + PixelB;
+ }
+
+ PixelA = leds2[XY(0, y)];
+ PixelB = leds2[XY(VPANEL_W - 1, y)];
+
+ PixelA %= 255 - fractions;
+ PixelB %= fractions;
+
+ leds[XY(0, y)] = PixelA + PixelB;
+ }
+ }
+
+ void MoveFractionalNoiseY(byte amt = 16) {
+ // move delta pixelwise
+ for (int x = 0; x < VPANEL_W; x++) {
+ uint16_t amount = noise[x][0] * amt;
+ byte delta = 31 - (amount / 256);
+
+ for (int y = 0; y < VPANEL_W - delta; y++) {
+ leds2[XY(x, y)] = leds[XY(x, y + delta)];
+ }
+ for (int y = VPANEL_W - delta; y < VPANEL_W; y++) {
+ leds2[XY(x, y)] = leds[XY(x, y + delta - VPANEL_W)];
+ }
+ }
+
+ //move fractions
+ CRGB PixelA;
+ CRGB PixelB;
+
+ for (uint8_t x = 0; x < VPANEL_H; x++) {
+ uint16_t amount = noise[x][0] * amt;
+ byte delta = 31 - (amount / 256);
+ byte fractions = amount - (delta * 256);
+
+ for (uint8_t y = 1; y < VPANEL_W; y++) {
+ PixelA = leds2[XY(x, y)];
+ PixelB = leds2[XY(x, y - 1)];
+
+ PixelA %= 255 - fractions;
+ PixelB %= fractions;
+
+ leds[XY(x, y)] = PixelA + PixelB;
+ }
+
+ PixelA = leds2[XY(x, 0)];
+ PixelB = leds2[XY(x, VPANEL_W - 1)];
+
+ PixelA %= 255 - fractions;
+ PixelB %= fractions;
+
+ leds[XY(x, 0)] = PixelA + PixelB;
+ }
+ }
+
+ void standardNoiseSmearing() {
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ FillNoise();
+
+ MoveX(3);
+ MoveFractionalNoiseY(4);
+
+ MoveY(3);
+ MoveFractionalNoiseX(4);
+ }
+
+
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/Geometry.h b/examples/ChainedPanelsAuroraDemo/Geometry.h
new file mode 100644
index 0000000..8efb768
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Geometry.h
@@ -0,0 +1,150 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from Noel Bundy's work: https://github.com/TwystNeko/Object3d
+ * Copyright (c) 2014 Noel Bundy
+ *
+ * Portions of this code are adapted from the Petty library: https://code.google.com/p/peggy/
+ * Copyright (c) 2008 Windell H Oskay. All right reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Geometry_H
+#define Geometry_H
+
+struct Vertex
+{
+ float x, y, z;
+ Vertex()
+ {
+ this->set(0, 0, 0);
+ }
+
+ Vertex(float x, float y, float z)
+ {
+ this->set(x, y, z);
+ }
+
+ void set(float x, float y, float z)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+};
+
+struct EdgePoint
+{
+ int x, y;
+ boolean visible;
+
+ EdgePoint()
+ {
+ this->set(0, 0);
+ this->visible = false;
+ }
+
+ void set(int a, int b)
+ {
+ this->x = a;
+ this->y = b;
+ }
+};
+
+struct Point
+{
+ float x, y;
+
+ Point()
+ {
+ set(0, 0);
+ }
+
+ Point(float x, float y)
+ {
+ set(x, y);
+ }
+
+ void set(float x, float y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+
+};
+
+struct squareFace
+{
+ int length;
+ int sommets[4];
+ int ed[4];
+
+ squareFace()
+ {
+ set(-1, -1, -1, -1);
+ }
+
+ squareFace(int a, int b, int c, int d)
+ {
+ this->length = 4;
+ this->sommets[0] = a;
+ this->sommets[1] = b;
+ this->sommets[2] = c;
+ this->sommets[3] = d;
+ }
+
+ void set(int a, int b, int c, int d)
+ {
+ this->length = 4;
+ this->sommets[0] = a;
+ this->sommets[1] = b;
+ this->sommets[2] = c;
+ this->sommets[3] = d;
+ }
+
+};
+
+struct triFace
+{
+ int length;
+ int sommets[3];
+ int ed[3];
+
+ triFace()
+ {
+ set(-1,-1,-1);
+ }
+ triFace(int a, int b, int c)
+ {
+ this->length =3;
+ this->sommets[0]=a;
+ this->sommets[1]=b;
+ this->sommets[2]=c;
+ }
+ void set(int a, int b, int c)
+ {
+ this->length =3;
+ this->sommets[0]=a;
+ this->sommets[1]=b;
+ this->sommets[2]=c;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PaletteFireKoz.h b/examples/ChainedPanelsAuroraDemo/PaletteFireKoz.h
new file mode 100644
index 0000000..8398331
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PaletteFireKoz.h
@@ -0,0 +1,6 @@
+const uint8_t PROGMEM palette_fire[] = {/* RGB888 R,G,B,R,G,B,R,G,B,... */
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x05,0x00,0x00,0x0a,0x00,0x00,0x10,0x00,0x00,0x15,0x00,0x00,0x1b,0x00,0x00,0x20,0x00,0x00,0x25,0x00,0x00,0x2b,0x00,0x00,0x31,0x00,0x00,0x36,0x00,0x00,0x3c,0x00,0x00,0x41,0x00,0x00,0x46,0x00,0x00,0x4c,0x00,0x00,0x52,0x00,0x00,0x57,0x00,0x00,0x5d,0x00,0x00,0x62,0x00,0x00,0x68,0x00,0x00,0x6d,0x00,0x00,0x73,0x00,0x00,0x79,0x00,0x00,0x7e,0x00,0x00,0x83,0x00,0x00,0x89,0x00,0x00,0x8e,0x00,0x00,0x94,0x00,0x00,0x9a,0x00,0x00,0x9f,0x00,0x00,0xa5,0x00,0x00,0xaa,0x00,0x00,0xb0,0x00,0x00,0xb5,0x00,0x00,0xbb,0x00,0x00,0xc0,0x00,0x00,0xc6,0x00,0x00,0xcb,0x00,0x00,0xd1,0x00,0x00,0xd7,0x00,0x00,0xdc,0x00,0x00,0xe1,0x00,0x00,0xe6,0x00,0x00,0xe8,0x02,0x00,0xe9,0x08,0x00,0xe9,0x0f,0x00,0xe9,0x13,0x00,0xe9,0x16,0x00,0xe9,0x1b,0x00,0xe9,0x21,0x00,0xe9,0x26,0x00,0xe9,0x2a,0x00,0xe9,0x2e,0x00,0xe9,0x32,0x00,0xe9,0x37,0x00,0xe9,0x3b,0x00,0xe9,0x3f,0x00,0xe9,0x44,0x00,0xe9,0x4a,0x00,0xe9,0x4e,0x00,0xe9,0x52,0x00,0xe9,0x56,0x00,0xe9,0x5a,0x00,0xe9,0x5d,0x00,0xe9,0x63,0x00,0xe9,0x67,0x00,0xe9,0x6b,0x00,0xe9,0x71,0x00,0xe9,0x77,0x00,0xe9,0x78,0x00,0xe9,0x7c,0x00,0xe9,0x81,0x00,0xe9,0x86,0x00,0xe9,0x8b,0x00,0xe9,0x8f,0x00,0xe9,0x93,0x00,0xe9,0x99,0x00,0xe9,0x9d,0x00,0xe9,0xa0,0x00,0xe9,0xa4,0x00,0xe9,0xaa,0x00,0xe9,0xb0,0x00,0xe9,0xb4,0x00,0xe9,0xb5,0x00,0xe9,0xb9,0x00,0xe9,0xbe,0x00,0xe9,0xc3,0x00,0xe9,0xc9,0x00,0xe9,0xce,0x00,0xe9,0xd2,0x00,0xe9,0xd6,0x00,0xe9,0xd9,0x00,0xe9,0xdd,0x00,0xe9,0xe2,0x00,0xe9,0xe7,0x02,0xe9,0xe9,0x0e,0xe9,0xe9,0x1c,0xe9,0xe9,0x28,0xe9,0xe9,0x38,0xe9,0xe9,0x48,0xe9,0xe9,0x57,0xe9,0xe9,0x67,0xe9,0xe9,0x73,0xe9,0xe9,0x81,0xe9,0xe9,0x90,0xe9,0xe9,0xa1,0xe9,0xe9,0xb1,0xe9,0xe9,0xbf,0xe9,0xe9,0xcb,0xe9,0xe9,0xcb,0xe9,0xe9,0xcd,0xe9,0xe9,0xd9,0xe9,0xe9,0xe5,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,0xe6,0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe0,0xe0,0xe0,0xdc,0xdc,0xdc,0xd8,0xd8,0xd8,0xd2,0xd2,0xd2,0xca,0xca,0xca,0xc1,0xc1,0xc1,0xb7,0xb7,0xb7,0xab,0xab,0xab,0x9d,0x9d,0x9d,0x8f,0x8f,0x8f,0x81,0x81,0x81,0x72,0x72,0x72,0x64,0x64,0x64,0x56,0x56,0x56,0x4a,0x4a,0x4a,0x3e,0x3e,0x3e,0x33,0x33,0x33,0x2a,0x2a,0x2a,0x22,0x22,0x22,0x1b,0x1b,0x1b,0x16,0x16,0x16,0x11,0x11,0x11,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x05,0x05,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+//const uint8_t PROGMEM palletfire[] = {/* RGB888 R,G,B,R,G,B,R,G,B,... */
+//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x05,0x00,0x00,0x0a,0x00,0x00,0x10,0x00,0x00,0x15,0x00,0x00,0x1b,0x00,0x00,0x20,0x00,0x00,0x25,0x00,0x00,0x2b,0x00,0x00,0x31,0x00,0x00,0x36,0x00,0x00,0x3c,0x00,0x00,0x41,0x00,0x00,0x46,0x00,0x00,0x4c,0x00,0x00,0x52,0x00,0x00,0x57,0x00,0x00,0x5d,0x00,0x00,0x62,0x00,0x00,0x68,0x00,0x00,0x6d,0x00,0x00,0x73,0x00,0x00,0x79,0x00,0x00,0x7e,0x00,0x00,0x83,0x00,0x00,0x89,0x00,0x00,0x8e,0x00,0x00,0x94,0x00,0x00,0x9a,0x00,0x00,0x9f,0x00,0x00,0xa5,0x00,0x00,0xaa,0x00,0x00,0xb0,0x00,0x00,0xb5,0x00,0x00,0xbb,0x00,0x00,0xc0,0x00,0x00,0xc6,0x00,0x00,0xcb,0x00,0x00,0xd1,0x00,0x00,0xd7,0x00,0x00,0xdc,0x00,0x00,0xe1,0x00,0x00,0xe6,0x00,0x00,0xe8,0x02,0x00,0xe9,0x08,0x00,0xe9,0x0f,0x00,0xe9,0x13,0x00,0xe9,0x16,0x00,0xe9,0x1b,0x00,0xe9,0x21,0x00,0xe9,0x26,0x00,0xe9,0x2a,0x00,0xe9,0x2e,0x00,0xe9,0x32,0x00,0xe9,0x37,0x00,0xe9,0x3b,0x00,0xe9,0x3f,0x00,0xe9,0x44,0x00,0xe9,0x4a,0x00,0xe9,0x4e,0x00,0xe9,0x52,0x00,0xe9,0x56,0x00,0xe9,0x5a,0x00,0xe9,0x5d,0x00,0xe9,0x63,0x00,0xe9,0x67,0x00,0xe9,0x6b,0x00,0xe9,0x71,0x00,0xe9,0x77,0x00,0xe9,0x78,0x00,0xe9,0x7c,0x00,0xe9,0x81,0x00,0xe9,0x86,0x00,0xe9,0x8b,0x00,0xe9,0x8f,0x00,0xe9,0x93,0x00,0xe9,0x99,0x00,0xe9,0x9d,0x00,0xe9,0xa0,0x00,0xe9,0xa4,0x00,0xe9,0xaa,0x00,0xe9,0xb0,0x00,0xe9,0xb4,0x00,0xe9,0xb5,0x00,0xe9,0xb9,0x00,0xe9,0xbe,0x00,0xe9,0xc3,0x00,0xe9,0xc9,0x00,0xe9,0xce,0x00,0xe9,0xd2,0x00,0xe9,0xd6,0x00,0xe9,0xd9,0x00,0xe9,0xdd,0x00,0xe9,0xe2,0x00,0xe9,0xe7,0x02,0xe9,0xe9,0x0e,0xe9,0xe9,0x1c,0xe9,0xe9,0x28,0xe9,0xe9,0x38,0xe9,0xe9,0x48,0xe9,0xe9,0x57,0xe9,0xe9,0x67,0xe9,0xe9,0x73,0xe9,0xe9,0x81,0xe9,0xe9,0x90,0xe9,0xe9,0xa1,0xe9,0xe9,0xb1,0xe9,0xe9,0xbf,0xe9,0xe9,0xcb,0xe9,0xe9,0xcb,0xe9,0xe9,0xcd,0xe9,0xe9,0xd9,0xe9,0xe9,0xe5,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,0xe6,0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe0,0xe0,0xe0,0xdc,0xdc,0xdc,0xd8,0xd8,0xd8,0xd2,0xd2,0xd2,0xca,0xca,0xca,0xc1,0xc1,0xc1,0xb7,0xb7,0xb7,0xab,0xab,0xab,0x9d,0x9d,0x9d,0x8f,0x8f,0x8f,0x81,0x81,0x81,0x72,0x72,0x72,0x64,0x64,0x64,0x56,0x56,0x56,0x4a,0x4a,0x4a,0x3e,0x3e,0x3e,0x33,0x33,0x33,0x2a,0x2a,0x2a,0x22,0x22,0x22,0x1b,0x1b,0x1b,0x16,0x16,0x16,0x11,0x11,0x11,0x0d,0x0d,0x0d,0x0b,0x0b,0x0b,0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x05,0x05,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+//};
diff --git a/examples/ChainedPanelsAuroraDemo/PatternAttract.h b/examples/ChainedPanelsAuroraDemo/PatternAttract.h
new file mode 100644
index 0000000..7df342c
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternAttract.h
@@ -0,0 +1,73 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternAttract_H
+
+class PatternAttract : public Drawable {
+private:
+ const int count = 8;
+ Attractor attractor;
+
+public:
+ PatternAttract() {
+ name = (char *)"Attract";
+ }
+
+ void start() {
+ int direction = random(0, 2);
+ if (direction == 0)
+ direction = -1;
+
+ for (int i = 0; i < count; i++) {
+ Boid boid = Boid(15, 31 - i);
+ boid.mass = 1; // random(0.1, 2);
+ boid.velocity.x = ((float) random(40, 50)) / 100.0;
+ boid.velocity.x *= direction;
+ boid.velocity.y = 0;
+ boid.colorIndex = i * 32;
+ boids[i] = boid;
+ //dim = random(170, 250);
+ }
+ }
+
+ unsigned int drawFrame() {
+ // dim all pixels on the display
+ uint8_t dim = beatsin8(2, 170, 250);
+ effects.DimAll(dim); effects.ShowFrame();
+
+ for (int i = 0; i < count; i++) {
+ Boid boid = boids[i];
+
+ PVector force = attractor.attract(boid);
+ boid.applyForce(force);
+
+ boid.update();
+ effects.drawBackgroundFastLEDPixelCRGB(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex));
+
+ boids[i] = boid;
+ }
+
+ return 15;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h b/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h
new file mode 100644
index 0000000..c6ea4a7
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h
@@ -0,0 +1,116 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from "Funky Noise" by Stefan Petrick: https://github.com/StefanPetrick/FunkyNoise
+ * Copyright (c) 2014 Stefan Petrick
+ * http://www.stefan-petrick.de/wordpress_beta
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternElectricMandala_H
+
+class PatternElectricMandala : public Drawable {
+ private:
+
+ // The coordinates for 16-bit noise spaces.
+#define NUM_LAYERS 1
+
+ // used for the random based animations
+ int16_t dx;
+ int16_t dy;
+ int16_t dz;
+ int16_t dsx;
+ int16_t dsy;
+
+ public:
+ PatternElectricMandala() {
+ name = (char *)"ElectricMandala";
+ }
+
+ void start() {
+ // set to reasonable values to avoid a black out
+ noisesmoothing = 200;
+
+ // just any free input pin
+ //random16_add_entropy(analogRead(18));
+
+ // fill coordinates with random values
+ // set zoom levels
+ noise_x = random16();
+ noise_y = random16();
+ noise_z = random16();
+ noise_scale_x = 6000;
+ noise_scale_y = 6000;
+
+ // for the random movement
+ dx = random8();
+ dy = random8();
+ dz = random8();
+ dsx = random8();
+ dsy = random8();
+ }
+
+ unsigned int drawFrame() {
+#if FASTLED_VERSION >= 3001000
+ // a new parameter set every 15 seconds
+ EVERY_N_SECONDS(25) {
+ //SetupRandomPalette3();
+ dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too
+ dx = random16(500) - 250;
+ dz = random16(500) - 250;
+ noise_scale_x = random16(10000) + 2000;
+ noise_scale_y = random16(10000) + 2000;
+ }
+#endif
+
+ noise_y += dy;
+ noise_x += dx;
+ noise_z += dz;
+
+ effects.FillNoise();
+ ShowNoiseLayer(0, 1, 0);
+
+ effects.Caleidoscope3();
+ effects.Caleidoscope1();
+
+ effects.ShowFrame();
+
+ return 0;
+ }
+
+ // show just one layer
+ void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
+ for (uint8_t i = 0; i < VPANEL_W; i++) {
+ for (uint8_t j = 0; j < VPANEL_H; j++) {
+
+ uint8_t color = noise[i][j];
+
+ uint8_t bri = color;
+
+ // assign a color depending on the actual palette
+ CRGB pixel = ColorFromPalette(effects.currentPalette, colorrepeat * (color + colorshift), bri);
+
+ effects.leds[XY(i, j)] = pixel;
+ }
+ }
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternFire.h b/examples/ChainedPanelsAuroraDemo/PatternFire.h
new file mode 100644
index 0000000..5d5d021
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternFire.h
@@ -0,0 +1,121 @@
+/*
+ Aurora: https://github.com/pixelmatix/aurora
+ Copyright (c) 2014 Jason Coon
+
+ Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/tree/master/examples/Fire2012WithPalette
+ Copyright (c) 2013 FastLED
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+// Note: (Kosso) : Doesn't look good with certain palettes.
+
+#ifndef PatternFire_H
+#define PatternFire_H
+
+#ifndef Effects_H
+#include "Effects.h"
+#endif
+
+class PatternFire : public Drawable {
+ private:
+
+ public:
+ PatternFire() {
+ name = (char *)"Fire";
+ }
+
+ // There are two main parameters you can play with to control the look and
+ // feel of your fire: COOLING (used in step 1 above), and SPARKING (used
+ // in step 3 above).
+ //
+ // cooling: How much does the air cool as it rises?
+ // Less cooling = taller flames. More cooling = shorter flames.
+ // Default 55, suggested range 20-100
+ int cooling = 100;
+
+ // sparking: What chance (out of 255) is there that a new spark will be lit?
+ // Higher chance = more roaring fire. Lower chance = more flickery fire.
+ // Default 120, suggested range 50-200.
+ unsigned int sparking = 100;
+
+ unsigned int drawFrame() {
+ // Add entropy to random number generator; we use a lot of it.
+ random16_add_entropy( random16());
+
+ effects.DimAll(235);
+
+ for (int x = 0; x < VPANEL_W; x++) {
+ // Step 1. Cool down every cell a little
+ for (int y = 0; y < VPANEL_H; y++) {
+ int xy = XY(x, y);
+ heat[xy] = qsub8(heat[xy], random8(0, ((cooling * 10) / VPANEL_H) + 2));
+ }
+
+ // Step 2. Heat from each cell drifts 'up' and diffuses a little
+ for (int y = 0; y < VPANEL_H; y++) {
+ heat[XY(x, y)] = (heat[XY(x, y + 1)] + heat[XY(x, y + 2)] + heat[XY(x, y + 2)]) / 3;
+ }
+
+ // Step 2. Randomly ignite new 'sparks' of heat
+ if (random8() < sparking) {
+ // int x = (p[0] + p[1] + p[2]) / 3;
+
+ int xy = XY(x, VPANEL_H - 1);
+ heat[xy] = qadd8(heat[xy], random8(160, 255));
+ }
+
+ // Step 4. Map from heat cells to LED colors
+ for (int y = 0; y < VPANEL_H; y++) {
+ int xy = XY(x, y);
+ byte colorIndex = heat[xy];
+
+ // Recommend that you use values 0-240 rather than
+ // the usual 0-255, as the last 15 colors will be
+ // 'wrapping around' from the hot end to the cold end,
+ // which looks wrong.
+ colorIndex = scale8(colorIndex, 200);
+
+ // override color 0 to ensure a black background?
+ //if (colorIndex != 0) {
+ // effects.leds[xy] = CRGB::Black;
+ //}
+ //else {
+ effects.leds[xy] = effects.ColorFromCurrentPalette(colorIndex);
+ //}
+ }
+ }
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_z += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ // effects.MoveX(2);
+ effects.MoveFractionalNoiseX(2);
+
+ effects.ShowFrame();
+
+ return 15;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternFireKoz.h b/examples/ChainedPanelsAuroraDemo/PatternFireKoz.h
new file mode 100644
index 0000000..c553d6b
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternFireKoz.h
@@ -0,0 +1,109 @@
+/*
+ Aurora: https://github.com/pixelmatix/aurora
+ Copyright (c) 2014 Jason Coon
+
+ Added by @Kosso. Cobbled together from various places which I can't remember. I'll update this when I track it down.
+ Requires PaletteFireKoz.h
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternFireKoz_H
+#define PatternFireKoz_H
+
+class PatternFireKoz : public Drawable {
+ private:
+
+ const int FIRE_HEIGHT = 800;
+
+ int Bit = 0, NBit = 1;
+ float fire_c;
+ // might not need this buffer here... there some led buffers set up in Effects.h
+ uint8_t fireBuffer[VPANEL_W][VPANEL_H][2];
+
+ public:
+ PatternFireKoz() {
+ name = (char *)"FireKoz";
+ }
+
+ unsigned int drawFrame() {
+
+ for (int x = 1; x < VPANEL_W - 1; x++)
+ {
+ fireBuffer[x][VPANEL_H - 2][Bit] = random(0, FIRE_HEIGHT);
+ if (random(0, 100) > 80)
+ {
+ fireBuffer[x][VPANEL_H - 2][Bit] = 0;
+ fireBuffer[x][VPANEL_H - 3][Bit] = 0;
+ }
+ }
+ for (int y = 1; y < VPANEL_H - 1; y++)
+ {
+ for (int x = 1; x < VPANEL_W - 1; x++)
+ {
+ fire_c = (fireBuffer[x - 1][y][Bit] +
+ fireBuffer[x + 1][y][Bit] +
+ fireBuffer[x][y - 1][Bit] +
+ fireBuffer[x][y + 1][Bit] +
+ fireBuffer[x][y][Bit]) /
+ 5.0;
+
+ fire_c = (fireBuffer[x - 1][y][Bit] +
+ fireBuffer[x + 1][y][Bit] +
+ fireBuffer[x][y - 1][Bit] +
+ fireBuffer[x][y + 1][Bit] +
+ fireBuffer[x][y][Bit]) /
+ 5.0;
+
+ if (fire_c > (FIRE_HEIGHT / 2) && fire_c < FIRE_HEIGHT) {
+ fire_c -= 0.2;
+ } else if (fire_c > (FIRE_HEIGHT / 4) && fire_c < (FIRE_HEIGHT / 2)) {
+ fire_c -= 0.4;
+ } else if (fire_c <= (FIRE_HEIGHT / 8)) {
+ fire_c -= 0.7;
+ } else {
+ fire_c -= 1;
+ }
+ if (fire_c < 0)
+ fire_c = 0;
+ if (fire_c >= FIRE_HEIGHT + 1)
+ fire_c = FIRE_HEIGHT - 1;
+ fireBuffer[x][y - 1][NBit] = fire_c;
+ int index = (int)fire_c * 3;
+ if (fire_c == 0)
+ {
+ effects.drawBackgroundFastLEDPixelCRGB(x, y, CRGB(0, 0, 0));
+ }
+ else
+ {
+ effects.drawBackgroundFastLEDPixelCRGB(x, y, CRGB(palette_fire[index], palette_fire[index + 1], palette_fire[index + 2]));
+ }
+ }
+ }
+ //display.drawRect(0, 0, VPANEL_W, VPANEL_H, display.color565(25, 25, 25));
+
+ NBit = Bit;
+ Bit = 1 - Bit;
+
+ effects.ShowFrame();
+
+ return 30; // no idea what this is for...
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternFlock.h b/examples/ChainedPanelsAuroraDemo/PatternFlock.h
new file mode 100644
index 0000000..3ae31b1
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternFlock.h
@@ -0,0 +1,125 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from "Flocking" in "The Nature of Code" by Daniel Shiffman: http://natureofcode.com/
+ * Copyright (c) 2014 Daniel Shiffman
+ * http://www.shiffman.net
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+// Flocking
+// Daniel Shiffman <http://www.shiffman.net>
+// The Nature of Code, Spring 2009
+
+// Demonstration of Craig Reynolds' "Flocking" behavior
+// See: http://www.red3d.com/cwr/
+// Rules: Cohesion, Separation, Alignment
+
+#ifndef PatternFlock_H
+#define PatternFlock_H
+
+class PatternFlock : public Drawable {
+ public:
+ PatternFlock() {
+ name = (char *)"Flock";
+ }
+
+ static const int boidCount = 10;
+ Boid predator;
+
+ PVector wind;
+ byte hue = 0;
+ bool predatorPresent = true;
+
+ void start() {
+ for (int i = 0; i < boidCount; i++) {
+ boids[i] = Boid(15, 15);
+ boids[i].maxspeed = 0.380;
+ boids[i].maxforce = 0.015;
+ }
+
+ predatorPresent = random(0, 2) >= 1;
+ if (predatorPresent) {
+ predator = Boid(31, 31);
+ predatorPresent = true;
+ predator.maxspeed = 0.385;
+ predator.maxforce = 0.020;
+ predator.neighbordist = 16.0;
+ predator.desiredseparation = 0.0;
+ }
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(230); effects.ShowFrame();
+
+ bool applyWind = random(0, 255) > 250;
+ if (applyWind) {
+ wind.x = Boid::randomf() * .015;
+ wind.y = Boid::randomf() * .015;
+ }
+
+ CRGB color = effects.ColorFromCurrentPalette(hue);
+
+ for (int i = 0; i < boidCount; i++) {
+ Boid * boid = &boids[i];
+
+ if (predatorPresent) {
+ // flee from predator
+ boid->repelForce(predator.location, 10);
+ }
+
+ boid->run(boids, boidCount);
+ boid->wrapAroundBorders();
+ PVector location = boid->location;
+ // PVector velocity = boid->velocity;
+ // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
+ // effects.leds[XY(location.x, location.y)] += color;
+ effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color);
+
+ if (applyWind) {
+ boid->applyForce(wind);
+ applyWind = false;
+ }
+ }
+
+ if (predatorPresent) {
+ predator.run(boids, boidCount);
+ predator.wrapAroundBorders();
+ color = effects.ColorFromCurrentPalette(hue + 128);
+ PVector location = predator.location;
+ // PVector velocity = predator.velocity;
+ // backgroundLayer.drawLine(location.x, location.y, location.x - velocity.x, location.y - velocity.y, color);
+ // effects.leds[XY(location.x, location.y)] += color;
+ effects.drawBackgroundFastLEDPixelCRGB(location.x, location.y, color);
+ }
+
+ EVERY_N_MILLIS(200) {
+ hue++;
+ }
+
+ EVERY_N_SECONDS(30) {
+ predatorPresent = !predatorPresent;
+ }
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternFlowField.h b/examples/ChainedPanelsAuroraDemo/PatternFlowField.h
new file mode 100644
index 0000000..be91ff2
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternFlowField.h
@@ -0,0 +1,92 @@
+/*
+* Aurora: https://github.com/pixelmatix/aurora
+* Copyright (c) 2014 Jason Coon
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+* the Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternFlowField_H
+
+class PatternFlowField : public Drawable {
+ public:
+ PatternFlowField() {
+ name = (char *)"FlowField";
+ }
+
+ uint16_t x;
+ uint16_t y;
+ uint16_t z;
+
+ uint16_t speed = 1;
+ uint16_t scale = 26;
+
+ static const int count = 40;
+
+ byte hue = 0;
+
+ void start() {
+ x = random16();
+ y = random16();
+ z = random16();
+
+ for (int i = 0; i < count; i++) {
+ boids[i] = Boid(random(VPANEL_W), 0);
+ }
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(240);
+
+ // CRGB color = effects.ColorFromCurrentPalette(hue);
+
+ for (int i = 0; i < count; i++) {
+ Boid * boid = &boids[i];
+
+ int ioffset = scale * boid->location.x;
+ int joffset = scale * boid->location.y;
+
+ byte angle = inoise8(x + ioffset, y + joffset, z);
+
+ boid->velocity.x = (float) sin8(angle) * 0.0078125 - 1.0;
+ boid->velocity.y = -((float)cos8(angle) * 0.0078125 - 1.0);
+ boid->update();
+
+ effects.drawBackgroundFastLEDPixelCRGB(boid->location.x, boid->location.y, effects.ColorFromCurrentPalette(angle + hue)); // color
+
+ if (boid->location.x < 0 || boid->location.x >= VPANEL_W ||
+ boid->location.y < 0 || boid->location.y >= VPANEL_H) {
+ boid->location.x = random(VPANEL_W);
+ boid->location.y = 0;
+ }
+ }
+
+ EVERY_N_MILLIS(200) {
+ hue++;
+ }
+
+ x += speed;
+ y += speed;
+ z += speed;
+
+ effects.ShowFrame();
+
+ return 50;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h
new file mode 100644
index 0000000..98c9b08
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h
@@ -0,0 +1,51 @@
+/*
+*
+* Aurora: https://github.com/pixelmatix/aurora
+* Copyright (c) 2014 Jason Coon
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+* the Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternIncrementalDrift_H
+#define PatternIncrementalDrift_H
+
+class PatternIncrementalDrift : public Drawable {
+ public:
+ PatternIncrementalDrift() {
+ name = (char *)"Incremental Drift";
+ }
+
+ unsigned int drawFrame() {
+ uint8_t dim = beatsin8(2, 230, 250);
+ effects.DimAll(dim); effects.ShowFrame();
+
+ for (int i = 2; i <= VPANEL_W / 2; i++)
+ {
+ CRGB color = effects.ColorFromCurrentPalette((i - 2) * (240 / (VPANEL_W / 2)));
+
+ uint8_t x = beatcos8((17 - i) * 2, MATRIX_CENTER_X - i, MATRIX_CENTER_X + i);
+ uint8_t y = beatsin8((17 - i) * 2, MATRIX_CENTER_Y - i, MATRIX_CENTER_Y + i);
+
+ effects.drawBackgroundFastLEDPixelCRGB(x, y, color);
+ }
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternInfinity.h b/examples/ChainedPanelsAuroraDemo/PatternInfinity.h
new file mode 100644
index 0000000..87803a7
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternInfinity.h
@@ -0,0 +1,58 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternInfinity_H
+
+class PatternInfinity : public Drawable {
+public:
+ PatternInfinity() {
+ name = (char *)"Infinity";
+ }
+
+ unsigned int drawFrame() {
+ // dim all pixels on the display slightly
+ // to 250/255 (98%) of their current brightness
+ effects.DimAll(250); effects.ShowFrame();
+
+ // the Effects class has some sample oscillators
+ // that move from 0 to 255 at different speeds
+ effects.MoveOscillators();
+
+ // the horizontal position of the head of the infinity sign
+ // oscillates from 0 to the maximum horizontal and back
+ int x = (VPANEL_W - 1) - effects.p[1];
+
+ // the vertical position of the head oscillates
+ // from 8 to 23 and back (hard-coded for a 32x32 matrix)
+ int y = map8(sin8(effects.osci[3]), 8, 23);
+
+ // the hue oscillates from 0 to 255, overflowing back to 0
+ byte hue = sin8(effects.osci[5]);
+
+ // draw a pixel at x,y using a color from the current palette
+ effects.Pixel(x, y, hue);
+
+ return 15;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternLife.h b/examples/ChainedPanelsAuroraDemo/PatternLife.h
new file mode 100644
index 0000000..8074e40
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternLife.h
@@ -0,0 +1,129 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from Andrew: http://pastebin.com/f22bfe94d
+ * which, in turn, was "Adapted from the Life example on the Processing.org site"
+ *
+ * Made much more colorful by J.B. Langston: https://github.com/jblang/aurora/commit/6db5a884e3df5d686445c4f6b669f1668841929b
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternLife_H
+#define PatternLife_H
+
+class Cell {
+public:
+ byte alive : 1;
+ byte prev : 1;
+ byte hue: 6;
+ byte brightness;
+};
+
+class PatternLife : public Drawable {
+private:
+ Cell world[VPANEL_W][VPANEL_H];
+ unsigned int density = 50;
+ int generation = 0;
+
+ void randomFillWorld() {
+ for (int i = 0; i < VPANEL_W; i++) {
+ for (int j = 0; j < VPANEL_H; j++) {
+ if (random(100) < density) {
+ world[i][j].alive = 1;
+ world[i][j].brightness = 255;
+ }
+ else {
+ world[i][j].alive = 0;
+ world[i][j].brightness = 0;
+ }
+ world[i][j].prev = world[i][j].alive;
+ world[i][j].hue = 0;
+ }
+ }
+ }
+
+ int neighbours(int x, int y) {
+ return (world[(x + 1) % VPANEL_W][y].prev) +
+ (world[x][(y + 1) % VPANEL_H].prev) +
+ (world[(x + VPANEL_W - 1) % VPANEL_W][y].prev) +
+ (world[x][(y + VPANEL_H - 1) % VPANEL_H].prev) +
+ (world[(x + 1) % VPANEL_W][(y + 1) % VPANEL_H].prev) +
+ (world[(x + VPANEL_W - 1) % VPANEL_W][(y + 1) % VPANEL_H].prev) +
+ (world[(x + VPANEL_W - 1) % VPANEL_W][(y + VPANEL_H - 1) % VPANEL_H].prev) +
+ (world[(x + 1) % VPANEL_W][(y + VPANEL_H - 1) % VPANEL_H].prev);
+ }
+
+public:
+ PatternLife() {
+ name = (char *)"Life";
+ }
+
+ unsigned int drawFrame() {
+ if (generation == 0) {
+ effects.ClearFrame();
+
+ randomFillWorld();
+ }
+
+ // Display current generation
+ for (int i = 0; i < VPANEL_W; i++) {
+ for (int j = 0; j < VPANEL_H; j++) {
+ effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(world[i][j].hue * 4, world[i][j].brightness);
+ }
+ }
+
+ // Birth and death cycle
+ for (int x = 0; x < VPANEL_W; x++) {
+ for (int y = 0; y < VPANEL_H; y++) {
+ // Default is for cell to stay the same
+ if (world[x][y].brightness > 0 && world[x][y].prev == 0)
+ world[x][y].brightness *= 0.9;
+ int count = neighbours(x, y);
+ if (count == 3 && world[x][y].prev == 0) {
+ // A new cell is born
+ world[x][y].alive = 1;
+ world[x][y].hue += 2;
+ world[x][y].brightness = 255;
+ } else if ((count < 2 || count > 3) && world[x][y].prev == 1) {
+ // Cell dies
+ world[x][y].alive = 0;
+ }
+ }
+ }
+
+ // Copy next generation into place
+ for (int x = 0; x < VPANEL_W; x++) {
+ for (int y = 0; y < VPANEL_H; y++) {
+ world[x][y].prev = world[x][y].alive;
+ }
+ }
+
+
+ generation++;
+ if (generation >= 256)
+ generation = 0;
+
+ effects.ShowFrame();
+
+ return 60;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternMaze.h b/examples/ChainedPanelsAuroraDemo/PatternMaze.h
new file mode 100644
index 0000000..8a94d26
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternMaze.h
@@ -0,0 +1,264 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Many thanks to Jamis Buck for the documentation of the Growing Tree maze generation algorithm: http://weblog.jamisbuck.org/2011/1/27/maze-generation-growing-tree-algorithm
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternMaze_H
+#define PatternMaze_H
+
+class PatternMaze : public Drawable {
+private:
+ enum Directions {
+ None = 0,
+ Up = 1,
+ Down = 2,
+ Left = 4,
+ Right = 8,
+ };
+
+ struct Point{
+ int x;
+ int y;
+
+ static Point New(int x, int y) {
+ Point point;
+ point.x = x;
+ point.y = y;
+ return point;
+ }
+
+ Point Move(Directions direction) {
+ switch (direction)
+ {
+ case Up:
+ return New(x, y - 1);
+
+ case Down:
+ return New(x, y + 1);
+
+ case Left:
+ return New(x - 1, y);
+
+ case Right:
+ default:
+ return New(x + 1, y);
+ }
+ }
+
+ static Directions Opposite(Directions direction) {
+ switch (direction) {
+ case Up:
+ return Down;
+
+ case Down:
+ return Up;
+
+ case Left:
+ return Right;
+
+ case Right:
+ default:
+ return Left;
+ }
+ }
+ };
+
+// int width = 16;
+// int height = 16;
+
+ static const int width = VPANEL_W / 2;
+ static const int height = VPANEL_H / 2;
+
+
+ Directions grid[width][height];
+
+ Point point;
+
+ Point cells[256];
+ int cellCount = 0;
+
+ int algorithm = 0;
+ int algorithmCount = 1;
+
+ byte hue = 0;
+ byte hueOffset = 0;
+
+ Directions directions[4] = { Up, Down, Left, Right };
+
+ void removeCell(int index) {// shift cells after index down one
+ for (int i = index; i < cellCount - 1; i++) {
+ cells[i] = cells[i + 1];
+ }
+
+ cellCount--;
+ }
+
+ void shuffleDirections() {
+ for (int a = 0; a < 4; a++)
+ {
+ int r = random(a, 4);
+ Directions temp = directions[a];
+ directions[a] = directions[r];
+ directions[r] = temp;
+ }
+ }
+
+ Point createPoint(int x, int y) {
+ Point point;
+ point.x = x;
+ point.y = y;
+ return point;
+ }
+
+ CRGB chooseColor(int index) {
+ byte h = index + hueOffset;
+
+ switch (algorithm) {
+ case 0:
+ default:
+ return effects.ColorFromCurrentPalette(h);
+
+ case 1:
+ return effects.ColorFromCurrentPalette(hue++);
+ }
+ }
+
+ int chooseIndex(int max) {
+ switch (algorithm) {
+ case 0:
+ default:
+ // choose newest (recursive backtracker)
+ return max - 1;
+
+ case 1:
+ // choose random(Prim's)
+ return random(max);
+
+ // case 2:
+ // // choose oldest (not good, so disabling)
+ // return 0;
+ }
+ }
+
+ void generateMaze() {
+ while (cellCount > 1) {
+ drawNextCell();
+ }
+ }
+
+ void drawNextCell() {
+ int index = chooseIndex(cellCount);
+
+ if (index < 0)
+ return;
+
+ point = cells[index];
+
+ Point imagePoint = createPoint(point.x * 2, point.y * 2);
+
+ //effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, CRGB(CRGB::Gray));
+
+ shuffleDirections();
+
+ CRGB color = chooseColor(index);
+
+ for (int i = 0; i < 4; i++) {
+ Directions direction = directions[i];
+
+ Point newPoint = point.Move(direction);
+ if (newPoint.x >= 0 && newPoint.y >= 0 && newPoint.x < width && newPoint.y < height && grid[newPoint.y][newPoint.x] == None) {
+ grid[point.y][point.x] = (Directions) ((int) grid[point.y][point.x] | (int) direction);
+ grid[newPoint.y][newPoint.x] = (Directions) ((int) grid[newPoint.y][newPoint.x] | (int) point.Opposite(direction));
+
+ Point newImagePoint = imagePoint.Move(direction);
+
+ effects.drawBackgroundFastLEDPixelCRGB(newImagePoint.x, newImagePoint.y, color);
+
+ cellCount++;
+ cells[cellCount - 1] = newPoint;
+
+ index = -1;
+ break;
+ }
+ }
+
+ if (index > -1) {
+ Point finishedPoint = cells[index];
+ imagePoint = createPoint(finishedPoint.x * 2, finishedPoint.y * 2);
+ effects.drawBackgroundFastLEDPixelCRGB(imagePoint.x, imagePoint.y, color);
+
+ removeCell(index);
+ }
+ }
+
+public:
+ PatternMaze() {
+ name = (char *)"Maze";
+ }
+
+ unsigned int drawFrame() {
+ if (cellCount < 1) {
+
+ effects.ClearFrame();
+
+ // reset the maze grid
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ grid[y][x] = None;
+ }
+ }
+
+ int x = random(width);
+ int y = random(height);
+
+ cells[0] = createPoint(x, y);
+
+ cellCount = 1;
+
+ hue = 0;
+ hueOffset = random(0, 256);
+
+ }
+
+ drawNextCell();
+
+ if (cellCount < 1) {
+ algorithm++;
+ if (algorithm >= algorithmCount)
+ algorithm = 0;
+
+ return 1000;
+ }
+
+ effects.ShowFrame();
+
+ return 0;
+ }
+
+ void start() {
+ matrix.fillScreen(0);
+ cellCount = 0;
+ hue = 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternMunch.h b/examples/ChainedPanelsAuroraDemo/PatternMunch.h
new file mode 100644
index 0000000..21d6720
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternMunch.h
@@ -0,0 +1,74 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Munch pattern created by J.B. Langston: https://github.com/jblang/aurora/blob/master/PatternMunch.h
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternMunch_H
+#define PatternMunch_H
+
+
+class PatternMunch : public Drawable {
+private:
+ byte count = 0;
+ byte dir = 1;
+ byte flip = 0;
+ byte generation = 0;
+
+public:
+ PatternMunch() {
+ name = (char *)"Munch";
+ }
+
+ unsigned int drawFrame() {
+
+ for (byte x = 0; x < VPANEL_W; x++) {
+ for (byte y = 0; y < VPANEL_H; y++) {
+ effects.leds[XY(x, y)] = (x ^ y ^ flip) < count ? effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) : CRGB::Black;
+
+ // The below is more pleasant
+ // effects.leds[XY(x, y)] = effects.ColorFromCurrentPalette(((x ^ y) << 2) + generation) ;
+ }
+ }
+
+ count += dir;
+
+ if (count <= 0 || count >= VPANEL_W) {
+ dir = -dir;
+ }
+
+ if (count <= 0) {
+ if (flip == 0)
+ flip = VPANEL_W-1;
+ else
+ flip = 0;
+ }
+
+ generation++;
+
+ // show it ffs!
+ effects.ShowFrame();
+
+ return 60;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h b/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h
new file mode 100644
index 0000000..96e8e53
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h
@@ -0,0 +1,338 @@
+/*
+* Aurora: https://github.com/pixelmatix/aurora
+* Copyright (c) 2014 Jason Coon
+*
+* Portions of this code are adapted from "Noise Smearing" by Stefan Petrick: https://gist.githubusercontent.com/embedded-creations/5cd47d83cb0e04f4574d/raw/ebf6a82b4755d55cfba3bf6598f7b19047f89daf/NoiseSmearing.ino
+* Copyright (c) 2014 Stefan Petrick
+* http://www.stefan-petrick.de/wordpress_beta
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+* the Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternNoiseSmearing_H
+#define PatternNoiseSmearing_H
+
+byte patternNoiseSmearingHue = 0;
+
+class PatternMultipleStream : public Drawable {
+public:
+ PatternMultipleStream() {
+ name = (char *)"MultipleStream";
+ }
+
+ // this pattern draws two points to the screen based on sin/cos if a counter
+ // (comment out NoiseSmearWithRadius to see pattern of pixels)
+ // these pixels are smeared by a large radius, giving a lot of movement
+ // the image is dimmed before each drawing to not saturate the screen with color
+ // the smear has an offset so the pixels usually have a trail leading toward the upper left
+ unsigned int drawFrame() {
+ static unsigned long counter = 0;
+#if 0
+ // this counter lets put delays between each frame and still get the same animation
+ counter++;
+#else
+ // this counter updates in real time and can't be slowed down for debugging
+ counter = millis() / 10;
+#endif
+
+ byte x1 = 4 + sin8(counter * 2) / 10;
+ byte x2 = 8 + sin8(counter * 2) / 16;
+ byte y2 = 8 + cos8((counter * 2) / 3) / 16;
+
+ effects.leds[XY(x1, x2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
+ effects.leds[XY(x2, y2)] = effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 128);
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(8);
+ // effects.MoveFractionalNoiseX();
+
+ effects.MoveY(8);
+ // effects.MoveFractionalNoiseY();
+
+ patternNoiseSmearingHue++;
+
+ return 0;
+ }
+};
+
+class PatternMultipleStream2 : public Drawable {
+public:
+ PatternMultipleStream2() {
+ name = (char *)"MultipleStream2";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(230); effects.ShowFrame();
+
+ byte xx = 4 + sin8(millis() / 9) / 10;
+ byte yy = 4 + cos8(millis() / 10) / 10;
+ effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
+
+ xx = 8 + sin8(millis() / 10) / 16;
+ yy = 8 + cos8(millis() / 7) / 16;
+ effects.leds[XY(xx, yy)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 80);
+
+ effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue + 160);
+
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_z += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ // effects.MoveFractionalNoiseY(4);
+
+ effects.MoveY(3);
+ //effects.MoveFractionalNoiseX(4);
+
+ patternNoiseSmearingHue++;
+
+ return 0;
+ }
+};
+
+class PatternMultipleStream3 : public Drawable {
+public:
+ PatternMultipleStream3() {
+ name = (char *)"MultipleStream3";
+ }
+
+ unsigned int drawFrame() {
+ //CLS();
+ effects.DimAll(235); effects.ShowFrame();
+
+ for (uint8_t i = 3; i < 32; i = i + 4) {
+ effects.leds[XY(i, 15)] += effects.ColorFromCurrentPalette(i * 8);
+ }
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_z += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ // effects.MoveFractionalNoiseY(4);
+
+ effects.MoveY(3);
+ // effects.MoveFractionalNoiseX(4);
+
+ effects.ShowFrame();
+
+ return 1;
+ }
+};
+
+class PatternMultipleStream4 : public Drawable {
+public:
+ PatternMultipleStream4() {
+ name = (char *)"MultipleStream4";
+ }
+
+ unsigned int drawFrame() {
+
+ //CLS();
+ effects.DimAll(235); effects.ShowFrame();
+
+ effects.leds[XY(15, 15)] += effects.ColorFromCurrentPalette(patternNoiseSmearingHue);
+
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(8);
+ // effects.MoveFractionalNoiseX();
+
+ effects.MoveY(8);
+ // effects.MoveFractionalNoiseY();
+
+ patternNoiseSmearingHue++;
+
+ return 0;
+ }
+};
+
+class PatternMultipleStream5 : public Drawable {
+public:
+ PatternMultipleStream5() {
+ name = (char *)"MultipleStream5";
+ }
+
+ unsigned int drawFrame() {
+
+ //CLS();
+ effects.DimAll(235); effects.ShowFrame();
+
+
+ for (uint8_t i = 3; i < 32; i = i + 4) {
+ effects.leds[XY(i, 31)] += effects.ColorFromCurrentPalette(i * 8);
+ }
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_z += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ // effects.MoveFractionalNoiseY(4);
+
+ effects.MoveY(4);
+ // effects.MoveFractionalNoiseX(4);
+
+ return 0;
+ }
+};
+
+class PatternMultipleStream8 : public Drawable {
+public:
+ PatternMultipleStream8() {
+ name = (char *)"MultipleStream8";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(230); effects.ShowFrame();
+
+ // draw grid of rainbow dots on top of the dimmed image
+ for (uint8_t y = 1; y < 32; y = y + 6) {
+ for (uint8_t x = 1; x < 32; x = x + 6) {
+
+ effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette((x * y) / 4);
+ }
+ }
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_z += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ // effects.MoveFractionalNoiseX(4);
+
+ effects.MoveY(3);
+ //effects.MoveFractionalNoiseY(4);
+
+ return 0;
+ }
+};
+
+class PatternPaletteSmear : public Drawable {
+public:
+ PatternPaletteSmear() {
+ name = (char *)"PaletteSmear";
+ }
+
+ unsigned int drawFrame() {
+
+ effects.DimAll(170); effects.ShowFrame();
+
+ // draw a rainbow color palette
+ for (uint8_t y = 0; y < MATRIX_HEIGHT; y++) {
+ for (uint8_t x = 0; x < MATRIX_WIDTH; x++) {
+ effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette(x * 8, y * 8 + 7);
+ }
+ }
+
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ //effects.MoveFractionalNoiseY(4);
+
+ effects.MoveY(3);
+ // effects.MoveFractionalNoiseX(4);
+ effects.ShowFrame();
+
+ return 0;
+ }
+};
+
+class PatternRainbowFlag : public Drawable {
+public:
+ PatternRainbowFlag() {
+ name = (char *)"RainbowFlag";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(10); effects.ShowFrame();
+
+ CRGB rainbow[7] = {
+ CRGB::Red,
+ CRGB::Orange,
+ CRGB::Yellow,
+ CRGB::Green,
+ CRGB::Blue,
+ CRGB::Violet
+ };
+
+ uint8_t y = 2;
+
+ for (uint8_t c = 0; c < 6; c++) {
+ for (uint8_t j = 0; j < 5; j++) {
+ for (uint8_t x = 0; x < VPANEL_W; x++) {
+ effects.leds[XY(x, y)] += rainbow[c];
+ }
+
+ y++;
+ if (y >= VPANEL_H)
+ break;
+ }
+ }
+
+ // Noise
+ noise_x += 1000;
+ noise_y += 1000;
+ noise_scale_x = 4000;
+ noise_scale_y = 4000;
+ effects.FillNoise();
+
+ effects.MoveX(3);
+ // effects.MoveFractionalNoiseY(4);
+
+ effects.MoveY(3);
+ // effects.MoveFractionalNoiseX(4);
+
+ return 0;
+ }
+};
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h b/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h
new file mode 100644
index 0000000..bc6618b
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h
@@ -0,0 +1,56 @@
+/*
+*
+* Inspired by and based on a loading animation for Prismata by Lunarch Studios:
+* http://www.reddit.com/r/gifs/comments/2on8si/connecting_to_server_so_mesmerizing/cmow0sz
+*
+* Lunarch Studios Inc. hereby publishes the Actionscript 3 source code pasted in this
+* comment under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
+* Lunarch Studios Inc. waives all rights to the work worldwide under copyright law,
+* including all related and neighboring rights, to the extent allowed by law.
+* You can copy, modify, distribute and perform the work, even for commercial purposes,
+* all without asking permission.
+*
+* Aurora: https://github.com/pixelmatix/aurora
+* Copyright (c) 2014 Jason Coon
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+* the Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternPendulumWave_H
+#define PatternPendulumWave_H
+
+class PatternPendulumWave : public Drawable {
+ public:
+ PatternPendulumWave() {
+ name = (char *)"Pendulum Wave";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(170); effects.ShowFrame();
+
+ for (int x = 0; x < VPANEL_W; x++)
+ {
+ uint8_t y = beatsin8(x + VPANEL_W, 0, VPANEL_H);
+ effects.drawBackgroundFastLEDPixelCRGB(x, y, effects.ColorFromCurrentPalette(x * 7));
+ }
+
+ return 15;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternPlasma.h b/examples/ChainedPanelsAuroraDemo/PatternPlasma.h
new file mode 100644
index 0000000..dcecc97
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternPlasma.h
@@ -0,0 +1,66 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from LedEffects Plasma by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Plasma.cpp?at=default
+ * Copyright (c) 2013 Robert Atkins
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternPlasma_H
+#define PatternPlasma_H
+
+class PatternPlasma : public Drawable {
+private:
+ int time = 0;
+ int cycles = 0;
+
+public:
+ PatternPlasma() {
+ name = (char *)"Plasma";
+ }
+
+ unsigned int drawFrame() {
+ for (int x = 0; x < VPANEL_W; x++) {
+ for (int y = 0; y < VPANEL_H; y++) {
+ int16_t v = 0;
+ uint8_t wibble = sin8(time);
+ v += sin16(x * wibble * 6 + time);
+ v += cos16(y * (128 - wibble) * 6 + time);
+ v += sin16(y * x * cos8(-time) / 8);
+
+ effects.Pixel(x, y, (v >> 8) + 127);
+ }
+ }
+
+ time += 1;
+ cycles++;
+
+ if (cycles >= 2048) {
+ time = 0;
+ cycles = 0;
+ }
+
+ effects.ShowFrame();
+
+ return 30;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternRadar.h b/examples/ChainedPanelsAuroraDemo/PatternRadar.h
new file mode 100644
index 0000000..602078b
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternRadar.h
@@ -0,0 +1,56 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternRadar_H
+
+class PatternRadar : public Drawable {
+ private:
+ byte theta = 0;
+ byte hueoffset = 0;
+
+ public:
+ PatternRadar() {
+ name = (char *)"Radar";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(254); effects.ShowFrame();
+
+ for (int offset = 0; offset < MATRIX_CENTER_X; offset++) {
+ byte hue = 255 - (offset * 16 + hueoffset);
+ CRGB color = effects.ColorFromCurrentPalette(hue);
+ uint8_t x = mapcos8(theta, offset, (VPANEL_W - 1) - offset);
+ uint8_t y = mapsin8(theta, offset, (VPANEL_H - 1) - offset);
+ uint16_t xy = XY(x, y);
+ effects.leds[xy] = color;
+
+ EVERY_N_MILLIS(25) {
+ theta += 2;
+ hueoffset += 1;
+ }
+ }
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h b/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h
new file mode 100644
index 0000000..272c604
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h
@@ -0,0 +1,79 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from FastLED Fire2012 example by Mark Kriegsman: https://github.com/FastLED/FastLED/blob/master/examples/Noise/Noise.ino
+ * Copyright (c) 2013 FastLED
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternSimplexNoise_H
+#define PatternSimplexNoise_H
+
+class PatternSimplexNoise : public Drawable {
+ public:
+ PatternSimplexNoise() {
+ name = (char *)"Noise";
+ }
+
+ void start() {
+ // Initialize our coordinates to some random values
+ noise_x = random16();
+ noise_y = random16();
+ noise_z = random16();
+ }
+
+ unsigned int drawFrame() {
+#if FASTLED_VERSION >= 3001000
+ // a new parameter set every 15 seconds
+ EVERY_N_SECONDS(15) {
+ noise_x = random16();
+ noise_y = random16();
+ noise_z = random16();
+ }
+#endif
+
+ uint32_t speed = 100;
+
+ effects.FillNoise();
+ ShowNoiseLayer(0, 1, 0);
+
+ // noise_x += speed;
+ noise_y += speed;
+ noise_z += speed;
+
+ effects.ShowFrame();
+
+ return 0;
+ }
+
+ // show just one layer
+ void ShowNoiseLayer(byte layer, byte colorrepeat, byte colorshift) {
+ for (uint8_t i = 0; i < VPANEL_W; i++) {
+ for (uint8_t j = 0; j < VPANEL_H; j++) {
+ uint8_t pixel = noise[i][j];
+
+ // assign a color depending on the actual palette
+ effects.leds[XY(i, j)] = effects.ColorFromCurrentPalette(colorrepeat * (pixel + colorshift), pixel);
+ }
+ }
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternSnake.h b/examples/ChainedPanelsAuroraDemo/PatternSnake.h
new file mode 100644
index 0000000..6201985
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternSnake.h
@@ -0,0 +1,145 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Portions of this code are adapted from LedEffects Snake by Robert Atkins: https://bitbucket.org/ratkins/ledeffects/src/26ed3c51912af6fac5f1304629c7b4ab7ac8ca4b/Snake.cpp?at=default
+ * Copyright (c) 2013 Robert Atkins
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternSnake_H
+#define PatternSnake_H
+
+class PatternSnake : public Drawable {
+private:
+ static const byte SNAKE_LENGTH = 16;
+
+ CRGB colors[SNAKE_LENGTH];
+ uint8_t initialHue;
+
+ enum Direction {
+ UP, DOWN, LEFT, RIGHT
+ };
+
+ struct Pixel {
+ uint8_t x;
+ uint8_t y;
+ };
+
+ struct Snake {
+ Pixel pixels[SNAKE_LENGTH];
+
+ Direction direction;
+
+ void newDirection() {
+ switch (direction) {
+ case UP:
+ case DOWN:
+ direction = random(0, 2) == 1 ? RIGHT : LEFT;
+ break;
+
+ case LEFT:
+ case RIGHT:
+ direction = random(0, 2) == 1 ? DOWN : UP;
+
+ default:
+ break;
+ }
+ }
+
+ void shuffleDown() {
+ for (byte i = SNAKE_LENGTH - 1; i > 0; i--) {
+ pixels[i] = pixels[i - 1];
+ }
+ }
+
+ void reset() {
+ direction = UP;
+ for (int i = 0; i < SNAKE_LENGTH; i++) {
+ pixels[i].x = 0;
+ pixels[i].y = 0;
+ }
+ }
+
+ void move() {
+ switch (direction) {
+ case UP:
+ pixels[0].y = (pixels[0].y + 1) % VPANEL_H;
+ break;
+ case LEFT:
+ pixels[0].x = (pixels[0].x + 1) % VPANEL_W;
+ break;
+ case DOWN:
+ pixels[0].y = pixels[0].y == 0 ? VPANEL_H - 1 : pixels[0].y - 1;
+ break;
+ case RIGHT:
+ pixels[0].x = pixels[0].x == 0 ? VPANEL_W - 1 : pixels[0].x - 1;
+ break;
+ }
+ }
+
+ void draw(CRGB colors[SNAKE_LENGTH]) {
+ for (byte i = 0; i < SNAKE_LENGTH; i++) {
+ effects.leds[XY(pixels[i].x, pixels[i].y)] = colors[i] %= (255 - i * (255 / SNAKE_LENGTH));
+ }
+ }
+ };
+
+ static const int snakeCount = 40;
+ Snake snakes[snakeCount];
+
+public:
+ PatternSnake() {
+ name = (char *)"Snake";
+ for (int i = 0; i < snakeCount; i++) {
+ Snake* snake = &snakes[i];
+ snake->reset();
+ }
+ }
+
+ void start()
+ {
+ effects.ClearFrame();
+ }
+
+ unsigned int drawFrame() {
+
+
+ fill_palette(colors, SNAKE_LENGTH, initialHue++, 5, effects.currentPalette, 255, LINEARBLEND);
+
+ for (int i = 0; i < snakeCount; i++) {
+ Snake* snake = &snakes[i];
+
+ snake->shuffleDown();
+
+ if (random(10) > 7) {
+ snake->newDirection();
+ }
+
+ snake->move();
+ snake->draw(colors);
+ }
+
+ effects.ShowFrame();
+
+ return 30;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternSpiral.h b/examples/ChainedPanelsAuroraDemo/PatternSpiral.h
new file mode 100644
index 0000000..23ce699
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternSpiral.h
@@ -0,0 +1,138 @@
+/*
+ * Portions of this code are adapted from "Funky Clouds" by Stefan Petrick:
+ * https://gist.github.com/anonymous/876f908333cd95315c35
+ *
+ * Copyright (c) 2014 Stefan Petrick
+ * http://www.stefan-petrick.de/wordpress_beta
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternSpiral_H
+#define PatternSpiral_H
+
+class PatternSpiral : public Drawable {
+private:
+ // Timer stuff (Oszillators)
+ struct timer {
+ unsigned long takt;
+ unsigned long lastMillis;
+ unsigned long count;
+ int delta;
+ byte up;
+ byte down;
+ };
+ timer multiTimer[5];
+
+ int timers = sizeof(multiTimer) / sizeof(multiTimer[0]);
+
+ // counts all variables with different speeds linear up and down
+ void UpdateTimers()
+ {
+ unsigned long now = millis();
+ for (int i = 0; i < timers; i++)
+ {
+ while (now - multiTimer[i].lastMillis >= multiTimer[i].takt)
+ {
+ multiTimer[i].lastMillis += multiTimer[i].takt;
+ multiTimer[i].count = multiTimer[i].count + multiTimer[i].delta;
+ if ((multiTimer[i].count == multiTimer[i].up) || (multiTimer[i].count == multiTimer[i].down))
+ {
+ multiTimer[i].delta = -multiTimer[i].delta;
+ }
+ }
+ }
+ }
+
+public:
+ PatternSpiral() {
+ name = (char *)"Spiral";
+ }
+
+ void start() {
+ // set all counting directions positive for the beginning
+ for (int i = 0; i < timers; i++) multiTimer[i].delta = 1;
+
+ // set range (up/down), speed (takt=ms between steps) and starting point of all oszillators
+
+ unsigned long now = millis();
+
+ multiTimer[0].lastMillis = now;
+ multiTimer[0].takt = 42; //x1
+ multiTimer[0].up = VPANEL_W - 1;
+ multiTimer[0].down = 0;
+ multiTimer[0].count = 0;
+
+ multiTimer[1].lastMillis = now;
+ multiTimer[1].takt = 55; //y1
+ multiTimer[1].up = VPANEL_H - 1;
+ multiTimer[1].down = 0;
+ multiTimer[1].count = 0;
+
+ multiTimer[2].lastMillis = now;
+ multiTimer[2].takt = 3; //color
+ multiTimer[2].up = 255;
+ multiTimer[2].down = 0;
+ multiTimer[2].count = 0;
+
+ multiTimer[3].lastMillis = now;
+ multiTimer[3].takt = 71; //x2
+ multiTimer[3].up = VPANEL_W - 1;
+ multiTimer[3].down = 0;
+ multiTimer[3].count = 0;
+
+ multiTimer[4].lastMillis = now;
+ multiTimer[4].takt = 89; //y2
+ multiTimer[4].up = VPANEL_H - 1;
+ multiTimer[4].down = 0;
+ multiTimer[4].count = 0;
+ }
+
+ unsigned int drawFrame() {
+ // manage the Oszillators
+ UpdateTimers();
+
+ // draw just a line defined by 5 oszillators
+ effects.BresenhamLine(
+ multiTimer[3].count, // x1
+ multiTimer[4].count, // y1
+ multiTimer[0].count, // x2
+ multiTimer[1].count, // y2
+ multiTimer[2].count); // color
+
+ // manipulate the screen buffer
+ // with fixed parameters (could be oszillators too)
+ // Params: center x, y, radius, scale color down
+ // --> NOTE: Affects always a SQUARE with an odd length
+ // effects.SpiralStream(15, 15, 10, 128);
+
+ effects.SpiralStream(31, 15, 64, 128); // for 64 pixel wide matrix!
+ // effects.SpiralStream(47, 15, 10, 128); // for 64 pixel wide matrix!
+
+ // why not several times?!
+ // effects.SpiralStream(16, 6, 6, 128);
+ // effects.SpiralStream(10, 24, 10, 128);
+
+ // increase the contrast
+ effects.DimAll(250); effects.ShowFrame();
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternSpiro.h b/examples/ChainedPanelsAuroraDemo/PatternSpiro.h
new file mode 100644
index 0000000..9c75952
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternSpiro.h
@@ -0,0 +1,107 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternSpiro_H
+
+class PatternSpiro : public Drawable {
+ private:
+ byte theta1 = 0;
+ byte theta2 = 0;
+ byte hueoffset = 0;
+
+ uint8_t radiusx = VPANEL_W / 4;
+ uint8_t radiusy = VPANEL_H / 4;
+ uint8_t minx = MATRIX_CENTER_X - radiusx;
+ uint8_t maxx = MATRIX_CENTER_X + radiusx + 1;
+ uint8_t miny = MATRIX_CENTER_Y - radiusy;
+ uint8_t maxy = MATRIX_CENTER_Y + radiusy + 1;
+
+ uint8_t spirocount = 1;
+ uint8_t spirooffset = 256 / spirocount;
+ boolean spiroincrement = false;
+
+ boolean handledChange = false;
+
+ public:
+ PatternSpiro() {
+ name = (char *)"Spiro";
+ }
+
+ unsigned int drawFrame() {
+ effects.DimAll(254); effects.ShowFrame();
+
+ boolean change = false;
+
+ for (int i = 0; i < spirocount; i++) {
+ uint8_t x = mapsin8(theta1 + i * spirooffset, minx, maxx);
+ uint8_t y = mapcos8(theta1 + i * spirooffset, miny, maxy);
+
+ uint8_t x2 = mapsin8(theta2 + i * spirooffset, x - radiusx, x + radiusx);
+ uint8_t y2 = mapcos8(theta2 + i * spirooffset, y - radiusy, y + radiusy);
+
+ CRGB color = effects.ColorFromCurrentPalette(hueoffset + i * spirooffset, 128);
+ effects.leds[XY(x2, y2)] += color;
+
+ if((x2 == MATRIX_CENTER_X && y2 == MATRIX_CENTER_Y) ||
+ (x2 == MATRIX_CENTRE_X && y2 == MATRIX_CENTRE_Y)) change = true;
+ }
+
+ theta2 += 1;
+
+ EVERY_N_MILLIS(25) {
+ theta1 += 1;
+ }
+
+ EVERY_N_MILLIS(100) {
+ if (change && !handledChange) {
+ handledChange = true;
+
+ if (spirocount >= VPANEL_W || spirocount == 1) spiroincrement = !spiroincrement;
+
+ if (spiroincrement) {
+ if(spirocount >= 4)
+ spirocount *= 2;
+ else
+ spirocount += 1;
+ }
+ else {
+ if(spirocount > 4)
+ spirocount /= 2;
+ else
+ spirocount -= 1;
+ }
+
+ spirooffset = 256 / spirocount;
+ }
+
+ if(!change) handledChange = false;
+ }
+
+ EVERY_N_MILLIS(33) {
+ hueoffset += 1;
+ }
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternSwirl.h b/examples/ChainedPanelsAuroraDemo/PatternSwirl.h
new file mode 100644
index 0000000..96793ca
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternSwirl.h
@@ -0,0 +1,77 @@
+/*
+* Aurora: https://github.com/pixelmatix/aurora
+* Copyright (c) 2014 Jason Coon
+*
+* Portions of this code are adapted from SmartMatrixSwirl by Mark Kriegsman: https://gist.github.com/kriegsman/5adca44e14ad025e6d3b
+* https://www.youtube.com/watch?v=bsGBT-50cts
+* Copyright (c) 2014 Mark Kriegsman
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy of
+* this software and associated documentation files (the "Software"), to deal in
+* the Software without restriction, including without limitation the rights to
+* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+* the Software, and to permit persons to whom the Software is furnished to do so,
+* subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in all
+* copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef PatternSwirl_H
+
+class PatternSwirl : public Drawable {
+ private:
+ const uint8_t borderWidth = 2;
+
+ public:
+ PatternSwirl() {
+ name = (char *)"Swirl";
+ }
+
+ void start() {
+ }
+
+ unsigned int drawFrame() {
+ // Apply some blurring to whatever's already on the matrix
+ // Note that we never actually clear the matrix, we just constantly
+ // blur it repeatedly. Since the blurring is 'lossy', there's
+ // an automatic trend toward black -- by design.
+ uint8_t blurAmount = beatsin8(2, 10, 255);
+
+#if FASTLED_VERSION >= 3001000
+ blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount);
+#else
+ effects.DimAll(blurAmount);
+#endif
+
+ // Use two out-of-sync sine waves
+ uint8_t i = beatsin8(27, borderWidth, VPANEL_H - borderWidth);
+ uint8_t j = beatsin8(41, borderWidth, VPANEL_W - borderWidth);
+ // Also calculate some reflections
+ uint8_t ni = (VPANEL_W - 1) - i;
+ uint8_t nj = (VPANEL_W - 1) - j;
+
+ // The color of each point shifts over time, each at a different speed.
+ uint16_t ms = millis();
+ effects.leds[XY(i, j)] += effects.ColorFromCurrentPalette(ms / 11);
+ effects.leds[XY(j, i)] += effects.ColorFromCurrentPalette(ms / 13);
+ effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17);
+ effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29);
+ effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37);
+ effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41);
+
+
+ effects.ShowFrame();
+ return 0;
+
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/PatternWave.h b/examples/ChainedPanelsAuroraDemo/PatternWave.h
new file mode 100644
index 0000000..90e7448
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/PatternWave.h
@@ -0,0 +1,120 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PatternWave_H
+#define PatternWave_H
+
+class PatternWave : public Drawable {
+private:
+ byte thetaUpdate = 0;
+ byte thetaUpdateFrequency = 0;
+ byte theta = 0;
+
+ byte hueUpdate = 0;
+ byte hueUpdateFrequency = 0;
+ byte hue = 0;
+
+ byte rotation = 0;
+
+ uint8_t scale = 256 / VPANEL_W;
+
+ uint8_t maxX = VPANEL_W - 1;
+ uint8_t maxY = VPANEL_H - 1;
+
+ uint8_t waveCount = 1;
+
+public:
+ PatternWave() {
+ name = (char *)"Wave";
+ }
+
+ void start() {
+ rotation = random(0, 4);
+ waveCount = random(1, 3);
+
+ }
+
+ unsigned int drawFrame() {
+ int n = 0;
+
+ switch (rotation) {
+ case 0:
+ for (int x = 0; x < VPANEL_W; x++) {
+ n = quadwave8(x * 2 + theta) / scale;
+ effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue));
+ if (waveCount == 2)
+ effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
+ }
+ break;
+
+ case 1:
+ for (int y = 0; y < VPANEL_H; y++) {
+ n = quadwave8(y * 2 + theta) / scale;
+ effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue));
+ if (waveCount == 2)
+ effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
+ }
+ break;
+
+ case 2:
+ for (int x = 0; x < VPANEL_W; x++) {
+ n = quadwave8(x * 2 - theta) / scale;
+ effects.drawBackgroundFastLEDPixelCRGB(x, n, effects.ColorFromCurrentPalette(x + hue));
+ if (waveCount == 2)
+ effects.drawBackgroundFastLEDPixelCRGB(x, maxY - n, effects.ColorFromCurrentPalette(x + hue));
+ }
+ break;
+
+ case 3:
+ for (int y = 0; y < VPANEL_H; y++) {
+ n = quadwave8(y * 2 - theta) / scale;
+ effects.drawBackgroundFastLEDPixelCRGB(n, y, effects.ColorFromCurrentPalette(y + hue));
+ if (waveCount == 2)
+ effects.drawBackgroundFastLEDPixelCRGB(maxX - n, y, effects.ColorFromCurrentPalette(y + hue));
+ }
+ break;
+ }
+
+ effects.DimAll(254);
+ effects.ShowFrame();
+
+ if (thetaUpdate >= thetaUpdateFrequency) {
+ thetaUpdate = 0;
+ theta++;
+ }
+ else {
+ thetaUpdate++;
+ }
+
+ if (hueUpdate >= hueUpdateFrequency) {
+ hueUpdate = 0;
+ hue++;
+ }
+ else {
+ hueUpdate++;
+ }
+
+ return 0;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/Patterns.h b/examples/ChainedPanelsAuroraDemo/Patterns.h
new file mode 100644
index 0000000..8242fb1
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Patterns.h
@@ -0,0 +1,259 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Patterns_H
+#define Patterns_H
+
+#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
+
+#include "Vector.h"
+#include "Boid.h"
+#include "Attractor.h"
+
+/*
+ * Note from mrfaptastic:
+ *
+ * Commented out patterns are due to the fact they either didn't work properly with a non-square display,
+ * or from my personal opinion, are crap.
+ *
+ * Kosso: I have removed the crappy ones and added a less crappy (and working!) Fire demo ;)
+ *
+ */
+#include "PaletteFireKoz.h" // Added by Kosso
+#include "PatternFireKoz.h" // Added by Kosso
+#include "PatternSpiro.h"
+#include "PatternRadar.h"
+#include "PatternSwirl.h"
+#include "PatternPendulumWave.h"
+#include "PatternFlowField.h"
+#include "PatternIncrementalDrift.h"
+#include "PatternMunch.h"
+#include "PatternElectricMandala.h"
+#include "PatternSimplexNoise.h"
+#include "PatternWave.h"
+#include "PatternAttract.h"
+#include "PatternFlock.h"
+#include "PatternInfinity.h"
+#include "PatternPlasma.h"
+#include "PatternSnake.h"
+#include "PatternFire.h" // Not very good.
+#include "PatternLife.h"
+#include "PatternMaze.h"
+#include "PatternSpiral.h"
+
+
+class Patterns : public Playlist {
+ private:
+ PatternFireKoz fireKoz;
+ PatternSpiro spiro;
+ PatternSwirl swirl;
+ PatternPendulumWave pendulumWave;
+ PatternFlowField flowField;
+ PatternIncrementalDrift incrementalDrift;
+ PatternMunch munch;
+ PatternElectricMandala electricMandala;
+ PatternSimplexNoise simplexNoise;
+ PatternWave wave;
+ PatternAttract attract;
+ PatternFlock flock;
+ PatternPlasma plasma;
+ PatternSnake snake;
+ PatternFire fire;
+ PatternLife life;
+ PatternMaze maze;
+ PatternSpiral spiral;
+
+ int currentIndex = 0;
+ Drawable* currentItem;
+
+ int getCurrentIndex() {
+ return currentIndex;
+ }
+
+ const static int PATTERN_COUNT = 18;
+
+ Drawable* shuffledItems[PATTERN_COUNT];
+
+ Drawable* items[PATTERN_COUNT] = {
+ &fireKoz, // added by Kosso
+ &spiro,
+ &life,
+ &flowField,
+ &pendulumWave,
+ &incrementalDrift,
+ &munch,
+ &electricMandala,
+ &simplexNoise,
+ &wave,
+ &attract,
+ &swirl,
+ &flock,
+ &plasma,
+ &snake,
+ &fire,
+ &maze,
+ &spiral,
+ };
+
+ public:
+ Patterns() {
+ // add the items to the shuffledItems array
+ for (int a = 0; a < PATTERN_COUNT; a++) {
+ shuffledItems[a] = items[a];
+ }
+
+ shuffleItems();
+
+ this->currentItem = items[0];
+ this->currentItem->start();
+ }
+
+ char* Drawable::name = (char *)"Patterns";
+
+ void stop() {
+ if (currentItem)
+ currentItem->stop();
+ }
+
+ void start() {
+ if (currentItem)
+ currentItem->start();
+ }
+
+ void move(int step) {
+ currentIndex += step;
+
+ if (currentIndex >= PATTERN_COUNT) currentIndex = 0;
+ else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1;
+
+ if (effects.paletteIndex == effects.RandomPaletteIndex)
+ effects.RandomPalette();
+
+ moveTo(currentIndex);
+
+ //if (!isTimeAvailable && currentItem == &analogClock)
+ // move(step);
+ }
+
+ void moveRandom(int step) {
+ currentIndex += step;
+
+ if (currentIndex >= PATTERN_COUNT) currentIndex = 0;
+ else if (currentIndex < 0) currentIndex = PATTERN_COUNT - 1;
+
+ if (effects.paletteIndex == effects.RandomPaletteIndex)
+ effects.RandomPalette();
+
+ if (currentItem)
+ currentItem->stop();
+
+ currentItem = shuffledItems[currentIndex];
+
+ if (currentItem)
+ currentItem->start();
+
+ // if (!isTimeAvailable && currentItem == &analogClock)
+ // moveRandom(step);
+ }
+
+ void shuffleItems() {
+ for (int a = 0; a < PATTERN_COUNT; a++)
+ {
+ int r = random(a, PATTERN_COUNT);
+ Drawable* temp = shuffledItems[a];
+ shuffledItems[a] = shuffledItems[r];
+ shuffledItems[r] = temp;
+ }
+ }
+
+
+ unsigned int drawFrame() {
+ return currentItem->drawFrame();
+ }
+
+ void listPatterns() {
+ Serial.println(F("{"));
+ Serial.print(F(" \"count\": "));
+ Serial.print(PATTERN_COUNT);
+ Serial.println(",");
+ Serial.println(F(" \"results\": ["));
+
+ for (int i = 0; i < PATTERN_COUNT; i++) {
+ Serial.print(F(" \""));
+ Serial.print(i, DEC);
+ Serial.print(F(": "));
+ Serial.print(items[i]->name);
+ if (i == PATTERN_COUNT - 1)
+ Serial.println(F("\""));
+ else
+ Serial.println(F("\","));
+ }
+
+ Serial.println(" ]");
+ Serial.println("}");
+ }
+
+ int getPatternIndex()
+ {
+ return currentIndex;
+ }
+
+ char * getCurrentPatternName()
+ {
+ return currentItem->name;
+ }
+
+ void moveTo(int index) {
+ if (currentItem)
+ currentItem->stop();
+
+ currentIndex = index;
+
+ currentItem = items[currentIndex];
+
+ if (currentItem)
+ currentItem->start();
+ }
+
+ bool setPattern(String name) {
+ for (int i = 0; i < PATTERN_COUNT; i++) {
+ if (name.compareTo(items[i]->name) == 0) {
+ moveTo(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ bool setPattern(int index) {
+ if (index >= PATTERN_COUNT || index < 0)
+ return false;
+
+ moveTo(index);
+
+ return true;
+ }
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/Playlist.h b/examples/ChainedPanelsAuroraDemo/Playlist.h
new file mode 100644
index 0000000..29c0c87
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Playlist.h
@@ -0,0 +1,39 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Playlist_H
+#define Playlist_H
+
+class Playlist : public Drawable {
+public:
+ virtual bool isPlaylist() {
+ return true;
+ }
+
+ boolean isCurrentItemFinished = true;
+
+ virtual void move(int step) = 0;
+ virtual void moveRandom(int step) = 0;
+ virtual int getCurrentIndex();
+};
+
+#endif
diff --git a/examples/ChainedPanelsAuroraDemo/Vector.h b/examples/ChainedPanelsAuroraDemo/Vector.h
new file mode 100644
index 0000000..8acbadc
--- /dev/null
+++ b/examples/ChainedPanelsAuroraDemo/Vector.h
@@ -0,0 +1,169 @@
+/*
+ * Aurora: https://github.com/pixelmatix/aurora
+ * Copyright (c) 2014 Jason Coon
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef Vector_H
+#define Vector_H
+
+template <class T>
+class Vector2 {
+public:
+ T x, y;
+
+ Vector2() :x(0), y(0) {}
+ Vector2(T x, T y) : x(x), y(y) {}
+ Vector2(const Vector2& v) : x(v.x), y(v.y) {}
+
+ Vector2& operator=(const Vector2& v) {
+ x = v.x;
+ y = v.y;
+ return *this;
+ }
+
+ bool isEmpty() {
+ return x == 0 && y == 0;
+ }
+
+ bool operator==(Vector2& v) {
+ return x == v.x && y == v.y;
+ }
+
+ bool operator!=(Vector2& v) {
+ return !(x == y);
+ }
+
+ Vector2 operator+(Vector2& v) {
+ return Vector2(x + v.x, y + v.y);
+ }
+ Vector2 operator-(Vector2& v) {
+ return Vector2(x - v.x, y - v.y);
+ }
+
+ Vector2& operator+=(Vector2& v) {
+ x += v.x;
+ y += v.y;
+ return *this;
+ }
+ Vector2& operator-=(Vector2& v) {
+ x -= v.x;
+ y -= v.y;
+ return *this;
+ }
+
+ Vector2 operator+(double s) {
+ return Vector2(x + s, y + s);
+ }
+ Vector2 operator-(double s) {
+ return Vector2(x - s, y - s);
+ }
+ Vector2 operator*(double s) {
+ return Vector2(x * s, y * s);
+ }
+ Vector2 operator/(double s) {
+ return Vector2(x / s, y / s);
+ }
+
+ Vector2& operator+=(double s) {
+ x += s;
+ y += s;
+ return *this;
+ }
+ Vector2& operator-=(double s) {
+ x -= s;
+ y -= s;
+ return *this;
+ }
+ Vector2& operator*=(double s) {
+ x *= s;
+ y *= s;
+ return *this;
+ }
+ Vector2& operator/=(double s) {
+ x /= s;
+ y /= s;
+ return *this;
+ }
+
+ void set(T x, T y) {
+ this->x = x;
+ this->y = y;
+ }
+
+ void rotate(double deg) {
+ double theta = deg / 180.0 * M_PI;
+ double c = cos(theta);
+ double s = sin(theta);
+ double tx = x * c - y * s;
+ double ty = x * s + y * c;
+ x = tx;
+ y = ty;
+ }
+
+ Vector2& normalize() {
+ if (length() == 0) return *this;
+ *this *= (1.0 / length());
+ return *this;
+ }
+
+ float dist(Vector2 v) const {
+ Vector2 d(v.x - x, v.y - y);
+ return d.length();
+ }
+ float length() const {
+ return sqrt(x * x + y * y);
+ }
+
+ float mag() const {
+ return length();
+ }
+
+ float magSq() {
+ return (x * x + y * y);
+ }
+
+ void truncate(double length) {
+ double angle = atan2f(y, x);
+ x = length * cos(angle);
+ y = length * sin(angle);
+ }
+
+ Vector2 ortho() const {
+ return Vector2(y, -x);
+ }
+
+ static float dot(Vector2 v1, Vector2 v2) {
+ return v1.x * v2.x + v1.y * v2.y;
+ }
+ static float cross(Vector2 v1, Vector2 v2) {
+ return (v1.x * v2.y) - (v1.y * v2.x);
+ }
+
+ void limit(float max) {
+ if (magSq() > max*max) {
+ normalize();
+ *this *= max;
+ }
+ }
+};
+
+typedef Vector2<float> PVector;
+
+#endif