Page 1 of 1

ESP8266 Wireless SID Project

PostPosted: Sat Mar 05, 2016 1:27 pm
by bl4rk
Hi folks,

I've been trying to start a SID project for about 5 years now. Back then I wanted to use a 6502 along with a CPLD and other 'real' hardware... while I might still do something like that (or even try to use an FPGA for everything except the SID), I think it's probably good that I waited so long because now this great cheap ESP8266 wireless SoC is around.

When I saw the https://github.com/atbrask/RealSIDShield project I thought that the whole idea of using py65 to emulate the 6502 was pretty neat, and very accessible for me since I'm a Python guy. Then I stumbled across Acid64, which also emulates the 6502 in software and has a couple of other neat features. So, the plan is to support both. I'm not sure which one I'll implement first, but it should be relatively easy to get both working... and since Acid64 is Windows only, when I'm on Mac or Linux I can use a python script to stream music.

Anyway, so this is my plan for the hardware:

- Adafruit ESP8266 Huzzah module (eventually when I make a PCB I'll just use an ESP8266)
- MCP23017 I2C I/O expander (for 16 GPIO)
- SID (duh)
- LM386 preamp

I've started to breadboard everything:
IMG_3158.JPG
Initial experimentation


If anyone wants to provide feedback, please don't hesitate! In particular, I'm curious about design surrounding the LM386 preamp, should the preamp be on a different board? I'm concerned that there might be noise issues. Also I'm using a 12v supply, and an LM7805 LDO in order to give the SID the required 12 and 5 volts. Is this a bad idea?

Eventually I will definitely get some boards made, I might include a 2nd SID for the option of stereo as well. I have no clue what that involves at the present time but it seems like it shouldn't be too hard.

Since the ESP is clocked at 80Mhz I think that it will be more than fast enough to handle the task. But if anyone thinks otherwise please let me know.

Ok going to play with Python now to see if I can figure out a little more about the py65 emulation method and Acid64 network protocols. Wish me luck.

EDIT Source code repo is up here: https://github.com/blark/espSID

Mark

Re: ESP8266 Wireless SID Project

PostPosted: Mon Mar 07, 2016 11:22 am
by bl4rk
Wow, cool! Looks like I made the front page. Hopefully this will help me out in this one question:

The SID needs a 1MHz clock and I thought that since the ESP is clocked at 80MHz that this would be easy. I can't get the GPIO to toggle that fast though, it seems to be limited to a couple hundred KHz when using the Arduino IDE.

I guess my options are 1) figure out how to get faster GPIO, or 2) use an external clock. I really don't want to introduce an extra component to the mix. Anyone have thoughts on this?

Re: ESP8266 Wireless SID Project

PostPosted: Mon Mar 07, 2016 1:39 pm
by renze
For the clock generation: I don't know for sure if it's possible to go to such high speeds with the i2s hardware, but wouldn't it be possible to use the i2s hardware for generating a clock by enabling the dma and setting only the i2s clock pin to it's i2s function?

Re: ESP8266 Wireless SID Project

PostPosted: Mon Mar 07, 2016 1:39 pm
by ezflyr
Hi,

It's probably not a good idea to assume that everyone knows what a 'SID' is! I had to search for it, and finally found something audio related (I saw you had an LM386), that seemed to fit the bill.

SID = Sound Interface Device

First rule of good descriptive writing is to use commonly understood terminology, and where necessary to define the terminology that's not commonly understood.

John

Re: ESP8266 Wireless SID Project

PostPosted: Tue Mar 08, 2016 2:41 am
by Markus Gritsch
bl4rk wrote:The SID needs a 1MHz clock and I thought that since the ESP is clocked at 80MHz that this would be easy. I can't get the GPIO to toggle that fast though, it seems to be limited to a couple hundred KHz when using the Arduino IDE.


Since you also sent me a PM about this, I will try to give my 2 cents here, but don't expect too much :)

