Browse Source

Merge pull request #7 from ouellettetech/neopixelupdate

Updating NeoPixel Library
Lazar 1 year ago
parent
commit
a5b3a379ad

File diff suppressed because it is too large
+ 705 - 320
clock-mcu/src/firmware/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp


+ 318 - 139
clock-mcu/src/firmware/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.h

@@ -1,105 +1,129 @@
-/*--------------------------------------------------------------------
-  This file is part of the Adafruit NeoPixel library.
-
-  NeoPixel 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.
-
-  NeoPixel 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
-  <http://www.gnu.org/licenses/>.
-  --------------------------------------------------------------------*/
+/*!
+ * @file Adafruit_NeoPixel.h
+ *
+ * This is part of Adafruit's NeoPixel library for the Arduino platform,
+ * allowing a broad range of microcontroller boards (most AVR boards,
+ * many ARM devices, ESP8266 and ESP32, among others) to control Adafruit
+ * NeoPixels, FLORA RGB Smart Pixels and compatible devices -- WS2811,
+ * WS2812, WS2812B, SK6812, etc.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing products
+ * from Adafruit!
+ *
+ * Written by Phil "Paint Your Dragon" Burgess for Adafruit Industries,
+ * with contributions by PJRC, Michael Miller and other members of the
+ * open source community.
+ *
+ * This file is part of the Adafruit_NeoPixel library.
+ *
+ * Adafruit_NeoPixel 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.
+ *
+ * Adafruit_NeoPixel 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
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
 
 #ifndef ADAFRUIT_NEOPIXEL_H
 #define ADAFRUIT_NEOPIXEL_H
 
-#if (ARDUINO >= 100)
- #include <Arduino.h>
-#else
- #include <WProgram.h>
- #include <pins_arduino.h>
+#ifdef ARDUINO
+  #if (ARDUINO >= 100)
+  #include <Arduino.h>
+  #else
+  #include <WProgram.h>
+  #include <pins_arduino.h>
+  #endif
 #endif
 
-// The order of primary colors in the NeoPixel data stream can vary
-// among device types, manufacturers and even different revisions of
-// the same item.  The third parameter to the Adafruit_NeoPixel
-// constructor encodes the per-pixel byte offsets of the red, green
-// and blue primaries (plus white, if present) in the data stream --
-// the following #defines provide an easier-to-use named version for
-// each permutation.  e.g. NEO_GRB indicates a NeoPixel-compatible
-// device expecting three bytes per pixel, with the first byte
-// containing the green value, second containing red and third
-// containing blue.  The in-memory representation of a chain of
-// NeoPixels is the same as the data-stream order; no re-ordering of
-// bytes is required when issuing data to the chain.
-
-// Bits 5,4 of this value are the offset (0-3) from the first byte of
-// a pixel to the location of the red color byte.  Bits 3,2 are the
-// green offset and 1,0 are the blue offset.  If it is an RGBW-type
-// device (supporting a white primary in addition to R,G,B), bits 7,6
-// are the offset to the white byte...otherwise, bits 7,6 are set to
-// the same value as 5,4 (red) to indicate an RGB (not RGBW) device.
+#ifdef TARGET_LPC1768
+  #include <Arduino.h>
+#endif
+
+// The order of primary colors in the NeoPixel data stream can vary among
+// device types, manufacturers and even different revisions of the same
+// item.  The third parameter to the Adafruit_NeoPixel constructor encodes
+// the per-pixel byte offsets of the red, green and blue primaries (plus
+// white, if present) in the data stream -- the following #defines provide
+// an easier-to-use named version for each permutation. e.g. NEO_GRB
+// indicates a NeoPixel-compatible device expecting three bytes per pixel,
+// with the first byte transmitted containing the green value, second
+// containing red and third containing blue. The in-memory representation
+// of a chain of NeoPixels is the same as the data-stream order; no
+// re-ordering of bytes is required when issuing data to the chain.
+// Most of these values won't exist in real-world devices, but it's done
+// this way so we're ready for it (also, if using the WS2811 driver IC,
+// one might have their pixels set up in any weird permutation).
+
+// Bits 5,4 of this value are the offset (0-3) from the first byte of a
+// pixel to the location of the red color byte.  Bits 3,2 are the green
+// offset and 1,0 are the blue offset.  If it is an RGBW-type device
+// (supporting a white primary in addition to R,G,B), bits 7,6 are the
+// offset to the white byte...otherwise, bits 7,6 are set to the same value
+// as 5,4 (red) to indicate an RGB (not RGBW) device.
 // i.e. binary representation:
 // 0bWWRRGGBB for RGBW devices
 // 0bRRRRGGBB for RGB
 
 // RGB NeoPixel permutations; white and red offsets are always same
-// Offset:         W          R          G          B
-#define NEO_RGB  ((0 << 6) | (0 << 4) | (1 << 2) | (2))
-#define NEO_RBG  ((0 << 6) | (0 << 4) | (2 << 2) | (1))
-#define NEO_GRB  ((1 << 6) | (1 << 4) | (0 << 2) | (2))
-#define NEO_GBR  ((2 << 6) | (2 << 4) | (0 << 2) | (1))
-#define NEO_BRG  ((1 << 6) | (1 << 4) | (2 << 2) | (0))
-#define NEO_BGR  ((2 << 6) | (2 << 4) | (1 << 2) | (0))
+// Offset:         W        R        G        B
+#define NEO_RGB  ((0<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B
+#define NEO_RBG  ((0<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G
+#define NEO_GRB  ((1<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B
+#define NEO_GBR  ((2<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R
+#define NEO_BRG  ((1<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G
+#define NEO_BGR  ((2<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R
 
 // RGBW NeoPixel permutations; all 4 offsets are distinct
 // Offset:         W          R          G          B
-#define NEO_WRGB ((0 << 6) | (1 << 4) | (2 << 2) | (3))
-#define NEO_WRBG ((0 << 6) | (1 << 4) | (3 << 2) | (2))
-#define NEO_WGRB ((0 << 6) | (2 << 4) | (1 << 2) | (3))
-#define NEO_WGBR ((0 << 6) | (3 << 4) | (1 << 2) | (2))
-#define NEO_WBRG ((0 << 6) | (2 << 4) | (3 << 2) | (1))
-#define NEO_WBGR ((0 << 6) | (3 << 4) | (2 << 2) | (1))
-
-#define NEO_RWGB ((1 << 6) | (0 << 4) | (2 << 2) | (3))
-#define NEO_RWBG ((1 << 6) | (0 << 4) | (3 << 2) | (2))
-#define NEO_RGWB ((2 << 6) | (0 << 4) | (1 << 2) | (3))
-#define NEO_RGBW ((3 << 6) | (0 << 4) | (1 << 2) | (2))
-#define NEO_RBWG ((2 << 6) | (0 << 4) | (3 << 2) | (1))
-#define NEO_RBGW ((3 << 6) | (0 << 4) | (2 << 2) | (1))
-
-#define NEO_GWRB ((1 << 6) | (2 << 4) | (0 << 2) | (3))
-#define NEO_GWBR ((1 << 6) | (3 << 4) | (0 << 2) | (2))
-#define NEO_GRWB ((2 << 6) | (1 << 4) | (0 << 2) | (3))
-#define NEO_GRBW ((3 << 6) | (1 << 4) | (0 << 2) | (2))
-#define NEO_GBWR ((2 << 6) | (3 << 4) | (0 << 2) | (1))
-#define NEO_GBRW ((3 << 6) | (2 << 4) | (0 << 2) | (1))
-
-#define NEO_BWRG ((1 << 6) | (2 << 4) | (3 << 2) | (0))
-#define NEO_BWGR ((1 << 6) | (3 << 4) | (2 << 2) | (0))
-#define NEO_BRWG ((2 << 6) | (1 << 4) | (3 << 2) | (0))
-#define NEO_BRGW ((3 << 6) | (1 << 4) | (2 << 2) | (0))
-#define NEO_BGWR ((2 << 6) | (3 << 4) | (1 << 2) | (0))
-#define NEO_BGRW ((3 << 6) | (2 << 4) | (1 << 2) | (0))
-
-// Add NEO_KHZ400 to the color order value to indicate a 400 KHz
-// device.  All but the earliest v1 NeoPixels expect an 800 KHz data
-// stream, this is the default if unspecified.  Because flash space
-// is very limited on ATtiny devices (e.g. Trinket, Gemma), v1
-// NeoPixels aren't handled by default on those chips, though it can
-// be enabled by removing the ifndef/endif below -- but code will be
-// bigger.  Conversely, can disable the NEO_KHZ400 line on other MCUs
-// to remove v1 support and save a little space.
-
-#define NEO_KHZ800 0x0000 // 800 KHz datastream
+#define NEO_WRGB ((0<<6) | (1<<4) | (2<<2) | (3)) ///< Transmit as W,R,G,B
+#define NEO_WRBG ((0<<6) | (1<<4) | (3<<2) | (2)) ///< Transmit as W,R,B,G
+#define NEO_WGRB ((0<<6) | (2<<4) | (1<<2) | (3)) ///< Transmit as W,G,R,B
+#define NEO_WGBR ((0<<6) | (3<<4) | (1<<2) | (2)) ///< Transmit as W,G,B,R
+#define NEO_WBRG ((0<<6) | (2<<4) | (3<<2) | (1)) ///< Transmit as W,B,R,G
+#define NEO_WBGR ((0<<6) | (3<<4) | (2<<2) | (1)) ///< Transmit as W,B,G,R
+
+#define NEO_RWGB ((1<<6) | (0<<4) | (2<<2) | (3)) ///< Transmit as R,W,G,B
+#define NEO_RWBG ((1<<6) | (0<<4) | (3<<2) | (2)) ///< Transmit as R,W,B,G
+#define NEO_RGWB ((2<<6) | (0<<4) | (1<<2) | (3)) ///< Transmit as R,G,W,B
+#define NEO_RGBW ((3<<6) | (0<<4) | (1<<2) | (2)) ///< Transmit as R,G,B,W
+#define NEO_RBWG ((2<<6) | (0<<4) | (3<<2) | (1)) ///< Transmit as R,B,W,G
+#define NEO_RBGW ((3<<6) | (0<<4) | (2<<2) | (1)) ///< Transmit as R,B,G,W
+
+#define NEO_GWRB ((1<<6) | (2<<4) | (0<<2) | (3)) ///< Transmit as G,W,R,B
+#define NEO_GWBR ((1<<6) | (3<<4) | (0<<2) | (2)) ///< Transmit as G,W,B,R
+#define NEO_GRWB ((2<<6) | (1<<4) | (0<<2) | (3)) ///< Transmit as G,R,W,B
+#define NEO_GRBW ((3<<6) | (1<<4) | (0<<2) | (2)) ///< Transmit as G,R,B,W
+#define NEO_GBWR ((2<<6) | (3<<4) | (0<<2) | (1)) ///< Transmit as G,B,W,R
+#define NEO_GBRW ((3<<6) | (2<<4) | (0<<2) | (1)) ///< Transmit as G,B,R,W
+
+#define NEO_BWRG ((1<<6) | (2<<4) | (3<<2) | (0)) ///< Transmit as B,W,R,G
+#define NEO_BWGR ((1<<6) | (3<<4) | (2<<2) | (0)) ///< Transmit as B,W,G,R
+#define NEO_BRWG ((2<<6) | (1<<4) | (3<<2) | (0)) ///< Transmit as B,R,W,G
+#define NEO_BRGW ((3<<6) | (1<<4) | (2<<2) | (0)) ///< Transmit as B,R,G,W
+#define NEO_BGWR ((2<<6) | (3<<4) | (1<<2) | (0)) ///< Transmit as B,G,W,R
+#define NEO_BGRW ((3<<6) | (2<<4) | (1<<2) | (0)) ///< Transmit as B,G,R,W
+
+// Add NEO_KHZ400 to the color order value to indicate a 400 KHz device.
+// All but the earliest v1 NeoPixels expect an 800 KHz data stream, this is
+// the default if unspecified. Because flash space is very limited on ATtiny
+// devices (e.g. Trinket, Gemma), v1 NeoPixels aren't handled by default on
+// those chips, though it can be enabled by removing the ifndef/endif below,
+// but code will be bigger. Conversely, can disable the NEO_KHZ400 line on
+// other MCUs to remove v1 support and save a little space.
+
+#define NEO_KHZ800 0x0000 ///< 800 KHz data transmission
 #ifndef __AVR_ATtiny85__
-#define NEO_KHZ400 0x0100 // 400 KHz datastream
+#define NEO_KHZ400 0x0100 ///< 400 KHz data transmission
 #endif
 
 // If 400 KHz support is enabled, the third parameter to the constructor
@@ -108,75 +132,230 @@
 // is sufficient to encode pixel color order, saving some space.
 
 #ifdef NEO_KHZ400
-typedef uint16_t neoPixelType;
+typedef uint16_t neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
 #else
-typedef uint8_t  neoPixelType;
+typedef uint8_t  neoPixelType; ///< 3rd arg to Adafruit_NeoPixel constructor
 #endif
 
+// These two tables are declared outside the Adafruit_NeoPixel class
+// because some boards may require oldschool compilers that don't
+// handle the C++11 constexpr keyword.
+
+/* A PROGMEM (flash mem) table containing 8-bit unsigned sine wave (0-255).
+   Copy & paste this snippet into a Python REPL to regenerate:
+import math
+for x in range(256):
+    print("{:3},".format(int((math.sin(x/128.0*math.pi)+1.0)*127.5+0.5))),
+    if x&15 == 15: print
+*/
+static const uint8_t PROGMEM _NeoPixelSineTable[256] = {
+  128,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,
+  176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,
+  218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,
+  245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
+  255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
+  245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,
+  218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,
+  176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,
+  128,124,121,118,115,112,109,106,103,100, 97, 93, 90, 88, 85, 82,
+   79, 76, 73, 70, 67, 65, 62, 59, 57, 54, 52, 49, 47, 44, 42, 40,
+   37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 17, 15, 14, 12, 11,
+   10,  9,  7,  6,  5,  5,  4,  3,  2,  2,  1,  1,  1,  0,  0,  0,
+    0,  0,  0,  0,  1,  1,  1,  2,  2,  3,  4,  5,  5,  6,  7,  9,
+   10, 11, 12, 14, 15, 17, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35,
+   37, 40, 42, 44, 47, 49, 52, 54, 57, 59, 62, 65, 67, 70, 73, 76,
+   79, 82, 85, 88, 90, 93, 97,100,103,106,109,112,115,118,121,124};
+
+/* Similar to above, but for an 8-bit gamma-correction table.
+   Copy & paste this snippet into a Python REPL to regenerate:
+import math
+gamma=2.6
+for x in range(256):
+    print("{:3},".format(int(math.pow((x)/255.0,gamma)*255.0+0.5))),
+    if x&15 == 15: print
+*/
+static const uint8_t PROGMEM _NeoPixelGammaTable[256] = {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,
+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
+    3,  3,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,  6,  6,  7,
+    7,  7,  8,  8,  8,  9,  9,  9, 10, 10, 10, 11, 11, 11, 12, 12,
+   13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
+   20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
+   30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
+   42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+   58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 75,
+   76, 77, 78, 80, 81, 82, 84, 85, 86, 88, 89, 90, 92, 93, 94, 96,
+   97, 99,100,102,103,105,106,108,109,111,112,114,115,117,119,120,
+  122,124,125,127,129,130,132,134,136,137,139,141,143,145,146,148,
+  150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,
+  182,184,186,188,191,193,195,197,199,202,204,206,209,211,213,215,
+  218,220,223,225,227,230,232,235,237,240,242,245,247,250,252,255};
+
+/*! 
+    @brief  Class that stores state and functions for interacting with
+            Adafruit NeoPixels and compatible devices.
+*/
 class Adafruit_NeoPixel {
 
  public:
 
   // Constructor: number of LEDs, pin number, LED type
-  Adafruit_NeoPixel(uint16_t n, uint8_t p=6, neoPixelType t=NEO_GRB + NEO_KHZ800);
+  Adafruit_NeoPixel(uint16_t n, uint16_t pin=6,
+    neoPixelType type=NEO_GRB + NEO_KHZ800);
   Adafruit_NeoPixel(void);
   ~Adafruit_NeoPixel();
 
-  void
-    begin(void),
-    show(void),
-    setPin(uint8_t p),
-    setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b),
-    setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w),
-    setPixelColor(uint16_t n, uint32_t c),
-    setBrightness(uint8_t),
-    clear(),
-    updateLength(uint16_t n),
-    updateType(neoPixelType t);
-  uint8_t
-   *getPixels(void) const,
-    getBrightness(void) const,
-    sine8(uint8_t) const,
-    gamma8(uint8_t) const;
-  int8_t
-    getPin(void) { return pin; };
-  uint16_t
-    numPixels(void) const;
-  static uint32_t
-    Color(uint8_t r, uint8_t g, uint8_t b),
-    Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w);
-  uint32_t
-    getPixelColor(uint16_t n) const;
-  inline bool
-    canShow(void) { return (micros() - endTime) >= 300L; }
+  void              begin(void);
+  void              show(void);
+  void              setPin(uint16_t p);
+  void              setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b);
+  void              setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b,
+                      uint8_t w);
+  void              setPixelColor(uint16_t n, uint32_t c);
+  void              fill(uint32_t c=0, uint16_t first=0, uint16_t count=0);
+  void              setBrightness(uint8_t);
+  void              clear(void);
+  void              updateLength(uint16_t n);
+  void              updateType(neoPixelType t);
+  /*!
+    @brief   Check whether a call to show() will start sending data
+             immediately or will 'block' for a required interval. NeoPixels
+             require a short quiet time (about 300 microseconds) after the
+             last bit is received before the data 'latches' and new data can
+             start being received. Usually one's sketch is implicitly using
+             this time to generate a new frame of animation...but if it
+             finishes very quickly, this function could be used to see if
+             there's some idle time available for some low-priority
+             concurrent task.
+    @return  1 or true if show() will start sending immediately, 0 or false
+             if show() would block (meaning some idle time is available).
+  */
+  bool           canShow(void) const { return (micros()-endTime) >= 300L; }
+  /*!
+    @brief   Get a pointer directly to the NeoPixel data buffer in RAM.
+             Pixel data is stored in a device-native format (a la the NEO_*
+             constants) and is not translated here. Applications that access
+             this buffer will need to be aware of the specific data format
+             and handle colors appropriately.
+    @return  Pointer to NeoPixel buffer (uint8_t* array).
+    @note    This is for high-performance applications where calling
+             setPixelColor() on every single pixel would be too slow (e.g.
+             POV or light-painting projects). There is no bounds checking
+             on the array, creating tremendous potential for mayhem if one
+             writes past the ends of the buffer. Great power, great
+             responsibility and all that.
+  */
+  uint8_t          *getPixels(void) const { return pixels; };
+  uint8_t           getBrightness(void) const;
+  /*!
+    @brief   Retrieve the pin number used for NeoPixel data output.
+    @return  Arduino pin number (-1 if not set).
+  */
+  int16_t           getPin(void) const { return pin; };
+  /*!
+    @brief   Return the number of pixels in an Adafruit_NeoPixel strip object.
+    @return  Pixel count (0 if not set).
+  */
+  uint16_t          numPixels(void) const { return numLEDs; }
+  uint32_t          getPixelColor(uint16_t n) const;
+  /*!
+    @brief   An 8-bit integer sine wave function, not directly compatible
+             with standard trigonometric units like radians or degrees.
+    @param   x  Input angle, 0-255; 256 would loop back to zero, completing
+                the circle (equivalent to 360 degrees or 2 pi radians).
+                One can therefore use an unsigned 8-bit variable and simply
+                add or subtract, allowing it to overflow/underflow and it
+                still does the expected contiguous thing.
+    @return  Sine result, 0 to 255, or -128 to +127 if type-converted to
+             a signed int8_t, but you'll most likely want unsigned as this
+             output is often used for pixel brightness in animation effects.
+  */
+  static uint8_t    sine8(uint8_t x) {
+    return pgm_read_byte(&_NeoPixelSineTable[x]); // 0-255 in, 0-255 out
+  }
+  /*!
+    @brief   An 8-bit gamma-correction function for basic pixel brightness
+             adjustment. Makes color transitions appear more perceptially
+             correct.
+    @param   x  Input brightness, 0 (minimum or off/black) to 255 (maximum).
+    @return  Gamma-adjusted brightness, can then be passed to one of the
+             setPixelColor() functions. This uses a fixed gamma correction
+             exponent of 2.6, which seems reasonably okay for average
+             NeoPixels in average tasks. If you need finer control you'll
+             need to provide your own gamma-correction function instead.
+  */
+  static uint8_t    gamma8(uint8_t x) {
+    return pgm_read_byte(&_NeoPixelGammaTable[x]); // 0-255 in, 0-255 out
+  }
+  /*!
+    @brief   Convert separate red, green and blue values into a single
+             "packed" 32-bit RGB color.
+    @param   r  Red brightness, 0 to 255.
+    @param   g  Green brightness, 0 to 255.
+    @param   b  Blue brightness, 0 to 255.
+    @return  32-bit packed RGB value, which can then be assigned to a
+             variable for later use or passed to the setPixelColor()
+             function. Packed RGB format is predictable, regardless of
+             LED strand color order.
+  */
+  static uint32_t   Color(uint8_t r, uint8_t g, uint8_t b) {
+    return ((uint32_t)r << 16) | ((uint32_t)g <<  8) | b;
+  }
+  /*!
+    @brief   Convert separate red, green, blue and white values into a
+             single "packed" 32-bit WRGB color.
+    @param   r  Red brightness, 0 to 255.
+    @param   g  Green brightness, 0 to 255.
+    @param   b  Blue brightness, 0 to 255.
+    @param   w  White brightness, 0 to 255.
+    @return  32-bit packed WRGB value, which can then be assigned to a
+             variable for later use or passed to the setPixelColor()
+             function. Packed WRGB format is predictable, regardless of
+             LED strand color order.
+  */
+  static uint32_t   Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
+    return ((uint32_t)w << 24) | ((uint32_t)r << 16) | ((uint32_t)g <<  8) | b;
+  }
+  static uint32_t   ColorHSV(uint16_t hue, uint8_t sat=255, uint8_t val=255);
+  /*!
+    @brief   A gamma-correction function for 32-bit packed RGB or WRGB
+             colors. Makes color transitions appear more perceptially
+             correct.
+    @param   x  32-bit packed RGB or WRGB color.
+    @return  Gamma-adjusted packed color, can then be passed in one of the
+             setPixelColor() functions. Like gamma8(), this uses a fixed
+             gamma correction exponent of 2.6, which seems reasonably okay
+             for average NeoPixels in average tasks. If you need finer
+             control you'll need to provide your own gamma-correction
+             function instead.
+  */
+  static uint32_t   gamma32(uint32_t x);
 
  protected:
 
