Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Phillips Dvd Remote Codes

Status
Not open for further replies.

jagadeesh1987

New Member
Dear All

I am decoding Philllips Dvd remote ,After decoding all the keys and analyzing the waveforms it is following Bi -Phase (Space ) encoding technique .

My problem is i am getting two different codes for single key as shown below

button 2 --- 110011000011000000011------------->(21 bits)
button 2 --- 1100110000011000000011----------->(22 bits)

Power --- 110011000011010100100------------->(21 bits)
power --- 1100110000011010100100------------>(22 bits)


Please suggest solution for me for preparing lookup table for further proceedings
 
Last edited:
Dear Nigel Goodwin

Thanx for your quick response ,i compared with RC 5 protocol,but its not matching with it . And my problem is i am unable find any particular protocol for above codes which i mentioned
 
Looks like standard RC6 mode 0 protocol to me, as described here:

https://www.sbprojects.com/knowledge/ir/rc6.php

Note that the trailer/toggle bit is twice the size of the other bits, this may cause confusion

I will look harder when I get back from work

EDIT: I see that the "control" byte is 0x04 and the information byte is 0x02 (hexadecimal) while the toggle bit is 1

On alternate button presses the toggle bit will toggle 0 and 1 alternately, and don't forget that the toggle bit is double-sized, which makes decoding a little trickier.
 
Last edited:
Hi,
Thanks for your response , if possible can you write the above waveforms in the form 0`s &1`s , so that i will compare all my decoded data .

And my another problem is i am getting 21 & 22 bits for single key .
 
Here's some RC6 decoding data in MicroPascal - it describes the protocol reasonably well.

Code:
unit Rc6_Decoder;

// D. Rosseel
// Original: 26-03-2009
// Latest update: 21-04-2009

// For 36Khz IR receivers with inverse output (= output active low), like the TSOP1736.
// The output of the Rc6 receiver is to be connected to the PIC's external interrupt pin (PortB.0).

{.$DEFINE DEBUG}

// --------------- interface ------------------

procedure Rc6_Interrupt;
// always to be called (unconditionally) in the program's "interrupt" procedure

procedure Rc6_Init;
// to be called before the Rc6 decoder can be used

function GetRc6(var Toggle, System, Command: byte): boolean;
// Returns true if an Rc6 code is received and decoded.
// If true, then "Toggle", "System" and "Command" contain the last decoded Rc6 code.
// Restarts Rc6 decoding (was stopped until this function gets the Rc6 data already received).


{$IFNDEF DEBUG}
implementation
{$ENDIF}

const Rc6_IDLE            = 0; // Rc6 decoder state constants
      Rc6_DECODING_HEADER = 1; // leader, startbit, mode bits and Toggle bit decoding
      Rc6_DECODING        = 2; // System and Command decoding
      Rc6_COMPLETED       = 3; // correct Rc5 code received and decoded

var Rc6_State: byte;           // State of the Rc6 decoder

      { ------ !!!!! -------
        The timer0 requires a clock (after prescaler) of 62.5 KHz. This means, when the
        CPU clock is 4 MHz a prescaler value of 16 is required: 4 MHz / 4 / 16 = 62.5 KHz.
        The time/timerstep is then 16 microsecs. (1/62500)
        For other CPU clock speeds the prescaler has to be adjusted accordingly, or
        if not possible both prescaler and "Rc6_TIME_..." constants have to be adapted.
      }
      
const
      Rc6_NR_Rc6_Bits = 16;
      
      // Leader pulses
      Rc6_LEADER_TIME_BOUNDARY = 125;
       { the leader Time "On" = 2666 uS = timer value 167
         the leader Time "Off" = 889 uS = timer value 83 }
         
      // "normal pulses"
      Rc6_TIME_BOUNDARY  = 42;  // below 42 = short, above = long
      { 1 bit time = 888 uS
        "short" time = 1/2 bittime = 444 uS, = timer value 28
        "long"  time = 1 bittime = 888 uS,  = timer value 55 }
        
      // First bit after the Toggle (trailer) bit
      Rc6_TRAILER_TIME_BOUNDARY = 69;
      { this is 889 + (444 / 2) millisecs = timer value 69 }

