I'm working on a Arduino-based synthesizer using this tutorial, specifically using a wavetable and 1-bit DAC. I understand that the value for OCR2A register sets the frequency, but how do I calculate the value?
I've seen this list of notes which is great, but I want arbitrary frequencies in Hz...
Here's the code I'm working from:
#include <avr/interrupt.h>
// sinewave parameters
#define FREQ 18
#define PI2 6.283185 // 2*PI saves calculation later
#define AMP 127 // scaling factor for sine wave
#define OFFSET 128 // offset shifts wave to all >0 values
#define LENGTH 256 // length of the wave lookup table
byte wave[LENGTH]; // wavetable
void setup() {
// populate wavetable
for (int i = 0; i < LENGTH; i++) {
float v = (AMP * sin((PI2 / LENGTH) * i));
wave[i] = int(v + OFFSET);
}
// set timer1 for 8-bit fast PWM output
pinMode(9, OUTPUT); // make timer’s PWM pin an output
TCCR1B = (1 << CS10); // set prescaler to full 16MHz
TCCR1A |= (1 << COM1A1); // pin low when TCNT1=OCR1A
TCCR1A |= (1 << WGM10); // use 8-bit fast PWM mode
TCCR1B |= (1 << WGM12);
// set up timer2 to call ISR
TCCR2A = 0; // no options in control register A
TCCR2B = (1 << CS21); // set prescaler to divide by 8
TIMSK2 = (1 << OCIE2A); // call ISR when TCNT2 = OCRA2
OCR2A = FREQ; // set frequency of generated wave
sei(); // enable interrupts to generate waveform!
}
void loop() {
// nothing to do here!
}
// called every time TCNT2 = OCR2A
ISR (TIMER2_COMPA_vect) { // called when TCNT2 == OCR2A
static byte index = 0; // points to each table entry
OCR1AL = wave[index++]; // update the PWM output
asm("NOP; NOP"); // fine tuning
TCNT2 = 6; // timing to compensate for ISR run time
}
asm("NOP; NOP");
andTCNT2 = 6;
are total nonsense and should be removed, as should thesei();
line from setup (it's unnecessary). Also, theLENGTH
#define is totally ignored in the ISR, so if it was ever set to something other than 256 the code would break. >_<TCNT2=6
and got a lot more high-freq partials. WithTCNT2=6
but noasm("NOP;NOP")
I get no audio, just buzzing. It seems to be fine withoutsei()
, but (obviously) my timer programming is really bad, and I don't entirely understand what they do.asm()
statement that according to the comments adds two nops only adds one, so...