The purpose of this project is to demonstrate the use of an ATmega88, -168, or -328 as an SIRC IR remote control receiver. IR transmitters send a serial signal modulated onto a carrier that is around 40 kHz. The receiver module sees the 40 kHz signal and demodulates the serial signal from it. This prevents any random IR from interfering with the receiver. In this respect all IR remotes are the same. Beyond that, the frequency can vary from 30 to 56 kHz, and the serial signal can be pulse width modulated, pulse position modulated, or who knows what.
There is also an ATtiny2313 SIRC version...
The screen captures below show the Sony 12-bit and 20-bit SIRC protocol as output by the TFMS-5400, at the input to the ATmega328. I don't have a 15-bit sample because I couldn't find any remote that offered it.
I chose the Sony SIRC protocol because it looked fairly simple. I use the TFMS-5400 40kHz device, which matches the Sony SIRC specification. More importantly, I have a bag full of them that I picked up on eBay some time back. There are other parts and other families which may be more appropriate for other protocols. [TFMS-5xx0 datasheet] [TSOP-17xx datasheet] The output of the TFMS-5400 is a logic level serial signal that matches whatever format the transmitter sends, which in this case is pulse width modulated. The device is 5V only, so the signal is 0-5V, but I have run it at 3.6V with good results, as can be seen by the captures above.
A frame always starts with a 2.4 mS logic zero. At the end of the 2.4 mS pulse, the first bit starts. A bit is a logic one for 0.6 mS, followed by a logic zero for either 0.6 mS for a zero bit, or 1.2 mS for a one bit. The frame consists of the start bit, 7 command bits, and 5 address bits for a 12-bit frame. The 20-bit frame consists of the 12-bit frame followed by 8 "extra" bits.
I annotated the image above to show what you get from hitting the "0" key. The command is 9, and the address is 1. The data is sent LSB first. The largest command number possible is 127 and the largest address possible is 31. To decode the serial bit stream, we have to come up with a way of differentiating a one from a zero. The high part of the bits are all the same, so they don't help us identify the bit, but the low part is 0.6 mS for a zero and 1.2 mS, twice as large, for a one. That suggests timing the low part of the bit, and that's what we'll do. With timer 2 set to use the prescaler with the divide by 256 tap we get 16 uS per count. The three times we are interested in are 2400 uS (a count of 150), 1200 uS (a count of 75) and 600 uS (a count of 38). To simplify the interrupt routine a little, we assume that the bit is a zero. The timer is started at the falling edge of the signal, and the count is read at the rising edge. If the count is around 150, we know it is a start bit. If the count is around 75, we know it is a one bit.
To assemble the command and address fields, we rotate the bit value into the MSB of the command field, until we have counted the correct number of bits (7), then we switch to rotating bits into the address field until we hit the correct total number of bits (12). Anything else that comes is rotated into the "extra" field, which should be 8 bits, but we don't really care, because we don't use them. In a 15-bit frame, three bits will come in after the 12-bit frame and will fall in the extra field. At the end, if there have been 15 bits received, the extra bits are added as the most significant bits in the address field. That should satisfy the 15-bit protocol, but I haven't been able to test it. Counting the bits is only to determine which field they belong to - it is not used to determine when we are done. Timer 2, if we do not see another low transition, will timeout after 4.08 mS. This is the signal that the frame has ended.