Question

I have a small 3.5ch USeries helicopter controlled by an IR remote control, using an Arduino I have decoded its 32 bit protocol. Except for last 3 bits which appear to be some form of checksum. As I have successfully decoding the channels from the remote, in that they track their corresponding controls, I can see that slight changes in the controls yield specific changes in the 3 bits, that are very reproducible and deterministic. Whereas I have not yet found a common theme or formal to reproduce the supposed checksum. I have tried simple things like Parity or Added Checksum. I can see the effects of changing specific bits on the cksum but when I combine the changes they don't simply add to the 3 bit value.

struct Useries // bit structure recieved from 32 bit IR command
{
   unsigned cksum    : 3;    // 0..2
   unsigned Rbutton  : 1;    // 3
   unsigned Lbutton  : 1;    // 4
   unsigned Turbo    : 1;    // 5
   unsigned Channel  : 2;    // 6,7
   unsigned Trim     : 6;    // 8..13
   unsigned Yaw      : 5;    // 14..18
   unsigned Pitch    : 6;    // 19..24
   unsigned Throttle : 7;    // 25..31
};

So the question is "How can I determine the formula for the chksum?" or what ever it is, as to program a recreation of it.

As it appears deterministic one should be able to take the recorded output of cksum and the other 27 bits and derive a formula for it. Much like PLD logic. Whereas the stimuls being 2^27 bit or 128M possibilities, versus the output being only 2^3 or 8 I would suspect even a small sample of <1% or less would provide the formula.

Another way, Is to look at it as a crypto problem and the 3 bit cksum is a hash.

Either way. Any methods or guidance as to determine the solution is greatly appreciated.

Here is sample data


FYI - The USeries is not the Syma. The Syma's decode does not have a cksum. Once I get the USeries chksum determined I will open source them from a fork of Ken Shirriff.

Just FYI

Struct SymaR5// bit structure recieved from 32 bit IR command
{
   unsigned Trim     : 8;    // 0..7   0x7F
   unsigned Throttle : 7;    // 8..15  0x7F
   unsigned Channel  : 1;    // 16     0x01
   unsigned Pitch    : 8;    // 17..24 0x7F
   unsigned Yaw      : 8;    // 25..31 0x7F
};
Was it helpful?

Solution

A quick check on parity masks results in seven masks that always give parity zero on your data. (Two of your bits are always the same, so I made an assumption about regularity in the mask to eliminate some contenders.) The masks are:

0x2e5cb972
0x5cb972e5
0x72e5cb97
0x972e5cb9
0xb972e5cb
0xcb972e5c
0xe5cb972e

Any of these masks anded with any of your data values (all 32 bits) results in parity zero. Three can be considered special, since each of your identified parity bits occurs just once respectively in those three (the ones ending in 2, 9, and c). So those three masks without the last three bits can be used to get each of the parity bits.

The mask repeats these seven bits: 0010111. This C code uses shifts and exclusive-ors to apply the mask and parity calculation:

    p = x;
    while ((x >>= 7) != 0)
        p ^= x;
    p = (p ^ (p >> 1) ^ (p >> 2) ^ (p >> 4)) & 7;

where x and p are 32-bit unsigned types. x is the 32 bits received. If p is zero when done, then the received value is good.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top