An Engineer's Perspective

Category Archives: Demodulation

One field of communication and DSP that has always intrigued me is signal intelligence, the attempt to receive and decode an unknown signal. It’s an interesting puzzle that requires a wide variety of hardware, software, and analytical skills. I like to think that my research is, at least tangentially, a form of signal intelligence in that I’m attempting to use ultrasound signatures to determine what is happening inside the body. While receiving and interpreting ultrasound signals is interesting, I had a desire to look at more artificial, data bearing signals. I decided I would try to receive and decode the signal my garage door remote transmits to the base unit to open and close the door. In addition, I also wanted to create a device that would mimic my remote and be able to open the garage door on my command. This post will detail that attempt.

Remote Signal

The first task in this project required determining at what frequency my garage door remote operated. This was actually quite simple since the FCC ID# was easily visible. With a quick check of the FCC website, I was able to determine that the remote operated at 390 MHz. While not a super high frequency signal, it was beyond the bandwidth of my previous SDR. That SDR used an ADC with an integrated analog front end which limited its bandwidth to a few dozen MHz. So, partly driven by this project as well as a few other projects I am working on, I decided to design a new SDR with a wide bandwidth front end, and a high-resolution, high-speed ADC to allow for the reception of just these types of signals.

I plan to detail the design and construction of this new ADC board (along with a companion high-speed DAC board) in a later post. For now, I’ll just give a few of the critical details. In the image shown below, you can see the ADC on the left. This is a 14-Bit, 125 MSPS Analog Devices, AD9445 ADC with LVDS outputs. The low-jitter clock can be seen just below the ADC. To the right of the ADC is a Xilinx Spartan 3E chip. This is a big step down from the Virtex5 used in the previous post but given the costs associated with the Virtex5 (both the chip itself and the required PCB and assembly fees) I think it was well worth it. In addition, the Spartan3E can be programmed with the Xilinx ISE WebPACK without an additional license. As a student at the University of Minnesota, I currently have access to a full version of the ISE Design Suite, but at some point in the future I may not have this luxury so this was a big issue for me. Below the Spartan3E board there is the JTAG programming port, some LEDs, and a few inputs for clocks and triggers. Along the far right is the same USB module used in the 3D magnet localization project and allows me to quickly stream the data back to the computer.

The analog front end on this board consists only of a single RF transformer. This allows the passage of signals with frequency content well into the hundreds of MHz. I’m able to use the ADC in an under-sampling mode to still digitize these high frequency signals. For the purposes of this project, I created an IQ demodulator that looked at a ~250 KHz swath of bandwidth and streamed the complex baseband signal back to the computer. I hooked up a small whip antenna to collect the RF transmissions from the remote and then monitored at 15 MHz (the 390 MHz signal is in the 7th Nyquist zone of the ADC and, with aliasing, would appear at 15 MHz).

The plot below shows the envelope of the signal I received when I pressed the open/close button on the remote. The remote was positioned very close to the whip antenna to ensure reception.

I had been worried that perhaps the remote signal would have a very low SNR and make it difficult to decode, but that was not the case. The plot below focuses on the first burst of data.

It’s clear that the remote is using simply On-Off Keying to transmit 83 bits of data. In fact, while the open/close button is depressed, the remote continuously transmits two frames of data 83 bits long, separated by 100 ms. These two frames of data are labeled A and B in the first plot above. Closer inspection revealed that the bits are transmitted at an approximate data rate of 2000 bits per second.

To get an idea of how the codes change with each button press, I recorded a long data set where I repeatedly pressed the open/close button. The hexadecimal representation of those received codes is shown below with each row representing the full code received for that button press.

A few things are immediately obvious when looking at the above codes. The first frame appears to only use the numbers 8, 9, and 11 for each nibble. The second frame appears to only use the 2, 6, and 14 for each nibble. While the codes don’t appear to be completely random (e.g. the last byte of the first frame is always 128, and the first nibble of the second frame is always 14), to my eyes, there isn’t an easily discernible pattern in this small code sample. This makes sense since most modern garage door openers use a rolling code system that transmits a new random number with each button press. The main garage door unit and the remote are synchronized so the main unit knows which codes to expect. The main unit will not only look for the current code, but also the next hundred or so codes to ensure the remote and main unit do not fall out of alignment due to the remote being pressed while out of range.

