I had my Lego train out(that uses Lego power functions) and wanted to try controlling it using my TV-B-On remote. I did a bit of googling and found the datasheet on the IR protocol. I whipped up something quick and dirty. It didn't work. What was it? Was it the fact that I didn't send the code 5 times as per the specification? Do I actually need to count out 6 IR pulses (the stop/start bit, high and low bits all start with 6 IR pulses, it's just the delay after that differentiates them?) Do I need the send the 16 bits LSB first?
I first grabbed my Arduino Uno and uploaded the IRdump sketch from IRremote library, but the output wasn't too useful in this instance. I then pulled out my inexpensive logic analyzer and opened Pulseview(Sigrock.) I then proceeded down the rabbit hole of getting my code to count out exactly 6 IR pulses. Still not working. I then tried sending the 16 bits LSB first. Nope. I also tried sending the code 5 times as per the specification and still nothing. While I was at it, I hooked up my signal analyzer through a 3 pin IR receiver and discovered that per an IR burst it just shows up as one burst (the 6 IR pulses just shows up as a single large pulse.) So it wasn't critical to count out 6 IR pulses.
I then decided to find an Arduino Lego PF library, make up a sketch of the code that I was trying to send on my TV-B-On on my Uno, hook that up to my logic analyzer and examine the output. I found a working library here. A ran everything and decoded the bits (the PWM decoder in Pulseview made it easy to tell the 0,1, and stop/start bits apart.) I shortly discovered the problem. The problem was with the 4th nibble, the LRC data. The datasheet states that the LRC is calculated by doing an xor operation on the first three numbers and the number 0xf. I assumed that doing an xor operation on 4 numbers would work just like two numbers, is there is a single one bit in a particular position, the result is one, overwise it's zero like shown below:
The bits that I decoded from the known working code however gave me 1011 instead. I looked up the rules for more than 2 numbers and found this from this website "To find each bit of XOR just calculate number of 1’s in the corresponding bits. If it is even or zero then that XOR’ed bit is 0. If it is odd then that XOR’ed bit is 1." I made the correction to my code and it worked. I did find out for the mode I was using at the time at least that I don't need to send the code 5 times with the specified delays per the datasheet.
Here's a screenshot from pulseview of the generated output and I've also included my code that's still very much a work in progress.
EDIT: I've also included the capture both at the pin and thru an IR receiver. I'm not sure how to easily decode the capture thru the IR receiver.
void send_message(unsigned int mess);
void send_combopwm(char nib2, char nib3, char nib1);
void send_singleoutput(char mode, char output, char nib3, char nib1);
volatile int count=0;
DDRB |= 0b00000011;
OCR0A = 212-1;
Read more »