Setting up Timer1 causes nothing but pain (Micro).

Hello. I'm new to the whole Arduno scene.

A while back I bought an Arduino Micro from ADA Fruit.

I've had a lot of fun but I've moved on to working with timers and that's where I run into problems.

I'm trying to build an audio circuit (that will, hopefully, one day go into an Apple IIe).

I am following the tutorial here:

Seems like every tutorial I find assumes I have a different Arduino than the Micro and reference timers or settings that are different. Anyway...

The tutorial above has the follow section of code:

/****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 = 32; // Set frequency of generated wave
 sei(); // Enable interrupts to generate waveform!

Well, I'm pretty sure that the Micro (or, more accurately, the ATmega32u4) doesn't have Timer2. But I believe it does have Timer0 and Timer1.

I also assume that Timer0 is 8bit and Timer1 is 16bit.

So, I changed the above code to:

	/******** Set timer1 for 8-bit fast PWM 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 timer0 to call ISR ********/
 	TCCR0A = 0;				// No options in control register A
 	TCCR0B = (1 << CS01);	// Set prescaler to divide by 8
 	TIMSK0 = (1 << OCIE0A); // Call ISR when TCNT0 = OCRA0
 	OCR0A = 32;				// Set frequency of generated wave
 	sei();					// Enable interrupts to generate waveform!

When I try to upload it, everything breaks. Including the IDE can no longer find the USB port!

I found the following line is the line that breaks everything:

 	TIMSK0 = (1 << OCIE0A); // Call ISR when TCNT0 = OCRA0

When I comment it out, all is fine and I can upload. BUT, the timer does not work. At least not that I can tell.

Here is the code that I have for the ISR:

/******** Called every time TCNT1 = OCR1A ********/
ISR(TIMER1_COMPA_vect) {		// Called when TCNT1 == OCR1A
	static byte index=0;		// Points to each table entry
	OCR1AL = wave[index++];		// Update the PWM output
	// asm(“NOP;NOP”); // Fine tuning
	TCNT1 = 6;					// Timing to compensate for ISR run time
}

I had to comment out the "asm" line because I got an error about "NOP;" not being defined.

But, from what I can tell, that code isn't being called anyway.

So, my questions are:

  1. Where can I go to learn about these timers for the Arduino and MICRO (NOTE, MICRO and/or ATmega32u4) ? Preferably something that doesn't assume I'm already a 40 year veteran in electrical engineering. lol

  2. Can anyone find what is wrong with the code shown below?

BTW, I have pin 9 attached to a piezo speaker. I have confirmed that I can play tones through the circuit when I don't use interrupts but use straight "tone" instead.

Thanks!

// Tone.ino

#include <avr/interrupt.h> // Use timer interrupt library
#include <notes.h>

/******** Sine wave parameters ********/
#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


/******** Lookup table ********/
#define LENGTH 256		// Length of the wave lookup table
byte wave[LENGTH];		// Storage for waveform

const int TxPin = 8;
const int pwmPin = 9;

int melody[] = {
  NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4
};


int noteDurations[] = {
  4, 8, 8, 4,4,4,4,4 
};


void setupTimers() {

	/******** Set timer1 for 8-bit fast PWM 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 timer0 to call ISR ********/
 	TCCR0A = 0;				// No options in control register A
 	TCCR0B = (1 << CS01);	// Set prescaler to divide by 8
 	TIMSK0 = (1 << OCIE0A); // Call ISR when TCNT0 = OCRA0
 	OCR0A = 32;				// Set frequency of generated wave
 	sei();					// Enable interrupts to generate waveform!
}



void setup() {

	Serial1.begin(9600);
	delay(50);

	clear();
	backlightOn();

	printStr("Ready...");

	pinMode(TxPin, OUTPUT);
	pinMode(pwmPin, OUTPUT);
	delay(50);

	/* Populate the waveform table with a sine wave */
	for (int i=0; i<LENGTH; i++) {				// Step across wave table
		float v = (AMP*sin((PI2/LENGTH)*i));	// Compute value
		wave[i] = int(v+OFFSET); 				// Store value as integer
 	}

	for (int thisNote = 0; thisNote < 8; thisNote++) {
		// to calculate the note duration, take one second 
		// divided by the note type.
		//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
		int noteDuration = 1000/noteDurations[thisNote];
		tone(8, melody[thisNote],noteDuration);

		// to distinguish the notes, set a minimum time between them.
		// the note's duration + 30% seems to work well:
		int pauseBetweenNotes = noteDuration * 1.30;
		delay(pauseBetweenNotes);
		// stop the tone playing:
		noTone(8);
	}

 	setupTimers();

 	clear();
 	printStr("Timers");
 	cr();
 	printStr("  initialized...");

}


/******** Called every time TCNT1 = OCR1A ********/
ISR(TIMER1_COMPA_vect) {		// Called when TCNT1 == OCR1A
	static byte index=0;		// Points to each table entry
	OCR1AL = wave[index++];		// Update the PWM output
	// asm(“NOP;NOP”); // Fine tuning
	TCNT1 = 6;					// Timing to compensate for ISR run time
}




void backlightOn() {
	Serial1.write(17);
	delay(50);
}

void backlightOff() {
	Serial1.write(18);
	delay(50);
}


void clear() {
	Serial1.write(12);
	delay(50);
}

void cr() {
	Serial1.write(13);
	delay(50);
}

void playTone(int duration, int scale, int note) {
	
	duration = constrain(duration, 208, 214);
	scale = constrain(scale, 215, 219);
	note = constrain(note, 220, 232);

    Serial1.write(scale);
    Serial1.write(note);
    Serial1.write(duration);
    delay(50);
}

void printStr(String str) {
	Serial1.print(str);
	delay(50);
}

void loop() {

}

TIMER0 is used for the timing of millis().
I don't know if the software serial-over-usb or the bootloader uses TIMER0.
As far as I know, any library that uses TIMER2 can not be used with the Leonardo/Micro.

If you want to do sound synthesis, use a ATmega328p based Arduino.