1khz Sine Wave Generator

At www.projects.cappels.org Mr. Cappels has many AVR based projects. I was interested in his latest, a 1khz sine wave generator. I ported his C version to the AVR and was able to achieve a nice digital sine wave with 6 bit resolution and a 1.007khz frequency. I used a 6 bit R2R DAC off of PORTD to make it easier. I used his basic schematic isarapix.org for the DAC. His project is at 1_KHz_Sine_Wave_Generator
Timer2 interrupts are used to cycle through the sine table at the frequency of interest.

/*
Copyright 2007 Richard Cappels used with his permission
www.projects.cappels.org
This assumes an R/2R DAC (or other DAC) connected to PORTD, and
Arduino 16mhz clock
The frequency measured at the output of the DAC is 1.007 kHz.
ported to arduino by hotcarrier
output to pd7-pd2 with 6 bits- needs high order pd7 to work
correctly
*/

#include <avr/interrupt.h>
#include <stdlib.h>

char sinetable [32];
int i ;

void ioinit (void)
{
//Initialize output ports
PORTD = B11111111;
DDRD = B11111111;

}

void timer_setup(){
TCCR2A = 0;
TCNT2=455; //455 outputs 1.007khz
TCCR2B = B00000010;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
}
void setup(){

ioinit();
arraysetup();
cli();
timer_setup();
i = 0;
sei();

}

ISR(TIMER2_OVF_vect) {

PORTD=(sinetable[i++]);
TCNT2=455;
if(i==32){
i=0;
}

}
void arraysetup(void){
sinetable[0]=127; // Put 32 step 8 bit sine table into array.
sinetable[1]=152;
sinetable[2]=176;
sinetable[3]=198;
sinetable[4]=217;
sinetable[5]=233;
sinetable[6]=245;
sinetable[7]=252;
sinetable[8]=254;
sinetable[9]=252;
sinetable[10]=245;
sinetable[11]=233;
sinetable[12]=217;
sinetable[13]=198;
sinetable[14]=176;
sinetable[15]=152;
sinetable[16]=128;
sinetable[17]=103;
sinetable[18]=79;
sinetable[19]=57;
sinetable[20]=38;
sinetable[21]=22;
sinetable[22]=10;
sinetable[23]=3;
sinetable[24]=0;
sinetable[25]=3;
sinetable[26]=10;
sinetable[27]=22;
sinetable[28]=38;
sinetable[29]=57;
sinetable[30]=79;
sinetable[31]=103;
}
void loop()
{

while (1)
{

}

}

Thanks, just what I needed!

How did you know the value 455 would output 1khz? Is it possible to output lower frequencies?

How did you know the value 455 would output 1khz? Is it possible to output lower frequencies?

Often, the fastest way is to try it yourself and see. It won't harm anything to edit that number. That number appears to be computed from the 32 samples for the sine table, and the desired sine wave duration (1/1000 second), measured in timer tick units.

I replaced it with a variable Val, and I tried decrementing it infinitely(Val--) in the void loop() function. The pitch changed, but their isnt much of a range at all. It was also strange because even though I was decrementing the value, the pitch only changed if I did a Serial.println(Val) in void loop().

Interrupts are tricky business, I'm beginning reading about them but so far I am totally confused.

You'd need to do the whole cli()-timer_setup()-sti() sequence again if you want to change the interrupt rate on the fly. Yes, the available frequencies are probably fairly granular, if the closest to 1KHz you can get is 1007Hz.

Richard Cappels explains how this work pretty well on the web site referenced at the beginning of my original post.

There is a great example, that I found more clear, at Arduino sketch for high frequency precision sine wave tone sound synthesis | Adrian Freed