Skip to content
shirriff edited this page May 6, 2011 · 1 revision

Details of the receiving library

The IRrecv library consists of two parts. An interrupt routine is called every 50 microseconds, measures the length of the marks and spaces, and saves the durations in a buffer. The user calls a decoding routine to decode the buffered measurements into the code value that was sent (typically 11 to 32 bits).
The decode library tries decoding different protocols in succession, stopping if one succeeds. It returns a structure that contains the raw data, the decoded data, the number of bits in the decoded data, and the protocol used to decode the data.

For decoding, the MATCH macro determine if the measured mark or space time is approximately equal to the expected time.

The RC5/6 decoding is a bit different from the others because RC5/6 encode bits with mark + space or space + mark, rather than by durations of marks and spaces. The getRClevel helper method splits up the durations and gets the mark/space level of a single time interval.

For repeated transmissions (button held down), the decoding code will return the same decoded value over and over. The exception is NEC, which sends a special repeat code instead of repeating the transmission of the value. In this case, the decode routine returns a special REPEAT value.

In more detail, the receiver’s interrupt code is called every time the TIMER1 overflows, which is set to happen after 50 microseconds. At each interrupt, the input status is checked and the timer counter is incremented. The interrupt routine times the durations of marks (receiving a modulated signal) and spaces (no signal received), and records the durations in a buffer. The first duration is the length of the gap before the transmission starts. This is followed by alternating mark and space measurements. All measurements are in “ticks” of 50 microseconds.

The interrupt routine is implemented as a state machine. It starts in STATE_IDLE, which waits for the gap to end. When a mark is received, it moves to STATE_MARK which times the duration of the mark. It then alternates between STATE_MARK and STATE_SPACE to time marks and spaces. When a space of sufficiently long duration is received, the state moves to STATE_STOP, indicating a full transmission is received. The interrupt routine continues to time the gap, but blocks in this state.

The STATE_STOP is used a a flag to indicate to the decode routine that a full transmission is available. When processing is done, the resume() method sets the state to STATE_IDLE so the interrupt routine can start recording the next transmission. There are a few things to note here. Gap timing continues during STATE_STOP and STATE_IDLE so an accurate measurement of the time between transmissions can be obtained. If resume() is not called before the next transmission starts, the partial transmission will be discarded. The motivation behind the stop/resume is to ensure the receive buffer is not overwritten while it is still being processed; debugging becomes very difficult if the buffer is constantly changing.

Details of the sending library

The transmission code is straightforward. To ensure accurate output frequencies and duty cycles, I use the PWM timer, rather than delay loops to modulate the output LED at the appropriate frequency. (See my Arduino PWM Secrets article for more details on the PWM timers.) At the low level, enableIROut sets up the timer for PWM output on pin 3 at the proper frequency. The mark() method sends a mark by enabling PWM output and delaying the specified time. The space() method sends a space by disabling PWM output and delaying the specified time.

Clone this wiki locally