From Trammell Hudson's Projects
SHA2017 Badge e-ink Gameboy
When I saw in Anne-Jan's presentation at hackon.nl that the SHA2017 badge had a very neat e-ink screen and a Gameboy-esque deisgn, I knew that it needed a retro game emulator.
There was a manufacturing glitch that required surface mount rework on half of the badges -- a (counterfeit?) USB to serial IC was drawing too much current on its RX pin, leading to it the ESP32 browning out. The fix was to cut the trace and solder a 10k resistor across the cut, but there was very little room on the pin to do this, so we spent the day at Rev Space in Den Haag staring through a microscope. After reworking many badges, I was able to take one home to hack on before SHA.
The official badge API is in Micropython, and the python extension to talk to the e-ink is in C. The python interface is really neat for lots of reasons, but the emulator I wanted to use required native code, and I wanted to be able to call it from the Arduino ESP32 framework to make it easier for others to add their own games without dealing with the Esprif SDK directly. A few hours of hacking later, I had enough of a shim layer to be able to call their badge e-ink and read the cap-sense buttons from C++, and the badge team merged my pull-request into the mainline tree.
The gnuboy Gameboy emulator is GPLed and works with most games, so it seemed like a reasonable place to start. The ESP32 only has 256KB of RAM (but plenty of flash), which required changing some of the framebuffer and RAM layouts in the emulator's LCD tile cache. sprite_tm suggested some hacks to improve tile rendering even more and now there is RAM to spare. Games like Tetris are playable since the screen doesn't update very fast, but Mario and other side scrollers have lots of ghosting.
The first big patch was to move the e-ink drawing to a separate FreerRTOS task (the esp32 has dual cores) and use a semaphore to signal when a new frame is ready. This still had lots of flashing and 1-0.5 Hz refresh rates, which were not playable. To try to improve the performance I hacked on the e-ink refresh LUT and changed the timings to find ones that had less flash and acceptable ghosting with about a 3 Hz update rate. They still need a full refresh periodically and there appears to be a burnin problem for games that are left running for too long. Also, the capacitive sensors have a long latency, which makes timing sensitive games very difficult.
The badge was a hit a the camp and I ran into a backpack-sized Gameboy re-make, also running Super Marioland.
If you want to flash your own badge, the GPLed github/osresearch/gamebadge is available. You will have to provide your own Gameboy ROM image -- name it game.rom and run this to create a .c file that can be linked into the firmware:
xxd -i game.rom | sed 's/unsigned/const unsigned/' > game.c
If you're feeling like extending the system, the badge has a micro-SD card slot and could load the game from there instead. That would add to the retro feel of swapping carts to change games!