Tag Archives: Modulation

Garage Door Hack

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.

Software Defined Radio SDR ADC Board

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.

Garage Door Remote Signal

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.

Garage Door Remote Signal

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.

Consecutive Remote CodesA 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.

OOK Transmission ModuleThe 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.

Voltage Controlled Oscillator VCO

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.

Voltage Controlled Oscillator VCO

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.

Frequency Shift

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.

Remote Code vs. FPGA Code

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.

Remote Code vs. FPGA Code

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.





Ultrasonic Communications Link

After finishing the Software Defined Radio project, I really wanted to play around with the other side of the data chain, mainly, signal generation. I’m by no means an RF designer, I know a little about antennas and transmission lines and even if I could design a transmitter I’m not at all clear about all the laws and regulations surrounding amateur RF transmissions. So instead of an electromagnetic based transmitter, I decided to stay more in my comfort zone and implement an ultrasound based communications link. I wanted to create a signal that could be amplified and played on an ultrasound transducer, transmitted through water, and received by a second transducer for demodulation. Specifically, I wanted to use an FPGA to take in a baseband audio signal, modulate it onto a passband signal and then use a digital-to-analog converter to synthesize the signal. This post will describe the system I ended up using and some of the results and data I collected.

System Overview

I again chose to use the Virtex 5 as the FPGA. Two main reasons, the first was the gigabit ethernet connection available with this evaluation board. I’ve used a number of USB modules to transfer data to and from an FPGA, and there is no real comparison to the flexibility and speed offered by the GbE connection. The other reason was an old prototype board made by a labmate of mine, Dalong Liu. He was investigating an arbitrary waveform generator awhile ago and created a prototype board for the Max5858. There is actually a third reason and that’s the DSP48 slices. These allow for very efficient implementation of many DSP operations. The virtex-5 sx50t which I used here has 288 DSP48 slices. For a single channel application such as this, this many DSP48 slices is more than enough.

The Max5858 is a dual-channel, 300 MHz, 10-bit DAC . It is a fairly sophisticated DAC, it allows for 2x, and 4x onboard interpolation and can multiplex the channels to save on IO pins. I used the DAC in the multiplexed configuration with 4x interpolation enabled. This allowed me to clock data into the DAC at 50 MHz while still sampling the output at 200 MHz. The output was fed into a linear amplifier and sent to a high power ultrasound transducer with a center frequency of 2.5 MHz. This was sent across a water tank to a hydrophone that was connected to the SDR system described in the previous post.

You can see the water tank setup below. The transmitting transducer is highlighted in blue and the hydrophone is highlighted in green. These were spaced about 20 to 30 centimeters apart.
Transmit and Receive Tank Setup

Data Download

The first issue in this system implementation is just getting the data down to the FPGA. I’m dealing with many different data rates. There is the rate at which data is generated, the rate at which data is transferred, and the rate at which data is played out. If the rate at which data is generated does not match the rate at which data is played out, then some decimation or interpolation will be required. Even if the rates are supposed to be equal, they will almost certainly not be EXACTLY equal. This can cause you to, eventually, gain or lose a sample unexpectedly. This is a major issue in high speed serial links as well.

In order to deal with this issue, I created a 32K FIFO on the FPGA. This FIFO took in 16 bit data from the CPU on one side, and dispensed the data to the modulation cores on the other. The data was dispensed at a software adjustable rate depending on how the data was created. For most of the results I present here, I used a 25 ksps or a 50 ksps data rate.

To begin, I would allow the FIFO to fill with a thousand samples and then enable the modulation core to begin removing samples from the FIFO. I separated occupancy of the FIFO into a number of zones, an underflow warning zone, an all clear zone, and an overflow warning zone. As the occupancy transitioned these zones, a UDP packet would be sent to the CPU alerting to this transition. These packets allowed the CPU to perform its own flow control. So once the modulation core had removed enough samples to move the FIFO from the all clear zone to the underflow warning zone, a message would be sent back to the CPU and the CPU would stream additional data down to the FPGA to push it back into the all clear zone.

I was fairly generous in the limits of these zones. Latency wasn’t a big issue for me here so I was more than willing to pad the zones to ease the response time needed by the CPU. I ended up calling anything under 1024 samples the underflow warning zone, and if I had only 1024 free spaces left in the FIFO, I would call this my overflow warning zone, everything else was the all clear zone. The figure below shows the FIFO arrangement along with the UDP packets transmitted at each transition. In the extreme case that I actually did suffer a buffer underflow or overflow, I would transmit this information back to the CPU as well. Though in practice this never happened.

FIFO Diagram with status updates

