Friday 28 April 2017

infrared - Reverse-engineering IR check bits/CRC


I'm trying to build a simple Arduino-based IR remote control for a cheap toy IR-controlled helicopter (same as this one - it's called "Diamond Gyro" or "Diamond Force"). I've decoded the IR protocol except for the last few bits. These last bits seem to be a check or CRC, but I haven't been able to "crack" it.


It's easy enough to simply repeat a recorded packet, but I want to fully control the helicopter. That means reverse-engineering the check bits.


(I should add that I do software by day, but electronics is a sometimes-hobby, so maybe I'm just missing something very basic.)


The details of the protocol are in the question and answer, but here are the basics:




  • 32 bit packet spanning multiple individual values/commands of varying length (plus 1 start bit/preamble, which doesn't count as data)

  • The values are little endian (MSB first)

  • I'm positive I've got the first 22 bits mapped...

  • ... but the following 4 bits are a little mysterious, although I know the purpose of at least 2 of them.

  • The last 6 bits do seem to be a check or CRC of some kind


Here's a diagram


 0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
--+---------------------------+-----------+---+---+-+-+-----------

P| Yaw | Throttle | Pitch | T | C |X|X| CRC?

P: Preamble (always 1), T: Trim, C: Channel,
X: Either part of the channel data or the checksum.

First of all, I'm not sure whether the X bits are part of the channel value, part of the check, or something else. They always follow the channel value though, so it's likely the channel value is 3-4 bits wide, although 2 bits would be sufficient for the 3 possible channel values.


Second, there are the last 6 bits (marked CRC? above) which are clearly some kind of check (and indeed, the helicopter doesn't respond if I change any of those bits).


So basically, there's a packet of 24-26 data bits, followed by 6-8 check bits. And I'd really like to figure those check bits out so I can compose packets myself.


Below are a bunch of samples of the binary data I'm getting. The preamble "1" is always present, and I don't believe it counts as part of the data, but I've included it anyway, just in case it's the key to everything.


Again, I don't know if the X bits are part of the data or the check. Depending on the way the check's calculated, it might be that the first 1-2 bits of the check just happen to follow the channel value. But it's also quite possible that the channel value is 4 bits long, incorporating the X bits. Or it's in between with one X bit being part of the channel, and the other being part of the check. I don't know.



If anyone knows what that check is, or how I could go about finding out, I'd love to know. I imagine I can brute-force it, but even if that's the only option, I'd love to hear some hints for how to best do that.


The helicopter is dirt cheap, so I doubt there's anything really fancy going on.


Channel A                                                       
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000100 10000100 000000 00 01 01 000101 Left Mid + throttle
1 000000 10000110 010001 00 01 01 010010 Left Max + throttle
1 100001 10000110 000000 00 01 01 100010 Right Mid + throttle
1 100100 10000100 010001 00 01 01 110100 Right Max + throttle
1 010001 00000000 001011 00 01 01 011111 Forward Min

1 010001 00000000 000000 00 01 01 010100 Forward Max
1 010001 00000000 011000 00 01 01 001100 Back Min
1 010001 00000000 100101 00 01 01 110001 Back Max
1 010001 00000000 010001 01 01 01 010101 Left Trim
1 010001 00000000 010001 10 01 01 100101 Right Trim
1 010001 00000011 010001 00 01 01 000110 Throttle 01 (min)
1 010001 00010110 010001 00 01 01 010011 Throttle 02
1 010001 00011111 010001 00 01 01 011010 Throttle 03
1 010001 00101111 010001 00 01 01 101010 Throttle 04
1 010001 00111110 010001 00 01 01 111011 Throttle 05

1 010001 01010101 010001 00 01 01 010000 Throttle 06
1 010001 01011111 010001 00 01 01 011010 Throttle 07
1 010001 01101100 010001 00 01 01 101001 Throttle 08
1 010001 01111010 010001 00 01 01 111111 Throttle 09
1 010001 10000101 010001 00 01 01 000000 Throttle 10 (max)

Channel B
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000000 10000110 010001 00 00 10 010101 Left Max + throttle

1 100100 10000110 010001 00 00 10 110001 Right Max + throttle
1 010001 00000000 001001 00 00 10 011010 Forward Min
1 010001 00000000 000000 00 00 10 010011 Forward Max
1 010001 00000000 010111 00 00 10 000100 Back Min
1 010001 00000000 100110 00 00 10 110101 Back Max
1 010001 00000000 010001 01 00 10 010010 Left Trim
1 010001 00000000 010001 10 00 10 100010 Right Trim
1 010001 00000001 010001 00 00 10 000011 Throttle Min
1 010001 00110100 010001 00 00 10 110110 Throttle Mid
1 010001 01100111 010001 00 00 10 100101 Throttle High

1 010001 10001111 010001 00 00 10 001101 Throttle Max

Channel C
P Yaw Throttle Pitch Tr Ch XX Check Description
--------------------------------------------------------------
1 000000 10000101 010001 00 10 00 011100 Left Max + throttle
1 100100 10000101 010001 00 10 00 111000 Right Max + throttle
1 010001 00000000 001010 00 10 00 010011 Forward Min
1 010001 00000000 000000 00 10 00 011001 Forward Max
1 010001 00000000 010111 00 10 00 001110 Back Min

1 010001 00000000 100110 00 10 00 111111 Back Max
1 010001 00000000 010001 01 10 00 011000 Left Trim
1 010001 00000000 010001 10 10 00 101000 Right Trim
1 010001 00000001 010001 00 10 00 001001 Throttle Min
1 010001 00110100 010001 00 10 00 111100 Throttle Mid
1 010001 01100110 010001 00 10 00 101110 Throttle High
1 010001 10000101 010001 00 10 00 001101 Throttle Max

Answer



First of all, it's pretty clear that the "XX" bits are part of the channel designation, since that's the only thing they depend on. The "XX" bits may simply be a check on the "Ch" bits.


The check bits are a simple bitwise XOR of 24 of the 26 data bits: If you take the 6 Yaw bits, the 6 LSBs of the Throttle, the 6 Pitch bits, and the next 6 bits, and XOR these quantities together, you get the 6 check bits. It appears that the upper 2 bits of the Throttle do not affect the check bits at all.



The following Perl script verifies this.


#!/usr/bin/perl

# crc.pl - verify decoding of check bits

# On the lines starting with '1', just keep the '0's and '1's in an array.
while (<>) {
my @letters = split '', $_;
next unless $letters[0] eq '1';
@letters = grep /[01]/, @letters;

@letters = @letters[1..32];
$a = string2bin (@letters[0..5]);
$b = string2bin (@letters[8..13]);
$c = string2bin (@letters[14..19]);
$d = string2bin (@letters[20..25]);
$e = string2bin (@letters[26..31]);
$f = $a ^ $b ^ $c ^ $d;
printf "%02X %02X %02X %02X %02X %02X %s\n", $a, $b, $c, $d, $e, $f,
$e == $f ? '-' : '###';
}


sub string2bin {
my $temp = 0;
for (@_) {
$temp = ($temp << 1) + ($_ eq '1' ? 1 : 0);
}
$temp;
}

No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...