You are on page 1of 14

11,631,212 memb ers (75,530 o n lin e)

articles

Q&A

forums

Sign in

lounge

Search fo r articles, qu estio n s, tip s

C# Remote Control using the Audio Port


Michael Wolski, 10 Jun 2004

CPOL

Rate this:

4.90 (82 votes)

This article describes the development of C# code that allows you to send consumer IR codes from your mobile device using the audio port.
Download PocketBeamer PocketPC binaries - 9.66 KB
Download PocketBeamer source - 15.2 KB

Introduction
One of the most exciting aspects of a mobile device is its ability to let you to interact with your surroundings. This article takes a look at a method of
controlling consumer appliances (stereo, DVD player, VCR, television, hobby robots, etc...) using their built-in infrared (IR) receivers. There are several good
applications available that allow you to send/receive IR signals from your Pocket PC, but they all suffer from the same problem: the IRDA port on most models
is too weak to produce a consumer IR signal that can go further than 8 feet. The clever developers at Griffin Technology came up with a nifty device that
plugs into your mobile PC's audio port and can send much stronger signals. My hat is off to their developers for coming up with this idea, as it is truly
inventive. This article will explore how they can accomplish the feat of sending of consumer IR signals using, well, ... sound, and how you can use it in your own
applications.
Note: This is NOT a paid advertisement, and I have absolutely no relationship with the Griffin Technology people. Rather, when this device first came, I
contacted Griffin about getting access to an SDK so that I could incorporate the sending of IR codes in my own applications. I was very disappointed with the
one-line response I received and the attitude towards consumers in their postings on other web forums. So I decided to work work this puzzle out for myself.
Hey, how hard could it be? Famous last words.

Background - IR Signals in a nutshell (or a very very small box)


First things first: What is an IR code?
There are articles on the web that can explain IR signals in much greater detail than I can here. For example, Barry Gordon has a great write-up about how
infrared signaling works over at RemoteCentral.com. That site also has loads of IR codes in their IR database that you can use to control your own devices. But
anyway, I will take crack at explaining simple consumer IR signaling in a nutshell:
When you use your remote control to (say) turn on your television, you are really sending a command to the TV on a beam of infrared (IR) light. Unlike a
flashlight, the IR light is not visible to the naked eye so you won't actually see the beam. But the sensitive IR receiver on your television can "see" it, and uses
the information it contains to perform a given command. What command should it perform? Well, the beam of IR light that your remote control sends is
really comprised of many little ON and OFF pulses of light. The combination of ON and OFF pulses determines the exact command that your television should
perform. One set of ON and OFF pulses means TURN ON, and another means CHANNEL UP. A diagram of what is happening can be seen below:

converted by W eb2PDFConvert.com