This scheme worked very well and was able to stream data down to the FPGA continuously. For these experiments I used wav files and would have a server just wait for the request for data packet before transmitting down the next 1600 samples. If I were to incorporate a live signal source such as a microphone I would need to add some additional flow control on the host side, but the FPGA side could remain untouched.

AM Modulation

AM modulation is relatively straightforward to implement on the FPGA. A diagram of the system is shown below along with the data types and widths I used at each stage. The generic form of an AM modulation signal is: (0.5 + m(t))*sin(2*pi*fc), where m(t) is the message signal. I was able to save myself the bother of adding my message signal onto a constant 0.5 by using the trick that you can convert a two’s complement number (which my message was stored as) into an offset binary number by just inverting the most significant bit. This offset binary signal is then multiplied with a carrier wave generated by a Xilinx DDS core. I added one addition scaling step at the output so I could easily vary the amplitude of the signal.

FPGA AM Modulation Implementation

To test this AM modulating system I connected the DAC output directly to the ADC on the SDR, and instead of decimating and retrieving the IQ data as I normally do, I sampled at 20 MHz and streamed the data directly back to the computer for analysis.

Below you can see a Middle C tone (~261.6 Hz) modulated onto a 1 MHz carrier. I believe for this particular test I used about 95% modulation.

1 MHz Carrier Modulated with a Middle C Tone

I sampled the envelope of this signal at 25 ksps and below you can see the result of this quantization. The envelope level only changes every 40 us resulting in the staircase appearance of the signal.

Quantized AM Envelope

Below you can see the spectrum centered around the carrier, with the single frequency sidebands on either side.

AM Spectrum at Carrier

Of course, sampling any signal introduces copies of the spectrum at integer multiples of the sampling frequency. In the spectrum below you can see the replicated spectrums at 25 KHz intervals. This is a sample and hold scheme, which should attenuate the spectral images in a sinc like manner. You can see this in the attenuated images the further you move away from the carrier frequency.

Images due to Sampling the Envelope

The close up of the first replica shows what we would expect, both sidebands without a carrier. What’s really needed here is a final bandpass filter on the output to pass only the carrier and sidebands and eliminate all the spectral images.

First Image

This simple test verified that the system was work as expected and I moved onto implementing the FM modulator.

FM Modulation

I’m essentially using a direct FM generation technique to create the FM signal. The amplitude of the incoming signal directly modulates the carrier frequency. The nice thing about doing this in the digital realm is that I have complete control over the frequency deviation. I am not limited by the linear range of a varactor diode to control the carrier frequency.

You can see in the system diagram below, I scale the incoming audio signal to directly control the frequency deviation of the FM modulation. The numerically controlled oscillator is driven at 50 MHz with a 32 bit frequency word. This introduces a frequency scaling of 50e6/2^32 (~0.0116) on the incoming signal. A maximum amplitude signal (+-32767) would create a frequency deviation about the carrier of only ~381 Hz. This is relatively small. The scaling factor between the FIFO and the numerically controlled oscillator allows this frequency deviation value to be increased at my discretion. The output of this multiplier is added on to the static carrier frequency to form the input frequency word to the oscillator. Just like the AM modulator,  the data stream is run through one last scaling unit to allow control over the output amplitude before being presented to the DAC.

FPGA FM Modulation Implementation

The design philosophy behind both the AM and the FM modulator is that the host should not have to modify its data based on the type of modulation performed on the FPGA. The host can stream the 16 bit, signed data down to the FPGA in the same manner for both FM and AM modulation. This ability allowed me to test the FM modulator with the same data as the AM modulator, the Middle C tone.

Below you can see the spectrum for a the Middle C tone with a modulation index of 5.8 (i.e. the frequency deviation divided by the sinusoidal message frequency). The spectrum of an FM signal modulated by a sinusoid has a close form solution which consists of a summation of sinusoids weighted by bessel functions of the first kind. I’ve placed black dots on the spectrums below that show the ideal magnitude of these spectral components based on the modulation index used.

FM Spectrum Sinusoid, Modulation Index 5.8

As we increase the modulation index, the bandwidth used by the system increases. There is a very simple way to estimate the bandwidth used by an FM signal, it’s called Carson’s Rule. This says that the bandwidth of an FM signal can be approximated by the expression 2(Fd + Fm) where Fd is the frequency deviation and Fm is the maximum frequency content in the message signal. In the previous case, the frequency deviation was approximately 1,526 Hz which, according to Carson’s rule would give a bandwidth of about 3.6 KHz. For the case below we would expect a bandwidth of twice that, 7.2 Khz. Keep in mind that these bandwidths include both the upper and the lower sidebands, while these plots show only the upper sidebands. It’s clear that while Carson’s rule correctly estimates where the power is contained, there are significantly spectral components outside this bandwidth.

