In my previous two blog posts I showed how I started to build a “code learner" for infrared remote controls in a PSoC5LP chip. This code learner captures the infrared signal from a remote control, decodes the signal, and compresses it in a format that can be stored in a nonvolatile memory location inside the PSoC5LP chip. The stored code is then retrieved from memory and used to reconstruct the modulated signal, which is sent off-chip to drive an infrared transmitter LED. This code learner algorithm will be implemented in my brainwaves appliance controller project so users can “teach” the brainwaves appliance controller specific codes needed to control their TVs, cable or satellite receivers, and other electronic devices that use infrared remote controls.
In the previous two blog posts I described how I got to the point where my algorithm captured the infrared signal and measured the duration of demodulated carrier-on and carrier-off pulses. In this blog I am showing how I compress the measured signal into a format that I can store in the EEPROM memory inside the PSoC5LP. The following figure shows a demodulated infrared signal (upper trace) and raw received signal that includes the carrier frequency (lower trace). On the figure I marked the pulse width measured with the PSoC5LP algorithm that I developed so far.
These values are stored for now in two arrays of uint16 type integers, each 100 values deep. This is volatile memory that will be erased every time the chip is powered off, so a user would need to load again the codes into the brainwaves appliance controller every time the power goes off/on. This is not a “user friendly” approach, so I started to look into how I can store the codes in a non-volatile memory that would preserve the values during power off.
From the PSoC5LP datasheet I learned that there is a section of EEPROM nonvolatile memory available. This non-volatile memory block is organized in 128 rows of 16 bytes each. Reads can be done at byte level; however, writes have to be done at row level. My arrays of values have 200 locations and if I try to assign each value to a row so I can easily write it then I will not have enough memory available. So I need to somehow compress these arrays. I may be able to combine multiple array values in one row, making it possible to fit all data in less that 128 rows. However, this will cover only one infrared remote control command and I need to store 8 of these codes in the EEPROM, which I don’t think I can fit.
So my next step was to take a look at the data and see what I can simplify. I started by plotting the pulse lengths on a graph, shown in the figure below:
The bars shown in red represent the time while the infrared carrier signal is on and the bars shown in blue represent the time while the carrier signal is off. These values correspond to the waveforms shown in the first figure above. This graph suggests that the information is encoded in two types of pulse lengths of carrier-off, a short pulse and a long pulse. The carrier-on pulses are all of similar length. The two very long pulses right at the beginning are the preamble used by receivers to tune the local oscillator and demodulator. They do not transmit command specific information, but I still need to record their length since I need to reconstruct them when driving the transmitter infrared LED.
My approach to compress these arrays of data is to compute a unit interval of time based on all the recorded pulse lengths, and then to express each pulse length in terms of this unit interval. Looking at the graph above I see that all the short pulses have similar values but are not equal, and all the long pulses have similar values but also are not equal. It also looks to me that the long pulses are three times longer than the short pulses. After doing some reading on the various encoding techniques used in infrared remote control protocols I realized that a good choice would be to always express the pulse lengths in an integer multiple of the shortest pulse. However, due to measurement errors the duration of the short pulse is not easy to determine. Here is the pulse table with values represented in the graph above:
The short pulses span values between 474us and 557us and the long pulses between 1611us and 1666us. So visually a good choice for unit interval would be 515us, the average short pulse length. The challenge was then to implement this “visual” choice into an algorithm executed by the MCU inside the PSoC5LP chip.
Here is the code that I wrote to determine the unit interval:
The code first calculates the minimum and average pulse width of carrier-on and carrier-off values from the arrays and then computes the unit interval. Then each pulse length is converted from microseconds into unit intervals and stored in another array. The resulted pulse lengths have now values of either 1 or 3, so the amount of data is significantly reduced. If I further convert these values into logic “1” and logic “0” bits I can fit them in one row of the EEPROM nonvolatile memory in a PsoC5LP chip.
This is where I am now with developing the code learning algorithm. Next step will be to write a code that would store the compressed pulse length values in a non-volatile EEPROM memory of the PSoC5LP chip and to read it back.
That’s it for now; I will come back with a new update as I get more work done.
Best Wishes,
Cosmin