-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathofdm_hardware_correct.py
More file actions
152 lines (119 loc) · 5.57 KB
/
ofdm_hardware_correct.py
File metadata and controls
152 lines (119 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""This script contains code to decode a received OFDM signal.
The signals we used to test this algorithm are generated in
generate_ofdm.py (BPSK signals). The signals were transmitted using Universal
Sofware Radio Peripherals (USRPs) with the following settings:
- Samp Rate (Sps): 6e6
- Ch0Center Freq (Hz): 2.454e9
- Tx Gain (dB): 80
Please note that the gain settings are dependent on the environment and may
need to be changed for best results.
Authors: Annie Ku and Ariana Olson
Usage:
- Generate and OFDM signal with generate_ofdm.py. See the documentation in
these file for details. A binary file that can be transmitted over USRP
is generated, along with a .npz file containing signal components in
numpy arrays that are used in this file for decoding.
- Save the received data to a known location.
- Run this script with the path to the received data specified. The default
path is 'Data/ofdmReceiveFile_70.dat'.
python3 ofdm_hardaware_correct.py --rx_data_path=<path/to/received>.dat --tx_npz_path=<path/to/npz>.npz
- If you would like to generate plots, please add --make_plots=True argument.
"""
from __future__ import print_function, division
from utils import ofdm_util as ofdm
from utils import nonflat_channel_timing_error
import matplotlib.pyplot as plt
import numpy as np
import argparse
# Set up commandline arguments.
FLAGS = None
parser = argparse.ArgumentParser()
parser.add_argument('--rx_data_path', type=str,
default='Data/ofdmReceiveFile_70', help=
'The path to the binary file of received data')
parser.add_argument('--tx_npz_path', type=str, default='tx_arrays.npz',
help='Path to .npz file containing components of the transmitted'
+ 'signal.')
parser.add_argument('--make_plots', type=bool, default=False,
help='Generate and display plots.')
parser.add_argument('--qpsk', type=bool, default=False,
help='Decode a qpsk signal')
FLAGS, unparsed = parser.parse_known_args()
received_data = np.fromfile("Data/ofdmReceiveFile_70.dat", dtype=np.float32)
signal_time_rx = received_data[::2] + received_data[1::2]*1j
if FLAGS.make_plots:
plt.plot(signal_time_rx)
plt.title("Received Signal Without Correction")
plt.show()
# Load signal components for decoding and calculating bit-error rates.
tx_arrays = np.load(FLAGS.tx_npz_path)
lts = tx_arrays['lts']
header_time = tx_arrays['header_time']
data_time = tx_arrays['data_time']
header_freq = tx_arrays['header_freq']
data_freq = tx_arrays['data_freq']
if FLAGS.make_plots:
tmp = signal_time_rx
plt.plot(signal_time_rx)
# Find the start of the data using the LTS.
signal_time_len = lts.shape[-1] + header_time.shape[-1] + data_time.shape[-1]
lag, signal_time_rx = ofdm.detect_start_lts(signal_time_rx, lts,
signal_time_len)
if FLAGS.make_plots:
tmp[:lag] = 0
tmp[lag + signal_time_len:] = 0
plt.plot(tmp)
plt.title("received data")
plt.show()
# Estmate f_delta using the LTS.
lts_rx = signal_time_rx[:lts.shape[-1]]
f_delta_est = ofdm.estimate_f_delta(lts_rx, ofdm.NUM_SAMPLES_PER_PACKET)
print(f_delta_est, 'estimated f_delta')
# Correct for f_delta.
signal_time_rx = ofdm.correct_freq_offset(signal_time_rx, f_delta_est)
# Estimate the channel using the known channel estimation sequence.
channel_est_start = lts.shape[-1]
channel_est_end = channel_est_start + header_time.shape[-1]
header_time_rx = signal_time_rx[channel_est_start:channel_est_end]
header_freq_rx = ofdm.convert_time_to_frequency(ofdm.NUM_SAMPLES_PER_PACKET, ofdm.NUM_SAMPLES_CYCLIC_PREFIX, header_time_rx)
H = ofdm.estimate_channel(header_freq, header_freq_rx)
header_eq = ofdm.equalize_frequency(H, header_freq_rx, qpsk=FLAGS.qpsk, est_phase=True)
# See what the bit-error rate is for the decoded known header.
print((ofdm.decode_signal_freq(header_eq, qpsk=FLAGS.qpsk) == header_freq).mean())
# Convert from time to frequency domain.
data_time_rx = signal_time_rx[channel_est_end:]
data_freq_rx = ofdm.convert_time_to_frequency(ofdm.NUM_SAMPLES_PER_PACKET, ofdm.NUM_SAMPLES_CYCLIC_PREFIX, data_time_rx)
if FLAGS.make_plots:
# Plot the time domain signal after finding the start.
plt.subplot(2, 1, 1)
plt.plot(data_time_rx[:ofdm.NUM_SAMPLES_PER_PACKET + ofdm.NUM_SAMPLES_CYCLIC_PREFIX])
plt.title("Time Domain with Cyclic Prefixes After Finding Start (first" +
"packet of {} samples with {} cyclic prefix" +
"samples".format(ofdm.NUM_SAMPLES_PER_PACKET,
ofdm.NUM_SAMPLES_CYCLIC_PREFIX))
plt.plot()
# Plot the frequency domain signal.
plt.subplot(2, 1, 2)
plt.stem(data_freq_rx[:ofdm.NUM_SAMPLES_PER_PACKET])
plt.title("Frequency Domain (first packet of {}" +
"samples)".format(ofdm.NUM_SAMPLES_PER_PACKET))
plt.show()
# Correct for the channel and the phase offset.
data_freq_eq = ofdm.equalize_frequency(H, data_freq_rx, qpsk=FLAGS.qpsk, est_phase=False)
if FLAGS.make_plots:
tmp = data_freq_eq[12::ofdm.NUM_SAMPLES_PER_PACKET]
plt.plot(tmp.real, tmp.imag, ".")
plt.title("Constellation plot of subcarrier 12")
plt.show()
plt.plot(data_freq_eq)
plt.title("Received Data (Frequency) after equalization, before quantization")
plt.show()
# Decode the signal in the frequency domain.
bits = ofdm.decode_signal_freq(data_freq_eq, qpsk=FLAGS.qpsk)
# Calculate the percent error rate.
print(data_freq.shape)
percent_error = ofdm.calculate_error(ofdm.decode_signal_freq(data_freq, qpsk=FLAGS.qpsk)[:4000], bits[:4000])
if FLAGS.make_plots:
plt.plot(np.sign(data_freq) == bits, 'o')
plt.show()
print("The bit error rate is: {}%".format(percent_error))