FM Spectrum Sinusoid, Modulation Index 11.6


The overall system ended up working quite nicely. I was able to transmit voice and music with both AM and FM. It was a bit of a shock after I set everything up and turned on the amplifier to hear my own voice coming out of the speakers on the receivers. I was not expecting everything to work on the first try. I ended up testing both voice and music transmissions. All results here used a 3.5 MHz center frequency for the modulation. I recorded my own voice for the voice transmissions and used a song from a Flaming Lips CD I had laying around for the music.

Voice Transmission

The voice transmission consisted of me saying, “This is a test, 1, 2, 3 ,4 over.” The initial tests consisted of a simple loopback test to guage to the quality of the direct connection. I tested carrier frequencies from 1 Mhz to 10 MHz and was able to hear no difference in performance between any of the carriers.  So I then moved to the real thing, transmitting the audio through the ultrasound transducers.

The figure below shows the demodulated signal received on the hydrophone. The demodulation procedure was very straightforward. I used Matlab to first find the envelope of the signal, isolated the segment corresponding to my voice and removed the D.C. bias. This can be performed with a single line of Matlab code: Audio = detrend(abs(hilbert(Signal))); Here Signal contains the modulated voice, and Audio is the demodulated audio signal shown below. You can listen to the demodulated signal AM signal here.

AM Voice DemodulationAs I explain in the SDR post, the data is collected as IQ baseband. This is kind of interesting for an AM signal, since if all frequencies were exactly correct, we would demodulate the AM signal simply through the IQ demodulation. The AM modulation process multiplies a message signal by a carrier, just like the IQ process multiplies the incoming signal by a carrier. If the modulation carrier and the IQ carrier were at the exact same frequency, they would cancel each other out (minus some dc bias term due to any phase different). However, as you can see in the figure below, the IQ data still has a sinusoidal modulation, even though the IQ demodulator was tuned to the same frequency as the AM modulator. Why is this? Because the oscillators used to generator the AM signal and the IQ signal are not perfect. Theses tiny differences lead to the sinusoidal modulation seen here. The red represents the real part of the signal and the green represents the imaginary.

IQ Voice SignalThe figure below is just a close up few of the IQ data. You can see that the two frequencies are not off by much, only about 11 to 12 Hz.

Close Up IQ Voice SignalAfter the success of the AM modulation I was anxious to try out the FM modulation. Here again, the demodulation was done with Matlab. I used what amounts to the following line of code to demodulate the signal, Audio  = diff( unwrap( atan2( imag(Signal), real(Signal) ) ) ); This uses the atan2 function to calculate the angle of the frequency phasor. I remove the 2 pi discontinuities with the unwrap function, and then isolate the message signal with the diff command (i.e. takes the difference between neighboring elements in the series). Below you can see the demodulated FM signal and you can listen to that signal here.

Demodulated FM Voice Signal

For those who are interested in playing around with the demodulation here are the modulated AM Voice and FM Voice wav files as received by the hydrophone.

Music Transmission

The voice transmissions were nice and I was very happy they worked, but it didn’t provide a very vibrant signal to test the quality of the link, for that I relied on some music. I band limited the music to 5 KHz and setup the CPU data server to stream the music continuously down to the FPGA for easy testing.

Below you can see the received spectrum for the AM signal. You can seen a nice peak at the carrier with the audio contained nicely within +-5 KHz. You can listen to a segment of this audio here.

AM Music Spectrum

The final test I did was to use the FM modulator to transmit the music. For this I used a modulation scaling factor of 8. This scaling factor gives a max frequency deviation of 3 KHz for a maximum amplitude signal. You can listen to the demodulated FM signal here.

For all the transmission tests attempted, the audio quality was so nice I really wished I had a larger tank and a more dynamic environment to test out the communications link. I think it would be frowned upon if I brought the FPGAs and transducers over to the campus natatorium, so I tried to create my own forms of interference.

The first thing I did was to physically remove the hydrophone. You can listen to that here. Obviously, once the hydrophone was removed we lost all transmission, but when it was placed back in you begin to hear the audio again.

The other thing I tried was creating bubbles between the source transducer and the hydrophone. I wasn’t able to create a wall of bubbles, but I was able to create a decent stream. You can really hear the effect these had on the audio quality, FM Music with Bubbles

Future Work

I would really like to try and expand this communications link to incorporate data transfer. I’d like to explore some spread spectrum modulation techniques on the FPGA. This FPGA has a lot of reserve power so I could potentially implement some DSP intensive algorithms. This sort of a setup could be a challenge at high data rates since the ultrasound will bounce around for awhile allowing for significant multipath interference.