Problems with timing

I've run into a few problems with the AVR firmware. (The GitHub repository for which is located here.) Recording of IR signals works fine and the values I record correspond nicely to the theoretical reality ("theoretical reality"?). If you can't remember the protocols and timings, you can find a great explanation of the various protocols here.

But – when I send the signals they are too long (as recorded by my oscilloscope connected to the output pin of the MCU which controls the IR LEDs).
My first approach was:

_delay_us( high_duration );
_delay_us( low_duration );

First I tried simply subtracting a "trim" value from each recorded duration. Which almost worked. But the necessary trim value became so high that, for short durations, the total delay became less than zero microseconds (which, of course, was interpreted as a really high number instead). And even if I clamped the delay values so they couldn't be less than zero, the pulses were still too long.

So instead I now use the 16 bit TIMER1 (TIMER0 is used to generate the 38 kHz output to modulate the IR signal). I configure the timer for CTC mode with the same duration as when sampling IR signals. When learning signals I increase a counter (16 bit resolution) to record the pulse as a number of "sample intervals".
Now when sending, I simply use the raw recorded counter value and decrease a counter on every compare match of the timer. When reaching zero, I toggle the IR signal and reset the counter to the next value in the recorded sequence. When I reach a counter value of zero I stop the timer and the signal is complete.

And a whole 'nother thing is that I've been running the MCU on 3.3 V at 16 MHz. Which according to the datasheet (section 28.3 Speed Grades) is out of spec. Sure, it may well run fine but in this case where timing is crucial I had better throttle it down to 12 MHz which is inside the Safe Operating Area.

And lo and behold – everything works!

Leave a Reply