Well, I have deemed the FPGA Synthesizer “done”, at least in its current revision. I have still not lit up the MIDI port, but I don’t think I want to write a bunch of MIDI code in 6502 asm, so for now I have put the project on ice. It has exceeded all my expectations at this point.

So far, it plays the following stuff (all in hardware):

.NSF (complete with support for NES, VRC6, VRC7, FME7, N106, MMC5, FDS expansion audio)
.SID (complete, with quad-SID support, filters, RSID, PSID, and Compute! Gazette MUS format)
.GBS (complete, with normal Gameboy and Gameboy Colour support)
.SAP (complete, with dual POKEYs)
.SGC (complete, with support for SN76489, Colecovision, SMS, Gamegear modes)

It also plays a variety of FM music formats through a Verilog’d OPL3 (.CMF, .RAW, .IMF, .WLF, .D00)

Internally the following sound chips are written in Verilog by me:

6581/6582/8580 SID (quad, with full filters, full combined waveforms, proper ADSR w/ original bugs, 95% of a C64 to run RSID tunes, hardware filters)
RP2A03G NES (all expansion chips supported: VRC6, VRC7, FME7, N106, MMC5, FDS)
POKEY (As found on the Atari 8 bit line)
SN76489 (used for GG/SMS/Coleco)
AY-3-8910 (Written, but not used by a replayer yet)
OPL3 (FM support, can play OPL2 music also)

There’s around 70 or 80 separate sound channels that eventually get mixed down inside to the final DAC outputs. Most outputs have full user control of volume and channel selection, and if it gets filtered by the hardware filters or not.

The packaging was finally finished, along with the capacitive touch panel for the user interface. Battery charging and control are likewise finished, and I ended up implementing a first order derivative for the end of charge detection. Voltage depression isn’t very detectable on NiMh cells, so I couldn’t use that easily. The PIC’s ADC was too noisy to pick up the changes, so I went with delta temperature over delta time. When temp rise hits 3 degrees/minute, the charging is terminated. It works very well and doesn’t detect false ends of charge. There’s also a maximum temperature cutoff and a maximum time cutoff in case of some other kind of failure.




This is the UI PCB, it is a capacitive touch based affair.




Front of the finished synthesizer.




Side view.




Back view, showing power button and charge LED.




The guts.


So that’s the finished result. It didn’t come out too bad after all, but I did have to hack up the UI PCB some to make it work- Specifically I had to mount it on the top of the box and run wires to a cut up PCB inside that has the touch chip on it. The plastic was just way too thick on the enclosure for it to work through the plastic, unfortunately. But, the end result is pretty nice and the capacitive touch stuff works extremely well, so in the end it all worked out.

I will be working on a new synthesizer sometime in the future, which will be programmed in C, making development alot easier. Midi’s being reserved for that time.

FPGA Synthesizer Progress

Well it’s been awhile.  I haven’t been lazy, far from it.  Been so busy I haven’t had much chance to update the blog!  I spent the last 2 months learning verilog, and then performing a 100% conversion of my project from schematic entry to 100% verilog!  I didn’t know anything about verilog until having a little discussion with someone about it, and it seemed like a good time to learn it.   I already had a working project in schematic entry (around 150 schematics all linked together in this case) and figured it’d be a good learning experience to port it to verilog.

Long story short, the conversion was a success, and I ended up fixing a few bugs and adding some features along the way.  I ended up 100% redoing my OPL3 core, and vastly simplified and improved it, reducing device resource usage immensely.    To date, I have full support for the following sound chips:  SID (quad),  POKEY (quad), OPL3 (full support),  NES audio, N106 (8 chan wavetable), VRC6 (3 channels), VRC7 (FM synth), MMC5 (two squares+digi), FME7 (3 squares), and FDS audio (1 chan wavetable).  The wishlist of additions is:   Atari 2600 with extended range, Gameboy sound, and coleco/SMS sound (SN76489).  These shouldn’t be too tough, but before I can implement those I need to emulate the target CPUs which are Z80 and GBCPU.

This leads me to the current work:  I created a small RISC CPU for the FPGA which can emulate other 8 bit CPUs with cycle accuracy.  I figured that emulating the 8 bit CPUs would be by far more resource efficient on the FPGA, since to change the emulated CPU I only have to change the code in the block RAM.  Thus, 6502, Z80, GB CPU, etc. can be accomodated without sacrificing accuracy or speed, while only requiring one peice of hardware.  Ironically, the RISC CPU is smaller than the 6502 it will replace in FPGA resources.  The only minor downside is the 4K of blockRAM I used, but that’s a small price to pay ultimately for what it can do.

