{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Helper PLL mode example\n", "\n", "Time domain simulation with helper PLL mode\n", "\n", "- Period error (**Helper PLL**)\n", " - $\\Delta{period} = N - (tag_{gtx}[n] - tag_{gtx}[n-1]) $\n", " - where ideally $f_{helper} = \\dfrac{f_{in} * (N-1)}{N}$ \n", "\n", "- Phase error (**Main PLL**)\n", " - $\\text{Let } \\Delta tag[n] = tag_{main}[n] - tag_{gtx}[n] \\text{ mod N}$\n", "\n", " - $\\Delta\\phi[n] = \\begin{cases}\n", " \\Delta tag[n] - N, & \\text{if } \\Delta tag > N/2 \\\\\n", " \\Delta tag[n], & otherwise\n", " \\end{cases} \\quad$\n", " \n", "\n", "- ADPLL PID (common for main and helper PLL)\n", " - $P[n] = err[n] * K_P$\n", " - $I[n] = I[n-1] + err[n] * K_I$\n", " - $D[n] = (err[n] - err[n-1]) * K_D$\n", " - $adpll[n] = \\text{base adpll} + P[i] + I[n] + D[n] $\n", " - where $\\text{base adpll}$ is constant and obtain from frequency counter in HW" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from plotly_resampler import FigureResampler, FigureWidgetResampler\n", "from plotly.subplots import make_subplots\n", "import plotly.graph_objects as go\n", "import numpy as np\n", "from wrpll import WRPLL_simulator" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# settings\n", "timestep = 1e-10\n", "total_steps = 100_000_000\n", "sim_mode = \"helper_pll\"\n", "adpll_period = 100e-6 # in seconds, the period that pll will trigger, (minimum > the sampling rate of collector)\n", "start_up_delay = 100e-6 # in seconds, the frequency adjustment is DISABLE until time > start_up_delay\n", "\n", "gtx_freq = 125_001_519\n", "\n", "helper_filter = {\n", " \"KP\": 2,\n", " \"KI\": 0.5,\n", " \"KD\": 0,\n", "}\n", "\n", "main_filter = { # unused\n", " \"KP\": 12,\n", " \"KI\": 0,\n", " \"KD\": 0,\n", "}\n", "\n", "# simulation have RNG for\n", "# - gtx, main and helper jitter\n", "# - starting phase for main and helper\n", "# - base_adpll error\n", "\n", "wrpll_sim = WRPLL_simulator(\n", " timestep=timestep,\n", " total_steps=total_steps,\n", " sim_mode=sim_mode,\n", " helper_filter=helper_filter,\n", " main_filter=main_filter,\n", " gtx_freq=gtx_freq,\n", " adpll_write_period=adpll_period,\n", " start_up_delay=start_up_delay,\n", ")\n", "wrpll_sim.run()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# faster than pyplot with resampling feature\n", "# see https://github.com/predict-idlab/plotly-resampler\n", "\n", "fig = FigureWidgetResampler(make_subplots(rows=2, shared_xaxes=True))\n", "fig.add_trace(go.Scattergl(name='period error'), hf_x=wrpll_sim.time, hf_y=wrpll_sim.period_err, row=1, col=1)\n", "\n", "fig.add_trace(go.Scattergl(name='gtx'), hf_x=wrpll_sim.time, hf_y=wrpll_sim.gtx+1, row=2, col=1)\n", "fig.add_trace(go.Scattergl(name='main'), hf_x=wrpll_sim.time, hf_y=wrpll_sim.main, row=2, col=1)\n", "fig.add_trace(go.Scattergl(name='helper'), hf_x=wrpll_sim.time, hf_y=wrpll_sim.helper-1, row=2, col=1)\n", "\n", "fig.update_layout(\n", " xaxis2=dict(title=\"time (sec)\"),\n", "\n", " yaxis1=dict(title=\"beating period error\"),\n", " yaxis2=dict(title=\"Signal\"),\n", " height=1000,\n", " showlegend=True,\n", " title_text=\"PLL example\",\n", " legend=dict(\n", " orientation=\"h\",\n", " yanchor=\"bottom\",\n", " y=1.02,\n", " xanchor=\"right\",\n", " x=1,\n", " ),\n", ")\n", "\n", "fig" ] } ], "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.11.6" } }, "nbformat": 4, "nbformat_minor": 4 }