Skip to content

Commit

Permalink
improve apa102 display fcn (#296)
Browse files Browse the repository at this point in the history
* improve apa102 display fcn

Actually for APA102 LEDs, the start-frame needs to be zeros of 32bit size.
For the end-frame n/2 bits needs to be written (n is size of apa102 strip.
This improvement reduces the bytes needed to be written resulting in notable increase of speed.

* fix tests

* fix edge case

* formatting

---------

Co-authored-by: Richard Hull <[email protected]>
  • Loading branch information
markoaurelije and rm-hull authored Nov 3, 2024
1 parent 8b12fe0 commit 35d1842
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
7 changes: 4 additions & 3 deletions luma/led_matrix/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
# As before, as soon as the with block completes, the canvas buffer is flushed
# to the device

from math import ceil
import luma.core.error
import luma.led_matrix.const
from luma.core.interface.serial import noop
Expand Down Expand Up @@ -420,13 +421,13 @@ def display(self, image):
assert image.size == self.size
self._last_image = image.copy()

# Send zeros to reset, then pixel values then zeros at end
# Send 32 zero-bits to reset, then pixel values then n/2 zero-bits at end
sz = image.width * image.height * 4
buf = bytearray(sz * 3)
buf = bytearray(4 + sz + ceil(image.width * image.height / 8 / 2))

m = self._mapping
for idx, (r, g, b, a) in enumerate(image.getdata()):
offset = sz + m[idx] * 4
offset = 4 + m[idx] * 4
brightness = (a >> 4) if a != 0xFF else self._brightness
buf[offset] = (0xE0 | brightness)
buf[offset + 1] = b
Expand Down
19 changes: 14 additions & 5 deletions tests/test_apa102.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
# Copyright (c) 2014-18 Richard Hull and contributors
# See LICENSE.rst for details.

from math import ceil
from luma.led_matrix.device import apa102
from luma.core.render import canvas

from helpers import serial, setup_function # noqa: F401


def padding(n):
return [0] * n * 4
def start_frame():
return [0] * 4


def end_frame(n):
return [0] * ceil(n / 2 / 8)


def test_init_cascaded():
device = apa102(serial, cascaded=7)
assert device.width == 7
assert device.height == 1
serial.data.assert_called_with(padding(7) + [0xE0, 0, 0, 0] * 7 + padding(7))
serial.data.assert_called_with(start_frame() + [0xE0, 0, 0, 0] * 7 + end_frame(7))


def test_hide():
Expand All @@ -40,7 +45,9 @@ def test_contrast():
draw.rectangle(device.bounding_box, outline="red")
serial.reset_mock()
device.contrast(0x6B)
serial.data.assert_called_with(padding(6) + [0xE6, 0, 0, 0xFF] * 6 + padding(6))
serial.data.assert_called_with(
start_frame() + [0xE6, 0, 0, 0xFF] * 6 + end_frame(6)
)


def test_display():
Expand All @@ -50,4 +57,6 @@ def test_display():
with canvas(device) as draw:
draw.rectangle(device.bounding_box, outline=(0x11, 0x22, 0x33, 0x44))

serial.data.assert_called_with(padding(4) + [0xE4, 0x33, 0x22, 0x11] * 4 + padding(4))
serial.data.assert_called_with(
start_frame() + [0xE4, 0x33, 0x22, 0x11] * 4 + end_frame(4)
)

0 comments on commit 35d1842

Please sign in to comment.