Introducing, a prototype of what I am tentatively calling the ‘Arduboy Classic’ (with Kevin’s blessing?). Using an Arduino Leonardo (same ATmega32U4 microcontroller as the Arduboy), but with the screen, the buttons, the speaker, and the LED indicator all being provided by the front half of a classic Nintendo GameBoy!
Here’s a video of the prototype running some adapted Arduboy demos:
There are a few other components in the mix as well, an Arduino Nano (ATmega328) working as a sort of co-processor / LCD controller, and two other chips – a 2K dual-port RAM chip plus an 8-bit flip-flop which act together as a memory buffer between the Leonardo and the Nano. (And for the moment I’m also still using the GameBoy’s little power PCB to get the negative 20V required by the LCD.)
I had a breakout board made for the 21-pin connector which allows the ribbon cable from the GameBoy’s front daughterboard to connect straight into a breadboard for prototyping. And then started out with just the Nano and the daughterboard, working on hooking up all of the LCD’s control signals and getting something (anything!) to show up on the LCD – the awesome research into this by mARC at robotdialogs.com was a great foundation to be able to start from!
Once the Nano and the LCD were cooperating, I added in the Leonardo and started adapting the Arduboy libraries with the goal of feeding the Nano with some actual data to display on the LCD. Using the dual-port 2K FIFO (first-in, first-out) RAM as a middle-man means that there is no need for strict synchronisation between the Leonardo and the Nano – they can both be independently reading from / writing to the same memory without any conflicts, and once the Leonardo writes a frame into memory the Nano can keep reading that same frame until a new one is ready.
The second part of the memory buffer is a SN74HC374 8-bit flip-flop. Because each byte is only on the FIFO’s output pins for a brief moment, I added in this flip-flop to keep the data latched for longer so that the Nano can read in each byte straight off the pins without having to store anything in its own RAM. Another advantage of the flip-flop is that it has enough drive to defeat the RX / TX resistors on pins 0 and 1 of the Nano, which the FIFO alone cannot do and had me scratching my head for a while over unexpected vertical lines on the LCD!
The GameBoy speaker is driven directly from a single pin on the Leonardo, with a 220 Ohm resistor in series, and the GameBoy’s battery LED is connected to a PWM pin on the Leonardo to allow for nice controlled fades. The buttons on the GameBoy are arranged in a matrix with diode arrays like so:
…and so the Leonardo reads the button values in a two-stage process, which looks like:
pinMode(A0, INPUT_PULLUP); // Down & Start
pinMode(A1, INPUT_PULLUP); // Up & Select
pinMode(A2, INPUT_PULLUP); // Left & B Button
pinMode(A3, INPUT_PULLUP); // Right & A Button
pinMode(A4, INPUT); // pin 5, button diode arrays
pinMode(A5, INPUT); // pin 9, button diode arrays
I hooked the LCD's VSYNC pin up to a scope, and it is firing at around 80Hz – which means around 80 frames per second! Although a big part of the reason for this speed is that the Arduboy code on the Leonardo is only putting out 128x64 sized frames, so for each 160x144 frame drawn by the Nano, all of the pixels outside of that 128x64 'active area' do not require any decision-making, and so I just set the data lines to zero and clock those pixels straight out at top speed.
DDRF &= ~B00000010; // set A4 to INPUT, LOW DDRF |= B00000001; // set A5 to OUTPUT, LOW button_state = ((~PINF) & B11110000); // Down, Up, Left, Right DDRF &= ~B00000001; // set A5 to INPUT, LOW DDRF |= B00000010; // set A4 to OUTPUT, LOW button_state |= ((~PINF) & B11110000) >> 4; // Start, Select, B, A
The next step would be to move up to a bigger FIFO, and a microcontroller with more RAM, so that we can start working with the full 160x144 frame – for this purpose I have an 8K FIFO and a choice of the Mighty-1284P (which has 16K of RAM) or the Teensy++ (which has 8K of RAM) ready and waiting:
Of course, this will also mean more work on the Arduboy libraries to adapt to the bigger frame size. And while we’re at it, changing from the vertical byte orientation of the Arduboy’s display to a horizontal byte orientation would also be a handy optimisation – because at the moment assembling the value for one horizontal byte means accessing the values for eight different vertical bytes:
The end goal of all of this would be to produce a drop-in replacement for the GameBoy motherboard – I have already sourced components for the power switch, power jack, and volume dial. And there is ample space in the motherboard’s footprint for the two microcontrollers:
So, if you have read this far and you are still interested, I have setup a MailChimp list for sending out updates on the project, and would certainly be open to collaborating with others moving forward! (Kevin? )