Output a 1MHz clock for SID chip

I’m trying to build an 8 bit synthesizer based on the SID 6581 chip found in the Commodore64. It requires a 1MHz clock input. Right now I’m using the timer2 interrupt, but I’m not sure it’s working. Is there a more standard way to provide a reliable clock-out at a specific frequency than interrupts. Maybe a built-in function perhaps?

Thanks for any reply.

The code is based on the interrupt tutorial

void setupTimer2()
{

int result=(257 - 16); //the 0.5 is for rounding;

TCCR2A = 0;
TCCR2B = 0<<CS22 | 0<<CS21 | 1<<CS20;

//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;

//load the timer for its first cycle
TCNT2=result;
}
int counter = 0;
//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {

samples++;

if(samples == 16)
{
if(writeHigh)
{
digitalWrite(CLOCK, HIGH);
}
else
{
digitalWrite(CLOCK, LOW);
}
samples = 0;
writeHigh = !writeHigh;
}

//Capture the current timer value. This is how much error we have
//due to interrupt latency and the work in this function
latency=TCNT2;

//Reload the timer and correct for latency. //Reload the timer and correct for latency. //Reload the timer and correct for latency.
TCNT2=latency + 257 - 16;
}

I think your method will not work for one main reason: you are trying to interrupting every microsecond, and your interrupt takes much longer to execute that a microsecond. This frequent of an interrupt will pretty much take up all of your processing time, and you will have to write an incredibly efficient ISR just to make sure you get out before the next interrupt. You will need to do direct register manipulation (e.g. no calls to digitalWrite() as this takes several microseconds to execute) and you should probably write the ISR in assembly just to maximize speed efficiency.

Instead of interrupts, you could set it up so one of the timers outputs a 50% duty-cycle PWM at 1 MHz, or you could modify your mega168 to run off of a 1 MHz clock (internal 8 MHz RC oscillator with CKDIV8 fuse bit programmed) and output that clock signal on the CKOUT pin (though I'm not sure you want your entire Arduino running at 1 MHz, and I'm not sure how happy the bootloader would be with this).

I'd recommend using a hardware PWM. This would be a case of set it up and forget it, with no need for interrupts or any other processor interaction. You will have to configure the PWM yourself, however, as the analogWrite() function will not produce the proper frequency. I suggest you use a fast PWM with Timer2 running with a prescaler of 1 (so it's counting at the full speed of 16 MHz), and a TOP of 15 and a compare match on 8. I've posted some sample code that shows how to do something like this in other threads.

  • Ben

Does the 1MhZ clock have to come from Arduino ?

If not then there are other rather easy solutions for making it, like a crystal or ceramic resonator or a 555 based oscillator.

Use a 1mhz crystal for the mos6581.

Is there a more standard way to provide a reliable clock-out at a specific frequency than interrupts.

Yes, use a stable clock source like a crystal or oscillator. Interrupts and timers from a micro-controller seems like the LAST thing you would want to use.

I tend to wonder if, in the future, say - 20 years from now - we'll find all kinds of Commodore 64 machines without any capability for sound...?

BTW, golgobot, do you know the SID has been emulated with the Arduino?:

http://www.arduino.cc/playground/Main/SID-emulator

:)

I think it could be a good idea not only to use the MOS6581 for a SID Emulator. Use the MOS6526CIA too ! It has two timers included.

C 64 Parts: http://www.htu.tugraz.at/~herwig/c64/bauteile.php

Commodore SID 6581 Datasheet: http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet

Don't think you can get there writing in arduino code anyway. This yields 87 KHz on a score, 11.5uS period.

byte toggle =0; // used to select output hi/lo
byte outputPin5 = 5; // could be any

void setup (){
pinMode (outputPin5, OUTPUT);
}
void loop(){
toggle = 1-toggle;  // results in 0 1 0 1 ...
digitalWrite (outputPin5, toggle);
}

Don't think you can get there with an output pin using arduino code. This yields ~87KHz, 11.5uS, measured on a scope.

byte toggle =0; // used to select output hi/lo byte outputPin5 = 5; // could be any

void setup (){ pinMode (outputPin5, OUTPUT); } void loop(){ toggle = 1-toggle; // results in 0 1 0 1 ... digitalWrite (outputPin5, toggle); }

This might be helpful: http://www.robotsimple.com/DS1077_Programmable_Oscillator_Breakout_16_2_kHz_to_133MHz

Gentlefolk, the original post is from [u]2008/u and the original poster never replied. By now he's either figured out a solution, given up, or passed away.

Well, it was fun seeing just how fast an output could be made to toggle anyway …

:)

In that case... http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230286016

For the record, the "best" way to output a clock signal is to configure timer 1 or timer 2 to toggle a pin.