An open-source handheld game console based on the STM32 microcontroller
For the past few years I've been spending a lot of time thinking about and developing embedded systems, from the Kitty-feed-o-tron 9000 to various cameras and light meters. Sometime around last christmas, I caught wind of NextThingCo's PocketCHIP, which is really a thing of beauty. Using a tiny Linux computer to as a retro game emulator is definitely nothing new (see the literally hundreds of DIY Raspberry Pi "retropi" systems out there) but it looks slick as hell and I find a lot of charm in the PICO-8 virtual console. On the other end of the spectrum, there's also the Arduboy based on the ATmega32u4, which also looks highly polished with its 128 x 96 monochrome OLED. (Interestingly, this configuration is almost identical to version 3 of my TSL2591 light meter, except with more buttons and a speaker! I really dig the 32u4.)
I was pretty close to buying one of these, until I realized that I could just make my own. In fact, I realized that I should make my own, for my own benefit - at least as a learning experience. At about the same time, I started investigating 32-bit microcontrollers for work, since many of them have an FPU and can do a lot of the number crunching that an 8-bit micro could not. I was using mbed to write code for a STM32 Nucleo board and a 128 x 128 OLED display from Adafruit, and it struck me - this could make an awesome game system! So, if you've stayed with me so far, that's where this project has its origins.
While I was waiting for my boards to come back from the fab, I came across the Pokketo on Instagram, which in concept is very much similar to what I'm trying to do here (although I'm not likely to try to monetize my design in any way). I think it's really cool that others are also developing awesome open source game consoles!
The idea is very simple. To make something that slots in somewhere between the super-simple 8-bit game systems and the monstrously powerful systems (in relative terms) based on Linux SBC's. I decided to use the venerable STM32 MCU, since the development boards are dirt cheap and are easy to program using mbed, which has a reasonable userbase and a good repository of existing code. From the beginning, I had a number of requirements in mind:
- Color display (at least 16-bit, 565 color), at least 96 x 96 px, at > 30 fps
- Mono sound, at least 3 channels, 8 bit resolution and 11 kHz sample rate
- "Vertical" form factor akin to Game Boy/Game Boy Color, at least 10 buttons, pocketable
- Removable flash memory, USB charging, programming and debugging interface
I would have been pretty confident about being able to do all of the above on an Arduino or Teensy, but I wasn't exactly confident about doing it with the STM32 - the mbed community is relatively small (and mostly based around the LPC series of boards) so if I got stuck somewhere I might have a hard time getting help. But, I already had a STM32F401RE Nucleo and an Adafruit SSD1351 OLED display kicking around in a drawer so I breadboarded up a quick proof of concept.
With a bit of finagling, I was able to write some code to interface with the OLED display via SPI, and to produce audio output on a 1-bit DAC. Both of these were a little challenging for a noob like me - the standard mbed SPI library is slow as molasses, and generating sound waveforms in real-time takes some careful attention to produce efficient interrupt routines. All told, I was able to squeeze 40 fps and 11 kHz 3-channel sound out of the STM32. Not bad at all!
I also wrote a silly little game creatively titled "Mr. Balloon's Awesome Adventure", which is basically a clone of the infamous "Flappy Bird". You guide a shiny red balloon through an infinite field of nefarious clouds, until you inevitably flub up and collide with one, at which point balloon pops and the game is over.
I was pleased as punch with the above results, so I got right to designing a prototype PCB in KiCAD. Just like coding, EDA is not one of my areas of expertise (but I'm working on that!). Over the past 3 years or so I've migrated from Fritzing (ugh) to Eagle (fun and slick, but the freeware limitations can feel oppressive) to KiCAD. I made the move because it's completely open-source, and it has that awesome 3D viewer.
This was my first major project made in KiCAD, here's what I came up with. You can see the Game Boy-esque form factor taking shape here. You can also see here that I could be bothered to make 3D CAD files to match some of the custom footprints. I also made a couple of tiny boards for a pogo pin probe for programming/USART debugging, not shown here.
At about the same time I also designed an enclosure in Solidworks, with the assumption that it would be printed from Shapeways WSF (white strong and flexible), one of my favorite prototyping materials. I settled on a simple two-piece design (minus the ten buttons). I think it would lend itself well to injection molding, with a little more attention to draft angle and wall thickness. Because I'm just a lunatic I also modeled the PCB (again). This helped me feel more at ease that it would all fit together properly without relying on the KiCAD model format that I'm not familiar with.
Luckily I'm blessed with access to lab space and a stereo microscope (actually an ancient wire bonder) to do my solder paste stenciling, component placing, and hot plate reflow. Some day in the near future I'll have to set up my own home facility to do this kind of work. This was far and away the most complex board I've reflowed, so it was definitely a learning process. I needed a few attempts to keep the stencil pressed flat against the boards when applying solder paste, and avoid "squishing" the paste all over the board. There were also a few expletive-inducing moments when I was placing a component and managed to drag a stray finger through the stenciled paste.
Luckily the reflowed board worked on almost the first try! I accidentally switched the pinout on two of the SPI pins for the SSD1351, but after a quick bit of rework, everything was working. Looks pretty spiffy in the purple and gold (University of Washington school colors - natch). Enclosing everything in the 3D printed case makes things look a bit more grown-up.
To me, the hardware was the easy part. The whole issue of writing code and getting it onto the board is another story altogether. As mentioned previously, I chose the STM32 series in part because it's supported by mbed. Yes, you can set up a toolchain and use a in-circuit programmer, but this seemed like adding an unnecessary level of complexity. On the STMstation, the pins needed for serial programming (TCK, TMS, GND, RST, at the bare minimum) are broken out to test pads that can be probed by pogo pins. The ST Nucleo boards include an ST-Link V2-1 unit which can connect to any STM32 prototype board as a mass storage device to simply drag and drop code exported from the mbed online compiler. No, it's not a simple as using the Arduino IDE, but it works, and pretty well.
At time of writing, I have two original applications working on the STMstation: "Mr. Balloon's Awesome Adventure" as highlighted earlier, and "MusiComposer," which is a very simple synthesizer. Here's a demo of it playing "Miku" by Anamanaguchi:
A couple of issues surfaced during initial testing of the prototype:
- OLED D/C and SCLK pinouts were switched. This was resolved by reworking the PCB with tiny 38 AWG wire.
- The high speed external clock (HSE) does not start. Luckily the STM32 also has an internal oscillator (HSI). The timeout for the HSE is long (10 s) so this must be corrected in the mbed-dev library.
- The trim pot for audio output is ineffective. In hindsight, it could be eliminated altogether.