From 7a3b118186db4bf44dbebd80c14f432f1d0be8c9 Mon Sep 17 00:00:00 2001 From: firepixie Date: Tue, 31 Jan 2023 12:01:02 -0800 Subject: [PATCH] NeoPixel Cufflink CircuitPython Code first commit --- NeoPixel_Novelty_Cufflinks/README.md | 6 ++ NeoPixel_Novelty_Cufflinks/code.py | 84 +++++++++++++++++++++++ NeoPixel_Novelty_Cufflinks/tom-thumb.pcf | Bin 0 -> 24444 bytes 3 files changed, 90 insertions(+) create mode 100644 NeoPixel_Novelty_Cufflinks/README.md create mode 100755 NeoPixel_Novelty_Cufflinks/code.py create mode 100755 NeoPixel_Novelty_Cufflinks/tom-thumb.pcf diff --git a/NeoPixel_Novelty_Cufflinks/README.md b/NeoPixel_Novelty_Cufflinks/README.md new file mode 100644 index 000000000..728a41fd5 --- /dev/null +++ b/NeoPixel_Novelty_Cufflinks/README.md @@ -0,0 +1,6 @@ +# NeoPixel Novelty Cufflinks + +CircuitPython Code for Cufflinks with scrolling text that chooses a random string to display and a heart icon. Built on the QT Py RP2040 with the NeoPixel 5x5 BFF attached. + +Tutorial at https://learn.adafruit.com/neopixel-novelty-cufflinks-with-scrolling-text/overview + diff --git a/NeoPixel_Novelty_Cufflinks/code.py b/NeoPixel_Novelty_Cufflinks/code.py new file mode 100755 index 000000000..fb496d135 --- /dev/null +++ b/NeoPixel_Novelty_Cufflinks/code.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: Copyright (c) 2023 Erin St. Blaine for Adafruit Industries +# +# SPDX-License-Identifier: MIT +import time +from random import randint +import board +import neopixel +import fontio +from adafruit_display_text.bitmap_label import Label +from adafruit_bitmap_font import bitmap_font +from displayio import Bitmap +from rainbowio import colorwheel + +tom_thumb = bitmap_font.load_font("tom-thumb.pcf", Bitmap) + +_glyph_keys = ['bitmap', 'tile_index', 'width', 'height', 'dx', 'dy', 'shift_x', 'shift_y'] +def patch_glyph(base, **kw): + d = {} + for k in _glyph_keys: + d[k] = kw.get(k, getattr(base, k)) + return fontio.Glyph(**d) + +class PatchedFont: + def __init__(self, base_font, patches): + self.base_font = base_font + self.patches = patches + + def get_glyph(self, glyph): + g = self.base_font.get_glyph(glyph) + patch = self.patches.get(glyph) + if patch is not None: + # print("patching", repr(chr(glyph)), g) + g = patch_glyph(g, **patch) + # print("patched", g) + return g + + def get_bounding_box(self): + return self.base_font.get_bounding_box() + +font = PatchedFont(tom_thumb, + {32: {'shift_x': 1, 'dx': 0}, + 105: {'dx': 0, 'shift_x': 2}, + 33: {'dx': 0, 'shift_x': 2}, + }) + +# List of text strings +text_strings = [" love bun ", " dear me ", " my bear ", + " my my ", " you are babe "] +# Create a label object +label = Label(text="text", font=font) +bitmap = label.bitmap +heart_bitmap = [ + 0, 1, 1, 0, 0, + 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, + 0, 1, 1, 0, 0 +] +pixels = neopixel.NeoPixel(board.A1, 5*5, brightness=.08, auto_write=False) +while True: + for hue in range(0, 255, 3): + color = colorwheel(hue) + pixels[:] = [pixel * color for pixel in heart_bitmap] + pixels.show() + time.sleep(.05) + hue = 0 + string_index = randint(0, 4) + label.text = text_strings[string_index] + bitmap = label.bitmap + print(string_index) + for i in range(bitmap.width): + # Use a rainbow of colors, shifting each column of pixels + hue = hue + 7 + if hue >= 256: + hue = hue - 256 + color = colorwheel(hue) + # Scoot the old text left by 1 pixel + pixels[:20] = pixels[5:] + # Draw in the next line of text + for y in range(5): + # Select black or color depending on the bitmap pixel + pixels[20+y] = color * bitmap[i,y] + pixels.show() + time.sleep(.2) diff --git a/NeoPixel_Novelty_Cufflinks/tom-thumb.pcf b/NeoPixel_Novelty_Cufflinks/tom-thumb.pcf new file mode 100755 index 0000000000000000000000000000000000000000..b9f2ae7283b86595c4dfb229a18ad159041b4b1d GIT binary patch literal 24444 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 E0rnN;DF6Tf literal 0 HcmV?d00001