[1]:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator
from sk_dsp_comm import sigsys as ss
from sk_dsp_comm import digitalcom as dc
from sk_dsp_comm import synchronization as sync
from scipy import signal
%config InlineBackend.figure_formats=['svg'] # SVG inline viewing
Phase Lock Loops¶
The module synchronization.py has component classes for implementing NCO’s (32-bit and 48-bit), DSP loop filters (two types), accumulator (used in the loop filters), \(K_p\) and \(K_i\) calculation functions, and several digital PLL analysis functions.
[2]:
NCO1 = sync.NCO(3.25e6,120e6, n_bits=32)
NCO2 = sync.NCO(3.0e6,120e6, n_bits=48)
[3]:
Nclks = 100000
n = np.arange(Nclks)
x_32 = np.zeros(len(n))
data_bit = 1
for k in range(Nclks):
NCO1.update(0.0)
x_32[k] = NCO1.out_sin()
# x[k] = data_bit
# if NCO1.NCO32_pos_edge():
# data_bit = 2*random.randint(0,2) - 1
y_32 = dc.farrow_resample(x_32,3.5,3.25)
[4]:
Nclks = 100000
n = np.arange(Nclks)
x_48 = np.zeros(len(n))
data_bit = 1
for k in range(Nclks):
NCO2.update(0.0)
x_48[k] = NCO2.out_sin()
# x[k] = data_bit
# if NCO2.NCO48_pos_edge():
# data_bit = 2*random.randint(0,2) - 1
y_48 = dc.farrow_resample(x_48,3.5,3.25)
[5]:
plt.plot(y_32[1000:1300])
plt.plot(y_48[1000:1300])
plt.grid();
[6]:
Py_32, fy_32 = ss.psd(y_32,2**16,120,scale_noise=False)
Py_48, fy_48 = ss.psd(y_48,2**16,120,scale_noise=False)
plt.plot(fy_32,10*np.log10(Py_32),120)
plt.plot(fy_48,10*np.log10(Py_48),120)
plt.ylim(-60,0)
plt.xlim(0, 4)
plt.title(r'Sinusoid Spectrum using the Sinusoid Scaling Option')
plt.xlabel(r'Frequency (MHz)')
plt.ylabel(r'PSD (dB)')
plt.grid();
Complex Baseband PLL¶
[7]:
fs = 100e3
fc = 0
n = np.arange(10000)
x_in = np.exp(1j*2*np.pi*fc/fs*n + 1j*np.pi/8)
[8]:
phi_pstep = sync.phi_phase_step(n,100,0.707,fs)
phi_fstep = sync.phi_freq_step(n,100,0.707,fs)
[1.0, -1.9973318238750948, 0.9973353797885762]
[1.0, -1.9973318238750948, 0.9973353797885762]
[9]:
y_d_pll, y_lf_pll, x_NCO_pll = sync.cbb_pll(x_in, 100, 1.0, fc_pll=0.0, f_clk_pll=fs, pll_open=False)
t_pll = np.arange(0,len(y_d_pll))/fs
plt.plot(t_pll*1e3,phi_pstep/2/np.pi * np.pi/8,label='Linear Theory')
plt.plot(t_pll*1e3,y_d_pll,label='Measured')
plt.title(r'Type 2 PLL Phase Step (Freq. Step) Response')
plt.ylabel(r'Phase Error')
plt.xlabel(r'Time (ms)')
plt.legend()
plt.grid();
PLL (kp, ki) = (4.247e-04, 5.659e-07)