Jump to content

Programming a SID Chip Directly


skrasms
 Share

Recommended Posts

This is a little bit off-topic, but deals with the SID chip itself.

I am trying to interface a SID 6582 directly with a microcontroller. I think I have everything connected correctly, but I do not have any tested write sequences to use. Basically, what is the simplest set of register writes I can do to get sound? When I first turned the chip on and sent some random data to it, sound came out. To turn on oscillator one, I tried this sequence:

1) Reset all registers to zero (route oscillators straight to output, clear everything)

2) Write anything to address 0

3) Write anything to address 1

4) Write 10000001 to address 4 (select noise wave, turn on gate)

5) Write 11110000 to address 6 (maximum sustain value)

6) Write 00001111 to address 18 (maximum output volume)

7) Wait

...but the result was no output. Is that not a good program to get oscillator 1 going? I am trying to narrow the problem down to being software or hardware.

I have the write pin tied low (it is active low for writing), and toggle the CS pin low for two microseconds then high to write data. It's a poor scheme for timing, but it seemed like it would work for a test run.

Any help/advice would is greatly appreciated.

Link to comment
Share on other sites

we too!!

Sorry i can  t help with technical details but i was just wondering: why don t you study the SID application to see what it is needed and where?

Simone

I've been looking at the asm code from the midibox SID micro, but most of it is over my head right now. I program my micro almost completely in C.

Link to comment
Share on other sites

It's working now! There were 3 errors:

1) The address for output volume is 24, not 18. 0x18 is the hex value for 24

2) I had a couple address bits switched

3) The timing for my writing scheme was sketchy. I moved it to an interrupt routine in sync with the clock signal to guarantee the datasheet timing specs are met every time.

It takes about 9 microseconds for my write routine to update the SID... a little slow but not terrible.

Link to comment
Share on other sites

  • 2 weeks later...

Mine is working also, but the notes are not sounding equal every time. My guess this has to do with the crystal not being in sync with the crystal of the atmel.

How did you make the clock tick with the SID?

I guess a possible solution would be to make a timer pwm output run at 1 MHz.

Any suggestions??

Link to comment
Share on other sites

Mine is working also, but the notes are not sounding equal every time. My guess this has to do with the crystal not being in sync with the crystal of the atmel.

What do you mean about notes not sounding equal? Do you mean if you write the same frequency register values twice you hear different pitches each time?

How did you make the clock tick with the SID?

I guess a possible solution would be to make a timer pwm output run at 1 MHz.

Any suggestions??

That works great. 1MHz PWM with 50% duty cycle is what I'm doing.

Link to comment
Share on other sites

What do you mean about notes not sounding equal? Do you mean if you write the same frequency register values twice you hear different pitches each time?

That's exactly what i mean. I've checked what my mega8535 made of the midi codes for the SID and they were all correct and the same every time. So the only factor that could make the difference is the fact that the SID and the mega8535 are running asynchrone. 

Link to comment
Share on other sites

Are you using only one, or all 3 oscillators with the same pitch?

It doesn't sound like that, thats more a phasing-like problem. Mine is really like bits are not read correctly due to the async of the clocks.

All 3 oscillators are with the same pitch, the result that is computed is correct and also correct on the output pins of the 74hc595's.

The result in sound are wrong, some are off pitch, others on pitch.

Every time a note is played on the SID the result is different. It seems like some bits are not read correctly by the SID, all the pins on the 74hc595's are correct though. So that made me jump to the conclusion that it might be the 1 MHz clock being async with the mega8535.

Link to comment
Share on other sites

I accessed the SID totally asynchronously many years w/o such problems. It works, so long it is ensured that address/data is stable before CS# (and WE#) has been activated. The pulse width of the CS# line should be at least 1.2 uS at 1 MHz SID clock rate.

There is only one issue which could happen on asynchronous control: the gate could be triggered twice.

But you will notice this effect only on very sophisticated drum sounds - I guess, that you are far away from such a step ;)

Recently I rewrote the SID access routines in C. For the case it helps:

http://svnmios.midibox.org/filedetails.php?repname=svn.mios32&path=%2Ftrunk%2Fmodules%2Fsid%2Fsid.c

Best Regards, Thorsten.

Link to comment
Share on other sites

