# The SID: Classic 8-bit sound

## Метаданные

- **Канал:** Ben Eater
- **YouTube:** https://www.youtube.com/watch?v=LSMQ3U1Thzw
- **Просмотры:** 204,217
- **Источник:** https://ekstraktznaniy.ru/video/20721

## Описание

More 6502: https://eater.net/6502

Support these videos on Patreon: https://www.patreon.com/beneater or https://eater.net/support for other ways to support.

0:00 Generating different sounds
2:15 The SID chip
7:39 6502 computer addressing
13:00 Hooking the SID up to my computer
18:23 Testing SID features
25:08 Porting some vintage code
29:49 Demo!

------------------

Social media:
Website: https://www.eater.net
Twitter: https://x.com/beneater
Patreon: https://patreon.com/beneater
Reddit: https://www.reddit.com/r/beneater

Special thanks to these supporters for making this video possible:
Adrien Friggeri, Aleksey Smolenchuk, aliceitc, Anthony Weems, anula, Ben, Ben Cochran, Ben Kamens, Benjamin Keil, Benji Bromberg, Bill Cooksey, Binh Tran, Bradley Stach, Brian Haug, Carl Fooks, Carsten Schwender, Chad Fertig, Chris Anders, Chris Fala, Chris Lajoie, Craig Hawco, criis, Cristi Cobzarenco, Daniel Kouchekinia, Daniel Tang, David Clark, David Cox, David Dawkins, David Sastre Medin

## Транскрипт

### Generating different sounds []

In my previous videos, I got my 6502based breadboard computer to make a few different noises and sort of emulate different instruments. With square waves of different frequencies, you can generate different notes. And with different duty cycles, you can get a different sound for the same note. Adding a capacitor here creates a lowass filter that changes it to more of a triangle wave, which also creates uh even different sounds. And just a quick reminder that I sell these kits to build your own 6502 computer, including the serial interface and programmer that I use. All that's available on my website, eater. net/6502. So, here's the same LM386 audio amplifier and speaker that I had on the computer. And I've got it hooked up to this signal generator. Of course, I can generate square waves. I can uh change the duty cycle, can generate a triangle wave or a saw to wave. And those all have different sounds of course. But what else can we do? Well, one thing is to modulate the amplitude of the waveform. So, I can make this triangle wave louder or quieter by changing the amplitude. But with more control over the amplitude, for example, modulating the amplitude of this triangle wave with a slower saw to like this, you can get a different sort of effect that's more interesting than just turning the note on and off. This change in amplitude over time is referred to as an envelope. And being able to change this envelope uh can create all sorts of different sound effects. Another way to make more complex sounds is to combine uh multiple different sounds. For example, if I've got the two outputs of the signal generator hooked up together um going into this amplifier through these two resistors to mix them together. That'll let me generate sound from either output. For example, here's a sine wave at 440 htz. And then on the second output, I have a sine wave at 350 htz. So, here's one and the other. Of course, those are different sounds. But if I combine them, you get a very different sound. And if you're in North America, you might recognize that as a dial tone. Though, I guess phones don't have dial tones anymore. So, maybe that's a different topic. Uh, but either way, I think it's wild how these two different sounds by themselves versus together.

### The SID chip [2:15]

