Bits de control IR de ingeniería inversa/CRC

Estoy tratando de construir un control remoto IR simple basado en Arduino para un helicóptero de juguete barato controlado por IR (igual que este , se llama "Diamond Gyro" o "Diamond Force"). He decodificado el protocolo IR a excepción de los últimos bits. Estos últimos bits parecen ser un cheque o CRC, pero no he podido "descifrarlo".

Es bastante fácil simplemente repetir un paquete grabado, pero quiero controlar completamente el helicóptero. Eso significa aplicar ingeniería inversa a los bits de control.

(Debo agregar que hago software de día, pero la electrónica es un pasatiempo a veces, así que tal vez me esté perdiendo algo muy básico).

Los detalles del protocolo están en la pregunta y respuesta , pero aquí están los conceptos básicos:

  • Paquete de 32 bits que abarca múltiples valores/comandos individuales de longitud variable (más 1 bit de inicio/preámbulo, que no cuenta como datos)
  • Los valores son little endian (MSB primero)
  • Estoy seguro de que tengo los primeros 22 bits asignados...
  • ... pero los siguientes 4 bits son un poco misteriosos, aunque conozco el propósito de al menos 2 de ellos.
  • Los últimos 6 bits parecen ser un cheque o CRC de algún tipo

aquí hay un diagrama

 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.

En primer lugar, no estoy seguro de si los Xbits son parte del valor del canal, parte del cheque o algo más. Sin embargo, siempre siguen el valor del canal, por lo que es probable que el valor del canal tenga entre 3 y 4 bits de ancho, aunque 2 bits serían suficientes para los 3 valores de canal posibles.

En segundo lugar, están los últimos 6 bits (marcados CRC?arriba) que son claramente algún tipo de verificación (y, de hecho, el helicóptero no responde si cambio alguno de esos bits).

Básicamente, hay un paquete de 24 a 26 bits de datos, seguido de 6 a 8 bits de verificación. Y realmente me gustaría descifrar esos bits de verificación para poder componer paquetes yo mismo.

A continuación hay un montón de muestras de los datos binarios que estoy recibiendo. El preámbulo "1" siempre está presente, y no creo que cuente como parte de los datos, pero lo he incluido de todos modos, por si acaso es la clave de todo.

Nuevamente, no sé si los Xbits son parte de los datos o del cheque. Dependiendo de la forma en que se calcule el cheque, es posible que los primeros 1 o 2 bits del cheque simplemente sigan el valor del canal. Pero también es muy posible que el valor del canal tenga una longitud de 4 bits, incorporando los Xbits. O está en el medio, Xsiendo un bit parte del canal y el otro parte del control. No sé.

Si alguien sabe qué es ese cheque, o cómo podría averiguarlo, me encantaría saberlo. Me imagino que puedo usar la fuerza bruta, pero incluso si esa es la única opción, me encantaría escuchar algunos consejos sobre cómo hacerlo mejor.

El helicóptero es muy barato, así que dudo que haya algo realmente elegante.

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

Respuestas (3)

En primer lugar, está bastante claro que los bits "XX" son parte de la designación del canal, ya que es de lo único que dependen. Los bits "XX" pueden ser simplemente una verificación de los bits "Ch".

Los bits de verificación son un XOR bit a bit simple de 24 de los 26 bits de datos: si toma los 6 bits de guiñada, los 6 LSB del acelerador, los 6 bits de paso y los siguientes 6 bits, y XOR estas cantidades juntas, obtiene los 6 bits de control. Parece que los 2 bits superiores del acelerador no afectan en absoluto a los bits de verificación.

El siguiente script de Perl verifica esto.

