For small carrier periods (approaching something like 20 microseconds) you can't reliably use that interrupt-driven output to be able to generate and modulate your carrier. The program spends too much time in the interrupt routine (with interrupts disabled) so the other timing is screwed up. I mean, you could use direct manipulation of the output port bit to save a little time, but it's still not practical (in my opinion).
So: Since you are using Arduino Pin 9 for your output, consider the following: Pin 9 can be connected directly to the the OCR1A output pin, so use Timer1, not Timer2.
Maybe something like the following:
#include <avr/io.h>
// Since you are using Arduino pin 9 as an output pin, why not use Timer1 since OC1A
// is connected to pin 9 and the timer circuit can manipulate it directly (no
// interupt routine required)
//
// davekw7x
void setup()
{
unsigned long hz = 39200L; // Carrier frequency
pinMode(9, OUTPUT); // The OC1A pin will have LED output signal
cli(); // I like to disable interrupts while setting up timer stuff
//WGM13:0 = 1010 for Phase-correct PWM with ICR1 as top
//CS12:0 = 001 for no prescaling
TCCR1A = _BV(WGM11);
TCCR1B = _BV(WGM13) | _BV(CS10);
//
// IRC1 determines the frequency, OCR1A determines the duty cycle of the carrier
//
ICR1 = F_CPU / 2 / hz - 1;
OCR1A = ICR1 / 3; // 33% duty cycle. If you want a 50% duty cycle, change it to ICR1 / 2
TIMSK2 = 0; // Disable Timer2 Interrupt (We won't be using it to transmit.)
sei();
}
byte msg[16] = {0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0};
void loop()
{
for(int i = 0; i < 16; i++)
{
if(msg[i]) {
sendMark();
}
else {
sendSpace();
}
}
delay(1000); // Give it enough delay so that you can see the stuff on a scope.
}
void sendMark()
{
TCCR1A |= _BV(COM1A1); // Enable pin 9 PWM output
delayMicroseconds(3332);
TCCR1A &= ~(_BV(COM1A1)); // Disable pin 9 PWM output
delayMicroseconds(833);
}
void sendSpace()
{
TCCR1A |= _BV(COM1A1); // Enable pin 9 PWM output
delayMicroseconds(833);
TCCR1A &= ~(_BV(COM1A1)); // Disable pin 9 PWM output
delayMicroseconds(833);
}
Note that you don't have to start and stop the timer; you just control whether pin 9 is connected to OCR1A or not. You can also see that the carrier is (automatically) turned off between messages. Note that, in the "Real World", you will probably need a certain amount of carrier presence before you send the first message (due to the way that most IR Remote receivers work---check the data sheet of your device). Anyhow, maybe this is a start???
If you just want to observe (measure) the carrier with no modulation, then you can use the following loop:
void loop()
{
TCCR1A |= _BV(COM1A1);
while (1)
;
}
Or some such thing.
Regards,
Dave