Bit-banging the I/O lines to get a 1 MHz clock is definitely not the way to go. Even if you could achieve 1 MHz (which you can't) there would be no time to do anything else.

In my SID player project over here viewtopic.php?f=56&t=2197 I used a counter of the PIC32 together with output compare which toggles a pin at 985248 Hz (PAL) or 1022727 HZ (NTSC). I don't know if the ESP8266 has such a pheripheral.

Another thing to investigate is the maximum sustained data rate you can stream to the ESP8266 over WiFi. Some digi-tunes like 'Fanta in Space' or 'Pollycracker' require 100+ kByte/s sustained data rate.

Cheers,
Markus

Re: ESP8266 Wireless SID Project

PostPosted: Tue Mar 08, 2016 8:56 am
by bl4rk
Markus Gritsch wrote:Bit-banging the I/O lines to get a 1 MHz clock is definitely not the way to go. Even if you could achieve 1 MHZ (which you can't) there would be no time to do anything else.

In my SID player project over here viewtopic.php?f=56&t=2197 I used a counter of the PIC32 together with output compare which toggles a pin at 985248 Hz (PAL) or 1022727 HZ (NTSC). I don't know if the ESP8266 has such a pheripheral.

Another thing to investigate is the maximum sustained data rate you can stream to the ESP8266 over WiFi. Some digi-tunes like 'Fanta in Space' or 'Pollycracker' require 100+ kByte/s sustained data rate.


Thanks Markus!

I will have to look into the data transfer thing. About that though...please bear with me. For most tunes the SID gets updated at 50Hz, there are 25 registers, each of which are 8 bits, so that means there is 25 bytes per register update. The math per sec is 25B * 50 = 1250B, so by my (probably flawed) math it should be a max of ~1.2kB/sec... or at 60Hz ~1.5kB. Am I doing something very wrong to arrive at these numbers?

I looked and the Fanta in Space file is 51kB, while the Pollycracker file is 48kB. I am guessing all of this is because of sampling in these files, and I have no clue how that works, and am a little foggy on all the different filetypes introduced since I was 13 years old and actually using the C64 :)

Thanks again!

Re: ESP8266 Wireless SID Project

PostPosted: Tue Mar 08, 2016 9:41 am
by Markus Gritsch
bl4rk wrote:Am I doing something very wrong to arrive at these numbers?


No, but the numbers can vary quite a bit. If you have a look at "Fanta in Space" using ACID 64 again, you will see that it has an update rate of 15639 Hz. Further, ACID 64 does not simply send the register values and that's it. To be cycle exact, it also adds the clock count (i.e. timestamp) when a specific value should be written to a specific register. This also adds some overhead.

Since data transfer rate can vary, you should buffer the data coming from ACID 64 and write the SID registers according to the included timestamps at the precise moment. Maybe you should have a look at the ACID 64 network protocol.

Cheers,
Markus

Re: ESP8266 Wireless SID Project

PostPosted: Tue Mar 08, 2016 9:55 am
by bl4rk
Markus Gritsch wrote:No, but the numbers can vary quite a bit. If you have a look at "Fanta in Space" using ACID 64 again, you will see that it has an update rate of 15639 Hz. Further, ACID 64 does not simply send the register values and that's it. To be cycle exact, it also adds the clock count (i.e. timestamp) when a specific value should be written to a specific register. This also adds some overhead.

Since data transfer rate can vary, you should buffer the data coming from ACID 64 and write the SID registers according to the included timestamps at the precise moment. Maybe you should have a look at the ACID 64 network protocol.


Ahhh. I thought it was something like that! Haha, I'm hoping most older songs don't use techniques like that, so I can get my little project going first with 50-60Hz songs.

I've looked a bit into the ACID64 protocol, but first I'm going to implement my own dumb protocol that just sends frames so I can hear some music (I'm impatient). I already have a ring buffer on the ESP8266 side, as I anticipated the need to buffer frames.

Now I'm leaning toward throwing out the MCP I/O expander and replacing it with CPLD for I/O and clock generation... I can't make any noise until I figure this damn clock thing out :)

Re: ESP8266 Wireless SID Project

PostPosted: Wed Mar 09, 2016 10:46 pm
by bl4rk
Ok, it's official, I'm dumping the MCP I/O expander in favor of a waaay cooler part: a Xilinx XC9572XL CPLD.

In the first iteration of the project (in my head anyway) I was going to use the CPLD for bus decoding. So I had a couple DP XC9572XL boards sitting around the house. I ordered a couple 20MHz and 50MHz oscillators and slapped them on and voila, I has a clock ;)

Now for the next trick, to make the thing speak SPI so I can send it data from the ESP. This has the benefit of speeding up transfers too since the ESP SPI bus runs at 1Mhz. Woot. This will be the hard part for me as I'm pretty stupid with this logic stuff. Wish me luck.

I don't think anyone has ever been so excited about a clock.
2016-03-09_22-29-04.png
1Mhz SID clock from the XC9572XL