The specs on the CPU are:  18 bit instruction word, single cycle instructions, 32 bytes of RAM,  single and dual byte address modes, and a few special instructions to make CPU emulation easier such as jump tables and bit setting and clearing.  I named it the “KevRISC”  CPU 🙂

Update on the SID/MIDI/whatever box

Weeell, here’s the update. I have been working on this project for exactly 2 weeks now… The software end of things anyways.

Since last time, the PCB has been fully assembled, all the hardware has been debugged/tested/working except the USB part (been lazy on that). Been a whirlwind week of SD cards and FAT file systems and LCD displays!

As it stands, it will boot any SD card I stuff into it, load the firmware off the card into RAM, then run it. The firmware right now can load/display the directory of the card, lets you step through it including subdirs, etc and then load/play SID tunes.

You’d think sorting a directory list would be fairly easy- I spent more time than I want to admit on that piece of code. The unit can load up to 1023 directory entries off the card and then sort/display then in just a few seconds. Most directories are pretty much instantanious. I figured 1000+ entries would be more than good enough for this project. Who will wanna hit “page down” 200 times to see all 1000 files? hehe.

I made a custom font last night that allows me to cram 5 lines of text on the LCD, with kearning so that the text is packed in nice and close without wasting pixels. It can show about 30-40 characters on a line this way.

Also I bought one of those $30 CVS “one time use” camcorders and made it a bit more than one time use by making up a cable and then unlocking it. For more info on the CVS camera thing, check out HERE.

I will include a pic or two some time about my cable I made. Anyways, I mention the videocamera because I used it to make a small video of me looking and sounding like an idiot describing the device 🙂 You can watch me make a fool of myself on Youtube:


[application/x-shockwave-flash]

And here’s a few pics of the thinger (clicky for bigger)

That’s it for now, enjoy 🙂

PCB Prototype of the SID Filter / Sound Board

Well, after working on it for 2 months, I have finished design of the hardware and have made a PCB, then stuffed it. I am missing 4 or 5 parts though so I haven’t fired it up just yet. First the pictures:

Now that those are out of the way, what the hell am I looking at? Well, it’s evolved into alot more than just a simple SID emulator. It’s turned into a small portable hand held battalion of FPGA and audio goodness.

On board are a Cylcone 3C25, 16Mbytes of RAM, a PIC micro, USB, SD card, dual 1/4″ jacks for audio out, a 1/8″ stereo headphone jack (not on the board yet), MIDI in, and a bunch of debug/programming connectors and the 20 pin display connector. There’s dual analog SID filters, 4 24 bit audio DACs, digital volume controls and other analog goodies.

The plans for this beast are simple: a programmable MIDI box that lets you “play” nearly any kind of classic videogame or computer sound you wish. The second function is a full inclusive chiptune playing “engine” that reads tunes off the SD card and then plays them.

There’s a 132*32 pixel LCD with backlight that connects up to the 20 pin connector, and the 4 mounting holes at the top receive it. I do not have it mounted just yet since I was busy soldering it all up. I need get some hardware to mount it at the exact right height for my box, too. The box has a holder for 4 AA cells, which will be nicads or NiMh more likely, and will power the works.

The USB and SD card will act together as a standard windows/linux/etc. mass storage device to allow you to plug it in and drag/drop tunes to/from it. The USB will also provide recharging power to charge the batteries up. A DC power jack will be provided too for running it at a gig if you don’t want to use batteries.

Well, that’s about it for now. Here’s a sample of what the current hardware sounded like before I made the PCB. It’s about as good as can be done using standard parts. The filter’s offset and span can be tweaked in software now though, so I can change the response greatly.

current version 20 filter test.

SID Filter

I dinked around some more on the filter circuit, totally redoing part of it again. I think I have the framework down now for the “could be final” version. Time will tell. Anyways, here’s some more pics and sounds and things. I know the Fc curve isn’t correct just yet, but now I have the power to correct this in software I think. I have to make up a table and some other shiznit, but now that FC can easily be manipulated I am not too worried.

Here’s the lashup as it stands:

with the flash on


and with the flash off

Aaand here’s some audio:

Analog

Gloria

Hard Track

Mechanicus

Miami Vice

Needledrop

Poseidon: Planet Eleven

Spijkerhoek

Walking Home

Zamzara, tracks 3 and 4 (track 4 is “hidden” and is not shown as playable in the SID file)