I was happy with these results and the overall performance of the SDR in receiving and decoding the remote signal, however my final goal remained using these results to create a device capable of mimicking my remote and fooling the main unit into opening and closing. The garage system’s use of the rolling code made it impossible for me to predict codes into the future. I decided the best thing (only thing) I could do would be to take the remote out of range of the main unit and record the next dozen or so codes, creating a code library that I could then replay to the main unit to open and close the door. Before doing this, however, I needed to design a transmission module that could generate a OOK data stream with a 390 MHz carrier.

Transmission Module

The graphic below shows the board I ended up making to generate the needed RF signal. The signal generation starts with a voltage controlled oscillator (VCO) whose frequency can be tuned between approximately 350 MHz and 410 MHz (shown on the far left of the board with a potentiometer to control the frequency). The output of the VCO is fed to an RF switch whose output is connected to a whip antenna. The digital logic input of the RF switch is used to generate the on-off keying. In addition to the whip antenna output, I also included an SMA output to help with the debugging.

The first thing I needed to do with this board was set the potentiometer controlling the frequency to the right voltage to ensure the carrier is at 390 MHz. I used the debug output on the far right of the board to connect the VCO directly to my ADC board. I measured both the control voltage and the VCO frequency as recorded by the ADC to generate the plot shown below. This data was collected at the full sampling rate for a bandwidth of 62.5 MHz.

This plot demonstrates the aliasing present in under-sampling. What was in reality a monotonic increase in frequency, appears to first decrease then increase. Since I know what is happening I can correct for this aliasing and generate the correct frequency vs. voltage plot, as shown below.

We can see the VCO has an approximate 14 MHz/Volt sensitivity, meaning the potentiometer should be set to give a control voltage of about 3.5 volts.

One VCO related thing I found interesting was the sensitivity to temperature. I ran a quick experiment where I monitored the VCO frequency as I placed my finger on the case. The spectrogram below shows how quickly the frequency changes with just that small thermal influence.

The final step in the transmission module was generating the logic signal to control the RF switch. I felt the easiest method to create this signal would be with an FPGA. I essentially needed an SPI port which can handle a very large data word, the flexibility of an FPGA made this a breeze. The only issue I ran into was that the data rate of the remote is slightly slower than the 2k baud I initially thought. Upon closer inspection, the bit periods were about 504 us and the time between frames was more like 100.4 ms. With this small correction I was able to accurately mimic the pass band signal generated from the garage remote. The data below shows the remote data signal overlain with my synthesized signal as recorded by the SDR board.

The above graphic shows the first frame with the remote signal in blue and the synthesized signal in red. Over the 40 ms they stay nicely aligned. The graphic below shows the second frame comparison.

By the end of this frame there is a slight misalignment between the FPGA and the remote, but it does not appear to be significant.

So with all the components up and running and the library of codes built up, it was just a matter of connecting everything together in my garage and hoping for the best. I’ve posted a video of me testing out the system below. The FPGA is connected to the transmission module with a BNC cable. The red wire running off the transmission module is the whip antenna used to transmit the signal to the garage door opener above. The slide switches located along the right side of the FPGA control which code from the library is played out.

Thoughts on Garage Remote Security

Working through this project has caused me to reconsider how secure my garage is to potential intruders. There seem to be some very serious flaws with how the rolling codes are implemented. The rolling codes are meant to do two things; one, they should prevent someone from recording the transmitted signal and being able to replay that signal at will to open or close the garage door. Two, they should prevent someone from using a recorded code to predict future codes. I don’t know enough about the algorithms used to create the rolling codes to have an opinion on the latter issue, but from this brief look at how the remote behaves there appear to be some serious flaws with the former.

The original garage remotes had a series of dip switches that could be toggled to create a unique ID number that would identify each remote to its base unit. This would allow neighbors to have the same make and model of garage door opener without interfering with each other. The downside to this implementation is that an intruder only needs to know your dip switch settings to craft a signal capable of opening your garage. If the intruder didn’t have physical access to the remote, he or she could just record the remote transmission and replay this to gain access. To counter this weakness, rolling codes were introduced. With rolling codes, by the time you record the transmission, the code is already out of date and useless. Or at least it should be…

