Thanks to several people who have mentioned the square waves look like battlements or crenelations : which are "a parapet with alternating openings (embrasures) and raised sections (merlons), often used on castle walls and towers for defense purposes." At least I got "merlon" right! sites.pitt.edu/~medart/menuglossary/crenelation.htm
I'm not sure what is so compelling about watching white numbers scroll down a blue screen for 45 minutes, but it is! You are either an evil genius secretly hypnotizing all of us - someday you'll flip a switch and we'll turn into your 8-bit zombie horde - or else you're unappoligetically following your geeky soul which we all love because it's somehow similar to our own.
Fun fact: the star field background on Galaxian arcade games is a LFSR output to the screen, under the sprites and text. Its period is plus or minus one of the number of vertical pixels, so it scrolls one pixel per frame. Plus one to scroll in one direction and minus one to scroll in the other. It was a really efficient way to make a nice scrolling background. Maybe four TTL IC's. Back on the SID though. My first guess is the 24-bit registers are dynamic rather than static, so they need to be refreshed much like in the 6502 itself. I assume the TEST bit in the register halts the refresh cycle, so the bits start to float up to a 1 state. This would explain the 'analogue' nature of the reset, because the registers are slowly drifting at random rates to 1's. As soon as the TEST bit is released, it'll latch the random values in the register. If anyone knows more about it, I'd love to hear! Also, if you wanted to find the state of the hidden bits of the shift register after applying the TEST bit, you wouldn't need to compare the output against a table of the sequence. Just allowing it to shift 24 times and measuring the MSB each shift will give you the result, because the hidden data doesn't change as its being shifted. It could be done in BASIC quite accurately if there was a loop to wait until the register changes, and to print the MSB as it shifts in. Cheers.
As to my understanding of SID chip, on every rising edge of clock signal, 24bit oscillator is adding 16bit value from $d400/01 (first channel) to itself. If test bit is set, it will reset that 24bit oscillator to 0. Noise LFSR is driven by rising edge of bit 19 of oscillator.
Good idea! It works too, here it is: 100 A =54299:REM OSC 3 OUTPUT 110 REM LOWEST FREQ $0001 120 POKE 54286,1:POKE 54287,0 130 REM 50/50 PULSE DUTY CYCLE $800 140 POKE 54288,0:POKE 54289,8 150 REM 16=TRIANGLE, 32=SAWTOOTH 160 REM 64=PULSE, 128=NOISE 170 POKE 54290,128 180 REM PRINT PEEK(A):GOTO180 200 R=22:B=7 210 C=0:DIM R(R),B(B) 220 FOR I=0 TO B:READ B(I):NEXT 230 DATA 22,20,16,13,11,7,4,2 240 REM CREATE THE 23 BIT REGISTER 245 PRINT:PRINT "recreate the 23-bit register" 250 FOR I=R TO 0 STEP -1 260 D=PEEK(A):R(I) = -(D>127):PRINT CHR$(48+R(I)); 270 IF PEEK(A)=D THEN 270 280 NEXT I:PRINT 290 REM 23 BIT REGISTER RECREATED 300 REM BUT RANDOM NUMBERS ARE 23 310 REM BEHIND IN THE SEQUENCE. 315 PRINT:PRINT"sid","lfsr" 320 FOR I=0 TO R 330 GOSUB 810 340 IF PEEK(A)D THEN PRINT D,"i=";I:D=PEEK(A):I=I-1:REM DO ANOTHER SHIFT 350 NEXT I 400 REM LFSR REGISTER HAS MATCHED SID 410 GOSUB 710:PRINT D,V 420 IF PEEK(A)D THEN D=PEEK(A):GOTO 410 430 GOTO 420 599 END 700 REM CREATE NEXT RANDOM LFSR SAMPLE 710 V=0 720 FOR N=0 TO B:V=V*2+R(B(N)):NEXT N 800 REM PERFORM LINEAR SHIFT 810 T=(R(22)+R(17)) AND 1 820 FOR N=R TO 1 STEP -1 830 R(N)=R(N-1):NEXT N 840 R(0)=T 850 RETURN
Thanks for doing this one. I somehow missed it when I was looking for SID random number generation help earlier. I had no idea what all was involved in a Linear-Feedback Shift Register, until now. You have a gift for explaining a wide range of topics from the very simple to the very complicated in a way that is easy for me to understand. None of your videos are boring or uninteresting. You make all of them a fun adventure to tag along on with you.
I've been a fan of LFSRs ever since after reading about how "River Raid" for Atari VCS used one to procedurally generate the playfields. It was programmed by Carol Shaw in 1982. Yay for women engineers!
Yes, I think the story is that David Crane got onto LFSRs for generating the world of Pitfall! and then that idea went around the office and Carol realized it would be perfect for River Raid.
Yes. River Raid was one of the first algorithmically generated worlds. At the time it was a nice way to create a very big game environment with tiny amount of code.
If you play a note, then set the waveform to 0 but keep the gate on you get the same analog delay effect but with audio. E.g. poke 54290,17 and then poke 54290,1 I believe you can also use a REU to sample voice 3 output at high frequency. The VIC chip in the VIC 20 also uses a LFSR but it does not have enough bits, so you can actually hear the noise repeat.
Went with the British spelling of Behaviour. You Canadians are a confusing bunch ;-) I've been fascinated with the LFSR in the SID for a long time. Done enough Cipher work on 8 bit machines to have a real appreciation for how well this worked given the time it was designed. This is the best visualization I've seen so far. There's a fantastic series of programs in Programming the 64 that do an excellent job with explanations and visuals of many SID concepts. It's Chapter 13. 31:16 - almost 56 days on an NTSC machine
I wrote a SID (and 6510) simulator for AVR microcontroller around 2005 and couldn't get the noise channel quite right. I don't remember if the info just was not easily available or I just didn't research it properly. Any way, the AVR played songs on real 6581 quite nicely, and somewhat acceptable on the simulated SID :D great video!
This video is actually super helpful for me, because I've been contributing to a C64 emulator. I had ideas as to better implement $d41b, but this video and the way you described the data in this register gave me a lot of ideas!
Thank you for this interesting and informative tutorial to the mysterious SID chip - mysterious to me, that is. I loaded your disk into MAME and followed along, changed parameters and got some unearthly sounds out of the emulated SID. Great fun!
While there isn't a dedicated operator, you can still perform XOR operations in BASIC using: (n1 or n2) and not (n1 and n2) It doesn't really matter much for just one bit, but the above method works on larger values (up to 15 bits in BASIC), without using math tricks.
This is the way I would do. But I found Robin's way creative. An thinking the way Basic works (at least on Apple II and TRS80 that I am more familiar with) maybe even faster.
I may well have left a comment before on this video but I need to leave another because I've just watched it again and want to thank you once more. I wanted to implement a 'noise' waveform in my e-ther theremin-like device and the idea of generating it in the same way as the SID appealed to me. (frankly, if someone's already done the hard work, and done it extremely well, then you're silly to try to reinvent the wheel). I was very happy that a search of your channel for 'lfsr' found the right video! (I did remember that it was a 23-bit lfsr). It was a pleasure to watch the whole video again and your explanation of how the numbers are generated was very clear and thorough. I was easily able to write the same pseudo-random number generator in C (even making an 8-bit value by selecting those exact same bits). The bit that baffled me a little was how to get it to sound different at different 'frequencies'. (I started out by making every sample a random number. If you resample a bunch of random numbers, guess what, you get a bunch of random numbers and it sounds the same!!) I realised that the SID changes the rate that it changes the number (according to the frequency settings) and once I did the same then I had something that sounded like the SID, ie if you go up through the frequencies, it sounds a bit more like applying filter than changing the frequency. It's a really nice effect when you control the 'frequency' and volume with theremin-like controls. (good for seaside effects etc). ~ Shiela
I understand that you can get some interesting waveforms by turning on multiple bits of the waveform register at once (I've seen some music use them, the title music for Ghosts 'n' Goblins for instance)--it'd be neat to see a discussion of how that works. Also the low-pass filters!
Supposedly, Bob Yannes was shooting for 32 voices for the SID but there wasn't enough time or money (silicon space) to do it. Can you imagine what could be accomplished with 32 voices considering what they can now do with "only" 3?
It would judt sound yet another FM synthetis. SID sound is so distinc because clever programmers did magic around the limitations. We would have missed the charm of that era completely.
@@DMStern Could be since Ensoniq created that chip and Bob Yannes was the founder of Ensoniq. Also, it has 32 voices, just as his original concept for the SID would have had. It's strange that the Apple II GS is not more well known and revered for its sound prowess given its impressive on-paper capabilities.
Great timing with this. I'm currently working on music for my C64 port of the arcade game Venture. I am not a musician, but I'm trying to do the whole thing myself.
I wonder what the 54299 register looks like over time during your line 90 loop, after the test bit is set. If I had my C64 set up I'd try it out. Cool stuff!
Another interesting episode. Thank you. I think it uses 23 and 17 because they are both prime numbers. If one of the numbers was divisible by 2, for example, then the sequence would likely be half as long. Just a wild guess :-)
Clearing the gate bit starts the release phase of the envelope, not the decay. The Attack, decay and release phases are trigged by the gate bit, with the sustain lasting until the gate is cleared, which starts the release.
Any chance the reset isn't really a reset but a continuing through the sequence until the initial register state is reached? That seems like it fits with being called a test bit. It would also explain the timing differences. The further along in the sequence when you hit reset, the less time it takes to get back to the beginning.
I don't think so. The sample playing routine used in the "Vicious Sid" demo is based on reseting the oscillator using the test bit, and then waiting until it reaches the desired value (search for "Vicious Sid Demo Routine Explained" for an in-depth explanation). From a chip-design perspective it also wouldn't make much sense. (Edit: of course it's always possible the noise oscillator behaves completely differently from the others in this regard.)
The random reset is most interesting thing in video! I thought the output values would be far later in the sequence because of delay in BASIC for Poking the test bit before you actually enable the waveform... I think the PLA, power supply (or both) are bad in my C128 so can't test my SID. Is there any difference in timing if you enable the waveform and then (or simultaneously) set the test bit? From hardware engineering background, assuming above idea has no effect, I can only guess some kind of drain / slow-leak circuit is activated with test bit? As charge is slowly dissipated, bits will 'randomly' register as 1, and the longer the time, the more likely? Such a scheme would explain the various (presumably thermal differences you report) and would also be cheaper than 22 "reset" transistors... Still doesn't explain why they would not just continuously feed all 1s into the LSFR and you could then reset quickly with high frequency ... which your video showed does not work... anyway, great video!
I Love the SID Chip and all of those Sid tunes I had helped me get into the original artists music. But my latest endeavor are the GIF viewing software for the Commodore 64. They let me translate older 87a GIF files. But anything made after the 89a upgrade won't let me convert newer GIF files on my VICE emulator. I'm really bummed because I used Photoshop 7 (Yes a very old version of Photoshop to create the GIFS. But even those are not recognized by either of the two GIF viewing programs I found for the Commodore 64. They both only translate GIFS that are really old that I have. My one friend would screen cap games on his Tandy PC and then send them to me over his modem to my C64. So I have images from Space Quest 3, Ultima 6 and 7 and also X-Wing. Plus some art work by people creating EGA and VGA drawings or digital scans. All the images I'm trying to view came from my Canon DSLRS. I made the images 320 X 200 and some at 160 X 200. I limited there color range and saved them as GIFS. I used a D64 editor to add them to a virtual disk. However only my oldest GIFS I have from the early 90s work with the decoding software. I wonder if anyone has written an up to date GIF viewer for the C=64 that will view 89a GIFS?
You could write a sample and hold modulator with the output of oscillator 3 and the noise waveform. The random "bleep bloop" stereotypical computer sound you got a lot in 60s and 70s sci-fi _is_ a sample and hold from old analogue synths like the Moog Modular and Arp Odyssey. Peek a value from oscillator three and set the pitch of a triangle wave on another oscillator with some kind of multiplier. Hold that value for a period of time before Peeking another one. You do this so you don't get a smooth pitch transition and get that stepped effect. Voilà! Sci-Fi computer sound. For extra flair, retrigger the envelope with each sample so it's like a small pluck. It's funny how they call it "white noise" in the manual. You can't pitch white noise. I think it's actually periodic noise. Given the SID is an analogue Synthesizer I'm surprised they didn't put a real whitenoise generator in there. Periodic is more useful for percussion, though.
I thought where you were going was to get the SID with noise as a random number generator. I liked watching all this. I have done the same "science" myself. Its a cross between study and play 😂😃😁
3:45 To help visualize the waveform, I commented line 180 and added the following line which prints asterisks in a horizontal position that is proportional to the available screen width: 190 printtab(peek(a)/6.6)"*":goto190
Fun fact: Square waves and triangle waves both consist only of odd harmonics of the base frequency. They sound different because the amplitudes of the harmonics fall off faster for the triangle. Also of note, a square wave is a special case of a pulse wave, when the duty cycle is 50%. Anything other than 50% is not a square wave and will include even harmonics.
The SID was before it's time with ADSR and more. In fact they jumped this to stored sounds using DACs. The AY 3 series of chips never had the power of the Sid. Shame no one to build any more Sid's. Does anyone hay the original mask
Fascinating stuff Robin! Is it me, or when the Linear shift isn't producing the expected values, the values it does select seem to change faster, or is that the magic of video editing? Thanks again!!
I do jump cut ahead at times when I have nothing to say, but I didn't change the speed of the video at all (like, a fast-forward effect) in this video. So it should be all real-time, except for when I jump ahead. So I'm not sure what would make it seem faster, that's strange!
The longer you let it run, the more bits are shifted, and will need to be reset, thus your running before resetting influences the amount of resetting that may be needed. If some bits are slower to reset it makes sence it works if those bits doesn't have to reset... Setting a rate that matches with a few readouts of each value, then making sure the program runs for same amount of iterations before stopping every time will at least make that more consistent. It also needs to stop the sid.
My wild guess: the test bit feeds into the lfsr instead of the tap. So when set you need wait long enough for whatever frequency you set. You set an extremely low sequence so must wait in the tenth of seconds. Should try with higher frequency if test bit gets 1s in the lfsr quicker. It would make sense to me that they did NOT implement a parallel load of 1s in a hardware 22 bit registers (it needs lots of transistors) but they can well put a gate: lower bit comes from either TAP or from fixed 1 when TEST is set. UPDATE after watching rest of video: you tested just that... nope!
there are a lot of different names for the linear feedback shift register...e.g. I've always known them as "polynomial counters" and a friend referred to them as "Taylor counters." First one I can think of, was a write-up by Don Lancaster ca. 1976...
1:07 Is the actual DAC 8 bits? 1:38 Wouldn't it have been fun if they made it so if the voice-3 frequency is 0 and you write to $D41B, the voice-3 level is set to whatever (high) 8-bit value is written. Sounds like that capability was within grasp. 3:04 For a little more speed you could have wrapped the PEEK in a FOR loop of I=0 to 1 STEP 0. 11:15 The solid parts are called Merlons and the gaps are called Crenels. 17:26 Look at the huge bezel on that retro-phone! 19:20 You could make this run faster by using a BASIC numeric variable to hold the bits. You could use the bitwise operators if you extract 12-bit sub-values with division and subtraction. 23:48 I remember that name from the 1990s. Google has conflicting information on how to pronounce the Germanic (ä) letter.
The resultant waveforms are actually 12 bits (note the pulse width comparison register is also 12 bits). Except the triangle wave - this uses 11 bits, and the 12th bit is used to invert the remaining 11 bits giving you the triangle wave. This ability to invert the 11 LSBs of the triangle wave is what also enables the ring modulation.
You can improve the speed of the Basic LFSR program by using cyclic buffers. You then do not have to copy the values around. Instead you only have to store the start offset in the buffer. If you make the size of the buffer a power of 2, you can wrap around using AND.
To me the SID chip is better at generating music and the Atari POKEY chip is better at generating sound effects, especially explosions. Things blowing up just sound kinda wimpy through the SID.
If you are right about being temperature sensitive then every time you stop the program to edit it, then the hardware is cooling down ever so slightly as the c64 is idling more. That would explain why the program returns both the 'normal' and mixed number sequences can be achieved with the same delay value since everything begins heating up again. I would suggest adding the ability to change delay value with hotkeys while running.
"I don't know how long that would take." My simple calculations and rough guesstimate, using about 13 seconds to do 24 iterations on your C64.. works out to about 52.6 days. Assuming it doesn't slow down the further it gets into larger numbers. But that was the only major factor I could think of, so about 52.6 days. A long time, in other words. And I guess screen scrolling would add in a little extra time as well.. I could get a better estimate by running some longer demos later. Maybe I'll try that.
FASCINATING -- I always thought the SID was sampling radio noise or something. Question, does the C64 kernal do any kind of SID setup in its startup sequence? (I imagine it might.) Or, you might put your program into a cartridge and have it start sampling the SID immediately after startup, and see if it starts in that "11111111111111111111100" state (it must?) I was actually always frustrated by the SID, I could never get it to work properly (or the way I wanted it to). I wanted to command a voice to do its ADSR sequence, but I'd ask it for a new note prior to the final "release" and it wouldn't play the note! I never figured out how the other guys got the SID to work to play music. My experiments always skipped notes because the SID always insisted on playing the complete ADSR envelope for the current note before it would accept a command for the next note.
Currently working on an interrupt-driven tone generator (two voices) on my Tandy Color Computer 3. I am interested mostly on sine wave and crash/noise. It is not obvious doing that on a computer that has no sound hardware except for a 6-bit DAC output to a single speaker.
Hmm... why is that random-number generator in the SID kind of a random number itself, like 23 bits instead of more of a typically computerish number like 24 or 16 (a multiple of 2, 8, or 16, etc.)?
It seems that the reset bit only resets some of the bits in the 24 bit register and you have to wait until the oscillator cycles all the bits through the bits that are being reset. You can't observe all the 24 bits but it might be possible to infer the bits by running the program. Does that reset bit also reset the bits when the SID is in a different mode, say sawtooth? It might be possible to see on an oscilloscope what happens to the waveform at different frequencies, different delays etc.
I'm going to watch this a second time to catch any details I've missed, but in the meantime -- how frequently does the noise waveform update its output value, relative to the frequency of the oscillator? When you are showing the triangle wave, for example, we can see a single cycle stretched out over several seconds as it slowly ramps from 0 to 255 and back again... the noise waveform, on the other hand, is just switching from one pseudo-random number to another, right? So does it update this value once, twice, or some larger number of times per what *would* be considered a full wave cycle (even though it's different every time and therefore not technically "cycling")? Put another way, how many values would it output per second if its frequency was set to 1 Hz?
At about 15:00 is when you do say & demonstrate that the numbers are generated more rapidly as the frequency is increased; lemme keep watching and see if you ever specify how many times they change per "cycle" as per my above question... who knows, maybe I missed it on the first viewing...
After watching again, it seems like if it's updating about once per second at a frequency of "one", and the other waveforms cycle once at a little over 16 seconds, then it's likely the noise is updating its value 16x per "cycle period" as that is a nice, round, power of two. Anyway, I've just ported your LFSR simulator to C code and I'm going to play around with it, see if I can make some commodore-like fake explosion sounds or whatever. I know it can be made more efficient by using real bit-shifting, but I wanted to start as close as possible to the original just to make sure it's working. :) // SID LFSR simulation ported from BASIC int c = 0; int b[8] = {22,20,16,13,11,7,4,2}; int r[23] = {0,0,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1}; // initial shift register state while(c < 100){ int t = (r[22]+r[17])&1; //do taps for (int i=r; i>=1; i--) r[n] = r[n] - 1; //do shift r[0] = t; int v = 0; for (int i=0; i=0; i--){ // INSERT CODE HERE TO PRINT r[n] with NO carriage return } // INSERT CODE HERE TO PRINT tab, v, tab, c, carriage return c++; }
You don't need to pre-compute all the values for comparison, just run the simulation in tandem with the real thing step-wise; - Run sim until you have two different outputs. - Run SID until you have to different outputs. - Compare old to new, continue step-wise until you've iterated all 8million steps. OFC this will mask repeated values (assuming of course there's no way to guarantee that you're reading the "next" value from the SID every time, that would eliminate this issue) but I'd hazard the probability of getting the same "new" value after both generators have generated the same value for some arbitrary number of repeated steps is probably pretty low.
My friend DLH who runs the awesome BombJack site got a real C= security badge and made this excellent reproduction of it. I just like the look of it better than some of the solder burns on my table :)
Hi Robin! I am still enjoying this new found gem channel :-) I see you have an expansion board attached, with multiple card slots and some DIP switches. How does that work?
Hi, it's a CMD EX3 that extends the expansion port signals to 3 additional slots and allows some to be turned on and off individually. It's very useful to allow some cartridges to work together, such as the RAM expansions and Super Snapshot utility cartridge. I'll put a link in a 2nd comment (sometimes Google bots kill link comments):
Funny how the noise waveform is illustrated completely wrong in the book, the frequency is all over the place and it would not have that kind of linear slope even with the filter.
"Basic doesn't have an exclusive or". Well, BASIC 2.0 doesn't. BASIC 7.0 does, so clearly you should have done this on a 128 in 128 mode. :) (Though it's a function instead of an operator and spelled XOR even though the 6502 opcode is EOR. Never quite understood those choices...)
It should be audible during the "Robin From The Future" (handless) sections. In the other sections I'm setting the frequency so low that it's inaudible. I just did the math, it's at about 0.06Hz.
For the enthusiasts who find this interesting, then you may also like a video (DOScember Making AUDIO/Covox Hardware and Software) on my channel, where I create a DAC for a parallel port (8088 but works in everything) and explain the principle and I write a few pieces of code in assembly to generate sound from it.
Hi Robin. is there any way to improve this program. so that "BAD" is not displayed. why when I hold down the "W" key it shows "BAD". I have this effect on the vice c64 emulator. I don't have a real computer. greetings. 10 GETA $ 20 IF A $ = "W" THEN? "SHOT": GOTO10 30? "BAD": GOTO10
Thanks to several people who have mentioned the square waves look like battlements or crenelations : which are "a parapet with alternating openings (embrasures) and raised sections (merlons), often used on castle walls and towers for defense purposes." At least I got "merlon" right! sites.pitt.edu/~medart/menuglossary/crenelation.htm
Castellations, castellated?
I'm not sure what is so compelling about watching white numbers scroll down a blue screen for 45 minutes, but it is! You are either an evil genius secretly hypnotizing all of us - someday you'll flip a switch and we'll turn into your 8-bit zombie horde - or else you're unappoligetically following your geeky soul which we all love because it's somehow similar to our own.
Kind of funny how even 20 years after being introduced to Basic I still find this stuff interesting. Keep up the good work!
Basic blows my mind everyday what the c64 could do is amazing
Fun fact: the star field background on Galaxian arcade games is a LFSR output to the screen, under the sprites and text. Its period is plus or minus one of the number of vertical pixels, so it scrolls one pixel per frame. Plus one to scroll in one direction and minus one to scroll in the other. It was a really efficient way to make a nice scrolling background. Maybe four TTL IC's.
Back on the SID though. My first guess is the 24-bit registers are dynamic rather than static, so they need to be refreshed much like in the 6502 itself. I assume the TEST bit in the register halts the refresh cycle, so the bits start to float up to a 1 state. This would explain the 'analogue' nature of the reset, because the registers are slowly drifting at random rates to 1's. As soon as the TEST bit is released, it'll latch the random values in the register. If anyone knows more about it, I'd love to hear!
Also, if you wanted to find the state of the hidden bits of the shift register after applying the TEST bit, you wouldn't need to compare the output against a table of the sequence. Just allowing it to shift 24 times and measuring the MSB each shift will give you the result, because the hidden data doesn't change as its being shifted. It could be done in BASIC quite accurately if there was a loop to wait until the register changes, and to print the MSB as it shifts in. Cheers.
As to my understanding of SID chip, on every rising edge of clock signal, 24bit oscillator is adding 16bit value from $d400/01 (first channel) to itself. If test bit is set, it will reset that 24bit oscillator to 0. Noise LFSR is driven by rising edge of bit 19 of oscillator.
Good idea! It works too, here it is:
100 A =54299:REM OSC 3 OUTPUT
110 REM LOWEST FREQ $0001
120 POKE 54286,1:POKE 54287,0
130 REM 50/50 PULSE DUTY CYCLE $800
140 POKE 54288,0:POKE 54289,8
150 REM 16=TRIANGLE, 32=SAWTOOTH
160 REM 64=PULSE, 128=NOISE
170 POKE 54290,128
180 REM PRINT PEEK(A):GOTO180
200 R=22:B=7
210 C=0:DIM R(R),B(B)
220 FOR I=0 TO B:READ B(I):NEXT
230 DATA 22,20,16,13,11,7,4,2
240 REM CREATE THE 23 BIT REGISTER
245 PRINT:PRINT "recreate the 23-bit register"
250 FOR I=R TO 0 STEP -1
260 D=PEEK(A):R(I) = -(D>127):PRINT CHR$(48+R(I));
270 IF PEEK(A)=D THEN 270
280 NEXT I:PRINT
290 REM 23 BIT REGISTER RECREATED
300 REM BUT RANDOM NUMBERS ARE 23
310 REM BEHIND IN THE SEQUENCE.
315 PRINT:PRINT"sid","lfsr"
320 FOR I=0 TO R
330 GOSUB 810
340 IF PEEK(A)D THEN PRINT D,"i=";I:D=PEEK(A):I=I-1:REM DO ANOTHER SHIFT
350 NEXT I
400 REM LFSR REGISTER HAS MATCHED SID
410 GOSUB 710:PRINT D,V
420 IF PEEK(A)D THEN D=PEEK(A):GOTO 410
430 GOTO 420
599 END
700 REM CREATE NEXT RANDOM LFSR SAMPLE
710 V=0
720 FOR N=0 TO B:V=V*2+R(B(N)):NEXT N
800 REM PERFORM LINEAR SHIFT
810 T=(R(22)+R(17)) AND 1
820 FOR N=R TO 1 STEP -1
830 R(N)=R(N-1):NEXT N
840 R(0)=T
850 RETURN
Niche appeal no doubt, but for me, this is my favorite episode in 2022 to date. Nice experiments, demonstrations, and explainations!
Thanks for doing this one. I somehow missed it when I was looking for SID random number generation help earlier. I had no idea what all was involved in a Linear-Feedback Shift Register, until now.
You have a gift for explaining a wide range of topics from the very simple to the very complicated in a way that is easy for me to understand. None of your videos are boring or uninteresting. You make all of them a fun adventure to tag along on with you.
I've been a fan of LFSRs ever since after reading about how "River Raid" for Atari VCS used one to procedurally generate the playfields. It was programmed by Carol Shaw in 1982. Yay for women engineers!
Yes, I think the story is that David Crane got onto LFSRs for generating the world of Pitfall! and then that idea went around the office and Carol realized it would be perfect for River Raid.
Well woman are only the whole other half of humanity so I guess shocker they can program?
Yes. River Raid was one of the first algorithmically generated worlds. At the time it was a nice way to create a very big game environment with tiny amount of code.
If you play a note, then set the waveform to 0 but keep the gate on you get the same analog delay effect but with audio. E.g. poke 54290,17 and then poke 54290,1
I believe you can also use a REU to sample voice 3 output at high frequency.
The VIC chip in the VIC 20 also uses a LFSR but it does not have enough bits, so you can actually hear the noise repeat.
Went with the British spelling of Behaviour. You Canadians are a confusing bunch ;-)
I've been fascinated with the LFSR in the SID for a long time. Done enough Cipher work on 8 bit machines to have a real appreciation for how well this worked given the time it was designed. This is the best visualization I've seen so far.
There's a fantastic series of programs in Programming the 64 that do an excellent job with explanations and visuals of many SID concepts. It's Chapter 13.
31:16 - almost 56 days on an NTSC machine
I wrote a SID (and 6510) simulator for AVR microcontroller around 2005 and couldn't get the noise channel quite right. I don't remember if the info just was not easily available or I just didn't research it properly. Any way, the AVR played songs on real 6581 quite nicely, and somewhat acceptable on the simulated SID :D great video!
I just discovered your channel. Man I got immediately impressed by the sheer details you get into and knowledge you possess. Great stuff!
Thanks for watching!
17:49 Go to bed, Robin, it's gone four in the morning.....
This video is actually super helpful for me, because I've been contributing to a C64 emulator. I had ideas as to better implement $d41b, but this video and the way you described the data in this register gave me a lot of ideas!
Very nice that you are able to demonstrate the internals of the SID just using plain basic like this.
8:24 Future Robin meant to say "release", not decay
I'd love to see you an Bil Herd do an episode together. It would be interesting to have a developer and a hardware engineer discuss some of this.
Thank you for this interesting and informative tutorial to the mysterious SID chip - mysterious to me, that is. I loaded your disk into MAME and followed along, changed parameters and got some unearthly sounds out of the emulated SID. Great fun!
While there isn't a dedicated operator, you can still perform XOR operations in BASIC using:
(n1 or n2) and not (n1 and n2)
It doesn't really matter much for just one bit, but the above method works on larger values (up to 15 bits in BASIC), without using math tricks.
This is the way I would do. But I found Robin's way creative. An thinking the way Basic works (at least on Apple II and TRS80 that I am more familiar with) maybe even faster.
I may well have left a comment before on this video but I need to leave another because I've just watched it again and want to thank you once more. I wanted to implement a 'noise' waveform in my e-ther theremin-like device and the idea of generating it in the same way as the SID appealed to me. (frankly, if someone's already done the hard work, and done it extremely well, then you're silly to try to reinvent the wheel). I was very happy that a search of your channel for 'lfsr' found the right video! (I did remember that it was a 23-bit lfsr). It was a pleasure to watch the whole video again and your explanation of how the numbers are generated was very clear and thorough. I was easily able to write the same pseudo-random number generator in C (even making an 8-bit value by selecting those exact same bits). The bit that baffled me a little was how to get it to sound different at different 'frequencies'. (I started out by making every sample a random number. If you resample a bunch of random numbers, guess what, you get a bunch of random numbers and it sounds the same!!) I realised that the SID changes the rate that it changes the number (according to the frequency settings) and once I did the same then I had something that sounded like the SID, ie if you go up through the frequencies, it sounds a bit more like applying filter than changing the frequency. It's a really nice effect when you control the 'frequency' and volume with theremin-like controls. (good for seaside effects etc). ~ Shiela
I understand that you can get some interesting waveforms by turning on multiple bits of the waveform register at once (I've seen some music use them, the title music for Ghosts 'n' Goblins for instance)--it'd be neat to see a discussion of how that works. Also the low-pass filters!
Supposedly, Bob Yannes was shooting for 32 voices for the SID but there wasn't enough time or money (silicon space) to do it. Can you imagine what could be accomplished with 32 voices considering what they can now do with "only" 3?
I believe the sound chip in the Apple IIGS is close to how Yannes originally imagined the SID.
It would judt sound yet another FM synthetis. SID sound is so distinc because clever programmers did magic around the limitations. We would have missed the charm of that era completely.
@@DMStern Could be since Ensoniq created that chip and Bob Yannes was the founder of Ensoniq. Also, it has 32 voices, just as his original concept for the SID would have had. It's strange that the Apple II GS is not more well known and revered for its sound prowess given its impressive on-paper capabilities.
Great timing with this. I'm currently working on music for my C64 port of the arcade game Venture. I am not a musician, but I'm trying to do the whole thing myself.
Cool, I love Venture and played it a lot on my ColecoVision and Atari 2600. Let me know when you get it done!
@@8_Bit It's done as far as everything is in there. That was not such a simple game to program!
"And it has a more kind of 'biting' sound..."
Yes, yes, like the "TEETH" (ha, of course!) of a basic (ha, "BASIC"!) sawblade!
I tried your program on a C64 mini ... it worked fine with no delay needed
I wonder what the 54299 register looks like over time during your line 90 loop, after the test bit is set. If I had my C64 set up I'd try it out.
Cool stuff!
Another interesting episode. Thank you. I think it uses 23 and 17 because they are both prime numbers. If one of the numbers was divisible by 2, for example, then the sequence would likely be half as long. Just a wild guess :-)
Clearing the gate bit starts the release phase of the envelope, not the decay. The Attack, decay and release phases are trigged by the gate bit, with the sustain lasting until the gate is cleared, which starts the release.
We appreciate you geek-meister, we really fricking do 👌
"I don't know how I'm going to edit this" ... Not that it matters; we are going to sit on the edge of our seats watching every run :-)
Any chance the reset isn't really a reset but a continuing through the sequence until the initial register state is reached? That seems like it fits with being called a test bit. It would also explain the timing differences. The further along in the sequence when you hit reset, the less time it takes to get back to the beginning.
I don't think so. The sample playing routine used in the "Vicious Sid" demo is based on reseting the oscillator using the test bit, and then waiting until it reaches the desired value (search for "Vicious Sid Demo Routine Explained" for an in-depth explanation). From a chip-design perspective it also wouldn't make much sense.
(Edit: of course it's always possible the noise oscillator behaves completely differently from the others in this regard.)
The random reset is most interesting thing in video! I thought the output values would be far later in the sequence because of delay in BASIC for Poking the test bit before you actually enable the waveform... I think the PLA, power supply (or both) are bad in my C128 so can't test my SID. Is there any difference in timing if you enable the waveform and then (or simultaneously) set the test bit?
From hardware engineering background, assuming above idea has no effect, I can only guess some kind of drain / slow-leak circuit is activated with test bit? As charge is slowly dissipated, bits will 'randomly' register as 1, and the longer the time, the more likely? Such a scheme would explain the various (presumably thermal differences you report) and would also be cheaper than 22 "reset" transistors...
Still doesn't explain why they would not just continuously feed all 1s into the LSFR and you could then reset quickly with high frequency ... which your video showed does not work... anyway, great video!
This is great stuff, thanks for sharing!
I Love the SID Chip and all of those Sid tunes I had helped me get into the original artists music.
But my latest endeavor are the GIF viewing software for the Commodore 64. They let me translate older 87a GIF files. But anything made after the 89a upgrade won't let me convert newer GIF files on my VICE emulator. I'm really bummed because I used Photoshop 7 (Yes a very old version of Photoshop to create the GIFS. But even those are not recognized by either of the two GIF viewing programs I found for the Commodore 64. They both only translate GIFS that are really old that I have. My one friend would screen cap games on his Tandy PC and then send them to me over his modem to my C64. So I have images from Space Quest 3, Ultima 6 and 7 and also X-Wing. Plus some art work by people creating EGA and VGA drawings or digital scans. All the images I'm trying to view came from my Canon DSLRS. I made the images 320 X 200 and some at 160 X 200. I limited there color range and saved them as GIFS. I used a D64 editor to add them to a virtual disk. However only my oldest GIFS I have from the early 90s work with the decoding software. I wonder if anyone has written an up to date GIF viewer for the C=64 that will view 89a GIFS?
You could write a sample and hold modulator with the output of oscillator 3 and the noise waveform. The random "bleep bloop" stereotypical computer sound you got a lot in 60s and 70s sci-fi _is_ a sample and hold from old analogue synths like the Moog Modular and Arp Odyssey. Peek a value from oscillator three and set the pitch of a triangle wave on another oscillator with some kind of multiplier. Hold that value for a period of time before Peeking another one. You do this so you don't get a smooth pitch transition and get that stepped effect. Voilà! Sci-Fi computer sound. For extra flair, retrigger the envelope with each sample so it's like a small pluck.
It's funny how they call it "white noise" in the manual. You can't pitch white noise. I think it's actually periodic noise. Given the SID is an analogue Synthesizer I'm surprised they didn't put a real whitenoise generator in there. Periodic is more useful for percussion, though.
Crenelations! The things on top of a castle wall.
I thought where you were going was to get the SID with noise as a random number generator. I liked watching all this. I have done the same "science" myself. Its a cross between study and play 😂😃😁
3:45 To help visualize the waveform, I commented line 180 and added the following line which prints asterisks in a horizontal position that is proportional to the available screen width:
190 printtab(peek(a)/6.6)"*":goto190
Fun fact: Square waves and triangle waves both consist only of odd harmonics of the base frequency. They sound different because the amplitudes of the harmonics fall off faster for the triangle. Also of note, a square wave is a special case of a pulse wave, when the duty cycle is 50%. Anything other than 50% is not a square wave and will include even harmonics.
fascinating. this means we could create a real digital oscilloscope / spectrum analyzer for that oscillator! :)
Future Robin!? Great Scott!
The SID was before it's time with ADSR and more. In fact they jumped this to stored sounds using DACs. The AY 3 series of chips never had the power of the Sid.
Shame no one to build any more Sid's.
Does anyone hay the original mask
Interesting, 40 years and there are still things we don't know about Commodore 64.
Fascinating stuff Robin! Is it me, or when the Linear shift isn't producing the expected values, the values it does select seem to change faster, or is that the magic of video editing?
Thanks again!!
I do jump cut ahead at times when I have nothing to say, but I didn't change the speed of the video at all (like, a fast-forward effect) in this video. So it should be all real-time, except for when I jump ahead. So I'm not sure what would make it seem faster, that's strange!
@@8_Bit You could see this effect straight away. unless you were skipping in seconds ... the C64 display wasn't jumping around though!
Very odd!
The longer you let it run, the more bits are shifted, and will need to be reset, thus your running before resetting influences the amount of resetting that may be needed.
If some bits are slower to reset it makes sence it works if those bits doesn't have to reset...
Setting a rate that matches with a few readouts of each value, then making sure the program runs for same amount of iterations before stopping every time will at least make that more consistent.
It also needs to stop the sid.
My wild guess: the test bit feeds into the lfsr instead of the tap. So when set you need wait long enough for whatever frequency you set. You set an extremely low sequence so must wait in the tenth of seconds. Should try with higher frequency if test bit gets 1s in the lfsr quicker.
It would make sense to me that they did NOT implement a parallel load of 1s in a hardware 22 bit registers (it needs lots of transistors) but they can well put a gate: lower bit comes from either TAP or from fixed 1 when TEST is set.
UPDATE after watching rest of video: you tested just that... nope!
there are a lot of different names for the linear feedback shift register...e.g. I've always known them as "polynomial counters" and a friend referred to them as "Taylor counters."
First one I can think of, was a write-up by Don Lancaster ca. 1976...
very interesting Robin
Never thought id miss seeing your hands but this video prooved me wrong
1:07 Is the actual DAC 8 bits?
1:38 Wouldn't it have been fun if they made it so if the voice-3 frequency is 0 and you write to $D41B, the voice-3 level is set to whatever (high) 8-bit value is written. Sounds like that capability was within grasp.
3:04 For a little more speed you could have wrapped the PEEK in a FOR loop of I=0 to 1 STEP 0.
11:15 The solid parts are called Merlons and the gaps are called Crenels.
17:26 Look at the huge bezel on that retro-phone!
19:20 You could make this run faster by using a BASIC numeric variable to hold the bits. You could use the bitwise operators if you extract 12-bit sub-values with division and subtraction.
23:48 I remember that name from the 1990s. Google has conflicting information on how to pronounce the Germanic (ä) letter.
The resultant waveforms are actually 12 bits (note the pulse width comparison register is also 12 bits). Except the triangle wave - this uses 11 bits, and the 12th bit is used to invert the remaining 11 bits giving you the triangle wave. This ability to invert the 11 LSBs of the triangle wave is what also enables the ring modulation.
It's pronounced like the "a" in "fashion".
You can improve the speed of the Basic LFSR program by using cyclic buffers. You then do not have to copy the values around. Instead you only have to store the start offset in the buffer. If you make the size of the buffer a power of 2, you can wrap around using AND.
Harder to debug, and the LFSR appears to be 23 bits, which complicates things a bit. For a quick one-off, what he did is the easiest.
8 bit show and tellikinesis. I see what you did there :)
To me the SID chip is better at generating music and the Atari POKEY chip is better at generating sound effects, especially explosions. Things blowing up just sound kinda wimpy through the SID.
The POKEY has a fantastic gritty sound. As does its predecessor the TIA in the Atari 2600; I love some of those sound effects.
If you are right about being temperature sensitive then every time you stop the program to edit it, then the hardware is cooling down ever so slightly as the c64 is idling more. That would explain why the program returns both the 'normal' and mixed number sequences can be achieved with the same delay value since everything begins heating up again. I would suggest adding the ability to change delay value with hotkeys while running.
"I don't know how long that would take." My simple calculations and rough guesstimate, using about 13 seconds to do 24 iterations on your C64.. works out to about 52.6 days. Assuming it doesn't slow down the further it gets into larger numbers. But that was the only major factor I could think of, so about 52.6 days. A long time, in other words. And I guess screen scrolling would add in a little extra time as well.. I could get a better estimate by running some longer demos later. Maybe I'll try that.
Im curious how this woukd sou d on the D64tv. It would probably take me several hours to type that out using the joy stick on the device
Great and interesting video! 👍😎
Cool video! Will you please revisit this with a program that makes the sounds and prints the values at the same time?
FASCINATING -- I always thought the SID was sampling radio noise or something.
Question, does the C64 kernal do any kind of SID setup in its startup sequence? (I imagine it might.)
Or, you might put your program into a cartridge and have it start sampling the SID immediately after startup, and see if it starts in that "11111111111111111111100" state (it must?)
I was actually always frustrated by the SID, I could never get it to work properly (or the way I wanted it to).
I wanted to command a voice to do its ADSR sequence, but I'd ask it for a new note prior to the final "release" and it wouldn't play the note!
I never figured out how the other guys got the SID to work to play music. My experiments always skipped notes because the SID always insisted on playing the complete ADSR envelope for the current note before it would accept a command for the next note.
Currently working on an interrupt-driven tone generator (two voices) on my Tandy Color Computer 3. I am interested mostly on sine wave and crash/noise. It is not obvious doing that on a computer that has no sound hardware except for a 6-bit DAC output to a single speaker.
What happens if you put one of those numbers other than the 2^something like 64 in the waveform slot?
Hmm... why is that random-number generator in the SID kind of a random number itself, like 23 bits instead of more of a typically computerish number like 24 or 16 (a multiple of 2, 8, or 16, etc.)?
It seems that the reset bit only resets some of the bits in the 24 bit register and you have to wait until the oscillator cycles all the bits through the bits that are being reset. You can't observe all the 24 bits but it might be possible to infer the bits by running the program.
Does that reset bit also reset the bits when the SID is in a different mode, say sawtooth? It might be possible to see on an oscilloscope what happens to the waveform at different frequencies, different delays etc.
The GEOS had a tight loop to decode its loaded code using this. 😎
Thanks!
im wondering if the test bit is OR'ing what goes into the LFSR, and if ya dont hold it long enough you dont get a full reset or something?
"8-Bit-Show-and-Telekinesis," hahaha!
I'm going to watch this a second time to catch any details I've missed, but in the meantime -- how frequently does the noise waveform update its output value, relative to the frequency of the oscillator? When you are showing the triangle wave, for example, we can see a single cycle stretched out over several seconds as it slowly ramps from 0 to 255 and back again... the noise waveform, on the other hand, is just switching from one pseudo-random number to another, right? So does it update this value once, twice, or some larger number of times per what *would* be considered a full wave cycle (even though it's different every time and therefore not technically "cycling")? Put another way, how many values would it output per second if its frequency was set to 1 Hz?
At about 15:00 is when you do say & demonstrate that the numbers are generated more rapidly as the frequency is increased; lemme keep watching and see if you ever specify how many times they change per "cycle" as per my above question... who knows, maybe I missed it on the first viewing...
After watching again, it seems like if it's updating about once per second at a frequency of "one", and the other waveforms cycle once at a little over 16 seconds, then it's likely the noise is updating its value 16x per "cycle period" as that is a nice, round, power of two.
Anyway, I've just ported your LFSR simulator to C code and I'm going to play around with it, see if I can make some commodore-like fake explosion sounds or whatever. I know it can be made more efficient by using real bit-shifting, but I wanted to start as close as possible to the original just to make sure it's working. :)
// SID LFSR simulation ported from BASIC
int c = 0;
int b[8] = {22,20,16,13,11,7,4,2};
int r[23] = {0,0,1,1,1, 1,1,1,1,1,
1,1,1,1,1, 1,1,1,1,1,
1,1,1}; // initial shift register state
while(c < 100){
int t = (r[22]+r[17])&1; //do taps
for (int i=r; i>=1; i--) r[n] = r[n] - 1; //do shift
r[0] = t;
int v = 0;
for (int i=0; i=0; i--){
// INSERT CODE HERE TO PRINT r[n] with NO carriage return
}
// INSERT CODE HERE TO PRINT tab, v, tab, c, carriage return
c++;
}
Your telekinesis sounds a lot like someone typing on a keyboard.
You don't need to pre-compute all the values for comparison, just run the simulation in tandem with the real thing step-wise;
- Run sim until you have two different outputs.
- Run SID until you have to different outputs.
- Compare old to new, continue step-wise until you've iterated all 8million steps.
OFC this will mask repeated values (assuming of course there's no way to guarantee that you're reading the "next" value from the SID every time, that would eliminate this issue) but I'd hazard the probability of getting the same "new" value after both generators have generated the same value for some arbitrary number of repeated steps is probably pretty low.
Didn't appreciate the frequency going down to 1/16Hz. It would have made a good analog function generator.
To get to 8388608 at a rate of one per second would take a little over 97 days.
It looks like your simulator runs at 2 per second so it would take ~48.5 days
I've always wondered what the security badge is about. Did you work as security for commodore?
My friend DLH who runs the awesome BombJack site got a real C= security badge and made this excellent reproduction of it. I just like the look of it better than some of the solder burns on my table :)
Hasn´t the SID been decapped and analyzed like the 6502?
Hi Robin! I am still enjoying this new found gem channel :-)
I see you have an expansion board attached, with multiple card slots and some DIP switches. How does that work?
Hi, it's a CMD EX3 that extends the expansion port signals to 3 additional slots and allows some to be turned on and off individually. It's very useful to allow some cartridges to work together, such as the RAM expansions and Super Snapshot utility cartridge. I'll put a link in a 2nd comment (sometimes Google bots kill link comments):
rr.pokefinder.org/rrwiki/images/3/3b/Commodore_World_Issue07Vol02No02_EX2plus1_EX3.pdf
Funny how the noise waveform is illustrated completely wrong in the book, the frequency is all over the place and it would not have that kind of linear slope even with the filter.
Hi,id like 16550 packs of hole punched continuous paper for my old printer… and do you sell ink ribbons?
I wonder if you could see the values by using an oscilloscope to capture the signal while the program is running
Wonder who decided to call it peeking and pokeing
9:10 ever look at an old hacksaw or wood saw blade? Looks Alot like it..., probably sound little like a saw too
"Basic doesn't have an exclusive or". Well, BASIC 2.0 doesn't. BASIC 7.0 does, so clearly you should have done this on a 128 in 128 mode. :) (Though it's a function instead of an operator and spelled XOR even though the 6502 opcode is EOR. Never quite understood those choices...)
Could they not have used a DES chip in CBC Mode to generate the random numbers.
Where is SID sound? Am I going deaf?
It should be audible during the "Robin From The Future" (handless) sections. In the other sections I'm setting the frequency so low that it's inaudible. I just did the math, it's at about 0.06Hz.
Does that box say Space Pilot or Space Pilaf?
I'd like to try some Space Pilaf!!
Why do you READ A: B(N)=A instead of just doing READ B(N)?
No good reason - that was probably refactored code that I didn't think to clean up afterwards.
sounds like a leaky air hose :-)
For the enthusiasts who find this interesting, then you may also like a video (DOScember Making AUDIO/Covox Hardware and Software) on my channel, where I create a DAC for a parallel port (8088 but works in everything) and explain the principle and I write a few pieces of code in assembly to generate sound from it.
❤
PCs still faster, still not much megahertz. c64 the same for decades. constantly being rediscovered.
Boolean math
2^16 = 65536 that is my guess
0+0 should have 0+0*15
That was 3 unedited videos smushed together. The noise thing, was that 20 minutes? Oh only 13. Just arrrgh
Hi Robin.
is there any way to improve this program. so that "BAD" is not displayed.
why when I hold down the "W" key it shows "BAD". I have this effect on the vice c64 emulator. I don't have a real computer. greetings.
10 GETA $
20 IF A $ = "W" THEN? "SHOT": GOTO10
30? "BAD": GOTO10