Anyhow, what I want to discuss in this video is this. This is the classic SID chip from the Commodore 64. And I'm going to hook it up to my computer and play with it a little. Though I'm not sure how practical this is. These chips are no longer in production and very difficult to find. And there's a lot of counterfeits out there. But I thought it'd be interesting to play with a little to see what it can do. I've got the 6581 version of this chip, or at least I hope I do. Hopefully, this is not a counterfeit. And here's the data sheet for it. The SID is the sound interface device. And here's the pin out, which we'll come back to that. But if we look at the description, let's uh see what it can do. So it says it has three synthesizer voices which can be used independently or in conjunction with each other uh to create complex sounds. So we just saw how you can make different sounds by combining two waveforms. This can do three or you can just use them as separate instruments playing simultaneously. I think that's probably more common. Each voice consists of a tone oscillator, envelope generator, and an amplitude modulator. If we look at the block diagram here, you can see we've got a tone oscillator, waveform generator, the envelope generator, and amplitude modulator. And that's repeated three times for the three different voices. The tone oscillator, waveform generator creates the basic notes. And then it can create either a triangle wave, a saw to wave, a square wave for which you can control the duty cycle and such, or uh noise. And noise is what you might imagine. just random static. But unlike this, which is true white noise, the SID can generate noise that changes at the frequency of the oscillator. So it can vary from a low rumble to a hissing, more like white noise. So that's the oscillator and waveform generator. Then there's the envelope generator, which controls the shape of the envelope. And I demonstrated a very simple envelope here that starts at 100% and just drops to zero over, you know, a few hundred milliseconds. But the envelope that the SID can create gives you more control. The oscillator output is then modulated by the amplitude modulator. And the result looks something like this sketch here. This represents a triangle wave that's modulated by the shape of the output of the envelope generator here. And this ADSR refers to the parameters for what the envelope generator can do. A is for attack. It's the slope of the envelope as the sound, you know, initially ramps up. Then D is for decay. So once the sound ramps up from zero to its maximum value, it ramps back down to a sustained volume at this decay rate. So that's the slope coming back down. S is then the sustained level. So once it's ramped up to attack and decay to the decay rate, it will then stay at that sustained level for however long the notes being played for. And then finally, when you stop playing the note, the slope of that drop off is the release rate. So R is release rate. So those three blocks, the oscillator, the envelope generator, amplitude modulator make up each voice. And then there are three voices and they're combined together um potentially also with an external input into a master volume control and then to the output. And then optionally each uh of these voices can be passed through a filter that can apply some other effects. And all this is controlled by the 6502 microprocessor. So there's five address lines up here for you know a z through a4 that uh you can use to select different registers. There's a chip select, read, write, clock and reset. And so by setting a register value on those address lines A 0 through A4, the CPU can read or write different values to the data bus. And these are all the different registers here. So you can see for uh voice one, you can set the frequency. It's two bytes. There's frequency low and frequency high. You've then got the pulse width. So if you're generating a square wave, you can set the pulse width to basically control the duty cycle. So there's pulse width low and pulse width high. So it's 12 bits there to set that. Then the control register lets you set which sort of waveform to generate. So you've got triangle, uh, saw, square wave, or noise. Then there's a couple other bits, uh, here for features that I won't get into. And then you've got the settings for attack, decay, sustain, and release. for attack, uh, decay, and release. You've got this table here that tells you how those values equate to an actual time interval. And then those registers are repeated three times for each of the three voices. Then you've got some registers for controlling the filter as well as four bits here for controlling the master volume. And then a few other features that I won't go into. Uh, but overall, it's a very capable chip. You know, way ahead of its time. But let's see what it takes to get one of these hooked up to my computer. You know, if we look at the data sheet, it has um an example circuit here, and a lot of it's pretty straightforward. The eight data lines connect to from the CPU. Reset uh the clock and the readwrite pins also connect directly to the CPU. And the first five address lines from the CPU connect to the address lines on the SID. The only tricky part is that the remaining address lines from the CPU have to go through some logic to decode when the CPU address lines are set to a particular address. that's not used by anything else. That way, when the CPU reads or writes to those unused addresses, the chip select line on the SID goes active. Then, it interprets the remaining address lines and the data lines as a read or write to a particular register. And the way I'm going to do

### 6502 computer addressing [7:39]

that is here's roughly the current schematic for the computer. Um, this is the CPU here, the 6502. We've got ROM, we've got RAM, we've got the peripherals, the versal interface adapter, and the UART. Um, and just kind of review how the address logic currently works. We've got address 15 here coming out of the CPU. Um, if that's high, then this nan gate is basically configured as an inverter. So, it's going to be low here. And then chip select on the ROM is active low. So, the ROM is selected anytime A15 is high, which is going to be address 80000 through FFF. If A15 is low, then we invert it uh and invert it again. And the RAM is active. But only if A14 is also low because it's connected here to the output enable. So if A15 is low and A14 is low then the RAM is going to be active which is going to be for address 0000 through 3 FFF. Otherwise if A15 is low we invert it. So if A15 is low and A14 is high then we're selecting all of our peripherals. So we've got the versal interface adapter and the uh UART here. And then we can also use that for the SID. Now the interface adapter is also looking for A13 to be high. So if A13 and A14 high, A15 low means address 600 0. And then with these four address bits, that's going to go through 6 0F for the interface adapter. The UART is looking for A12 to be high. So A15 low, A14, and A12 high is going to be address 500 0. and it's got two additional address bits here. So that's going to be through 5003 are the addresses for the UART. So those are all the current addresses we have in use. So now we want to add some address decode logic for the SID chip. It has a single chip select pin that's active low. So we're going to have to do something a little bit different. And I'm going to do something that's maybe a little bit of a hack. We already have a quad nanate chip here and we're using three of the four nan gates on it. So we've got one unused nan gate. But that's not quite enough. There also isn't any room on here to add any more logic chips. So, I'm going to use a couple diodes to make an ANDgate. And there's three things I want to and together. I want A15 to be low. So, it's inverted here. So, this is the inverse of A15. So, I want that. I want A14. So, I'll grab that here as well. And then I also want A1. So, I can just pull off A11. And I want to end all of these together. Right. So, we've got A15 low, A14, and A11. So, if I hook these all up to dodes, I just do three diodes here and hook these all up to dodes and then connect all of them together and add a pull-up resistor here. Maybe a 1k pull-up resistor. Doesn't really matter. Then this output will be high because of the pull-up resistor. Unless any of these three things goes low, in which case current will flow through whichever diode pulling this node here low. So this will be high when A15 is low, A14 is high and A11 is high. So that means an address of 48 0. And since the SID has five address lines that can go through 481F. So those will be the addresses for the SID chip. And you might have noticed, you know, I'm looking at address 15, 14, and 11. I'm kind of ignoring um A12 and A13. And that's because I'm kind of making a trade-off. It's just an engineering decision. I'm trading efficient use of the address space in exchange for reduced complexity of the address decode logic. For example, you know, if we tried to write to address, you know, 68 0, for example, if we convert this to binary, 6 is 0 1 0. 8 is 1 0 0. And then we've got eight more zeros here. So address 68000 would look like this in binary. So address 15 is low, 14 is high, 13 is high, 12 is low, and 11 is high. So with address 13 high like this, the versal interface adapter is going to think that it's being selected. And it's going to look at, you know, these address lines here and think you're writing into address zero on the versal interface adapter. But with A11 high as well, the SID will think that you're also trying to write to its register zero because A11 is going to be high. A14 is high and A15 is low. So the SID is also going to think you're writing into its register zero. And that's probably not a normal thing you'd want to do. So on this computer, address 6800 is not a valid address. And that's just a trade-off because, you know, we could add more logic to check every single address line for each of these chips. But that's a lot of extra logic. And you know, as you can see, none of the address ranges uh that we've defined so far overlap. So, this works fine. The only other thing to add is that, you know, this output here is going to go high when address 15 is low, address 14 is high, and address 11 is high. But if we look at the SIDS chip select line, it's active low. It's got the bar over it. So, we actually need to invert this. Fortunately, we have that extra NAND gate. So we can just kind of bring this into the inputs of that NAND gate and invert it that way. So let's wire this up. So I've got the pin out of the SID

### Hooking the SID up to my computer [13:00]

