From 39d3f9c4b94aba542e62f77c220414a140fdacdf Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 13:51:20 -0500 Subject: [PATCH 01/13] Allow padding to be a float padding_above is in "lines of text" units, so being able to position by 0.3 e.g., is useful to get a desired layout. --- adafruit_pybadger/pybadger_base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index bd5c7ed..7081cce 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -274,7 +274,7 @@ def badge_line( scale: int = 1, font: Union[BuiltinFont, BDF, PCF] = terminalio.FONT, left_justify: bool = False, - padding_above: int = 0, + padding_above: float = 0, ) -> None: """Add a line of text to the display. Designed to work with ``badge_background`` for a color-block style badge, or with ``image_background`` for a badge with a background image. @@ -331,7 +331,7 @@ def badge_line( trim_padding = 0 if font is terminalio.FONT: trim_y = 4 * scale - trim_padding = 4 * padding_above + trim_padding = round(4 * padding_above) if not padding_above: text_label.y = self._y_position + ((height // 2) * scale) - trim_y @@ -342,14 +342,14 @@ def badge_line( self._y_position += height * scale + 4 else: - text_label.y = ( + text_label.y = round( self._y_position + (((height // 2) * scale) - trim_y) + ((height * padding_above) - trim_padding) ) if font is terminalio.FONT: - self._y_position += (height * scale - trim_y) + ( + self._y_position += (height * scale - trim_y) + round( (height * padding_above) - trim_padding ) else: From 0237d6658583206c26d18ce822f3df7ae402a1b1 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 13:51:37 -0500 Subject: [PATCH 02/13] use bitmap text in most cases this is more performant and can also use less RAM --- adafruit_pybadger/pybadger_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 7081cce..91ffc81 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -36,7 +36,7 @@ from adafruit_bitmap_font import bitmap_font import displayio from adafruit_display_shapes.rect import Rect -from adafruit_display_text import label +from adafruit_display_text import bitmap_label as label import terminalio import adafruit_miniqr From bae8fe746e9b65314a1fbf5e5359f01efe9a463b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 13:54:16 -0500 Subject: [PATCH 03/13] Fix dimming of display The old code would never brighten again after it went dim. Now, it will brighten on movement or when `activity()` is called from outside. --- adafruit_pybadger/pybadger_base.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 91ffc81..6b9894d 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -424,14 +424,17 @@ def auto_dim_display(self, delay: float = 5.0, movement_threshold: int = 10): while True: pybadger.auto_dim_display(delay=10) """ - if not self._check_for_movement(movement_threshold=movement_threshold): - current_time = time.monotonic() - if current_time - self._start_time > delay: - self.display.brightness = 0.1 - self._start_time = current_time + current_time = time.monotonic() + if self._check_for_movement(movement_threshold=movement_threshold: + self.activity(current_time) + if current_time - self._start_time > delay: + self.display.brightness = 0.1 else: self.display.brightness = self._display_brightness + def activity(self, current_time=None): + self._start_time = current_time or time.monotonic() + @property def pixels(self) -> NeoPixel: """Sequence like object representing the NeoPixels on the board.""" From d5660075eca986098090a9ce32ef89d0fdd1a1da Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 13:56:57 -0500 Subject: [PATCH 04/13] Add, use `show` method to reduce display jank This also removes 'with open(...) as ...:' because for correct functionality the OnDiskBitmap needs to retain the open file handle for as long as it exists. In particular, this fixes a problem where switching to the 'business card' view with a background image would redraw twice. Calling `show()` also acts as activity, so it'll brighten the screen. At present, this is not configurable. --- adafruit_pybadger/pybadger_base.py | 73 ++++++++++++++---------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 6b9894d..6dc5a9b 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -161,27 +161,20 @@ def _create_badge_background(self) -> None: if self._background_group is None: self._background_group = displayio.Group() - self.display.show(self._background_group) + self.show(self._background_group) if self._background_image_filename: - with open(self._background_image_filename, "rb") as file_handle: - on_disk_bitmap = displayio.OnDiskBitmap(file_handle) - background_image = displayio.TileGrid( - on_disk_bitmap, - pixel_shader=getattr( - on_disk_bitmap, "pixel_shader", displayio.ColorConverter() - ), - # TODO: Once CP6 is no longer supported, replace the above line with below - # pixel_shader=on_disk_background.pixel_shader, - ) - self._background_group.append(background_image) - for image_label in self._lines: - self._background_group.append(image_label) - - self.display.refresh() - else: - for background_label in self._lines: - self._background_group.append(background_label) + file_handle = open(self._background_image_filename, "rb") + on_disk_bitmap = displayio.OnDiskBitmap(file_handle) + background_image = displayio.TileGrid( + on_disk_bitmap, + pixel_shader=getattr( + on_disk_bitmap, "pixel_shader", displayio.ColorConverter() + ), + ) + self._background_group.append(background_image) + for image_label in self._lines: + self._background_group.append(image_label) def badge_background( self, @@ -362,7 +355,7 @@ def show_custom_badge(self) -> None: if not self._created_background: self._create_badge_background() - self.display.show(self._background_group) + self.show(self._background_group) # pylint: disable=too-many-arguments def _create_label_group( @@ -550,22 +543,20 @@ def show_business_card( business_card_label_groups.append(email_two_group) business_card_splash = displayio.Group() - self.display.show(business_card_splash) - with open(image_name, "rb") as file_name: - on_disk_bitmap = displayio.OnDiskBitmap(file_name) - face_image = displayio.TileGrid( - on_disk_bitmap, - pixel_shader=getattr( - on_disk_bitmap, "pixel_shader", displayio.ColorConverter() - ), - # TODO: Once CP6 is no longer supported, replace the above line with below - # pixel_shader=on_disk_bitmap.pixel_shader, - ) - business_card_splash.append(face_image) - for group in business_card_label_groups: - business_card_splash.append(group) - - self.display.refresh() + image_file = open(image_name, "rb") + on_disk_bitmap = displayio.OnDiskBitmap(image_file) + face_image = displayio.TileGrid( + on_disk_bitmap, + pixel_shader=getattr( + on_disk_bitmap, "pixel_shader", displayio.ColorConverter() + ), + # TODO: Once CP6 is no longer supported, replace the above line with below + # pixel_shader=on_disk_bitmap.pixel_shader, + ) + business_card_splash.append(face_image) + for group in business_card_label_groups: + business_card_splash.append(group) + self.show(business_card_splash) # pylint: disable=too-many-locals def show_badge( @@ -650,11 +641,17 @@ def show_badge( group.append(hello_group) group.append(my_name_is_group) group.append(name_group) + self.show(group) + + def show(self, group) -> None: self.display.show(group) + self.auto_refresh = False + self.display.refresh() + self.activity() def show_terminal(self) -> None: """Revert to terminalio screen.""" - self.display.show(None) + self.show(None) @staticmethod def bitmap_qr(matrix: adafruit_miniqr.QRBitMatrix) -> displayio.Bitmap: @@ -706,7 +703,7 @@ def show_qr_code(self, data: str = "https://circuitpython.org") -> None: ) qr_code = displayio.Group(scale=qr_code_scale) qr_code.append(qr_img) - self.display.show(qr_code) + self.show(qr_code) @staticmethod def _sine_sample(length: int) -> Generator[int, None, None]: From eb31a88b0b6a35bea0eb7a933e048cb842401eb7 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:04:39 -0500 Subject: [PATCH 05/13] remove circuitpython6 compatibility code --- adafruit_pybadger/pybadger_base.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 6dc5a9b..873947d 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -168,9 +168,7 @@ def _create_badge_background(self) -> None: on_disk_bitmap = displayio.OnDiskBitmap(file_handle) background_image = displayio.TileGrid( on_disk_bitmap, - pixel_shader=getattr( - on_disk_bitmap, "pixel_shader", displayio.ColorConverter() - ), + pixel_shader=on_disk_bitmap.pixel_shader, ) self._background_group.append(background_image) for image_label in self._lines: @@ -546,12 +544,7 @@ def show_business_card( image_file = open(image_name, "rb") on_disk_bitmap = displayio.OnDiskBitmap(image_file) face_image = displayio.TileGrid( - on_disk_bitmap, - pixel_shader=getattr( - on_disk_bitmap, "pixel_shader", displayio.ColorConverter() - ), - # TODO: Once CP6 is no longer supported, replace the above line with below - # pixel_shader=on_disk_bitmap.pixel_shader, + on_disk_bitmap, pixel_shader=on_disk_bitmap.pixel_shader ) business_card_splash.append(face_image) for group in business_card_label_groups: From cd3f9a8f62d7ce49c81b1ba1f539307da1617b7a Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:07:23 -0500 Subject: [PATCH 06/13] fix movement check call --- adafruit_pybadger/pybadger_base.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 873947d..e20890a 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -164,7 +164,9 @@ def _create_badge_background(self) -> None: self.show(self._background_group) if self._background_image_filename: - file_handle = open(self._background_image_filename, "rb") + file_handle = open( # pylint: disable=consider-using-with + self._background_image_filename, "rb" + ) on_disk_bitmap = displayio.OnDiskBitmap(file_handle) background_image = displayio.TileGrid( on_disk_bitmap, @@ -416,7 +418,7 @@ def auto_dim_display(self, delay: float = 5.0, movement_threshold: int = 10): pybadger.auto_dim_display(delay=10) """ current_time = time.monotonic() - if self._check_for_movement(movement_threshold=movement_threshold: + if self._check_for_movement(movement_threshold=movement_threshold): self.activity(current_time) if current_time - self._start_time > delay: self.display.brightness = 0.1 @@ -541,7 +543,7 @@ def show_business_card( business_card_label_groups.append(email_two_group) business_card_splash = displayio.Group() - image_file = open(image_name, "rb") + image_file = open(image_name, "rb") # pylint: disable=consider-using-with on_disk_bitmap = displayio.OnDiskBitmap(image_file) face_image = displayio.TileGrid( on_disk_bitmap, pixel_shader=on_disk_bitmap.pixel_shader From 998e0f988c26bcad2427f791f9129a36d2a8662f Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:10:01 -0500 Subject: [PATCH 07/13] make it OK to call acceleration() if no accelerometer; fix return type --- adafruit_pybadger/pybadger_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index e20890a..543d8a2 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -439,12 +439,12 @@ def light(self) -> bool: return self._light_sensor.value @property - def acceleration(self) -> Union[LSM6DS33, LIS3DH_I2C]: + def acceleration(self) -> Tuple[int, int, int]: """Accelerometer data, +/- 2G sensitivity.""" return ( self._accelerometer.acceleration if self._accelerometer is not None - else None + else (0, 0, 0) ) @property From d2df1ef3be8646d47ea9699c9233e9012c8ceb6e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:13:02 -0500 Subject: [PATCH 08/13] use annotations and TYPE_CHECKING .. and eliminate imports no longer used since the change to the acceleration property --- adafruit_pybadger/pybadger_base.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 543d8a2..2411b28 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -27,6 +27,9 @@ """ +from __future__ import annotations + + import time import array import math @@ -55,16 +58,17 @@ pass try: + from typing import TYPE_CHECKING +except ImportError: + TYPE_CHECKING = const(0) + +if TYPE_CHECKING: from typing import Union, Tuple, Optional, Generator from adafruit_bitmap_font.bdf import BDF # pylint: disable=ungrouped-imports from adafruit_bitmap_font.pcf import PCF # pylint: disable=ungrouped-imports from fontio import BuiltinFont from keypad import Keys, ShiftRegisterKeys from neopixel import NeoPixel - from adafruit_lsm6ds.lsm6ds33 import LSM6DS33 - from adafruit_lis3dh import LIS3DH_I2C -except ImportError: - pass __version__ = "0.0.0-auto.0" From c8cbc432f55d883b6b19a056e198a9c8af79fdab Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:13:55 -0500 Subject: [PATCH 09/13] changes made by black via pre-commit --- adafruit_pybadger/pybadger_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 2411b28..23c14c8 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -476,7 +476,7 @@ def show_business_card( email_font_one: Union[BuiltinFont, BDF, PCF] = terminalio.FONT, email_string_two: Optional[str] = None, email_scale_two: int = 1, - email_font_two: Union[BuiltinFont, BDF, PCF] = terminalio.FONT + email_font_two: Union[BuiltinFont, BDF, PCF] = terminalio.FONT, ) -> None: """Display a bitmap image and a text string, such as a personal image and email address. @@ -573,7 +573,7 @@ def show_badge( my_name_is_string: str = "MY NAME IS", name_font: Union[BuiltinFont, BDF, PCF] = terminalio.FONT, name_scale: int = 1, - name_string: str = "Blinka" + name_string: str = "Blinka", ) -> None: """Create a "Hello My Name is"-style badge. From e1f96af4d69adcb6057c6f3bb27dc9dc9e9eae1e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:14:16 -0500 Subject: [PATCH 10/13] fix use of auto_refresh property during display update --- adafruit_pybadger/pybadger_base.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 23c14c8..b72cf08 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -643,10 +643,12 @@ def show_badge( self.show(group) def show(self, group) -> None: + """Show the given group, refreshing the screen immediately""" + self.activity() + self.display.auto_refresh = False self.display.show(group) - self.auto_refresh = False self.display.refresh() - self.activity() + self.display.auto_refresh = True def show_terminal(self) -> None: """Revert to terminalio screen.""" From 4a23749b6df562e46fcf049efe823bd45c8be170 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:14:38 -0500 Subject: [PATCH 11/13] fix activity() to immediately un-dim screen --- adafruit_pybadger/pybadger_base.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index b72cf08..01b8e7f 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -430,6 +430,10 @@ def auto_dim_display(self, delay: float = 5.0, movement_threshold: int = 10): self.display.brightness = self._display_brightness def activity(self, current_time=None): + """Turn postpone dimming of the screen""" + if not hasattr(self.display, "brightness"): + return + self.display.brightness = self._display_brightness self._start_time = current_time or time.monotonic() @property From ee4d7dfcaaaa6b23df3e268eb2a6971a109dfd58 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 14:14:59 -0500 Subject: [PATCH 12/13] make it OK to call auto_dim_display if brightness is not settable --- adafruit_pybadger/pybadger_base.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/adafruit_pybadger/pybadger_base.py b/adafruit_pybadger/pybadger_base.py index 01b8e7f..c7d280c 100644 --- a/adafruit_pybadger/pybadger_base.py +++ b/adafruit_pybadger/pybadger_base.py @@ -421,6 +421,8 @@ def auto_dim_display(self, delay: float = 5.0, movement_threshold: int = 10): while True: pybadger.auto_dim_display(delay=10) """ + if not hasattr(self.display, "brightness"): + return current_time = time.monotonic() if self._check_for_movement(movement_threshold=movement_threshold): self.activity(current_time) From d15c90b87e7e0d34a5e381f5c262c643443f8c0e Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 26 Apr 2022 15:15:10 -0500 Subject: [PATCH 13/13] Add an asyncio example with a fancy precomputed qr code --- examples/QR_Blinka_CircuitPythonOrg.bmp | Bin 0 -> 38470 bytes .../QR_Blinka_CircuitPythonOrg.bmp.license | 3 + examples/pybadger_pygamer_asyncio.py | 88 ++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 examples/QR_Blinka_CircuitPythonOrg.bmp create mode 100644 examples/QR_Blinka_CircuitPythonOrg.bmp.license create mode 100644 examples/pybadger_pygamer_asyncio.py diff --git a/examples/QR_Blinka_CircuitPythonOrg.bmp b/examples/QR_Blinka_CircuitPythonOrg.bmp new file mode 100644 index 0000000000000000000000000000000000000000..84d9e1195975e24d7c9e04170f76703e53077843 GIT binary patch literal 38470 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 XHLD#zo!hyLruFK^PortUT+#jiNDDTP literal 0 HcmV?d00001 diff --git a/examples/QR_Blinka_CircuitPythonOrg.bmp.license b/examples/QR_Blinka_CircuitPythonOrg.bmp.license new file mode 100644 index 0000000..1a8072c --- /dev/null +++ b/examples/QR_Blinka_CircuitPythonOrg.bmp.license @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# +# SPDX-License-Identifier: CC-BY-SA-4.0 diff --git a/examples/pybadger_pygamer_asyncio.py b/examples/pybadger_pygamer_asyncio.py new file mode 100644 index 0000000..3433207 --- /dev/null +++ b/examples/pybadger_pygamer_asyncio.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2022 Jeff Epler for Adafruit Industries +# SPDX-License-Identifier: MIT + +# pylint: disable=consider-using-with + +import asyncio +from displayio import TileGrid, OnDiskBitmap, Group +from rainbowio import colorwheel +from adafruit_pybadger import pybadger + +# If you choose to enter a pronoun it's shown on the "business card" page +pronoun = "" +custom_line1 = "FIRST" +custom_line2 = "LAST" # also a great place to show a pronoun + +# Set up the custom image +qr_image = OnDiskBitmap(open("/QR_Blinka_CircuitPythonOrg.bmp", "rb")) +qr_tg = TileGrid(qr_image, pixel_shader=qr_image.pixel_shader) +qr_gp = Group() +qr_gp.append(qr_tg) + +pybadger.badge_background( + background_color=pybadger.WHITE, + rectangle_color=pybadger.PURPLE, + rectangle_drop=0.25, + rectangle_height=0.55, +) + +pybadger.badge_line( + text="HELLO I'M", color=pybadger.BLINKA_PURPLE, scale=2, padding_above=1 +) +pybadger.badge_line(text=custom_line1, color=pybadger.WHITE, scale=6, padding_above=1) +pybadger.badge_line( + text=custom_line2, color=pybadger.BLINKA_PURPLE, scale=2, padding_above=0.25 +) + +# Start with the custom badge page +pybadger.show_custom_badge() + +# This task responds to buttons and changes the visible page +async def ui_task(): + while True: + if pybadger.button.a: + pybadger.show_business_card( + image_name="Blinka.bmp", + name_string="Jeff Epler", + name_scale=2, + email_string_one="jeff@adafruit.com", + email_string_two=pronoun, + ) + elif pybadger.button.b: + pybadger.show(qr_gp) + elif pybadger.button.start: + pybadger.show_custom_badge() + elif pybadger.button.select: + pybadger.activity() + else: + pybadger.auto_dim_display( + delay=0.5 + ) # Remove or comment out this line if you have the PyBadge LC + await asyncio.sleep(0.02) + + +# This task animates the LEDs +async def led_task(): + pixels = pybadger.pixels + pixels.auto_write = False + num_pixels = len(pixels) + j = 0 + while True: + bright = pybadger.display.brightness > 0.5 + j = (j + (7 if bright else 3)) & 255 + b = 31 / 255.0 if bright else 5 / 255.0 + if pixels.brightness != b: + pixels.brightness = b + for i in range(num_pixels): + rc_index = i * 97 + j + pixels[i] = colorwheel(rc_index & 255) + pixels.show() + await asyncio.sleep(0.02) + + +# Run both tasks via asyncio! +async def main(): + await asyncio.gather(ui_task(), led_task()) + + +asyncio.run(main())