Pic Lab, PIC16, Experiment #21, The IR remote protocol (RC5)

It is time to put my hands on the IR protocol.

The goal: To study IR protocol and gain the skills to work with it

Tools: a microcontroller PIC16f877A, an IR receiver TSOP1736(1738), devboard

a TSOP1736 receiver on the devboard

Now, a piece of the information about the RC5 protocol as such.

The frequency: of the carrier is 36 KHz, so the period is about 27.8 us.

A modulation: in the RC5 protocol is realized in a next way: each single bit is divided by half in time. We seek for a transition, or the edge direction: the rising edge is one, the falling edge is 0 – the Manchester code.

Manchester code states

One important thing we need to take into account – the transmitter amplifier usually is the common emitter configuration, so the logic should be inverted on a receiver side:

Inverted Manchester code states

That’s the very basis of the coding scheme. Now to the modulation: each single bit is represented by 64 pulses, 32 which represent a high level will be switching with clock about 36KHz, and the low level you will get a constant level, no switching.

The data packet representation consists of 14 bits and has the next view:

RC5 protocol data packet structure

Where:

S1, S2 – starting bits, always equal to 1, they will serve as an anchor to catch a start of transmission.

T – kind of checkbox, showing that the button on a remote is being hold, when it happened the T bit is toggling. An example of application: user wants to switch the tv to channel #2, without a T bit if user will hold the button long enough, it will produce 22 or 222 or 2222.

A4-A0 – an address, by this one system will determine what kind of device is receiving the signal. Here we have a list of devices and their addresses:

0 - TV
 
1 - TV2
 
2 - Teletext
 
3 - An extension for first two TVs
 
4 - A laser video player
 
5 - Videorecorder1
 
6 - Videorecorder2
 
7 - Reserved
 
8 - Satellite equipment?(SAT1)
 
9 - Extension for video recorders
 
10 - SAT2
 
11 - Reserved
 
12 - CD video player
 
13 - Reserved
 
14 - CD photo (no idea, what the heck is that)
 
15 - Reserved
 
16 - Pre-amplifier
 
17 - Reciever/tuner
 
18 - tape/vhs?
 
19 - Preamplifier 2
 
20 - CD
 
21 - Audio stand
 
22 - Satellite audio receiver(?)
 
23 - DCC record (?)
 
24 - Reserved
 
25 - Reserved
 
26 - Recording CD
 
27 - 31 - Reserved

Finally, С5-С0 – the command by itself, which also has the own specification. Everything has specification, smart guys developed the protocol.

0-9 - just numbers
 
12 - waiting mode
 
13 - Mute
 
14 - Setup
 
16 - Volume +
 
17 - Volume -
 
18 - Brightness +
 
19 - Brightness -
 
20 - Saturation +
 
21 - Saturation -
 
22 - Bass +
 
23 - Bass -
 
24 - Treble +
 
25 - Treble -
 
26 - Balance right
 
27 - Balance left
 
48 - Pause
 
50 - Fastforward
 
51 - Fastbackward
 
53 - Play
 
54 - Stop
 
55 - Record
 
63 - System choice (?)
 
71 - Display switch off(?)
 
77 - Linear function +
 
78 - Linear function -
 
80 - Up
 
81 - Down
 
82 - Menu
 
83 - Exit from menu
 
84 - Display the A/V status
 
85 - Left
 
86 - Right
 
87 - OK
 
88 - Picture in picture
 
89 - Picture shift
 
90 - Picture in picture - swapping pictures
 
91 - Strobe
 
92 - Multistrobe
 
93 - Image blocking
 
94 - Scan
 
95 - Choose picture in picture
 
96 - Mosaic
 
97 - Picture DNR(?)
 
98 - Save
 
99 - Strobe of the picture-in-picture
 
100 - Call for the main image
 
101 - Freeze of the picture-in-picture
 
102 - ? up
 
103 - ? down
 
118 - Alternative mode
 
119 - Options (different mode)
 
123 - Connect
 
124 - Disconnect

Time to move to the practice, that what I had:

the remote I had in my stash

The Chinese remote, I got it together with a TV tuner somebody gave away. There are different IR protocols, but by accident I found that this remote works with a Philips TV, so I made an “educated guess”.

To check my guess I brought the remote to my work lab and connected the LED leg to the scope:

The scope waveform from the remote LED leg

You can think “why do I see such a weird waveform?”. Well this is because the signal we see there is from the transmitting LED, not from the receiver. So far so good, the theory seems to have an agreement with the practice – we have 14 bits in total, lets check the carrier frequency now:

The zoomed in waveform, frequency is measured

The frequency is 38KHz! It was a quite wise decision to connect the remote to the scope first – it means that I need to buy 38KHz receiver, not 36KHz. Plus that something you certainly would be good to be aware of before coding the uC. Also, I stumbled at such words somewhere in the web:

The command data is a Manchester coded bitstream modulating a 36 kHz carrier. (Often the carrier used is 38 kHz or 40 kHz, apparently due to misinformation about the actual protocol.)

