TIMER0, TIMER1 and TIMER2 Compare interrupts issue

Dear All;

I would like to produce different analog Waveforms (Sinewave, Triangle, Squarewave ...) with different frequencies through a Arduino Duemilanove. I would like to have the waveforms on three different ports.

I have found a simple code in a webpage which seems to be a good start point. I have edited and debugged this code and used it for my application.

This method is based on "DIRECT DIGITAL SYNTHESIZER (DDS)" method. In order to have proper output we need to have a R2R resistor ladder connected to Arduino. infact this R2R resistor ladder converts digital outputs to analog signals.please take a look at: http://didier.longueville.free.fr/arduinoos/?p=64 and http://didier.longueville.free.fr/arduinoos/?p=111

In order to have three different waveforms on three ports I need to use "Compare interrupts" of TIMER0, TIMER1 and TIMER2.

To test the performance of this method, I first wrote a simple code, I have included my code below for your review. Now, Here is the problem:

I can successfully generate signals with desired frequencies on the ports which are being updated by TIMER1 and TIMER2 Interrupts, but the frequnecy of the signal which is being generated by TIMER0 interrupt is 1/3 (One third) of the two other signals (generated by the TIMER1 and TIMER2 interrupts). For example when I have 250Hz signal on PortB and PortD, There is a 80Hz signal on PortC!!!

The strange thing here is when I remove TIMER1 Interrupt from this code, the signal frequency on PortC which is being updated by TIMER0 becomes 250Hz!!!!

Can anyone please tell me what is the probelm?


int vWaveData[256];
long int i;
unsigned long int tuningWordM;
int upperCountingValue, desiredfreq;
double refFrequency;
long int phaseAccumulator0,phaseAccumulator1,phaseAccumulator2;
void generateWaveData(); // Generate wave data in global vector

void setup()
{
cli(); // Disable interrupts while setting registers
TCCR2A = 0; // Reset control registers
TCCR2B = 0; // Reset control registers
TCCR2A |= (1 << WGM21); // Clear Timer2 on Compare Match (CTC) Mode
TCCR2B |= (1 << CS20); // Prescaler x1 for Timer2
OCR2A = 255; // Set compared value
ASSR &= ~(1 << AS2); // Use system clock for Timer/Counter2
TIMSK2 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK2 |= (1 << OCIE2A); // Enable Output Compare Match A Interrupt

TCCR1A = 0; // Reset control registers
TCCR1B = 0; // Reset control registers
TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
TCCR1B |= (1 << CS10); // Prescaler x1
OCR1A = 255; // Set compared value
TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK1 |= (1 << OCIE1A); // Enable Output Compare Match A Interrupt */

TCCR0A = 0; // Reset control registers
TCCR0B = 0; // Reset control registers
TCCR0A |= (1 << WGM01); // Clear Timer on Compare Match (CTC) Mode
TCCR0B |= (1 << CS00); // Prescaler x1
OCR0A = 199; // Set compared value
TIMSK0 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK0 |= (1 << OCIE0A); // Enable Output Compare Match A Interrupt

generateWaveData(); // Create Sinewave look-up table
upperCountingValue = 255;
desiredfreq=250;
refFrequency = 16000000/(upperCountingValue+1);
tuningWordM = ((pow(2, 32) * desiredfreq) / refFrequency);

DDRB = B11111111; //Set PORTB as output
DDRC = B11111111; //Set PORTC as output
DDRD = B11111111; //Set PORTD as output

sei(); // Enable interrupts once registers have been update
}

void loop()
{
}

void generateWaveData() //Generate a Sawtooth Wave
{
for (int i=0; i < 256; i++)
vWaveData = (i*63)/256;
*} *
ISR(TIMER2_COMPA_vect) // Interrupt service run when Timer/Counter2 reaches OCR2A
*{ *

phaseAccumulator2 += tuningWordM;
byte phaseAccumulatorMSB2 = (phaseAccumulator2 >> 24);
PORTB = vWaveData[phaseAccumulatorMSB2];
}
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
*{ *
phaseAccumulator1 += tuningWordM;
byte phaseAccumulatorMSB1 = (phaseAccumulator1 >> 24);
PORTD = vWaveData[phaseAccumulatorMSB1];
}
ISR(TIMER0_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
phaseAccumulator0 += tuningWordM;
byte phaseAccumulatorMSB0 = (phaseAccumulator0 >> 24);
PORTC = vWaveData[phaseAccumulatorMSB0];
}
-------------------------------------------------------------
Steps per cycle is 256 (table length) and max dac counts are 2^6 - 1 = 63, where 6 is the number of bits of the R2R ladder DAC.
Thanx in advanced

Correction: OCRA0=255;

Problem still exist.
Any Help appreciated!

Sorry for annoying posts, It seems I did not post my compelete code, here is the complete code, please ignore the last ones:


int vWaveData[256];
long int i;
unsigned long int tuningWordM;
int upperCountingValue, desiredfreq;
double refFrequency;
long int phaseAccumulator0,phaseAccumulator1,phaseAccumulator2;
void generateWaveData(); // Generate wave data in global vector

void setup()
{
cli(); // Disable interrupts while setting registers
TCCR2A = 0; // Reset control registers
TCCR2B = 0; // Reset control registers
TCCR2A |= (1 << WGM21); // Clear Timer2 on Compare Match (CTC) Mode
TCCR2B |= (1 << CS20); // Prescaler x1 for Timer2
OCR2A = 255; // Set compared value
ASSR &= ~(1 << AS2); // Use system clock for Timer/Counter2
TIMSK2 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK2 |= (1 << OCIE2A); // Enable Output Compare Match A Interrupt

TCCR1A = 0; // Reset control registers
TCCR1B = 0; // Reset control registers
TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
TCCR1B |= (1 << CS10); // Prescaler x1
OCR1A = 255; // Set compared value
TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK1 |= (1 << OCIE1A); // Enable Output Compare Match A Interrupt

TCCR0A = 0; // Reset control registers
TCCR0B = 0; // Reset control registers
TCCR0A |= (1 << WGM01); // Clear Timer on Compare Match (CTC) Mode
TCCR0B |= (1 << CS00); // Prescaler x1
OCR0A = 255; // Set compared value
TIMSK0 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK0 |= (1 << OCIE0A); // Enable Output Compare Match A Interrupt

generateWaveData(); // Create Sinewave look-up table
upperCountingValue = 255;
desiredfreq=250;
refFrequency = 16000000/(upperCountingValue+1);
tuningWordM = ((pow(2, 32) * desiredfreq) / refFrequency);

DDRB = B11111111; //Set PORTB as output
DDRC = B11111111; //Set PORTC as output
DDRD = B11111111; //Set PORTD as output

sei(); // Enable interrupts once registers have been update
}

void loop()
{
}

void generateWaveData() //Generate a Sawtooth Wave
{
for (int i=0; i > 24);
PORTB = vWaveData[phaseAccumulatorMSB2];
}

ISR(TIMER2_COMPA_vect) // Interrupt service run when Timer/Counter2 reaches OCR2A
{
phaseAccumulator2 += tuningWordM;
byte phaseAccumulatorMSB2 = (phaseAccumulator2 >> 24);
PORTB = vWaveData[phaseAccumulatorMSB2];
}

ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{

phaseAccumulator1 += tuningWordM;
byte phaseAccumulatorMSB1 = (phaseAccumulator1 >> 24);
PORTD = vWaveData[phaseAccumulatorMSB1];

}

ISR(TIMER0_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
phaseAccumulator0 += tuningWordM;
byte phaseAccumulatorMSB0 = (phaseAccumulator0 >> 24);
PORTC = vWaveData[phaseAccumulatorMSB0];
}


void generateWaveData() //Generate a Sawtooth Wave
{
for (int i=0; i > 24[glow]);[/glow]
PORTB = vWaveData[phaseAccumulatorMSB2];
}

This doesn't look right. There is code that tries to read vWaveData, but no code that writes to the array?

There is a generateWaveData() function in the code. It is exactly after LOOP function!

