After I finalised my case design, I shifted attention towards getting the Raspberry Pi configured to run games in the way I wanted. I basically wanted to be able to run existing python/pygame games on the device, making sure that the screen, audio and input from buttons via GPIO would all be working smoothly.
I started with the 27-05-2016 build of Raspbian, standard config for expanding the boot partition and configuring for a 104 key keyboard. I followed this guide for installing the kernel modules for the PiTFT 2.8 support. I wanted to use pygame and have support for the touchscreen, so I followed this guide to ensure the SDL version underneath pygame would support the screen (apparently needs to be SDL 1.2, there are reports of issues with SDL 2.0). I wrote a simple pygame app to test the touchscreen and test pre-installed gpio-connected buttons that came with the screen. I added a line at the top of the script before pygame.init() to ensure the SDL output was set to the framebuffer:
os.putenv('SDL_FBDEV', '/dev/fb1')
The touchscreen was working great, and very conveniently linked straight into the mouse drivers, such that touches come up as mouse click events in pygame. I added these lines in to get this happening:
os.putenv('SDL_MOUSEDRV', 'TSLIB')
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
I used the python RPi.GPIO package, that came pre-insalled, to try and read button presses and at this point discovered the performance was fairly underwhelming: I was using event detection, and tried a combination of logic rules to read whether the pin was high or low, to detect short presses and long button holds, also tried playing with the bouncetime argument: all to no avail. I ended up realising that Adafruit had actually written a really nice c-based daemon, "Adafruit-Retrogame" which would map gpio events to key strokes: exactly what I wanted! And it worked perfectly: configured it to the keys I wanted, compiled it and added it to /etc/rc.local to run in the background on boot up.
Wireless: I setup my RPi to connect automatically to my wireless access point using this guide. I really wanted to get wireless working, as I knew from the case shell I wanted, it would be hard to feed one of the USB ports to the side for a keyboard or usb drive etc. (the other alternative for debugging would be a Bluetooth keyboard, but I still also wanted to be able to copy games on/off the device). I found the wireless would drop out constantly: turned off the pre-installed wireless power management: single line "sudo iwconfig wlan0 power off" added to /etc/rc.local to turn off every time on boot: wireless then working perfectly.
The last thing I did was to test the performance of one of my previous pyweek entries to see how it would go on the pi. The first thing I noticed was considerable audio lag for sounds (music was ok, but sounds would play at least 300-400 ms after being triggered) ... Found out I could fix this by reducing the buffer size using the following pre initialisation line in all python/pygame code:
pygame.mixer.pre_init(44100,-16,1,512)
More details on this here. The game was set to run at 30 fps, but I was only getting about 22-23 fps and the graphics were pretty choppy. I tweaked the PiTFT frame rate and SPI frequency by editing the settings in /boot/config.txt editing the relevant line to:
dtoverlay=pitft28r,rotate=90,speed=42000000,fps=30
After a bit of experimentation, these settings seemed the best balance for a not too choppy graphics and enough CPU left over to run the game smoothly.
Now that the Pi was setup, it was time to start putting all the hardware together!
Sunday, July 10, 2016
Wednesday, June 29, 2016
Homemade Handheld Videogame Console: Part 1
Ever since I started programming games, I've always been keen on the idea of building my own custom hardware to run them. Its one thing to write a game that runs on a PC or laptop, but running on hardware specifically designed for games is just more exciting. I've found often when I'm writing a game I am imagining holding a gamepad in my hand, and that a keyboard is just a poor substitute. I'd previously played around making an Arduino-based video game console and I wanted to make something with a bit more performance (colour graphics!). Other design criteria were:
- Ability to play games written in python: because I'd already written a few from previous pyweek comps and its the language I'm most comfortable with and hence most likely to want to develop more games in.
- Portable: I wanted to try something portable ever since I saw the PiGRRL.
The first video game device I owned as a kid was the original gameboy ... it has a special place in my heart; so many hours spent playing Tetris, Metroid II, Super Mario Land, R-type, Adventure Island :) ... it was still working perfectly up until about 8 years ago when it reached a stage where it would chew through a pack of double As in about 180 seconds. Sadly it no longer powers up, but the memory lives on. The only other handheld I have is a DS Lite, which I did a bit of homebrew development on, but never finished anything.
Based on the inspiration provided by the PiGRRL, I decided to go with a Raspberry Pi 3 as the core of the console, as I'd had experience with it before, runs pygame reliably, could find a good screen (PiTFT 2.8 LCD screen capable of 320 x 240 pixels) and GPIOs make it easy to design custom buttons. I decided to go with the same audio amp and power boost converter/USB battery charger used in the PiGRRL2, as I hadn't had much experience with these before, and they seemed to play well with the RPi. Good thing about the RPi3 is that it also has built-in wifi and bluetooth, which means I can debug/copy code on/off without having to open up the case or worry about feeding out a USB port from the case, which would put constraints on the case shape.
So I started doing some research on different handheld consoles to get a feel for what I liked/didn't like. I was keen on a landscape format (i.e. DS Lite or PSP) rather than a portrait format (i.e. Gameboy), and I started sketching out some case shapes. I walked around JB HiFi for a bit trying out the new PSP Vita and the 3DS: the thing that gets me about these modern handhelds is that the case is thin, the buttons are super small and located pretty close to the edge of the device. I find them kind of uncomfortable to play after a while ... I dunno, I guess they are more designed for a younger market these days with smaller hands, but my hands aren't that big either. I pick up my old gameboy again and it's more comfortable: a combination of being slightly fatter and a bit heavier too.
So I finalise some sketches for the shape I like and it's time for some CAD. Last time I did any serious CAD was in undergrad, so I had some rehashing to do. From a random conversation I had with someone about 3D printing, I remember them mentioning parametric cad modelling and "OpenSCAD", in which objects are "programmed" ... the concept was appealing to me (as was the fact that I could get OpenSCAD free and open source). A week (and a bit) later, I've got the case design finished:
Man, it took me such a long time (learning curves in OpenSCAD, and "programming" the shape I wanted took a few goes, implementations that didn't work) but I'm happy with the end result, and because its parametric I can easily adjust anything that is not working out further down the line.
Subscribe to:
Posts (Atom)



