From 5932bf058c834872804bd508e4ead9ad2fdbebc7 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 24 Jul 2025 09:01:55 -0500 Subject: [PATCH 1/2] add sd_check(), play_file(), stop_play(), show_QR(), hide_QR() portalbase APIs. Fix for status_led pin already in use. Fix for caption text is None --- adafruit_fruitjam/__init__.py | 15 ++++---- adafruit_fruitjam/graphics.py | 31 +++++++++++++++ adafruit_fruitjam/peripherals.py | 65 +++++++++++++++++++++++++++++++- 3 files changed, 103 insertions(+), 8 deletions(-) diff --git a/adafruit_fruitjam/__init__.py b/adafruit_fruitjam/__init__.py index 6c2d970..57240b9 100644 --- a/adafruit_fruitjam/__init__.py +++ b/adafruit_fruitjam/__init__.py @@ -162,7 +162,7 @@ def __init__( # noqa: PLR0912,PLR0913,Too many branches,Too many arguments in f network = Network( status_neopixel=self.peripherals.neopixels - if status_neopixel is None + if status_neopixel is None or status_neopixel == board.NEOPIXEL else status_neopixel, esp=esp, external_spi=spi, @@ -191,14 +191,14 @@ def __init__( # noqa: PLR0912,PLR0913,Too many branches,Too many arguments in f # Convenience Shortcuts for compatibility - # self.sd_check = self.peripherals.sd_check - # self.play_file = self.peripherals.play_file - # self.stop_play = self.peripherals.stop_play + self.sd_check = self.peripherals.sd_check + self.play_file = self.peripherals.play_file + self.stop_play = self.peripherals.stop_play self.image_converter_url = self.network.image_converter_url self.wget = self.network.wget - # self.show_QR = self.graphics.qrcode - # self.hide_QR = self.graphics.hide_QR + self.show_QR = self.graphics.qrcode + self.hide_QR = self.graphics.hide_QR if default_bg is not None: self.graphics.set_background(default_bg) @@ -207,7 +207,8 @@ def __init__( # noqa: PLR0912,PLR0913,Too many branches,Too many arguments in f print("Init caption") if caption_font: self._caption_font = self._load_font(caption_font) - self.set_caption(caption_text, caption_position, caption_color) + if caption_text is not None: + self.set_caption(caption_text, caption_position, caption_color) if text_font: if text_position is not None and isinstance(text_position[0], (list, tuple)): diff --git a/adafruit_fruitjam/graphics.py b/adafruit_fruitjam/graphics.py index fdb6fc5..68f5158 100644 --- a/adafruit_fruitjam/graphics.py +++ b/adafruit_fruitjam/graphics.py @@ -66,3 +66,34 @@ def __init__( if supervisor.runtime.display is None: request_display_config(640, 480) super().__init__(supervisor.runtime.display, default_bg=default_bg, debug=debug) + + def qrcode(self, qr_data, *, qr_size=1, x=0, y=0, hide_background=False): # noqa: PLR0913 Too many arguments in function definition + """Display a QR code + + :param qr_data: The data for the QR code. + :param int qr_size: The scale of the QR code. + :param x: The x position of upper left corner of the QR code on the display. + :param y: The y position of upper left corner of the QR code on the display. + :param hide_background: Hide the background while showing the QR code. + + """ + super().qrcode( + qr_data, + qr_size=qr_size, + x=x, + y=y, + ) + if hide_background: + self.display.root_group = self._qr_group + self._qr_only = hide_background + + def hide_QR(self): + """Clear any QR codes that are currently on the screen""" + + if self._qr_only: + self.display.root_group = self.root_group + else: + try: + self._qr_group.pop() + except (IndexError, AttributeError): # later test if empty + pass diff --git a/adafruit_fruitjam/peripherals.py b/adafruit_fruitjam/peripherals.py index 76a47b1..015672c 100644 --- a/adafruit_fruitjam/peripherals.py +++ b/adafruit_fruitjam/peripherals.py @@ -15,7 +15,7 @@ **Hardware:** -* `Adafruit Fruit Jam `_ +* `Adafruit Fruit Jam `_" **Software and Dependencies:** @@ -26,12 +26,19 @@ """ +import os + +import adafruit_sdcard import adafruit_tlv320 import audiobusio +import audiocore import board +import busio +import digitalio import displayio import framebufferio import picodvi +import storage import supervisor from digitalio import DigitalInOut, Direction, Pull from neopixel import NeoPixel @@ -140,6 +147,35 @@ def __init__(self): self._audio = audiobusio.I2SOut(board.I2S_BCLK, board.I2S_WS, board.I2S_DIN) + self._sd_mounted = False + sd_pins_in_use = False + SD_CS = board.SD_CS + # try to Connect to the sdcard card and mount the filesystem. + try: + # initialze CS pin + cs = digitalio.DigitalInOut(SD_CS) + except ValueError: + # likely the SDCard was auto-initialized by the core + sd_pins_in_use = True + + # if placeholder.txt file does not exist + if "placeholder.txt" not in os.listdir("/sd/"): + self._sd_mounted = True + + if not sd_pins_in_use: + try: + # if sd CS pin was not in use + # try to initialize and mount the SDCard + sdcard = adafruit_sdcard.SDCard( + busio.SPI(board.SD_SCK, board.SD_MOSI, board.SD_MISO), cs + ) + vfs = storage.VfsFat(sdcard) + storage.mount(vfs, "/sd") + self._sd_mounted = True + except OSError: + # sdcard init or mounting failed + self._sd_mounted = False + @property def button1(self) -> bool: """ @@ -175,3 +211,30 @@ def dac(self): @property def audio(self): return self._audio + + def sd_check(self): + return self._sd_mounted + + def play_file(self, file_name, wait_to_finish=True): + """Play a wav file. + + :param str file_name: The name of the wav file to play on the speaker. + :param bool wait_to_finish: flag to determine if this is a blocking call + + """ + + # can't use `with` because we need wavefile to remain open after return + self.wavfile = open(file_name, "rb") + wavedata = audiocore.WaveFile(self.wavfile) + self.audio.play(wavedata) + if not wait_to_finish: + return + while self.audio.playing: + pass + self.wavfile.close() + + def stop_play(self): + """Stops playing a wav file.""" + self.audio.stop() + if self.wavfile is not None: + self.wavfile.close() From 2a5d7e81e784d48afcdd94080a1caed0eae9bd6d Mon Sep 17 00:00:00 2001 From: foamyguy Date: Thu, 24 Jul 2025 10:05:15 -0500 Subject: [PATCH 2/2] fix docs build --- adafruit_fruitjam/peripherals.py | 2 +- docs/conf.py | 2 ++ requirements.txt | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/adafruit_fruitjam/peripherals.py b/adafruit_fruitjam/peripherals.py index 015672c..1c2c5ad 100644 --- a/adafruit_fruitjam/peripherals.py +++ b/adafruit_fruitjam/peripherals.py @@ -15,7 +15,7 @@ **Hardware:** -* `Adafruit Fruit Jam `_" +* `Adafruit Fruit Jam `_ **Software and Dependencies:** diff --git a/docs/conf.py b/docs/conf.py index 8fb2cba..5afc3cc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -30,6 +30,8 @@ "framebufferio", "picodvi", "audiobusio", + "audiocore", + "storage", "terminalio", ] diff --git a/requirements.txt b/requirements.txt index 331814a..d26fdd0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,3 +12,4 @@ adafruit-circuitpython-esp32spi adafruit-circuitpython-requests adafruit-circuitpython-bitmap-font adafruit-circuitpython-display-text +adafruit-circuitpython-sd