Artículos

Protocolo RC6 y Media Remote Control XBox 360

La XBOX 360 puede ser controlada mediante el Media Remote Control para poder ver videos, imágenes o escuchar MP3's. Este control funciona todavía mediante luz infrarroja, a diferencia de los controles inalámbricos estándar de la Xbox.

 

 

Como todo control infrarrojo, éste emplea una portadora de una frecuencia dada sobre la cual monta la transmisión de bits que representan el botón o función que uno haya presionado. Si se abre la tapa de las baterías del control se puede observar que el control maneja el protocolo RC6.

 

 

 Las características básicas del protocolo RC6 pueden verse en la página SB-Projects - IR remote control - Philips RC-6:
http://www.sbprojects.com/knowledge/ir/rc6.htm

Mi objetivo era ver si el control realmente implementaba el protocolo y si era posible replicarlo, por lo que escribí una aplicación para el microcontrolador PIC18F452 para poder medir los tiempos de envío. El medidor está conformado por

  • TSOP1738. Un módulo que recibe luz infrarroja enviada a 38kHz (+/- 5%) y entrega una salida TTL en los siguientes casos: 0 si existe una señal infrarroja de 38kHz o 1 si no existe una señal de 38kHz.
  • 74LS04. Compuerta NOT que invierte la salida del TSOP. Si existe señal de 38kHz entrega un 1, si no existe entrega un 0.
  • PIC18F452. Se emplea el módulo de comparación y captura (CCP) para medir el tiempo en alto o bajo que el la compuerta NOT entrega.
  • MAX232. Convertidor TTL a RS232 para ver en la hyperterminal los tiempos medidos por el PIC.

El PIC se encarga de medir los tiempos en alto y bajo que el TSOP detecta y se dividen entre 444us para poder representarlos en unidades de tiempo 't', las cuales son los tiempos que duran las distintas formas de enviar bits en el protocolo.

El circuito es bastante simple.

 

 

 Se debe conectar la salida a ambas entradas del módulo CCP ya que CCP1 captura las bajadas de flanco y CCP2 las subidas de flanco. Entre ambos podrán medir la duración de un pulso alto o un pulso bajo, ya desmontados de la señal de 36kHz usando el TSOP1738.


Archivo HEX para pruebas
Contraseña migsantiago.com

(Descarga)

El programa del PIC fue compilado usando CCS y se muestra a continuación.

/*

Programa que mide el tiempo de transmisión de un control XBOX 360 que usa

el protocolo RC6.

 

Envía por RS232 los tiempos altos y bajos de la señal de 36kHz demodulada por

un TSOP1738 (a falta de uno de 36kHz).

 

Colocar a la salida del TSOP un 7404 para reinvertir la señal y obtenerla tal

cual el protocolo lo indica, es más fácil interpretarlo así. Posteriormente

se puede hacer por software.

 

Autor: Santiago Villafuerte

http://www.migsantiago.com

*/

 

#include "18f452.h"

#fuses nowdt,noput,nobrownout,noprotect,nodebug,NOLVP,xt,nocpd,CCP2C1

#use delay(clock=4000000) //4MHz internos

#use rs232(baud=19200, xmit=PIN_c6,rcv=PIN_c7)

#use fast_io(c)

 

#define datos 128

 

//------------------------------------------------------------------------------

//Globales

int16 tiempos[datos];

int flanco[datos];

int16 i;

int envia;

 

//------------------------------------------------------------------------------

void main()

{

//No envía datos al principio

envia=0;

//Configura entradas y salidas

set_tris_c(0b10000110);

   //CCP1 - RC2

   //CCP2 - RC1

   //TX - RC6

   //RX - RC7

 

//Configura timer1 para leer de 0 hasta 65,536us

//con resolución de 1us por bit @ 4MHz

SETUP_TIMER_1(T1_INTERNAL);

 

//Configura CCP1 y CCP2

//CCP1 - Bajada

//CCP2 - Subida

SETUP_CCP1(CCP_CAPTURE_FE);

SETUP_CCP2(CCP_CAPTURE_RE);

 

//Habilita interrupción por CCP1 o CCP2

ENABLE_INTERRUPTS(INT_CCP1);

ENABLE_INTERRUPTS(INT_CCP2);

enable_interrupts(GLOBAL);

 

while(1)

   {

   if(envia==1)

      {

      disable_interrupts(global);

      envia=0;

      printf("Inicio\n\r");

      for(i=0;i<datos;i++)

         {

         if(flanco[i]==0)

            printf("T0: %1.1f t\n\r",(float)tiempos[i]/444);

         else

            printf("T1: %1.1f t ",(float)tiempos[i]/444);

         }

      i=0;

      printf("Fin\n\r");

      enable_interrupts(GLOBAL);

      }

   }

}

 

