Here's the theory of operation
------------------------------

Sending IR:

Arrange timer1 in always count up mode scaled to count in chunks of 4
microseconds (the units I use for pulse width measurement) with a compare
register set for duration of pulse and an interrupt on compare match.

Arrange timer2 in PWM output mode where I can enable the output
pin to send a MARK, and disable it to send a SPACE.

When starting a send operation, arrange for the compare register to
trigger interrupt in the near future, then do all the sending from
the interrupt routine.

The IR pulse sequence to send gets pushed on a circular buffer where
the interrupt routine can pop off the next pulse.

In timer1 interrupt routine, toggle timer2 PWM output and set new compare
register to old compare register + next pulse width. If I run out of
data, turn off timer1 and timer2 set IR output to LOW and we are done.

Receiving IR:

Arrange timer1 in input capture mode and clock speed at 4 microseconds
per tick. Initially set it to capture on SPACE->MARK edge (which may mean
trailing edge since I think the IR receiver module is active LOW)
and setup an interrupt on capture.

In interrupt routine, record the captured time of edge arrival, and toggle
the edge that triggers capture, switching to the MARK->SPACE edge. Once
we have recorded the first MARK start time, we can subtract the new time
from the previous time to get the pulse width in units of 4 microseconds.

Also after the initial capture interrupt, we can enable the output compare
register interrupt, and in each capture interrupt routine, set the output
compare register to something like captured time + 2*max_pulse_width_seen.
This will move compare register around just in front of the capture.
Probably want to enable the compare interrupt only when capturing a SPACE
time since a MARK will inevitably come to an end and trigger a capture
interrupt, but a SPACE might be the end of a sequence of unknown length.

If we get do get an output compare interrupt, then we know the last
SPACE has gone on long enough to really be the end of the IR sequence,
not an actual SPACE, then we can flag the end and reset all the
state back to waiting for IR pulse to start up again.

The captured MARK and SPACE pulses plus the status at the end of
the sequence dure to timeout gets pushed on a circular buffer
where the main loop can find it.

Command Enhancements
--------------------

The version 1 command set is very basic.

An obvious enhancement would be to provide commands for storing IR
codes in flash and/or eprom and sending stored codes without needing
to send across all the raw data (then I'd need commands for discovering
what codes are already stored).
