ESP8266 VGM Player
A basic shift-register-based VGM player for the SN76489 PSG chip.
This reads VGM data from uint8 arrays stored in the ESP8266 flash memory and plays them back on a SN76489 PSG sound chip via a SN74HC595 shift register. A ~3.58 MHz clock signal to drive the PSG is generated by an externally controlled LTC6903 programmable oscillator. The PSG can also accept a 4 MHz signal (mainly for BBC Micro songs), but will produce tones out-of-pitch with Sega Master system games.
The ESP8266 was chosen for this project for its incredibly fast processor and enormous RAM/ROM (64k, 4M respectively). This eliminates the need for a slower and more complicated system that uses external storage like an SD card or EEPROM.
This project is still early in it's lifespan, so there are still lots of improvements to make!
As of right now, the pinout is:
ESP | SHIFT REGISTER |
---|---|
ESP D0 | latch (12) |
ESP D1 | SRclock (11) |
ESP D2 | SERdata (14) |
(SKIP D3) | |
ESP D4 | SRCLR (10) |
ESP | SN76489 PSG |
---|---|
ESP D3 | WE (5) |
SN76489 PSG | SHIFT REGISTER & clock |
---|---|
PSG Clock | Clock out LTC6903 (external part, you must supply a 3.58 MHz clock signal) |
PSG D0-D7 | Shift Register QA-QH |
PSG OE | GND |
Shift register OE must be grounded too.
SN-OUT can be directly hooked up to low-powered speakers without amplification. This chip is pretty loud by itself. I reccomend a 10 uF cap connecting SN-OUT to GROUND.
Prepackaged VGM music in array format can be found in music.h. Just uncomment the track you would like to hear. Arrays of VGM music can be made by first extracting the uncompressed VGM file from a VGZ with 7zip. (If you have a VGM file that isn't playing properly, try opening it in 7zip anyways and extracting.) Then, take your uncompressed VGM file and head over to a linux PC and use the
xxd -i YOURTRACK.VGM OUTPUTFILE.txt
command to automatically create an array-friendly format. Change the array length int to "music_length" and the array data type to "uint8 ICACHE_RODATA_ATTR music_data[]"
Right now, there seems to be minor timing issues and there is no support for dynamic clock speeds.
I'm using an external PIC16F690 microcontroller to set the output clock of the LTC6903. I've included the CCS C code and the compiled HEX should you want to use it. You could easily setup the LTC6903 using SPI from the ESP8266, but since it's a bit limited for pins and I already had a chip programmed for this specific use, I went that route.