-  boolean
 #ifdef NEO_KHZ400  // If 400 KHz NeoPixel support enabled...
-    is800KHz,      // ...true if 800 KHz pixels
+  bool              is800KHz;   ///< true if 800 KHz pixels
 #endif
-    begun;         // true if begin() previously called
-  uint16_t
-    numLEDs,       // Number of RGB LEDs in strip
-    numBytes;      // Size of 'pixels' buffer below (3 or 4 bytes/pixel)
-  int8_t
-    pin;           // Output pin number (-1 if not yet set)
-  uint8_t
-    brightness,
-   *pixels,        // Holds LED color values (3 or 4 bytes each)
-    rOffset,       // Index of red byte within each 3- or 4-byte pixel
-    gOffset,       // Index of green byte
-    bOffset,       // Index of blue byte
-    wOffset;       // Index of white byte (same as rOffset if no white)
-  uint32_t
-    endTime;       // Latch timing reference
+  bool              begun;      ///< true if begin() previously called
+  uint16_t          numLEDs;    ///< Number of RGB LEDs in strip
+  uint16_t          numBytes;   ///< Size of 'pixels' buffer below
+  int16_t           pin;        ///< Output pin number (-1 if not yet set)
+  uint8_t           brightness; ///< Strip brightness 0-255 (stored as +1)
+  uint8_t          *pixels;     ///< Holds LED color values (3 or 4 bytes each)
+  uint8_t           rOffset;    ///< Red index within each 3- or 4-byte pixel
+  uint8_t           gOffset;    ///< Index of green byte
+  uint8_t           bOffset;    ///< Index of blue byte
+  uint8_t           wOffset;    ///< Index of white (==rOffset if no white)
+  uint32_t          endTime;    ///< Latch timing reference
 #ifdef __AVR__
-  volatile uint8_t
-    *port;         // Output PORT register
-  uint8_t
-    pinMask;       // Output PORT bitmask
+  volatile uint8_t *port;       ///< Output PORT register
+  uint8_t           pinMask;    ///< Output PORT bitmask
+#endif
+#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
+  GPIO_TypeDef *gpioPort;       ///< Output GPIO PORT
+  uint32_t gpioPin;             ///< Output GPIO PIN
 #endif
 };
 
-#endif // ADAFRUIT_NEOPIXEL_H
+#endif // ADAFRUIT_NEOPIXEL_H