here for reference. And I'll start by hooking up power and ground. Ground is pin 14. And the power is pin 25. And that's 5volt power. Uh this chip also requires in addition to 5 volts, it also requires 12 volts, which is another thing that makes it a little bit inconvenient. But I'll hook the 12volt power up later. So I've got the 5volt power and ground hooked up. And I'll add another decoupling capacitor here just for good measure. This chip is generating sound, so I want the power to be as clean as possible so we get as clean of a sound as possible or at least as good as we can get on a breadboard. And next, I'll hook up the chip select. This is the one we just talked about with uh we're going to use this nan gate here and a bunch of diodes. So working backwards from the chip select input on the SID, which is pin eight, I'll hook that to the output of the nan gates. Then I'll tie the two inputs of that nan gate together. And so that basically makes an inverter with this is the input. That's the output that goes to chip select. And the input of that we're going to pull high. So I'll add a 1k resistor there to pull that high. And then I want to add these three diodes. And those dodes are going to come off of uh pins four and five on that same chip as well as address 11, which we'll have to find somewhere. So I'll add a diode to pin four and another one to pin five. And then the third diode's got to go to A11. So, I'll add that diode here. And A11 is actually pin 20 here on the CPU all the way on the end here. So, I can jumper from that diode over to the very end here. So, we've got A15 coming in here being inverted. That's coming around here and that's going into one diode. So, we're looking for A15 to be low. Then A14 is coming in here and that's going to this diode. So, we're looking for A14 to be high. And then we have A11 coming around here through this diode. So we're looking for A11 to be high. So if all of those are set appropriately, then no current will flow through these diodes and the pull-up resistor will pull up and the N gate here will invert that and we'll have a low input on the active low chip select. Otherwise, if any of those dodes is conducting current, that'll pull these inputs here low and then the output will be high and this active low chip select will be inactive. Hopefully that makes sense. The rest of the control signals are pretty straightforward. So, we've got readwrite, we've got clock, and we've got reset. So, read I'll add and I'll bring that around and kind of pull that off of the readwrite pin that's going into the UART. And for the clock, the same deal. I'll take the clock input and pull that off of where the clock's going into the UART as well. And then the reset pin, I'll bring that over to where the reset signal is going into the UART as well. And then there's these other uh cap 1 A, cap 1B, cap 2 A, cap 2B, uh pins one through four. And those you just add capacitors. And the example circuit here shows on those 2200 poparad uh capacitor. So I'll add a couple capacitors on those pins and uh just make sure everything's in there. And then pin 27 is audio output. So that's going to go to our amplifier here. Uh which means I can get rid of the audio output that's going currently going or coming from the uh via chip. Keep knocking this capacitor out back in there. So audio out is this pin. And right now I'll just connect it over here to an unused part of the board. Because if we look at this example circuit, audio out has a 1k resistor that goes to ground and then a one microfarad capacitor actually going to the audio output. So I'll add that 1k resistor to ground and then the one microfarad capacitor going to the amplifier input. And so that's pretty much everything except for the five address lines and the eight data lines as well as that 12volt input that we'll talk about in a minute. So for those first five address lines, I think the easiest thing to do is pull them off of the RAM chip here. So here's A Z and that goes to pin 9 on the SID. A1, A2, A3, and there's A4. So we've got these five address lines now. And I can kind of route these around here. somewhere. Something like that kind of works. And then we need to hook up the eight data lines. And those I can just run over to the datab bus here where it's going into the UART. So there's D7, D6, D5, D4, D3, D2, D1, and D0. So we've got D0 through D7. We're not using pot X or pot Y. Those are for game paddle inputs. Another feature that the SID has. We got power. We're not using external audio input. We've got our audio output hooked up to our amplifier. This is that 12volt input we will need to do that. We've got our capacitors hooked up, reset, clock, read, write, chip select all hooked up with all the logic and address zero through address 4 and ground. So the only thing remaining is that 12volt uh power. And that's an unfortunate thing about this SID chip is that it requires a separate 12volt power input despite the fact that the rest of this computer is all 5vt. So I'm just going to hook up an external 12volt supply just to get this working. So 12volt power here and then ground from that supply. And then I'll add a one microfarad decoupling capacitor here too just to make sure this is relatively clean 12volt power going in. And there we go. So I think everything's hooked up. So let me connect my serial console and the 5volt power. And then I'll also need to turn on the 12volt power. Reset the computer. And if I want I can drop into basic here. So that's good. The computer seems to at least still work. Actually, I think initially to

### Testing SID features [18:23]

