From ea8ded614f980b81a545a3c81ec8149aad7939d5 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 21 Feb 2020 17:14:16 -0500 Subject: [PATCH 1/6] Revert "Merge pull request #70 from adafruit/revert-59-pixelbuf" This reverts commit 10db851c81873fd8db207ff0c4d9342426ee25a4, reversing changes made to 68388d0941fc4803c55b20d81f182215fd690ca2. --- neopixel.py | 169 +++++++++++++---------------------------------- requirements.txt | 1 + setup.py | 2 +- 3 files changed, 48 insertions(+), 124 deletions(-) diff --git a/neopixel.py b/neopixel.py index 9840700..aca77d5 100644 --- a/neopixel.py +++ b/neopixel.py @@ -2,6 +2,8 @@ # # Copyright (c) 2016 Damien P. George # Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +# Copyright (c) 2019 Carter Nelson +# Copyright (c) 2019 Roy Hooper # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -25,28 +27,33 @@ `neopixel` - NeoPixel strip driver ==================================================== -* Author(s): Damien P. George & Scott Shawcroft +* Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper """ -import math - import digitalio from neopixel_write import neopixel_write +try: + import _pixelbuf +except ImportError: + import adafruit_pypixelbuf as _pixelbuf + __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git" + # Pixel color order constants -RGB = (0, 1, 2) +RGB = 'RGB' """Red Green Blue""" -GRB = (1, 0, 2) +GRB = 'GRB' """Green Red Blue""" -RGBW = (0, 1, 2, 3) +RGBW = 'RGBW' """Red Green Blue White""" -GRBW = (1, 0, 2, 3) +GRBW = 'GRBW' """Green Red Blue White""" -class NeoPixel: + +class NeoPixel(_pixelbuf.PixelBuf): """ A sequence of neopixels. @@ -57,7 +64,7 @@ class NeoPixel: brightness :param bool auto_write: True if the neopixels should immediately change when set. If False, `show` must be called explicitly. - :param tuple pixel_order: Set the pixel color channel order. GRBW is set by default. + :param str: Set the pixel color channel order. GRBW is set by default. Example for Circuit Playground Express: @@ -87,28 +94,37 @@ class NeoPixel: pixels[::2] = [RED] * (len(pixels) // 2) time.sleep(2) """ + bpp = None + n = 0 + def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None): - self.pin = digitalio.DigitalInOut(pin) - self.pin.direction = digitalio.Direction.OUTPUT + self.bpp = bpp self.n = n - if pixel_order is None: - self.order = GRBW - self.bpp = bpp + + if not pixel_order: + pixel_order = GRB if bpp == 3 else GRBW else: - self.order = pixel_order - self.bpp = len(self.order) - self.buf = bytearray(self.n * self.bpp) - # Set auto_write to False temporarily so brightness setter does _not_ - # call show() while in __init__. - self.auto_write = False - self.brightness = brightness - self.auto_write = auto_write + self.bpp = bpp = len(pixel_order) + if isinstance(pixel_order, tuple): + order_chars = RGBW + order = [] + for char_no, order in enumerate(pixel_order): + order[pixel_order] = order_chars[char_no] + pixel_order = ''.join(order) + + super().__init__(n, bytearray(self.n * bpp), + brightness=brightness, + rawbuf=bytearray(self.n * bpp), + byteorder=pixel_order, + auto_write=auto_write) + + self.pin = digitalio.DigitalInOut(pin) + self.pin.direction = digitalio.Direction.OUTPUT def deinit(self): """Blank out the NeoPixels and release the pin.""" - for i in range(len(self.buf)): - self.buf[i] = 0 - neopixel_write(self.pin, self.buf) + self.fill(0) + self.show() self.pin.deinit() def __enter__(self): @@ -120,100 +136,6 @@ def __exit__(self, exception_type, exception_value, traceback): def __repr__(self): return "[" + ", ".join([str(x) for x in self]) + "]" - def _set_item(self, index, value): - if index < 0: - index += len(self) - if index >= self.n or index < 0: - raise IndexError - offset = index * self.bpp - r = 0 - g = 0 - b = 0 - w = 0 - if isinstance(value, int): - if value>>24: - raise ValueError("only bits 0->23 valid for integer input") - r = value >> 16 - g = (value >> 8) & 0xff - b = value & 0xff - w = 0 - # If all components are the same and we have a white pixel then use it - # instead of the individual components. - if self.bpp == 4 and r == g and g == b: - w = r - r = 0 - g = 0 - b = 0 - elif (len(value) == self.bpp) or ((len(value) == 3) and (self.bpp == 4)): - if len(value) == 3: - r, g, b = value - else: - r, g, b, w = value - else: - raise ValueError("Color tuple size does not match pixel_order.") - - self.buf[offset + self.order[0]] = r - self.buf[offset + self.order[1]] = g - self.buf[offset + self.order[2]] = b - if self.bpp == 4: - self.buf[offset + self.order[3]] = w - - def __setitem__(self, index, val): - if isinstance(index, slice): - start, stop, step = index.indices(len(self.buf) // self.bpp) - length = stop - start - if step != 0: - length = math.ceil(length / step) - if len(val) != length: - raise ValueError("Slice and input sequence size do not match.") - for val_i, in_i in enumerate(range(start, stop, step)): - self._set_item(in_i, val[val_i]) - else: - self._set_item(index, val) - - if self.auto_write: - self.show() - - def __getitem__(self, index): - if isinstance(index, slice): - out = [] - for in_i in range(*index.indices(len(self.buf) // self.bpp)): - out.append(tuple(self.buf[in_i * self.bpp + self.order[i]] - for i in range(self.bpp))) - return out - if index < 0: - index += len(self) - if index >= self.n or index < 0: - raise IndexError - offset = index * self.bpp - return tuple(self.buf[offset + self.order[i]] - for i in range(self.bpp)) - - def __len__(self): - return len(self.buf) // self.bpp - - @property - def brightness(self): - """Overall brightness of the pixel""" - return self._brightness - - @brightness.setter - def brightness(self, brightness): - # pylint: disable=attribute-defined-outside-init - self._brightness = min(max(brightness, 0.0), 1.0) - if self.auto_write: - self.show() - - def fill(self, color): - """Colors all pixels the given ***color***.""" - auto_write = self.auto_write - self.auto_write = False - for i, _ in enumerate(self): - self[i] = color - if auto_write: - self.show() - self.auto_write = auto_write - def write(self): """.. deprecated: 1.0.0 @@ -226,7 +148,8 @@ def show(self): The colors may or may not be showing after this function returns because it may be done asynchronously.""" - if self.brightness > 0.99: - neopixel_write(self.pin, self.buf) - else: - neopixel_write(self.pin, bytearray([int(i * self.brightness) for i in self.buf])) + neopixel_write(self.pin, self.buf) + + def fill(self, color): + """Colors all pixels the given ***color***.""" + _pixelbuf.fill(self, color) diff --git a/requirements.txt b/requirements.txt index edf9394..5feab09 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ Adafruit-Blinka +adafruit-circuitpython-pypixelbuf diff --git a/setup.py b/setup.py index b2eb264..19b9d72 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ author='Adafruit Industries & Damien P. George', author_email='circuitpython@adafruit.com', - install_requires=['Adafruit-Blinka'], + install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-pypixelbuf'], # Choose your license license='MIT', From 91a5e4e2f352730bb2edb36735f84604e2296f15 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 21 Feb 2020 17:16:19 -0500 Subject: [PATCH 2/6] Fixes for latest _pixelbuf --- neopixel.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/neopixel.py b/neopixel.py index aca77d5..856bd13 100644 --- a/neopixel.py +++ b/neopixel.py @@ -112,11 +112,7 @@ def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_orde order[pixel_order] = order_chars[char_no] pixel_order = ''.join(order) - super().__init__(n, bytearray(self.n * bpp), - brightness=brightness, - rawbuf=bytearray(self.n * bpp), - byteorder=pixel_order, - auto_write=auto_write) + super().__init__(n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write) self.pin = digitalio.DigitalInOut(pin) self.pin.direction = digitalio.Direction.OUTPUT @@ -142,14 +138,5 @@ def write(self): Use ``show`` instead. It matches Micro:Bit and Arduino APIs.""" self.show() - def show(self): - """Shows the new colors on the pixels themselves if they haven't already - been autowritten. - - The colors may or may not be showing after this function returns because - it may be done asynchronously.""" - neopixel_write(self.pin, self.buf) - - def fill(self, color): - """Colors all pixels the given ***color***.""" - _pixelbuf.fill(self, color) + def _transmit(self, buffer): + neopixel_write(self.pin, buffer) From 9fba7b6d9de75234e3435531c5dda81559af2764 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 21 Feb 2020 18:35:42 -0500 Subject: [PATCH 3/6] add docs for methods on parent class --- neopixel.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/neopixel.py b/neopixel.py index 856bd13..708fe5c 100644 --- a/neopixel.py +++ b/neopixel.py @@ -93,6 +93,18 @@ class NeoPixel(_pixelbuf.PixelBuf): with neopixel.NeoPixel(NEOPIXEL, 10) as pixels: pixels[::2] = [RED] * (len(pixels) // 2) time.sleep(2) + + .. py:method:: NeoPixel.show() + + Shows the new colors on the pixels themselves if they haven't already + been autowritten. + + The colors may or may not be showing after this function returns because + it may be done asynchronously. + + .. py:method:: NeoPixel.fill(color) + + Colors all pixels the given ***color***. """ bpp = None n = 0 From 60b545a762abb40f3cdf7fda758fa76de18089a4 Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 21 Feb 2020 18:46:10 -0500 Subject: [PATCH 4/6] reformat docs --- neopixel.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/neopixel.py b/neopixel.py index 708fe5c..0d5228e 100644 --- a/neopixel.py +++ b/neopixel.py @@ -96,15 +96,15 @@ class NeoPixel(_pixelbuf.PixelBuf): .. py:method:: NeoPixel.show() - Shows the new colors on the pixels themselves if they haven't already - been autowritten. + Shows the new colors on the pixels themselves if they haven't already + been autowritten. - The colors may or may not be showing after this function returns because - it may be done asynchronously. + The colors may or may not be showing after this function returns because + it may be done asynchronously. .. py:method:: NeoPixel.fill(color) - Colors all pixels the given ***color***. + Colors all pixels the given ***color***. """ bpp = None n = 0 From ccc70932767148b695dbf532b59c28c34db7794d Mon Sep 17 00:00:00 2001 From: Roy Hooper Date: Fri, 21 Feb 2020 18:50:56 -0500 Subject: [PATCH 5/6] add docs for brightness --- neopixel.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/neopixel.py b/neopixel.py index 0d5228e..ad4e42f 100644 --- a/neopixel.py +++ b/neopixel.py @@ -105,6 +105,11 @@ class NeoPixel(_pixelbuf.PixelBuf): .. py:method:: NeoPixel.fill(color) Colors all pixels the given ***color***. + + .. py:attribute:: brightness + + Overall brightness of the pixel (0 to 1.0) + """ bpp = None n = 0 From ef6edc4875a691ef1d36ca1e0f5b9d7dfb13a177 Mon Sep 17 00:00:00 2001 From: George Waters Date: Thu, 23 Apr 2020 17:55:55 -0400 Subject: [PATCH 6/6] Add support for CP versions < 5 --- neopixel.py | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/neopixel.py b/neopixel.py index ad4e42f..3a36826 100644 --- a/neopixel.py +++ b/neopixel.py @@ -30,12 +30,18 @@ * Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Roy Hooper """ +# pylint: disable=ungrouped-imports +import sys import digitalio from neopixel_write import neopixel_write -try: - import _pixelbuf -except ImportError: + +if sys.implementation.version[0] < 5: import adafruit_pypixelbuf as _pixelbuf +else: + try: + import _pixelbuf + except ImportError: + import adafruit_pypixelbuf as _pixelbuf __version__ = "0.0.0-auto.0" @@ -43,13 +49,13 @@ # Pixel color order constants -RGB = 'RGB' +RGB = "RGB" """Red Green Blue""" -GRB = 'GRB' +GRB = "GRB" """Green Red Blue""" -RGBW = 'RGBW' +RGBW = "RGBW" """Red Green Blue White""" -GRBW = 'GRBW' +GRBW = "GRBW" """Green Red Blue White""" @@ -111,25 +117,20 @@ class NeoPixel(_pixelbuf.PixelBuf): Overall brightness of the pixel (0 to 1.0) """ - bpp = None - n = 0 - - def __init__(self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None): - self.bpp = bpp - self.n = n + def __init__( + self, pin, n, *, bpp=3, brightness=1.0, auto_write=True, pixel_order=None + ): if not pixel_order: pixel_order = GRB if bpp == 3 else GRBW else: - self.bpp = bpp = len(pixel_order) if isinstance(pixel_order, tuple): - order_chars = RGBW - order = [] - for char_no, order in enumerate(pixel_order): - order[pixel_order] = order_chars[char_no] - pixel_order = ''.join(order) + order_list = [RGBW[order] for order in pixel_order] + pixel_order = "".join(order_list) - super().__init__(n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write) + super().__init__( + n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write + ) self.pin = digitalio.DigitalInOut(pin) self.pin.direction = digitalio.Direction.OUTPUT @@ -149,6 +150,13 @@ def __exit__(self, exception_type, exception_value, traceback): def __repr__(self): return "[" + ", ".join([str(x) for x in self]) + "]" + @property + def n(self): + """ + The number of neopixels in the chain (read-only) + """ + return len(self) + def write(self): """.. deprecated: 1.0.0