#!/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;
}
¡Perfecto! Y: ¡El helicóptero está de acuerdo! Supongo que debería haber visto el esquema XOR yo mismo, pero, al igual que con la decodificación del protocolo, creo que me engañé pensando que era más complicado de lo que realmente era. ¡Gracias! Esa fue la última pieza del rompecabezas, creo.
Solo para seguir los comentarios de @ Olin: los lenguajes de secuencias de comandos como Perl facilitan la manipulación de los datos y prueban hipótesis en la forma algorítmica que sugiere. Es por eso que incluí mi guión aquí, como una demostración. He estado usando Perl desde finales de la década de 1980, así que recurro a eso, pero todos los lenguajes de secuencias de comandos modernos son igualmente capaces para este tipo de cosas. Dio la casualidad de que lo primero que intenté fue correcto. Anteriormente había escaneado los datos a ojo y encontré algunas líneas que eran diferentes en solo unos pocos bits.
Personalmente, recurro a Ruby (nunca me ha gustado mucho Perl, pero no tengo problemas para entender su script). Utilicé Ruby para realizar la demodulación/detección de envolvente del software de la señal IR a partir de datos de tiempo sin procesar (ya que estaba leyendo directamente del IC del controlador, no de un receptor), resolviendo los detalles del protocolo e incluso generando algunos gráficos para mi pregunta anterior . También probé algunas cosas para descifrar los bits de verificación yo mismo, pero estaba trabajando con suposiciones incorrectas (es decir, CRC). Necesitaba nuevos ojos, los suyos, en este caso, sobre los datos en sí.

No veo un patrón inmediatamente obvio, así que atacaría esto más algorítmicamente. Aparentemente, tiene la capacidad de capturar una gran cantidad de paquetes y luego usar alguna forma automatizada para ingresarlos a una computadora. Capturaría un gran número mientras variaba lentamente los controles.

Después de tener una pila de paquetes en un archivo, escriba un código para descifrar el código. Piense en ello como un problema de criptografía. Una de las primeras cosas que haría es buscar pares de paquetes que solo varíen en un bit. Eso debería decirle de inmediato si tiene una suma de verificación simple o algo más complicado como un CRC. Si se trata de una suma de comprobación básica, entonces la suma de comprobación de dichos pares de paquetes solo debería variar si se le suma una potencia de 2. Si un montón de bits varían de manera impredecible, entonces probablemente tenga un CRC.

Si se trata de una suma básica, luego de obtener algunos cambios de un solo bit, debería poder averiguar cómo se agrega cada campo a la suma de verificación. Si parece un CRC, entonces probablemente haría una búsqueda exhaustiva a continuación. Es solo una suma de verificación de 6 bits, por lo que solo hay 64 polinomios posibles. Puede haber hasta 64 valores de inicio diferentes, pero normalmente se inicia un CRC con el conjunto de bits alto y los otros bits en 0. Los nuevos bits se pueden desplazar desde cualquier extremo. Probablemente, al menos si quien diseñó el CRC supiera lo que estaba haciendo, entonces si ejecuta todo el paquete a través del CRC, el resultado debería ser 0. El número de combinaciones es lo suficientemente pequeño como para que una búsqueda exhaustiva por máquina encuentre la respuesta instantáneamente en tiempo humano si realmente es un CRC habitual.

Agregado:

Acabo de ver la respuesta de Dave Tweed donde ha demostrado que esto es incluso más simple que una suma, solo XOR de los campos. Hay muchos ingenieros perezosos por ahí. Hubiera hecho esto con un CRC, que es realmente muy fácil de calcular.

Dejaré mi respuesta aquí como una descripción de cómo atacar algo como esto cuando no ves un patrón por inspección. Si hubiera utilizado este método, habría visto que los cambios de un solo bit en los datos habrían resultado en cambios de un solo bit en la suma de comprobación, lo que habría apuntado inmediatamente a un esquema XOR.

¡Gracias de nuevo! Antes de que Dave Tweed encontrara la respuesta más simple, este es el tipo de respuesta que esperaba. Estuve investigando verificaciones CRC de fuerza bruta, pero encontré algunas guías prácticas (en cambio, en su mayoría encontré complicaciones, como invertir la entrada/salida y, por supuesto, no estaba seguro de esos bits en ese momento) X. En cuanto a cambiar un solo bit y mirar el cheque, me hubiera gustado intentarlo, pero habría requerido algo de trabajo con este controlador barato. Habría tenido que modificarlo un poco para obtener ese tipo de resolución.
En cuanto a los ingenieros perezosos: por eso pensé que sería un CRC. Fácil de implementar, como dices. Oh bien

Acerca de los XX: como señala Dave, parecen ser parte de la información del canal, ya que siempre son los mismos para un canal determinado. No son realmente necesarios; como dijiste, puedes codificar 3 canales con solo 2 bits, pero los 4 bits dados permiten una distancia de Hamming de 2. Esto significa que los códigos para los canales siempre están separados por al menos 2 bits; cambiar un solo bit no da como resultado un código de canal válido. Junto con la suma de comprobación, esto aumenta la fiabilidad.