play with this, I'd prefer to be in the ROM monitor. Uh, so let me reset again. And now we should be able to just write to some registers and get this thing to make sounds. So, let's try it out. So, we got the registers here for voice one. First is the frequency, low and high. And there's a table here that equates musical notes to frequencies and the corresponding value we need to write to those registers. So, here's a 440 hertz. And we need to write 1 cd6. So, we want to put 1 cd6 into these first two registers here and the addresses for all this is at 480 0 and this is the first register right at zero. So that'd be 4800 0 and it's low then high. So 1 CD6 would be D61C. So that'll write D6 to 4800 and 1 C to 4801. Then we have the control register. That's register 4. So it's going to be at address 4804. And here we can choose what waveform we want. Noise, square, saw, or triangle. If we want triangle, that's going to be 00001 or just one in hex. And the next four bits, we're not using any of these. But gate controls whether this voice is making noise or not. So we set this to one when we want it to start making noise and then zero to stop making noise. So we want this to start making noise. So it's going to be 00001 or in hex that's just one. If we do that, well, it's not making any noise. And I think that's because we also need to set the volume. Either that or something else is broken. But if we look at the rest of these registers, we've got the three voices. And then down here, we've got volume in register 18. So, let's set that. So, this be 48. And these first four bits we're not using. We can set that all to zero. And then the last four bits, if we want maximum volume, we'll just put one or f. So the first four bits are zero and then F for the volume. And we're still not hearing anything. And now I think the issue is the envelope configuration because we have these values here for attack, decay, sustain, and release. And I think they're probably all defaulting to zero, which is mostly fine. You know, attack of zero means it's going to quickly ramp up to maximum volume when we play a noise. Decay of zero means it's then going to quickly ramp down to the sustain level, uh, which is also zero. So, it's going to sustain at zero volume level. So, we should probably fix that. And then release. If that's zero, it means when we stop playing the note, it'll ramp down quickly. But let's change the sustain. So, it's address six. So, if we set 4806, and we'll just sustain at full volume. So, that's F. And then release can stay at zero. That's fine. And it's still not making noise. So, let's try playing the note again. Um, and to do that, we need to toggle this gate because we set the gate to one to start playing the note. But when we did that, sustain was still set to zero. So I think it may still be playing the note at a level of zero. So let's toggle that gate. And that's in address 4. So if we set 4804, we still want a triangle wave, so it's one. But then we'll set the gate to zero. So that stops playing the note. And now if we say 4804, we want triangle wave. and then start playing the note. And there we go. Let me adjust this. Yeah, that looks like a triangle wave. And then let me stop that. If I want to do something more interesting with the envelope, let's uh set 4805. And that's this register here to attack of 9, a decay of seven, we'll sustain at 8, which is half of the total volume, and then a long decay of a. And so we can look at the uh table here that says what those rates are. So attack rate of nine is going to be 250 millisecond attack. Decay of seven is about 240 millisecond decay time. So approximately the same attack and decay. And then sustain at 8 is about half of the total amplitude because it goes from 0 to 15. So eight's about half of that. And then release I said a. So that's a second and a half. So a pretty long release. So, let's try that. So, I'll set that and then we'll play a note. So, this will start playing and you can kind of see that initial attack and now it's just steady at half of the rate. And then when I stop, you'll see the decay. And probably another way to see that is if I slow the scope down and now play the note again. Yeah, you can see that attack and decay. Now it's just steady. And then if I stop playing the note, you see the release. And of course, we can do other shapes. We can do saw to. So that's going to be two and then one to start playing it. It's a different sound. Let me zoom in. And you can see that's more of a saw to wave. We've got square wave, which would be four, and then one to play it. And that seems like it's not working, but that's because for the square wave, we can set the pulse width, right? We have these registers here for pulse width low, pulse width high, and that's defaulting to zero. So, if we look at the data sheet for pulse width, it says a value of zero or fff in the pulse width registers. Of course, we have a value of zero will produce a constant DC output, while a value of 800 will produce a square wave. So, let's set that uh pulse width to 800 0. And so the we've got pulsewidth low and then pulsewidth high. So the eight will be in the high and then the 0 is in low. We've already got 00 there. So really we just need to set an eight here in pulsewidth high which is register three. So if we set 4803 to uh 8. That should give us a square wave. And that is a pretty terrible looking square wave. Though I'm willing to give it the benefit of the doubt that it's trying. I think there's just a lot of extra capacitance in there that's causing it to be less than square. But whatever it is, we can probably change the duty cycle. If we set 4803 to 02 instead of 8, you can see and hear the duty cycle changed. Finally, the last waveform is that noise. So if we do that, we get noise. And like I was saying, this isn't pure white noise. We can actually change the uh frequency. So if I set uh 4800 which is our frequency to a different value let's say 3 4 2b we get different noise. So that's a basic overview of what each of the voices can do. And of course there are three voices that can play simultaneously. But the real magic comes

