Dear all,
I've been studying the Make Project "Advances Arduino Sound Synthesis" and tried to expand it so that I can get two independent sine tone signals on the pwm pins 9 and 10.
I have the problem that I can't tune the outputs independently and I don't understand why. I'm using two interrupt service routines on timers 0 and 2 to set the values of the OCR1AL (for pin 9 ) and OCR1BL (for pin 10. I'm only outputting 8 bit values, hence OCR1AH and OCR1BH are ignored).
When I tune the two sine tones close to each other (e.g. by setting OCR0A = 50 and OCR2A = 60) they are producing the same frequency on both pins. If I tune them far apart from each other (e.g. by setting OCR0A = 50 and OCR2A = 100), they produce an octave. Any other intervallic ratios are impossible.
It seems as if the output of OCR1AL and OCR1BL influence each other, which doesn't really make sense to me.
Any help would be much appreciated! Underneath is the complete code.
Thanks!
Marko
/******** Load AVR timer interrupt macros ********/
#include <avr/interrupt.h>
/******** Sine wave parameters ********/
#define PI2 6.283185 // 2 * PI - saves calculating it later
#define AMP 127 // Multiplication factor for the sine wave
#define OFFSET 128 // Offset shifts wave to just positive values
/******** Lookup table ********/
#define LENGTH 256 // The length of the waveform lookup table
byte wave[LENGTH]; // Storage for the waveform
void setup() {
/******** Populate the waveform lookup table with a sine wave ********/
for (int i=0; i<LENGTH; i++) {
float v = (AMP*sin((PI2/LENGTH)*i)); // Calculate current entry
wave[i] = int(v+OFFSET); // Store value as integer
}
/******** Set timer1 for 8-bit fast PWM output ********/
DDRB = 6;// pinMode(9, OUTPUT) and pinMode(10, OUTPUT);
TCCR1B = (1 << CS10); // Set prescaler to full speed 16MHz (no prescaling)
TCCR1A = (1 << COM1A1); // PWM pin to go low when TCNT1= OCR1A
TCCR1A |= (1 << COM1B1); // PWM pin to go low when TCNT1= OCR1B
TCCR1A |= (1 << WGM10); // Put timer into 8-bit fast PWM mode
TCCR1B |= (1 << WGM12);
/******** Set up timer 2 to call ISR ********/
TCCR2A = 0; // We need no options in control register A
TCCR2B = (1 << CS20); // Set prescaller to divide by 8 // try TCCR2B = (1 << CS20) for finer range
TIMSK2 = (1 << OCIE2A); // Set timer to call ISR when TCNT2 = OCRA2
/******** Set up timer 0 to call ISR ********/
TCCR0A = 0; // We need no options in control register A
TCCR0B = (1 << CS20); // Set prescaller to divide by 8 // try TCCR2B = (1 << CS20) for finer range
TIMSK0 = (1 << OCIE0A); // Set timer to call ISR when TCNT0 = OCRA2
OCR2A = 60; // sets the frequency of the generated wave has to be > TCNT2
OCR0A = 30;
sei(); // Enable interrupts to generate waveform!
}
void loop() {
}
/******** Called every time TCNT2 = OCR2B ********/
ISR(TIMER0_COMPA_vect) { // Called each time TCNT2 == OCR2B
static byte index = 0; // Points to successive entries in the wavetable
OCR1BL = wave[index++]; // Update the PWM output
asm("NOP;NOP"); // Fine tuning
TCNT0 = 6; // Timing to compensate for time spent in ISR
}
/******** Called every time TCNT2 = OCR2A ********/
ISR(TIMER2_COMPA_vect) { // Called each time TCNT2 == OCR2A
static byte index = 0; // Points to successive entries in the wavetable
OCR1AL = wave[index++]; // Update the PWM output
asm("NOP;NOP"); // Fine tuning
TCNT2 = 6; // Timing to compensate for time spent in ISR
}