Initial commit: Arduino Uno Q USB Audio Synth project

- USB gadget (UAC1 + MIDI) with boot persistence
- USB host mode with auto-detection
- Pure Data synth patch with ALSA + UDP netreceive MIDI input
- MIDI rawmidi-to-UDP bridge (midi-bridge.py)
- LED matrix visualization (led-matrix-viz.py via arduino-router RPC)
- MCU sketch for LED matrix control (Arduino_RouterBridge + ArduinoGraphics)
- Conftest/OPA Rego policy validation suite for .pd files
- gen_synth_pd.py: programmatic .pd file generator
- System services: midi-bridge, led-matrix-viz, pd-synth-auto, usb-role-detect
- Justfile with deploy, enable, diagnostic recipes
- Diagnostic script (diag.sh)
This commit is contained in:
2026-06-22 22:46:36 -07:00
commit 8cd796e3dd
38 changed files with 2681 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
#include "ArduinoGraphics.h"
#include "Arduino_LED_Matrix.h"
#include "Arduino_RouterBridge.h"
Arduino_LED_Matrix matrix;
String last_displayed = "";
String clear_matrix(String arg) {
matrix.clear();
last_displayed = "";
return "OK";
}
String draw_frame(String a_str, String b_str, String c_str, String d_str) {
uint32_t f[4];
f[0] = (uint32_t)a_str.toInt();
f[1] = (uint32_t)b_str.toInt();
f[2] = (uint32_t)c_str.toInt();
f[3] = (uint32_t)d_str.toInt();
matrix.loadFrame(f);
last_displayed = "frame";
return "OK";
}
String show_text(String text) {
matrix.clear();
matrix.beginText(0, 0, 0xFFFFFF);
matrix.text(text);
matrix.endText(SCROLL_LEFT);
last_displayed = "text:" + text;
return "OK";
}
String show_char(String c) {
if (c.length() == 0) return "ERROR: no char";
matrix.clear();
matrix.beginText(0, 0, 0xFFFFFF);
matrix.text(c);
matrix.endText(NO_SCROLL);
last_displayed = "char:" + c;
return "OK";
}
String show_two(String a, String b) {
matrix.clear();
matrix.beginText(0, 0, 0xFFFFFF);
matrix.text(a);
matrix.beginText(4, 0, 0xFFFFFF);
matrix.text(b);
matrix.endText(NO_SCROLL);
last_displayed = "two:" + a + b;
return "OK";
}
String set_brightness(String level) {
int l = level.toInt();
if (l < 1) l = 1;
if (l > 8) l = 8;
matrix.setGrayscaleBits(l);
matrix.clear();
return "OK";
}
String get_status(String arg) {
if (last_displayed.length() == 0) return "Matrix: cleared";
return "Matrix shows: " + last_displayed;
}
String play_heart(String arg) {
matrix.clear();
uint32_t hframes[][5] = {
{0x38022020, 0x810408a0, 0x2200e800, 0x20000000, 66},
{0x1c011010, 0x40820450, 0x11007400, 0x10000000, 66},
{0x0e008808, 0x20410228, 0x08803a00, 0x08000000, 66},
{0x07004404, 0x10208114, 0x04401d00, 0x04000000, 66},
{0x03802202, 0x0810408a, 0x02200e80, 0x02000000, 66},
{0x01c01101, 0x04082045, 0x01100740, 0x01000000, 66},
{0x00e00880, 0x82041022, 0x808803a0, 0x00000000, 66},
{0x00700440, 0x40020011, 0x004401c0, 0x00000000, 66},
{0x00380200, 0x20010008, 0x802000e0, 0x00000000, 66},
{0x00180100, 0x10008004, 0x00100060, 0x00000000, 66},
{0x00080080, 0x08004002, 0x00080020, 0x00000000, 66},
};
int n = sizeof(hframes) / sizeof(hframes[0]);
for (int i = 0; i < n * 3; i++) {
matrix.loadFrame(hframes[i % n]);
delay(66);
}
matrix.clear();
last_displayed = "heart animation";
return "OK";
}
void setup() {
matrix.begin();
matrix.textFont(Font_5x7);
matrix.textScrollSpeed(100);
matrix.clear();
matrix.beginText(0, 0, 0xFFFFFF);
matrix.text(".");
matrix.endText(NO_SCROLL);
delay(15000);
Bridge.begin();
Monitor.begin();
Bridge.provide_safe("draw_frame", draw_frame);
Bridge.provide_safe("show_text", show_text);
Bridge.provide_safe("show_char", show_char);
Bridge.provide_safe("show_two", show_two);
Bridge.provide_safe("clear", clear_matrix);
Bridge.provide_safe("set_brightness", set_brightness);
Bridge.provide("get_status", get_status);
Bridge.provide("play_heart", play_heart);
matrix.clear();
play_heart("");
Monitor.println("LED Matrix Bridge ready");
}
void loop() {
delay(1000);
}
+9
View File
@@ -0,0 +1,9 @@
profiles:
default:
fqbn: arduino:zephyr:unoq
platforms:
- platform: arduino:zephyr
libraries:
- Arduino_RouterBridge
- ArduinoGraphics
default_profile: default