Look at how this remote behaves when the open/close button is pressed. As long as the button is depressed, both code frames are transmitted continuously, resulting in multiple transmissions of the current code for even brief button presses. Now imagine you’re an intruder with the capability to record and transmit codes in real-time (a system that could easily be constructed for less than $300…) and you want to break into my garage. You could wait for me to come home and activate my garage door opener. The moment I press the button my remote begins transmitting the first frame of the current code (let’s call this code number 100). Now your device detects the transmission at the same moment my main unit does and you both begin decoding the frame. After 50 ms both your device and the main unit have decoded and stored the first frame of code 100, now instead of just passively waiting for the second frame, your device begins actively transmitting random bits. Your device continues this transmission for the next 100 ms thereby disrupting the ability of the main unit to receive the second code and open the garage door. If the remote only transmitted a code one time, this would be the end of the story, the intruder would have managed to record frame 1 of code 100 and disrupted the proper operation of the overall system, but the security of the garage hasn’t been compromised. The intruder would just be able to create a nuisance and force me to get out and manually activate my garage door. However, this isn’t the case.

After the intruder disrupts the second frame of code 100, the remote will retransmit the entire code. On the remote’s second transmission of code 100, the intruder could reverse what he did previously. He could disrupt frame 1 while recording frame 2. The intruder now has the entirety of code 100, but the main garage door unit has been prevented from receiving the correct code. The intruder can continue to transmit random bits as long as it detects the remote is actively transmitting code 100.

As the person pressing the remote button, all I would notice is that the garage door did not respond to my remote. This happens to me all the time so I would not think too much of it, I would simply press the remote button again. Pressing the remote again would cause the transmission of the next code, code 101. And here is where the intruder would be able to cover his tracks. The intruder’s system could go through the exact same steps as before, recording frame 1, then frame 2 of code 101. At the end of the transmissions, the intruder would have both codes 100 and 101 and the main unit would still be waiting for code 100. Instead of just staying silent after the transmission of code 101, the intruder could immediately play out code 100 causing the garage door to open. I would think nothing of this whole experience and continue on as if nothing happened. The problem is that now the intruder’s system knows code 101 and the main garage unit is expecting code 101.

I can’t say I’m going to lose any sleep over the prospect of someone spoofing my garage door opener, but I’m also not going to store something valuable in my garage and expect the rolling code security to protect it.

Moving forward, I would like to spend some time looking into the algorithms used to generate the rolling codes to see how secure they are and if they have any vulnerabilities. I would imagine that encryption for garage doors has its own set of unique constraints if only because of the long time the system will be in use. I think most people have the same garage door opener for many years, possibly decades. So even a brute force attack that took three years to search through all the possible keys would be too weak. Once you cracked the code, the opener would most likely still be in use and vulnerable.

The previous GOES post dealt with the Low Rate Information Transmission (LRIT) data stream. There is another interesting data stream transmitted by the GOES satellite, that is the Emergency Managers Weather Information Network (EMWIN) data stream. This service streams a variety of weather related information, everything from terrestrial weather warnings and radar images, to space weather conditions. There are a variety of different dissemination techniques for the EMWIN messages. There is an internet feed available, terrestrial radio sources and of course the GOES satellite. Even within the GOES satellite constellation there are two separate methods for transmitting the EMWIN message. Until December 14th of this year GOES-West (aka GOES-11) will use a FSK transmission approach to transmit data with very little overheard (i.e. data is streamed continuously with no FEC), essentially a 9600 baud RS-232 link. After December 14th, GOES-West will begin transmitting its data with the same scheme as GOES-East (aka GOES-13), a 17970 Symbol/Sec Offset Quadrature Phase Shift Keying (OQPSK) modulation with heavy FEC and packetized data. In addition, there is a carrier frequency change from 1690.725 MHz for EMWIN-I to 1692.7 MHz for EMWIN-N. Below you can see the spectrum for the EMWIN-I signal. For reference, the FSK has a frequency separation of 3600 Hz. Each of the spectrum plots shown below span 100 KHz bandwidth.

Below, for comparison, is the spectrum of the EMWIN-N spectrum from GOES-13. It’s clear that there has been some filtering of the data pulses to contain the bandwidth of this signal.