//------------------------------------------------------------------------------

#int_ccp1

void flanco_bajada()

{

flanco[i]=1; //Tiempo en uno

tiempos[i++]=CCP_1-CCP_2;

if(i==datos)

   {

   i=0;

   envia=1;

   }

}

 

//------------------------------------------------------------------------------

#int_ccp2

void flanco_subida()

{

flanco[i]=0; //Tiempo en cero

tiempos[i++]=CCP_2-CCP_1;

if(i==datos)

   {

   i=0;

   envia=1;

   }

}

 

 

Cuando se detecta un flanco de bajada o subida se ejecuta una interrupción y se almacena en un arreglo el tipo de flanco detectado y en otro arreglo la duración del pulso, la cual es la diferencia entre los tiempos almacenados en CCP1 y CCP2. Esto se repite las veces que la constante datos indique. Una vez que se haya almacenado la cantidad de datos indicada (128) se envía todo el arreglo almacenado vía RS232. Esto se hace así para que un envío RS232 no afecte la medición de tiempos y ofrece la posibilidad de medir 128 transiciones continuas.

Una vez programado y conectado el PIC18, se presiona el botón ON/OFF del control remoto de la XBOX y en la hyperterminal se obtienen los siguientes tiempos:

Inicio
T1: 0.2 t T0: 147.3 t
T0: 140.2 t
T1: 6.1 t T0: 1.8 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.9 t
T1: 1.0 t T0: 1.9 t
T1: 3.0 t T0: 1.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 2.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 1.9 t
T1: 2.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 1.9 t
T1: 2.0 t T0: 1.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 0.9 t
T1: 2.0 t T0: 0.9 t
T1: 1.0 t T0: 1.9 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 7.4 t

T1: 6.0 t T0: 1.9 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 2.0 t
T1: 1.0 t T0: 1.9 t
T1: 3.0 t T0: 2.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 2.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 2.0 t
T1: 2.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 2.0 t
T1: 2.0 t T0: 2.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 0.9 t
T1: 1.0 t T0: 1.0 t
T1: 1.0 t T0: 1.0 t
T1: 2.0 t Fin
 

En negritas se observan el envío de un comando completo. Los siguientes pulsos muestran las duraciones de los bits en el protocolo.

 

 

En la siguiente imagen se ve el arreglo de bits que detecté en un envío de comando.

 


 

  • El primer renglón indica T1: 6.1 t T0: 1.8 t que es un aproximado de 6t en ALTO y 2t en BAJO. Ese es el pulso de inicio.
  • Luego se ve T1: 1.0 t T0: 1.0 t que es el bit inicial.
  • Luego se ven 3 líneas:
    T1: 1.0 t T0: 1.0 t
    T1: 1.0 t T0: 1.9 t
    T1: 1.0 t

    las cuales contienen los 3 bits del modo de envío, los cuales son 1 1 0. Se puede observar que el segundo T0 dura 2t, esto se debe a que se une el tiempo bajo del fin de un 1 y el tiempo bajodel inicio de un 0.
  • Luego se ve:
    T0: 1.9 t
    T1: 3.0 t

    el cual representa los 2t bajos y 2t altos del bit de rastreo.
  • Posteriormente se toman de la misma forma los tiempos altos y bajos para armar los 32 bits del comando enviado.
  • Por último se observa un tiempo bajo de 7t al finalizar el envío, T0: 7.4 t.

Interpretando los datos arrojados por el pic se tiene la siguiente secuencia de bits enviada al presionar el botón ON/OFF del control:

Pulso Inicial - Bit Inicial - 110 - Bit Rastreo 0 - 10000000 00001111 01110100 00001100 - Tiempo Libre

Realizando la misma operación pero ahora presionando otros botones se tiene:

  • Botón Y
    Pulso Inicial - Bit Inicial - 110 - Bit Rastreo 0 - 10000000 00001111 11110100 00100110 - Tiempo Libre
  • Botón X
    Pulso Inicial - Bit Inicial - 110 - Bit Rastreo 0 - 10000000 00001111 01110100 00010011 - Tiempo Libre
  • Botón Guía XBOX
    Pulso Inicial - Bit Inicial - 110 - Bit Rastreo 0 - 10000000 00001111 01110100 01100100 - Tiempo Libre