SID Chip Markings and Revisions


top markings bottom markings
-------------------------------------------------------
MOS 6581 2282 AM211713 KOREA (filter is blown)
MOS 6581 2383 AH225704 KOREA (dead)
MOS 6581 2383 AH225705 KOREA (dead)
MOS 6581 1284 DH015117 PHILIPPINES
MOS 6581 1884 TH136576 THAILAND
MOS 6581 2184 AH153572 KOREA
MOS 6581 2284 NM192192 TAIWAN (this one of the ebay remarked chips)
MOS 6581 4684 AH127608 2 KOREA
MOS 6581 CBM 2285 AH111555 3 KOREA
MOS 6581R4AR 3586 S HH332126 HC-30 HONG KONG
MOS 6581R4AR 4086 14 HH392108 HC-30 HONG KONG
MOS 6581R4AR 4986 14 HH462130 HC-30 HONG KONG

MOS 6582 3186 25 HM292833 HC-30 HONG KONG
MOS 8580R5 0987 25 HH076904 HC-30 HONG KONG

After seeing this stuff, I have some theories about the bottom markings:

The first letter denotes the fab, the second letter I am not too sure about, while the next two numbers are the week the dice were made. the remaining 4 letters are a wafer lot code most likely. Some chips have a number after this which appears to be the die revision, but only from late 84 on appears to have it. The 4684 and 2285 date coded chips have a 2 and 3, respectively which appears to be the die revision.

Later chips were actually marked R3 (at the tail end of production) and all R4 and on chips were marked. The only exception I can find is my 6582 chip which has to be an R5 no matter what.

New SID ADSR Info!

Well, I wrote up a doc about new information found that sheds light on how the SID performs the ADSR prescaling. This prescaler is the 15 bit counter that divides the clock pulses coming in which then clock the envelope counter up/down.

* * * *

New SID info!
————-
08/02/2008
Kevin Horton
with help from:
Jonathan Gevaryahu AKA Lord Nightmare

New information about the SID ADSR circuit’s prescaler has been found by inspecting the SID’s die shots. Without further ado, here it is.

SID ADSR Prescaler
——————

Upon investigation, the SID uses a 15 bit LFSR for its prescaler, and NOT a counter. Resid and probably all other SID emulators handle this using a regular counter. The die on the SID, however, shows an odd little table for the ADSR prescale values. This table is reproduced below (LordNightmare entered it, thanks)

This is the small table as on the die. The bit polarities are unknown, as are the bit orders. All we know is the left 15 bits are the LFSR compare values, and the right 4 bits are the SID ADSR prescale values. This is the raw table as seen on the die shot:

100011111111010 0001
001101101010111 0000
111111111110001 1001
010110111001000 1000
010101010001100 0101
101110000001000 0100
111111001111101 1101
111111011110001 1100
111100110011111 0011
111000100110010 0010
110000111111111 1011
111011011110011 1010
100111111111111 0111
101110111011111 0110
111111110000000 1111
101101111011011 1110

After finagling around with some QBASIC code, I generated an exact match to this table. Here are the 16 values, in order. (It’s the same table as above, I just rearranged them in the proper order)

0123 are the 4 ADSR bits, and they are backwards and inverted. The 15 LFSR match bits are inverted also.

LSB -> MSB 0123
——————–
111111110000000 1111
100111111111111 0111
110000111111111 1011
111100110011111 0011
111111001111101 1101
010101010001100 0101
111111111110001 1001
100011111111010 0001
101101111011011 1110
101110111011111 0110
111011011110011 1010
111000100110010 0010
111111011110001 1100
101110000001000 0100
010110111001000 1000
001101101010111 0000

Aaand, here is my table, fixed up and in order. All the values turned out to be N-1, where N is the number of cycles it takes. i.e. for entry 0 which takes 9 cycles, the counter will expire after 8, but then it takes 1 cycle to reload it, which equals 9 total. The code example below implements this properly.

# comp value (hex, binary)
————————
0: 7F00 111111100000000
1: 0006 000000000000110
2: 003C 000000000111100
3: 0330 000001100110000
4: 20C0 010000011000000
5: 6755 110011101010101
6: 3800 011100000000000
7: 500E 101000000001110
8: 1212 001001000010010
9: 0222 000001000100010
A: 1848 001100001001000
B: 59B8 101100110111000
C: 3840 011100001000000
D: 77E2 111011111100010
E: 7625 111011000100101
F: 0A93 000101010010011

