I grow up in the era of Commodore and Atari. In this time, the CPU performance was nothing compared to what is available today and one really needed to use a lot of tricks and tips to get enough power from the devices (e.g. sinus lookup tables). In some extent that is of course valid today for the AAA game titles but for smaller games, just the amount of RAM present in a ordinary PC is multiple times compared to back then and of course there are numerous libraries and game engines today that get you quickly up to speed without having to spent a lot of time thinking how to implement stuff, like e.g. scrolling background or sprite handling. All those tricks and tips used back then is of less use today and might soon be forgotten. I am not saying it is a bad thing, since I believe techonology progress is in general a good thing and it is as it is but I cannot help feeling a bit sad about it.
I decided to build a small handheld console that can bring life in those old algorithms and refresh my own memory. I have always been fascinated of Nintendo GameBoy, SEGA GameGear and all those hand held consoles that popped up in the 80/90th. A good base for such console would be the STM32H745 from ST Electronics. It is a dual core Cortex running at whoosing 480MHz and should be plenty for my small games. Yes, even that is a lot more CPU power compared to back then but the displays of today have a higher resolution and more colors that actually requires a fast MCU with a lot of RAM to keep the framebuffer in memory and still get a descent screen refresh time. I decided to do the game logic in Lua, a interpreted language that I followed for a couple of years but so far done very little with and a small TFT LCD 128×128 pixels (normally a game console has a screen with a widescreen-ratio but I thought it would be interesting to use a squared screen). I reserved some extra RAM for the framebuffer to be able to go up in screen resolution if needed.
With that as a concept I started with the design.
- Game logic in (precompiled) Lua
- Battery powered
- USB charging
- Download games using USB connector
- Protected against malcious games (that is, supervise the game running and if it crashes or goes in infinite loop inform user in a nice way)
- Vibration motor
- Small speaker for sound
- External flash memory for game storage (graphics take lot of space!)
- Networking (not TCP/IP but a simple protocol to let two players play against each other)
- 128×128 TFT LCD (parallell 8080 protocol 16 bits)
- (Website to create games online)
- Open source, Open hardware
I want my console to be small but still manageable. Since I handsolder the PCBs I cannot use too small components or packaging like BGAs.
- Power supply
Internal LiPo battery with charging, based on MCP73831.
A mini USB connector that serves two purposes: Charge the internal battery using a standard mobile charger and enables the user to download new games (and possibly update the firmware).
A SWD connector for updating the MCU.
4. Battery level voltage divider
STM32H745, dual-core, Corex-M7@480MHx & Corex-M4@240MHz
6. Power supply and power off switch
A game without any sound would be boring. A onboard piezosummer generates some simple sound effects.
8. LED backlight driver
9. Vibration motor driver circuit
Gives the user a haptic feedback.
10 External memory
MX25L512G, An external quad SPI flash memory with 64 MB to store all that graphics in a game.
11. Crystal for MCU
12. Battery status and User LEDs
13. Game buttons
Standard buttons for direction: Left, Right, Up and Down plus two additional buttons A- and B-button. A separate button that pauses the game and enters the main firmware menu.
128x128xRGB565 pixels TFT, setup to communicate with the 8080 interface (parallell, 16 bits) using the FMC feature of the STM32H7. PWM controlled backlight to set light intensity and enables fade in/fade out effects.
The initialization is done by the Cortex-M7. When it is ready it will start the M4 and then enter the main menu. If the user selects to start a game from the main menu, Cortex-M7 will ask M4 to run the Lua script and it will start acting as a slave CPU for the M4. The M7 is responsible for drawing the screen according to instructions from the M4 (the M4 gets its instructions from the Lua script). It will also supervise the M4 so if there is a crash or similiar, it will gracefully turn off the M4 and enter the main menu. No RTOS is used in the cores, only state machines.
Increase screen to 320×240, add touchscreen.