Sunday, March 04, 2018

Nestronic System Architecture (Part 2)

(For an introduction to this project, please read the previous blog post.)

System Design

Now that the design of the system is mostly complete, I'd like to present it in a little more of a top-down fashion. First, I'll present a block diagram of the complete system. Then I'll go in-depth on how I arrived at all the relevant elements of the system. Finally, I'll show the detailed circuit schematics this all represents.

The design of the Nestronic consists of two major subsystems. First, there's the NES CPU Section, which builds around the RP2A03 CPU and contains everything necessary to actually synthesize video game music. Second, there's the ESP32 Microcontroller Section, which provided the front-end and completes the project.

Block Diagram

Thursday, February 22, 2018

Introducing the Nestronic! (Part 1)

Project Background


After finishing my previous project, I felt I needed something new to keep up the momentum. There were a lot of things I learned about during the development of the project, which I didn't use but but wanted to explore. I also liked the idea of projects that combined modern and retro elements.

I spent a lot of time scouring the Internet for ideas, but was frustrated with what I found. Far too many projects seemed to be rehashes of the same old ideas, often involving interfacing someone's favorite microcontroller to some sensor or display device. Plenty of elements that would be fun to use as part of a project, but nothing too inspiring on its own. In other words, I really didn't want to build yet another weather station.

One idea that did mildly pique my interest was that of a "modernized" alarm clock (kinda like this). You know, one that could actually sync its time via NTP and that wouldn't lose minutes if left unplugged for too long. I wasn't sure if this idea was tempting enough on its own, but perhaps it could be combined with something else...

As the search wore on, I eventually stumbled upon a project that really caught my eye. This project was Aiden Lawrence's Sega Genesis Music Player. It took the original synthesizer chips from the Sega Genesis, combined them with a modern microcontroller, and used all this to "authentically" play video game music. This idea was almost perfect!

Okay, I say almost, because I didn't actually have a Sega Genesis when I was growing up. Instead, I had a Nintendo Entertainment System (NES). So what if I could build a similar project around the NES? What would it take? And could I combine it with my previous idea to make the ultimate "Nintendo Alarm Clock"?

Unfortunately, unlike the Sega Genesis, the NES does not actually use separate audio chips. Instead, its CPU is actually a modified 6502 core combined with an integrated audio processing unit (APU). As such, I'd need a fundamentally different design. Instead of simply interfacing with audio chips, I'd have to actually build a system capable of running code on that CPU. Thus began a lot of research, including reading all the NES and Famicom schematics posted online. I also found the resources from the NESizer2 project to be quite valuable.

So I finally had my idea! Build a device that combined a NES game music player with an alarm clock! I could wake up to various video game soundtracks, and even get cool sound effects when pushing the buttons.

Initial Approach and Project Goals

The first thing I'd need for this project, is a way to actually run code on a NES CPU from within my own system. This would make it possible for the NES CPU to communicate with a data source and poke values into its audio registers.

There were two ways I could go about accomplishing this:

The hack'ish way involved a modern microcontroller messing with (or pretending to be) the memory on the CPU's bus. (The NESizer2 implemented something like this.) This approach certainly required fewer components, but would involve chasing clock timings. It also seemed a little bit too quick-and-dirty for my tastes.

The more conventional way, which I ultimately opted for, involved putting an SRAM, EEPROM, address decoding, and I/O peripheral ICs onto the NES CPU's bus. Doing this, I'd then write a complete program in 6502 assembly code to transform the NES CPU into an externally controllable audio synthesizer.

The second thing I'd need was a modern microcontroller to act as the front-end. I decided to use this as an excuse to play with the Espressif ESP32, which I had learned about during the development of my last project (which used an ESP8266).

Finally I'd need a bunch of peripherals... A nice display, an SD card interface to provide access to data, some input devices, etc.

At this point, I set out a number of basic goals for the project:
  • Use an authentic NES CPU (RP2A03) to synthesize audio
  • Use an Espressif ESP32 as the front-end microcontroller
  • Use entirely modern components (beyond the NES CPU)
  • Finally embrace surface mount components, which I'd explicitly avoided in all my previous projects

Music Source

At the outset of this project, the VGM (Video Game Music) format seemed like an ideal thing to start with. Its what Aiden's Sega Genesis project used. There were a lot of game rips already available, and the format was literally "poke this value into that register, sleep for X samples, poke this value into that register, etc." It seemed almost trivial to write code that could transform a VGM file into actual NES APU writes.

As I got deeper into the project, I also learned about NSF (NES Sound Format). It seems like NSF has an even larger catalogue of rips and is more popular with the chiptune community. Unfortunately, NSF seems to only be viable on emulators (or an architecturally correct NES with whichever bank switching chip a particular game felt like using). So when/if I decide to start dealing with NSF files, I think I'm going to have to basically convert them to VGM first. (Either by hacking an emulator on my PC, or by running a stripped down emulator on the ESP32 that captures APU writes and sends them across.)

Early Tinkering

I began my actual work on the project by proving out various elements of the NES portion of the system. The first step was to get myself an SRAM chip, an EEPROM chip, some 74-series glue logic, and actually build myself a functional "computer" around the RP2A03.

Breadboard NES Core

To prove that I could actually execute my own code on this thing, I fired up my old HP 1630G logic analyzer. It was of similar vintage as the NES itself, which somehow felt appropriate:

HP 1630G Front Display

I felt a huge sense of victory when I finally got to the point where I could write code, compile it, put it on the EEPROM, and see the RP2A03 actually executing it on the logic analyzer:

Logic Analyzer Probes

Program Code Execution

At this point, I duplicated the audio output components from the original NES schematic, wired them up to a pair of amplified computer speakers, and began running some APU test code that I found online:

Since everything was still working, I decided to move onto the next step.

I read up on the VGM format specification, and began writing a C program to parse the NES-specific subset of it. Testing with the theme of a famous video game, I started by trying to see if I could programmatically convert that theme's VGM data directly to 6502 assembly for the NES CPU. It actually wasn't that hard at all! But it was big! Trimming it down to fit within my paltry 8KB EEPROM only got me a few seconds!

But these were a glorious few seconds of victory!

I then modified my C program to produce output in a more compact binary form, and modified my 6502 assembly program to iterate over this binary data and "play" it. This made room for a few more seconds of song, and gave me a more useful test-bed to evaluate some ideas for how to actually feed data into the system during the next phase of the project.

I also built out a basic audio amplifier circuit, using an LM386 and a small 8 ohm speaker:

Thus, the final proof of concept!

Next Steps

The next step is to take what has been accomplished so far, and to build a complete system design around it. That involves selecting a display device, determining how best to configure and use the ESP32 as a front-end, and most importantly, figuring out exactly how I'm going to make the ESP32 feed data into the NES CPU. I'll be detailing this in the next blog post.

Afterward, I'll need to design an enclosure, control pad, and write plenty of software.