This pseudocode will implement the SID counter exactly as it works on the real chip.

adsrtable = [
0x7F00,
0x0006,
0x003C,
0x0330,
0x20C0,
0x6755,
0x3800,
0x500E,
0x1212,
0x0222,
0x1848,
0x59B8,
0x3840,
0x77E2,
0x7625,
0x0A93
];

feedback = (LFSR >> 14) ^ (LFSR >> 13); // perform XOR on last 2 bits
if (LFSR == adsrtable[rate]) // check to see if LFSR matches table value
{
LFSR = 0x7fff; // reset LFSR
// perform your envelope functions here
}
else
{
LFSR = (LFSR << 1) | feedback; // it wasn't a match, clock the LFSR once
}

More SID Filter Work

Well, I dorked around with the filter some more. I boosted the gain up going into it and this seems to have produced some of the characteristic distortion, but it’s still not as distorty as I want. However it does seem to be sorta kinda somewhat getting a bit closer maybe to sounding like a real SID. I think.

Anyways enough of that. Here are the MP3s:

After the War

Alrite! (PRI)

Analog

Gloria

Hard Track

Mechanicus tune 3

Snake Disco

Spijkerhoek (hey I spelled it right this time!)

Major SID Filter Progress!

Well I spent the weekend hacking my new idea for the SID filter, and I think it’s kinda sort of a success. Maybe. Here’s what it looks like:

The board in the background is my FPGA dev unit, and the board in the foreground is the analog filter/volume section. The FPGA is of course handling all the digital end while the board in front is doing the filter, volume control, and other analog functions.

It’s 10 chips, but to add a second SID will only take another 5. I got the controls down to 4 pots, but I can ditch those once I figure out the proper settings. I have totally redesigned the silly thing 8 times now, and I think I might possibly have a winner- time will tell. So far however I am very impressed with the output of it. It sounds like an R2 and/or an R3 SID. I have been using the SOASC MP3s for comparason purposes (and the SIDMan to a lesser extent). You can hit up the SOASC HERE.

I did a few tunes off of the “SID distortion” page (you can find that here) for your comparason pleasure. NOTE: He uses a Catweasel board and an R4 SID for his testing, which I believe to be a poor combination. The capacitors on the board are just as important as the SID when it comes to how the filter will sound! What value caps are on the Catweasel board? I cannot find that info anywhere. My friend has one and he can’t figure it out either.

Anyways, I believe a real stock C64 is the best test bed for how the SID “should” sound, since it will have the exact set of circuitry that is needed; this includes the specific output circuitry in the computer- an NPN transistor, 0.1uF cap and some resistors. These parts will add/change the sound somewhat (the .1uF cap in particular) and should really be taken into concideration.

The only problem I’ve found so far on my SID recreation is that the audio is too clean (there’s no bus noise) and there’s a slight resonance issue with my filter, but I am not 100% sure if this is due to my end or not. I am going to perform some more testing on this to find out.

Sooo, without further ado, here are the samples of my thinger in action:

Gloria (uses some heavy duty distortion from the filter!)

Hard Track (from the distortion page)

Spijerhoek (god, I hope I spelled that right. 🙂 This one might have minor resonance issues, not sure)

Agent X: The Mad Professor’s Back (a classic Folin tune, makes insane use of alot of filter modes)

Brain Artifice tune #10 (This makes heavy use of the filters also).

Miami Vice. 100% filtered all the time.

Poseidon: Planet Eleven ( uses odd filterage)

Aaand, that’s all for now.

The SID Filter Lives!

OK, I just fired up my latest incarnation of the SID filter I’m working on and initial results seem fairly promising. Here’s the goods. NOTE: I am manually adjusting filter cutoff and depth here, I do not have it under SID control at this time. As such, it won’t sound exactly like the tune’s filter program, but eh it’s a test.

I tested some of the harder tunes to emulate, specifically Gloria which sounds cool when the filter distorts. Well it seems to sound pretty distorty to me.

NOTE: there’s some high frequency whistle in the filtered channel, this is due to aliasing between the DAC and the soundcard I think. I am investigating. It does not appear to be due to the filter oscillating.

LEFT channel is unfiltered, RIGHT channel is filtered. I have included two versions of two songs- one with filtered/unfiltered split, and one that is mono with both mixed together as if it were a real SID.

Gloria (filtered/unfiltered)
Gloria (mixed, mono)

Spijkerhoek(filtered/unfiltered)

Procession (filtered/unfiltered)
Procession (mixed, mono)