ECE 132A: Lab 3
Due: Friday, March 6, 2026 at 11:59 PM via Gradescope
Throughout this lab and future ones, you may reference the tutorial on this page as needed.
- Implement a complete digital communication system using Pluto SDRs via the RemoteRF platform.
- Generate and pulse-shape M-QAM symbols, set transmit parameters, and transmit the waveform.
- Configure receiver parameters, capture a received signal, and apply a matched filter.
- Estimate and equalize the channel using pilots and perform symbol detection.
- Investigate the relationship between transmit gain and symbol-error rate (SER).
- Compare the SER performance with and without a matched filter to understand its benefits.
- (Optional) Implement Zadoff-Chu sequence-based frame synchronization.
- (Optional) Implement frequency synchronization when communicating between two separate Pluto SDRs.
Introduction
In this lab, you will be implementing an end-to-end digital communication system using the Pluto SDRs via the RemoteRF platform. You will implement virtually all of the core concepts we have covered since first introducing digital communication techniques.
By default, you will only need to access a single Pluto at any given time, as you will be transmitting and receiving from the same device. If you wish to attempt to transmit from one Pluto and receive from another, you may do so for bonus points. Note that this may require carrier frequency synchronization to account for the carrier frequency offset (CFO) between two Plutos.
In completing this lab, it is advised that you do as much development and testing without the SDRs as possible. You can also consider saving received signals for offline processing and debugging. These are engineering skills I hope you develop in completing these labs, along with implementing core concepts from class. As with all labs, you are permitted and encouraged to employ creative liberty in conducting this exercise, especially where you feel the provided instructions are not complete or exhaustive.
You will likely want to begin this lab by creating a new Python script and importing the Python module ece132a that you created in Lab 2.
This module and its functions can be imported into your main script (e.g., main.py) using the following.
from ece132a import *Put together a lab report with your results from this lab and attach your code. Provide any commentary and explanation where you see fit. Upload your lab report as a PDF to Gradescope.
Part I: The Transmitter
Begin by generating random -QAM symbols, drawn uniformly from a constellation with unit average energy per symbol, .
Let’s start with 64-QAM.
Optionally, insert zeros before or after your sequence of symbols; this will make it a bit easier to recognize your signal in the time domain.
Then, perform pulse shaping at the transmitter using a root raised cosine (RRC) filter at a symbol rate of symbols per second, meaning symbols are sent every 10 microseconds.
Make sure your RRC filter has been normalized to have unit energy.
Use a sampling rate of 1 MSPS, and thus the number of samples per symbol should be 10, i.e., sps = 10.
Use a rolloff factor of .
Use a cyclic transmit buffer, and set the transmit gain to dB.
Plot the real and imaginary parts of the transmit signal, zooming in so your pulse-shaped symbols can be observed clearly.
Transmit this pulse-shaped waveform from the Pluto at a carrier frequency of your choice between 900–930 MHz using sdr.tx().
Part II: The Receiver
Set the receiver’s carrier frequency to that matching the transmitter.
Set the receiver’s gain control to "manual", and use a gain of 40 dB.
Set the receive buffer size to samples.
Take a receive capture with the Pluto using sdr.rx().
Plot the real and imaginary parts of the received signal, zooming in so the received pulse-shaped waveform can be observed clearly.
Part III: Timing Synchronization
You will notice that your received signal is not perfectly time-aligned with the transmit signal.
In other words, the received copy of the transmit signal has some time offset that needs to be accounted for at the receiver.
Correcting for this offset is the problem of timing synchronization.
You will also notice that you have received multiple copies of your transmitted signal, due to the size of your receive buffer relative to the length of the transmit signal (which was cyclically transmitted).
We only want to extract a single copy of the transmitted signal.
Albeit impractical, for the sake of this lab, we will solve this by performing a cross-correlation between the transmit signal and receive signal to locate and extract only a single copy of the receive signal.
You need to use the cross-correlation to determine the timing offset, and then return the L samples following this offset, with L the length of the transmit signal.
Plot the magnitude of the cross-correlation output during frame synchronization.
In practical systems, the receiver does not know the transmitted signal, so the above approach is not practically viable.
If the receiver knows part of the transmit signal, however, it can indeed use the aforementioned approach—this is how practical systems solve this problem.
They do so by prepending a known sequence at the transmitter that the receiver can cross-correlate with to locate the transmit signal.
Desirable sequences for such purposes are Zadoff-Chu sequences, since they exhibit good correlation properties.
Prepend a Zadoff-Chu sequence to your symbols before pulse shaping at the transmitter, and assume that this sequence is known to the receiver.
Given our received signal is upsampled by a factor of sps samples per symbol, the receiver can either correlate with the Zadoff-Chu symbols (one out of every sps received samples) or correlate with a pulse-shaped version of those Zadoff-Chu symbols.
Complete this if you are interested in bonus points.
By transmitting and receiving with a single Pluto, we are not subjected to severe carrier frequency offset and there little to no need for frequency synchronization. This is not necessarily the case when transmitting from one Pluto to another, since there may exist some carrier frequency offset (CFO), as we saw in Lab #1. For bonus points, transmit from one Pluto to another and perform frequency synchronization. One simple way is to use the technique from Lab #1 to estimate the CFO by transmitting and receiving a complex exponential. There are more sophisticated techniques, but I will leave it up to you to investigate them. One simple technique that Wi-Fi employs is based on a short training field (STF) and long training field (LTF) for coarse and fine CFO estimation. Perhaps you can look it up and implement it. I hope some of you tackle this, as I would love to see how things turn out. Complete this if you are interested in bonus points.
Part IV: Matched Filter
Pass the received signal through a filter matched to the transmitter’s pulse shape. Plot the impulse response of the effective pulse shape to confirm it indeed satisfies the Nyquist ISI criterion. It should also have a peak value of 1, assuming the transmit pulse shape and matched filter have each been normalized to have unit energy. Plot the real and imaginary parts of the matched filter output.
Part V: Channel Estimation, Channel Equalization, and Symbol Detection
Sample the extracted portion of the received signal from Part IV every seconds to get your received symbols. If everything has gone according to plan, these received symbols contain the transmitted symbols plus AWGN, with little to no ISI. If you plot the received symbols on the complex plane, you will notice they appear scaled and rotated, when compared to the originally transmitted symbols. This scaling and rotation is caused by the channel between the transmitter and receiver and needs to be corrected. First, the complex gain by which the transmitted signal has been scaled and rotated needs to be estimated—this is called channel estimation. To estimate the channel, insert known symbols (called pilots) into your transmitted signal wherever you’d like: before or after your data or interleaved within the data. For the pilots, you can simply use randomly drawn M-QAM symbols. Assume the receiver knows these pilots and their locations and can thus use them to estimate the complex gain of the channel. Perform channel estimation and then use this channel estimate to equalize your received signal by dividing it by this estimated complex gain. Plot the real and imaginary components of each received symbol on the complex plane after equalization, and then overlay the originally transmitted symbols. Hopefully they align well now. Perform maximum likelihood symbol detection and report your symbol-error rate (SER) in the title of your plot.
Part VI: Symbol-Error Rate Curves
Vary the transmit gain from dB to dB and plot the corresponding SER for each. Do not exceed dB. Repeat this for 256-QAM and include it on the same plot as 64-QAM. The y-axis should be in log-scale and the x-axis should be transmit gain (in dB). Note that, in order to get meaningful values of SER, you may need to average across multiple transmissions.
Part VII: What Does a Matched Filter Buy Us?
Finally, suppose instead of a root raised cosine filter, we use a raised cosine filter at the transmitter, without a matched filter at the receiver. We still perform all of the aforementioned synchronization and equalization procedures. Repeat Part VI, overlaying your lines atop those from Part VI on a single figure. Does the matched filter seem to improve SER? By how much?