Software¶
The SquishBox Python package makes it easy to build menu-driven hardware applications for Raspberry Pi audio projects.
Instead of dealing directly with GPIO timing, LCD protocols, encoder debouncing, and event handling, your program interacts with a single high-level object:
import squishbox
sb = squishbox.SquishBox()
From there you can:
Write text to the LCD
Read knob and button actions
Present menus and prompts
Edit text from the front panel
Control LEDs and outputs
Launch shell commands
Build complete standalone hardware applications
This page is a practical primer for customizing/writing SquishBox apps.
Application Model¶
Most SquishBox programs follow a simple pattern:
Create the shared
SquishBox()instanceDraw something on the LCD
Wait for user input
Respond to that input
Repeat until exit
Example:
import squishbox
sb = squishbox.SquishBox()
sb.lcd.clear()
sb.lcd.write("Hello SquishBox", row=0)
while True:
action = sb.get_action()
if action == "inc":
sb.lcd.write("Turned Right ", row=1)
elif action == "dec":
sb.lcd.write("Turned Left ", row=1)
elif action == "select":
sb.lcd.write("Tapped ", row=1)
elif action == "back":
break
The default control mappings usually are:
inc— clockwise turndec— counterclockwise turnselect— encoder tapback— encoder hold
These mappings come from the hardware configuration and may be customized.
Configuration File¶
The SquishBox configuration file is loaded on import, and defines settings such as:
LCD configuration
UI timings
Inputs/Outputs and bindings
Custom LCD characters
The default path for the configuration file is:
$HOME/SquishBox/config/squishboxconf.yaml
Drop-in config files can be used for things such as
hardware overlays (e.g. squishboxconf.d/v2.yaml).
Using the LCD¶
The built-in LCD object is available as:
sb.lcd
Clear the display:
sb.lcd.clear()
Set contrast/backlight levels:
sb.contrast_level = 70
sb.backlight_level = 40
Write text:
sb.lcd.write("Patch Loaded", row=0)
sb.lcd.write("Grand Piano", row=1, align="right")
Long text automatically scrolls when needed. Alignment is left by default.
Custom Characters¶
Characters beyond the standard “ASCII Printable” set can be defined as custom characters in the configuration file:
glyphs_5x8:
wifi_on: |
-XXX-
X---X
--X--
-X-X-
-----
--X--
-----
-----
A maximum of 8 unique custom characters can be displayed at once, but an arbitrary number can be defined in the LCD object. They are displayed using element access:
sb.lcd.write("WiFi status: " + sb.lcd["wifi_on"], row=0)
Temporary Messages¶
Use timeout= to overlay a message briefly:
sb.lcd.write("Saved", row=1, timeout=2)
This is useful for confirmations and status notices.
Input/Output Access¶
Controls and outputs are defined and bound to actions in the configuration file.
controls:
knob1:
type: encoder
pins: [22, 27]
events: {left: dec, right: inc}
knob1_button:
type: button
pin: 17
events: {tap: select, hold: back}
outputs:
led_fader: {type: pwm, pin: 4, level: 60}
led_blinker: {type: binary, pin: 23}
Reading Input Directly¶
For games, meters, transport controls, or custom interfaces, use raw actions:
while True:
action = sb.get_action(timeout=0.1)
if action == "inc":
value += 1
elif action == "dec":
value -= 1
elif action == "back":
break
timeout allows your loop to continue running while waiting for input.
Outputs and LEDs¶
Configured outputs are available through:
sb.outputs
Example:
sb.outputs["led1"].on()
sb.outputs["led1"].off()
PWM duty cycles are controlled using a level property.
Miscellaneous Toos¶
Running Shell Commands¶
For integrating Linux utilities:
result = sb.shell_cmd("hostname -I")
sb.lcd.write(result, row=1)
Useful for:
audio tools
system commands
WiFi utilities
file conversion
launching synth engines
Long Running Tasks¶
Use the activity spinner while work is in progress:
with sb.lcd.activity("Loading..."):
load_large_patch()
This gives visual feedback on the LCD while your task runs.
Error Handling¶
Unhandled exceptions are automatically shown on the LCD with useful debug information.
Still, for user-facing programs, catch expected errors:
try:
load_patch(name)
except Exception as e:
sb.display_error(e, "Load failed")