You also try to have 3 interrupts firing about 62000 times per second each. That gives you about 85 clock cycles for each interrupt. I doubt the interrupt code is that fast.
Since all three interrupts run at the same frequency, why not use only one interrupt? (unless you plan to make OCR1A != OCR2A etc)

There is a generateWaveData() function in the code. It is exactly after LOOP function!

Yes, but the function doesn't seem to do what its name implies. Maybe a cut & paste error? Please use the code-tage also.

It seems I made a mistake again, you were right!, Sorry dude!

IGNORE LAST CODES!!!

Here is the code!, I still have the problem!


int vWaveData[256];
long int i;
unsigned long int tuningWordM;
int upperCountingValue, desiredfreq;
double refFrequency;
long int phaseAccumulator0,phaseAccumulator1,phaseAccumulator2;
void generateWaveData(); // Generate wave data in global vector

void setup()
{
cli(); // Disable interrupts while setting registers
TCCR2A = 0; // Reset control registers
TCCR2B = 0; // Reset control registers
TCCR2A |= (1 << WGM21); // Clear Timer2 on Compare Match (CTC) Mode
TCCR2B |= (1 << CS20); // Prescaler x1 for Timer2
OCR2A = 255; // Set compared value
ASSR &= ~(1 << AS2); // Use system clock for Timer/Counter2
TIMSK2 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK2 |= (1 << OCIE2A); // Enable Output Compare Match A Interrupt

TCCR1A = 0; // Reset control registers
TCCR1B = 0; // Reset control registers
TCCR1B |= (1 << WGM12); // Clear Timer on Compare Match (CTC) Mode
TCCR1B |= (1 << CS10); // Prescaler x1
OCR1A = 255; // Set compared value
TIMSK1 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK1 |= (1 << OCIE1A); // Enable Output Compare Match A Interrupt

TCCR0A = 0; // Reset control registers
TCCR0B = 0; // Reset control registers
TCCR0A |= (1 << WGM01); // Clear Timer on Compare Match (CTC) Mode
TCCR0B |= (1 << CS00); // Prescaler x1
OCR0A = 255; // Set compared value
TIMSK0 = 0; // Reset Timer/Counter2 Interrupt Mask Register
TIMSK0 |= (1 << OCIE0A); // Enable Output Compare Match A Interrupt

generateWaveData(); // Create Sinewave look-up table
upperCountingValue = 255;
desiredfreq=250;
refFrequency = 16000000/(upperCountingValue+1);
tuningWordM = ((pow(2, 32) * desiredfreq) / refFrequency);

DDRB = B11111111; //Set PORTB as output
DDRC = B11111111; //Set PORTC as output
DDRD = B11111111; //Set PORTD as output

sei(); // Enable interrupts once registers have been update
}

void loop()
{
}

void generateWaveData() //Generate a Sawtooth Wave
{
for (int i=0; i < 256; i++)
vWaveData = (i*63)/256;
}
ISR(TIMER2_COMPA_vect) // Interrupt service run when Timer/Counter2 reaches OCR2A
*{ *
phaseAccumulator2 += tuningWordM;
byte phaseAccumulatorMSB2 = (phaseAccumulator2 >> 24);
PORTB = vWaveData[phaseAccumulatorMSB2];
}
ISR(TIMER1_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
phaseAccumulator1 += tuningWordM;
byte phaseAccumulatorMSB1 = (phaseAccumulator1 >> 24);
PORTD = vWaveData[phaseAccumulatorMSB1];
}
ISR(TIMER0_COMPA_vect) // Interrupt service run when Timer/Counter1 reaches OCR1A
{
phaseAccumulator0 += tuningWordM;
byte phaseAccumulatorMSB0 = (phaseAccumulator0 >> 24);
PORTC = vWaveData[phaseAccumulatorMSB0];
}

... and what's the point of storing wave data as 16 bit ints when your are outputting the values to 8-bit ports?

If you go to this Webpage: http://didier.longueville.free.fr/arduinoos/?p=64
There is a link at the top which contains a PDF file in which the principle of operation is fully and nicely expained.

even if I change vWavwdata to byte, problem still exist!

Try this:
Have only one interrupt, but put the code from all three current interrupts into it, and make sure to have a separate tuningWordM for each voice.