{
      
      Rc6 Bit coding:

       <--1 bit Time -->
       |               |
               --------
               |        "0" bit, no IR signal to IR signal transition
       --------
       --------
               |        "1" bit, IR signal to no IR signal transition
               --------


      RC6 coding/timing

      Legend: (1) = leader
              (2) = startbit (always "1")
              (3) = 3 mode bits (here always "000" is expected)
              (4) = trailer bit (= Toggle bit). Timing is different from regular bits
              (5) = 8 system bits
              (6) = 8 Command bits

          |<--- (1) ---->|<-(2)->|<-------- (3) -------->|<-- (4)--->|<--- (5) --->...<--- (6) --->|
          |              |       |       |       |       |           |       |     ...     |       |

 Edge# -> 0        1     2   3       4   5   6   7   8   9    10    11  12
          ---------      ----        ----    ----    ----      ------    ----     Case A:
          |        |     |   |       |   |   |   |   |   |     |     |   |        Toggle = 0 and
       ---         ------    --------    ----    ----    ------      ----         first sys bit = 0
       
       
 Edge# -> 0        1     2   3       4   5   6   7   8         9    10  11
          ---------      ----        ----    ----    ----------      ----         Case B:
          |        |     |   |       |   |   |   |   |         |     |   |        Toggle = 1 and
       ---         ------    --------    ----    ----          ------      ----   first sys bit = 1
       
       
 Edge# -> 0        1     2   3       4   5   6   7   8   9    10        11
          ---------      ----        ----    ----    ----      ----------         Case C:
          |        |     |   |       |   |   |   |   |   |     |         |        Toggle = 0 and
       ---         ------    --------    ----    ----    ------          ----     first sys bit = 1
       
       
 Edge# -> 0        1     2   3       4   5   6   7   8         9        10
          ---------      ----        ----    ----    ----------          ----     Case D:
          |        |     |   |       |   |   |   |   |         |         |        Toggle = 1 and
       ---         ------    --------    ----    ----          ----------         first sys bit = 0
}
      
var
{$IFDEF DEBUG}
    Rc6_Times: array[50] of byte; // array for the Rc6_Times measured
    Rc6_TimesIndex: byte;         // index/count for above
{$ENDIF}
    Rc6_Bits:  word;              // will hold the received bits
    Rc6_BitCount: byte;           // count for above
    
    Rc6_PrevBit: byte;            // the value of the previous bit
    Rc6_ShortPulses: byte;        // nr of subsequent short pulses measured
    
    Rc6_EdgeCount: byte;
    Rc6_Toggle : byte;
    
    Rc6_Time  : byte;
    Rc6_Error : boolean;

{$IFDEF DEBUG}
implementation
{$ENDIF}

procedure Rc6_Interrupt;
begin
  if (INTCON.INTE > 0) and (INTCON.INTF > 0) then
  begin // Total execution time is about 55 uS at 4 Mhz CPU clock
        
    OPTION_REG := OPTION_REG xor %01000000; // toggle the INTEDG (interrupt edge)
    INTCON.INTF := 0;
    
    Rc6_Time := TMR0;   // get time
    TMR0 := 0;          // restart timer
    
    Inc(Rc6_EdgeCount); // a new edge is there
    
