Issue
138 January 2002
WHAT
GOOD IS IrD,Eh?
Part
1: Cordless Protocol
byJeff
Bachiochi
Start
Standards Make It Happen
IrPHY
The Range
UART To IrDA IR
Encoder/Decoder
Gimme More Sources
& PDF
IR Encoder/Decoder
You probably
know Microchip as a microprocessor manufacturer, so you
can easily guess the company’s approach for the MCP2120.
I considered using Microchip’s least expensive processor,
the PIC12C508. Microchip was the first company to recognize
the potential merit of a microprocessor with low pin count.
Although this device has an internal RC oscillator, which
requires no crystal for applications not requiring high
accuracy timing, I chose to use an external crystal to
achieve higher accuracy over temperature and voltage.
This limits the I/O available to four, the minimum necessary
for this project (see Figure 4).
| Figure
4—The smallest available 8-pin microprocessor
is used to encode and decode data between a UART and
IR transceiver. |
There are essentially
two signals that must be looked at for this application,
TX from the serial port and IRRX from the IR receiver.
Because the IrDA protocol is half-duplex, I won’t have
to do two things at once, however, the transmit path will
have priority over the receive path. The shortest loop,
which includes testing for both signals, is shown in Listing
1.
| Listing
1—This minimum timing loop of 5.425 µs will most
likely miss a minimum IRRX pulse of 1.41 µs. |
The numbers
in parenthesis show the instruction cycle count for the
loop as five cycles. Using a standard crystal frequency
of 3.6864 MHz (divides evenly into standard data rates),
you get an execution cycle time of 1.085 µs, or:

The five-cycle
loop will therefore take 5.425 µs to complete. The fastest
bit time of the TX serial output is 104 µs (1/9600). So,
you can see that pulse if you are in the loop watching.
The shortest
IRRX pulse is 1.41 µs (the minimum acceptable pulse duration).
There is a good chance you will miss an IRRX pulse while
in the loop. The loop would be fast enough if you increased
the crystal frequency 10 times, however, 36.864 MHz is
faster than the 4-MHz maximum of the PIC12C508, so that’s
out.
An interrupt
could solve this problem. Unfortunately, the PIC12C508
has no interrupts available. It does, however, have a
wake-on-pin-change function. Note though that by the time
the oscillator starts from sleep, you’ve missed a whole
bunch of IR pulses, so that won’t help either.
The saving grace
here is that an IR pulse won’t repeat for at least 104
µs, which gives you plenty of time to do something after
you’ve seen the IRRX pulse. About the only peripheral
the 12C508 has is an 8-bit timer. Although the timer doesn’t
have an overflow interrupt, it does have a clock input
for the timer. This means that an external (selectable
rising or falling) edge will increment the timer. You
can read the cleared timer to determine if an IR pulse
has been detected (timer can’t be zero). Now, if only
the IRRX pulse fits within the input specifications. Let’s
look at that. An external T0CKI input must be low for
two clocks + 20, or:

The minimum
received pulse is 1410 ns (1.41 µs), so you’re in like
Flynn.
The SEND_BIT
and RECEIVE_BIT routines are not fancy. I use in-line
cycle counting to assure things happen at the right times.
During the SEND_BIT routine, I wait 0.4375 of a bit time
before enabling the IRTX pulse for 0.1875 of a bit time.
At around 0.9375 of a bit time, I start watching TX for
another low. If I see TX low, I jump to the top of SEND_BIT
again without going back to the loop. If TX stays high,
I jump back to the loop routine to look for more action.
During the RECEIVE_BIT
routine, I clear the timer (to get ready for the next
IRRX pulse), wait 0.4375 of a bit time, and then clear
the RX output bit. I start testing the timer for zero
at around 0.9375 of a bit time (no pulse yet). If it has
incremented within 0.125 of a bit time, I jump back to
the top of the RECEIVE_BIT routine without setting the
RX output bit (for another continuous 0 bit time). If
the timer doesn’t increment during the sampling period,
I wait out the rest of the bit time, set the RX output
bit, and jump to the loop to look for more action.