Skip to content

Virtual Jumpers

This an exploration into the boundaries between physical and virtual tools. It takes the concept of jumpers on a breadboard and turns it into something which is … slightly different:

top view

The placement of the small headers suggests that each of them carries the signal of the button, switch, LED, etc next to them, and that jumpers can then connect them together. Presumably, pressing the leftmost button should turn on the green LED, right?

Well, yes, maybe …

However, there’s something slightly more devious going on underneath the board:

bottom view

Everything is connected to the Blue Pill µC, including the 5+8 jumper fields - those little 3-pin headers in which jumper wires can be inserted. So instead of actual signals, the µC is sensing the placement of jumpers and then “applying those instructions” to simulate the request.

In other words: it’s all virtual, the µC decides what to do with button presses, knob turns, etc.


In this proof-of-concept setup, there are a few simple ways to interpret the jumpers:

  • When the potentiometer is connected to an LED, it could control its brightness, while buttons and slide switches only turn them on or off.
  • If multiple buttons are jumpered to the same LED, that could be treated as a logic “OR”, i.e. pressing either button would turn on that LED.
  • Similarly, the slide switches could have “AND” functionality: when a button and a switch are tied to the LED, it would only respond to button presses when the slide switch is on.
  • The potmeter could be controlling the rate of a pulse instead of generating an analog value, so that its output would blink an LED instead of dimming it.
  • The rotary encoder on the right could be a LED dimmer, or it could be shown as a bar of varying length when attached to the OLED - or both, when attached to LED and OLED.

The reason this works, is that the jumpers are not actual signals, so there’s no risk of shorting them out. As will be explained below, for the µC it’s really just another sensor, in the form of a matrix which is periodically scanned to detect all jumper connections.

Is it a breadboard?

The “jumper fields” on this board act a bit like the 5-pin groups on a solderless breadboard. In fact, this is similar to the old “digitrainers” used in education to explore electronic circuits:


The idea is to place a solderless breadboard in the middle, with some digital or analog circuit on it, and then use the surrounding tools to control it and to inspect / measure its behaviour.

But the prototype I made also shows its fatal flaw: while it has a few “tools”, there is no place for a breadboard with a “circuit under test” on it. That leaves only a very limited number of ways to place jumpers, making it fairly useless in practice.

One way to fix this would be to add some OLEDs, each surrounded by a few jumper fields. You could then “install” a simulated circuit on each OLED, and use the jumpers to feed it its inputs and inspect its outputs. Or interconnect a few of them for more interesting configurations.

Hybrid circuits

But why stop at the obvious?

  • What if the µC was simulating a much more complex circuit, and the inputs and outputs of that circuit were exposed as jumpers? A retrocomputer, a user-defined module coded in some programming language or visually, as a diagram?

  • What if there was room to place more advanced electronics circuits, such as oscillators, numeric readouts, op-amp circuits, tiny oscilloscopes, etc? The wiring could be a mix of jumpers and “real” cables with suitable connectors for carrying audio signals or even 50Ω HF connections?

These ideas are not new. The music scene has been exploring the human-machine interface for decades, coming up with synthesizers and patch panels, as well as the Modular Eurorack:

modular eurorack

The difference here, is that Eurorack cables carry actual audio signals and ±10V control signals (envelopes, triggers, sweeps, etc).

The “virtual jumper” idea I’m proposing here is different, in that the jumpers are not carrying data, they just convey a patch configuration to the µC.


As seen in the picture of the back side of this prototype, each of the jumper fields is tied to a GPIO pin. This requires a lot of extra pins, but fortunately many common µCs now have many such GPIO pins available.

As it turns out, the prototype uses every available GPIO pin of the Blue Pill:

• potentiometer: PB0
• rotary encoder: PB5 PB6 PB7
• 2 slide switches: PB1 PA15
• 3 buttons: PB13 PB14 PB15
• 3 LEDs: PA8 PA9 PA10
• 12 jumper pins for the above + µC: PA0..PA7 & PB8..PB12
• 2 pins for USB: PA11 PA12

The mechanism for “reading out” the jumper connections is fairly simple:

  1. set all jumper-field GPIO pins to input-pulldown mode
  2. change one pin to an output and set it to “1”
  3. read all the inputs and check which ones just went high
  4. restore the pin to input-pulldown mode
  5. rinse and repeat for each pin (there are 13 in this prototype)

The result is a “netlist”: a map of connections. When jumpers are combined, more than two pins may end up being tied together, i.e. creating a “net”.

This logic has been implemented in C++ and uses JeeH to control the GPIO hardware:

    int tied = 0;
    for (int i = 0; i < 13; ++i) {
        auto b = 1<<i;
        if (tied & b)
        auto r = checkJumpers(i);
        if ((tied | r) != (tied | b))
            printf("%2d: %013b\n", i, r);
        tied |= r;

The above needs to be run periodically, e.g. every 100 ms, using some additional definitions:

#include <jee.h>

using PA = Port<'A'>;
using PB = Port<'B'>;

void initJumpers () {
    PA::modeMap (0x00FF, Pinmode::in_pulldown);
    PB::modeMap (0x1F00, Pinmode::in_pulldown);

int checkJumpers (int n) {
    auto b = 1 << n;
    if (n < 8) {
        PA::modeMap (b, Pinmode::out);
        MMIO32(PA::bsrr) = b; // set
    } else {
        PB::modeMap (b, Pinmode::out);
        MMIO32(PB::bsrr) = b; // set
    int r = (MMIO32(PA::idr) & 0x00FF) | (MMIO32(PB::idr) & 0x1F00);
    if (n < 8) {
        MMIO32(PA::brr) = b; // clear
        PA::modeMap (b, Pinmode::in_pulldown);
    } else {
        MMIO32(PB::brr) = b; // clear
        PB::modeMap (b, Pinmode::in_pulldown);
    return r;

The pin assignments (PA0..PA7 & PBB..PB12) makes it easy to capture them all in one go.

Full source is available at stm32x/jumpers.

Where to go from here

This prototype is of limited use. In fact, I haven’t even bothered to fully implement the idea, i.e. using the jumpers to redirect to the LEDs and OLED. The current version just prints the jumper connections to the USB serial port and has the buttons “virtually hard-wired” to the LEDs.

This has been an interesting exploration, but it’s too rough to put into practice in this state. There are too many directions to make it useful. For now, I think it’s all best described as a “solution looking for a problem”, but who knows … maybe it will evolve further some day.