Due to misinformation, huh! Anyway, I do not care much, and I have a single remote, so not quite much of choices available for me.

The next movement for me is a building of the receiver. I had bought the TSOP1738 analogue, in the next package:

the package for TSOP1738

In that package the pinout is mirrored with respect to TSOP1736. The application diagram can be checked in the datasheet:

the application diagram from the datasheet

Good to have a scope handy, but sadly I did not have at the moment. If I would have it would be so easy to connect to the receiver input and check the signal type. Oh wait I have the one, built-in in Pickit2.

Connected, and pushing the “8” button:

number 8 is transferred to TSOP

There are clear two starting bits and the one could see 0b001000 = 8. The address is 0, since it is a remote from TV tuner. Now, how we can force our microcontroller to work with all this stuff? I developed my algorithm based on INTE and TMR1 interrupts.

The main difficulty in the program I met – we can’t trigger the absolute transmission starting point, what we see is is the edge, or already the middle of the Manchester coded bit S1. My algorithm is the next:

  1. Connect the receiver leg to the RB0 pin. Set INTEDG = 0, falling edge detection
  2. If the INTE interrupt is detected very first time then:
    • Launch timer for the interval 1.25 ms (3/4 of one bit modulated at 38 KHz)
    • Change INTEDG value on the inverted one
  3. If INTE interrupt happened not in the first time, then:
    • Change INTEDG to the inverted one
    • If INTEDG = bufer, launch TMR1 for 1.250 ms
  4. If TMR1 interrupt is detected, capture the RB0 state and put it to the buffer and save to the variable used for memory records

To make it simpler for understanding (for me as well), I made the next picture:

An algorithm described in diagram

Put some attention to this picture: we have received byte 11000001001000. Using beforementioned algorithm we will get a bit different number: 10000010010001, the MSB 1 is lost, but we gained another 1 in the end, and the end always will be 1.

So what we need to do now is to simply remove this extra 1 in LSB part and parse the byte to determine an address and the command.

Okay, time to expose the code:

#include <htc.h>
#include <stdio.h>
#include "usart.h"
 
#define _XTAL_FREQ 4000000
#define IRpin RB0
 
volatile static bit direction;    //1 - rising, 0 - falling
volatile unsigned char IRbyte;    //recieved byte
volatile bit buffer;              //буфер для значений таймера
volatile unsigned char bytecount; //количество байт
 
__CONFIG(WDTDIS & UNPROTECT & LVPDIS & HS);
 
void StartTimer()                 //refresh timer procedure
{
T1CKPS1 = 0;                      //no dividers
T1CKPS0 = 0;
 
T1OSCEN = 0;                      //internal ocs
TMR1CS = 0;                       // Fosc/4
TMR1IE = 1;                       // TMR1 overflow interrupt
TMR1H = 0b11111011; TMR1L = 0b00010110;       //1.257ms
 
TMR1ON = 1;                       // enable timer
}
 
void main()
{
TRISB0 = 1;                        //RB0 input
init_comms();                      //uart initialization
printf("\r\nStart");               //debug message
buffer = 0;                        //initial conditions
IRbyte = 0;
bytecount = 0;
direction = 0;
INTEDG = 0;                        //waiting fallinge edge interrupt
 
GIE = 1;                           //go go go
PEIE = 1;
INTE = 1;
 
while(1)
{
 if (bytecount>13)                 //if we recieved already 14 bits
  {
   GIE = 0;                        //blocking interrups for a while
   printf("\r\nPressed button is %d", IRbyte);  //throwing command to uart
   IRbyte = 0;                     //and back to 0 state
   bytecount=0;
   INTEDG = 0;
   buffer = 0;
   GIE = 1;
  }
}//while(1)
 
}
 
void interrupt isr()
{
  if (INTF)                       //RB0
   {
     if (bytecount<1)             //if this is a first time
       {
         direction = 1;           //waiting rising edge interruption
         INTEDG = 1;
         StartTimer();            //launch the timer
         bytecount++;             //increment counter of bits count
       } else                     //if not in the first time
          {
            direction = !direction; //change type of the edge interrup on the inverted one
             if (direction==buffer) //check if we can already relaunch the timer
               {
                StartTimer();
                bytecount++;
               } //if (direction==buffer)
            INTEDG = direction;
          } //else
     INTF = 0;
} //INTF
 
else {                            //RB0 interrupt has higher priority
if (TMR1IF)
  {
   buffer = IRpin;                // RB0 state to buffer
   TMR1ON = 0;                    //disable timer
   TMR1IF = 0;
    if ((bytecount>7)&&(bytecount<14))   //grabbing command only
     {
       IRbyte <<= 1;
       IRbyte |= buffer;
     }
   }
}
 
}

Example of the work:

All works fine, just I don’t have the toggle bit processing so I can have some false commands without proper handling.

The sources

1 thought on “Pic Lab, PIC16, Experiment #21, The IR remote protocol (RC5)

  1. Pingback: Remote control for the fan | diymicro.org

Leave a Reply

Your email address will not be published.