Earlier this year, I decided to design a project to evaluate Seeed Studio’s Fusion PCBA service. I didn’t have any immediate need for a PCBA, and so I found myself in the classic hobbyist situation: a solution in search of a problem.
The project needed a low parts count, a small PCB, and it had to be fun to design. I settled on a programmable Gameboy cartridge to meet my hobbyist needs. So, with Seeed Studio’s fusion PCBA parts library in hand, I fired up KiCAD and began my design journey! I began with some handy footprints from Gekkio’s awesome Gameboy footprints library, available on their GitHub: https://github.com/Gekkio/gb-hardware
Unfortunately, I had chosen the wrong footprint for the selected Flash chip, but Seeed Studio caught the issue and was able to help me correct it easily. Overall, their service was very good! I happily received my PCBA’s in a number of weeks.
Upon receiving the boards, I soon discovered that I did not place the mounting holes in the standard locations for a Gameboy shell. No worries though – that’s where FreeCAD and a set of calipers come in handy. Exporting a 3d rendering of the PCB from KiCAD took any guessing out of the equation:
The final result looks pretty good – I will note that a Gameboy PCB should be 0.6mm, but in my excitement, I must have accidentally selected 1.6mm. Therefore, the cartridge shell is very thin at the back, but the PCB gives it rigidity.
Setting up a project in STM32 Cube IDE is trivial work, however – I discovered that I had used a slightly incompatible footprint for the MCU. One of the pins is no longer available for GPIO:
I double-checked all of the library components and indeed found that it was my mistake. That’s the price you pay for feverish hobbyist development, I suppose! Fortunately, I have GPIO to spare (At the top of the PCB), so I can do a hardware patch without any issues.
In bringing the board up, however, I have found that I am unable to get the MCU running at the intended 84 MHz – anything above 48MHz triggers hard faults in the CPU. Luckily, STM32 Cube IDE makes it trivial to configure global clock settings. I am not yet sure if this will be fast enough to meet the timing requirements of the Gameboy – I was unsure about 84MHz being fast enough. But, we will soon enough find out.
Stay tuned for hardware patching and new revisions!
As far back as I can remember, I’ve been fascinated with computers. This began with the venerable Nintendo Entertainment System – as a child I often dreamt of making my own NES game. This interest lasted well into my teen years, when I would read programming how-to’s from NesDev and other corners of the internet.
Later in life, I met a fellow named Brad Taylor – he was the author of many programming guides for the NES, and just happened to show up at my local hackerspace one fateful day. I had no idea this guy lived in the same country as me, let alone the same city – small world! With Brad’s NES expertise and my PCB design skills, we joined forces to make a USB reprogrammable NES cartridge. This project would be my first foray into PCBA (Printed Circuit Board Assembly), wherein a vendor does all of the component placement and soldering. This was a big deal for me!
Hardware Design
Initially, Brad and I wanted to make a PCB that could do some very ambitious things, requiring either a very capable processor, or an FPGA device. We began down this path, but soon realized that we were biting off much more than we could chew for something we had never done before. So, we decided to take a step back, and make a smaller project to verify the foundations of our design. Our final design goals were:
Be programmable via USB
Be able to play NROM format games
Feature nonvolatile storage (no battery required)
Be as cheap and easy to manufacture as possible
Component Selection
One of our design goals for this project was to make it cheap and easy to manufacture and prototype. That meant excluding BGA packages, which really limited our options. We also opted for a 2 layer PCB to keep manufacturing costs down, which made the layout more challenging than it would be on a 4 layer board.
For the memory, we used whatever was cheap and available from digikey – and could tolerate the NES’s 5V logic buses. We wound up using a SST39SF010 device (one for the PRG memory, and one for the CHR memory).
For the USB interface, I took a misstep in choosing an FTDI FT232H USB interface – I had selected it solely because I had previous experience using this chip. So, we did save some time on having to learn new tools – but at a unit price over $10 at the time, we likely could have found a cheaper option, and simply spent some time learning a new platform. Lesson learned!
One of the challenges of making an NES cartridge is interacting with the console’s lockout functionality. Luckily, the krikzz forums had a firmware load for an Attiny device, so we simply included this same chip in our design, and flashed the provided firmware onto it.
The rest of the components in this design were fairly standard, and included some generic shift registers and regulator circuitry. We used the shift registers to take serially-loaded memory data, and present it to the flash chips as a 48-bit parallel interface.
Fundraising
PCBA can be a costly service, and I didn’t want to go out-of-pocket on the order of $100’s – $1k for a hobby project. To this end, Brad and I opted to fundraise for a production run by following a crowdfunding model. We didn’t want to go as far as a kickstarter, so we solicited local tech groups (as well as friends and family) to see who would be interested in owning one of the cartridges. We received 13 orders and were able to keep the per-unit cost to around 80 dollars, which was a reasonable amount for all involved.
PCB Design, Iterations, Oversights
This design went through a number of hand-soldered prototype revisions before I placed the final order. We never did get a prototype 100% working due to the difficulty of soldering fine-pitched components, but we were reasonably confident that it would work (this later turned out to be partly incorrect).
One oversight was the control circuitry for the “read only” signal to the memory circuitry – we had assumed that the FTDI device would always provide a logic high on a particular signal, and we were using this signal to determine whether or not the device was plugged in to a USB host. This proved wrong, it only held true for a few units. We had to re-work the PCBs with a hardware patch to correct this:
This patch takes one of the clock signals, rectifies it, and low-pass filters it to provide our “read only” signal. So instead of detecting if we are plugged in to a USB host, we now detect if we are connected to a powered-on NES. Luckily this patch saved the batch!
A more serious oversight existed in the design of the USB micro-B connector footprint. When I tested the assembled units back, they didn’t come up in dmesg… and the USB cable was getting hot to the touch. After some debugging, it turned out that the USB connector’s metal casing was shorting out the extra-long USB pads – I had designed them as such to ease manual soldering, but this was problematic for automated assembly. This was fixed by manually removing each USB connector, applying kapton tape to shield the casing from the PCB traces, and re-soldering it in place (yes, this was very tedious).
Software Design
Flashing Software Design
The flashing software for this design – the logic that shuffled a file from my PC to the cartridge – was simple in concept: use libftdi to connect to the USB interface, and bit-bang the memory data out through the shift register chain. I wrote a number of abstracted layers to produce the bit patterns needed for parallel memory programming, you can see a video of me testing the entire SR output chain below.
Unfortunately, I used up all of the FTDI’s I/O, and couldn’t route back a signal for the “Flash is done writing the current byte” signal. This meant I had to wait the maximum write time delay between every byte to ensure that it wrote successfully. I consider this the single largest oversight in the project, as it meant that programming an NES game (order of kB’s) would take 5 minutes or more. I did not realize just how long this would take until I had implemented and tested it. But, after a ton of testing with Brad’s cartridge reader device, we had a working unit!
Game Software Design
Making and selling a cartridge is all well and good, but I can’t go shipping it with material that I had no right to distribute. To that end, I fulfilled a lifelong dream and created an NES game, Harambe’s Revenge:
I could write an entire series of blog posts on how difficult it was to write this game. And for all of my efforts – it is a very basic game. I wrote it entirely in 6502 assembly, and did the graphics myself via GIMP. I used https://github.com/pinobatch/pently for the audio playback library, and started the project with Damien Yarrick’s Project Template. Brad’s knowledge of NES programming was invaluable during my efforts.
Lessons Learned
At the end of the day, we achieved our goals of learning to design for PCBA, and verified some design assumptions for a future board. We even successfully filled all of the orders. The most important outcomes, in my opinion:
Validate footprints for automated PCBA – casings can short out large hand-soldering pads
Bit-banging is a poor choice for programming a memory device, and while it kept monetary costs down, I wouldn’t opt for this approach again. If I were to redesign this, I would use an MCU with built-in USB functionality.
Start small – had we went for our initial design, there’s a large likelihood we would have not been able to complete it before losing steam. All of the work to make this ‘simple’ board took place over the course of a year!
Anticipate failure – we made more PCB’s than were required, as we anticipated that there would be some unit failures, and there certainly were.
Most of all – this project really drove home an important notion: projects don’t succeed on technical merit alone. There will always be difficulties – it’s not about how good your PCB layout is, or how elegant your code is. The success of a complex project comes down to perseverance and teamwork in the face of unpredictable problems. Having said that – thank you for all of your help and hard work, Brad!