Now, behind the scenes, your television remote is doing a little extra work than is outlined above. Yes, it sends a series of ON and OFF pulses and their
sequence determines the specific command it is trying to send (power on, power off, change channel, etc...). But these ON and OFF pulses are really made up
of a wave of IR light at a given carrier frequency. All this means is that the long pulse of ON is comprised of many little ON/OFF flickering of IR light. The IR
light goes on-off-on-off-on-off... for a duration of the total ON time. Each little on-off duration is at the carrier frequency.
This carrier frequency serves several purposes including power savings and the better handling of "noise". (Note: even though IR signals are at a higher
wavelength than visible light, they are still subject to the introduction of noise produced by visible light and other radiating sources). The carrier frequency
varies from remote-to-remote and brand-to-brand. Normally, consumer IR remotes operate in the 36KHz (that's 36,000 cycles per second) to 40Khz range.
Remember this range, as it is very important later on. An example of a wave using a carrier frequency can be seen below:

Background - Code breaking


The last section was a very brief description of how a remote control sends its code using an Infrared (IR) wave. In this section, we will take a quick (and I
mean quick) look at what the remote control sends. This is known as the IR code. Remember, in order for a remote control to send different commands, it
needs to send a specific IR code for each command. This way, the receiving unit (say the television) can distinguish between a channel up command or a
power off command.
A popular example of an IR code format is the Pronto CCF format. The Pronto is a consumer device made by Philips that learns your remote control codes
and allows you to setup your own user-interface to play them back. When the Pronto learns your remote codes, it is basically analyzing the IR wave your
remote control produces when you press a given button. This is the same wave we discussed above. It is the unique series of ON/OFF values from this wave
that gets stored as the IR code for that button. An example of a typical IR code (in Pronto format) is below:
0000 0067 000D 000D 0060 0019 0018 0018 0018 0018 0018 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0030 0018 0018 0018
0030 0018 0018 03FB 0060 0018 0018 0018 0018 0018 0018 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0030 0018 0018 0018
0030 0018 0018 03E5
There is nothing like a big long string of Hex codes to make you reach for another dose of aspirin and a cup of coffee. But in this case, hold off. The code
above is really quite simple and shouldn't cause you overdue stress. The first 4 values are just a descriptive header. The rest of the code is comprised of 1 or 2
signals (depending on the header).
Header: 0000 0067 000D 000D
The header is made up of 4 words. The first word (0x0000 in this case) specifies the code format. For our purposes, this will always be 0000 denoting a "Raw"
format. There are other values for this indicating different types of encoding. Feel free to read up on those other format types, but we won't be covering them
here. The second word (0x0067 = 103 decimal) is the frequency divider of the carrier signal, which is relative to the Pronto's internal clock that operates at
4,145,146Hz. So the carrier frequency for this IR code is really 4,145,146Hz /103 = 40,244Hz. The next words in the header describe what signals are
contained within the code.
The third word (0x000D = 13 decimal) is known as the "once count" and indicates that this IR code has 13 on/off pairs of data known as signal bursts. The
"once" signal is the signal that is sent if you press and let-go of a key on your remote control. Note that this value indicates the number of signal pairs, which
means there will really be 2*Value of data for this signal. In this case, 13 pairs means we will be reading 26 values. The values are the alternating ON/OFF
duration of the code. So you can see (using the color coding) that the green "once" signal starts with an ON value of 0x0060 followed by an OFF value of
0x0019 followed by an ON value of 0x0018 followed by... well, you get the picture. If the value of this word is 0x0000, it means that there is no "once" code,
and that you should always send the "repeat" code no matter if you are pressing the key once, or repeating.

converted by W eb2PDFConvert.com

The fourth word (0x000D = 13 decimal) is the "repeat count" and indicates that there are also 13 signal bursts in the "repeat" signal. The "repeat" signal is the
signal that is sent if you hold a key down (say, the volume key) on your remote control. If you hold a key, the "once" signal is sent followed by as many
repetitions of the "repeat" signal as possible (while you are holding the remote control key down). When you let go off the key, the remote stops sending. So
again using the color coding, you can see that the purple signal is the repeat signal. If the value of this word is 0x0000, it means there is no "repeat" code and
the key doesn't repeat.
That's it! An extremely brief overview of a summarized version of a condensed beginner's guide to the workings of consumer IR codes. Now go grab yourself
that coffee and let's get on with the meat of the article.

Mystery Unfolds - How do they do it?


Now that we know a little about IR codes and how they are built, the real question is: How can we send IR waves through the audio port of our PDA? The
Total Remote comes with software to accomplish this, but I really would like to have the ability to do this from my own mobile application. So I broke out my
trusty/dusty USB oscilloscope, a pad and paper, an old Sony VCR, and a pack of Mentos candy and started to investigate this conundrum myself. Four hours
and 2 cavities later, I came up with how to send the proper signals through the audio port to tell my VCR to start/stop/play/etc...
To work on this problem, I wrote down a list of questions I thought needed answering in order to come to the solution. My overriding goal here was to figure
out the how without actually breaking open the hardware. You see, I am cheap and clumsy. So prying open this little piece of hardware with the tools of
choice (hammer and vice grips) would mostly likely lead to me right into buying a replacement. This scenario did not fall within my zero-budget. So I had to
do the cheapest thing I could and actually exercise the mental muscle. Here is a list of what came to mind:

1. How can an audio signal turn into a 40Khz carrier signal?


By examining the Total Remote hardware itself, the answer to this question became apparent. The hardware has 2 IR emitting LEDs on the top, and a stereo
mini-jack plug which connects it to the PDA. I was very puzzled by the 2 separate LEDs. At first, I thought they used 2 in order to give a wider transmission
angle. In other words, 2 LEDs spaced slightly apart might beam a signal cone wider than just a single LED. But further examination and reflection proved this
was not necessarily the case.
Next, I was wondering how I could send any 40Khz signal through the audio port. You see, audio ports are manufactured to really only pass signals within the
range of human hearing which tops out around 20Khz. Anything over 20Khz would be squashed by either noise filtering or simply the performance of the
port itself. So how could I possibly get a 40Khz signal from a 20KHz port? What I really needed was a port that could pass twice the bandwidth. Twice. Two.
Hrm... where have I heard that number before....two ... I just ate two Mentos, no.... there were those twins I knew in college, no ....waittaminnut! Could it be a
coincidence that there are two LEDs and that I need twice the bandwidth. Yeah, probably just coincidence.
No, wait! Something I was forgetting is that, sure, the audio port is limited to around 20KHz, but the audio port is in stereo. This means there are two
channels (left and right), each capable of sending a 20KHz audio signal. Heyyy, maybe each of those LEDs is wired to a separate channel and would account
for the stereo mini-jack plug they used. But even so, how can I get 40Khz from a 20KHz channel? The answer is to send a 20KHz signal through each channel
and to send one signal out-of-phase with the other. This will double the effective frequency of the emitted signal, thus giving us the 40Khz we need to send
carrier signals.

2. How can we get enough power from the audio port to drive the IR signal further than a few feet?
OK, so we figured out how it was theoretically possible to send a 40Khz signal through the IR port, but that would be useless unless we can send it a
reasonable distance. After all, what good is a remote control that you have to get yourself out of your chair to use! I did some web searches and I found that
audio ports on PDAs are not really known for being very powerful. So I wondered how much power the Total Remote software was generating from the audio
port. There was only one way to conclusively find out: bring out the oscilloscope!
I plugged in my handy dandy USB oscilloscope, ran the Total Remote software, pressed a key to send a signal, and recorded the output. What I saw baffled
me at first. Here is a screenshot of the beginning of the signal:

converted by W eb2PDFConvert.com

Yes, I pretty much had the same reaction as you, looking at the beginning of the signal. What the heck is that? With a little more observation, I calculated that
when I pressed a remote control key (in the software), the signal that was generated started with this "preamble" of a 500Hz wave on both channels that was
out-of-phase. After this preamble, I could see what I expected: periods of on/off signal bursts that represented the IR code. This looked like:

So, I was curious. What is the purpose of the preamble? The answer appears to be that in order to boost the power from the audio port to send the IR signal
a reasonable distance, we need to "charge up" the total remote. My guess (because I never really pulled out the hammer and opened the hardware) is that
inside there is a little capacitor tuned to this preamble signal. The preamble charges up the capacitor and this power is subsequently released when the rest of
the IR signal is sent. This power boost enables the IR signal to travel further. Again, this is just a guess. Whether I am right or wrong is immaterial as long as I
can reproduce the same preamble.

3. How can I send a signal through software?


Ok, so at this point, I had an idea of what needed to be accomplished in order to send an IR signal using the Total Remote. I needed to create an out-ofphase stereo audio signal that included a "preamble" of 500Hz to charge up the total remote, followed by on/off signal bursts of the given carrier frequency. If
I could create this signal in some sort of audio format, I could simply play the sound file to send the IR command. And what is the first thing that comes to
mind when you think of raw audio files?

Doing the WAV


So my mission is clear. I need to create raw audio files that represent the IR code I want to send, and each audio file should have a "preamble" to charge up
the Total Remote. I believe the WAV file format is perfectly suited for this task. It is well documented, and has the flexibility to handle my needs. I won't go
full-bore into the structure of the WAV file format but you can easily Google the information from the web. Stanford.edu has a good short description of the
WAV format, and there is a different one over at SonicSpot.
When you download my source code, you will see only three classes that I created to support generating and sending the audio files. The PCMWaveGen object
encapsulates the writing of the actual WAV file. The IRWav class is derived from PCMWaveGen. It takes an IR Code and generates the proper wav file, and
optionally sends it to the Total Remote (audio port). Finally, we have the ProntoCCF object which encapsulates the file format used to input IR codes.

PCMWaveGen
converted by W eb2PDFConvert.com

This class encapsulates the writing of a WAV file. If you look at the source code, you will see it basically consists of a list of properties and several Write
methods. All of the properties map to properties in the the WAV file format. The basic WAV file consists of headers followed by sample data. The sample data
is really data at-a-point-in-time, or a "sampling" of the output stream. The headers just describe what kind of sample data to expect. An overview of the file
format layout looks something like:
Hide Co p y Co de

Section 1: RIFF Header Chunk


Section 2: FMT sub-chunk
Section 3: Data sub-chunk

This PCMWaveGen object is really not that interesting by itself, but the two methods to note are the WriteHeader and WriteFormat methods. At the very
beginning of a WAV file, there is a "RIFF" header. As you can see, it is very simple.
Hide Co p y Co de

public bool WriteHeader(BinaryWriter writer)


{
WriteString(writer,"RIFF");
writer.Write(this.ChunkSize);
WriteString(writer,"WAVE");
}

The real meat-and-potatoes of the information is in the Format section. As you can see, it consists of the audio format, number of channels, bit rate, etc...
Hide Co p y Co de

public void WriteFormat(BinaryWriter writer)


{
WriteString(writer,"fmt ");
writer.Write(this.FormatChunkSize);
writer.Write(this.AudioFormat);
writer.Write(this.NumChannels);
writer.Write(this.SampleRate);
writer.Write(this.ByteRate);
writer.Write(this.BlockAlign);
writer.Write(this.BitsPerSample);
}

ProntoCCF
This simple class takes the string representation of a Pronto CCF formatted IR code and translates it into signal arrays. The signal arrays are burst pairs just
like we discussed at the top of this article. Instead of creating yet another arbitrary format, I figured it would be easier in the long run to write a simple class
that parses out the Pronto codes. To use this class, you only need to pass the raw IR code string to its FromString() method. All of the processing is done
for you.
If you are looking for IR codes to use with your own devices, I would suggest RemoteCentral.com. They have a great database of different brands of remote
control codes that you can use. One thing to note: although a lot of times it is easy to grab an IR code from the web and have it work, they can sometimes be
very temperamental. If you have a method of learning your own IR codes, this is much more reliable than using someone's code that might not work for you
(for whatever reason). I only mention this because in the past, I have lost hours of work thinking there was an error in my code, when in reality, a simple
change of the IR code was the answer.

IRWav
This is the real workhorse class, as it encapsulates the generation of a WAV file from an IR code. To begin using this class, you only need to do the following:
Hide Co p y Co de

using DForge.IR.Formats;
using DForge.IR.TotalRemote;
ProntoCCF irCommand = new
ProntoCCF("0000 006D 001A 0000 ...rest of ir code here...");
IRWav totalRemote = new IRWav();
if(!totalRemote.SendSignal(irCommand,true))
MessageBox.Show("Failed to send the signal");

When designing this class, I wanted to make it as efficient as possible. You see, creating WAV files on the fly is no easy task for a little 'ole PDA. Sure, it can
handle it, but you really don't want the user waiting for 5 seconds every time you send an IR signal. To eliminate this waiting, I decided to cache the IR signals
so that they only get generated once. They are cached by using a unique ID (GUID) that is associated with every IR command. So when you see methods that
take a Guid idCommand parameter, this is the reason. When you send a command and it doesn't find the ID in the cache, it will generate the signal and
cache it for later use. The next time you send the signal, it looks up the ID form the cache and sends the pre-generated signal. If you want to just send a
temporary signal (like in the above example), either leave off the ID or send Guid.Empty in its place. If you do this, the code will generate the IR WAV file
every time (and you won't gain the benefits of caching).
One thing to note: if you change the actual IR code, you must clear the cache before sending the new code. Otherwise, it will look in the cache and pull up the
old pre-generated version and send that instead. As you can see, I provide two methods of clearing the cache. The first clears the entire cache, and the second
clears the pre-generated signal for a given command.
Hide Co p y Co de

converted by W eb2PDFConvert.com

/// <summary>
/// Clears the cached signal directory
/// </summary>
public void ClearCache()
{
if(Directory.Exists(this.CacheDirectory))
Directory.Delete(this.CacheDirectory,true);
Directory.CreateDirectory(this.CacheDirectory);
}
/// <summary>
/// Clears the cached signal for the given command
/// </summary>
public void ClearCache(Guid idCommand)
{
string strFilename = CacheDirectory + idCommand.ToString();
if(File.Exists(strFilename))
File.Delete(strFilename);
}

When you send a signal using IRWave, you will see several things going on. First, you will notice that we turn up the volume on the audio port to its
maximum level. This is the equivalent of us saying we want to send the IR signal with maximum power. Remember in the earlier sections, how we discovered
that preamble signal and how it is used to boost the power? Well, if we don't push the audio port's volume to maximum power before we send the signals,
the preamble would be for nothing. So we save the current audio volume level and put it up to 100% power for maximum range. Next, we check the cache to
see if the signal has already been created. If it is in the cache, we use it. Otherwise, we take the hit and generate the WAV file from the IR command. Finally,
we put the volume back to its original level. I figured this was a nice touch, so that when you later plug your headphones in and queue up your Celine Dione
MP3 collection, you won't get popped eardrums. Well, no more than normally at least.
Hide Sh rin k

Co p y Co de

/// Sends the given IR signal via IR


public bool SendSignal(Guid idCommand, double irCarrier,
short[] signal, bool usePreamble)
{
bool success = true;
try
{
// For total remote we need to send maximum power to the audio port
// so that we get the greatest range.
Sound.PushVolumePercent(100);
string strFilename = this.TempWavFilename;
if(idCommand!=Guid.Empty)
{
// We should cache commands with ids.
// Only generate a signal file if it doesn't already exist
strFilename = CacheDirectory + idCommand.ToString();
if(!File.Exists(strFilename))
this.WriteIRWAVFile(strFilename,irCarrier,signal,usePreamble);
}
else
{
// For commands without Ids (temporary ones) then we just
// write out the audio version of the IR signal to a temp file
this.WriteIRWAVFile(strFilename,irCarrier,signal,usePreamble);
}
// Play the audio signal through the total remote,
// generating an IR signal
success = Sound.Play(strFilename);
// Make sure we reset the volume to its previous value.
Sound.PopVolume();
}
catch(Exception except)
{
MessageBox.Show(except.Message);
success = false;
}
return success;
}

The next step in processing is to examine the WriteIRWAVFile method. This method draws upon the base class (PCMWavGen) to write the necessary
information to create a valid WAV file. WriteHeader and WriteFormat generated sections #1 and #2 of the WAV file format. The 3rd section is generated
by calling the WriteWAVSignal method which (finally) gets to the issue of generating the proper audio WAV data.
Hide Co p y Co de

converted by W eb2PDFConvert.com

public bool WriteIRWAV(BinaryWriter destWriter,


double carrierFreq, short[] signal, bool usePreamble)
{
bool success = true;
try
{
WriteHeader(destWriter);
WriteFormat(destWriter);
WriteWAVSignal(destWriter,carrierFreq,signal,usePreamble);
}
catch(Exception e)
{
MessageBox.Show(e.Message);
success = false;
}
return success;
}

The WriteWAVSignal method creates audio data for the given IR code. If you can remember from previous sections, the IR code consists of a series of
ON/OFF burst pairs. The ON time is comprised of many on-off transitions of the signal, the frequency of which is determined by the carrier frequency of the
IR code. The OFF time is, well, simply time where we want to be absolutely quiet and send no signal at all.
Hide Sh rin k

Co p y Co de

converted by W eb2PDFConvert.com

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

Creates a WAV audio signal that represents


the given consumer IR remote control code.
</SUMMARY>
<PARAM name="writer">Destination of the WAV data</PARAM>
<PARAM name="carrierFreq">Carrier of the IR code in hz (ie. 38000)</PARAM>

/// <PARAM name="irSignalPairs">Array of alternating short values


///
representing ON and OFF times of the carrier signal for the IR code.
///
Times are given in multiples of the carrier signal.</PARAM>
/// <PARAM name="usePreamble">If true, the WAV signal will be prefixed
///
by a 1Khz preamble (necessary for the Total Remote hardware)</PARAM>
/// <returns></returns>
public bool WriteWAVSignal(BinaryWriter writer, double irCarrier,
short[] irSignalPairs, bool usePreamble)
{
bool success = true;
try
{
// Indicate a DATA chunk is to follow in the WAV
WriteString(writer,"data");
// Mark the data size location for later
long dataSizePos = writer.BaseStream.Position;
// Write a dummy size for now
int dataSize = 0;
writer.Write(dataSize);
// Mark beginning of data to determine size later
long dataStartPos = writer.BaseStream.Position;
// If including the preamble for the Total Remote, then write it
if(usePreamble)
CreatePreamble(writer);
bool high = true;
double time = 0;
double halfCarrier = irCarrier/2;
// For each value in the IR code, generate its waveform.
// The array consists of pairs of short values indicating
// ON and OFF values of the carrier.
// An example would be { 0x5E, 0x19, 0x17, 0x19 }
// would produce an ON signal of
// duration 0x5E*Carrier followed by a "silence"
// of 0x19*Carrier followed by an
// ON signal of 0x17*Carrier followed by a "silence"
// of 0x19*Carrier ....
for(int i = 0; i < irSignalPairs.Length; i++)
{
// If last is a long "low" then ignore for now
if(i == irSignalPairs.Length-1 && !high)
break;
this.SampleHigh = high?255:128;
this.SampleLow = high?0:128;
time = (double)irSignalPairs[i] / irCarrier;
CreateStereoCarrier(writer,halfCarrier,irSignalPairs[i] ,true);
// toggle ON and OFF values
high = !high;
}
// Determine the overall Data size and write it to the WAV
dataSize = (int)(writer.BaseStream.Position-dataStartPos);
writer.BaseStream.Position = dataSizePos;
writer.Write(dataSize);
// Go ahead to end
writer.BaseStream.Position = writer.BaseStream.Length;
}
catch(Exception e)
{
MessageBox.Show(e.Message);
success = false;
}
return success;
}

The last method of note creates the data for a stereo carrier wave. Originally, I created a method that calculated a carrier wave with a given phase-shift and
called it twice to get a stereo wave. Due to speed issues, I rewrote this to calculate both channels at once. (The original method, although unused, is included
in IRWav). Also, I took one more caching step and cached the carrier wave that was generated. The IR codes that come from a single remote generally use the
exact same carrier frequency. So I managed to eek out more speed improvement by caching the last carrier frequency. Then I simply copy enough of these
carrier cycles into the destination signal that will fit in the given duration.
Hide Sh rin k

Co p y Co de

converted by W eb2PDFConvert.com

public void CreateStereoCarrier(BinaryWriter writer,


double carrierFreq, short cycles, bool phaseShift)
{
if(carrierFreq != _lastCarrierFreq || _lastCarrierWave == null
|| _lastCarrierWave.Length == 0 || _lastCarrierPhase != phaseShift)
{
if(_lastCarrierWave!=null)
_lastCarrierWave.Close();
_lastCarrierWave= new MemoryStream();
_lastCarrierFreq= carrierFreq;
_lastCarrierPhase= phaseShift;
BinaryWriter bw = new BinaryWriter(_lastCarrierWave); double
samplesPerWave = this.SampleRate/carrierFreq; double
quant = 2*Math.PI/samplesPerWave; double
sampleValue = 0; byte
bytValue = 0; int
i = 0; double
delta = Math.Abs(this.SampleHigh-this.SampleLow); double
cycleDuration = 1 / carrierFreq;
double step = 1/ ((double)this.SampleRate);
//For each sample, determine the value that would create a signal
//of the given carrier frequency for the duration specified
for(double time = 0; time < cycleDuration; time += step)
{
sampleValue = delta/2 * (1 + Math.Cos(quant*i));
bytValue = (byte)(this.SampleLow+sampleValue);
//First channel
bw.Write(bytValue);
//Are we phase shifting the second channel?
if(phaseShift)
bytValue = (byte)(this.SampleLow + delta - sampleValue);
//Second Channel
bw.Write(bytValue);
i++;
}
//create a "silent" wave as well.
_lastNullCarrierWave = new byte[_lastCarrierWave.Length];
for(int j= 0;j<_lastNullCarrierWave.Length;j++)
_lastNullCarrierWave[j] = (byte)(this.SampleLow+delta/2);
}
if(writer != null)
{
// Now make an exact copy of the carrier
// cycle for each of the remaining cycles
if(this.SampleHigh - this.SampleLow == 0)
{
for(short nI=0; nI < cycles/2; nI++)
writer.Write(_lastNullCarrierWave,0,
(int)_lastNullCarrierWave.Length);
}
else
{
for(short nI=0; nI < cycles/2; nI++)
writer.Write(_lastCarrierWave.GetBuffer(),
0,(int)_lastCarrierWave.Length);
}
}
}

Sample Application

The sample application is very simple and is meant to be nothing more than an illustration of how to use the underlying IR code. To really take advantage of
the sample application, you need 2 things.
converted by W eb2PDFConvert.com

First, you need to purchase or borrow a $29 Total Remote audio dongle. This is the hardware that fits in the audio port, as shown in the picture at the
top of this article.
Second, you need to locate valid IR code data for the devices you wish to control (television, VCR, DVD, etc...). This second part is the trickiest, but you
should have good luck finding them in the places I mention in this article.
The actual sending of the IR data couldn't be simpler, as illustrated by the following snippet:
Hide Co p y Co de

/// <summary>
/// Private member that allows us to send signals to the TotalRemote
/// </summary>
IRWav _totalRemote = new IRWav();
///
///
///
///

<summary>
Sends an IR command
</summary>
<PARAM name="idCommand">Unique ID of the command (or Guid.Empty)</PARAM>

/// <PARAM name="irCommand">IR Command to send</PARAM>


void SendIRCommand(Guid idCommand, DForge.IR.Formats.ProntoCCF irCommand)
{
if(!_totalRemote.SendSignal(idCommand,irCommand,true))
MessageBox.Show("Failed to send the signal");
}

The sample application reads the config.xml file and dynamically generates buttons for the user interface. (Please note that the config.xml file must reside in
the same directory as the executable.) When you press a button, its associated IR code is then sent through the total remote. Each entry in the config.xml file
consists of an ID (used to uniquely identify the button), a Name (displayed on the button), and the Code (actual Pronto CCF data representing the IR code
you want to send). An example of the config.xml file is as follows:
Hide Sh rin k

Co p y Co de

<?xml version="1.0" encoding="utf-8" ?>


<Buttons>
<Button ID="Button1" type=button>
<Id>6A25C487-F171-49a2-A6D8-2C5F28FF546F</Id>
<Name>Sony VCR Play</Name>
<Code>0000 006D 0020 0000 005E 0019 0017 0019 0017
0019 0017 0019 0030 0019 002E 0019 0017 0019 0017
0019 0017 0019 0030 0019 0017 0019 0030 0019 002F
0019 0030 0019 0017 0019 0030 00AF 0060 0019 0017
0019 0017 0019 0017 0019 0030 0019 0030 0019 0017
0019 0017 0019 0017 0019 0030 0019 0017 0019 0030
0019 0030 0019 0030 0019 0017 0019 0030 3F03</Code>
</Button>
<Button ID="Button2" type=button>
<Id>F96CA367-E471-4bff-AC39-7D3594E135F8</Id>
<Name>Sony VCR Stop</Name>
<Code>0000 0067 001A 0000 0060 0019 0018 0018 0018
0018 0018 0018 0030 0018 0030 0018 0018 0018 0018
0018 0030 0018 0030 0018 0018 0018 0030 0018 0018
03FB 0060 0018 0018 0018 0018 0018 0018 0018 0030
0018 0030 0018 0018 0018 0018 0018 0030 0018 0030
0018 0018 0018 0030 0018 0018 03E5</Code>
</Button>
<Button ID="Button3" type=button>
<Id>7A4F502A-2593-4d00-A4F3-3672B7B390B2</Id>
<Name>Zenith Television Power ON/OFF</Name>
<Code>0000 006D 0022 0000 0018 0011 0018 00A5 0018
00CF 0018 0011 0018 00A5 0018 0010 0018 00A5 0019
00CD 0018 0010 0018 00A5 0018 00CE 0018 0011 0018
00A5 0018 00CE 0016 00CF 0018 0011 0018 13B6 0018
0011 0018 00A5 0018 00CF 0018 0011 0018 00A5 0018
0010 0018 00A5 0019 00CD 0018 0010 0018 00A5 0018
00CE 0018 0011 0018 00A5 0018 00CE 0016 00CF 0018
0011 0018 13B6</Code>
</Button>
</Buttons>

Wrapping it up
So, there we have it from start to finish. I really must commend Griffin for devising a very clever solution to sending IR signals through the audio port. The
method is ingenious and quite simple. I even toyed with creating a homemade version of the dongle, but just haven't had the time. I think the recipe is as
follows:
1 part stereo mini-jack +
1 part capacitor +
1 part resistor +
2 parts LEDs +
1 part Elfin Magic
= Homemade Total Remote

converted by W eb2PDFConvert.com

The problem is that I am a bit short on the Elfin magic. Maybe someone will take this article as the basis and come up with the home version. But either way,
once you know a bit about how IR signals are created, the process of determining how to convert audio to IR is pretty straightforward.
I do have a couple closing notes:
I cannot stress enough that when using this application to send IR codes to your own devices that the IR code is very important! Not only do you need to
find the proper IR code for your make/model of device, but it has to be a good code. Generally, the codes I found were usable. But a lot of codes were
missing the full code. Hint: If you get an IR code that doesn't seem to work, try sending it twice in rapid succession. If this still doesn't work, then it is probably
a bad code. Also, please do not send me requests for IR codes!!! I don't have a big-book-of-IR-codes. Search the web (or look at the sites I references) and
you will find them.
This method of using the audio port may not work on all PDAs. If the hardware manufacturer skimped on the audio port, it might not be capable of sending
a signal (or at least a strong one). For example, I believe the Dell Axim (at least older models) have a problem with using the audio port in this manner. See
the Griffin Technology site for a complete list of supported models.

References
Boy howdy, I certainly referenced a lot when developing this project. Here are the links of the relevant sources:
Griffin Technology - Total Remote Manufacturer.
Barry Gordon - Excellent write-up of how consumer IR signaling works.
RemoteCentral.com - Wealth of IR codes and general consumer IR information.
Stanford.edu - Explanation of the WAV file format.
SonicSpot - Further WAV file format information.
Parallax Inc - Makers of the USB oscilloscope I used (OPTAScope 81m).

More Reading
Here are some related IR links:
LIRC - LIRC is a LINUX package that allows you to decode and send infra-red signals of many (but not all) commonly used remote controls.
WinLIRC - WinLIRC is the Windows equivalent of LIRC, the Linux Infrared Remote Control program.
Ultramote - a Compact Flash IR extender for the pocket PC.
PDAWin extender schematic - a hardware schematic for building your own pocketpc IR extender.

History
4/18/04 - Article submitted
4/22/04 - Minor editing and fixing of hyperlinks
6/10/04 - Added extra references

License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share
EM AIL

About the Author


Michael Wolski
Web Developer
United States

Michael is an avid Windows developer, working on applications ranging from agricultural, military, financial, and workflow to those ranging in scope from
mobile, desktop and client-server systems. He is a co-author of the MFC Bible 4 published by Macmillan. In 2003 he was a team member on the project
converted by W eb2PDFConvert.com

that won the CES 2003 Best of Innovations award for Home Automation. Currently he is working for a start-up developing .Net applications for home
automation on desktop, PocketPC, and Palm platforms. He also runs a software development and consulting business at http://www.digitForge.com

You may also be interested in...


Remoting with GUIs

Vendor Landscape: Application Delivery Controllers

Remote Control PCs

Understanding the Need for a Single Code Base in


Enterprise Mobile App Development

Pocket PC TV Remote Control

Will Mobile Application Development Follow the Path of


Web Development?

Comments and Discussions


You must Sign In to use this message board.
Search Comments

Go
First Prev Next

Windows 8 working fix


andrew douse 18-Feb-15 1:37
Update on Visual 03?
Member 10760803 22-Apr-14 7:40
My vote of 5
achinverma 20-Sep-13 19:50
How to change BitsPerSample
pataha 25-Sep-11 17:17
Anyone tried it?
Adrian Ber 13-Sep-09 2:37
port
Adrian Ber 12-Sep-09 9:02
Ipaq 210
JohnK888 5-Jan-09 6:07
(Applause)
Predrag Tomasevic 4-Oct-08 7:34
Porting to Linux and MacOSX
jumpjack 2-Jul-08 6:40
Platform
erasmur 23-Jun-08 3:46
I found the Griffin patent descriprion freely available online! (free registration required)
jumpjack 14-May-08 21:47
Audio to the PDA possible?
mangotj 1-Nov-07 16:54
Where to get a dongle?
t_barbz 30-Oct-06 6:12

converted by W eb2PDFConvert.com

Using the built in IrDA port


t_barbz 27-Oct-06 5:45

i have a silly idea


NuVanDibe 13-Aug-06 22:28
Built my own dongle...
RF_GUY 20-Jul-06 5:47
Re: Built my own dongle...
slkhu 10-Aug-06 17:18
Re: Built my own dongle...
slkhu 17-Aug-06 21:01
Re: Built my own dongle...
slkhu 26-Sep-06 22:28
Re: Built my own dongle...
oliseski 30-Mar-07 9:38
Re: Built my own dongle...
jumpjack 14-May-08 10:56
Re: Built my own dongle...
jumpjack 14-May-08 21:42
Re: Built my own dongle...
slkhu 25-Dec-08 22:00
PC Remote
Acuum 6-Jul-06 3:32
Could it be simpler
Acuum 6-Jul-06 3:20
Re: Could it be simpler
Acuum 6-Jul-06 3:23
Re: Could it be simpler
RF_GUY 3-Aug-06 7:01
looks more like AM modulation to me
calixo 19-Feb-06 0:10
Port Software to s60?
uzzors2k 12-Nov-05 10:01
Nice Article, Can i use the IR remote to control my computer
reddyp82 29-Oct-05 16:04
Audio Out to IR
Vlad_one 9-Sep-05 22:49
some body help me?
Robby Sanjaya 30-Nov-04 4:18
CreateStereoCarrier (double) not used
tewiahc 14-Nov-04 5:25
Has anyone got this working on an IPAQ?
tewiahc 11-Nov-04 22:23
Re: Has anyone got this working on an IPAQ?
mralbright83 30-Mar-06 5:03
error...
hml_hml 31-Oct-04 9:09
Re: error...
manuelito80 3-Nov-04 23:00
The first Burst
BKnight2002 29-Sep-04 3:18

converted by W eb2PDFConvert.com

Manipulate IR port
draven2040 13-Sep-04 13:39
Be good to port this to Win32 XP
norm.net 9-Jun-04 4:51

Re: Be good to port this to Win32 XP


Michael Wolski 10-Jun-04 7:12
Re: Be good to port this to Win32 XP
franktmay 10-Dec-04 4:48
Great Explanation!
Megan Forbes 8-Jun-04 9:57
Recording
James Poag 30-May-04 14:44
Re: Recording
reinux 4-Mar-05 23:48
What about doing the hardware?
aroch 27-May-04 0:08
Re: What about doing the hardware?
Michael Wolski 27-May-04 3:30
Re: What about doing the hardware?
olaf.w 24-Jun-05 3:38
Re: What about doing the hardware?
rand3289 22-Aug-05 10:39
Re: What about doing the hardware?
RF_GUY 19-Jul-06 6:59
Refresh
General

News

1 2 Next
Suggestion

Question

Bug

Answer

Joke

Rant

Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
Permalin k | Advertise | Privacy | Terms o f U se | Mo b ile
W eb 03 | 2.8.150723.1 | Last U p dated 11 Ju n 2004

Layo u t: fixed | flu id


Select Lan gu age

Article Co p yrigh t 2004 b y Mich ael W o lski


Everyth in g else Co p yrigh t Co dePro ject, 1999-2015

converted by W eb2PDFConvert.com

You might also like