
I wanted to be able to read the IR signals from the 9-button SparkFun remote control ($ 4.95) from the SparkCore. Turns out, it was quite easy, a tiny bit of hardware and some software.
The first thing is the IR receiver. It's a SparkFun 8554 ($ 9.95), which contains a Vishay TSOP853 IR receiver. It outputs a nice digital stream of bits after demodulating the IR data stream. It connects to Vcc and ground, and works at 3.3V or 5V, but I used it at 3.3V that the SparkCore uses. The final pin is data, which I connected to D0. The TSOP853 has an internal pull-up, so you don't need an external one.
The hardware is capable of receiving other 38 kHz IR codes including RC5/RC6, RCMM, r-step and XMP, basically everything except Sony, which is 40 kHz. The software I wrote only decodes NEC, but of course you could modify it to decode whatever you wanted. Judging from a quick sampling of remotes on my desk, the TiVo and Apple remotes also use the NEC protocol. My Scientific Atlantic cable TV remote and TCL TV remote do not.
There is a good explanation of the NEC IR protocol here. Note that the output from the TSOP853 is inverted from the logic levels described on that page.
A normal transmission begins with a header, a logic low for 9000µs and then a high for 4500µs. After this there's a space, which is 562.5µs and then a logic bit. This is 562.5µs for logic 0 and 1687.5µs for logic 1. Note that these times are very approximate, and remote controls may vary quite a bit from the published specification.
Essentially, each bit consists of a space and then a high pulse of varying width depending on whether it's a 0 or 1. There are 32 bits in the code, sent MSB first, and then another space to mark the end of the transmission.
(If you don't see a waveform diagram above, upgrade your browser! IE9 or later, or pretty much any version of Chrome, Firefox, Safari or Opera should work fine.)
As I mentioned the MSB is first, so here's how the value 0xE5, a binary value of 11100101, is sent:
A real transmission would be 32 bits, not 8 bits, and would include the header above, but you get the idea. Also, there's actually only 16 bits of information in the 32 bits of data, because 16 bits of it are complement values for error checking. But typically the values are listed with all 32 bits (4 bytes), as they are below.
The only other thing of note is the repeat sequence, which is 9000µs of low following by 2250µs of high instead of the normal header. This is used when you hold down a button - the original key is sent then the repeat sequence is sent repeatedly while the button is being held down.
There are two reasonable ways to decode the IR signals. You can do edge-triggered interrupts or you can use a timer and poll at some multiple of 562.5µs and count the number of samples at a given logic level. I used the interrupt method, as it's easy to do on the SparkCore and is quite efficient. Here's the code for the SparkCore:
I think the code should be self-explanatory.
By the way, I think this should also work on the Arduino, except for the Spark.publish line. You'll have to do whatever you want to do with the IR code in place of that line.
In my case, the Spark.publish line sends the event into the cloud. It's received by an Apache Tomcat webapp running a Server-Side Events (SSE) client, which then parses the data field for the hex button code. For the 9-button SparkFun remote, the codes are:
public static final int REMOTE_POWER = 0x10EFD827;
public static final int REMOTE_A = 0x10EFF807;
public static final int REMOTE_B = 0x10EF7887;
public static final int REMOTE_C = 0x10EF58A7;
public static final int REMOTE_UP = 0x10EFA05F;
public static final int REMOTE_DOWN = 0x10EF00FF;
public static final int REMOTE_LEFT = 0x10EF10EF;
public static final int REMOTE_RIGHT = 0x10EF807F;
public static final int REMOTE_SELECT = 0x10EF20DF;
public static final int REMOTE_REPEAT = -1;
And that's it!