The Problem

Building a DIY electronic instrument often stalls at the point where hardware schematics, firmware source, and user documentation are scattered across separate repositories or undocumented folders. Engineers must hunt for the correct build scripts, track down missing dependencies, and piece together the control‑flow between the on‑board code and the web‑based configuration UI.

What This Does

minichord bundles the complete stack for a pocket‑sized musical instrument:

  • Hardware assets – PCB layout, bill‑of‑materials, and 3‑D enclosure files live under hardware/.
  • Firmware – C/C++ sources, the LittleFS file‑system library, and a PlatformIO project sit in firmware/. The entry point for the compiled device is the hex file firmware/firmware.hex.
  • Documentation & UI – A MkDocs‑driven website (documentation/site/) and a JavaScript‑based “minicontrol” UI (documentation/site/minicontrol/javascript/). The static entry points are documentation/docs/index.html and documentation/site/minicontrol/index.html.

The repository also contains a Python generator (firmware/generator/generate.py) that assembles LittleFS images for the device.

How It Is Wired

Execution starts when the Teensy MCU boots the flashed firmware.hex. The main firmware (C++ files under firmware/) initializes the LittleFS volume (via firmware/lib/LittleFS/src/LittleFS.cpp) and registers a Sysex handler (firmware/include/sysex_handler.h). Incoming MIDI SysEx messages are dispatched to that handler, which reads or writes preset data stored in the LittleFS image.

When a user accesses the web UI, the browser loads documentation/site/minicontrol/index.html. The page’s script (documentation/site/minicontrol/javascript/index.js) creates a MinichordController object (defined in minichordcontroller.js). This object issues HTTP requests to the device’s built‑in web server (served by the firmware) to upload/download preset blobs. The JavaScript modules are isolated – the static analysis reports zero import edges among the seven internal modules, so each UI script operates independently.

The Python generator (firmware/generator/generate.py) is invoked manually to rebuild the LittleFS image. It imports the LittleFS C headers (firmware/lib/LittleFS/src/LittleFS.h) and writes a binary blob that the firmware later mounts. No circular dependencies are present, simplifying any future refactor.

How To Use It

# Clone the repo (preserve the upstream URL)
git clone https://github.com/moses-y/minichord
cd minichord

# Install documentation build tools
pip install -r documentation/requirements.txt

# Build the static site (produces HTML under documentation/site/)
bash documentation/build_site.sh

# Install firmware build tools (PlatformIO must be installed separately)
pip install -r firmware/generator/requirements.txt   # for the image generator
# Build firmware with PlatformIO (environment name defined in firmware/PlatformIO.ini)
pio run -e <env>                                   # replace <env> with the target board
# Flash the resulting .hex to the Teensy (e.g., via `pio run -t upload`)

# Optional: generate a new LittleFS image
python firmware/generator/generate.py

No environment variables are required by the code base. The only missing piece is a documented PlatformIO environment name, which must be read from the firmware/PlatformIO.ini file.

Real‑World Use

A boutique synth maker can fork this repo, customize the PCB Gerbers in hardware/PCB/, adjust the preset format in firmware/include/sysex_handler.h, and re‑flash the device. The web UI lets end‑users edit patches on a laptop without recompiling firmware, while the generator script can be scripted into a CI step to update the embedded file system automatically.

Code Health & Issues

  • High – Vulnerable dependenciesjinja2@3.1.4 (CVE‑2024‑56201) and others listed in documentation/requirements.txt.
  • High – No license – repository root lacks a LICENSE file, leaving reuse rights undefined.
  • High – No test suite – despite 23 source files, there are no automated tests.
  • Medium – Missing Dependabot – no automated vulnerability updates for the two requirements.txt manifests.
  • Medium – No CI vulnerability scan – GitHub Actions workflow .github/workflows/static.yml does not run a dependency‑review or OSV scan.
  • Medium – Large binaries – 23 blobs >5 MiB (e.g., hardware/3D/rendering/render_v11_bottom.step 28 MiB) inflate clone size.
  • Low – No job timeouts – static workflow lacks timeout-minutes.
  • Low – Missing repo conventions – no .editorconfig, .gitattributes, or formatter config.
  • Low – Dependencies without lockfiledocumentation/requirements.txt has no requirements.lock.
  • High – Deep nestingfirmware/lib/LittleFS/src/littlefs/lfs.c, firmware/generator/generate.py, and firmware/lib/LittleFS/src/LittleFS.h reach 8‑level indentation.
  • High – Duplicated JS code – identical 6‑line blocks appear across 20 UI scripts (index.js, minichordcontroller.js).
  • High – Oversized fileslfs.c (≈4 k lines) and LittleFS.cpp exceed maintainability limits.
  • Medium – High branching densityfirmware/include/sysex_handler.h contains 258 branch points in 715 lines.
  • Low – TODO/FIXME markers – 7 unresolved comments in firmware/lib/LittleFS/src/LittleFS.cpp.

The Bottom Line

minichord provides a complete, open‑hardware instrument stack with clear separation between hardware, firmware, and web UI, but the code base suffers from maintainability hotspots, duplicated UI logic, and critical security hygiene gaps (missing license, vulnerable dependencies, no tests). It is suitable for hardware hobbyists or small manufacturers willing to invest in refactoring and adding proper CI/test coverage before production deployment.