Click here to Skip to main content
15,867,453 members
Articles / Mobile Apps / Windows Mobile
Article

Universal Remote Control with PDA

Rate me:
Please Sign up or sign in to vote.
4.67/5 (21 votes)
10 May 20076 min read 132.5K   1.5K   83   25
Developing a “Universal Remote Control for the PDA”

Introduction

At the end of our 4th year in the HTL (technical college) we were looking for an interesting project. We decided to develop our own "Universal Remote Control for the PDA." With this program it is possible to control your TV. During our internet research, we didn't find much information about this topic, but we found some useful information on codeproject.com and therefore we decided to publish our own solution here.

About the program

General:

  • application for PocketPC (Windows Mobile 3.0 and later)
  • Windows CE operating system
  • code in C# (Visual Studio 2005)

Implementation requires:

  • opening COM Ports on the PDA (COM1, COM2,…)
  • creating code to send to the PDA (RC5-Code)
  • creating pauses (range in µs)

Transmission

The existing infrared port on the PDA uses the standard IrDA protocol. The problem is that although the IrDA class in C# is able to open the port, an endpoint is required for successful transmission. This means that the class needs a connection between two intelligent devices (PDA-PDA or PDA-Handy). Therefore it is not possible to use the IrDA for a connection-oriented transmission to a dumb device such as a TV.

There are three types of infrared transmission:

  • Standard IR (SIR 115Kbps)
  • Fast IR (FIR 4Mbps)
  • Consumer IR (CIR 115Kbps)

CIR is the type you find in remote controls with a wide and long range. The wavelength of infrared light is between 940 and 950 nm. How the commands are coded depends on the manufacturer of the device.

Screenshot - one.jpg

We use the serial port and can generally create every code on the basis of the UART protocol. The first step is to find out which of the COM-ports on the PDA is responsible for the IR-port.

COM1 RS232 connector on DS, if DS is in normal (not transparent) mode
COM2 Raw IR, used internally by IrDA protocol (If you really need Raw IrDA, use this port in the same manner as for RS232 communication.)
COM3 Used internally by IrDA protocol (Use IrDA sockets for communication with IrDA)
COM4 GPS module in the device
COM5 GSM module
COM6 GPS module in DS, if DS in normal state (read-only access)
COM7 RS232 connector on the device (Lemo connector on H41RS device)
COM8 RS232 connector on DS, if DS in transparent mode
COM9 Free

The COM2-port makes it possible to send serial data through the IR-port. The SerialPort-class in C# provides methods of accessing the serial driver properties. We wrote a program which could display all available COM-ports on the PDA. The initial problem was that only COM3-port was shown. The solution was to install an update for the SerialPort-class. The update is called Microsoft .NET Compact Framework 2.0 Service Pack 1 and repairs some of the faulty methods in the SerialPort-class.

C#
public void GetName()
        {
            StringBuilder s = new StringBuilder();
            String s1;

            //get a list of port names
            string[] ports = SerialPort.GetPortNames();

            //display port names
            foreach (string port in ports)
            {
                s.Append(port+" ");
            }

            s1 = s.ToString();
            label1.Text = "Port Names: "+s1;
        }

RC5-code

For further steps, basics of RC5-code are required. First we must initialize all parameters of the serial port:

C#
//initialize the parameters for the SerialPort object
        public static String portName = "COM2";
        static int baudRate = 115200;
        public static Parity parity = Parity.None;
        static int dataBits = 7;
        public static StopBits stopBits = StopBits.One;
        SerialPort IR_COM = new SerialPort(portName, baudRate, parity, 
            dataBits, stopBits);

Manchester code

The next step is to initialise the parameters to generate the Manchester code. In RohCodeToManchester(), the raw data array will be passed to ManchesterCode(). ManchesterCode() generates of 1 a change from 1 to 0 and of 0 a change from 0 to 1.

C#
//initialize the parameters for the function ManchesterCode and 
//RohCodeToManchester
        char[] rohData = new char[14] {
             '1','1','0','0','0','0','0','0','0','0','0','1','0','0' };  
        public char[] manchesterData = new char[29];
        int index = 0, md = 0;

public void ManchesterCode(char c)
        {   
             if (c == '1')
             {  // 1 -> 10
                 manchesterData[index] = '1';
                 manchesterData[++index] = '0';
             }
             if (c == '0')
             {  // 0 -> 01
                 manchesterData[index] = '0';
                 manchesterData[++index] = '1';
             }
             index++;    
        }

        public void RohCodeToManchester()
        {   
            for (int i=0; i < rohData.Length; i++)
            {   //the array rohData is passed to the function ManchesterCode
                ManchesterCode(rohData[i]);
            }

            //mark the end
            manchesterData[28] = 'e';
        }

Generating burst and pause

To guarantee a safe data transmission, a 38 kHz modulated signal is transferred. The signal is then demodulated by the IR-receiver. The signal looks like this:

Screenshot - two.jpg

In the following calculations, you have to consider that the IR-transmitter inverts the signal and the LSB will be transmitted first. The following steps will be explained from this point of view, which is also the view of the program.

A low bit will be burst-modulated and a high bit will be a pause. So every 0 in the Manchester code is burst-modulated and every 1 stands for a pause of 889µs. What we know is that the baud rate must be 115 kBaud and the signal has to be modulated with 38 kHz.

The period length of 26µs accords to the baud rate of 38.4kBaud. Because 38.4kBaud is not a standard baud rate, we have to bring it up to 115.2kBaud. One bit will take 8.7µs.

Screenshot - three.jpg

Where

  • Ts is the period length
  • ts is the duration of a bit
  • Vs is the baud rate
  • f is the frequency

Our desired burst should look like 100100100, including start- and stop-bit. This accords to the presentation bellow. From our starting base of 100100100, we calculate back and consider that the IR-transmitter will invert the signal and send the LSB first.

100100100 with start- and stop-bit
0010010 without start- and stop-bit
1101101 inverted
1011011 LSB at first
0x5B hexadecimal

Screenshot - four.jpg

The word length is set to 1 start-bit, 7 data-bits and 1 stop-bit. The image on the top shows us that the start- and stop-bit is ideally integrated into the burst. Therefore one burst takes 79.7µs. Because the burst stands for the logical 0 in the data stream, we have to bring the burst up to the RC5 data length of 889µs. For one bit we have to send the burst 0x5B 11 times.

Screenshot - five.jpg

Where

  • tb is the duration of a burst
  • z is the number of bursts

A logical way to generate the pause would be to send 0x00 11 times, but this is not the solution because with each byte the stop-bit is part of the bit stream. So we had to find a timer that could create a pause of 889µs. There is a counter called QueryPerformanceCounter, which is a function in the coredll.dll on the PDA. Through the QueryPerformanceCounter, we could achieve an exact time measurement. This is because the QueryPerformanceCounter has direct access to the processor clock.

In the following code, we import the coredll.dll and make the initialization for the QueryPerformanceCounter and the BurstOut function. With DllImport you can import the .dll and after this you can use QueryPerformanceCounter() as a normal function in your program. The byte-array called BufferBurst include 22 times 0x5B. This is the result of the calculation above, as we had to send 11 times 0x5B for one RC5 bit. Because two logical 0s could appear in rapid succession in the data stream, the BufferBurst has double length.

C#
>//import the coredll.dll with the functions QueryPerformanceCounter
//and QueryPerformanceFrequency
        [DllImport("coredll.dll")]
        extern static int QueryPerformanceCounter(ref long perfCounter);
        [DllImport("coredll.dll")]
        extern static int QueryPerformanceFrequency(ref long frequency);

        //initialize the parameters for the QueryPerformanceCounter
        long ctrStart = 0, ctrAkt = 0, ctrEnd = 0;

BurstOut() passes a variable of the type long to the QPC() method. This variable sets the time interval for the QueryPerformanceCounter. In QPC() we stay in the while-loop until we have reached the specified time.

C#
public void QPC(long data)
        {   //start the counter
            QueryPerformanceCounter(ref ctrStart);
            
            //specified the end time
            ctrEnd = ctrStart + data;

            while (ctrAkt < ctrEnd)
            {   //wait until the counter reaches the end time
                QueryPerformanceCounter(ref ctrAkt);
            }
        }

The modulation is done in the BurstOut() function, where the Manchester code array is passed by a while-loop. There we proof the current and following bit. If the bit sequence is 10, a pause of 889µs is made and if the bit sequence is 11, we wait twice as long. When the bit sequence is 01, we send the burst 11 times and by a sequence of 00, 22 times.

