[HELP] Reverse engineering AC IR

Hi, I have been trying to reverse engineer a Air Conditioner remote protocol, and it was rather easy except for the last byte that seems to be a checksum.

Here are all the readings I gathered: https://www.dropbox.com/s/4eytexnsst1d0jg/codes.log

And some notes I took about the protocol: https://www.dropbox.com/s/e4vjacjyviwmitz/notas.txt

The protocol has 17 bytes, the first 5 seem to be some sort of serial number, all of them are described on the notes document.

Any help is appreciated.

Have you tried …

http://www.checksumcalculator.com/

… to figure out what algoritm is used ?

Being something for an AC remote and considering the checksum is only 8bits I believe i can say MD5 and SHA1 are pretty much excluded and as far as I understand CRC32 has 32bits of checksum, so it would be out too.

I did try http://reveng.sourceforge.net/ but no success.

   unsigned char check;

   check=248;
   for(i=0;i<16;i++)
      check+=(data[i]>>4)+(data[i]&0x0f);

This works fine for the first 27 of 31 examples.

Either the last 4 were copied wrong or maybe there is an additional wrinkle.

Good eye, Renate!

It does look like the “checksum” is a simple sum (it is clearly not a CRC because if one bit in the message changes, many bits in a CRC change). However, the sum appears to be 5 bits long, in reverse order. The three rightmost bits never change so they can probably be ignored for the purpose of the calculation.

Renate:

   unsigned char check;

check=248;
for(i=0;i<16;i++)
check+=(data[i]>>4)+(data[i]&0x0f);



This works fine for the first 27 of 31 examples.

Either the last 4 were copied wrong or maybe there is an additional wrinkle.

Thanks for your help, however I am not being able to reproduce the checksum with your code.

For this input

unsigned char data[]={0b00000010, 0b00000000, 0b00101000, 0b00000001, 0b11000010, 0b01010010, 0b00011000, 0b00000010, 0b11000100, 0b00010011, 0b00010110, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00101010};

I get 01000100 none of the others is correct either.

Here is a small program I created, what am I doing wrong?

#include <stdio.h>


int main(){

    int i;
    unsigned char check;

    unsigned char data[]={0b00000010, 0b00000000, 0b00101000, 0b00000001, 0b11000010, 0b01010010, 0b00011000, 0b00000010, 0b11000100, 0b00010011, 0b00010110, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00101010};

    check=248;
    for(i=0;i<16;i++)
        check+=(data[i]>>4)+(data[i]&0x0f);

    printf("%d",check);
    return 0;
}

I agree that the above code does not reproduce the last data byte, either in the bit-reversed or forward direction.

We don’t know what Renate’s data statements look like or what “work” means, either. The “checksum” is incrementing in the bit reversed direction, as the temperature increases. So maybe all bits need to be reversed in each data byte for the simple sum approach to work.

Here is my brief stab at it, along with a handy little routine that prints a byte in binary format:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *byte_to_binary(char x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }
    return b;
}
int main()
{
     int i;
    unsigned char check;
    unsigned char data[]={0b00000010, 0b00000000, 0b00101000, 0b00000001, 0b11000010, 0b01010010, 0b00011000, 0b00000010, 0b11000100, 0b00010011, 0b00010110, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00101000};
//                          00000010    00000000    00101000    00000001    11000010    01010010    00011000    00000010    11000100    00010011    00010110    00000000    00000000    01000000    00000000    00000000    00101010
    check=248;
    for(i=0;i<16;i++)
        check+=(data[i]>>4)+(data[i]&0x0f);

    printf("%u\n",check);
    printf("check: %s\n", byte_to_binary(check));
    printf("data[16]: %s\n", byte_to_binary(data[16]));
    return 0;
}

I tried reversing all the bits in each data byte and that worked for the first case. I’ll leave it to you to check the others.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHAR_BIT 8

unsigned char ReverseBits(unsigned char v)
{
    unsigned char r = v;
    int s = sizeof(v) * CHAR_BIT - 1;
    for (v >>= 1; v; v >>= 1) {
        r <<= 1; r |= v & 1; s--;
    }
    return r << s;
}

char *byte_to_binary(char x)
{
    static char b[9];
    b[0] = '\0';
    int z;
    for (z = 128; z > 0; z >>= 1)
        strcat(b, ((x & z) == z) ? "1" : "0");
    return b;
}
int main()
{
     int i;
    unsigned char check;
    unsigned char data[]={0b00000010, 0b00000000, 0b00101000, 0b00000001, 0b11000010, 0b01010010, 0b00011000, 0b00000010, 0b11000100, 0b00010011, 0b00010110, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00101010};
//                          00000010    00000000    00101000    00000001    11000010    01010010    00011000    00000010    11000100    00010011    00010110    00000000    00000000    01000000    00000000    00000000    00101010
    check=248;
    for(i=0;i<16;i++) {
        data[i] = ReverseBits(data[i]);
        check += (data[i]>>4) + (data[i]&0x0f);
    }

    printf("sum (dec): %u\n",check);
    printf("check    : %s\n", byte_to_binary(check));
    printf("data[16] : %s\n", byte_to_binary(data[16]));
    data[16] = ReverseBits(data[16]);
    printf("dataR[16]: %s\n", byte_to_binary(data[16]));
        return 0;
}

Oh, I thought it was very clear that the bytes are LSB first.

Ok, got it working and outputing the correct checksums, those last 4 I re-captured them and yes there was a problem with them, working good now :slight_smile:

Thanks for your help.