Merge pull request #2 from FoamyGuy/bell_and_fruitjam_example
Some checks failed
Build CI / test (push) Has been cancelled

ASCII Bell support and Fruit Jam example
This commit is contained in:
foamyguy 2025-07-09 16:12:39 -05:00 committed by GitHub
commit f15134618b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 169 additions and 3 deletions

View file

@ -5,7 +5,8 @@
`adafruit_color_terminal`
================================================================================
Extension of supports ANSI color escapes for subsets of text
Extension of supports ANSI color escapes for subsets of text and optionally the
ASCII bell escape code.
* Author(s): Tim Cocks
@ -28,6 +29,7 @@ Implementation Notes
__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Color_Terminal.git"
from audiocore import WaveFile
from displayio import Palette, TileGrid
from terminalio import Terminal
from tilepalettemapper import TilePaletteMapper
@ -63,9 +65,20 @@ class ColorTerminal:
:param height: The height of the terminal in characters.
:param custom_palette: A custom palette of colors to use instead of the default ones.
Must contain at least 9 colors.
:param audio_interface: The audio interface to use for playing ASCII bell escape codes.
:param bell_audio_file: The wave audio file to use for the ASCII bell escape codes.
Defaults to beep.wav
"""
def __init__(self, font, width, height, custom_palette=None):
def __init__(
self,
font,
width,
height,
custom_palette=None,
audio_interface=None,
bell_audio_file="/beep.wav",
):
if custom_palette is None:
self.terminal_palette = Palette(9)
self.terminal_palette[0] = 0x000000
@ -99,6 +112,11 @@ class ColorTerminal:
self.cur_color_mapping = [0, 1]
self.audio_interface = audio_interface
if audio_interface is not None:
beep_wave_file = open(bell_audio_file, "rb")
self.beep_wave = WaveFile(beep_wave_file)
@staticmethod
def parse_ansi_colors(text):
"""
@ -195,6 +213,13 @@ class ColorTerminal:
if not color_map:
self.terminal.write(s)
if (
"\x07" in s
and self.audio_interface is not None
and not self.audio_interface.playing
):
print("playing beep")
self.audio_interface.play(self.beep_wave)
return
idx = 0
@ -222,6 +247,12 @@ class ColorTerminal:
self.apply_color(cur_slice)
self.terminal.write(cur_slice)
if (
"\x07" in cur_slice
and self.audio_interface is not None
and not self.audio_interface.playing
):
self.audio_interface.play(self.beep_wave)
# index after last can be in the color map if color code is last thing in string
if idx in color_map:

View file

@ -25,7 +25,7 @@ extensions = [
# Uncomment the below if you use native CircuitPython modules such as
# digitalio, micropython and busio. List the modules you use. Without it, the
# autodoc module docs will fail to generate with a warning.
autodoc_mock_imports = ["terminalio", "tilepalettemapper", "displayio"]
autodoc_mock_imports = ["terminalio", "tilepalettemapper", "displayio", "audiocore"]
autodoc_preserve_defaults = True

BIN
examples/beep.wav Normal file

Binary file not shown.

View file

@ -0,0 +1,3 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense

View file

@ -0,0 +1,71 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
import supervisor
from adafruit_fruitjam import peripherals
from displayio import Group
from terminalio import FONT
from adafruit_color_terminal import ColorTerminal
main_group = Group()
display = supervisor.runtime.display
if display is None or peripherals.get_display_config()[2] < 4:
print(
"To use ColorTerminal there must be an initialized display with a color depth at least 4."
)
print(
"Initializing display to default size 640x480 with color depth 8, ",
"if you do not want this configuration then initialize the display ",
"before running this example.",
)
peripherals.request_display_config(640, 480, 8)
fruitjam_peripherals = peripherals.Peripherals()
fruitjam_peripherals.dac.headphone_output = True
fruitjam_peripherals.dac.configure_clocks(sample_rate=16000, bit_depth=16)
font_bb = FONT.get_bounding_box()
screen_size = (display.width // font_bb[0], display.height // font_bb[1])
terminal = ColorTerminal(
FONT, screen_size[0], screen_size[1], audio_interface=fruitjam_peripherals.audio
)
main_group.append(terminal.tilegrid)
black = chr(27) + "[30m"
red = chr(27) + "[31m"
green = chr(27) + "[32m"
yellow = chr(27) + "[33m"
blue = chr(27) + "[34m"
magenta = chr(27) + "[35m"
cyan = chr(27) + "[36m"
white = chr(27) + "[37m"
reset = chr(27) + "[0m"
message = f"Hello {green}World{reset} {yellow}ANSI\n"
terminal.write(message)
print(message, end="")
message = f"{magenta}Terminal {red}Colors{reset}"
terminal.write(message)
print(message)
display.root_group = main_group
print(terminal.cursor_x, terminal.cursor_y)
move_cursor = chr(27) + "[10;10H"
terminal.write(f" Something {move_cursor}{cyan} Else{reset}")
time.sleep(2)
terminal.write(" beep\x07")
while True:
pass

View file

@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import supervisor
from adafruit_fruitjam import peripherals
from displayio import Group
from terminalio import FONT
from adafruit_color_terminal import ColorTerminal
main_group = Group()
display = supervisor.runtime.display
if display is None or peripherals.get_display_config()[2] < 4:
print(
"To use ColorTerminal there must be an initialized display with a color depth at least 4."
)
print(
"Initializing display to default size 640x480 with color depth 8, ",
"if you do not want this configuration then initialize the display ",
"before running this example.",
)
peripherals.request_display_config(640, 480, 8)
font_bb = FONT.get_bounding_box()
screen_size = (display.width // font_bb[0], display.height // font_bb[1])
terminal = ColorTerminal(FONT, screen_size[0], screen_size[1])
main_group.append(terminal.tilegrid)
black = chr(27) + "[30m"
red = chr(27) + "[31m"
green = chr(27) + "[32m"
yellow = chr(27) + "[33m"
blue = chr(27) + "[34m"
magenta = chr(27) + "[35m"
cyan = chr(27) + "[36m"
white = chr(27) + "[37m"
reset = chr(27) + "[0m"
message = f"Hello {green}World{reset} {yellow}ANSI\n"
terminal.write(message)
print(message, end="")
message = f"{magenta}Terminal {red}Colors{reset}"
terminal.write(message)
print(message)
display.root_group = main_group
print(terminal.cursor_x, terminal.cursor_y)
move_cursor = chr(27) + "[10;10H"
terminal.write(f" Something {move_cursor}{cyan} Else{reset}")
while True:
pass

View file

@ -92,6 +92,8 @@ ignore = [
"PLR2004", # magic-value-comparison
"UP030", # format literals
"PLW1514", # unspecified-encoding
"PLR0913", # too many args
"PLR0917", # too many positional args
]