Re: ESP8266 Wireless SID Project

PostPosted: Sat Mar 12, 2016 5:02 pm
by bl4rk
Switching over to the CPLD for glue between the SID and ESP has worked out really well. It's been a lot of fun learning more about logic, somewhat frustrating but mostly fun :)

I figure I shdould now recap how the project will work:

1. Python 6502 implementation runs the SID program and extracts the SID register values for each "frame" of the song, stores them in a FIFO. This code is pretty much complete (thanks greatly to the RealSID project by A.T. Brask https://github.com/atbrask/RealSIDShield)
2. ESP receives ~100 frames (2seconds @ 50Hz) of music saves them into another FIFO, a ticker timer is set up for 50Hz which sends the frame data (registers) to the CPLD. I've got some work to do on the TCP code here and sending over to the CPLD but it should be pretty simple.
3. The CPLD clocks the SID, and works as an I/O expander putting the necessary address and data on the SID bus. I need to finalize the SPI slave and then write the glue for the SID (to assert addr and data when the shift register is full).
4. SID plays music (hopefully)
5. LM386 amplifies it
6. ??? profit ???

I've implemented a simple clock divider and a 200 bit shift register that is fed all 25 SID registers for each update from the ESP. Since the ESP SPI is done in hardware it works up to 80MHz! This is waaaaay better than the measly KHz that I I2C was giving me before with the MCP chip.

I wrote a testbench for my shift register to make sure everything is working correctly. Here it is shifting in alternating 0x00 then 0xFF for 25 bytes:
2016-03-12_16-44-35.png
shift register test bench

As you can see the MOSI line is just set to invert every byte so I can make sure things are working properly. In the terminal of my test bench I've also set up some debug output so I can follow the register filling up with bits:
2016-03-12_16-47-58.png
debug console

I've chosen to do it this way so I can just shift in all 25 one-byte registers at once into one big buffer, then pass them over to another module that will handle writing the value to the bus for the SID. Right now the timing will be handled by the ESP, and that will be fine for 50 and 60 Hz songs but eventually I will build a buffer in the CPLD and have it handle all the timing because it will be much more reliable.

Finally on the ESP8266 side, here is a screenshot from my logic analyzer of the ESP sending out 25 bytes of data on the SPI bus (slowed down to a measly 4Mhz as to not overwhelm the poor Saleae):
2016-03-12_16-39-17.png
SPI goodness


It's all coming together! Soon I will hear bleeps and bloops!

And yes, for those interested, the next step is designing a PCB and slapping this all onto one nice PCB that you can just plug in to your stereo and stream to from anywhere.

Re: ESP8266 Wireless SID Project

PostPosted: Sun Mar 20, 2016 12:43 pm
by bl4rk
Whew. I finally got some music out of my SID!

After struggling immensely with the logic part of this project I have somewhat workable code. It was certainly a huge learning experience for me, as I had only ever dabbled with logic programming one other time while playing with a 6502 processor -- but I digress.

Once I started working in Verilog I quickly learned that without creating a test bench for each module I was implementing it would be pretty much impossible to move forward. Test benches turned out to be frustrating because they don't 100% mimic what actual hardware does, so you have to be careful. I ended up making a SPI slave module, clock module, ram module to store the received SID frame and a "SID glue" module to take the received SID registers and write them to the SID. The folks over at edaboard.com were very helpful during this process! I'm a complete hack with Verilog/logic stuff, their patience and input was instrumental.

One frame of register updates for the SID is 200 bits (25 registers x 8bits), and since you need to avoid writing duplicate register information across each update you also need to store the last frame of registers. Because storing 400bits (200 * 2) in CPLD is not possible (AFAIK), I had to move over to an FPGA, which has much more room. Since I am a dev board hoarder I have a Mojo v3, XuLa 2, and a couple of other FPGA dev boards hanging around -- I decided the Mojo would be easiest to slide in place of the CPLD, mostly because I've used it before and learned a lot from the tutorials they offer (https://embeddedmicro.com/tutorials/mojo).

At this point I'm not sure if I want to keep the FPGA in the project, because in the future I can implement a 6502 on it and do the SID processing there ... or go back to a CPLD and use SRAM for storage (which would likely be a lot cheaper, but less fun and flexible for experimentation).

Here's a quick video that I made of the thing in action for the first time:

https://www.youtube.com/watch?v=VwTKdCBm7dU