### Porting some vintage code [25:08]

from the creativity of composers who use these tools to create amazingly complex music. And I wasn't sure if I'd be able to easily demonstrate because the music written on the Commodore 64, for example, is very specific to that hardware. And obviously, no one's written SID music specifically for my computer. But amazingly, over on Patreon, Josh, who goes by normal user, did the work to port some music to my particular architecture. Here's the code he came up with, and it's a pretty clever way of porting the code from the Commodore. First, he sets up a 60 Hz timer to trigger an interrupt 60 times a second. And on the Commodore, it used the video raster interrupt for this. Then uh rather than create an interrupt handler, he's using this uh wait instruction here, which is part of the modern Western Digital 6502 chip that I'm using. Um and it just waits for that 60 times a second interrupt, or really any interrupt, and then uh goes on to the next step in playing the music. Then the rest of the code here is more or less original. Um just modified to use the addressing for my computer um you know, the 4800 base. and so forth. If we go up here though, back to the top here, you can see that he's got it set up to start in RAM at address 03000, which actually with my BIOS running is where the input buffer is. So, I need to move this somewhere else. But actually, instead of doing it here, I'm just going to delete this and I'll locate it with the linker. So, I can assemble this. I'm using the CA65 assembler. We need to tell it we're using the 65C02 CPU that has that weight instruction. and that assembled it. Then I've got a linker config file and this gives uh just enough information about where it's going to run the code. So it says that RAM starts at address zero and this is the size which matches my computer. Then it says that the code is going to be loaded into RAM starting at address 0400. So to link it, I'll run the linker and reference that config file and then give it the assembled object file. So that creates this file a. out. And if we look at that, this is the machine code to play music. So then to get this to uh be able to load this on the computer, I asked an AI chatbot to write a Python script that will print the machine code in the right format. And so if we run this Python code and give it the output file, this is what we get. And it's just printing out memory locations followed by the bytes that would go into that memory location in order to load this whole thing. And if we scroll up, you'll see it's starting at address 400. So I can just copy this whole thing. If I run that again and send it to uh PB copy, that'll put it into my clipboard. And if I go back to the serial terminal, I can just paste this into WASmon. And now it's taking that machine code that we just looked at and it's writing it into memory starting at address 400. So that's done. The uh program is now in RAM. Uh but there's one more thing that I need to do. You Josh set this timer up to uh trigger interrupt 60 times a second. The problem is that in ROM I still have the interrupt handler from my previous video. So as soon as it gets a timer interrupt, it resets the timer to a different value. So this 60 Hz time here is totally ignored. And I found that the quickest fix for that is just to leave my interrupt handler in place and just update the variables in memory that are used for setting the timer value. So the computer clock runs at 1 MHz. So that's a million per second and we want 60 per second. So the timer needs to run for that many clock ticks which in hex is 411A. Now my interrupt handler is getting the value from address 00ca. So we can set that to 41 1 and that's the sound one variable. You can see my previous video. And then sound 2 follows that. So that's also going to be 41 1 again. So that'll make sure the interrupt handler for changing the square wave duty cycle in my other video works to generate a proper 60 Hz clock now. So in troubleshooting that I hooked up channel two of my scope here to the interrupt line. So once I start playing this you'll see this pulse low every 60th of a second. Channel one is still on the SID output. So you'll be able to see that as well. And then I'm going to add one more thing. So I've got this little speaker here and it sounds okay. But rather than have you try to listen to that through a microphone, I'm going to hook the output of the SID directly to an input up on my camera. You know, that way, you know, what you're listening to is going to be exactly what the SID is capable of producing, you know, directly through your own headphones or speaker. And then when I play this, I want you to listen to all the different instruments and effects that are generated with only the basic building blocks we just looked at. In fact, if you watch the scope while it plays, it looks to me like it's maybe only using square waves and noise for the drum effects. It's pretty remarkable. So let's run the code at

### Demo! [29:49]

address 04 0 Heat. Heat. up here. Heat. Heat. Heat. — Heat. — Heat up here. Heat. —
