{ "cells": [ { "cell_type": "raw", "id": "b57d5681-1fa5-440f-81b1-fa433bdc74b9", "metadata": {}, "source": [ "\\tableofcontents % LaTeX rendered pdf will have a TOC with links\n", "% These TeX commands run at the start to remove section numbering\n", "%\\renewcommand{\\thesection}{\\hspace*{-1.0em}}\n", "%\\renewcommand{\\thesubsection}{\\hspace*{-1.0em}}\n", "%\\renewcommand{\\thesubsubsection}{\\hspace*{-1.0em}}" ] }, { "cell_type": "code", "execution_count": null, "id": "ce05783c-75b8-4284-8f4d-830f5fd0cff6", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from sk_dsp_comm import sigsys as ss\n", "from sk_dsp_comm import synchronization as sync\n", "from matplotlib import pyplot as plt" ] }, { "cell_type": "markdown", "id": "9410d6b2-9b30-447d-b9d3-7488b3bd1036", "metadata": {}, "source": [ "# Automatic Frequency Control" ] }, { "cell_type": "markdown", "id": "1d18c610-51f3-4609-954c-13d831554e81", "metadata": {}, "source": [ "The module `synchronization.py` has component classes for implementing AFC. The following example shows how to implement the AFC a quadricorrelator/frequency discriminator class for sample-by-sample processing, as is needed for tracking loop simulation/implementation." ] }, { "cell_type": "markdown", "id": "a16d4f86-dc74-472b-9636-b231e741ce02", "metadata": {}, "source": [ "## AFC Tracking Loop" ] }, { "cell_type": "code", "execution_count": null, "id": "14cb09f2-14dd-47a4-872f-4f68659c6e5b", "metadata": {}, "outputs": [], "source": [ "# Define input signal for AFC\n", "f_clk_afc = 100e3\n", "n = np.arange(100000)\n", "fc = 1000\n", "fm = 100\n", "# Test with amplitude modulation\n", "x_in = (1 + 0.8*np.cos(2*np.pi*fm/f_clk_afc*n))*np.exp(1j*2*np.pi*fc/f_clk_afc*n)" ] }, { "cell_type": "code", "execution_count": null, "id": "a8426f60-d643-41b8-ae5e-c18b437df980", "metadata": {}, "outputs": [], "source": [ "Bn_afc = 10\n", "y_d_afc, y_lf_afc, x_out_afc = sync.cbb_afc(x_in, Bn_afc, 1.0, fc_afc=0.0, f_clk_afc=f_clk_afc, afc_open=False)\n", "plt.plot(n/f_clk_afc*1e3,y_d_afc,label='Discrim Out')\n", "plt.plot(n/f_clk_afc*1e3,y_lf_afc,label='LF Out')\n", "# Plot RC lowpass step response theory\n", "# Analog\n", "plt.title(r'AFC Frequency Step Response')\n", "plt.ylabel(r'Frequency/Frequency Error')\n", "plt.xlabel(r'Time (ms)')\n", "plt.legend()\n", "plt.grid();" ] }, { "cell_type": "code", "execution_count": null, "id": "8eb6a05c-2a8d-4051-9be1-619c608e2321", "metadata": {}, "outputs": [], "source": [ "Px_in, fx_in = ss.psd(x_in,2**15,f_clk_afc)\n", "plt.plot(fx_in,10*np.log10(Px_in),label='Input Signal at 1kHz')\n", "Px_out, fx_out = ss.psd(x_out_afc[10000:],2**15,f_clk_afc)\n", "plt.plot(fx_out,10*np.log10(Px_out),label='AFC Output, less transient')\n", "plt.title(r'PSD at Input and Output of AFC')\n", "plt.xlabel(r'Frequency (Hz)')\n", "plt.ylabel(r'PSD (dB)')\n", "plt.ylim(-20,40)\n", "plt.xlim(-500,2000)\n", "plt.legend()\n", "plt.grid();" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }