Pocket Operator Video

Spring 2025

To celebrate the 10th anniversary of the first Pocket Operators, Teenage Engineering ran the #PO10DIY contest — a call for makers of all kinds to submit hacks / mods / designs / reimaginings of their pocket-sized synthesizer line.

The brief was pretty broad — they were asking for DIY ideas & designs that center pocket operators. They also listed some inspiring projects from the contest that accompanied the original launch, including custom cases, eurorack mods, alternative input devices, and more.

I immediately knew I wanted to submit something. Teenage Engineering has always been an inspiration of mine — I love their playful and lovingly crafted instruments, and I wanted to make something that felt like the RMNA homage to TE.

Brainstorming

I had a few initial ideas:

Sweatshirt Operator

Solder tiny wires onto all of the buttons of a Pocket Operator, then connect those to e-textile soft buttons on a comfy sweatshirt with a PO-inspired design on it. I've experimented with e-textiles before and it's a really fun way to interact with electronics.

PO-Video

I've built a lot of video synths at this point, and I would love to try reconceptualizing them into a miniature, intentionally-constrained format. I've worked with some cool transflective two-color 400x240 displays that might be the right size, so it could have a nice consistent look too!

Some kind of sync pulse generator

Since pocket operators can synchronize to a simple square wave timing signal, maybe I can build something to generate that... like a crank, or a wearable that measures your heartbeat, or a pedometer! I've done an experiment with heartbeat-powered BPM in the past and found the sensor to be very finicky, but I'd love to revisit this.

I loved the whimsy of the Sweatshirt Operator, but ultimately I decided to go with the PO-Video — mostly because I wanted it to be real so that I could play with it :)


High-level design

Next I had to figure out how to fit all the components into the Pocket Operator format. Fortunately TE provided files showing all the important dimensions of the pocket operator boards. I pulled up Adafruit's measurements for the Sharp Memory Display, and realized it's really close to the width of the PO circuit boards — it's just 3.5mm wider. I would have loved for it to fit exactly on the board, but figured that was close enough that this might work.

The next step was making a few mockups. I roughly scaled these images to be the right size relative to each other in Figma and started figuring out how I wanted to rearrange things. On the left is a photo of the PO-33 K.O.!, and on the right are three variations I considered:

  1. Extending the entire board vertically while keeping all the standard buttons and room for a model name + logo (which I would swap for an RMNA wordmark)
  2. Deleting two rows of buttons while keeping room for a model name + logo
  3. Deleting one row of buttons and the model name / logo

After looking at it for a while I decided option 3 was the best compromise — staying as close as possible to the original pocket operator form factor felt right, and I decided that the extra row of buttons would be more useful than room for branding (which I could display on a boot screen if I wanted).

Sacrificing one row of buttons would likely mean doing an 8-step sequence instead of 16, but that seemed ok too, since the visuals can move around a lot in just a single step anyway.

Inputs

After reflecting on the past video synthesizers I've built, and brainstorming and sketching a bit, I had a rough idea for how I wanted the interface to work. The basic concept was similar to the Video Sequencer, in that what you see on screen is composed of several overlapping layers, each of which is like a "drawing tool" based primarily on some basic shape (circles, lines, triangles, etc).

Here's my rough mockup of the layout
  • The typical PO-standard buttons:
    • Layer select
    • Project select
    • BPM select
    • FX modifier for punch-in effects
    • Play / pause
    • Write mode
  • 8 buttons to punch-in visual layers, or toggle steps on and off in write mode
  • Three "style" buttons to select one of three options for how a layer gets generated — this would turn 8 drawing tools into 24
  • A black / white toggle to set the primary color of the active layer

There were two major design questions I had related to the generated visuals:

At this point, it seemed like I had enough of the design pieces in place that I could start working on the circuits. I had a lot of other design work to do, but I wanted to do it with the actual working hardware as soon as possible. Both of these questions in particular required a lot of tinkering with working code, so we'll come back to these later.

There's only so much you can solve in your head!


Components & Circuits

Here's everything I used in this project:

The total cost for these parts (not including the PCBs) was ~$100 to assemble one PO-Video, and I bought some backup parts just in case I bungled something. Most of that cost is the screen though, which comes in at a whopping $45. It's so unique though!

After poring over datasheets and tinkering and measuring I started making a circuit schematic in KiCAD.

What's going on in here?

I'll be honest I kinda YOLO'd this schematic and went right into PCB layout. I did test the memory display on a breadboard so I could get a sense of the refresh rate of the display, but I didn't mock up this circuit really. I tripled checked things and then tried to get the PCB done ASAP so I could send it off and hopefully have time to do a second revision if there was an error I couldn't solve with a few hacky jumper wires.


PCB Layout

I do not have a lot of experience doing this — I've made a few small boards, but this was definitely the most elaborate PCB I've made so far! The boards I made previously were simple enough that the layout was pretty straightforward. This one took some experimenting! Doing the schematic first is nice because KiCAD can tell you if you forgot to connect something in the schematic.

I realized that there was enough criss-crossing of traces that I would need a more systematic approach, and I settled on a basic strategy of doing vertical traces on the bottom layer and horizontal traces on the top layer. I'm not sure if there's a better standard approach but that seemed to work well enough!

This is a two-layer PCB, in that there are components on both sides, and little printed connections between them on both sides. Here are views of both layers combined, then just the top layer (red), and just the bottom layer (blue).

I made (at least) two mistakes...

Fortunately neither of those are deal breakers! I was able to jump the LED data connection to the next pin over, and I'm just living with a backwards power switch.

I sent these boards off to JLCPCB, and it cost ~$50 for five boards, and to my surprise they arrived in ~4 days. Wild!


Assembly

A lot of these components are surface mount, and very small. I had done a bit of surface-mount soldering with my soldering iron before, and it's kinda doable. But these components are close enough together and some (like the LEDs) are a bit more delicate, so I decided to upgrade my setup a bit with a new tool: a hot plate!

This thing heats a circuit board from underneath, and you can attach small components with solder paste that turns from goo to nicely melted solder in just a few seconds. It's also good for loosening components that you want to remove or rework later.
If you haven't seen this before, it's pretty fun to watch. Here's a couple LEDs getting soldered with this hotplate.

The paste is like little balls of solder suspended in some gooey medium. As it heats up the balls of solder melt and combine, and the white solder-mask keeps the solder stuck to the pads and not the rest of the board. The effect is that the parts kind of slide into place under surface tension.
It's a bit hard to see what's going on when you're working with small components like this, so I checked all my work with a USB microscope. Sadly not all of the LEDs wound up working... I think it's maybe due to some janky solder paste connections, so I'm going to try cooking it again on the hotplate.

In the meantime, I decided to move on and not have LEDs for the sake of time... I have a whole screen to indicate status with anyway :)

After a bit of hand soldering on the through-hole components, it was all assembled! Side-by-side with a real pocket operator, it's looking pretty good! Because I was using larger NeoPixels instead of the tiny red LEDs on the official ones, I didn't have as much space for fun graphics below the buttons — there are some tiny icons there though. When testing all the components, I discovered that only the first six LEDs in the chain work... I'm not 100% sure why, but my hunch is that there's a wonky solder paste blob somewhere. There's actually a separate problem that makes the LEDs difficult anyway, so I wasn't too stressed about that — I'll mention that issue later.


Code

At this point I was able to test all the different components of this device together. And everything pretty much worked as expected! (except the LEDs)

So now I could move on to making it generate pretty visuals. I have a lot of experience building video synths with the RP2040, so I already knew how to make the sequencer part work, and I had some good ideas for visual patterns I wanted to try, but I had a big technical question to figure out first:

Long story short: yes! With some constraints.

This is a video from my first memory display test. Tinkering with the display quickly made me realize that wiping and redrawing the canvas from scratch doesn't look great because of the somewhat low refresh rate (compared to DVI at least), and single frame buffer for this display — it flickered heavily. I decided to embrace the contraints of this display and rely mostly on small incremental display updates and letting the framebuffer accumulate messy overdrawn pixels over time.

So here, it's really just drawing one circle during each frame, which looks much better! In the final version of this project, the UI strips on the sides are redrawn from scratch each time (to cover up anything from the canvas that bleeds over), but the central canvas just builds up a big mess from small incremental shapes.
This is a shot of when I got the mirroring working for the first time. After I had spent a few hours rooting around the PicoDVI library, I decided for the sake of time and my sanity I would just try the inefficient route, but it actually worked out just fine.