I actually also did run the SID asynchrone with an AT90S8515. And that ran perfectly, SID directly connected to the 8515. Now, 2 years later, i decided to use the SIDboards you designed in combination with a mega8535 (for obvious reasons, being the onboard 8x ad conversion etc..). Earlier on i had trouble issues with the powersupply of this newly build SIDsynth, but this has been overcome.

It puzzles me why this new combination did not work as well as my old setup. So I suspected it had to be something with clock not being sync. (although I've never had any troubles with that before...). As is said; the board for the SID is now a board you designed (v3). My only change is that the CLK input is being fed by a crystal of 1 MHz and not by a PWM output. Outside that board is a mega8535 with a midi in- and output. (you might want to have a look at http://avr.tjerkdegroot.nl/) Also i completely reprogrammed the routine, it now only has the basics to trigger notes etc.

Your last post made me start thinking about the CS# en WE# lines... I'll check them, first thing..

The CS is connected to the SID via a pin on the 8535, directly to the SID.

The WE (I guess the R/W line is what you mean) is connected directly to GND via your board.

The RES (reset pin no 5 on SID) is connected to a pin on the 74hc595

Seems ok to me? Thanks for your cooperative support Thorsten!

Link to comment
Share on other sites

Your last post made me start thinking about the CS# en WE# lines... I'll check them, first thing..

The CS is connected to the SID via a pin on the 8535, directly to the SID.

The WE (I guess the R/W line is what you mean) is connected directly to GND via your board.

The RES (reset pin no 5 on SID) is connected to a pin on the 74hc595

Thats fine.

I assume that one of the following issues leads to instable register writes:

  • setup or hold violations while loading the serial registers. I don't know, if you are using the SPI peripheral, or if you are using a SW based bitbanging method. For testing purposes, just reduce the frequency (bitbanging: insert some NOPs between shifts) - especially ensure, that there is a delay between setting the serial input of 74HC595, and setting SCLK=1
  • CS# active (=0) while updating the address/data values - ensure, that CS# is 1
  • there should be a delay between the rising RCLK edge (74HC595 take over address/data values) and the falling CS# edge to ensure, that the data/addresses are stable during CS#=0

Could it be, that mega8535 is clocked at a higher frequency? Then such IO timing issues would be obvious.

If this doesn't help, just show your code - it says more than 1000 words ;)

Best Regards, Thorsten.

Link to comment
Share on other sites

The mega 8535 is not overclocked, it is running at its own normal speed (being 8 MHz coming from a crystal).

Your hint for the timing between setting the serial input and settings of SCLK=1 sounds like a good idea.

I'll be happy to show you the code of my routine that sends the data to the 74hc595's.

(come to think of it; i already tried building in a delay but that didn't work out, never thought of the NOP's though.. good idea!)

In my routine i use two databytes for controlling the SID.

1: shiftctrl = holds the addressreg for the data

2: shiftdata= holds the data for that address

And one more:

3: portcout = contains the data that will be put on the port (i do this so i can alter the bits without disturbing any real outputs on portc, this way only

the correct byte appears on the port C)

Reset bit is being set in the routine here below, as well as the controls for sending the bits to the 74hc595s

Hope you can read it well..

Sendportc:
SendportcSetup:
			ldi temp,16
			sts shiftcount,temp

			lds temp,portcout	;keep CS low
			cbr temp,CS		;
			sts portcout,temp	;

			lds temp,shiftctrl	;keep reset high on SID
			sbr temp,sidreset	;
			sts shiftctrl,temp	;
sendportlus:
			lds temp,portcout
			cbr temp,RCLK		;outputs 74hc595 low, do not show
			cbr temp,SCLK		;SCLK clockbit keep it low
			sts portcout,temp
			out portc,temp
sendcrotate:
			lds temp,shiftctrl
			clc
			ror temp			;shift first ctrlbyte
			sts shiftctrl,temp

			lds temp,shiftdata
			ror temp			;shift second databyte
			sts shiftdata,temp

			brcs sendwelcarry	;carry set?
sendgeencarry:
			lds temp,portcout
			cbr temp,serdat
			sts portcout,temp
			rjmp sendport
sendwelcarry:
			lds temp,portcout
			sbr temp,serdat
			sts portcout,temp
sendport:
			lds temp,portcout
			out portc,temp		;portcout op port C zetten

			lds temp,portcout
			sbr temp,sclk		;SLCK clock high
			sts portcout,temp
			out portc,temp

			lds temp,portcout
			cbr temp,sclk		;SLCK clock low
			sts portcout,temp
			out portc,temp		

			lds temp,shiftcount    ;clkcounter test all 16 bits 
			dec temp
			sts shiftcount,temp
			brne sendportlus	;
			;rjmp sendportcshow
SendportcShow:
			lds temp,portcout	;RCLK high, show the outputs....
			sbr temp,RCLK
			sts portcout,temp	
			out portc,temp
			lds temp,portcout	;RCLK low
			cbr temp,RCLK
			sts portcout,temp	
			out portc,temp
SendPortcEnd:
			ret

EDIT: I've noticed I've never actually made CS low on the port nor do I make it high in the routine..hmmm

I'll try to make CS high, show on port

then transfer bits to 74 hc595

make CS low, show on port

and show bits 74hc595 to SID

And insert a few NOP here and there..

Link to comment
Share on other sites

It's fixed!

The problem was that the timing between pushing bits towards the 74hc595 and clockin them in.

Thanks for pushing me in the right direction!

I'll include my routine here, for others to freely use and ofcourse, make it better!

Sendportc:
SendportcSetup:
			ldi temp,16
			sts shiftcount,temp

			lds temp,portcout	;keep CS low
			cbr temp,CS			;
			sts portcout,temp	;
			out portc,temp

			lds temp,shiftctrl	;keep RESET high
			sbr temp,sidreset	;
			sts shiftctrl,temp	;
sendportlus:
			lds temp,portcout
			cbr temp,RCLK		;dont show outputs 74hc595
			cbr temp,SCLK		;clockbit low
			sts portcout,temp
			out portc,temp

sendcrotate:
			lds temp,shiftctrl
			clc
			ror temp			;shiftctrl to right
			sts shiftctrl,temp

			lds temp,shiftdata
			ror temp			;shiftdata to right
			sts shiftdata,temp

			brcs sendwelcarry	;carry set?
sendgeencarry:
			lds temp,portcout
			cbr temp,serdat		;put 0 in serdat
			sts portcout,temp
			rjmp sendport
sendwelcarry:
			lds temp,portcout
			sbr temp,serdat		;put 1 in serdat
			sts portcout,temp
sendport:
			lds temp,portcout
			out portc,temp		;out with the serdat bit

			ldi temp,0x20		;delay 
senddelay:						;
			dec temp                   ;
			brne senddelay          ;

			lds temp,portcout
			sbr temp,sclk		;clockin high
			sts portcout,temp
			out portc,temp

			lds temp,portcout
			cbr temp,sclk		;clockin low
			sts portcout,temp
			out portc,temp		

			lds temp,shiftcount     ;all 16 bits done?
			dec temp
			sts shiftcount,temp
			brne sendportlus	;nope
SendportcShow:
			lds temp,portcout
			sbr temp,CS			;CS high
			sts portcout,temp
			out portc,temp

			lds temp,portcout	;RCLK high
			sbr temp,RCLK
			sts portcout,temp	
			out portc,temp
			lds temp,portcout	;RCLK low
			cbr temp,RCLK
			sts portcout,temp	
			out portc,temp

			lds temp,portcout
			cbr temp,CS			;CS low
			sts portcout,temp
			out portc,temp
SendPortcEnd:
			ret

Link to comment
Share on other sites

fine! :)

You should consider to use read-modify-write instructions (sbi/cbi on Atmel AVR) to control the pins, otherwise you will have to disable all interrupts which access the same port while reading/changing/writing the port output value.

Another advantage: this results into a step wise approach, which is required anyhow to avoid race conditions (like setting the serial output and SCLK at the same moment)

And it's faster (a single instruction to set/clear a pin) :)

8 MHz is quite slow, so that no "nops" (delays) are required. By unrolling the loop, you should be able to write a single SID register in ca. 11..12 uS

Best Regards, Thorsten.

Link to comment
Share on other sites

8 MHz is quite slow, so that no "nops" (delays) are required. By unrolling the loop, you should be able to write a single SID register in ca. 11..12 uS

I know, so today I changed the 8 MHz processor and crystal for a 20 MHz type (16 MHz for mega8535). I slipped in some more delay routines, played with the timing and now, everything is running smoothly!

This way it can perform some more tasks, like LFO's and LCDs and such.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...