Throughout this lab and future ones, you may reference the tutorial on this page as needed.

Lab Objectives
  • 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.
  • Implement Zadoff-Chu sequence-based frame synchronization.
  • (Optional) Implement symbol synchronization as an alternative to the upsampled cross-correlation.
  • (Optional) Implement frequency synchronization when transmitting between two separate Pluto SDRs.
  • 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.


Introduction

In this lab, you’ll be implementing end-to-end digital communication using the Pluto SDRs via the RemoteRF platform. You’ll only need to access a single Pluto at any given time, as you’ll 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. If you encounter any bugs or issues along the way, please post them on Piazza, as this will be helpful to us in the long-term. I hope you enjoy this opportunity to apply many concepts from class on SDRs.

Perhaps you will want to begin by importing the Python module ece230b 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 ece230b 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. Use a sampling rate of 1 MSPS, and thus the number of samples per symbol should be 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 905–925 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: 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. Plot the real and imaginary parts of the matched filter output.

Part IV: Frame Synchronization

You’ll notice 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, as discussed in class. You’ll 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 signal (which was cyclically transmitted). We only want to extract one copy of the transmitted signal. Prepend to your transmitted symbols a Zadoff-Chu sequence to help us locate the transmitted signal. Assume that this sequence is known to the receiver. Given our received signal is upsampled by a factor of 10 samples per symbol, the receiver can either correlate with the Zadoff-Chu symbols (one out of every ten samples) or correlate with a pulse-shaped version of those symbols. Perform frame synchronization using one (or both) of these methods and extract a single copy of the transmitted signal. Plot the magnitude of the cross-correlation output during frame synchronization.

Bonus A: Symbol Synchronization

In Part IV, we circumvented the need for symbol synchronization by correlating our upsampled receive signal with our Zadoff-Chu sequence (or a pulse-shaped version of such). Alternatively, you could first perform symbol synchronization, downsample the received signal, and then correlate with the Zadoff-Chu sequence. Complete this if you’re interested in bonus points.

Bonus B: Frequency Synchronization

By transmitting and receiving with a single Pluto, we are not subjected to severe carrier frequency offset and there is no significant need for frequency synchronization. This is not necessarily the case when transmitting from one Pluto to another. For bonus points, transmit from one Pluto to another and perform frequency synchronization. Perhaps you can even use your code from Lab #1 to confirm whether or not your CFO estimation is accurate. Note that you may use a single Python script to do all of this by simply creating two separate SDR objects (each having its own dedicated reservation). I hope some of you tackle this, as I would love to see how things turn out.

Part V: 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. The channel across our narrowband transmission is approximately frequency-flat and thus causes a scaling and rotation of our transmitted symbols. Plot the real and imaginary components of each received symbol on the complex plane, and then overlay the originally transmitted symbols. You should be able to observe the effects of the channel.

To undo these effects, we need to employ channel estimation and equalization. To estimate the channel, insert 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. The receiver knows these pilots and their locations and can thus use them to estimate the effects of the channel, as discussed in class. Perform such channel estimation and then use this channel estimate to equalize your received signal. 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 symbol detection and report your symbol error rate (SER).

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 will likely 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? Pretty cool huh?