Porównaj commity

...

2 Commity

Autor SHA1 Wiadomość Data
Max Carlson 812de90e5e Remove references to delay as it's no longer needed 2024-02-08 17:58:02 +02:00
Max Carlson 51f1f46230 Use a single array as a buffer, including header and trailer
Uses an offset to ensure get/set() happens in the right place. Also caches the memoryview once to make show() as efficient as possible. It turned out passing the header/trailer values as-is from python is the right approach. Everything works well for me now, maybe I'll look into DMA next :)
2024-02-08 17:53:08 +02:00
1 zmienionych plików z 25 dodań i 25 usunięć

Wyświetl plik

@ -4,7 +4,7 @@ import rp2
# based on https://learn.adafruit.com/intro-to-rp2040-pio-with-circuitpython/advanced-using-pio-to-drive-neopixels-in-the-background by https://learn.adafruit.com/u/jepler
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=False, pull_thresh=32)
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=False, pull_thresh=32)
def sk6812():
wrap_target()
pull(block) .side(0) # get fresh NeoPixel bit count value
@ -40,10 +40,6 @@ class slice_maker_class:
slice_maker = slice_maker_class()
# Delay here is the reset time. You need a pause to reset the LED strip back to the initial LED
# however, if you have quite a bit of processing to do before the next time you update the strip
# you could put in delay=0 (or a lower delay)
#
# Class supports different order of individual colors (GRB, RGB, WRGB, GWRB ...). In order to achieve
# this, we need to flip the indexes: in 'RGBW', 'R' is on index 0, but we need to shift it left by 3 * 8bits,
# so in it's inverse, 'WBGR', it has exactly right index. Since micropython doesn't have [::-1] and recursive rev()
@ -63,11 +59,10 @@ class Neopixel:
# 'W_in_mode', # bool: is 'W' in mode
# 'sm', # state machine
# 'shift', # shift amount for each component, in a tuple for (R,B,G,W)
# 'delay', # delay amount
# 'brightnessvalue', # brightness scale factor 1..255
# ]
def __init__(self, num_leds, state_machine, pin, mode="RGB", delay=3):
def __init__(self, num_leds, state_machine, pin, mode="RGB"):
"""
Constructor for library class
@ -76,9 +71,7 @@ class Neopixel:
:param pin: pin on which data line to led-strip is connected
:param mode: [default: "RGB"] mode and order of bits representing the color value.
This can be any order of RGB or RGBW (neopixels are usually GRB)
:param delay: [default: 0.0001] delay used for latching of leds when sending data
"""
self.pixels = array.array("I", [0] * num_leds)
# self.pixels_out = array.array("I", [0] * num_leds)
self.mode = mode
self.W_in_mode = 'W' in mode
@ -96,18 +89,31 @@ class Neopixel:
((mode.index('B') ^ 3) - 1) * 8, 0)
self.sm.active(1)
self.num_leds = num_leds
self.delay = delay
self.brightnessvalue = 255
# from https://learn.adafruit.com/intro-to-rp2040-pio-with-circuitpython/advanced-using-pio-to-drive-neopixels-in-the-background
byte_count = bpp * num_leds
bit_count = byte_count * 8
padding_count = -byte_count % 4
# send number of bits to read
self.header = bytearray(struct.pack("L", bit_count - 1))
# pad if needed, then send number of cycles to delay
self.trailer = bytearray(b"\0" * padding_count + struct.pack("L", 3840))
# use a single array
self.pixels = array.array("I")
# send number of bits to read
self.pixels.append(bit_count - 1)
# store offset into pixels array for get/set later
self.offset = len(self.pixels)
# add starting values for each pixel
pix = array.array("I", [0] * num_leds)
self.pixels.extend(pix)
# send number of cycles to delay
self.pixels.append(3840)
# use a memoryview to
self.mv = memoryview(self.pixels)
def brightness(self, brightness=None):
"""
@ -199,12 +205,13 @@ class Neopixel:
white = round(rgb_w[3] * bratio)
pix_value = white << sh_W | blue << sh_B | red << sh_R | green << sh_G
offset = self.offset
# set some subset, if pixel_num is a slice:
if type(pixel_num) is slice:
for i in range(*pixel_num.indices(self.num_leds)):
self.pixels[i] = pix_value
self.pixels[i + offset] = pix_value
else:
self.pixels[pixel_num] = pix_value
self.pixels[pixel_num + offset] = pix_value
def get_pixel(self, pixel_num):
"""
@ -213,7 +220,7 @@ class Neopixel:
:param pixel_num: Index of pixel to be set
:return rgb_w: Tuple of form (r, g, b) or (r, g, b, w) representing color to be used
"""
balance = self.pixels[pixel_num]
balance = self.pixels[pixel_num + self.offset]
sh_R, sh_G, sh_B, sh_W = self.shift
if self.W_in_mode:
w = (balance >> sh_W) & 255
@ -329,14 +336,7 @@ class Neopixel:
This method should be used after every method that changes the state of leds or after a chain of changes.
:return: None
"""
# If mode is RGB, we cut 8 bits of, otherwise we keep all 32
cut = 8
if self.W_in_mode:
cut = 0
self.sm.put(self.header, 0)
self.sm.put(memoryview(self.pixels), cut)
self.sm.put(self.trailer, 0)
self.sm.put(self.mv)
def fill(self, rgb_w, how_bright=None):
"""