Skip to content

Commit f5c637d

Browse files
committed
Add adafruit_pixelmap.PixelMap
.. a fast helper for animations. It is similar to and inspired by the PixelMap helper in Adafruit LED Animation library, but with an extremely fast 'paste' method for setting a series of pixels. This is a common operation for many animations, and can give a substantial speed improvement. It's named `adafruit_pixelmap` so that we can package a compatible version in pure Python for systems that can't fit it in C in flash, or for Blinka. This is a proof of concept and can make a very fast comet animation: ```python import time import adafruit_pixelbuf import adafruti_pixelmap import board import neopixel from supervisor import ticks_ms from adafruit_led_animation.animation.solid import Solid from adafruit_led_animation import color pixel_pin = board.GP0 pixel_num = 96 pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=1, auto_write=False, pixel_order="RGB") evens = adafruit_pixelmap.PixelMap(pixels, tuple(range(0, pixel_num, 2))) odd_indices = tuple((i, i+2) for i in range(1, pixel_num, 4)) print(odd_indices) odds = adafruit_pixelbuf.PixelMap(pixels, odd_indices) assert len(odds) == len(odd_indices) comet_length = 16 comet1 = [color.calculate_intensity(color.GREEN, ((1+i) / comet_length) ** 2.4) for i in range(comet_length)] comet2 = [color.calculate_intensity(color.PURPLE, ((1+i) / comet_length) ** 2.4) for i in range(comet_length)] pos1 = 0 pos2 = 96//4 while True: evens.paste(comet1, pos1, wrap=True, reverse=False, others=0) pos1 = (pos1 + 1) % len(evens) odds.paste(comet2, pos2, wrap=True, reverse=True, others=0) pos2 = (pos2 - 1) % len(odds) pixels.show() m = ticks_ms() if m % 2000 > 1000: time.sleep(.02) ```
1 parent 1853f49 commit f5c637d

File tree

17 files changed

+658
-30
lines changed

17 files changed

+658
-30
lines changed

locale/circuitpython.pot

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,7 @@ msgid "Unkown error code %d"
22672267
msgstr ""
22682268

22692269
#: shared-bindings/adafruit_pixelbuf/PixelBuf.c
2270+
#: shared-module/adafruit_pixelbuf/PixelMap.c
22702271
#, c-format
22712272
msgid "Unmatched number of items on RHS (expected %d, got %d)."
22722273
msgstr ""
@@ -3152,6 +3153,10 @@ msgstr ""
31523153
msgid "index is out of bounds"
31533154
msgstr ""
31543155

3156+
#: shared-bindings/adafruit_pixelbuf/PixelMap.c
3157+
msgid "index must be tuple or int"
3158+
msgstr ""
3159+
31553160
#: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c
31563161
#: ports/espressif/common-hal/pulseio/PulseIn.c py/obj.c
31573162
#: shared-bindings/bitmaptools/__init__.c
@@ -3537,6 +3542,10 @@ msgstr ""
35373542
msgid "negative shift count"
35383543
msgstr ""
35393544

3545+
#: shared-bindings/adafruit_pixelbuf/PixelMap.c
3546+
msgid "nested index must be int"
3547+
msgstr ""
3548+
35403549
#: shared-module/sdcardio/SDCard.c
35413550
msgid "no SD card"
35423551
msgstr ""

ports/atmel-samd/mpconfigport.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ CIRCUITPY_I2CTARGET ?= 0
4242
CIRCUITPY_JSON ?= 0
4343
CIRCUITPY_KEYPAD ?= 0
4444
CIRCUITPY_MSGPACK ?= 0
45+
CIRCUITPY_PIXELMAP ?= 0
4546
CIRCUITPY_RE ?= 0
4647
CIRCUITPY_SDCARDIO ?= 0
4748
CIRCUITPY_SYNTHIO ?= 0

ports/nrf/boards/aramcon_badge_2019/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ QSPI_FLASH_FILESYSTEM = 1
99
EXTERNAL_FLASH_DEVICES = "GD25Q16C"
1010

1111
CIRCUITPY_DISPLAYIO = 1
12+
CIRCUITPY_PIXELMAP = 0
1213

1314
CIRCUITPY_REQUIRE_I2C_PULLUPS = 0

py/circuitpy_defns.mk

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ endif
266266
ifeq ($(CIRCUITPY_PIXELBUF),1)
267267
SRC_PATTERNS += adafruit_pixelbuf/%
268268
endif
269+
ifeq ($(CIRCUITPY_PIXELMAP),1)
270+
SRC_PATTERNS += adafruit_pixelmap/%
271+
endif
269272
ifeq ($(CIRCUITPY_QRIO),1)
270273
SRC_PATTERNS += qrio/%
271274
endif
@@ -543,6 +546,8 @@ SRC_SHARED_MODULE_ALL = \
543546
_eve/__init__.c \
544547
adafruit_pixelbuf/PixelBuf.c \
545548
adafruit_pixelbuf/__init__.c \
549+
adafruit_pixelmap/PixelMap.c \
550+
adafruit_pixelmap/__init__.c \
546551
_stage/Layer.c \
547552
_stage/Text.c \
548553
_stage/__init__.c \

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ CFLAGS += -DCIRCUITPY_PEW=$(CIRCUITPY_PEW)
319319
CIRCUITPY_PIXELBUF ?= $(CIRCUITPY_FULL_BUILD)
320320
CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF)
321321