Once I got that figured out, I was really cooking, and started experimenting with patterns and shapes, and I returned to those design questions I mentioned earlier:

Let's dig in to each of these!

Interesting two-color patterns

With some experimentation I found a couple of guiding principles that made for interesting 1-bit visuals:

Not every layer follows every principle, but I tried to just keep these in mind when working on the pattern code. I'll also note that as of today I'd say the existing layer options are very much a WIP first pass!

Efficient knobs

TE does a great job of making sure that even though you only have two knobs on a pocket operator, you can get surprising range out of each individual sound. One easy trick is to use a single knob to control multiple parameters, like a macro — a single knob might control both pitch and some aspect of the timbre, or volume and the decay time.

With a video synthesizer, you often have even more parameters at your disposal:

Ideally I wanted it to feel like you're discovering interesting moments of harmony and balance at several points in the range of these knobs — so how could I make a system that allows people to navigate so many parameters with so few physical controls? For this project I tried something I'm calling a "cyclical macro".

As an example, let's say we want to control the size and X position of a circle with one knob. In a typical linear macro we could say when the knob is at 0, size = 0 and x = 0, and when the knob is at 1023, size = 50 and x = 320. But what if I want a small size and a high x? There are some combinations that are impossible to achieve! A cyclical macro might sweep through the entire range of size values twice, and the entire range of x values five times, so that somewhere in the 0-1023 range, you can get almost every combination of size and x position, with smooth transitions between.

I defined a little function like this, and it works great!

long cyclicalMap(int pot, float multiple, float phase, int min, int max) {
  int range = max - min;
  float cycle = sin((pot / 1023.0) * multiple * TWOPI + (phase * TWOPI)) / 2.0 + 0.5; //0-1
  return(min + (range * cycle));
}

Interface

With those major technical and aesthetic design questions answered, the rest of the project was mostly just making fun patterns. The last major piece of work was the UI. Official Pocket Operators have very charming custom LCD screens that evoke tamagotchis or a game-and-watch, with little characters that animate back and forth to the beat and tell a little story. I wanted to make something cute, but not necessarily as abstract. I thought it would fun to have a generative art tool look kind of like an old drawing app like MacPaint — a computer art interface that required painstaking manual work twisted into something automatic and a bit opaque.

On the left is the toolbar, showing icon representations of the 8 drawing tools / layers at your disposal. There's also a color swatch indicator that shows the color of the selected layer. Any layers that are active and drawing to the canvas are inverted, and the most recently selected layer has a little bar next to it in the margin — this is the layer that the knobs and other buttons control.

Below that is a BPM indicator ("TECHNO" / 140 BPM), a tiny 8-step sequencer (showing the active steps for the selected layer), and a play / write indicator. On the right side are two bars showing the values of the knobs.

I designed that UI with vector illustrations in Figma, but I had to translate it to this 1-bit display. I could have drawn it with literal shapes, like the stuff on the canvas, but I thought that would be slow and tedious to program. So instead I exported pngs of all my UI elements and converted them into bitmaps using image2cpp. That tool will convert an image into 2-color b/w bitmaps, but then also format the data as char arrays that you can store in program memory on your microcontroller, so you don't have to load and decode image files.

For example, here's the char array version of the "Layer 1" icon:

// 'Layer 01', 24x16px
const unsigned char epd_bitmap_Layer_01 [] PROGMEM = {
	0xff, 0xff, 0xff, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x81, 0xff, 0xf1, 0x80, 0x00, 0x01, 0x9f,
	0xfc, 0x01, 0x80, 0x00, 0x01, 0x80, 0x3f, 0xf9, 0x80, 0x00, 0x01, 0x81, 0xff, 0xc1, 0x80, 0x00,
	0x01, 0x9f, 0xff, 0x81, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff
};

Pretty neat! This wound up being plenty fast, and has the added benefit of making it easy to invert the image too, which I used for the active states.


Future work

I have a lot of things I still want to do on this project!


Source code + project files

Once I clean up my code a bit and finish a few more things I may release the source code and project files (PCB layout etc) in case any of y'all want to take a shot at building one! So stay tuned :)