{$IFDEF DEBUG}
    if Rc6_State = Rc6_IDLE then
    begin
      Rc6_TimesIndex  := 0;
    end
    else
    if (Rc6_State = Rc6_DECODING_HEADER) or
       (rc6_State = Rc6_DECODING) then
    begin
      Rc6_Times[Rc6_TimesIndex] := Rc6_Time;
      Inc(Rc6_TimesIndex);
    end;
{$ENDIF}

    case Rc6_State of
      Rc6_IDLE: //
        begin
          Rc6_State      := Rc6_DECODING_HEADER;
          RC6_EdgeCount  := 0;
          
          INTCON.T0IF := 0; // reset Timer0 overflow flag
          INTCON.T0IE := 1; // enable timer0 interrupt
        end;
        
      Rc6_DECODING_HEADER: // the "on" part of the leader has gone
                           // Execution time is about 20 uS at 4 Mhz CPU clock
        begin
          Rc6_Error := true;
          case Rc6_EdgeCount of
            1: if Rc6_Time > Rc6_LEADER_TIME_BOUNDARY then Rc6_Error := false;
            2: if Rc6_Time < Rc6_LEADER_TIME_BOUNDARY then Rc6_Error := false;
            3,5,6,7,8: if Rc6_Time < Rc6_TIME_BOUNDARY then Rc6_Error := false;
            4: if Rc6_Time > Rc6_TIME_BOUNDARY then Rc6_Error := false;
            9: begin
                 if Rc6_Time > Rc6_TIME_BOUNDARY
                 then Rc6_Toggle := 1                                           // Cases B and D
                 else Rc6_Toggle := 0;                                          // Cases A and C
                 Rc6_Error := false;
               end;
            10: begin
                  if Rc6_Toggle = 1 then
                  begin
                    if Rc6_Time > Rc6_TRAILER_TIME_BOUNDARY then
                    begin                                                       // Case D ends here
                      Rc6_State       := Rc6_DECODING; // actual data reached
                      Rc6_Bits        := 0;
                      Rc6_PrevBit     := 0;            // the first System bit is a "0"
                      Rc6_BitCount    := 1;
                      Rc6_ShortPulses := 0;
                    end;
                  end
                  else
                  begin
                                                                                // Case B (no action here)
                  end;                                                          // wait for the next edge
                  Rc6_Error := false;
                end;
            11: begin
                  if Rc6_Toggle = 1 then
                  begin                                                         // Case B ends here
                    Rc6_State       := Rc6_DECODING; // actual data reached
                    Rc6_Bits        := 1;
                    Rc6_PrevBit     := 1;            // the first System bit is a "1"
                    Rc6_BitCount    := 1;
                    Rc6_ShortPulses := 0;
                  end
                  else
                  begin  // Rc6_Toggle = 0
                    if Rc6_Time > Rc6_TRAILER_TIME_BOUNDARY then
                    begin                                                       // Case C ends here
                      Rc6_State       := Rc6_DECODING; // actual data reached
                      Rc6_Bits        := 1;
                      Rc6_PrevBit     := 1;            // the first bit is a "1"
                      Rc6_BitCount    := 1;
                      Rc6_ShortPulses := 0;
                    end;
                  end;
                  Rc6_Error := false;
                end;
            12: begin                                                           // Case A ends here
                  Rc6_State := Rc6_DECODING; // actual data reached
                  Rc6_Bits        := 0;
                  Rc6_PrevBit     := 0;
                  Rc6_BitCount    := 1;
                  Rc6_ShortPulses := 0;
                  Rc6_Error := false;
                end;
          end; // case
          
          if Rc6_Error then
          begin
            Rc6_State         := Rc6_IDLE; // restart
            OPTION_REG.INTEDG := 0;        // next Rc6 interrupt is negative going
            INTCON.T0IE       := 0;        // disable timer0 interrupt
          end;
        end;

      Rc6_DECODING: // Execution time is about 35 uS at 4 Mhz CPU clock
        begin
          if (Rc6_Time < Rc6_TIME_BOUNDARY) then         // short pulse detected
          begin
            inc(Rc6_ShortPulses);
            if (Rc6_ShortPulses = 2) then
            begin
              Rc6_Bits := Rc6_Bits shl 1;          // store the bit received
              Rc6_Bits.0 := Rc6_PrevBit;
              inc(Rc6_BitCount);
              Rc6_ShortPulses := 0;
            end;

          end else                                 // long pulse detected
          begin
            Rc6_PrevBit := Rc6_PrevBit xor 1;      // toggle the bit
            Rc6_Bits := Rc6_Bits shl 1;            // store the bit received
            Rc6_Bits.0 := Rc6_PrevBit;
            inc(Rc6_BitCount);
            Rc6_ShortPulses := 0;
          end;

          if Rc6_BitCount = Rc6_NR_Rc6_Bits then   // all bits are received
          begin
            Rc6_State := Rc6_COMPLETED;
            OPTION_REG.INTEDG := 0; // next Rc6 interrupt is negative going
            INTCON.T0IE := 0;       // disable timer0 interrupt
          end;
        end;

      Rc6_COMPLETED: //
        begin
          OPTION_REG.INTEDG := 0; // next Rc6 interrupt is negative going
        end;

    end;
  end;

  if (INTCON.T0IF = 1) and (INTCON.T0IF > 0) then  // timer 0 overflow, timeout
  begin
    if (Rc6_State = Rc6_DECODING_HEADER) or
       (Rc6_State = Rc6_DECODING) then // something is wrong
    begin
      Rc6_State := Rc6_IDLE;  // start all over
      OPTION_REG.INTEDG := 0; // next Rc6 interrupt is negative going
      INTCON.T0IE       := 0; // disable timer0 interrupt
    end;
  end;
  
  INTCON.T0IF := 0; // always reset timer0 overflow flag
  
