From 814b0afe06ff61f2a0f8e921725558c0fd8af335 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 5 Feb 2019 18:27:52 -0800 Subject: [PATCH 01/12] Added NeoPixel FeatherWing. Modified DotStar Lib. --- README.rst | 1 + adafruit_featherwing/dotstar_featherwing.py | 58 ++--- adafruit_featherwing/neopixel_featherwing.py | 234 ++++++++++++++++++ docs/api.rst | 2 + docs/examples.rst | 12 +- ...=> featherwing_dotstar_palette_example.py} | 2 +- examples/featherwing_dotstar_simpletest.py | 4 +- .../featherwing_neopixel_palette_example.py | 51 ++++ examples/featherwing_neopixel_simpletest.py | 64 +++++ requirements.txt | 1 + setup.py | 2 +- 11 files changed, 396 insertions(+), 35 deletions(-) create mode 100755 adafruit_featherwing/neopixel_featherwing.py rename examples/{featherwing_dotstar_palettetest.py => featherwing_dotstar_palette_example.py} (95%) create mode 100644 examples/featherwing_neopixel_palette_example.py create mode 100644 examples/featherwing_neopixel_simpletest.py diff --git a/README.rst b/README.rst index d4743e4..d4f919c 100644 --- a/README.rst +++ b/README.rst @@ -26,6 +26,7 @@ These drivers depends on: * `Seesaw `_ * `HT16K33 `_ * `DotStar `_ +* `NeoPixel `_ Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index ce21191..ba9dee7 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -49,7 +49,7 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): self.columns = 12 self._brightness = brightness self._auto_write = True - self._dotstar = dotstar.DotStar(clock, data, self.rows * self.columns, + self._display = dotstar.DotStar(clock, data, self.rows * self.columns, brightness=self._brightness, auto_write=False) def __setitem__(self, indices, value): @@ -64,7 +64,7 @@ def __setitem__(self, indices, value): a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1 """ - self._dotstar[self._get_index(indices)] = value + self._display[self._get_index(indices)] = value self._update() def __getitem__(self, indices): @@ -74,7 +74,7 @@ def __getitem__(self, indices): a slice of DotStar indexes to retrieve a single int that specifies the DotStar index """ - return self._dotstar[self._get_index(indices)] + return self._display[self._get_index(indices)] def _get_index(self, indices): """ @@ -120,7 +120,7 @@ def fill(self, color=0): dotstar.fill() # Clear all lit DotStars """ - self._dotstar.fill(color) + self._display.fill(color) self._update() def show(self): @@ -143,7 +143,7 @@ def show(self): dotstar.show() # Update the DotStars """ - self._dotstar.show() + self._display.show() def shift_right(self, rotate=False): """ @@ -165,22 +165,22 @@ def shift_right(self, rotate=False): dotstar[6, 3] = (0, 255, 0) # Rotate it off the screen - for i in range(0, 11): + for i in range(0, dotstar.columns - 1): dotstar.shift_right(True) time.sleep(.1) time.sleep(1) # Shift it off the screen - for i in range(0, 11): + for i in range(0, dotstar.columns - 1): dotstar.shift_right() time.sleep(.1) """ for y in range(0, self.rows): - last_pixel = self._dotstar[(y + 1) * self.columns - 1] if rotate else 0 + last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 for x in range(self.columns - 1, 0, -1): - self._dotstar[y * self.columns + x] = self._dotstar[y * self.columns + x - 1] - self._dotstar[y * self.columns] = last_pixel + self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] + self._display[y * self.columns] = last_pixel self._update() def shift_left(self, rotate=False): @@ -203,22 +203,22 @@ def shift_left(self, rotate=False): dotstar[6, 3] = (0, 255, 0) # Rotate it off the screen - for i in range(0, 11): + for i in range(0, dotstar.columns - 1): dotstar.shift_left(True) time.sleep(.1) time.sleep(1) # Shift it off the screen - for i in range(0, 11): + for i in range(0, dotstar.columns - 1): dotstar.shift_left() time.sleep(.1) """ for y in range(0, self.rows): - last_pixel = self._dotstar[y * self.columns] if rotate else 0 + last_pixel = self._display[y * self.columns] if rotate else 0 for x in range(0, self.columns - 1): - self._dotstar[y * self.columns + x] = self._dotstar[y * self.columns + x + 1] - self._dotstar[(y + 1) * self.columns - 1] = last_pixel + self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] + self._display[(y + 1) * self.columns - 1] = last_pixel self._update() def shift_up(self, rotate=False): @@ -241,22 +241,22 @@ def shift_up(self, rotate=False): dotstar[6, 3] = (0, 255, 0) # Rotate it off the screen - for i in range(0, 5): + for i in range(0, dotstar.rows - 1): dotstar.shift_up(True) time.sleep(.1) time.sleep(1) # Shift it off the screen - for i in range(0, 5): + for i in range(0, dotstar.rows - 1): dotstar.shift_up() time.sleep(.1) """ for x in range(0, self.columns): - last_pixel = self._dotstar[(self.rows - 1) * self.columns + x] if rotate else 0 + last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 for y in range(self.rows - 1, 0, -1): - self._dotstar[y * self.columns + x] = self._dotstar[(y - 1) * self.columns + x] - self._dotstar[x] = last_pixel + self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] + self._display[x] = last_pixel self._update() def shift_down(self, rotate=False): @@ -279,22 +279,22 @@ def shift_down(self, rotate=False): dotstar[6, 3] = (0, 255, 0) # Rotate it off the screen - for i in range(0, 5): + for i in range(0, dotstar.rows - 1): dotstar.shift_down(True) time.sleep(.1) time.sleep(1) # Shift it off the screen - for i in range(0, 5): + for i in range(0, dotstar.rows - 1): dotstar.shift_down() time.sleep(.1) """ for x in range(0, self.columns): - last_pixel = self._dotstar[x] if rotate else 0 + last_pixel = self._display[x] if rotate else 0 for y in range(0, self.rows - 1): - self._dotstar[y * self.columns + x] = self._dotstar[(y + 1) * self.columns + x] - self._dotstar[(self.rows - 1) * self.columns + x] = last_pixel + self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] + self._display[(self.rows - 1) * self.columns + x] = last_pixel self._update() def _update(self): @@ -302,7 +302,7 @@ def _update(self): Update the Display automatically if auto_write is set to True """ if self._auto_write: - self._dotstar.show() + self._display.show() @property def auto_write(self): @@ -357,9 +357,9 @@ def brightness(self): dotstar.brightness = 0.3 """ - return self._dotstar.brightness + return self._display.brightness @brightness.setter def brightness(self, brightness): - self._dotstar.brightness = min(max(brightness, 0.0), 1.0) - self._update() + self._display.brightness = min(max(brightness, 0.0), 1.0) + self._update() \ No newline at end of file diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py new file mode 100755 index 0000000..a4266d4 --- /dev/null +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -0,0 +1,234 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Melissa LeBlanc-Williams for Adafruit Industries LLC +# +# 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. +""" +`adafruit_featherwing.neopixel_featherwing` +==================================================== + +Helper for using the `NeoPixel FeatherWing `_. + +* Author(s): Melissa LeBlanc-Williams +""" + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_FeatherWing.git" + +import board +import neopixel +from adafruit_featherwing.dotstar_featherwing import DotStarFeatherWing + +class NeoPixelFeatherWing(DotStarFeatherWing): + """Class representing a `NeoPixel FeatherWing + `_. + + The feather uses pins D6 by default""" + def __init__(self, pixel_pin=board.D6, brightness=0.1): + """ + :param pin pixel_pin: The pin for the featherwing + :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 + """ + + # The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed! + # For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW. + + self.rows = 4 + self.columns = 8 + self._auto_write = True + self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, brightness=brightness, + auto_write=False, pixel_order=neopixel.GRB) + + def fill(self, color=0): + """ + Fills all of the NeoPixels with a color or unlit if empty. + + :param color: (Optional) The text or number to display (default=0) + :type color: list/tuple or int + + This example shows various ways of using the fill() function + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + neopixel.fill((255, 255, 255)) # Fill White + time.sleep(1) + neopixel.fill(0xFF0000) # Fill Red + time.sleep(1) + neopixel.fill() # Clear all lit NeoPixels + + """ + super().fill(color) + + def show(self): + """ + Update the NeoPixels. This is only needed if auto_write is set to False + This can be very useful for more advanced graphics effects. + + This example changes the blink rate and prints out the current setting + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + neopixel.fill() # Clear any lit NeoPixels + neopixel.auto_write = False + neopixel[0, 0] = (255, 255, 255) # Set White + time.sleep(1) + neopixel.show() # Update the NeoPixels + + """ + super().show() + + def shift_right(self, rotate=False): + """ + Shift all pixels left + + :param rotate: (Optional) Rotate the shifted pixels to the left side (default=False) + + This example shifts 2 pixels to the right + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + + # Draw Red and Green Pixels + neopixel[4, 1] = (255, 0, 0) + neopixel[5, 1] = (0, 255, 0) + + # Rotate it off the screen + for i in range(0, neopixel.columns - 1): + neopixel.shift_right(True) + time.sleep(.1) + + time.sleep(1) + # Shift it off the screen + for i in range(0, neopixel.columns - 1): + neopixel.shift_right() + time.sleep(.1) + + """ + super().shift_right(rotate) + + def shift_left(self, rotate=False): + """ + Shift all pixels left + + :param rotate: (Optional) Rotate the shifted pixels to the right side (default=False) + + This example shifts 2 pixels to the left + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + + # Draw Red and Green Pixels + neopixel[4, 1] = (255, 0, 0) + neopixel[5, 1] = (0, 255, 0) + + # Rotate it off the screen + for i in range(0, neopixel.columns - 1): + neopixel.shift_left(True) + time.sleep(.1) + + time.sleep(1) + # Shift it off the screen + for i in range(0, neopixel.columns - 1): + neopixel.shift_left() + time.sleep(.1) + + """ + super().shift_left(rotate) + + def shift_up(self, rotate=False): + """ + Shift all pixels up + + :param rotate: (Optional) Rotate the shifted pixels to bottom (default=False) + + This example shifts 2 pixels up + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + + # Draw Red and Green Pixels + neopixel[4, 1] = (255, 0, 0) + neopixel[5, 1] = (0, 255, 0) + + # Rotate it off the screen + for i in range(0, neopixel.rows - 1): + neopixel.shift_up(True) + time.sleep(.1) + + time.sleep(1) + # Shift it off the screen + for i in range(0, neopixel.rows - 1): + neopixel.shift_up() + time.sleep(.1) + + """ + super().shift_down(rotate) # Up and down are reversed + + def shift_down(self, rotate=False): + """ + Shift all pixels down. + + :param rotate: (Optional) Rotate the shifted pixels to top (default=False) + + This example shifts 2 pixels down + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + + # Draw Red and Green Pixels + neopixel[4, 1] = (255, 0, 0) + neopixel[5, 1] = (0, 255, 0) + + # Rotate it off the screen + for i in range(0, neopixel.rows - 1): + neopixel.shift_down(True) + time.sleep(.1) + + time.sleep(1) + # Shift it off the screen + for i in range(0, neopixel.rows - 1): + neopixel.shift_down() + time.sleep(.1) + + """ + super().shift_up(rotate) # Up and down are reversed diff --git a/docs/api.rst b/docs/api.rst index 5cd9014..1c1e449 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -13,3 +13,5 @@ .. automodule:: adafruit_featherwing.dotstar_featherwing :members: +.. automodule:: adafruit_featherwing.neopixel_featherwing + :members: diff --git a/docs/examples.rst b/docs/examples.rst index a5e5ea1..277bb21 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -19,9 +19,17 @@ Ensure your device works with this simple test. :caption: examples/featherwing_dotstar_simpletest.py :linenos: -.. literalinclude:: ../examples/featherwing_dotstar_palettetest.py - :caption: examples/featherwing_dotstar_palettetest.py +.. literalinclude:: ../examples/featherwing_neopixel_simpletest.py + :caption: examples/featherwing_neopixel_simpletest.py :linenos: +Other tests +------------ +.. literalinclude:: ../examples/featherwing_dotstar_palettetest.py + :caption: examples/featherwing_dotstar_palette_example.py + :linenos: +.. literalinclude:: ../examples/featherwing_neopixel_palettetest.py + :caption: examples/featherwing_neopixel_palette_example.py + :linenos: diff --git a/examples/featherwing_dotstar_palettetest.py b/examples/featherwing_dotstar_palette_example.py similarity index 95% rename from examples/featherwing_dotstar_palettetest.py rename to examples/featherwing_dotstar_palette_example.py index d13891b..e35c540 100644 --- a/examples/featherwing_dotstar_palettetest.py +++ b/examples/featherwing_dotstar_palette_example.py @@ -41,7 +41,7 @@ def rotate(degrees): dotstar.auto_write = False while True: for color in range(0, 360, 10): - for index in range(0, 72): + for index in range(0, dotstar.rows * dotstar.columns): palette_index = pixels[index] + color if palette_index >= 360: palette_index -= 360 diff --git a/examples/featherwing_dotstar_simpletest.py b/examples/featherwing_dotstar_simpletest.py index f301770..a5bd2da 100755 --- a/examples/featherwing_dotstar_simpletest.py +++ b/examples/featherwing_dotstar_simpletest.py @@ -1,5 +1,5 @@ """ -This example changes the screen different colors +This plays various animations and then draws random pixels at random locations """ @@ -57,4 +57,4 @@ def random_color(): x = random.randrange(0, dotstar.columns) y = random.randrange(0, dotstar.rows) dotstar[x, y] = (random_color(), random_color(), random_color()) - sleep(.1) + sleep(.1) \ No newline at end of file diff --git a/examples/featherwing_neopixel_palette_example.py b/examples/featherwing_neopixel_palette_example.py new file mode 100644 index 0000000..a98a844 --- /dev/null +++ b/examples/featherwing_neopixel_palette_example.py @@ -0,0 +1,51 @@ +""" +This creates a palette of colors, draws a pattern and +rotates through the palette creating a moving rainbow. +""" + +from math import sqrt, cos, sin, radians +from adafruit_featherwing import neopixel_featherwing + +neopixel = neopixel_featherwing.NeoPixelFeatherWing() + +# Remap the calculated rotation to 0 - 255 +def remap(vector): + return int(((255 * vector + 85) * 0.75) + 0.5) + +# Calculate the Hue rotation starting with Red as 0 degrees +def rotate(degrees): + cosA = cos(radians(degrees)) + sinA = sin(radians(degrees)) + red = cosA + (1.0 - cosA) / 3.0 + green = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA + blue = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA + return (remap(red), remap(green), remap(blue)) + +palette = [] +pixels = [] + +# Generate a rainbow palette +for degree in range(0, 360): + color = rotate(degree) + palette.append(color[0] << 16 | color[1] << 8 | color[2]) + +# Create the Pattern +for y in range(0, neopixel.rows): + for x in range(0, neopixel.columns): + pixels.append(x * 30 + y * -30) + +# Clear the screen +neopixel.fill() + +# Start the Animation +neopixel.auto_write = False +while True: + for color in range(0, 360, 10): + for index in range(0, neopixel.rows * neopixel.columns): + palette_index = pixels[index] + color + if palette_index >= 360: + palette_index -= 360 + elif palette_index < 0: + palette_index += 360 + neopixel[index] = palette[palette_index] + neopixel.show() diff --git a/examples/featherwing_neopixel_simpletest.py b/examples/featherwing_neopixel_simpletest.py new file mode 100644 index 0000000..17c062b --- /dev/null +++ b/examples/featherwing_neopixel_simpletest.py @@ -0,0 +1,64 @@ +""" +This example plays various animations +and then draws random pixels at random locations +""" + +from time import sleep +import random +from adafruit_featherwing import neopixel_featherwing + +neopixel = neopixel_featherwing.NeoPixelFeatherWing() + +# HELPERS +# a random color 0 -> 224 +def random_color(): + return random.randrange(0, 8) * 32 + +# Fill screen with random colors at random brightnesses +for i in range(0, 5): + neopixel.fill((random_color(), random_color(), random_color())) + neopixel.brightness = random.randrange(2, 10) / 10 + sleep(.2) + +# Set display to 30% brightness +neopixel.brightness = 0.3 + +# Create a gradiant drawing each pixel +for x in range(0, neopixel.columns): + for y in range(neopixel.rows - 1, -1, -1): + neopixel[x, y] = (y * 63, 255, y * 63) + +#Rotate everything left 36 frames +for i in range(0, 36): + neopixel.shift_down(True) + sleep(0.1) + +# Draw dual gradiant and then update +#neopixel.auto_write = False +for y in range(0, neopixel.rows): + for x in range(0, 4): + neopixel[x, y] = (y * 16 + 32, x * 8, 0) + for x in range(4, 8): + neopixel[x, y] = ((4 - y) * 16 + 32, (8 - x) * 8, 0) +neopixel.show() + +# Rotate everything left 36 frames +for i in range(0, 36): + neopixel.shift_left(True) + neopixel.shift_up(True) + neopixel.show() + sleep(0.1) +neopixel.auto_write = True + +# Shift pixels without rotating for an animated screen wipe +for i in range(0, neopixel.rows): + neopixel.shift_down() + sleep(0.4) + +# Show pixels in random locations of random color +# Bottom left corner is (0,0) +while True: + x = random.randrange(0, neopixel.columns) + y = random.randrange(0, neopixel.rows) + neopixel[x, y] = (random_color(), random_color(), random_color()) + sleep(.1) diff --git a/requirements.txt b/requirements.txt index 1cbf8f4..32c8ec6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ adafruit-circuitpython-ina219 adafruit-circuitpython-seesaw adafruit-circuitpython-ht16k33 adafruit-circuitpython-dotstar +adafruit-circuitpython-neopixel diff --git a/setup.py b/setup.py index 95aa788..90b67ee 100644 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice', 'adafruit-circuitpython-register', 'adafruit-circuitpython-ina219', 'adafruit-circuitpython-seesaw', 'adafruit-circuitpython-ht16k33', - 'adafruit-circuitpython-dotstar'], + 'adafruit-circuitpython-dotstar', 'adafruit-circuitpython-neopixel'], # Choose your license license='MIT', From a6bbcca12b952032883792f9b7be3f00a5f9df5e Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 5 Feb 2019 19:03:29 -0800 Subject: [PATCH 02/12] Restructured DotStar and NeoPixel to use common base class --- adafruit_featherwing/dotstar_featherwing.py | 139 ++++++++++++------- adafruit_featherwing/neopixel_featherwing.py | 83 +++++++++-- docs/examples.rst | 2 +- examples/featherwing_dotstar_simpletest.py | 2 +- 4 files changed, 165 insertions(+), 61 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index ba9dee7..5043f4f 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -34,23 +34,12 @@ import board import adafruit_dotstar as dotstar -class DotStarFeatherWing: - """Class representing a `DotStar FeatherWing - `_. +class PixelDisplayFeatherWing: + """Base Class for DotStar and NeoPixel FeatherWings The feather uses pins D13 and D11""" - def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): - """ - :param pin clock: The clock pin for the featherwing - :param pin data: The data pin for the featherwing - :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 - """ - self.rows = 6 - self.columns = 12 - self._brightness = brightness + def __init__(self): self._auto_write = True - self._display = dotstar.DotStar(clock, data, self.rows * self.columns, - brightness=self._brightness, auto_write=False) def __setitem__(self, indices, value): """ @@ -96,6 +85,88 @@ def _get_index(self, indices): else: raise ValueError('Index must be 1 or 2 number') + def _update(self): + """ + Update the Display automatically if auto_write is set to True + """ + if self._auto_write: + self._display.show() + + def _fill(self, color=0): + """ + Fills all of the Pixels with a color or unlit if empty. + """ + self._display.fill(color) + self._update() + + def _show(self): + """ + Update the Pixels. This is only needed if auto_write is set to False + This can be very useful for more advanced graphics effects. + """ + self._display.show() + + def _shift_right(self, rotate=False): + """ + Shift all pixels right + """ + for y in range(0, self.rows): + last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 + for x in range(self.columns - 1, 0, -1): + self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] + self._display[y * self.columns] = last_pixel + self._update() + + def _shift_left(self, rotate=False): + """ + Shift all pixels left + """ + for y in range(0, self.rows): + last_pixel = self._display[y * self.columns] if rotate else 0 + for x in range(0, self.columns - 1): + self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] + self._display[(y + 1) * self.columns - 1] = last_pixel + self._update() + + def _shift_up(self, rotate=False): + """ + Shift all pixels up + """ + for x in range(0, self.columns): + last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 + for y in range(self.rows - 1, 0, -1): + self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] + self._display[x] = last_pixel + self._update() + + def _shift_down(self, rotate=False): + """ + Shift all pixels down + """ + for x in range(0, self.columns): + last_pixel = self._display[x] if rotate else 0 + for y in range(0, self.rows - 1): + self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] + self._display[(self.rows - 1) * self.columns + x] = last_pixel + self._update() + +class DotStarFeatherWing(PixelDisplayFeatherWing): + """Class representing a `DotStar FeatherWing + `_. + + The feather uses pins D13 and D11""" + def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): + """ + :param pin clock: The clock pin for the featherwing + :param pin data: The data pin for the featherwing + :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 + """ + self.rows = 6 + self.columns = 12 + self._display = dotstar.DotStar(clock, data, self.rows * self.columns, + brightness=brightness, auto_write=False) + super().__init__() + def fill(self, color=0): """ Fills all of the DotStars with a color or unlit if empty. @@ -120,8 +191,7 @@ def fill(self, color=0): dotstar.fill() # Clear all lit DotStars """ - self._display.fill(color) - self._update() + super()._fill(color) def show(self): """ @@ -143,7 +213,7 @@ def show(self): dotstar.show() # Update the DotStars """ - self._display.show() + super()._show() def shift_right(self, rotate=False): """ @@ -176,12 +246,7 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - for y in range(0, self.rows): - last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 - for x in range(self.columns - 1, 0, -1): - self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] - self._display[y * self.columns] = last_pixel - self._update() + super()._shift_right(rotate) def shift_left(self, rotate=False): """ @@ -214,12 +279,7 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - for y in range(0, self.rows): - last_pixel = self._display[y * self.columns] if rotate else 0 - for x in range(0, self.columns - 1): - self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] - self._display[(y + 1) * self.columns - 1] = last_pixel - self._update() + super()._shift_left(rotate) def shift_up(self, rotate=False): """ @@ -252,12 +312,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - for x in range(0, self.columns): - last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 - for y in range(self.rows - 1, 0, -1): - self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] - self._display[x] = last_pixel - self._update() + super()._shift_up(rotate) def shift_down(self, rotate=False): """ @@ -290,19 +345,7 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - for x in range(0, self.columns): - last_pixel = self._display[x] if rotate else 0 - for y in range(0, self.rows - 1): - self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] - self._display[(self.rows - 1) * self.columns + x] = last_pixel - self._update() - - def _update(self): - """ - Update the Display automatically if auto_write is set to True - """ - if self._auto_write: - self._display.show() + super()._shift_down(rotate) @property def auto_write(self): diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index a4266d4..250d853 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,9 +33,9 @@ import board import neopixel -from adafruit_featherwing.dotstar_featherwing import DotStarFeatherWing +from adafruit_featherwing.dotstar_featherwing import PixelDisplayFeatherWing -class NeoPixelFeatherWing(DotStarFeatherWing): +class NeoPixelFeatherWing(PixelDisplayFeatherWing): """Class representing a `NeoPixel FeatherWing `_. @@ -51,9 +51,10 @@ def __init__(self, pixel_pin=board.D6, brightness=0.1): self.rows = 4 self.columns = 8 - self._auto_write = True - self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, brightness=brightness, - auto_write=False, pixel_order=neopixel.GRB) + self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, + brightness=brightness, auto_write=False, + pixel_order=neopixel.GRB) + super().__init__() def fill(self, color=0): """ @@ -77,7 +78,7 @@ def fill(self, color=0): neopixel.fill() # Clear all lit NeoPixels """ - super().fill(color) + super()._fill(color) def show(self): """ @@ -99,7 +100,7 @@ def show(self): neopixel.show() # Update the NeoPixels """ - super().show() + super()._show() def shift_right(self, rotate=False): """ @@ -132,7 +133,7 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - super().shift_right(rotate) + super()._shift_right(rotate) def shift_left(self, rotate=False): """ @@ -165,7 +166,7 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - super().shift_left(rotate) + super()._shift_left(rotate) def shift_up(self, rotate=False): """ @@ -198,7 +199,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - super().shift_down(rotate) # Up and down are reversed + super()._shift_down(rotate) # Up and down are reversed def shift_down(self, rotate=False): """ @@ -231,4 +232,64 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - super().shift_up(rotate) # Up and down are reversed + super()._shift_up(rotate) # Up and down are reversed + + @property + def auto_write(self): + """ + Whether or not we are automatically updating + If set to false, be sure to call show() to update + + This lights NeoPixels with and without auto_write + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + neopixel.fill() # Clear any lit NeoPixels + neopixel[0, 0] = (255, 255, 255) # Set White + time.sleep(1) + + neopixel.auto_write = False + neopixel[1, 0] = (255, 255, 255) # Set White + time.sleep(1) + neopixel.show() # Update the NeoPixels + + """ + return self._auto_write + + @auto_write.setter + def auto_write(self, write): + if isinstance(write, bool): + self._auto_write = write + + @property + def brightness(self): + """ + Overall brightness of the display + + This example changes the brightness + + .. code-block:: python + + import time + from adafruit_featherwing import neopixel_featherwing + + neopixel = neopixel_featherwing.NeoPixelFeatherWing() + neopixel.brightness = 0 + neopixel.fill(0xFFFFFF) + for i in range(0, 6): + neopixel.brightness = (i / 10) + time.sleep(.2) + + neopixel.brightness = 0.3 + + """ + return self._display.brightness + + @brightness.setter + def brightness(self, brightness): + self._display.brightness = min(max(brightness, 0.0), 1.0) + self._update() \ No newline at end of file diff --git a/docs/examples.rst b/docs/examples.rst index 277bb21..869656f 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -30,6 +30,6 @@ Other tests :caption: examples/featherwing_dotstar_palette_example.py :linenos: -.. literalinclude:: ../examples/featherwing_neopixel_palettetest.py +.. literalinclude:: ../examples/featherwing_neopixel_palette_example.py :caption: examples/featherwing_neopixel_palette_example.py :linenos: diff --git a/examples/featherwing_dotstar_simpletest.py b/examples/featherwing_dotstar_simpletest.py index a5bd2da..fb35dd2 100755 --- a/examples/featherwing_dotstar_simpletest.py +++ b/examples/featherwing_dotstar_simpletest.py @@ -57,4 +57,4 @@ def random_color(): x = random.randrange(0, dotstar.columns) y = random.randrange(0, dotstar.rows) dotstar[x, y] = (random_color(), random_color(), random_color()) - sleep(.1) \ No newline at end of file + sleep(.1) From b862de51b27ec0c948e4ce684a0a18f6221de339 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 5 Feb 2019 19:10:44 -0800 Subject: [PATCH 03/12] Linting --- adafruit_featherwing/dotstar_featherwing.py | 17 ++++++++++++----- adafruit_featherwing/neopixel_featherwing.py | 8 ++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index 5043f4f..d0ac87f 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -39,6 +39,9 @@ class PixelDisplayFeatherWing: The feather uses pins D13 and D11""" def __init__(self): + self.rows = 0 + self.columns = 0 + self._display = None self._auto_write = True def __setitem__(self, indices, value): @@ -53,8 +56,9 @@ def __setitem__(self, indices, value): a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1 """ - self._display[self._get_index(indices)] = value - self._update() + if self._display is not None: + self._display[self._get_index(indices)] = value + self._update() def __getitem__(self, indices): """ @@ -63,7 +67,10 @@ def __getitem__(self, indices): a slice of DotStar indexes to retrieve a single int that specifies the DotStar index """ - return self._display[self._get_index(indices)] + if self._display is not None: + return self._display[self._get_index(indices)] + else: + return None def _get_index(self, indices): """ @@ -161,11 +168,11 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): :param pin data: The data pin for the featherwing :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 """ + super().__init__() self.rows = 6 self.columns = 12 self._display = dotstar.DotStar(clock, data, self.rows * self.columns, brightness=brightness, auto_write=False) - super().__init__() def fill(self, color=0): """ @@ -405,4 +412,4 @@ def brightness(self): @brightness.setter def brightness(self, brightness): self._display.brightness = min(max(brightness, 0.0), 1.0) - self._update() \ No newline at end of file + self._update() diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 250d853..7e1b188 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -45,16 +45,12 @@ def __init__(self, pixel_pin=board.D6, brightness=0.1): :param pin pixel_pin: The pin for the featherwing :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 """ - - # The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed! - # For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW. - + super().__init__() self.rows = 4 self.columns = 8 self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, brightness=brightness, auto_write=False, pixel_order=neopixel.GRB) - super().__init__() def fill(self, color=0): """ @@ -292,4 +288,4 @@ def brightness(self): @brightness.setter def brightness(self, brightness): self._display.brightness = min(max(brightness, 0.0), 1.0) - self._update() \ No newline at end of file + self._update() From c5522d5f9fe9e71785b3bf217352b67fb9fd668a Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 5 Feb 2019 19:42:24 -0800 Subject: [PATCH 04/12] Undid class split. Linting. --- adafruit_featherwing/dotstar_featherwing.py | 151 ++++++------------- adafruit_featherwing/neopixel_featherwing.py | 34 ++--- docs/examples.rst | 2 +- 3 files changed, 64 insertions(+), 123 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index d0ac87f..2016a2a 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -34,15 +34,22 @@ import board import adafruit_dotstar as dotstar -class PixelDisplayFeatherWing: - """Base Class for DotStar and NeoPixel FeatherWings +class DotStarFeatherWing: + """Class representing a `DotStar FeatherWing + `_. The feather uses pins D13 and D11""" - def __init__(self): - self.rows = 0 - self.columns = 0 - self._display = None + def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): + """ + :param pin clock: The clock pin for the featherwing + :param pin data: The data pin for the featherwing + :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 + """ + self.rows = 6 + self.columns = 12 self._auto_write = True + self._display = dotstar.DotStar(clock, data, self.rows * self.columns, + brightness=brightness, auto_write=False) def __setitem__(self, indices, value): """ @@ -56,9 +63,8 @@ def __setitem__(self, indices, value): a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1 """ - if self._display is not None: - self._display[self._get_index(indices)] = value - self._update() + self._display[self._get_index(indices)] = value + self._update() def __getitem__(self, indices): """ @@ -67,10 +73,7 @@ def __getitem__(self, indices): a slice of DotStar indexes to retrieve a single int that specifies the DotStar index """ - if self._display is not None: - return self._display[self._get_index(indices)] - else: - return None + return self._display[self._get_index(indices)] def _get_index(self, indices): """ @@ -92,88 +95,6 @@ def _get_index(self, indices): else: raise ValueError('Index must be 1 or 2 number') - def _update(self): - """ - Update the Display automatically if auto_write is set to True - """ - if self._auto_write: - self._display.show() - - def _fill(self, color=0): - """ - Fills all of the Pixels with a color or unlit if empty. - """ - self._display.fill(color) - self._update() - - def _show(self): - """ - Update the Pixels. This is only needed if auto_write is set to False - This can be very useful for more advanced graphics effects. - """ - self._display.show() - - def _shift_right(self, rotate=False): - """ - Shift all pixels right - """ - for y in range(0, self.rows): - last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 - for x in range(self.columns - 1, 0, -1): - self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] - self._display[y * self.columns] = last_pixel - self._update() - - def _shift_left(self, rotate=False): - """ - Shift all pixels left - """ - for y in range(0, self.rows): - last_pixel = self._display[y * self.columns] if rotate else 0 - for x in range(0, self.columns - 1): - self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] - self._display[(y + 1) * self.columns - 1] = last_pixel - self._update() - - def _shift_up(self, rotate=False): - """ - Shift all pixels up - """ - for x in range(0, self.columns): - last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 - for y in range(self.rows - 1, 0, -1): - self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] - self._display[x] = last_pixel - self._update() - - def _shift_down(self, rotate=False): - """ - Shift all pixels down - """ - for x in range(0, self.columns): - last_pixel = self._display[x] if rotate else 0 - for y in range(0, self.rows - 1): - self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] - self._display[(self.rows - 1) * self.columns + x] = last_pixel - self._update() - -class DotStarFeatherWing(PixelDisplayFeatherWing): - """Class representing a `DotStar FeatherWing - `_. - - The feather uses pins D13 and D11""" - def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): - """ - :param pin clock: The clock pin for the featherwing - :param pin data: The data pin for the featherwing - :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 - """ - super().__init__() - self.rows = 6 - self.columns = 12 - self._display = dotstar.DotStar(clock, data, self.rows * self.columns, - brightness=brightness, auto_write=False) - def fill(self, color=0): """ Fills all of the DotStars with a color or unlit if empty. @@ -198,7 +119,8 @@ def fill(self, color=0): dotstar.fill() # Clear all lit DotStars """ - super()._fill(color) + self._display.fill(color) + self._update() def show(self): """ @@ -220,7 +142,7 @@ def show(self): dotstar.show() # Update the DotStars """ - super()._show() + self._display.show() def shift_right(self, rotate=False): """ @@ -253,7 +175,12 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - super()._shift_right(rotate) + for y in range(0, self.rows): + last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 + for x in range(self.columns - 1, 0, -1): + self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] + self._display[y * self.columns] = last_pixel + self._update() def shift_left(self, rotate=False): """ @@ -286,7 +213,12 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - super()._shift_left(rotate) + for y in range(0, self.rows): + last_pixel = self._display[y * self.columns] if rotate else 0 + for x in range(0, self.columns - 1): + self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] + self._display[(y + 1) * self.columns - 1] = last_pixel + self._update() def shift_up(self, rotate=False): """ @@ -319,7 +251,12 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - super()._shift_up(rotate) + for x in range(0, self.columns): + last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 + for y in range(self.rows - 1, 0, -1): + self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] + self._display[x] = last_pixel + self._update() def shift_down(self, rotate=False): """ @@ -352,7 +289,19 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - super()._shift_down(rotate) + for x in range(0, self.columns): + last_pixel = self._display[x] if rotate else 0 + for y in range(0, self.rows - 1): + self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] + self._display[(self.rows - 1) * self.columns + x] = last_pixel + self._update() + + def _update(self): + """ + Update the Display automatically if auto_write is set to True + """ + if self._auto_write: + self._display.show() @property def auto_write(self): diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 7e1b188..597905b 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,24 +33,26 @@ import board import neopixel -from adafruit_featherwing.dotstar_featherwing import PixelDisplayFeatherWing +from adafruit_featherwing.dotstar_featherwing import DotStarFeatherWing -class NeoPixelFeatherWing(PixelDisplayFeatherWing): +class NeoPixelFeatherWing(DotStarFeatherWing): """Class representing a `NeoPixel FeatherWing `_. The feather uses pins D6 by default""" + #pylint: disable-msg=super-init-not-called def __init__(self, pixel_pin=board.D6, brightness=0.1): """ :param pin pixel_pin: The pin for the featherwing :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 """ - super().__init__() self.rows = 4 self.columns = 8 + self._auto_write = True self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, brightness=brightness, auto_write=False, pixel_order=neopixel.GRB) + #pylint: enable-msg=super-init-not-called def fill(self, color=0): """ @@ -74,7 +76,7 @@ def fill(self, color=0): neopixel.fill() # Clear all lit NeoPixels """ - super()._fill(color) + super().fill(color) def show(self): """ @@ -96,7 +98,7 @@ def show(self): neopixel.show() # Update the NeoPixels """ - super()._show() + super().show() def shift_right(self, rotate=False): """ @@ -129,7 +131,7 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - super()._shift_right(rotate) + super().shift_right(rotate) def shift_left(self, rotate=False): """ @@ -162,7 +164,7 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - super()._shift_left(rotate) + super().shift_left(rotate) def shift_up(self, rotate=False): """ @@ -195,7 +197,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - super()._shift_down(rotate) # Up and down are reversed + super().shift_down(rotate) # Up and down are reversed def shift_down(self, rotate=False): """ @@ -228,7 +230,7 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - super()._shift_up(rotate) # Up and down are reversed + super().shift_up(rotate) # Up and down are reversed @property def auto_write(self): @@ -254,12 +256,7 @@ def auto_write(self): neopixel.show() # Update the NeoPixels """ - return self._auto_write - - @auto_write.setter - def auto_write(self, write): - if isinstance(write, bool): - self._auto_write = write + return super().auto_write @property def brightness(self): @@ -283,9 +280,4 @@ def brightness(self): neopixel.brightness = 0.3 """ - return self._display.brightness - - @brightness.setter - def brightness(self, brightness): - self._display.brightness = min(max(brightness, 0.0), 1.0) - self._update() + return super().brightness \ No newline at end of file diff --git a/docs/examples.rst b/docs/examples.rst index 869656f..757d8e4 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -26,7 +26,7 @@ Ensure your device works with this simple test. Other tests ------------ -.. literalinclude:: ../examples/featherwing_dotstar_palettetest.py +.. literalinclude:: ../examples/featherwing_dotstar_palette_example.py :caption: examples/featherwing_dotstar_palette_example.py :linenos: From bb1bf8236423f701c97329c2a4122685ca691376 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Tue, 5 Feb 2019 19:46:46 -0800 Subject: [PATCH 05/12] Final Linting --- adafruit_featherwing/neopixel_featherwing.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 597905b..027d025 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -54,6 +54,7 @@ def __init__(self, pixel_pin=board.D6, brightness=0.1): pixel_order=neopixel.GRB) #pylint: enable-msg=super-init-not-called + #pylint: disable-msg=useless-super-delegation def fill(self, color=0): """ Fills all of the NeoPixels with a color or unlit if empty. @@ -165,6 +166,7 @@ def shift_left(self, rotate=False): """ super().shift_left(rotate) + #pylint: enable-msg=useless-super-delegation def shift_up(self, rotate=False): """ @@ -280,4 +282,4 @@ def brightness(self): neopixel.brightness = 0.3 """ - return super().brightness \ No newline at end of file + return super().brightness From e7f836d89ee31722fd5ffcbdf4196e45d2fab121 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Wed, 6 Feb 2019 11:35:24 -0800 Subject: [PATCH 06/12] Changed display to matrix --- adafruit_featherwing/dotstar_featherwing.py | 42 ++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index 2016a2a..f32e4c2 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -48,7 +48,7 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): self.rows = 6 self.columns = 12 self._auto_write = True - self._display = dotstar.DotStar(clock, data, self.rows * self.columns, + self._matrix = dotstar.DotStar(clock, data, self.rows * self.columns, brightness=brightness, auto_write=False) def __setitem__(self, indices, value): @@ -63,7 +63,7 @@ def __setitem__(self, indices, value): a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1 """ - self._display[self._get_index(indices)] = value + self._matrix[self._get_index(indices)] = value self._update() def __getitem__(self, indices): @@ -73,7 +73,7 @@ def __getitem__(self, indices): a slice of DotStar indexes to retrieve a single int that specifies the DotStar index """ - return self._display[self._get_index(indices)] + return self._matrix[self._get_index(indices)] def _get_index(self, indices): """ @@ -119,7 +119,7 @@ def fill(self, color=0): dotstar.fill() # Clear all lit DotStars """ - self._display.fill(color) + self._matrix.fill(color) self._update() def show(self): @@ -142,7 +142,7 @@ def show(self): dotstar.show() # Update the DotStars """ - self._display.show() + self._matrix.show() def shift_right(self, rotate=False): """ @@ -176,10 +176,10 @@ def shift_right(self, rotate=False): """ for y in range(0, self.rows): - last_pixel = self._display[(y + 1) * self.columns - 1] if rotate else 0 + last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 for x in range(self.columns - 1, 0, -1): - self._display[y * self.columns + x] = self._display[y * self.columns + x - 1] - self._display[y * self.columns] = last_pixel + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x - 1] + self._matrix[y * self.columns] = last_pixel self._update() def shift_left(self, rotate=False): @@ -214,10 +214,10 @@ def shift_left(self, rotate=False): """ for y in range(0, self.rows): - last_pixel = self._display[y * self.columns] if rotate else 0 + last_pixel = self._matrix[y * self.columns] if rotate else 0 for x in range(0, self.columns - 1): - self._display[y * self.columns + x] = self._display[y * self.columns + x + 1] - self._display[(y + 1) * self.columns - 1] = last_pixel + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x + 1] + self._matrix[(y + 1) * self.columns - 1] = last_pixel self._update() def shift_up(self, rotate=False): @@ -252,10 +252,10 @@ def shift_up(self, rotate=False): """ for x in range(0, self.columns): - last_pixel = self._display[(self.rows - 1) * self.columns + x] if rotate else 0 + last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 for y in range(self.rows - 1, 0, -1): - self._display[y * self.columns + x] = self._display[(y - 1) * self.columns + x] - self._display[x] = last_pixel + self._matrix[y * self.columns + x] = self._matrix[(y - 1) * self.columns + x] + self._matrix[x] = last_pixel self._update() def shift_down(self, rotate=False): @@ -290,10 +290,10 @@ def shift_down(self, rotate=False): """ for x in range(0, self.columns): - last_pixel = self._display[x] if rotate else 0 + last_pixel = self._matrix[x] if rotate else 0 for y in range(0, self.rows - 1): - self._display[y * self.columns + x] = self._display[(y + 1) * self.columns + x] - self._display[(self.rows - 1) * self.columns + x] = last_pixel + self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] + self._matrix[(self.rows - 1) * self.columns + x] = last_pixel self._update() def _update(self): @@ -301,7 +301,7 @@ def _update(self): Update the Display automatically if auto_write is set to True """ if self._auto_write: - self._display.show() + self._matrix.show() @property def auto_write(self): @@ -356,9 +356,9 @@ def brightness(self): dotstar.brightness = 0.3 """ - return self._display.brightness + return self._matrix.brightness @brightness.setter def brightness(self, brightness): - self._display.brightness = min(max(brightness, 0.0), 1.0) - self._update() + self._matrix.brightness = min(max(brightness, 0.0), 1.0) + self._update() \ No newline at end of file From aef49c4a617132f0fae6ac137da963c17c49fe2f Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Wed, 6 Feb 2019 11:37:56 -0800 Subject: [PATCH 07/12] Linting --- adafruit_featherwing/dotstar_featherwing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index f32e4c2..b79dbfb 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -49,7 +49,7 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): self.columns = 12 self._auto_write = True self._matrix = dotstar.DotStar(clock, data, self.rows * self.columns, - brightness=brightness, auto_write=False) + brightness=brightness, auto_write=False) def __setitem__(self, indices, value): """ @@ -361,4 +361,4 @@ def brightness(self): @brightness.setter def brightness(self, brightness): self._matrix.brightness = min(max(brightness, 0.0), 1.0) - self._update() \ No newline at end of file + self._update() From c9b85824ceb87b3e55bf2558fdfcd74fb31bd471 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Wed, 6 Feb 2019 20:11:00 -0800 Subject: [PATCH 08/12] Neopixels and DotStars using Base Class --- adafruit_featherwing/dotstar_featherwing.py | 201 ++++++++++++++----- adafruit_featherwing/neopixel_featherwing.py | 42 ++-- 2 files changed, 178 insertions(+), 65 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index b79dbfb..830a180 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -34,22 +34,15 @@ import board import adafruit_dotstar as dotstar -class DotStarFeatherWing: - """Class representing a `DotStar FeatherWing - `_. +class PixelDisplayFeatherWing: + """Base Class for DotStar and NeoPixel FeatherWings The feather uses pins D13 and D11""" - def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): - """ - :param pin clock: The clock pin for the featherwing - :param pin data: The data pin for the featherwing - :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 - """ - self.rows = 6 - self.columns = 12 + def __init__(self): + self.rows = 0 + self.columns = 0 + self._matrix = None self._auto_write = True - self._matrix = dotstar.DotStar(clock, data, self.rows * self.columns, - brightness=brightness, auto_write=False) def __setitem__(self, indices, value): """ @@ -95,6 +88,148 @@ def _get_index(self, indices): else: raise ValueError('Index must be 1 or 2 number') + def _update(self): + """ + Update the Display automatically if auto_write is set to True + """ + if self._auto_write: + self._matrix.show() + + def _fill(self, color=0): + """ + Fills all of the Pixels with a color or unlit if empty. + """ + self._matrix.fill(color) + self._update() + + def _show(self): + """ + Update the Pixels. This is only needed if auto_write is set to False + This can be very useful for more advanced graphics effects. + """ + self._matrix.show() + + def _shift_right(self, rotate=False): + """ + Shift all pixels right + """ + for y in range(0, self.rows): + last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 + for x in range(self.columns - 1, 0, -1): + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x - 1] + self._matrix[y * self.columns] = last_pixel + self._update() + + def _shift_left(self, rotate=False): + """ + Shift all pixels left + """ + for y in range(0, self.rows): + last_pixel = self._matrix[y * self.columns] if rotate else 0 + for x in range(0, self.columns - 1): + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x + 1] + self._matrix[(y + 1) * self.columns - 1] = last_pixel + self._update() + + def _shift_up(self, rotate=False): + """ + Shift all pixels up + """ + for x in range(0, self.columns): + last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 + for y in range(self.rows - 1, 0, -1): + self._matrix[y * self.columns + x] = self._matrix[(y - 1) * self.columns + x] + self._matrix[x] = last_pixel + self._update() + + def _shift_down(self, rotate=False): + """ + Shift all pixels down + """ + for x in range(0, self.columns): + last_pixel = self._matrix[x] if rotate else 0 + for y in range(0, self.rows - 1): + self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] + self._matrix[(self.rows - 1) * self.columns + x] = last_pixel + self._update() + + @property + def auto_write(self): + """ + Whether or not we are automatically updating + If set to false, be sure to call show() to update + + This lights DotStars with and without auto_write + + .. code-block:: python + + import time + from adafruit_featherwing import dotstar_featherwing + + dotstar = dotstar_featherwing.DotStarFeatherWing() + dotstar.fill() # Clear any lit Dotstars + dotstar[0, 0] = (255, 255, 255) # Set White + time.sleep(1) + + dotstar.auto_write = False + dotstar[1, 0] = (255, 255, 255) # Set White + time.sleep(1) + dotstar.show() # Update the DotStars + + """ + return self._auto_write + + @auto_write.setter + def auto_write(self, write): + if isinstance(write, bool): + self._auto_write = write + + @property + def brightness(self): + """ + Overall brightness of the display + + This example changes the brightness + + .. code-block:: python + + import time + from adafruit_featherwing import dotstar_featherwing + + dotstar = dotstar_featherwing.DotStarFeatherWing() + dotstar.brightness = 0 + dotstar.fill(0xFFFFFF) + for i in range(0, 6): + dotstar.brightness = (i / 10) + time.sleep(.2) + + dotstar.brightness = 0.3 + + """ + return self._matrix.brightness + + @brightness.setter + def brightness(self, brightness): + self._matrix.brightness = min(max(brightness, 0.0), 1.0) + self._update() + +class DotStarFeatherWing(PixelDisplayFeatherWing): + """Class representing a `DotStar FeatherWing + `_. + + The feather uses pins D13 and D11""" + def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): + """ + :param pin clock: The clock pin for the featherwing + :param pin data: The data pin for the featherwing + :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 + """ + super().__init__() + self.rows = 6 + self.columns = 12 + self._matrix = dotstar.DotStar(clock, data, self.rows * self.columns, + brightness=brightness, auto_write=False) + def fill(self, color=0): """ Fills all of the DotStars with a color or unlit if empty. @@ -119,8 +254,7 @@ def fill(self, color=0): dotstar.fill() # Clear all lit DotStars """ - self._matrix.fill(color) - self._update() + super()._fill(color) def show(self): """ @@ -142,7 +276,7 @@ def show(self): dotstar.show() # Update the DotStars """ - self._matrix.show() + super()._show() def shift_right(self, rotate=False): """ @@ -175,12 +309,7 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - for y in range(0, self.rows): - last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 - for x in range(self.columns - 1, 0, -1): - self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x - 1] - self._matrix[y * self.columns] = last_pixel - self._update() + super()._shift_right(rotate) def shift_left(self, rotate=False): """ @@ -213,12 +342,7 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - for y in range(0, self.rows): - last_pixel = self._matrix[y * self.columns] if rotate else 0 - for x in range(0, self.columns - 1): - self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x + 1] - self._matrix[(y + 1) * self.columns - 1] = last_pixel - self._update() + super()._shift_left(rotate) def shift_up(self, rotate=False): """ @@ -251,12 +375,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - for x in range(0, self.columns): - last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 - for y in range(self.rows - 1, 0, -1): - self._matrix[y * self.columns + x] = self._matrix[(y - 1) * self.columns + x] - self._matrix[x] = last_pixel - self._update() + super()._shift_up(rotate) def shift_down(self, rotate=False): """ @@ -289,19 +408,7 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - for x in range(0, self.columns): - last_pixel = self._matrix[x] if rotate else 0 - for y in range(0, self.rows - 1): - self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] - self._matrix[(self.rows - 1) * self.columns + x] = last_pixel - self._update() - - def _update(self): - """ - Update the Display automatically if auto_write is set to True - """ - if self._auto_write: - self._matrix.show() + super()._shift_down(rotate) @property def auto_write(self): diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 027d025..043ee02 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,28 +33,25 @@ import board import neopixel -from adafruit_featherwing.dotstar_featherwing import DotStarFeatherWing +from adafruit_featherwing.dotstar_featherwing import PixelDisplayFeatherWing -class NeoPixelFeatherWing(DotStarFeatherWing): +class NeoPixelFeatherWing(PixelDisplayFeatherWing): """Class representing a `NeoPixel FeatherWing `_. The feather uses pins D6 by default""" - #pylint: disable-msg=super-init-not-called def __init__(self, pixel_pin=board.D6, brightness=0.1): """ :param pin pixel_pin: The pin for the featherwing :param float brightness: Optional brightness (0.0-1.0) that defaults to 1.0 """ + super().__init__() self.rows = 4 self.columns = 8 - self._auto_write = True - self._display = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, - brightness=brightness, auto_write=False, - pixel_order=neopixel.GRB) - #pylint: enable-msg=super-init-not-called + self._matrix = neopixel.NeoPixel(pixel_pin, self.rows * self.columns, + brightness=brightness, auto_write=False, + pixel_order=neopixel.GRB) - #pylint: disable-msg=useless-super-delegation def fill(self, color=0): """ Fills all of the NeoPixels with a color or unlit if empty. @@ -77,7 +74,7 @@ def fill(self, color=0): neopixel.fill() # Clear all lit NeoPixels """ - super().fill(color) + super()._fill(color) def show(self): """ @@ -99,7 +96,7 @@ def show(self): neopixel.show() # Update the NeoPixels """ - super().show() + super()._show() def shift_right(self, rotate=False): """ @@ -132,7 +129,7 @@ def shift_right(self, rotate=False): time.sleep(.1) """ - super().shift_right(rotate) + super()._shift_right(rotate) def shift_left(self, rotate=False): """ @@ -165,8 +162,7 @@ def shift_left(self, rotate=False): time.sleep(.1) """ - super().shift_left(rotate) - #pylint: enable-msg=useless-super-delegation + super()._shift_left(rotate) def shift_up(self, rotate=False): """ @@ -199,7 +195,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - super().shift_down(rotate) # Up and down are reversed + super()._shift_down(rotate) # Up and down are reversed def shift_down(self, rotate=False): """ @@ -232,7 +228,7 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - super().shift_up(rotate) # Up and down are reversed + super()._shift_up(rotate) # Up and down are reversed @property def auto_write(self): @@ -258,7 +254,12 @@ def auto_write(self): neopixel.show() # Update the NeoPixels """ - return super().auto_write + return self._auto_write + + @auto_write.setter + def auto_write(self, write): + if isinstance(write, bool): + self._auto_write = write @property def brightness(self): @@ -282,4 +283,9 @@ def brightness(self): neopixel.brightness = 0.3 """ - return super().brightness + return self._matrix.brightness + + @brightness.setter + def brightness(self, brightness): + self._matrix.brightness = min(max(brightness, 0.0), 1.0) + self._update() From 08b966273e962c0e7b45ad7783a3d64ee02cb9c2 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Wed, 6 Feb 2019 20:24:07 -0800 Subject: [PATCH 09/12] Fixed Base Class --- adafruit_featherwing/dotstar_featherwing.py | 64 +------------------- adafruit_featherwing/neopixel_featherwing.py | 2 +- 2 files changed, 3 insertions(+), 63 deletions(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index 830a180..c76cbde 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -34,7 +34,7 @@ import board import adafruit_dotstar as dotstar -class PixelDisplayFeatherWing: +class PixelMatrixFeatherWing: """Base Class for DotStar and NeoPixel FeatherWings The feather uses pins D13 and D11""" @@ -153,67 +153,7 @@ def _shift_down(self, rotate=False): self._matrix[(self.rows - 1) * self.columns + x] = last_pixel self._update() - @property - def auto_write(self): - """ - Whether or not we are automatically updating - If set to false, be sure to call show() to update - - This lights DotStars with and without auto_write - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.fill() # Clear any lit Dotstars - dotstar[0, 0] = (255, 255, 255) # Set White - time.sleep(1) - - dotstar.auto_write = False - dotstar[1, 0] = (255, 255, 255) # Set White - time.sleep(1) - dotstar.show() # Update the DotStars - - """ - return self._auto_write - - @auto_write.setter - def auto_write(self, write): - if isinstance(write, bool): - self._auto_write = write - - @property - def brightness(self): - """ - Overall brightness of the display - - This example changes the brightness - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.brightness = 0 - dotstar.fill(0xFFFFFF) - for i in range(0, 6): - dotstar.brightness = (i / 10) - time.sleep(.2) - - dotstar.brightness = 0.3 - - """ - return self._matrix.brightness - - @brightness.setter - def brightness(self, brightness): - self._matrix.brightness = min(max(brightness, 0.0), 1.0) - self._update() - -class DotStarFeatherWing(PixelDisplayFeatherWing): +class DotStarFeatherWing(PixelMatrixFeatherWing): """Class representing a `DotStar FeatherWing `_. diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 043ee02..1330591 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -35,7 +35,7 @@ import neopixel from adafruit_featherwing.dotstar_featherwing import PixelDisplayFeatherWing -class NeoPixelFeatherWing(PixelDisplayFeatherWing): +class NeoPixelFeatherWing(PixelMatrixFeatherWing): """Class representing a `NeoPixel FeatherWing `_. From 570bfe9716f317bf809d238ba1827c0d21350033 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Wed, 6 Feb 2019 21:01:01 -0800 Subject: [PATCH 10/12] Disabled bugged Lint Messages --- adafruit_featherwing/dotstar_featherwing.py | 1 + adafruit_featherwing/neopixel_featherwing.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index c76cbde..6b26f90 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -33,6 +33,7 @@ import board import adafruit_dotstar as dotstar +#pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation class PixelMatrixFeatherWing: """Base Class for DotStar and NeoPixel FeatherWings diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 1330591..26d4aa4 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,7 +33,8 @@ import board import neopixel -from adafruit_featherwing.dotstar_featherwing import PixelDisplayFeatherWing +from adafruit_featherwing.dotstar_featherwing import PixelMatrixFeatherWing +#pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation class NeoPixelFeatherWing(PixelMatrixFeatherWing): """Class representing a `NeoPixel FeatherWing From 20f1c9b0b44a94f52ffc5148ba07e954eef1ac13 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Thu, 7 Feb 2019 19:04:05 -0800 Subject: [PATCH 11/12] Moved PixelMatrix to separate class --- adafruit_featherwing/dotstar_featherwing.py | 121 +------------- adafruit_featherwing/neopixel_featherwing.py | 3 +- .../pixelmatrix_featherwing.py | 154 ++++++++++++++++++ 3 files changed, 156 insertions(+), 122 deletions(-) create mode 100644 adafruit_featherwing/pixelmatrix_featherwing.py diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index 6b26f90..f494647 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -33,126 +33,7 @@ import board import adafruit_dotstar as dotstar -#pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation - -class PixelMatrixFeatherWing: - """Base Class for DotStar and NeoPixel FeatherWings - - The feather uses pins D13 and D11""" - def __init__(self): - self.rows = 0 - self.columns = 0 - self._matrix = None - self._auto_write = True - - def __setitem__(self, indices, value): - """ - indices can be one of three things: - x and y ints that are calculated to the DotStar index - a slice of DotStar indexes with a set of values that match the slice - a single int that specifies the DotStar index - value can be one of three things: - a (r,g,b) list/tuple - a (r,g,b, brightness) list/tuple - a single, longer int that contains RGB values, like 0xFFFFFF - brightness, if specified should be a float 0-1 - """ - self._matrix[self._get_index(indices)] = value - self._update() - - def __getitem__(self, indices): - """ - indices can be one of three things: - x and y ints that are calculated to the DotStar index - a slice of DotStar indexes to retrieve - a single int that specifies the DotStar index - """ - return self._matrix[self._get_index(indices)] - - def _get_index(self, indices): - """ - Figure out which DotStar to address based on what was passed in - """ - if isinstance(indices, int): - if not 0 <= indices < self.rows * self.columns: - raise ValueError('The index of {} is out of range'.format(indices)) - return indices - elif isinstance(indices, slice): - return indices - elif len(indices) == 2: - x, y = indices - if not 0 <= x < self.columns: - raise ValueError('The X value of {} is out of range'.format(x)) - if not 0 <= y < self.rows: - raise ValueError('The Y value of {} is out of range'.format(y)) - return y * self.columns + x - else: - raise ValueError('Index must be 1 or 2 number') - - def _update(self): - """ - Update the Display automatically if auto_write is set to True - """ - if self._auto_write: - self._matrix.show() - - def _fill(self, color=0): - """ - Fills all of the Pixels with a color or unlit if empty. - """ - self._matrix.fill(color) - self._update() - - def _show(self): - """ - Update the Pixels. This is only needed if auto_write is set to False - This can be very useful for more advanced graphics effects. - """ - self._matrix.show() - - def _shift_right(self, rotate=False): - """ - Shift all pixels right - """ - for y in range(0, self.rows): - last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 - for x in range(self.columns - 1, 0, -1): - self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x - 1] - self._matrix[y * self.columns] = last_pixel - self._update() - - def _shift_left(self, rotate=False): - """ - Shift all pixels left - """ - for y in range(0, self.rows): - last_pixel = self._matrix[y * self.columns] if rotate else 0 - for x in range(0, self.columns - 1): - self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x + 1] - self._matrix[(y + 1) * self.columns - 1] = last_pixel - self._update() - - def _shift_up(self, rotate=False): - """ - Shift all pixels up - """ - for x in range(0, self.columns): - last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 - for y in range(self.rows - 1, 0, -1): - self._matrix[y * self.columns + x] = self._matrix[(y - 1) * self.columns + x] - self._matrix[x] = last_pixel - self._update() - - def _shift_down(self, rotate=False): - """ - Shift all pixels down - """ - for x in range(0, self.columns): - last_pixel = self._matrix[x] if rotate else 0 - for y in range(0, self.rows - 1): - self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] - self._matrix[(self.rows - 1) * self.columns + x] = last_pixel - self._update() +from adafruit_featherwing.pixelmatrix_featherwing import PixelMatrixFeatherWing class DotStarFeatherWing(PixelMatrixFeatherWing): """Class representing a `DotStar FeatherWing diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 26d4aa4..145ad0b 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,8 +33,7 @@ import board import neopixel -from adafruit_featherwing.dotstar_featherwing import PixelMatrixFeatherWing -#pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation +from adafruit_featherwing.pixelmatrix_featherwing import PixelMatrixFeatherWing class NeoPixelFeatherWing(PixelMatrixFeatherWing): """Class representing a `NeoPixel FeatherWing diff --git a/adafruit_featherwing/pixelmatrix_featherwing.py b/adafruit_featherwing/pixelmatrix_featherwing.py new file mode 100644 index 0000000..44c7068 --- /dev/null +++ b/adafruit_featherwing/pixelmatrix_featherwing.py @@ -0,0 +1,154 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Melissa LeBlanc-Williams for Adafruit Industries LLC +# +# 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. +""" +`adafruit_featherwing.pixelmatrix_featherwing` +==================================================== + +Base Class for the `NeoPixel FeatherWing ` and +`DotStar FeatherWing `_. + +* Author(s): Melissa LeBlanc-Williams +""" + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_FeatherWing.git" + +#pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation + +class PixelMatrixFeatherWing: + """Base Class for DotStar and NeoPixel FeatherWings + + The feather uses pins D13 and D11""" + def __init__(self): + self.rows = 0 + self.columns = 0 + self._matrix = None + self._auto_write = True + + def __setitem__(self, indices, value): + """ + indices can be one of three things: + x and y ints that are calculated to the DotStar index + a slice of DotStar indexes with a set of values that match the slice + a single int that specifies the DotStar index + value can be one of three things: + a (r,g,b) list/tuple + a (r,g,b, brightness) list/tuple + a single, longer int that contains RGB values, like 0xFFFFFF + brightness, if specified should be a float 0-1 + """ + self._matrix[self._get_index(indices)] = value + self._update() + + def __getitem__(self, indices): + """ + indices can be one of three things: + x and y ints that are calculated to the DotStar index + a slice of DotStar indexes to retrieve + a single int that specifies the DotStar index + """ + return self._matrix[self._get_index(indices)] + + def _get_index(self, indices): + """ + Figure out which DotStar to address based on what was passed in + """ + if isinstance(indices, int): + if not 0 <= indices < self.rows * self.columns: + raise ValueError('The index of {} is out of range'.format(indices)) + return indices + elif isinstance(indices, slice): + return indices + elif len(indices) == 2: + x, y = indices + if not 0 <= x < self.columns: + raise ValueError('The X value of {} is out of range'.format(x)) + if not 0 <= y < self.rows: + raise ValueError('The Y value of {} is out of range'.format(y)) + return y * self.columns + x + else: + raise ValueError('Index must be 1 or 2 number') + + def _update(self): + """ + Update the Display automatically if auto_write is set to True + """ + if self._auto_write: + self._matrix.show() + + def _fill(self, color=0): + """ + Fills all of the Pixels with a color or unlit if empty. + """ + self._matrix.fill(color) + self._update() + + def _show(self): + """ + Update the Pixels. This is only needed if auto_write is set to False + This can be very useful for more advanced graphics effects. + """ + self._matrix.show() + + def _shift_right(self, rotate=False): + """ + Shift all pixels right + """ + for y in range(0, self.rows): + last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 + for x in range(self.columns - 1, 0, -1): + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x - 1] + self._matrix[y * self.columns] = last_pixel + self._update() + + def _shift_left(self, rotate=False): + """ + Shift all pixels left + """ + for y in range(0, self.rows): + last_pixel = self._matrix[y * self.columns] if rotate else 0 + for x in range(0, self.columns - 1): + self._matrix[y * self.columns + x] = self._matrix[y * self.columns + x + 1] + self._matrix[(y + 1) * self.columns - 1] = last_pixel + self._update() + + def _shift_up(self, rotate=False): + """ + Shift all pixels up + """ + for x in range(0, self.columns): + last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 + for y in range(self.rows - 1, 0, -1): + self._matrix[y * self.columns + x] = self._matrix[(y - 1) * self.columns + x] + self._matrix[x] = last_pixel + self._update() + + def _shift_down(self, rotate=False): + """ + Shift all pixels down + """ + for x in range(0, self.columns): + last_pixel = self._matrix[x] if rotate else 0 + for y in range(0, self.rows - 1): + self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] + self._matrix[(self.rows - 1) * self.columns + x] = last_pixel + self._update() From 41627375a2f2182aae55f8bacdb67ee90ba04aee Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Mon, 11 Feb 2019 16:02:48 -0800 Subject: [PATCH 12/12] Removed a lot of the overriding functions --- adafruit_featherwing/dotstar_featherwing.py | 244 +----------------- adafruit_featherwing/neopixel_featherwing.py | 180 +------------ ...elmatrix_featherwing.py => pixelmatrix.py} | 52 +++- 3 files changed, 50 insertions(+), 426 deletions(-) rename adafruit_featherwing/{pixelmatrix_featherwing.py => pixelmatrix.py} (80%) mode change 100644 => 100755 diff --git a/adafruit_featherwing/dotstar_featherwing.py b/adafruit_featherwing/dotstar_featherwing.py index f494647..0947ac0 100755 --- a/adafruit_featherwing/dotstar_featherwing.py +++ b/adafruit_featherwing/dotstar_featherwing.py @@ -33,9 +33,9 @@ import board import adafruit_dotstar as dotstar -from adafruit_featherwing.pixelmatrix_featherwing import PixelMatrixFeatherWing +from adafruit_featherwing.pixelmatrix import PixelMatrix -class DotStarFeatherWing(PixelMatrixFeatherWing): +class DotStarFeatherWing(PixelMatrix): """Class representing a `DotStar FeatherWing `_. @@ -51,243 +51,3 @@ def __init__(self, clock=board.D13, data=board.D11, brightness=0.2): self.columns = 12 self._matrix = dotstar.DotStar(clock, data, self.rows * self.columns, brightness=brightness, auto_write=False) - - def fill(self, color=0): - """ - Fills all of the DotStars with a color or unlit if empty. - - :param color: (Optional) The text or number to display (default=0) - :type color: list/tuple or int - - This example shows various ways of using the fill() function - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.fill((255, 255, 255)) # Fill White - time.sleep(1) - dotstar.fill((255, 255, 255, 0.5)) # Fill White Half Brightness - time.sleep(1) - dotstar.fill(0xFF0000) # Fill Red - time.sleep(1) - dotstar.fill() # Clear all lit DotStars - - """ - super()._fill(color) - - def show(self): - """ - Update the DotStars. This is only needed if auto_write is set to False - This can be very useful for more advanced graphics effects. - - This example changes the blink rate and prints out the current setting - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.fill() # Clear any lit Dotstars - dotstar.auto_write = False - dotstar[0, 0] = (255, 255, 255) # Set White - time.sleep(1) - dotstar.show() # Update the DotStars - - """ - super()._show() - - def shift_right(self, rotate=False): - """ - Shift all pixels right - - :param rotate: (Optional) Rotate the shifted pixels to the left side (default=False) - - This example shifts 2 pixels to the right - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - - # Draw Red and Green Pixels - dotstar[5, 3] = (255, 0, 0) - dotstar[6, 3] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, dotstar.columns - 1): - dotstar.shift_right(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, dotstar.columns - 1): - dotstar.shift_right() - time.sleep(.1) - - """ - super()._shift_right(rotate) - - def shift_left(self, rotate=False): - """ - Shift all pixels left - - :param rotate: (Optional) Rotate the shifted pixels to the right side (default=False) - - This example shifts 2 pixels to the left - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - - # Draw Red and Green Pixels - dotstar[5, 3] = (255, 0, 0) - dotstar[6, 3] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, dotstar.columns - 1): - dotstar.shift_left(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, dotstar.columns - 1): - dotstar.shift_left() - time.sleep(.1) - - """ - super()._shift_left(rotate) - - def shift_up(self, rotate=False): - """ - Shift all pixels up - - :param rotate: (Optional) Rotate the shifted pixels to bottom (default=False) - - This example shifts 2 pixels up - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - - # Draw Red and Green Pixels - dotstar[5, 3] = (255, 0, 0) - dotstar[6, 3] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, dotstar.rows - 1): - dotstar.shift_up(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, dotstar.rows - 1): - dotstar.shift_up() - time.sleep(.1) - - """ - super()._shift_up(rotate) - - def shift_down(self, rotate=False): - """ - Shift all pixels down - - :param rotate: (Optional) Rotate the shifted pixels to top (default=False) - - This example shifts 2 pixels down - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - - # Draw Red and Green Pixels - dotstar[5, 3] = (255, 0, 0) - dotstar[6, 3] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, dotstar.rows - 1): - dotstar.shift_down(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, dotstar.rows - 1): - dotstar.shift_down() - time.sleep(.1) - - """ - super()._shift_down(rotate) - - @property - def auto_write(self): - """ - Whether or not we are automatically updating - If set to false, be sure to call show() to update - - This lights DotStars with and without auto_write - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.fill() # Clear any lit Dotstars - dotstar[0, 0] = (255, 255, 255) # Set White - time.sleep(1) - - dotstar.auto_write = False - dotstar[1, 0] = (255, 255, 255) # Set White - time.sleep(1) - dotstar.show() # Update the DotStars - - """ - return self._auto_write - - @auto_write.setter - def auto_write(self, write): - if isinstance(write, bool): - self._auto_write = write - - @property - def brightness(self): - """ - Overall brightness of the display - - This example changes the brightness - - .. code-block:: python - - import time - from adafruit_featherwing import dotstar_featherwing - - dotstar = dotstar_featherwing.DotStarFeatherWing() - dotstar.brightness = 0 - dotstar.fill(0xFFFFFF) - for i in range(0, 6): - dotstar.brightness = (i / 10) - time.sleep(.2) - - dotstar.brightness = 0.3 - - """ - return self._matrix.brightness - - @brightness.setter - def brightness(self, brightness): - self._matrix.brightness = min(max(brightness, 0.0), 1.0) - self._update() diff --git a/adafruit_featherwing/neopixel_featherwing.py b/adafruit_featherwing/neopixel_featherwing.py index 145ad0b..fb8da48 100755 --- a/adafruit_featherwing/neopixel_featherwing.py +++ b/adafruit_featherwing/neopixel_featherwing.py @@ -33,9 +33,9 @@ import board import neopixel -from adafruit_featherwing.pixelmatrix_featherwing import PixelMatrixFeatherWing +from adafruit_featherwing.pixelmatrix import PixelMatrix -class NeoPixelFeatherWing(PixelMatrixFeatherWing): +class NeoPixelFeatherWing(PixelMatrix): """Class representing a `NeoPixel FeatherWing `_. @@ -52,118 +52,6 @@ def __init__(self, pixel_pin=board.D6, brightness=0.1): brightness=brightness, auto_write=False, pixel_order=neopixel.GRB) - def fill(self, color=0): - """ - Fills all of the NeoPixels with a color or unlit if empty. - - :param color: (Optional) The text or number to display (default=0) - :type color: list/tuple or int - - This example shows various ways of using the fill() function - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - neopixel.fill((255, 255, 255)) # Fill White - time.sleep(1) - neopixel.fill(0xFF0000) # Fill Red - time.sleep(1) - neopixel.fill() # Clear all lit NeoPixels - - """ - super()._fill(color) - - def show(self): - """ - Update the NeoPixels. This is only needed if auto_write is set to False - This can be very useful for more advanced graphics effects. - - This example changes the blink rate and prints out the current setting - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - neopixel.fill() # Clear any lit NeoPixels - neopixel.auto_write = False - neopixel[0, 0] = (255, 255, 255) # Set White - time.sleep(1) - neopixel.show() # Update the NeoPixels - - """ - super()._show() - - def shift_right(self, rotate=False): - """ - Shift all pixels left - - :param rotate: (Optional) Rotate the shifted pixels to the left side (default=False) - - This example shifts 2 pixels to the right - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - - # Draw Red and Green Pixels - neopixel[4, 1] = (255, 0, 0) - neopixel[5, 1] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, neopixel.columns - 1): - neopixel.shift_right(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, neopixel.columns - 1): - neopixel.shift_right() - time.sleep(.1) - - """ - super()._shift_right(rotate) - - def shift_left(self, rotate=False): - """ - Shift all pixels left - - :param rotate: (Optional) Rotate the shifted pixels to the right side (default=False) - - This example shifts 2 pixels to the left - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - - # Draw Red and Green Pixels - neopixel[4, 1] = (255, 0, 0) - neopixel[5, 1] = (0, 255, 0) - - # Rotate it off the screen - for i in range(0, neopixel.columns - 1): - neopixel.shift_left(True) - time.sleep(.1) - - time.sleep(1) - # Shift it off the screen - for i in range(0, neopixel.columns - 1): - neopixel.shift_left() - time.sleep(.1) - - """ - super()._shift_left(rotate) - def shift_up(self, rotate=False): """ Shift all pixels up @@ -195,7 +83,7 @@ def shift_up(self, rotate=False): time.sleep(.1) """ - super()._shift_down(rotate) # Up and down are reversed + super().shift_down(rotate) # Up and down are reversed def shift_down(self, rotate=False): """ @@ -228,64 +116,4 @@ def shift_down(self, rotate=False): time.sleep(.1) """ - super()._shift_up(rotate) # Up and down are reversed - - @property - def auto_write(self): - """ - Whether or not we are automatically updating - If set to false, be sure to call show() to update - - This lights NeoPixels with and without auto_write - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - neopixel.fill() # Clear any lit NeoPixels - neopixel[0, 0] = (255, 255, 255) # Set White - time.sleep(1) - - neopixel.auto_write = False - neopixel[1, 0] = (255, 255, 255) # Set White - time.sleep(1) - neopixel.show() # Update the NeoPixels - - """ - return self._auto_write - - @auto_write.setter - def auto_write(self, write): - if isinstance(write, bool): - self._auto_write = write - - @property - def brightness(self): - """ - Overall brightness of the display - - This example changes the brightness - - .. code-block:: python - - import time - from adafruit_featherwing import neopixel_featherwing - - neopixel = neopixel_featherwing.NeoPixelFeatherWing() - neopixel.brightness = 0 - neopixel.fill(0xFFFFFF) - for i in range(0, 6): - neopixel.brightness = (i / 10) - time.sleep(.2) - - neopixel.brightness = 0.3 - - """ - return self._matrix.brightness - - @brightness.setter - def brightness(self, brightness): - self._matrix.brightness = min(max(brightness, 0.0), 1.0) - self._update() + super().shift_up(rotate) # Up and down are reversed diff --git a/adafruit_featherwing/pixelmatrix_featherwing.py b/adafruit_featherwing/pixelmatrix.py old mode 100644 new mode 100755 similarity index 80% rename from adafruit_featherwing/pixelmatrix_featherwing.py rename to adafruit_featherwing/pixelmatrix.py index 44c7068..17e82b3 --- a/adafruit_featherwing/pixelmatrix_featherwing.py +++ b/adafruit_featherwing/pixelmatrix.py @@ -20,7 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. """ -`adafruit_featherwing.pixelmatrix_featherwing` +`adafruit_featherwing.pixelmatrix` ==================================================== Base Class for the `NeoPixel FeatherWing ` and @@ -34,7 +34,7 @@ #pylint: disable-msg=unsubscriptable-object, unsupported-assignment-operation -class PixelMatrixFeatherWing: +class PixelMatrix: """Base Class for DotStar and NeoPixel FeatherWings The feather uses pins D13 and D11""" @@ -95,23 +95,28 @@ def _update(self): if self._auto_write: self._matrix.show() - def _fill(self, color=0): + def fill(self, color=0): """ Fills all of the Pixels with a color or unlit if empty. + + :param color: (Optional) The text or number to display (default=0) + :type color: list/tuple or int """ self._matrix.fill(color) self._update() - def _show(self): + def show(self): """ Update the Pixels. This is only needed if auto_write is set to False This can be very useful for more advanced graphics effects. """ self._matrix.show() - def _shift_right(self, rotate=False): + def shift_right(self, rotate=False): """ Shift all pixels right + + :param rotate: (Optional) Rotate the shifted pixels to the left side (default=False) """ for y in range(0, self.rows): last_pixel = self._matrix[(y + 1) * self.columns - 1] if rotate else 0 @@ -120,9 +125,11 @@ def _shift_right(self, rotate=False): self._matrix[y * self.columns] = last_pixel self._update() - def _shift_left(self, rotate=False): + def shift_left(self, rotate=False): """ Shift all pixels left + + :param rotate: (Optional) Rotate the shifted pixels to the right side (default=False) """ for y in range(0, self.rows): last_pixel = self._matrix[y * self.columns] if rotate else 0 @@ -131,9 +138,11 @@ def _shift_left(self, rotate=False): self._matrix[(y + 1) * self.columns - 1] = last_pixel self._update() - def _shift_up(self, rotate=False): + def shift_up(self, rotate=False): """ Shift all pixels up + + :param rotate: (Optional) Rotate the shifted pixels to bottom (default=False) """ for x in range(0, self.columns): last_pixel = self._matrix[(self.rows - 1) * self.columns + x] if rotate else 0 @@ -142,9 +151,11 @@ def _shift_up(self, rotate=False): self._matrix[x] = last_pixel self._update() - def _shift_down(self, rotate=False): + def shift_down(self, rotate=False): """ Shift all pixels down + + :param rotate: (Optional) Rotate the shifted pixels to top (default=False) """ for x in range(0, self.columns): last_pixel = self._matrix[x] if rotate else 0 @@ -152,3 +163,28 @@ def _shift_down(self, rotate=False): self._matrix[y * self.columns + x] = self._matrix[(y + 1) * self.columns + x] self._matrix[(self.rows - 1) * self.columns + x] = last_pixel self._update() + + @property + def auto_write(self): + """ + Whether or not we are automatically updating + If set to false, be sure to call show() to update + """ + return self._auto_write + + @auto_write.setter + def auto_write(self, write): + if isinstance(write, bool): + self._auto_write = write + + @property + def brightness(self): + """ + Overall brightness of the display + """ + return self._matrix.brightness + + @brightness.setter + def brightness(self, brightness): + self._matrix.brightness = min(max(brightness, 0.0), 1.0) + self._update()