Skip to content

Scripts based on gnuradio and custom python code to generate, transmit, receive and decode a 2x2 single-carrier MIMO waveform.

Notifications You must be signed in to change notification settings

rmerz/mimo-sc-waveform

Repository files navigation

Introduction

This directory contains several scripts based on gnuradio and custom python code to generate, transmit, receive and decode a 2x2 single-carrier MIMO waveform.

These scripts can either use a simulated channel, use two USRP x3x0 as transmitter and receiver, or use an IQ trace captured by a TSMW.

The MIMO waveform requires a patched version of gnuradio for the frequency and timing clock recovery blocks

List of scripts

  • generate_symbols.py: creates a series measurement symbols (should be eventually replaced by custom gnuradio modules)
  • generate_waveform.py: creates a pulse-shaped waveform (e.g. upsampled); can take a binary file of symbols as input or use a BPSK/QPSK constellation
  • transmit_waveform_synthetic_channel.py: simulates a (baseband) channel; takes the output of generate_waveform.py
  • transmit_symbols_synthetic_channel.py: combine pulse-shaping and baseband channel. Designed to directly take output from generate_symbols.py.
  • transmit_symbols_x300.py: transmits symbol sequences generated by generate_symbols.py. Does not take input from generate_waveform.py.
  • receive_waveform.py: receives a waveform (generated via generate_waveform.py, transmit_waveform_synthetic_channel.py or from a USRP); can directly decode BPSK/QPSK symbols or write the symbols to a binary file; performs frequency and timing recovery
  • receive_symbols.py: performs frame recovery, channel estimation and symbol decoding

Notes when using a real radio

For the frequency offset and timing offset compensation, it is critical to bring the input signal at a reasonable level. Therefore some level of gain control is necessary, whether this is automatic or manual.

Examples of 2x2 MIMO setup

2x2 MIMO setup with independent processing of each stream

By default, the first stream uses pilot ID -1 and the second stream uses pilot ID -2 (or 15, 14, respectively). This example decodes each stream independently

  • ./generate_symbols.py -r 7 -m 2
  • ./generate_waveform.py -l measurement_symbols_0.bin -i 0 && ./generate_waveform.py -l measurement_symbols_1.bin -i 1
  • ./transmit_waveform_synthetic_channel.py -m -f 0.2 s_pulse_shaped_signal_sps4_0.bin s_pulse_shaped_signal_sps4_1.bin
  • ./receive_Nx2_waveform.py -f rx_channel_s_pulse_shaped_signal_sps4_0.bin rx_channel_s_pulse_shaped_signal_sps4_1.bin --to-file rx_0.bin rx_1.bin
  • ./receive_symbols.py rx_0.bin --sync -c -i -1 -2
  • ./receive_symbols.py rx_1.bin --sync -c -i -2 -1

2x2 MIMO setup with independent processing of each stream (no frequency or timing offset)

Only the steps different from the previous example are shown: this example clearly shows the canonical 2x2 MIMO channel matrix used in transmit_waveform_synthetic_channel.py

  • ./transmit_waveform_synthetic_channel.py -m s_pulse_shaped_signal_sps4_0.bin s_pulse_shaped_signal_sps4_1.bin
  • ./receive_Nx2_waveform.py rx_channel_s_pulse_shaped_signal_sps4_0.bin rx_channel_s_pulse_shaped_signal_sps4_1.bin --to-file rx_0.bin rx_1.bin
  • ./receive_symbols.py rx_0.bin rx_1.bin --sync -c -i -1 -2

2x2 MIMO setup with LS processing

The system will break with a noise voltage reaching 0.5. With a noise voltage of 0.25, frame synchronization can function successfully.

  • ./transmit_waveform_synthetic_channel.py -m -f 0.2 -t 1.01 -v 0.1 s_pulse_shaped_signal_sps4_0.bin s_pulse_shaped_signal_sps4_1.bin
  • ./receive_Nx2_waveform.py -f rx_channel_s_pulse_shaped_signal_sps4_0.bin rx_channel_s_pulse_shaped_signal_sps4_1.bin --to-file rx_0.bin rx_1.bin --plot-offset-correction
  • ./receive_symbols.py rx_0.bin rx_1.bin --sync -c -i -1 -2

Here is another example that allows for bypassing generate_waveform.py

  • ./generate_symbols.py -r 7 -m 2
  • ./transmit_symbols_synthetic_channel.py measurement_symbols_0.bin measurement_symbols_1.bin -m -f 0.2 -t 1.0001 -v 0.1
  • ./receive_Nx2_waveform.py -f rx_channel_sps4_measurement_symbols_0.bin rx_channel_sps4_measurement_symbols_1.bin --to-file rx_0.bin rx_1.bin --plot-offset-correction
  • ./receive_symbols.py rx_0.bin rx_1.bin --sync -c -i -1 -2

Usage with USRP x300/x310

In this case, generate_symbols.py is first used to generate symbol sequences. Pulse-shaping is then performed directly before transmission with the x300/x310.

  • ./generate_symbols.py -r 7 -m 2
  • TBD

Reception with a R&S TSMW with K1 interface

The workflow needs to convert the samples captured with the TSMW to a binary file that can be loaded into gnuradio for processing with receive_Nx2_waveform.py. For instance, using the read_stream_iq_trace.py utility (this assumes that samples were captured with stream_iq.exe and converted via extract_iq.exe):

NUM=5 && ./read_stream_iq_trace.py -a ~/host/20150610_outdoor_test/iq_data_"$NUM".bin_channel_0.dat ~/host/20150610_outdoor_test/iq_data_"$NUM".bin_channel_1.dat --to-file ../../../sdr-utils.git/gnuradio/mimo_single_carrier_waveform/rx_samples_0.bin ../../../sdr-utils.git/gnuradio/mimo_single_carrier_waveform/rx_samples_1.bin --plot_spectral --gain 30 && echo $NUM

About

Scripts based on gnuradio and custom python code to generate, transmit, receive and decode a 2x2 single-carrier MIMO waveform.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages