Tips on Setting Up the GamePi43 RPi Retro Gaming Kit

Recently I got very interested in retro gaming, and began looking for solutions that I can use to build my own portable retro-style gaming console. I could just design my own and 3d-print a case, but I did not want to go through all the trouble doing so if one is readily available. Additionally, I wanted to make use of my Raspberry Pi 3B as it has been lying around doing nothing and collecting dust for almost two whole years.

What I ended up buying was one of WaveShare's gaming console kits, GamePi43. It is basically a shield PCB made for the RPi3, with a D-pad and some buttons pre-installed, along with a full enclosure. It is powered by two 18650 lithium ion batteries and has a built-in charging IC. The screen — a 4.3 inch IPS panel — also looks extraordinarily nice for something at this price point.

Upsides aside, like many electronics made in Shenzhen, there are some quirks with its official documentation and also things one can modify to improve upon. Listed below are some tips to work around issues with its documentation or drastically improve its user experience.

System Image / Drivers

Despite WaveShare's claims on their Wiki page, the case can actually be fully operational without using images provided by them or executing any of the scripts they have listed on their page. There are only two things that needs to be done upon a default RetroPie installation to make it fully operational inside the GamePi43 case.

Update (2020-09-24): You don't actually even need the retrogame daemon described below. I have written a Device Tree Overlay for GamePi43's GPIO layout, and you can use the file (and instructions) available at this gist to replace the following paragraph of instructions. Going the Device Tree Overlay path allows the input events to be processed in kernel instead of in userspace and reduces latency significantly.

The first is to enable controller input via GPIO — the D-pad and buttons present on the case are actually connected to the Pi's GPIO pins. The “driver” provided by WaveShare is actually the same as the retrogame daemon released by Adafruit, and you can just download the binary from Adafuit. I just downloaded the binary and put it in /usr/local/bin/retrogame, gave it +x permissions, and then extracted /boot/retrogame.cfg (you might want to uncomment the ESC line) from WaveShare's “driver” image and placed it in /boot. Then, unlike what is done in the official driver image, I used a systemd unit to start the daemon on boot

Description=Retrogame GPIO Input Service



You might now notice that the screen looks blurry for some reason. This is the second change to make — add the following to /boot/config.txt:

hdmi_cvt 800 480 60 6 0 0 0

(You can make these changes by plugging a keyboard into the Pi's USB port)

Screen Blanking

By default the screen is never turned fully off on idle. This can be problematic for heat output, LCD lifecycle, and more importantly, if you want to use your GamePi as a power bank (lol). Fortunately, the solution is pretty easy: just add hdmi_blanking=1 to /boot/config.txt, and change consoleblank=0 to consoleblank=<timeout_in_seconds> in /boot/cmdline.txt. Now, if the machine stays idle for <timeout_in_seconds>, it will turn the screen completely off.

“Soft” Halt / Power On Button

The GamePi43 comes with a clicky power switch at the top, which is nice, except that the switch kills power physically and does not allow a clean shutdown. You can run shutdown in command line or from RetroPie's menu, but that puts the RPi into a halted state that cannot be waken up under the default configuration of the case, and you still need to turn the power switch off and then on to power it back up again, which to me feels far from elegant.

After a bit of digging I learned that you can actually wake up a halted Pi by pulling GPIO3 (pin 5) LOW. Unfortunately, according to WaveShare's documentation, GPIO3 is unused in GamePi43, so we do not have anything on the machine that can power it up. What I then realized is that GPIO2 is actually used for the HK button and it is an active-LOW momentary switch, which means that if I short GPIO2 and GPIO3, I should be able to use the HK button as a soft (graceful) power button (because now HK pulls both GPIO2 and GPIO3 to LOW).

The mod was quite simple. I just pulled the Pi out of its socket on GamePi's board and then shorted the legs of the socket corresponding to GPIO2 and GPIO3 (pin 3 and pin 5). To short them, I simply cut a short piece of resistor leg and soldered it to both of the two pins. You could also just short the two pins on the back of your Pi but I figured that it's better to do my modifications on GamePi instead of my Pi.

Now, after you run shutdown -h now in the OS, you should be able to push the HK button once to cause the Pi to boot back up. All that's left is to write a simple script to add shutdown feature to the HK button

#!/usr/bin/env python

import RPi.GPIO as GPIO
import subprocess
import time

GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
  GPIO.wait_for_edge(3, GPIO.FALLING)
  down_ts = time.time()
  GPIO.wait_for_edge(3, GPIO.RISING)
  down_secs = time.time() - down_ts
  if down_secs >= 3:
      # Shut down if long-pressed for more than 3 secs['shutdown', '-h', 'now'], shell=False)

The scripts listens for push and pop events of GPIO3 (now shorted to the HK button) and triggers a halt if the button gets pushed for more than 3 seconds. Just make the script run on boot using systemd or whatever you like, and you now have a graceful shutdown / power on button in place of the forceful power switch.

Joystick-like Cap for D-pad

Let's face it: the D-pad that comes with GamePi43 is sub-par. It is hard to press and makes my thumb sore all the time, and you cannot even push down more than one direction at a time due to its sheer stiffness.

When I was playing with another open-source retro console owned by my sister, I noticed a trick that they used to make the D-pad feel better. All they did was sticking a round cap upon the D-pad (it came as a separate part that the end user puts it on), and suddenly the D-pad feels almost like a joystick. Of course, there are dents on the round cap to make it fit fingers better.

Learning from this trick, I quickly did some measurement on the D-pad of GamePi43, and then made a model in OpenSCAD similar to the one on my sister's console.

$fn = 100;
d = 23.3;
cross_width = 8.5;
dpad_height = 1;
cap_height = 5;
cap_roundness = 1;
dent_size = 12;

intersection() {
    union() {
        cube(size = [d, cross_width, dpad_height], center = true);
        cube(size = [cross_width, d, dpad_height], center = true);
    cylinder(h = 1, r = d / 2, center = true);
translate(v = [0, 0, cap_height / 2 + dpad_height / 2])
    difference() {
        minkowski() {
            cylinder(h = cap_height - cap_roundness * 2, r = d / 2, center = true);
        union() {
            translate(v = [0, 0, dent_size * 2])
                sphere(dent_size * 2);
            translate(v = [5, 0, dent_size])
            translate(v = [0, 5, dent_size])
            translate(v = [-5, 0, dent_size])
            translate(v = [0, -5, dent_size])

This was then printed on my Ender-3S and then stuck to the D-pad using some 3M double-sided tape.

The D-pad now feels way better than it was before, but unfortunately it is still stiffer than my liking. Nevertheless, you can at least press down diagonally with this simple mod.