Carrier Recovery & PED/FEDs
Est. read time: 1 minute | Last updated: September 23, 2024 by John Gentile
Contents
Frequency Error Detector (FED)
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from rfproto import measurements, multirate, plot, sig_gen
fs = 100.0e3
f_start = -fs/2
f_end = fs/2
num_samples = int(fs) # 1 second
lfm_chirp_sig = sig_gen.cmplx_dt_lfm_chirp(100, f_start, f_end, fs, num_samples)
mid_pt = int(len(lfm_chirp_sig)/2)
margin = 1000
plot.samples(np.real(lfm_chirp_sig[mid_pt - margin:mid_pt + margin]))
plt.show()
f, t, Zxx = signal.stft(np.real(lfm_chirp_sig), fs, nperseg=100)
plt.pcolormesh(t, f, np.abs(Zxx), vmin=0, vmax=2, shading='gouraud')
plt.title('STFT Magnitude')
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()
i_z1 = 0
q_z1 = 0
freq_disc = np.zeros(len(lfm_chirp_sig))
for i in range(len(lfm_chirp_sig)):
i_val = np.real(lfm_chirp_sig[i])
q_val = np.imag(lfm_chirp_sig[i])
a0 = i_z1 * q_val
a1 = q_z1 * i_val
freq_disc[i] = a1 - a0
i_z1 = i_val
q_z1 = q_val
plt.plot(freq_disc)
plt.show()
Blind, Non-Data Aided (NDA) FLL can be made by RRC/match filtering, Mth power to fold phase into sinusoid which has frequency offset at times the CFO, LPF’ing then using L&R type autocorrelation FED (see above) loop filtered to drive frequency error to zero.
Phase Error Detector (PED)
Combined Carrier Recovery
When frequency offset is not significant (e.x. majority of signal bandwidth is still within passband of matched filter, and/or when Coarse Frequency Correction (CFC) has already been applied upstream), frequency and phase errors can be jointly compensated in a carrier recovery scheme.
symbol_rate = 5e6
output_fs = 8.0 * symbol_rate
in_symbols = np.random.randint(0, 4, 2400).tolist()
output_iq = sig_gen.gen_mod_signal(
"QPSK",
in_symbols,
output_fs,
symbol_rate,
"RRC",
0.25,
)
plot.IQ(output_iq, alpha=0.1)
plot.plt.show()
plot.spec_an(output_iq, fs=output_fs, fft_shift=True, show_SFDR=False, y_unit="dB")
plt.show()
downsampled=multirate.decimate(output_iq[1:], 4)
plot.spec_an(downsampled, fs=output_fs/4, fft_shift=True, show_SFDR=False, y_unit="dB")
plt.show()
plot.IQ(downsampled, alpha=0.1)
plt.show()
References
- High modulation index PSK - carrier recovery - DSP Stack Exchange
- Mathworks Carrier Synchronizer System Object