Skip to content

Making Music With the 1806 Timer Q Toggle

March 23, 2017

The 1804/5/6 have a built-in 8 bit timer/counter with a bunch of functions. In timer mode, it decrements automatically every 32 machine cycles. When it gets to 0 it resets to whatever you first set it to and counts down again. It can cause an interrupt at 0 OR, it can just toggle Q. This generates a constant square wave without any further program interference. The range, on my 4MHZ olduino is about 30HZ to 7.8KHZ. If you can set the chip up with a ROM or some other way of feeding it instructions it’s an easy way to make sure you have a genuine 1804/5/6. The 10 byte program below generates a 30HZ square wave on my 4MHZ 1806.

68 0D CID ; disable timer interrupts
F8 FF LDI 255; maximum value
68 06 LDC ;load the timer
68 09 ETQ ; enable the Q toggle
68 07 STM ; start the timer

For extra points, it occurred to me that you could use this to make music in the traditional square wave sense. I wrote a tone(frequency,duration) function that calculates the initial timer value needed and starts the timer toggling Q for the required duration. This is similar enough to the equivalent Arduino function that I was able to crib some code from github to play a simple tune. That’s what you see running in the video above. That page also has a worthwhile explanation for converting sheet music to frequency,duration pairs.

void tone(int freq, int dur){ //tone at a particular frequency for a period
	unsigned char t;
	if (0!=freq){//0 would mean quiet for the duration
		asm(" STPC ; stop the timer\n");
		if (freq>7800) t=1; calculate the number of 64us ticks
		else if (freq<30) t=255;
		else t=7800/freq;
		LDC(t);
		asm(" ETQ;  enable the Q toggle\n");
		asm(" STM; start the timer\n");
		delay(dur);
		asm(" STPC\n");
	}else{
		delay(dur);
	}
}
#define playSpeed 2
#define numNotes 29
int line1[] = {
  NOTE_D4, 0, NOTE_F4, NOTE_D4, 0, NOTE_D4, NOTE_G4, NOTE_D4, NOTE_C4,
  NOTE_D4, 0, NOTE_A4, NOTE_D4, 0, NOTE_D4, NOTE_AS4, NOTE_A4, NOTE_F4,
  NOTE_D4, NOTE_A4, NOTE_D5, NOTE_D4, NOTE_C4, 0, NOTE_C4, NOTE_A3, NOTE_E4, NOTE_D4,
  0};

int line1_durations[] = {
  8, 8, 6, 16, 16, 16, 8, 8, 8,
  8, 8, 6, 16, 16, 16, 8, 8, 8,
  8, 8, 8, 16, 16, 16, 16, 8, 8, 2,
  2};

void main(){
	unsigned int thisNote=0,noteDuration,pauseBetweenNotes;
	printf("Hello Axel Fans\n");
	asm(" CID; disable timer interrupts\n");
	for(thisNote=0;thisNote<numNotes;thisNote++){
		noteDuration = 1000/line1_durations[thisNote];
		tone(line1[thisNote], noteDuration * playSpeed);
	}
	printf("\ndone\n");

}

 

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: