diff --git a/adafruit_led_animation/__init__.py b/adafruit_led_animation/__init__.py index ff60e91..05102ca 100644 --- a/adafruit_led_animation/__init__.py +++ b/adafruit_led_animation/__init__.py @@ -28,13 +28,23 @@ def monotonic_ms(): return monotonic_ns() // NANOS_PER_MS except (ImportError, NotImplementedError): - import time - - def monotonic_ms(): - """ - Implementation of monotonic_ms for platforms without time.monotonic_ns - """ - return int(time.monotonic() * MS_PER_SECOND) + try: + from time import monotonic + + def monotonic_ms(): + """ + Implementation of monotonic_ms for platforms without time.monotonic_ns + """ + return int(monotonic() * MS_PER_SECOND) + + except (ImportError, NotImplementedError): + from time import time_ns + + def monotonic_ms(): + """ + Implementation of monotonic_ms for platforms without time.monotonic_ns or time.monotonic + """ + return time_ns() // NANOS_PER_MS NANOS_PER_MS = const(1000000) diff --git a/adafruit_led_animation/animation/__init__.py b/adafruit_led_animation/animation/__init__.py old mode 100644 new mode 100755 index 87e1bf2..f54055f --- a/adafruit_led_animation/animation/__init__.py +++ b/adafruit_led_animation/animation/__init__.py @@ -29,6 +29,7 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git" from adafruit_led_animation import MS_PER_SECOND, monotonic_ms +from adafruit_led_animation.helper import pixel_object_show, pixel_object_auto_write_set class Animation: @@ -41,7 +42,7 @@ class Animation: # pylint: disable=too-many-arguments def __init__(self, pixel_object, speed, color, peers=None, paused=False, name=None): self.pixel_object = pixel_object - self.pixel_object.auto_write = False + pixel_object_auto_write_set(pixel_object, False) self._peers = [self] + peers if peers is not None else [self] self._speed_ms = 0 self._color = None @@ -116,7 +117,7 @@ def show(self): """ Displays the updated pixels. Called during animates with changes. """ - self.pixel_object.show() + pixel_object_show(self.pixel_object) @property def peers(self): @@ -154,7 +155,7 @@ def fill(self, color): Fills the pixel object with a color. """ self.pixel_object.fill(color) - self.pixel_object.show() + pixel_object_show(self.pixel_object) @property def color(self): diff --git a/adafruit_led_animation/color.py b/adafruit_led_animation/color.py old mode 100644 new mode 100755 index 9f8b17a..a062797 --- a/adafruit_led_animation/color.py +++ b/adafruit_led_animation/color.py @@ -24,7 +24,41 @@ https://circuitpython.org/downloads """ # Makes colorwheel() available. -from rainbowio import colorwheel # pylint: disable=unused-import +try: + from rainbowio import colorwheel # pylint: disable=unused-import +except (ImportError, ModuleNotFoundError): + + def colorwheel(pos): + """ + Generate a color from a position value on a color wheel. + This function maps an input position (0-255) to a color on a + virtual RGB color wheel. The colors transition smoothly through + red, green, and blue. + :param float pos: Position on the color wheel (0-255). Values outside + this range will be wrapped around. + :return: color + """ + + # ref: + # https://github.com/adafruit/circuitpython/blob/main/shared-module/rainbowio/__init__.c + pos = pos - ((pos // 256) * 256) + shift1 = 0 + shift2 = 0 + if pos < 85: + shift1 = 8 + shift2 = 16 + elif pos < 170: + pos -= 85 + shift1 = 0 + shift2 = 8 + else: + pos -= 170 + shift1 = 16 + shift2 = 0 + pos_new = (int)(pos * 3) + pos_new = pos_new if (pos_new < 256) else 255 + return (pos_new << shift1) | ((255 - pos_new) << shift2) + RED = (255, 0, 0) """Red.""" diff --git a/adafruit_led_animation/grid.py b/adafruit_led_animation/grid.py index b15254c..5e9ad31 100644 --- a/adafruit_led_animation/grid.py +++ b/adafruit_led_animation/grid.py @@ -26,7 +26,16 @@ """ from micropython import const -from .helper import PixelMap, horizontal_strip_gridmap, vertical_strip_gridmap +from .helper import ( + PixelMap, + horizontal_strip_gridmap, + vertical_strip_gridmap, + pixel_object_show, + pixel_object_auto_write, + pixel_object_auto_write_set, + pixel_object_brightness, + pixel_object_brightness_set, +) HORIZONTAL = const(1) @@ -130,7 +139,7 @@ def __setitem__(self, index, val): else: raise ValueError("PixelGrid assignment needs a sub-index or x,y coordinate") - if self._pixels.auto_write: + if pixel_object_auto_write(self._pixels): self.show() def __getitem__(self, index): @@ -150,12 +159,12 @@ def brightness(self): """ brightness from the underlying strip. """ - return self._pixels.brightness + return pixel_object_brightness(self._pixels) @brightness.setter def brightness(self, brightness): # pylint: disable=attribute-defined-outside-init - self._pixels.brightness = min(max(brightness, 0.0), 1.0) + pixel_object_brightness_set(self._pixels, brightness) def fill(self, color): """ @@ -170,18 +179,19 @@ def show(self): """ Shows the pixels on the underlying strip. """ - self._pixels.show() + pixel_object_show(self._pixels) @property def auto_write(self): """ auto_write from the underlying strip. """ - return self._pixels.auto_write + return pixel_object_auto_write(self._pixels) @auto_write.setter def auto_write(self, value): - self._pixels.auto_write = value + # pylint: disable=attribute-defined-outside-init + pixel_object_auto_write_set(self._pixels, value) def reverse_x_mapper(width, mapper): diff --git a/adafruit_led_animation/group.py b/adafruit_led_animation/group.py index 2377d1d..54731aa 100644 --- a/adafruit_led_animation/group.py +++ b/adafruit_led_animation/group.py @@ -30,6 +30,7 @@ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git" from adafruit_led_animation.animation import Animation +from adafruit_led_animation.helper import pixel_object_show class AnimationGroup: @@ -146,7 +147,7 @@ def animate(self, show=True): for member in self._members: if isinstance(member, Animation): if last_strip != member.pixel_object: - member.pixel_object.show() + pixel_object_show(member.pixel_object) last_strip = member.pixel_object else: member.show() diff --git a/adafruit_led_animation/helper.py b/adafruit_led_animation/helper.py index b033b58..0fd2dbf 100644 --- a/adafruit_led_animation/helper.py +++ b/adafruit_led_animation/helper.py @@ -138,7 +138,7 @@ def __setitem__(self, index, val): else: self._set_pixels(index, val) - if self._pixels.auto_write: + if pixel_object_auto_write(self._pixels): self.show() def __getitem__(self, index): @@ -161,12 +161,12 @@ def brightness(self): """ brightness from the underlying strip. """ - return self._pixels.brightness + return pixel_object_brightness(self._pixels) @brightness.setter def brightness(self, brightness): # pylint: disable=attribute-defined-outside-init - self._pixels.brightness = min(max(brightness, 0.0), 1.0) + pixel_object_brightness_set(self._pixels, brightness) def fill(self, color): """ @@ -182,18 +182,19 @@ def show(self): """ Shows the pixels on the underlying strip. """ - self._pixels.show() + pixel_object_show(self._pixels) @property def auto_write(self): """ auto_write from the underlying strip. """ - return self._pixels.auto_write + return pixel_object_auto_write(self._pixels) @auto_write.setter def auto_write(self, value): - self._pixels.auto_write = value + # pylint: disable=attribute-defined-outside-init + pixel_object_auto_write_set(self._pixels, value) @classmethod def vertical_lines(cls, pixel_object, width, height, gridmap): @@ -310,3 +311,57 @@ def __init__(self, pixel_object, start, end): pixel_ranges=[[n] for n in range(start, end)], individual_pixels=True, ) + + +def pixel_object_show(pixel_object): + """ + Show the pixel object. This is a helper function to handle both + MicroPython and CircuitPython. + :param pixel_object: The pixel object to show/write to. + """ + if hasattr(pixel_object, "show"): + pixel_object.show() + elif hasattr(pixel_object, "write"): + pixel_object.write() + + +def pixel_object_auto_write(pixel_object): + """ + Get the auto_write property of the pixel object. + :param pixel_object: The pixel object to get the auto_write property from. + :return: The auto_write property of the pixel object. + """ + if hasattr(pixel_object, "auto_write"): + return pixel_object.auto_write + return False + + +def pixel_object_auto_write_set(pixel_object, value): + """ + Set the auto_write property of the pixel object. + :param pixel_object: The pixel object to set the auto_write property on. + :param value: The value to set the auto_write property to. + """ + if hasattr(pixel_object, "auto_write"): + pixel_object.auto_write = value + + +def pixel_object_brightness(pixel_object): + """ + Get the brightness property of the pixel object. + :param pixel_object: The pixel object to get the brightness property from. + :return: The brightness property of the pixel object. + """ + if hasattr(pixel_object, "brightness"): + return pixel_object.brightness + return 1.0 + + +def pixel_object_brightness_set(pixel_object, value): + """ + Set the brightness property of the pixel object. + :param pixel_object: The pixel object to set the brightness property on. + :param value: The value to set the brightness property to. + """ + if hasattr(pixel_object, "brightness"): + pixel_object.brightness = value