Una vez habiendo entendido los tiempos y formas de envío escribí un programa para replicar el funcionamiento del control de la xbox pero de forma muy limitada, solo simula el botón Guía Xbox como si se presionara una vez cada segundo. Utilicé un PIC16F88 y un led emisor infrarrojo para lograrlo. El circuito usado es el siguiente.

 

Una conexión de este tipo genera lo siguiente:

•    Si CCP1 está en alto y RB2 en alto, el led no emite luz.
•    Si CCP1 está en bajo y RB2 en alto, el led no emite luz.
•    Si CCP1 está en alto y RB2 en bajo, el led emite luz.
•    Si CCP1 está en bajo y RB2 en bajo, el led no emite luz.

La terminal CCP1 tendrá una salida de 36kHz con duty time del 50% y la terminal RB2 funcionará respecto a los 't' requeridos por el protocolo. El programa en CCS es el siguiente.

/*Programa que genera una salida pwm a 36kHz para funcionar como el control

infrarrojo multimedia de la xbox 360.

El control opera a 36kHz siguiendo el estándar RC6.

Santiago Villafuerte

http://www.migsantiago.com/

*/

 

//fpwm=36kHz

//Tpwm=27.777us

//duty time= 13.88us

//Tpwm=(PR2+1)4 Tosc PRtm2

//Tpwm=(27+1)(4)(1/4MHz)(1)=28us

//fpwm=1/28us=35.714kHz

//duty time=CCP Tosc PRtm2

//duty time=56(1/4MHz)(1)=14us

//Res=[log(4MHz/35.714KHz)/log 2]=6.8bit=6bit

 

#include "16f88.h"

#fuses nowdt,noput,nobrownout,nolvp,noprotect,NOMCLR,INTRC_IO,ccpb3

//nomclr... habilita la patita mclr para que sea RA5 (I/O)

//intrc_io... usa reloj interno, habilita RA6 y RA7 como I/O

//CCPB3... CCP1 input/output multiplexed with RB3

#use delay(clock=4000000) //4MHz internos

#use fast_io (a)

#use fast_io (b)

 

//#define duty_time 0x0038

int i;

 

////////////////////////////////////////////////////////////////////////////////

void tren_on(int t)

{

output_low(pin_b2); //0V encienden led a 36kHz

for(i=0;i<t;i++)

   delay_us(440);

}

 

////////////////////////////////////////////////////////////////////////////////

void tren_off(int t)

{

output_high(pin_b2); //5V apagan led

for(i=0;i<t;i++)

   delay_us(440);

}

 

////////////////////////////////////////////////////////////////////////////////

void main(void)

{

int16 duty_time;

 

   duty_time=0x0034; //esto nunca cambia (13us)

   set_tris_a(0x00); //todo salida

   set_tris_b(0x00); //todo salida

 

   SETUP_ADC(ADC_OFF);

   SETUP_ADC_PORTS(NO_ANALOGS);

 

   setup_timer_2(T2_DIV_BY_1,25,1);

      //PR2=25

   set_pwm1_duty(duty_time);

      //13us

   setup_ccp1(CCP_PWM); //activa PWM

 

while(1)

{

//Prueba 1, envío de botón Guía Xbox cada 5 segundos

tren_on(6); tren_off(2); //LS

tren_on(1); tren_off(1); //SB

tren_on(1); tren_off(1); //MB2

tren_on(1); tren_off(1); //MB1

tren_off(1); tren_on(1); //MB0

tren_off(2); tren_on(2); //TR0

 

tren_on(1); tren_off(1); //1

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

 

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

 

tren_off(1); tren_on(1); //0

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

tren_off(1); tren_on(1); //0

tren_on(1); tren_off(1); //1

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

 

tren_off(1); tren_on(1); //0

tren_on(1); tren_off(1); //1

tren_on(1); tren_off(1); //1

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

tren_on(1); tren_off(1); //1

tren_off(1); tren_on(1); //0

tren_off(1); tren_on(1); //0

 

tren_off(7); //SIGNAL FREE

delay_ms(1000);

}

}

  Al conectarlo y probarlo frente a la Xbox 360, se observa que la Guía Xbox se abrey cierra constantemente, comprobando que el control clonado ha funcionado exitosamente.