On the arduino uno (= ATmega328/P), how can I manually clear the timer 1 output compare signal?
The purpose of the code is to generate some output pulses after a precise interval from the input pulse. There are two output channels that need to be driven, potentially with different delays. The pulse length isn't critical, just needs to be at least 8µs long, but the timing for the rising edge needs to be accurate.
Currently my code looks like this:
#define MAINS_PERIOD 16667 // in microseconds
ISR(TIMER1_CAPT_vect) {
GTCCR = _BV(TSM);
TCNT1 = TCNT1 - ICR1 - MAINS_PERIOD + 1 + 300;
GTCCR = 0;
}
ISR(TIMER1_COMPA_vect) {
delayMicroseconds(8);
OC1A = 0; // <---------- what do I do here?
}
ISR(TIMER1_COMPB_vect) {
delayMicroseconds(8);
OC1B = 0; // <---------- what do I do here?
}
void setup() {
TCCR1A = _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); // set output on compare match, normal mode, prescaler /8
TCCR1B = _BV(CS11) | _BV(ICNC1) | _BV(ICES1); // input capture noise cancel, positive edge
TIMSK1 = _BV(ICIE1) | _BV(OCIEA1), | _BV(OCIEB1); // generate interrupts for input capture, A/B compare match
pinMode(8, INPUT); //set data direction
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
}
I could potentially reconfigure the timer's output mode to clear on match and then force a match, but it seems like there ought to be a more straightforward way to do it:
ISR(TIMER1_COMPA_vect) {
delayMicroseconds(8);
TCCR1A &=~ _BV(COM1A0);
TCCR1C = _BV(FOC1A);
TCCR1A |= _BV(COM1A0);
}
Just clearing the output pin register bit (PORTB &=~ _BV(PORTB1);
) won't work in this case because the port register is ignored whenever an alternate function (like the timer output) is enabled on the pin.
Alternately, if there is a way to get the timer outputs to clear on overflow (some kind of undocumented 16-bit PWM mode?) that would be even better, but I doubt there is a way to do that.