322+
CIRCUITPY_PIXELMAP ?= $(CIRCUITPY_PIXELBUF)
323+
CFLAGS += -DCIRCUITPY_PIXELMAP=$(CIRCUITPY_PIXELMAP)
324+
322325
# Only for SAMD boards for the moment
323326
CIRCUITPY_PS2IO ?= 0
324327
CFLAGS += -DCIRCUITPY_PS2IO=$(CIRCUITPY_PS2IO)

shared-bindings/adafruit_pixelbuf/PixelBuf.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,7 @@ STATIC mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) {
253253
}
254254
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_show_obj, pixelbuf_pixelbuf_show);
255255

256-
//| def fill(
257-
//| self, color: Union[int, Tuple[int, int, int], Tuple[int, int, int, float]]
258-
//| ) -> None:
256+
//| def fill(self, color: PixelType) -> None:
259257
//| """Fills the given pixelbuf with the given color."""
260258
//| ...
261259

@@ -267,29 +265,21 @@ STATIC mp_obj_t pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t value) {
267265
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_fill);
268266

269267
//| @overload
270-
//| def __getitem__(
271-
//| self, index: slice
272-
//| ) -> Union[Tuple[Tuple[int, int, int], ...], Tuple[Tuple[int, int, int, float], ...]]: ...
273-
//| @overload
274-
//| def __getitem__(
275-
//| self, index: int
276-
//| ) -> Union[Tuple[int, int, int], Tuple[int, int, int, float]]:
268+
//| def __getitem__(self, index: slice) -> PixelReturnSequence:
277269
//| """Returns the pixel value at the given index as a tuple of (Red, Green, Blue[, White]) values
278270
//| between 0 and 255. When in PWM (DotStar) mode, the 4th tuple value is a float of the pixel
279271
//| intensity from 0-1.0."""
280272
//| ...
281273
//| @overload
282-
//| def __setitem__(
283-
//| self, index: slice, value: Tuple[Union[int, Tuple[float, ...], List[float]], ...]
284-
//| ) -> None: ...
274+
//| def __getitem__(self, index: int) -> PixelReturnType:
275+
//| """Returns the pixel value at the given index as a tuple of (Red, Green, Blue[, White]) values
276+
//| between 0 and 255. When in PWM (DotStar) mode, the 4th tuple value is a float of the pixel
277+
//| intensity from 0-1.0."""
278+
//| ...
285279
//| @overload
286-
//| def __setitem__(
287-
//| self, index: slice, value: List[Union[int, Tuple[float, ...], List[float]]]
288-
//| ) -> None: ...
280+
//| def __setitem__(self, index: slice, value: PixelSequence) -> None: ...
289281
//| @overload
290-
//| def __setitem__(
291-
//| self, index: int, value: Union[int, Tuple[float, ...], List[float]]
292-
//| ) -> None:
282+
//| def __setitem__(self, index: int, value: PixelType) -> None:
293283
//| """Sets the pixel value at the given index. Value can either be a tuple or integer. Tuples are
294284
//| The individual (Red, Green, Blue[, White]) values between 0 and 255. If given an integer, the
295285
//| red, green and blue values are packed into the lower three bytes (0xRRGGBB).

shared-bindings/adafruit_pixelbuf/PixelBuf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#ifndef CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
2828
#define CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H
2929

30+
#include "py/objtuple.h"
3031
#include "shared-module/adafruit_pixelbuf/PixelBuf.h"
3132

3233
extern const mp_obj_type_t pixelbuf_pixelbuf_type;
@@ -48,5 +49,7 @@ void common_hal_adafruit_pixelbuf_pixelbuf_show(mp_obj_t self);
4849
mp_obj_t common_hal_adafruit_pixelbuf_pixelbuf_get_pixel(mp_obj_t self, size_t index);
4950
void common_hal_adafruit_pixelbuf_pixelbuf_set_pixel(mp_obj_t self, size_t index, mp_obj_t item);
5051
void common_hal_adafruit_pixelbuf_pixelbuf_set_pixels(mp_obj_t self_in, size_t start, mp_int_t step, size_t slice_len, mp_obj_t *values, mp_obj_tuple_t *flatten_to);
52+
void common_hal_adafruit_pixelbuf_pixelbuf_parse_color(mp_obj_t self, mp_obj_t color, uint8_t *r, uint8_t *g, uint8_t *b, uint8_t *w);
53+
void common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(mp_obj_t self, size_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
5154

5255
#endif // CP_SHARED_BINDINGS_PIXELBUF_PIXELBUF_H

shared-bindings/adafruit_pixelbuf/__init__.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@
3939
//| RGB(W) strip/matrix manipulation, such as DotStar and Neopixel.
4040
//|
4141
//| Byteorders are configured with strings, such as "RGB" or "RGBD"."""
42+
//|
43+
//| # The types accepted when getting a pixel value
44+
//| PixelReturnType = Union[
45+
//| Tuple[int, int, int], Tuple[int, int, int, int], Tuple[int, int, int, float]
46+
//| ]
47+
//| PixelReturnSequence = Tuple[PixelReturnType]
48+
//| # The types returned when getting a pixel value
49+
//| PixelType = Union[int, PixelReturnType]
50+
//| PixelSequence = Union[Tuple[PixelType], List[PixelType]]
4251
// TODO: Pull in docs from adafruit_pixelbuf.
4352

4453
STATIC const mp_rom_map_elem_t pixelbuf_module_globals_table[] = {

0 commit comments

Comments
 (0)