photo of the Organ Stops Multi-input MIDI Encoder

Designing a Multi-input MIDI Encoder for Multiple Switch Closures

This site contains affiliate links. Please read Disclaimer for more information.

This post describes the design of a multi-input MIDI encoder intended for switch-heavy control applications like Virtual Pipe Organs or Amateur Radio Station Automation.

Why a Multi-input MIDI Encoder?

Most of the hardware projects I enjoy start the same way: with a physical problem that doesn’t look very complicated until you try to solve it cleanly. In this case, the problem was easy to describe—detect a large number of switch closures and make them visible to a computer—but harder to execute reliably, repeatably, and at scale.

Although this project grew out of a Virtual Pipe Organ build, the underlying design problem will be familiar to many amateur radio operators and station builders: how to connect a panel full of physical controls to modern software in a way that is robust, flexible, and easy to extend.

This post focuses on the technical design of a 48-input USB-connected encoder, how it evolved from a prototype to a manufactured circuit board, and why the resulting architecture generalizes well beyond its original musical application.

The Problem Space

photo of The VPO Project
The VPO Project

The hardware requirements were deceptively simple:

  • 48 independent SPST switch closures
  • Each switch pulls a line to ground when activated
  • Both press and release events must be detected
  • Output must be delivered over USB

In practice, this raises several immediate constraints:

  • Input count exceeds the GPIO capacity of most microcontrollers
  • Mechanical switch bounce must be handled cleanly
  • Multiple simultaneous activations must be supported
  • False triggers or stuck states are unacceptable
  • USB reliability matters more than raw speed

While the original application involved organ pedals and stop tabs, these constraints apply just as readily to control panels, macro keypads, antenna switching logic, and other station automation tasks.

Architecture Overview

The Teensy Quick Reference Card
Teensy Quick Reference Card

At the center of the design is a Teensy 4.0, chosen primarily for its native USB support and generous performance margin. Rather than multiplexing inputs or consuming valuable GPIO pins, I used dedicated I/O expanders to handle switch detection.

The system architecture consists of:

  • 3 × MCP23017 I²C GPIO expanders
  • 48 digital inputs total
  • Single shared I²C bus
  • USB connection directly from the Teensy

Each MCP23017 provides 16 GPIO pins with internal pull-up resistors, making them ideal for detecting switches that pull to ground. By assigning each expander a unique I²C address, the system scales cleanly to the required input count with minimal wiring complexity.

Firmware Design Goals

From the outset, the firmware had several non-negotiable goals:

  • Deterministic behavior
  • No global delays
  • Independent handling of each input
  • Clean separation between input sampling and output generation

The main loop follows a consistent pattern:

  1. Read all MCP23017 GPIO registers once per scan
  2. Cache the results locally
  3. Evaluate each input independently
  4. Apply debounce and lockout logic
  5. Emit output events only on validated state changes

Reading all GPIO ports in a single pass significantly reduces I²C traffic and avoids subtle timing issues that can arise when inputs are read individually.

Debounce and Lockout Strategy

photo of the MIDI Encoder breadboard
MIDI Encoder breadboard

Mechanical switches bounce. Reed switches bounce less—but they still bounce.

Rather than relying on delay-based debouncing, the firmware uses a state stability counter. A potential state change must be observed consistently for several consecutive scans before it is accepted. Once accepted, a short per-input lockout window suppresses any residual chatter.

This approach has several advantages:

  • Each input debounces independently
  • Simultaneous activations are handled cleanly
  • No blocking delays slow the scan loop

The result is fast, predictable behavior without false retriggering.

MIDI Output Strategy

For the production version, the encoder emits MIDI Continuous Controller (CC) messages:

  • One CC number per physical input
  • Value 127 on activation
  • Value 0 on release

This mapping works particularly well with virtual organ software such as Hauptwerk, which can dynamically learn and assign CC inputs.

To avoid any possibility of stuck states, the firmware also sends a MIDI safety (“panic”) sequence on boot, resetting controllers and ensuring the system starts in a known state.

Beyond MIDI: USB as a Control Interface

Although this encoder currently emits MIDI messages, that choice was driven by the needs of the musical application—not by any limitation of the hardware.

photo of the Stream Deck App Controller
Stream Deck App Controller

At its core, the firmware is simply detecting validated state changes and emitting structured events. MIDI is one convenient transport, but far from the only option.

With minimal firmware changes, the same architecture could support:

  • USB serial output (ASCII or binary protocols)
  • Human Interface Device (HID) keypresses
  • Hybrid USB devices presenting multiple interfaces simultaneously

For amateur radio operators, this opens up a wide range of possibilities: custom CAT control panels, macro triggers for logging software, band-dependent automation, or Stream Deck–style physical interfaces tailored to a specific operating style.

Seen in that light, this project is best understood as a general-purpose, scalable input front end, with behavior defined almost entirely in software.

Hardware Evolution: From Prototype to PCB

The earliest versions of this encoder were built on prototyping boards. That approach worked well for validating the firmware and electrical design, but hand-wiring dozens of inputs is neither pleasant nor repeatable.

photo of the MIDI Encoder Wired Prototype
MIDI Encoder Wired Prototype

Once the design stabilized, it made sense to move to a custom printed circuit board.

The production board was designed in KiCad and integrates:

  • Three MCP23017 expanders
  • Power distribution and decoupling
  • I²C pull-ups
  • JST-XH connectors for switch inputs
  • A Teensy 4.0 socket

The electrical design is straightforward, but care was taken with grounding, decoupling, and I²C signal routing to ensure reliability.

Manufacturing with PCBWay

graphic of the KiCad 3D view of finished PCB
KiCad 3D view of finished PCB

PCBWay provided fabrication and partial SMT assembly support for this project, covering most of the production cost for a small run of boards.

As the design moved from prototype to production hardware, I submitted the Gerbers and BOM for review. During that process, their production team flagged a discrepancy between the BOM and the PCB specifications — a detail I had overlooked. That brief exchange was reassuring. The issue was clarified quickly, and it demonstrated that the design files were being reviewed carefully rather than simply processed automatically.

The assembled boards arrived clean, well-labeled, and exactly as designed. The SMT components were precisely placed, solder joints were uniform, and there was no rework required before final assembly. Packaging was secure and professional, and the boards arrived in excellent condition.

Their assistance allowed me to move quickly from schematic to finished boards, freeing up time for integration work inside the console. I’m grateful for their help in bringing this stage of the Virtual Pipe Organ project to life.

Final assembly involved only through-hole components: the Teensy module and the input connectors. For a project of this scale, that division of labor worked extremely well.

Tooling Notes

Two tools played important roles in this project:

graphic of KiCad, "Rats Nest" stage
KiCad, “Rats Nest” stage
  • KiCad, which has matured considerably in recent versions
  • ChatGPT, which served as a capable (if occasionally overconfident) design assistant

ChatGPT was particularly useful for architecture discussions, code structure, debugging, and validating assumptions before committing them to hardware. Like any assistant, it works best when its suggestions are verified against reality.

Code Availability

All firmware for this project is publicly available on GitHub:

👉 https://github.com/jbkerkhoff/Organ_Pedals_Tab_Stops_MIDI

The repository includes source code, hardware notes, and a tagged v1.0 release representing a stable baseline.

This encoder is part of a larger Virtual Pipe Organ project documented at Roy Creek Ranch, where the focus shifts from electronics to restoration, integration, and long-term system design.

The encoder itself stands on its own as a flexible building block for many kinds of control projects.

Was this interesting or helpful? Share your thoughts . . .

This site uses Akismet to reduce spam. Learn how your comment data is processed.