The rest of this post will detail the demodulation and decoding of the EMWIN-N signal from the GOES-13 satellite. The data packet structure is the same as the structures used by the LRIT stream, so I’ll try to skip this material and just reference anyone who’s interested to my previous post on this topic.

Decision Directed Carrier Tracking

The table below is taken from a report by the Aerospace Company. This lays out all the parameters necessary for demodulating the EMWIN-N signal. Not only does the EMWIN signal share the same packet structure as the LRIT signal, it also shares the same forward error correction parameters. The Viterbi filter parameters, the RS parameters, as well as the randomization bits are identical between LRIT and EMWIN.

I chose to go a different route to recover the carrier for this data stream as compared to the LRIT data stream. Previously, I used a Costas loop to track the carrier on the BPSK signal. The costas loop for a BPSK signal is relatively straightforward. While there are implementations of the Costas loop available for the QPSK and OQPSK signals, I chose to use a decision directed tracking method.

There are two main steps to this implementation, first the decoder must determine the carrier frequency and phase, then the decoder must track this frequency and phase in time. Even though the transmitter in this case is a geostationary satellite and should have no doppler shifting, the tracking is still important. A phase error of just pi/4 can cause the decoder to produce garbage. This amount of phase error could come from numerous sources, the carrier frequency could be slightly off, the satellite may drift around, a local clock may heat up or cool down slightly changing the sampling frequency, etc… The point being, even though things should remain aligned, they won’t, and the tracking will account for this.

To initially lock onto the signal carrier, the decoder searches both carrier frequency and phase, evaluating the error rate in the first 50 ms of data (~900 Bits) for a chosen frequency, phase pair. The frequency, phase pair which results in the lowest (ideally zero) bit errors is chosen as the initial starting point for the decoder.

The bit errors over the 2D search space are shown below. I chose to search +-200 Hz of the specified carrier, evaluating 40 different phases between -pi and pi at each frequency. The blue streaks around -155 Hz represent no detected bit errors. At this frequency, there appear to be two phases (~0 and pi radians) which result in the best decoder performance.

The graphic below zooms in on the area outlined by the black box above. This search was performed with finer frequency and phase steps to increase the level of detail.

The zoomed in error map makes clear that for this brief time period, there are a relatively wide range of frequencies and phases which result in no bit errors. This isn’t surprising since we haven’t processed enough data to allow for errors due to small frequency offsets to manifest themselves. There has to be some sort of trade off between initial search time and precision. This search took only a few seconds but resulted in a frequency ambiguity of a few Hz and a phase ambiguity of a few tenths of a radian. This precision is sufficient since the decoder continues to track the signal throughout the demodulation process. For curiosities sake, I did perform a search with a much longer data record, 500 ms, over a smaller search space. The result of that search is shown below. This high precision search took many minutes to complete and is really unnecessary for this application. Even if we took the best frequency, phase pair from this extended search, without continually tracking, the demodulator would accumulator too much phase error within just a few seconds.

Based on the above analysis, I began the demodulation process with a carrier frequency of (1692.7e6 – 155.803) Hz, and a phase of -0.2 Radians. The actual retrieval of the bits is very straightforward. The real part is offset from the imaginary part by one half the symbol time and sampled every 1/17970 Seconds. I used an early-late timing scheme to ensure the sampling times remained correct.

I used a different process to track the phase during the demodulation than during the initial lock on procedure. I wanted to detect and correct any phase misalignment before bit errors occurred. To accomplish this, I processed the data in 90 ms batches. For each batch, I create a constellation map of the decoded symbols and recorded the average position of each symbol on the complex plane (i.e. the centroid of each symbol). Ideally, these centroid locations should be equally spaced at 45, 135, 225, and 315 degrees around the origin. Any phase error will shift the centroid locations off these ideals. I use the error between the measured centroid angles and the ideal to create a phase correction which is accounted for in the next batch. The figure below shows a constellation map from a number of different batches with the ideal centroid locations for each symbol identified.

Tracking the phase corrections throughout the decoding process gives us some idea of how close the initial estimate of the carrier frequency was to the observed carrier frequency. The phase correction scheme used is similar to a proportional controller, any frequency offset will show up as a constant trend in the phase correction. The figure below shows the applied phase corrections, with a very obvious trend.

