From f182797159563c9b0158c2d288a046fafa3a2de3 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sat, 14 Jan 2017 12:50:35 -0800 Subject: [PATCH] Add Concentric Ring Topology (#154) --- .../NeoPixelRingTopologyTest.ino | 100 ++++++++++++++++++ keywords.txt | 5 + src/NeoPixelBus.h | 1 + src/internal/NeoRingTopology.h | 89 ++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino create mode 100644 src/internal/NeoRingTopology.h diff --git a/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino b/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino new file mode 100644 index 0000000..64a1bcd --- /dev/null +++ b/examples/NeoPixelRingTopologyTest/NeoPixelRingTopologyTest.ino @@ -0,0 +1,100 @@ +//---------------------------------------------------------------------- +// NeoPixelRingTopologyTest +// This will display specific colors in specific locations on the led rings +// +// This is useful in confirming the layout of your rings +// +// It does require that you have the actual series of rings connected +//---------------------------------------------------------------------- + +#include + +const uint8_t PixelCount = 119; +const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 + +// define the layout of your series of rings +// +// This example is using all of Adafruits rings and a Jewel in the center. +// The center is the input and all the rings are connected in series going outward +// +// Rings: +// 0 - 1 (virtual ring, the center of the jewel) +// 1 - 6 (virtual ring, the outer ring of the jewel) +// 2 - 12 count ring +// 3 - 16 count ring +// 4 - 24 count ring +// 5 - 60 count ring comprised of four arc segments +// +// The values below in Rings[] are the index of the first pixel in each ring. +// An extra value is appended for a virtual ring start that also +// represents the total count of pixels in the complete series and this extra +// value is required. +// +class MyRingsLayout +{ +protected: + const uint16_t Rings[7] = {0, 1, 7, 19, 35, 59, PixelCount}; +}; + +// use the MyRingsLayout to declare the topo object +// +NeoRingTopology topo; + +// declare our strip +// +NeoPixelBus strip(PixelCount, PixelPin); + +// define some handy colors +// +RgbColor red(128, 0, 0); +RgbColor green(0, 128, 0); +RgbColor blue(0, 0, 128); +RgbColor black(0); + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + + strip.Begin(); + strip.Show(); + + Serial.println(); + Serial.println("Running..."); +} + +void loop() +{ + delay(2500); + + Serial.println(); + Serial.println("If your panel is correctly defined, you should see ..."); + Serial.println("First pixel in each ring is Red."); + Serial.println("Middle pixel in each ring is Green."); + Serial.println("Last Pixel in each ring is Blue."); + + + // use the topo to map the 2d polar cordinate to the pixel + // and use that to SetPixelColor + for (uint16_t ring = 0; ring < topo.getCountOfRings(); ring++) + { + // first pixel in each ring is red + strip.SetPixelColor(topo.Map(ring, 0), red); + // last pixel in each ring is blue + strip.SetPixelColor(topo.Map(ring, topo.getPixelCountAtRing(ring) - 1), blue); + // middle pixel in each ring is green + strip.SetPixelColor(topo.Map(ring, topo.getPixelCountAtRing(ring) / 2), green); + } + strip.Show(); + + delay(5000); + + Serial.println(); + Serial.println("Cleared to black ..."); + strip.ClearTo(black); + strip.Show(); +} + diff --git a/keywords.txt b/keywords.txt index d8a4639..08c2245 100644 --- a/keywords.txt +++ b/keywords.txt @@ -56,6 +56,7 @@ ColumnMajorAlternating90Layout KEYWORD1 ColumnMajorAlternating180Layout KEYWORD1 ColumnMajorAlternating270Layout KEYWORD1 NeoTopology KEYWORD1 +NeoRingTopology KEYWORD1 NeoTiles KEYWORD1 NeoMosaic KEYWORD1 NeoGammaEquationMethod KEYWORD1 @@ -139,6 +140,9 @@ Map KEYWORD2 MapProbe KEYWORD2 getWidth KEYWORD2 getHeight KEYWORD2 +getCountOfRings KEYWORD2 +getPixelCountAtRing KEYWORD2 +getPixelCount KEYWORD2 TopologyHint KEYWORD2 Correct KEYWORD2 SpriteWidth KEYWORD2 @@ -151,6 +155,7 @@ Parse KEYWORD2 ToString KEYWORD2 ToNumericalString KEYWORD2 + ####################################### # Constants (LITERAL1) ####################################### diff --git a/src/NeoPixelBus.h b/src/NeoPixelBus.h index d2b962a..fb2566d 100644 --- a/src/NeoPixelBus.h +++ b/src/NeoPixelBus.h @@ -40,6 +40,7 @@ License along with NeoPixel. If not, see #include "internal/Layouts.h" #include "internal/NeoTopology.h" +#include "internal/NeoRingTopology.h" #include "internal/NeoTiles.h" #include "internal/NeoMosaic.h" diff --git a/src/internal/NeoRingTopology.h b/src/internal/NeoRingTopology.h new file mode 100644 index 0000000..67fea42 --- /dev/null +++ b/src/internal/NeoRingTopology.h @@ -0,0 +1,89 @@ +#pragma once + +/*------------------------------------------------------------------------- +NeoRingTopology provides a mapping feature of a 2d polar cordinate to a +linear 1d cordinate. +It is used to map a series of concentric rings of NeoPixels to a index on +the NeoPixelBus. + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +template class NeoRingTopology : protected T_LAYOUT +{ +public: + NeoRingTopology() + { + } + + uint16_t Map(uint8_t ring, uint16_t pixel) const + { + if (pixel >= getPixelCountAtRing(ring)) + { + return 0; // invalid ring and/or pixel argument, always return a valid value, the first one + } + + return _map(ring, pixel); + } + + uint16_t MapProbe(uint8_t ring, uint16_t pixel) const + { + if (pixel >= getPixelCountAtRing(ring)) + { + return getPixelCount(); // total count, out of bounds + } + + return _map(ring, pixel); + } + + uint16_t getCountOfRings() const + { + return _ringCount() - 1; // minus one as the Rings includes the extra value + } + + uint16_t getPixelCountAtRing(uint16_t ring) const + { + if (ring >= getCountOfRings()) + { + return 0; // invalid, no pixels + } + + return T_LAYOUT::Rings[ring + 1] - T_LAYOUT::Rings[ring]; // using the extra value for count calc + } + + uint16_t getPixelCount() const + { + T_LAYOUT::Rings[_ringCount() - 1]; // the last entry is the total count + } + +private: + uint16_t _map(uint16_t ring, uint16_t pixel) const + { + return T_LAYOUT::Rings[ring] + pixel; + } + + uint16_t _ringCount() const + { + return sizeof(T_LAYOUT::Rings) / sizeof(T_LAYOUT::Rings[0]); + } +};