C#
public void BurstOut()
       {
           while (manchesterData[md] != 'e')
           {   
               //pause of 889µs
               if (manchesterData[md] == '1' && manchesterData[md + 1] == '0')
               {
                   QPC(319);
               }

               //pause of 1,778ms
               if (manchesterData[md] == '1' && manchesterData[md + 1] == '1')
               {
                   QPC(766);
                   md++;
               }

               //burst of 889µs
               if (manchesterData[md] == '0' && manchesterData[md + 1] == '1')
               {
                   IR_COM.Write(bufferBurst, 0, 10);
               }

               //pause of 1,778ms
               if (manchesterData[md] == '0' && manchesterData[md + 1] == '0')
               {
                   IR_COM.Write(bufferBurst, 0, 22);
                   md++;
               }

               //the end
               if (manchesterData[md] == '0' && manchesterData[md + 1] == 'e')
               {
                   IR_COM.Write(bufferBurst, 0, 10);
               }

               md++;
           }
       } 

History

  • May 10, 2007 - Original version posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Austria Austria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHow to turn on the irda LED on my pda TO CONTROL a tv Pin
vasqo26-Aug-10 1:15
vasqo26-Aug-10 1:15 
GeneralVB Code Pin
knc301717-Feb-10 14:20
knc301717-Feb-10 14:20 
QuestionWhere put Ir bytes Pin
Daniele Di Sarli26-Mar-09 12:29
Daniele Di Sarli26-Mar-09 12:29 
GeneralPDA Application Pin
trimandir prajapati30-Dec-08 17:58
trimandir prajapati30-Dec-08 17:58 
QuestionPossible in Vista? Pin
Lukas Poellabauer7-Jun-08 9:13
Lukas Poellabauer7-Jun-08 9:13 
QuestionI can not understand some issues, would you like to help me? Pin
mickeyfirst4-May-08 23:47
mickeyfirst4-May-08 23:47 
Questionsuitable PDA devices?? Pin
sk2001de20-Feb-08 5:44
sk2001de20-Feb-08 5:44 
GeneralSending a pulsed message Pin
kardath31-Jan-08 3:34
kardath31-Jan-08 3:34 
Generalcom2 port Pin
vamsiprasanth12-Jan-08 20:05
vamsiprasanth12-Jan-08 20:05 
Questionwhy 0x5B [modified] Pin
chojr4k30-Oct-07 2:28
chojr4k30-Oct-07 2:28 
GeneralAnswer Pin
betz23108712-Sep-07 0:35
betz23108712-Sep-07 0:35 
Generaldeveloping the same project for Symbian OS Pin
agg.varun11-Sep-07 15:24
agg.varun11-Sep-07 15:24 
GeneralRe: developing the same project for Symbian OS Pin
Amvrel8-Jul-08 2:54
Amvrel8-Jul-08 2:54 
GeneralIO exception on IPAQ 2210 Pin
f2knpw28-Aug-07 12:04
f2knpw28-Aug-07 12:04 
GeneralRe: IO exception on IPAQ 2210 Pin
Sean Hamlin21-Nov-07 20:55
Sean Hamlin21-Nov-07 20:55 
GeneralRe: IO exception on IPAQ 2210 Pin
Sean Hamlin21-Nov-07 21:46
Sean Hamlin21-Nov-07 21:46 
GeneralQPC Pin
G unit ressurection26-Jun-07 22:24
G unit ressurection26-Jun-07 22:24 
QuestionUrgent Pin
Hamza Ayman2-Jun-07 12:28
Hamza Ayman2-Jun-07 12:28 
AnswerRe: Urgent Pin
betz2310872-Jun-07 23:15
betz2310872-Jun-07 23:15 
GeneralManchester Roh Code Pin
hackman3vilGuy15-May-07 2:55
hackman3vilGuy15-May-07 2:55 
GeneralRe: Manchester Roh Code Pin
betz2310872-Jun-07 23:26
betz2310872-Jun-07 23:26 
QuestionIdeal PDA ? Pin
Peter Hayward14-May-07 14:45
Peter Hayward14-May-07 14:45 
AnswerRe: Ideal PDA ? Pin
quarterback15-May-07 20:33
quarterback15-May-07 20:33 
AnswerRe: Ideal PDA ? Pin
chojr4k23-May-07 7:06
chojr4k23-May-07 7:06 
GeneralVery Nice!!!!!!!!! Pin
Jatin Gera10-May-07 20:47
Jatin Gera10-May-07 20:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.