end;

procedure Rc6_Init;
{$IFDEF DEBUG}
var I: byte;
{$ENDIF}
begin
  Rc6_State := Rc6_IDLE;
  
  // Timer 0
  OPTION_REG.T0CS := 0;  // bit 5 TMR0 Clock Source Select bit:0=Internal Clock (CLKO) / 1=Transition on T0CKI pin
  OPTION_REG.T0SE := 0;  // bit 4 TMR0 Source Edge Select bit: 0=low/high / 1=high/low
  OPTION_REG.PSA  := 0;  // bit 3 Prescaler Assignment bit: 0=Prescaler is assigned to the Timer0
  OPTION_REG.PS2  := 0;  // Rc6_Bits 2-0  PS2:PS0: Prescaler Rate Select Rc6_Bits
  OPTION_REG.PS1  := 1;
  OPTION_REG.PS0  := 1;
  TMR0            := 0;  // preset for timer register
  
  INTCON.PEIE     := 1;
  INTCON.T0IF     := 0;
  INTCON.T0IE     := 0;  // disable timer 0 interrupt for now

  // external interrupt
  TRISB.0           := 1; // "Int" input
  OPTION_REG.INTEDG := 0; // start with downgoing edge
  INTCON.INTF       := 0;
  INTCON.INTE       := 1;

{$IFDEF DEBUG}
  for I := 0 to SizeOf(Rc6_Times) - 1 do Rc6_Times[I] := 0;
{$ENDIF}
end;

function GetRc6(var Toggle, System, Command: byte): boolean;
begin
  Result := false;
  
  if Rc6_State = Rc6_COMPLETED then
  begin
    Result    := true;
    Toggle    := Rc6_Toggle;
    System    := Hi(Rc6_Bits);
    Command   := Lo(Rc6_Bits);
    Rc6_State := Rc6_IDLE;
  end;
end;

end.
 
@Nigel Goodwin - many thanks, this saves me a lot of time annotating the waveform

@jagadeesh1987 note that Nigel's timing diagram shows mark as high, space as low. Your IR receiver and the waveform you attached show INVERTED signal, where a mark is low, so is upside-down compared to Nigel's waveform diagram.

EDIT: and binary bit decode is:

Leader (2.667mS mark, 0.889mS space) - start bit 1 - mode 000 - double length toggle 1 - 00000100 - 00000010

or shorthand binary:

Leader - 1000 - 1 - 00000100 00000010

Mark = 36KHz IR being transmitted, space = nothing transmitted
 
Last edited:
Thanks @hexreader , i am getting 2 codes for single key ,so how can i write look up table for 2 different codes for single key press .
 
You should get the same address and control information for any particular button, only the toggle bit should change.

Sounds as though you are not decoding correctly.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top