The tracking scheme applied ~400 radians of phase over ~600 seconds, giving a frequency of about 0.1 Hz (400/600/(2*pi)). Which means the initial guess was reasonably accurate. It also means that the decoder would have accumulated pi/4 radians of phase error in just 1.25 seconds if left uncorrected.

When I initially implemented the early-late timing scheme, I used a single precision number in one of my accumulators. In most of my day-to-day calculations, single precision is more than adequate (often I’m processing 12 bit ADC data). However, when used in the accumulator of the early-late algorithm it resulted in the following constellation map (same data as the previous constellation map).

Clearly a horrific decoding. Here’s what happened. This data represents a few seconds worth of collections, so millions of samples. The accumulator was keeping track of the sampling location of the next bit, this has both an integer part and a fractional part. As the integer part grew larger and larger, the ability to represent the fractional part decreased. Eventually the resolution of the fractional part grew so poor that it resulted in a complete loss of timing information. The quick fix was moving to a double precision accumulator. A better fix would have been to separate the integer and fractional part of the accumulator, thereby ensuring the resolution of the fractional component was independent of the integer size.

Once the symbols have been decoded, they must be converted to their two bit representation. I used the mapping:

+45 degrees -> 01

+135 degrees -> 00

-135 degrees -> 10

-45 degrees -> 11

The OQPSK allows the 17970 Symbols/Sec to represent a 35940 Bit/Sec data stream. The 35940 Bit/Sec data stream is run through the Viterbi decoder which brings the data rate back down to 17970 Bits/Sec. The decoded bits do not represent the data, instead they have an additional layer of encoding, where a bit transition represents a “1” bit, and no transition represents a “0” bit. This is a so-called Non-Return-to-Zero Mark (NRZ-M) encoding.

After removing the NRZ-M encoding, the bit stream is in the same format as the LRIT bit stream. It is encapsulated in CADUs, VCDUs, M_PDUs, and finally CP_PDUs. Unlike the LRIT, the EMWIN-N doesn’t rely on different APID to separate data. Instead there are just two VCDU packets transmitted, a fill packet (VCID = 63) and a data packet (VCID = 13).

The data is actually relatively straightforward to retrieve. It is a continuous stream of data contained in the data payload of the CP_PDU packets. The data stream is broken up into 1116 byte packets, each with 12 bytes of consecutive zeros serving as the alignment word, followed by an 80 byte header, and 1024 byte data payload. An example header is shown below:

/PFHADT45US.TXT/PN 3 /PT 3 /CS 11343 /FD9/24/2010 8:37:34 PM

The “/PFHADT45US.TXT” string represents the file name. The “/PN 3 /PT 3” string means that this is the third packet in a file made up of 3 packets. These are the relevant field for retrieving the data from the packets.

The data contained in the payload can be written directly to the file without any intermediate steps. This allows for very easy processing of the zip, gif, and jpg files. In the files associated with this post, I’ve included a script which will search the entire bitstream for files of a specific type, and write these files to the disk.

The following shows some of the data contained in the decoded EMWIN-N data stream. Unlike the LRIT images which contain various records explaining each image, the EMWIN-N images come pretty much as is, so you’re guess about what each image represents is as good as mine. If anyone knows of a place which details the naming convention please let me know.

JPEGs

This was the first full image contained in the data set.

There are a number of images like the one below, each focused on a different part of the country.

GIFs

There were only two gif’s present in the data set, each looked like a contour map of something.

TXTs

The vast majority of the data packets are either text files, or zipped text files. These text files give weather reports for every part of the country as well as other miscellaneous information. The most interesting report I found was a space weather report, shown below and can be downloaded here.

ZIS

The final data type transmitted through EMWIN is called ZIS, but is actually just a zip file. All the ZIS files I’ve looked at contain only text files.

M-Files and Data

I’ve organized the M-Files into three separate folders. One folder contains the code needed to demodulate the data into the OQPSK symbols. Another folder contains code to convert the symbols into the CP_PDU packets. The final folder contains the code required to retrieve individual files from the EMWIN-N data stream. I’ve included most of the binary data, but if you want to regenerate any of the other data you should only have to change a few file name declarations. The files can be downloaded here.