From 445c0424f4f276237d48b3596817b378c7c7a675 Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Sat, 19 Dec 2020 20:07:03 +0300 Subject: [PATCH 1/3] spelling mistakes/readme corrections --- FM6126A.md | 33 ++++++++---------------------- README.md | 9 ++++++-- examples/AuroraDemo/AuroraDemo.ino | 2 -- 3 files changed, 15 insertions(+), 29 deletions(-) diff --git a/FM6126A.md b/FM6126A.md index ac4d395..bfab4a5 100644 --- a/FM6126A.md +++ b/FM6126A.md @@ -1,44 +1,27 @@ ## The mystery of control registers for FM6126A chips +The only available Datasheet for this chips is in Chinese and does not shed a light on what those two control regs are. -Datasheet for this chis chip is in chineese and does not shed a light on what those two control regs are. - -An excellent insight could be found here - -https://github.com/hzeller/rpi-rgb-led-matrix/issues/746#issuecomment-453860510 +An excellent insight could be found here https://github.com/hzeller/rpi-rgb-led-matrix/issues/746#issuecomment-453860510 - - -So there are two regs - **REG1** and **REG1**, +So there are two regs in this chip - **REG1** and **REG2**, one could be written with 12 clock pusles (and usually called reg12, dunno why :)) - -the other one could be written with 13 clock pusles (and usually called reg13, dunno why :)) - +the other one could be written with 13 clock pulses (and usually called reg13, dunno why :)) -So I've done some measurmens on power consumption while toggling bits of **REG1** and it looks that it could provide a fine grained brighness control over matrix. - +I've done some measurmens on power consumption while toggling bits of **REG1** and it looks that it could provide a fine grained brighness control over the entire matrix with no need for bitbanging over RGB or EO pins. There are 6 bits (6 to 11) giving an increased brighness (compared to all-zeroes) and 4 bits (2-5) giving decreased brighness!!! +Still unclear if FM6112A brightness control is internally PWMed or current limited, might require some poking with oscilloscope. - - -So it seems that the most bright (and hungry for power) value is - -bool REG1[16] = {0,0,0,0,0, 1,1,1,1,1,1, 0,0,0,0,0}; and not {0,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1} as it is usually used. - +So it seems that the most bright (and hungry for power) value is bool REG1[16] = {0,0,0,0,0, 1,1,1,1,1,1, 0,0,0,0,0}; and not {0,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1} as it is usually used. I'm not sure about bit 1 - it is either not used or I was unable to measure it's influence to brightness/power. - - -Giving at least 10 bits of hardware brightness control opens pretty nice options for offloading. Should dig into this more deeper. - - +Giving at least 10 bits of hardware brightness control opens pretty nice options for offloading and simplifiyng matrix output. Should dig into this more deeper. Here are some of the measurments I've took for 2 64x64 panels filled with white color - reg value and corresponding current drain in amps. - |REG1 |bit value|Current, amps | diff --git a/README.md b/README.md index 77db967..d9b7f3d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ By default the pin mapping is as follows (defaults defined in ESP32-HUB75-Matrix | R1 G1 | R1 -> IO25 G1 -> IO26 | B1 GND | B1 -> IO27 | R2 G2 | R2 -> IO14 G2 -> IO12 -| B2 GND | B2 -> IO13 +| B2 E | B2 -> IO13 E -> N/A (required for 1/32 scan panels, like 64x64. Any available pin would do, i.e. IO32 ) | A B | A -> IO23 B -> IO19 | C D | C -> IO 5 D -> IO17 | CLK LAT | CLK -> IO16 LAT -> IO 4 @@ -52,7 +52,7 @@ However, if you want to change this, simply provide the wanted pin mapping as pa #define B_PIN 22 #define C_PIN 5 #define D_PIN 17 -#define E_PIN -1 +#define E_PIN -1 // required for 1/32 scan panels, like 64x64. Any available pin would do, i.e. IO32 #define LAT_PIN 4 #define OE_PIN 15 @@ -113,6 +113,8 @@ By default you should not need to change / set the brightness setting as the def The value to pass 'setPanelBrightness' must be a value less than MATRIX_WIDTH. For example for a single 64x32 LED Matrix Module, a value less than 64. However, if you set the brightness too high, you may experience ghosting. +Also you may use method `setPanelBrightness8(x)`, where x is a uint8_t value between 0-255. Library will recalculate required brightness level depending on matrix width (mostly useful with FastLED-based sketches). + Example: ``` @@ -122,6 +124,9 @@ void setup() { matrix.setPanelBrightness(16); // Set the brightness. 32 or lower ideal for a single 64x32 LED Matrix Panel. matrix.clearScreen(); // You must clear the screen after changing brightness level for it to take effect. + // or another way + matrix.setPanelBrightness(192); // Set the brightness to about 3/4 (192/256) of maximum. + matrix.clearScreen(); // You must clear the screen after changing brightness level for it to take effect. } ``` diff --git a/examples/AuroraDemo/AuroraDemo.ino b/examples/AuroraDemo/AuroraDemo.ino index 002a1ed..bd07bc3 100644 --- a/examples/AuroraDemo/AuroraDemo.ino +++ b/examples/AuroraDemo/AuroraDemo.ino @@ -71,7 +71,6 @@ void setup() listPatterns(); - //patterns.setPattern(0); // // simple noise patterns.moveRandom(1); // start from a random pattern Serial.print("Starting with pattern: "); @@ -91,7 +90,6 @@ void loop() patterns.moveRandom(1); //patterns.move(1); patterns.start(); - Serial.print("Changing pattern to: "); Serial.println(patterns.getCurrentPatternName()); From 33b95f534f043e78f8866fe8c020dc06fba6f38f Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Sat, 19 Dec 2020 20:28:47 +0300 Subject: [PATCH 2/3] ported changes from non-chained version of example. Tested with 128x128 pane (four 64x64 panels) Signed-off-by: Emil Muratov --- examples/ChainedPanelsAuroraDemo/Attractor.h | 2 +- .../ChainedPanelsAuroraDemo.ino | 9 +- examples/ChainedPanelsAuroraDemo/Drawable.h | 5 + examples/ChainedPanelsAuroraDemo/Effects.h | 1589 ++++++++--------- examples/ChainedPanelsAuroraDemo/Geometry.h | 2 +- .../ChainedPanelsAuroraDemo/PatternAttract.h | 5 +- .../ChainedPanelsAuroraDemo/PatternBounce.h | 73 + .../ChainedPanelsAuroraDemo/PatternCube.h | 219 +++ .../PatternElectricMandala.h | 10 +- .../ChainedPanelsAuroraDemo/PatternFire.h | 61 +- .../PatternIncrementalDrift.h | 2 +- .../PatternIncrementalDrift2.h | 64 + .../ChainedPanelsAuroraDemo/PatternInfinity.h | 7 +- .../ChainedPanelsAuroraDemo/PatternInvaders.h | 154 ++ .../ChainedPanelsAuroraDemo/PatternMaze.h | 4 +- .../ChainedPanelsAuroraDemo/PatternMunch.h | 7 +- .../PatternNoiseSmearing.h | 34 +- .../PatternPendulumWave.h | 20 +- .../ChainedPanelsAuroraDemo/PatternPulse.h | 82 + .../PatternSimplexNoise.h | 8 +- .../ChainedPanelsAuroraDemo/PatternSnake.h | 2 +- .../ChainedPanelsAuroraDemo/PatternSpark.h | 113 ++ .../ChainedPanelsAuroraDemo/PatternSpin.h | 100 ++ .../ChainedPanelsAuroraDemo/PatternSpiro.h | 9 +- .../ChainedPanelsAuroraDemo/PatternSwirl.h | 14 +- .../ChainedPanelsAuroraDemo/PatternTest.h | 20 + examples/ChainedPanelsAuroraDemo/Patterns.h | 102 +- 27 files changed, 1772 insertions(+), 945 deletions(-) create mode 100644 examples/ChainedPanelsAuroraDemo/PatternBounce.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternCube.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift2.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternInvaders.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternPulse.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternSpark.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternSpin.h create mode 100644 examples/ChainedPanelsAuroraDemo/PatternTest.h diff --git a/examples/ChainedPanelsAuroraDemo/Attractor.h b/examples/ChainedPanelsAuroraDemo/Attractor.h index 5a03511..8f5ba2f 100644 --- a/examples/ChainedPanelsAuroraDemo/Attractor.h +++ b/examples/ChainedPanelsAuroraDemo/Attractor.h @@ -34,7 +34,7 @@ public: Attractor() { location = PVector(MATRIX_CENTRE_X, MATRIX_CENTRE_Y); - mass = 8; + mass = 10; G = .5; } diff --git a/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino b/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino index ac63d1f..ac23bdf 100644 --- a/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino +++ b/examples/ChainedPanelsAuroraDemo/ChainedPanelsAuroraDemo.ino @@ -124,15 +124,16 @@ void setup() void patternAdvance(){ // Go to next pattern in the list (se Patterns.h) - patterns.stop(); - patterns.move(1); + patterns.stop(); + patterns.moveRandom(1); + //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(); + //Serial.println(patterns.getPatternIndex()); + //lastPattern = patterns.getPatternIndex(); // Save last index. preferences.begin("RGBMATRIX", false); preferences.putInt("lastPattern", lastPattern); diff --git a/examples/ChainedPanelsAuroraDemo/Drawable.h b/examples/ChainedPanelsAuroraDemo/Drawable.h index 6e97098..40356f4 100644 --- a/examples/ChainedPanelsAuroraDemo/Drawable.h +++ b/examples/ChainedPanelsAuroraDemo/Drawable.h @@ -43,6 +43,11 @@ public: return 0; }; + virtual void printTesting() + { + Serial.println("Testing..."); + } + virtual void start() {}; virtual void stop() {}; }; diff --git a/examples/ChainedPanelsAuroraDemo/Effects.h b/examples/ChainedPanelsAuroraDemo/Effects.h index 8ca709e..fa0ca45 100644 --- a/examples/ChainedPanelsAuroraDemo/Effects.h +++ b/examples/ChainedPanelsAuroraDemo/Effects.h @@ -1,62 +1,75 @@ /* - 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. -*/ + * 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; +// US vs GB, huh? :) +//const byte MATRIX_CENTRE_X = MATRIX_CENTER_X - 1; +//const byte MATRIX_CENTRE_Y = MATRIX_CENTER_Y - 1; +#define MATRIX_CENTRE_X MATRIX_CENTER_X +#define MATRIX_CENTRE_Y MATRIX_CENTER_Y + 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) +// forward declaration +uint16_t XY16( uint16_t x, uint16_t y); + +/* 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: VPANEL_W-1 etc. + * Ugh... uint8_t - really??? this weak method can't cope with 256+ pixel matrixes :( + */ +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() - + return XY16(x, y); } -/// Some mathematics provided by FastLED +/** + * The one for 256+ matrixes + * otherwise this: + * for (uint8_t i = 0; i < VPANEL_W; i++) {} + * turns into an infinite loop + */ +uint16_t XY16( uint16_t x, uint16_t y) +{ + if( x >= VPANEL_W) return 0; + if( y >= VPANEL_H) return 0; + + return (y * VPANEL_W) + x + 1; // everything offset by one to capute out of bounds stuff - never displayed by ShowFrame() +} + + 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); @@ -84,7 +97,7 @@ uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) { } // Array of temperature readings at each simulation cell -byte heat[NUM_LEDS]; +//byte heat[NUM_LEDS]; // none of the currently enabled effects uses this uint32_t noise_x; uint32_t noise_y; @@ -92,823 +105,751 @@ uint32_t noise_z; uint32_t noise_scale_x; uint32_t noise_scale_y; -uint8_t noise[VPANEL_W][VPANEL_H]; +//uint8_t noise[VPANEL_W][VPANEL_H]; +uint8_t **noise = nullptr; // we will allocate mem later 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). +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). + Effects(){ + // we do dynamic allocation for leds buffer, otherwise esp32 toolchain can't link static arrays of such a big size for 256+ matrixes + leds = (CRGB *)malloc(NUM_LEDS * sizeof(CRGB)); - /* 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); + // allocate mem for noise effect + // (there should be some guards for malloc errors eventually) + noise = (uint8_t **)malloc(VPANEL_W * sizeof(uint8_t *)); + for (int i = 0; i < VPANEL_W; ++i) { + noise[i] = (uint8_t *)malloc(VPANEL_H * sizeof(uint8_t)); } - // 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? + ClearFrame(); + matrix.clearScreen(); + } + ~Effects(){ + free(leds); + for (int i = 0; i < VPANEL_W; ++i) { + free(noise[i]); } + free(noise); + } - 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 - } - - + /* 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; + //matrix.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) { + leds[XY(x, y)] = ColorFromCurrentPalette(colorIndex); + //matrix.drawPixelRGB888(x, y, temp.r, temp.g, temp.b); // now draw it? + } - void CircleStream(uint8_t value) { - DimAll(value); ShowFrame(); + void PrepareFrame() { + // leds = (CRGB*) backgroundLayer.backBuffer(); + } - for (uint8_t offset = 0; offset < MATRIX_CENTER_X; offset++) { - boolean hasprev = false; - uint16_t prevxy = 0; + void ShowFrame() { + //#if (FASTLED_VERSION >= 3001000) + // nblendPaletteTowardPalette(currentPalette, targetPalette, 24); + //#else + currentPalette = targetPalette; + //#endif - 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); + // backgroundLayer.swapBuffers(); + // leds = (CRGB*) backgroundLayer.backBuffer(); + // LEDS.countFPS(); - uint16_t xy = XY(x, y); + for (int y=0; y= 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) + // scale the brightness of the screenbuffer down + void DimAll(byte value) + { + for (int i = 0; i < NUM_LEDS; i++) { - 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); + leds[i].nscale8(value); } + } - // 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); + void ClearFrame() + { + memset(leds, 0x00, NUM_LEDS * sizeof(CRGB)); // 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]; } - } - 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)]; - } + prevxy = xy; + hasprev = true; } } - // 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)]; - } + 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); } } + } +*/ - // 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)]; - } - } - } + // palettes + static const int paletteCount = 10; + int paletteIndex = -1; + TBlendType currentBlendType = LINEARBLEND; + CRGBPalette16 currentPalette; + CRGBPalette16 targetPalette; + char* currentPaletteName; - // 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)]; - } - } - } + static const int HeatColorsPaletteIndex = 6; + static const int RandomPaletteIndex = 9; - // 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)]; - } - } - } + void Setup() { + currentPalette = RainbowColors_p; + loadPalette(0); + NoiseVariablesSetup(); + } - // 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 CyclePalette(int offset = 1) { + loadPalette(paletteIndex + offset); + } - void BresenhamLine(int x0, int y0, int x1, int y1, byte colorIndex) - { - BresenhamLine(x0, y0, x1, y1, ColorFromCurrentPalette(colorIndex)); - } + void RandomPalette() { + loadPalette(RandomPaletteIndex); + } - 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; - } - } - } + void loadPalette(int index) { + paletteIndex = index; - // 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? - } - */ + if (paletteIndex >= paletteCount) + paletteIndex = 0; + else if (paletteIndex < 0) + paletteIndex = paletteCount - 1; - 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; + switch (paletteIndex) { + case 0: + targetPalette = RainbowColors_p; + currentPaletteName = (char *)"Rainbow"; + break; + //case 1: + // targetPalette = RainbowStripeColors_p; + // currentPaletteName = (char *)"RainbowStripe"; + // 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 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); - } - + void setPalette(String paletteName) { + if (paletteName == "Rainbow") + loadPalette(0); + //else if (paletteName == "RainbowStripe") + // loadPalette(1); + 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 VPANEL_W - 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-VPANEL_W (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[XY16(VPANEL_W - 1 - x, y)] = leds[XY16(x, y)]; + leds[XY16(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY16(x, y)]; + leds[XY16(x, VPANEL_H - 1 - y)] = leds[XY16(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[XY16(VPANEL_W - 1 - x, y)] = leds[XY16(y, x)]; + leds[XY16(x, VPANEL_H - 1 - y)] = leds[XY16(y, x)]; + leds[XY16(VPANEL_W - 1 - x, VPANEL_H - 1 - y)] = leds[XY16(x, y)]; + } + } + } + + // copy one diagonal triangle into the other one within a 16x16 + void Caleidoscope3() { + for (int x = 0; x <= MATRIX_CENTRE_X && x < VPANEL_H; x++) { + for (int y = 0; y <= x && y= 0; y--) { + leds[XY16(x, y)] = leds[XY16(y, x)]; + } + } + } + + void Caleidoscope6() { + for (int x = 1; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 7)] = leds[XY16(x, 0)]; + } //a + for (int x = 2; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 6)] = leds[XY16(x, 1)]; + } //b + for (int x = 3; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 5)] = leds[XY16(x, 2)]; + } //c + for (int x = 4; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 4)] = leds[XY16(x, 3)]; + } //d + for (int x = 5; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 3)] = leds[XY16(x, 4)]; + } //e + for (int x = 6; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 2)] = leds[XY16(x, 5)]; + } //f + for (int x = 7; x < MATRIX_CENTER_X; x++) { + leds[XY16(7 - x, 1)] = leds[XY16(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[XY16(i, y - d)] += leds[XY16(i + 1, y - d)]; // lowest row to the right + leds[XY16(i, y - d)].nscale8(dimm); + } + for (int i = y - d; i <= y + d; i++) { + leds[XY16(x + d, i)] += leds[XY16(x + d, i + 1)]; // right colum up + leds[XY16(x + d, i)].nscale8(dimm); + } + for (int i = x + d; i >= x - d; i--) { + leds[XY16(i, y + d)] += leds[XY16(i - 1, y + d)]; // upper row to the left + leds[XY16(i, y + d)].nscale8(dimm); + } + for (int i = y + d; i >= y - d; i--) { + leds[XY16(x - d, i)] += leds[XY16(x - d, i - 1)]; // left colum down + leds[XY16(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[XY16(a + centerX, b + centerY)] = leds[XY16(nextA + centerX, nextB + centerY)]; + leds[XY16(b + centerX, a + centerY)] = leds[XY16(nextB + centerX, nextA + centerY)]; + leds[XY16(-a + centerX, b + centerY)] = leds[XY16(-nextA + centerX, nextB + centerY)]; + leds[XY16(-b + centerX, a + centerY)] = leds[XY16(-nextB + centerX, nextA + centerY)]; + leds[XY16(-a + centerX, -b + centerY)] = leds[XY16(-nextA + centerX, -nextB + centerY)]; + leds[XY16(-b + centerX, -a + centerY)] = leds[XY16(-nextB + centerX, -nextA + centerY)]; + leds[XY16(a + centerX, -b + centerY)] = leds[XY16(nextA + centerX, -nextB + centerY)]; + leds[XY16(b + centerX, -a + centerY)] = leds[XY16(nextB + centerX, -nextA + centerY)]; + + // dim them + leds[XY16(a + centerX, b + centerY)].nscale8(dimm); + leds[XY16(b + centerX, a + centerY)].nscale8(dimm); + leds[XY16(-a + centerX, b + centerY)].nscale8(dimm); + leds[XY16(-b + centerX, a + centerY)].nscale8(dimm); + leds[XY16(-a + centerX, -b + centerY)].nscale8(dimm); + leds[XY16(-b + centerX, -a + centerY)].nscale8(dimm); + leds[XY16(a + centerX, -b + centerY)].nscale8(dimm); + leds[XY16(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[XY16(x, y)] += leds[XY16(x - 1, y)]; + leds[XY16(x, y)].nscale8(scale); + } + } + for (int y = fromY; y < toY; y++) + leds[XY16(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[XY16(x, y)] += leds[XY16(x + 1, y)]; + leds[XY16(x, y)].nscale8(scale); + } + } + for (int y = fromY; y < toY; y++) + leds[XY16(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[XY16(x, y)] += leds[XY16(x, y - 1)]; + leds[XY16(x, y)].nscale8(scale); + } + } + for (int x = 0; x < VPANEL_W; x++) + leds[XY16(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[XY16(x, y)] += leds[XY16(x, y + 1)]; + leds[XY16(x, y)].nscale8(scale); + } + } + for (int x = 0; x < VPANEL_W; x++) + leds[XY16(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[XY16(x, y)] += leds[XY16(x + 1, y + 1)]; + leds[XY16(x, y)].nscale8(scale); + } + } + for (int x = 0; x < VPANEL_W; x++) + leds[XY16(x, VPANEL_H - 1)].nscale8(scale); + for (int y = 0; y < VPANEL_H; y++) + leds[XY16(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[XY16(x + 1, y)] += leds[XY16(x, y + 1)]; + leds[XY16(x, y)].nscale8(scale); + } + } + // fade the bottom row + for (int x = 0; x < VPANEL_W; x++) + leds[XY16(x, VPANEL_H - 1)].nscale8(scale); + + // fade the right column + for (int y = 0; y < VPANEL_H; y++) + leds[XY16(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[XY16(x, y)] = leds[XY16(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[XY16(x, y)] = leds[XY16(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[XY16(x + x2 - x0, y + y2 - y0)] = leds[XY16(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[XY16(x, 7 - y)] = leds[XY16(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[XY16(7 - y, x)] = leds[XY16(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[XY16(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 (uint16_t i = 0; i < VPANEL_W; i++) { + uint32_t ioffset = noise_scale_x * (i - MATRIX_CENTRE_Y); + + for (uint16_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[XY16(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_W; x++) + { + leds[XY16(x, y)] = leds [XY16(x+1, y)]; + } + + leds[XY16(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_W, 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[XY16(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[XY16(x, y)] = leds [XY16(x, y+1)]; + } + + leds[XY16(x, VPANEL_H-1)] = tmp; + } + } // end column loop + } /// MoveY + + }; #endif diff --git a/examples/ChainedPanelsAuroraDemo/Geometry.h b/examples/ChainedPanelsAuroraDemo/Geometry.h index 8efb768..4e47557 100644 --- a/examples/ChainedPanelsAuroraDemo/Geometry.h +++ b/examples/ChainedPanelsAuroraDemo/Geometry.h @@ -147,4 +147,4 @@ struct triFace } }; -#endif +#endif \ No newline at end of file diff --git a/examples/ChainedPanelsAuroraDemo/PatternAttract.h b/examples/ChainedPanelsAuroraDemo/PatternAttract.h index 7df342c..dcb6491 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternAttract.h +++ b/examples/ChainedPanelsAuroraDemo/PatternAttract.h @@ -52,7 +52,7 @@ public: unsigned int drawFrame() { // dim all pixels on the display uint8_t dim = beatsin8(2, 170, 250); - effects.DimAll(dim); effects.ShowFrame(); + effects.DimAll(dim); for (int i = 0; i < count; i++) { Boid boid = boids[i]; @@ -66,7 +66,8 @@ public: boids[i] = boid; } - return 15; + effects.ShowFrame(); + return 0; } }; diff --git a/examples/ChainedPanelsAuroraDemo/PatternBounce.h b/examples/ChainedPanelsAuroraDemo/PatternBounce.h new file mode 100644 index 0000000..c0d595a --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternBounce.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 PatternBounce_H + +class PatternBounce : public Drawable { +private: + static const int count = 32; + PVector gravity = PVector(0, 0.0125); + +public: + PatternBounce() { + name = (char *)"Bounce"; + } + + void start() { + unsigned int colorWidth = 256 / count; + for (int i = 0; i < count; i++) { + Boid boid = Boid(i, 0); + boid.velocity.x = 0; + boid.velocity.y = i * -0.01; + boid.colorIndex = colorWidth * i; + boid.maxforce = 10; + boid.maxspeed = 10; + boids[i] = boid; + } + } + + unsigned int drawFrame() { + // dim all pixels on the display + effects.DimAll(170); effects.ShowFrame(); + + for (int i = 0; i < count; i++) { + Boid boid = boids[i]; + + boid.applyForce(gravity); + + boid.update(); + + effects.drawBackgroundFastLEDPixelCRGB(boid.location.x, boid.location.y, effects.ColorFromCurrentPalette(boid.colorIndex)); + + if (boid.location.y >= VPANEL_H - 1) { + boid.location.y = VPANEL_H - 1; + boid.velocity.y *= -1.0; + } + + boids[i] = boid; + } + + return 15; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternCube.h b/examples/ChainedPanelsAuroraDemo/PatternCube.h new file mode 100644 index 0000000..bebf5c8 --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternCube.h @@ -0,0 +1,219 @@ +/* + * 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 PatternCube_H +#define PatternCube_H + +class PatternCube : public Drawable { + private: + float focal = 30; // Focal of the camera + int cubeWidth = 28; // Cube size + float Angx = 20.0, AngxSpeed = 0.05; // rotation (angle+speed) around X-axis + float Angy = 10.0, AngySpeed = 0.05; // rotation (angle+speed) around Y-axis + float Ox = 15.5, Oy = 15.5; // position (x,y) of the frame center + int zCamera = 110; // distance from cube to the eye of the camera + + // Local vertices + Vertex local[8]; + // Camera aligned vertices + Vertex aligned[8]; + // On-screen projected vertices + Point screen[8]; + // Faces + squareFace face[6]; + // Edges + EdgePoint edge[12]; + int nbEdges; + // ModelView matrix + float m00, m01, m02, m10, m11, m12, m20, m21, m22; + + // constructs the cube + void make(int w) + { + nbEdges = 0; + + local[0].set(-w, w, w); + local[1].set(w, w, w); + local[2].set(w, -w, w); + local[3].set(-w, -w, w); + local[4].set(-w, w, -w); + local[5].set(w, w, -w); + local[6].set(w, -w, -w); + local[7].set(-w, -w, -w); + + face[0].set(1, 0, 3, 2); + face[1].set(0, 4, 7, 3); + face[2].set(4, 0, 1, 5); + face[3].set(4, 5, 6, 7); + face[4].set(1, 2, 6, 5); + face[5].set(2, 3, 7, 6); + + int f, i; + for (f = 0; f < 6; f++) + { + for (i = 0; i < face[f].length; i++) + { + face[f].ed[i] = this->findEdge(face[f].sommets[i], face[f].sommets[i ? i - 1 : face[f].length - 1]); + } + } + } + + // finds edges from faces + int findEdge(int a, int b) + { + int i; + for (i = 0; i < nbEdges; i++) + if ((edge[i].x == a && edge[i].y == b) || (edge[i].x == b && edge[i].y == a)) + return i; + edge[nbEdges++].set(a, b); + return i; + } + + // rotates according to angle x&y + void rotate(float angx, float angy) + { + int i; + float cx = cos(angx); + float sx = sin(angx); + float cy = cos(angy); + float sy = sin(angy); + + m00 = cy; + m01 = 0; + m02 = -sy; + m10 = sx * sy; + m11 = cx; + m12 = sx * cy; + m20 = cx * sy; + m21 = -sx; + m22 = cx * cy; + + for (i = 0; i < 8; i++) + { + aligned[i].x = m00 * local[i].x + m01 * local[i].y + m02 * local[i].z; + aligned[i].y = m10 * local[i].x + m11 * local[i].y + m12 * local[i].z; + aligned[i].z = m20 * local[i].x + m21 * local[i].y + m22 * local[i].z + zCamera; + + screen[i].x = floor((Ox + focal * aligned[i].x / aligned[i].z)); + screen[i].y = floor((Oy - focal * aligned[i].y / aligned[i].z)); + } + + for (i = 0; i < 12; i++) + edge[i].visible = false; + + Point *pa, *pb, *pc; + for (i = 0; i < 6; i++) + { + pa = screen + face[i].sommets[0]; + pb = screen + face[i].sommets[1]; + pc = screen + face[i].sommets[2]; + + boolean back = ((pb->x - pa->x) * (pc->y - pa->y) - (pb->y - pa->y) * (pc->x - pa->x)) < 0; + if (!back) + { + int j; + for (j = 0; j < 4; j++) + { + edge[face[i].ed[j]].visible = true; + } + } + } + } + + byte hue = 0; + int step = 0; + + public: + PatternCube() { + name = (char *)"Cube"; + make(cubeWidth); + } + + unsigned int drawFrame() { + uint8_t blurAmount = beatsin8(2, 10, 255); + +#if FASTLED_VERSION >= 3001000 + blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount); +#else + effects.DimAll(blurAmount); effects.ShowFrame(); +#endif + + zCamera = beatsin8(2, 100, 140); + AngxSpeed = beatsin8(3, 1, 10) / 100.0f; + AngySpeed = beatcos8(5, 1, 10) / 100.0f; + + // Update values + Angx += AngxSpeed; + Angy += AngySpeed; + if (Angx >= TWO_PI) + Angx -= TWO_PI; + if (Angy >= TWO_PI) + Angy -= TWO_PI; + + rotate(Angx, Angy); + + // Draw cube + int i; + + CRGB color = effects.ColorFromCurrentPalette(hue, 128); + + // Backface + EdgePoint *e; + for (i = 0; i < 12; i++) + { + e = edge + i; + if (!e->visible) { + matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color); + } + } + + color = effects.ColorFromCurrentPalette(hue, 255); + + // Frontface + for (i = 0; i < 12; i++) + { + e = edge + i; + if (e->visible) + { + matrix.drawLine(screen[e->x].x, screen[e->x].y, screen[e->y].x, screen[e->y].y, color); + } + } + + step++; + if (step == 8) { + step = 0; + hue++; + } + + effects.ShowFrame(); + + return 20; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h b/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h index c6ea4a7..1977a83 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h +++ b/examples/ChainedPanelsAuroraDemo/PatternElectricMandala.h @@ -70,7 +70,7 @@ class PatternElectricMandala : public Drawable { unsigned int drawFrame() { #if FASTLED_VERSION >= 3001000 // a new parameter set every 15 seconds - EVERY_N_SECONDS(25) { + EVERY_N_SECONDS(15) { //SetupRandomPalette3(); dy = random16(500) - 250; // random16(2000) - 1000 is pretty fast but works fine, too dx = random16(500) - 250; @@ -92,13 +92,13 @@ class PatternElectricMandala : public Drawable { effects.ShowFrame(); - return 0; + return 30; } // 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++) { + for (uint16_t i = 0; i < VPANEL_W; i++) { + for (uint16_t j = 0; j < VPANEL_H; j++) { uint8_t color = noise[i][j]; @@ -107,7 +107,7 @@ class PatternElectricMandala : public Drawable { // assign a color depending on the actual palette CRGB pixel = ColorFromPalette(effects.currentPalette, colorrepeat * (color + colorshift), bri); - effects.leds[XY(i, j)] = pixel; + effects.leds[XY16(i, j)] = pixel; } } } diff --git a/examples/ChainedPanelsAuroraDemo/PatternFire.h b/examples/ChainedPanelsAuroraDemo/PatternFire.h index 5d5d021..731aff9 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternFire.h +++ b/examples/ChainedPanelsAuroraDemo/PatternFire.h @@ -1,29 +1,27 @@ /* - 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. + * 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. + */ #ifndef PatternFire_H #define PatternFire_H @@ -58,7 +56,7 @@ class PatternFire : public Drawable { // Add entropy to random number generator; we use a lot of it. random16_add_entropy( random16()); - effects.DimAll(235); + effects.DimAll(235); for (int x = 0; x < VPANEL_W; x++) { // Step 1. Cool down every cell a little @@ -92,12 +90,10 @@ class PatternFire : public Drawable { colorIndex = scale8(colorIndex, 200); // override color 0 to ensure a black background? - //if (colorIndex != 0) { - // effects.leds[xy] = CRGB::Black; - //} - //else { + if (colorIndex != 0) + // effects.leds[xy] = CRGB::Black; + // else effects.leds[xy] = effects.ColorFromCurrentPalette(colorIndex); - //} } } @@ -109,9 +105,10 @@ class PatternFire : public Drawable { noise_scale_y = 4000; effects.FillNoise(); - // effects.MoveX(2); + effects.MoveX(2); effects.MoveFractionalNoiseX(2); + effects.ShowFrame(); return 15; diff --git a/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h index 98c9b08..573c765 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h +++ b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift.h @@ -26,7 +26,7 @@ class PatternIncrementalDrift : public Drawable { public: - PatternIncrementalDrift() { + PatternIncrementalDrift() { name = (char *)"Incremental Drift"; } diff --git a/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift2.h b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift2.h new file mode 100644 index 0000000..03312f6 --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternIncrementalDrift2.h @@ -0,0 +1,64 @@ +/* +* +* 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 PatternIncrementalDrift2_H +#define PatternIncrementalDrift2_H + +class PatternIncrementalDrift2 : public Drawable { + public: + PatternIncrementalDrift2() { + name = (char *)"Incremental Drift Rose"; + } + + unsigned int drawFrame() { + uint8_t dim = beatsin8(2, 170, 250); + effects.DimAll(dim); effects.ShowFrame(); + + for (int i = 2; i < VPANEL_H / 2; ++i) + //for (uint8_t i = 0; i < 32; i++) + { + CRGB color; + + uint8_t x = 0; + uint8_t y = 0; + + if (i < 16) { + x = beatcos8((i + 1) * 2, i, VPANEL_W - i); + y = beatsin8((i + 1) * 2, i, VPANEL_H - i); + color = effects.ColorFromCurrentPalette(i * 14); + } + else + { + x = beatsin8((32 - i) * 2, VPANEL_W - i, i + 1); + y = beatcos8((32 - i) * 2, VPANEL_H - i, i + 1); + color = effects.ColorFromCurrentPalette((31 - i) * 14); + } + + effects.drawBackgroundFastLEDPixelCRGB(x, y, color); + } + + return 0; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternInfinity.h b/examples/ChainedPanelsAuroraDemo/PatternInfinity.h index 87803a7..c99f329 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternInfinity.h +++ b/examples/ChainedPanelsAuroraDemo/PatternInfinity.h @@ -31,7 +31,9 @@ public: unsigned int drawFrame() { // dim all pixels on the display slightly // to 250/255 (98%) of their current brightness - effects.DimAll(250); effects.ShowFrame(); + blur2d(effects.leds, VPANEL_W > 255 ? 255 : VPANEL_W, VPANEL_H > 255 ? 255 : VPANEL_H, 250); + // effects.DimAll(250); effects.ShowFrame(); + // the Effects class has some sample oscillators // that move from 0 to 255 at different speeds @@ -51,7 +53,8 @@ public: // draw a pixel at x,y using a color from the current palette effects.Pixel(x, y, hue); - return 15; + effects.ShowFrame(); + return 30; } }; diff --git a/examples/ChainedPanelsAuroraDemo/PatternInvaders.h b/examples/ChainedPanelsAuroraDemo/PatternInvaders.h new file mode 100644 index 0000000..cad004c --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternInvaders.h @@ -0,0 +1,154 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Inspired by 'Space Invader Generator': https://the8bitpimp.wordpress.com/2013/05/07/space-invader-generator + * + * 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 PatternInvaders_H +#define PatternInvaders_H + +class PatternInvadersSmall : public Drawable { + private: + uint8_t x = 1; + uint8_t y = 1; + + public: + PatternInvadersSmall() { + name = (char *)"Invaders Small"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 5; j++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) color = color1; + + effects.drawBackgroundFastLEDPixelCRGB(x + i, y + j, color); + + if (i < 2) + effects.drawBackgroundFastLEDPixelCRGB(x + (4 - i), y + j, color); + } + } + + x += 6; + if (x > 25) { + x = 1; + y += 6; + } + + if (y > 25) y = x = 1; + + effects.ShowFrame(); + + return 125; + } +}; + +class PatternInvadersMedium : public Drawable { + private: + uint8_t x = 0; + uint8_t y = 0; + + public: + PatternInvadersMedium() { + name = (char *)"Invaders Medium"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 5; j++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) color = color1; + + matrix.fillRect(x + (i * 2), y + (j * 2), x + (i * 2 + 1), y + (j * 2 + 1), color); + + if (i < 2) + matrix.fillRect(x + (8 - i * 2), y + (j * 2), x + (9 - i * 2), y + (j * 2 + 1), color); + } + } + + x += 11; + if (x > 22) { + x = 0; + y += 11; + } + + if (y > 22) y = x = 0; + + effects.ShowFrame(); + + return 500; + } +}; + +class PatternInvadersLarge : public Drawable { + private: + + public: + PatternInvadersLarge() { + name = (char *)"Invaders Large"; + } + + void start() { + matrix.fillScreen(0); + } + + unsigned int drawFrame() { + matrix.fillScreen(0); + + CRGB color1 = effects.ColorFromCurrentPalette(random(0, 255)); + + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 5; y++) { + CRGB color = CRGB::Black; + + if (random(0, 2) == 1) { + color = color1; + } + + matrix.fillRect(1 + x * 6, 1 + y * 6, 5 + x * 6, 5 + y * 6, color); + + if (x < 2) + matrix.fillRect(1 + (4 - x) * 6, 1 + y * 6, 5 + (4 - x) * 6, 5 + y * 6, color); + } + } + + effects.ShowFrame(); + + return 2000; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternMaze.h b/examples/ChainedPanelsAuroraDemo/PatternMaze.h index 8a94d26..b4e26a9 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternMaze.h +++ b/examples/ChainedPanelsAuroraDemo/PatternMaze.h @@ -246,7 +246,7 @@ public: if (algorithm >= algorithmCount) algorithm = 0; - return 1000; + return 0; } effects.ShowFrame(); @@ -255,7 +255,7 @@ public: } void start() { - matrix.fillScreen(0); + effects.ClearFrame(); cellCount = 0; hue = 0; } diff --git a/examples/ChainedPanelsAuroraDemo/PatternMunch.h b/examples/ChainedPanelsAuroraDemo/PatternMunch.h index 21d6720..092dca1 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternMunch.h +++ b/examples/ChainedPanelsAuroraDemo/PatternMunch.h @@ -40,9 +40,9 @@ public: 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; + for (uint16_t x = 0; x < VPANEL_W; x++) { + for (uint16_t y = 0; y < VPANEL_H; y++) { + effects.leds[XY16(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) ; @@ -66,7 +66,6 @@ public: // show it ffs! effects.ShowFrame(); - return 60; } }; diff --git a/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h b/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h index 96e8e53..2d6723a 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h +++ b/examples/ChainedPanelsAuroraDemo/PatternNoiseSmearing.h @@ -65,10 +65,10 @@ public: effects.FillNoise(); effects.MoveX(8); - // effects.MoveFractionalNoiseX(); + effects.MoveFractionalNoiseX(); effects.MoveY(8); - // effects.MoveFractionalNoiseY(); + effects.MoveFractionalNoiseY(); patternNoiseSmearingHue++; @@ -103,10 +103,10 @@ public: effects.FillNoise(); effects.MoveX(3); - // effects.MoveFractionalNoiseY(4); + effects.MoveFractionalNoiseY(4); effects.MoveY(3); - //effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); patternNoiseSmearingHue++; @@ -137,10 +137,10 @@ public: effects.FillNoise(); effects.MoveX(3); - // effects.MoveFractionalNoiseY(4); + effects.MoveFractionalNoiseY(4); effects.MoveY(3); - // effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); effects.ShowFrame(); @@ -170,10 +170,10 @@ public: effects.FillNoise(); effects.MoveX(8); - // effects.MoveFractionalNoiseX(); + effects.MoveFractionalNoiseX(); effects.MoveY(8); - // effects.MoveFractionalNoiseY(); + effects.MoveFractionalNoiseY(); patternNoiseSmearingHue++; @@ -206,10 +206,10 @@ public: effects.FillNoise(); effects.MoveX(3); - // effects.MoveFractionalNoiseY(4); + effects.MoveFractionalNoiseY(4); effects.MoveY(4); - // effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); return 0; } @@ -241,10 +241,10 @@ public: effects.FillNoise(); effects.MoveX(3); - // effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); effects.MoveY(3); - //effects.MoveFractionalNoiseY(4); + effects.MoveFractionalNoiseY(4); return 0; } @@ -261,8 +261,8 @@ public: 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++) { + for (uint8_t y = 0; y < VPANEL_H; y++) { + for (uint8_t x = 0; x < VPANEL_W; x++) { effects.leds[XY(x, y)] += effects.ColorFromCurrentPalette(x * 8, y * 8 + 7); } } @@ -280,7 +280,7 @@ public: //effects.MoveFractionalNoiseY(4); effects.MoveY(3); - // effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); effects.ShowFrame(); return 0; @@ -327,10 +327,10 @@ public: effects.FillNoise(); effects.MoveX(3); - // effects.MoveFractionalNoiseY(4); + effects.MoveFractionalNoiseY(4); effects.MoveY(3); - // effects.MoveFractionalNoiseX(4); + effects.MoveFractionalNoiseX(4); return 0; } diff --git a/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h b/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h index bc6618b..985e15a 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h +++ b/examples/ChainedPanelsAuroraDemo/PatternPendulumWave.h @@ -34,6 +34,12 @@ #ifndef PatternPendulumWave_H #define PatternPendulumWave_H +#define WAVE_BPM 25 +#define AMP_BPM 2 +#define SKEW_BPM 4 +#define WAVE_TIMEMINSKEW VPANEL_W/8 +#define WAVE_TIMEMAXSKEW VPANEL_W/2 + class PatternPendulumWave : public Drawable { public: PatternPendulumWave() { @@ -41,15 +47,19 @@ class PatternPendulumWave : public Drawable { } unsigned int drawFrame() { - effects.DimAll(170); effects.ShowFrame(); + effects.ClearFrame(); - for (int x = 0; x < VPANEL_W; x++) + for (int x = 0; x < VPANEL_W; ++x) { - uint8_t y = beatsin8(x + VPANEL_W, 0, VPANEL_H); + uint16_t amp = beatsin16(AMP_BPM, VPANEL_H/8, VPANEL_H-1); + uint16_t offset = (VPANEL_H - beatsin16(AMP_BPM, 0, VPANEL_H))/2; + + uint8_t y = beatsin16(WAVE_BPM, 0, amp, x*beatsin16(SKEW_BPM, WAVE_TIMEMINSKEW, WAVE_TIMEMAXSKEW)) + offset; + effects.drawBackgroundFastLEDPixelCRGB(x, y, effects.ColorFromCurrentPalette(x * 7)); } - - return 15; + effects.ShowFrame(); + return 20; } }; diff --git a/examples/ChainedPanelsAuroraDemo/PatternPulse.h b/examples/ChainedPanelsAuroraDemo/PatternPulse.h new file mode 100644 index 0000000..8992a4d --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternPulse.h @@ -0,0 +1,82 @@ +/* + * Aurora: https://github.com/pixelmatix/aurora + * Copyright (c) 2014 Jason Coon + * + * Based at least in part on someone else's work that I can no longer find. + * Please let me know if you recognize any of this code! + * + * 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 PatternPulse_H +#define PatternPulse_H + +class PatternPulse : public Drawable { + private: + int hue; + int centerX = 0; + int centerY = 0; + int step = -1; + int maxSteps = 16; + float fadeRate = 0.8; + int diff; + + public: + PatternPulse() { + name = (char *)"Pulse"; + } + + unsigned int drawFrame() { + effects.DimAll(235); + + if (step == -1) { + centerX = random(32); + centerY = random(32); + hue = random(256); // 170; + step = 0; + } + + if (step == 0) { + matrix.drawCircle(centerX, centerY, step, effects.ColorFromCurrentPalette(hue)); + step++; + } + else { + if (step < maxSteps) { + // initial pulse + matrix.drawCircle(centerX, centerY, step, effects.ColorFromCurrentPalette(hue, pow(fadeRate, step - 2) * 255)); + + // secondary pulse + if (step > 3) { + matrix.drawCircle(centerX, centerY, step - 3, effects.ColorFromCurrentPalette(hue, pow(fadeRate, step - 2) * 255)); + } + step++; + } + else { + step = -1; + } + } + + effects.standardNoiseSmearing(); + + effects.ShowFrame(); + + return 30; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h b/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h index 272c604..3810ec0 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h +++ b/examples/ChainedPanelsAuroraDemo/PatternSimplexNoise.h @@ -60,17 +60,17 @@ class PatternSimplexNoise : public Drawable { effects.ShowFrame(); - return 0; + return 30; } // 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++) { + for (uint16_t i = 0; i < VPANEL_W; i++) { + for (uint16_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); + effects.leds[XY16(i, j)] = effects.ColorFromCurrentPalette(colorrepeat * (pixel + colorshift), pixel); } } } diff --git a/examples/ChainedPanelsAuroraDemo/PatternSnake.h b/examples/ChainedPanelsAuroraDemo/PatternSnake.h index 6201985..00895ab 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternSnake.h +++ b/examples/ChainedPanelsAuroraDemo/PatternSnake.h @@ -101,7 +101,7 @@ private: } }; - static const int snakeCount = 40; + static const int snakeCount = 6; Snake snakes[snakeCount]; public: diff --git a/examples/ChainedPanelsAuroraDemo/PatternSpark.h b/examples/ChainedPanelsAuroraDemo/PatternSpark.h new file mode 100644 index 0000000..059d97c --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternSpark.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef PatternSpark_H +#define PatternSpark_H + +class PatternSpark : public Drawable { + private: + + public: + PatternSpark() { + name = (char *)"Spark"; + } + + // 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 + uint8_t 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. + uint8_t sparking = 50; + + unsigned int drawFrame() { + // Add entropy to random number generator; we use a lot of it. + random16_add_entropy( random16()); + + effects.DimAll(235); effects.ShowFrame(); + + for (uint8_t 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) { + uint8_t xt = random8(MATRIX_CENTRE_X - 2, MATRIX_CENTER_X + 3); + + int xy = XY(xt, 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, 240); + + // 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(3); + effects.MoveFractionalNoiseX(4); + + effects.ShowFrame(); + + return 15; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternSpin.h b/examples/ChainedPanelsAuroraDemo/PatternSpin.h new file mode 100644 index 0000000..c3497e7 --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternSpin.h @@ -0,0 +1,100 @@ +/* +* 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 PatternSpin_H + + + +class PatternSpin : public Drawable { +public: + PatternSpin() { + name = (char *)"Spin"; + } + + float degrees = 0; + float radius = 16; + + float speedStart = 1; + float velocityStart = 0.6; + + float maxSpeed = 30; + + float speed = speedStart; + float velocity = velocityStart; + + void start() { + speed = speedStart; + velocity = velocityStart; + degrees = 0; + } + + unsigned int drawFrame() { + effects.DimAll(190); effects.ShowFrame(); + + CRGB color = effects.ColorFromCurrentPalette(speed * 8); + + // start position + int x; + int y; + + // target position + float targetDegrees = degrees + speed; + float targetRadians = radians(targetDegrees); + int targetX = (int) (MATRIX_CENTER_X + radius * cos(targetRadians)); + int targetY = (int) (MATRIX_CENTER_Y - radius * sin(targetRadians)); + + float tempDegrees = degrees; + + do{ + float radians = radians(tempDegrees); + x = (int) (MATRIX_CENTER_X + radius * cos(radians)); + y = (int) (MATRIX_CENTER_Y - radius * sin(radians)); + + effects.drawBackgroundFastLEDPixelCRGB(x, y, color); + effects.drawBackgroundFastLEDPixelCRGB(y, x, color); + + tempDegrees += 1; + if (tempDegrees >= 360) + tempDegrees = 0; + } while (x != targetX || y != targetY); + + degrees += speed; + + // add velocity to the particle each pass around the accelerator + if (degrees >= 360) { + degrees = 0; + speed += velocity; + if (speed <= speedStart) { + speed = speedStart; + velocity *= -1; + } + else if (speed > maxSpeed){ + speed = maxSpeed - velocity; + velocity *= -1; + } + } + + return 0; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/PatternSpiro.h b/examples/ChainedPanelsAuroraDemo/PatternSpiro.h index 9c75952..4b91e12 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternSpiro.h +++ b/examples/ChainedPanelsAuroraDemo/PatternSpiro.h @@ -37,7 +37,7 @@ class PatternSpiro : public Drawable { uint8_t spirocount = 1; uint8_t spirooffset = 256 / spirocount; - boolean spiroincrement = false; + boolean spiroincrement = true; boolean handledChange = false; @@ -46,8 +46,12 @@ class PatternSpiro : public Drawable { name = (char *)"Spiro"; } + void start(){ + effects.ClearFrame(); + }; + unsigned int drawFrame() { - effects.DimAll(254); effects.ShowFrame(); + blur2d(effects.leds, VPANEL_W > 255 ? 255 : VPANEL_W, VPANEL_H > 255 ? 255 : VPANEL_H, 192); boolean change = false; @@ -100,6 +104,7 @@ class PatternSpiro : public Drawable { hueoffset += 1; } + effects.ShowFrame(); return 0; } }; diff --git a/examples/ChainedPanelsAuroraDemo/PatternSwirl.h b/examples/ChainedPanelsAuroraDemo/PatternSwirl.h index 96793ca..3835ce1 100644 --- a/examples/ChainedPanelsAuroraDemo/PatternSwirl.h +++ b/examples/ChainedPanelsAuroraDemo/PatternSwirl.h @@ -36,6 +36,7 @@ class PatternSwirl : public Drawable { } void start() { + effects.ClearFrame(); } unsigned int drawFrame() { @@ -46,24 +47,25 @@ class PatternSwirl : public Drawable { uint8_t blurAmount = beatsin8(2, 10, 255); #if FASTLED_VERSION >= 3001000 - blur2d(effects.leds, VPANEL_W, VPANEL_H, blurAmount); + blur2d(effects.leds, VPANEL_W > 255 ? 255 : VPANEL_W, VPANEL_H > 255 ? 255 : 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); + uint8_t i = beatsin8(256/VPANEL_H, borderWidth, VPANEL_W - borderWidth); + uint8_t j = beatsin8(2048/VPANEL_W, borderWidth, VPANEL_H - borderWidth); + // Also calculate some reflections uint8_t ni = (VPANEL_W - 1) - i; - uint8_t nj = (VPANEL_W - 1) - j; + uint8_t nj = (VPANEL_H - 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(j, i)] += effects.ColorFromCurrentPalette(ms / 13); // this doesn't work for non-square matrixes effects.leds[XY(ni, nj)] += effects.ColorFromCurrentPalette(ms / 17); - effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); + //effects.leds[XY(nj, ni)] += effects.ColorFromCurrentPalette(ms / 29); // this doesn't work for non-square matrixes effects.leds[XY(i, nj)] += effects.ColorFromCurrentPalette(ms / 37); effects.leds[XY(ni, j)] += effects.ColorFromCurrentPalette(ms / 41); diff --git a/examples/ChainedPanelsAuroraDemo/PatternTest.h b/examples/ChainedPanelsAuroraDemo/PatternTest.h new file mode 100644 index 0000000..6f0544f --- /dev/null +++ b/examples/ChainedPanelsAuroraDemo/PatternTest.h @@ -0,0 +1,20 @@ + +#ifndef PatternTest_H +#define PatternTest_H + +class PatternTest : public Drawable { + private: + + public: + PatternTest() { + name = (char *)"Test Pattern"; + } + + unsigned int drawFrame() { + + matrix.fillScreen(matrix.color565(128, 0, 0)); + return 1000; + } +}; + +#endif diff --git a/examples/ChainedPanelsAuroraDemo/Patterns.h b/examples/ChainedPanelsAuroraDemo/Patterns.h index 8242fb1..a4eb838 100644 --- a/examples/ChainedPanelsAuroraDemo/Patterns.h +++ b/examples/ChainedPanelsAuroraDemo/Patterns.h @@ -34,52 +34,75 @@ * * 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 "PatternTest.h" +//#include "PatternNoiseSmearing.h" // Doesn't seem to work, omitting. #include "PatternSpiro.h" #include "PatternRadar.h" #include "PatternSwirl.h" #include "PatternPendulumWave.h" #include "PatternFlowField.h" #include "PatternIncrementalDrift.h" +#include "PatternIncrementalDrift2.h" // Doesn't seem to work, omitting. #include "PatternMunch.h" #include "PatternElectricMandala.h" +//#include "PatternSpin.h" // Doesn't seem to work, omitting. #include "PatternSimplexNoise.h" #include "PatternWave.h" #include "PatternAttract.h" +//#include "PatternBounce.h" // Doesn't seem to work, omitting. #include "PatternFlock.h" #include "PatternInfinity.h" #include "PatternPlasma.h" #include "PatternSnake.h" -#include "PatternFire.h" // Not very good. +#include "PatternInvaders.h" +//#include "PatternCube.h" // Doesn't seem to work, omitting. +//#include "PatternFire.h" // Doesn't seem to work, omitting. #include "PatternLife.h" #include "PatternMaze.h" +//#include "PatternPulse.h" // Doesn't seem to work, omitting. +//#include "PatternSpark.h" // Doesn't seem to work, omitting. #include "PatternSpiral.h" - class Patterns : public Playlist { private: - PatternFireKoz fireKoz; + PatternTest patternTest; + // PatternRainbowFlag rainbowFlag; // doesn't work + // PatternPaletteSmear paletteSmear; + // PatternMultipleStream multipleStream; // doesn't work + // PatternMultipleStream2 multipleStream2; // doesn't work + // PatternMultipleStream3 multipleStream3; // doesn't work + // PatternMultipleStream4 multipleStream4; // doesn't work + // PatternMultipleStream5 multipleStream5; // doesn't work + // PatternMultipleStream8 multipleStream8; // doesn't work PatternSpiro spiro; + // PatternRadar radar; PatternSwirl swirl; PatternPendulumWave pendulumWave; PatternFlowField flowField; PatternIncrementalDrift incrementalDrift; + PatternIncrementalDrift2 incrementalDrift2; PatternMunch munch; PatternElectricMandala electricMandala; + // PatternSpin spin; PatternSimplexNoise simplexNoise; PatternWave wave; PatternAttract attract; + // PatternBounce bounce; PatternFlock flock; + PatternInfinity infinity; PatternPlasma plasma; + PatternInvadersSmall invadersSmall; + // PatternInvadersMedium invadersMedium; + // PatternInvadersLarge invadersLarge; PatternSnake snake; - PatternFire fire; + // PatternCube cube; + // PatternFire fire; PatternLife life; PatternMaze maze; + // PatternPulse pulse; + // PatternSpark spark; PatternSpiral spiral; int currentIndex = 0; @@ -89,29 +112,49 @@ class Patterns : public Playlist { return currentIndex; } - const static int PATTERN_COUNT = 18; + const static int PATTERN_COUNT = 14; Drawable* shuffledItems[PATTERN_COUNT]; Drawable* items[PATTERN_COUNT] = { - &fireKoz, // added by Kosso - &spiro, - &life, + // &patternTest, // ok + &spiro, // cool + // &paletteSmear, // fail + // &multipleStream, // fail + // &multipleStream8,// fail + // &multipleStream5,// fail + // &multipleStream3,// fail + // &radar, // fail + // &multipleStream4, // fail + // &multipleStream2, // fail + &life, // ok &flowField, - &pendulumWave, - &incrementalDrift, - &munch, - &electricMandala, - &simplexNoise, - &wave, - &attract, - &swirl, - &flock, - &plasma, - &snake, - &fire, - &maze, - &spiral, + &pendulumWave, //11 ok + + &incrementalDrift, //12 ok + &incrementalDrift2, // 13 fail + &munch, // 14 ok + // &electricMandala, // 15 ok, but ugly (vortigont) + // &spin, // 16 ok but repeditivev + // &simplexNoise, // 17 - cool! + // &wave, // 18 ok (can't work with 256+ matrix due to uint8_t vars) + // &rainbowFlag, //20 // fail + &attract, // 21 ok + // &swirl, // 22 ok, but ugly (vortigont) + // &bounce, // boncing line crap + &flock, // works + &infinity, // works + &plasma, // works + // &invadersSmall, // works ish, but ugly (vortigont) + // &invadersMedium, // fail + // &invadersLarge, // fail + &snake, // ok + // &cube, // works ish + // &fire, // ok ish + &maze, // ok + // &pulse,// fail + // &spark, // same as fire + &spiral, // ok }; public: @@ -212,11 +255,6 @@ class Patterns : public Playlist { Serial.println("}"); } - int getPatternIndex() - { - return currentIndex; - } - char * getCurrentPatternName() { return currentItem->name; From 05d196d188a7de669254efc6479f835ed935f80f Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Mon, 21 Dec 2020 02:42:55 +0300 Subject: [PATCH 3/3] minor fixes and comments Signed-off-by: Emil Muratov --- ESP32-HUB75-MatrixPanel-I2S-DMA.cpp | 19 ++++++++----------- ESP32-HUB75-MatrixPanel-I2S-DMA.h | 18 ++++++++++++------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp b/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp index 3bb51df..17a4562 100644 --- a/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp +++ b/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp @@ -200,14 +200,17 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() for(int i=lsbMsbTransitionBit + 1; i DMA_MAX ) { #if SERIAL_DEBUG - Serial.println("Split DMA payload required."); - #endif + Serial.printf("rowColorDepthStruct struct is too large, split DMA payload required. Adding %d DMA descriptors\n", PIXEL_COLOR_DEPTH_BITS-1); + #endif numDMAdescriptorsPerRow += PIXEL_COLOR_DEPTH_BITS-1; // Not if numDMAdescriptorsPerRow is even just one descriptor too large, DMA linked list will not correctly loop. @@ -273,7 +276,7 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory() return true; -} // end initMatrixDMABuffer() +} // end allocateDMAmemory() @@ -301,7 +304,7 @@ void MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_pin, int rowColorDepthStruct *fb_malloc_ptr = matrix_row_framebuffer_malloc[row]; #if SERIAL_DEBUG - Serial.printf("DMA payload of %d bytes. DMA_MAX is %d.\r\n", sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS, DMA_MAX); + Serial.printf("Row %d DMA payload of %d bytes. DMA_MAX is %d.\r\n", row, sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS, DMA_MAX); #endif @@ -389,13 +392,6 @@ void MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_pin, int } -/* - //End markers - dmadesc_a[desccount-1].eof = 1; - dmadesc_b[desccount-1].eof = 1; - dmadesc_a[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_a[0]; - dmadesc_b[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_b[0]; -*/ //Serial.printf("Performing I2S setup.\n"); i2s_parallel_config_t cfg={ @@ -655,6 +651,7 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint */ void MatrixPanel_I2S_DMA::shiftDriver(const shift_driver _drv, const int dma_r1_pin, const int dma_g1_pin, const int dma_b1_pin, const int dma_r2_pin, const int dma_g2_pin, const int dma_b2_pin, const int dma_a_pin, const int dma_b_pin, const int dma_c_pin, const int dma_d_pin, const int dma_e_pin, const int dma_lat_pin, const int dma_oe_pin, const int dma_clk_pin){ switch (_drv){ + case ICN2038S: case FM6124: case FM6126A: { diff --git a/ESP32-HUB75-MatrixPanel-I2S-DMA.h b/ESP32-HUB75-MatrixPanel-I2S-DMA.h index 31a65f8..1147368 100644 --- a/ESP32-HUB75-MatrixPanel-I2S-DMA.h +++ b/ESP32-HUB75-MatrixPanel-I2S-DMA.h @@ -114,7 +114,7 @@ // RGB Panel Constants / Calculated Values #define COLOR_CHANNELS_PER_PIXEL 3 -#define PIXELS_PER_ROW ((MATRIX_WIDTH * MATRIX_HEIGHT) / MATRIX_HEIGHT) // = 64 +#define PIXELS_PER_ROW MATRIX_WIDTH // number of all pixels in a row of chained modules //#define PIXEL_COLOR_DEPTH_BITS (MATRIX_COLOR_DEPTH/COLOR_CHANNELS_PER_PIXEL) // = 8 #define ROWS_PER_FRAME (MATRIX_HEIGHT/MATRIX_ROWS_IN_PARALLEL) // = 16 @@ -169,13 +169,17 @@ typedef struct RGB24 { uint8_t blue; } RGB24; -enum shift_driver {SHIFT=0, FM6124, FM6126A}; +/** + * Enumeration of hardware-specific chips + * used to drive matrix modules + */ +enum shift_driver {SHIFT=0, FM6124, FM6126A, ICN2038S}; /***************************************************************************************/ // Used by val2PWM //C/p'ed from https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/ // Example calculator: https://gist.github.com/mathiasvr/19ce1d7b6caeab230934080ae1f1380e -const uint16_t lumConvTab[]={ +const uint8_t lumConvTab[]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 30, 30, 31, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 38, 39, 40, 41, 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86, 87, 88, 90, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 112, 113, 115, 116, 118, 120, 121, 123, 124, 126, 128, 129, 131, 133, 134, 136, 138, 139, 141, 143, 145, 146, 148, 150, 152, 154, 156, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 192, 194, 196, 198, 200, 203, 205, 207, 209, 212, 214, 216, 218, 221, 223, 226, 228, 230, 233, 235, 238, 240, 243, 245, 248, 250, 253, 255, 255}; /***************************************************************************************/ @@ -237,9 +241,11 @@ class MatrixPanel_I2S_DMA : public Adafruit_GFX { // Flush the DMA buffers prior to configuring DMA - Avoid visual artefacts on boot. clearScreen(); // Must fill the DMA buffer with the initial output bit sequence or the panel will display garbage - flipDMABuffer(); // flip to backbuffer 1 - clearScreen(); // Must fill the DMA buffer with the initial output bit sequence or the panel will display garbage - flipDMABuffer(); // backbuffer 0 + if (double_buffering_enabled){ + flipDMABuffer(); // flip to backbuffer 1 + clearScreen(); // Must fill the DMA buffer with the initial output bit sequence or the panel will display garbage + flipDMABuffer(); // backbuffer 0 + } // Setup the ESP32 DMA Engine. Sprite_TM built this stuff. configureDMA(dma_r1_pin, dma_g1_pin, dma_b1_pin, dma_r2_pin, dma_g2_pin, dma_b2_pin, dma_a_pin, dma_b_pin, dma_c_pin, dma_d_pin, dma_e_pin, dma_lat_pin, dma_oe_pin, dma_clk_pin ); //DMA and I2S configuration and setup