diff --git a/README.md b/README.md
index 227e6d1..be5c216 100644
--- a/README.md
+++ b/README.md
@@ -29,12 +29,7 @@ nix develop
- RAM usage and execution time estimate for simulation **ONLY**
- 1. 100,000,000 time steps: 6GiB RAM and 12 seconds
-
- 2. 200,000,000 time steps: 11GiB RAM and 20 seconds
-
- 3. 300,000,000 time steps: 16GiB RAM and 35 seconds
-
+ - 500,000,000 time steps: 8GiB RAM and 55 seconds
WRPLL formulas
diff --git a/src/WRPLL_timesim_example.py b/src/WRPLL_timesim_example.py
new file mode 100644
index 0000000..c465176
--- /dev/null
+++ b/src/WRPLL_timesim_example.py
@@ -0,0 +1,68 @@
+# %%
+from plotly_resampler import FigureWidgetResampler
+from plotly.subplots import make_subplots
+import plotly.graph_objects as go
+import numpy as np
+
+from wrpll_simulation.config import Timesim_Config, PI_Config
+from wrpll_simulation.timesim import WRPLL_Timesim
+
+# %%
+KP, KI = 6, 2
+sim_config = Timesim_Config(
+ timestep_size=1e-11,
+ sim_length=500_000_000,
+ helper_PI=PI_Config(KP=KP, KI=KI),
+ main_PI=PI_Config(KP=KP, KI=KI),
+ has_jitter=False,
+ step_input_time=10e-6,
+ step_frequency=6.25,
+ step_phase=0,
+)
+sim = WRPLL_Timesim(sim_config, np.random.default_rng(1))
+
+fig = FigureWidgetResampler(make_subplots(rows=2))
+# ROW 1
+fig.add_trace(
+ go.Scattergl(name="main - gtx freq diff"),
+ hf_x=sim.time,
+ hf_y=sim.freq_diff,
+ row=1,
+ col=1,
+)
+
+# ROW 2
+fig.add_trace(
+ go.Scattergl(name="main - gtx phase diff"),
+ hf_x=sim.time,
+ hf_y=sim.phase_diff,
+ row=2,
+ col=1,
+)
+
+
+title = (
+ f'step freq = {sim_config.step_frequency}Hz, '
+ f'step phase = {sim_config.step_phase}° | '
+ f'KP = {KP}, KI = {KI}'
+)
+
+fig.update_layout(
+ xaxis2=dict(title="Time (sec)", exponentformat="SI"),
+ yaxis1=dict(title="Frequency (Hz)"),
+ yaxis2=dict(title="Phase (degree)"),
+ height=950,
+ showlegend=True,
+ title_text=title,
+ legend=dict(
+ orientation="h",
+ yanchor="bottom",
+ y=1.02,
+ xanchor="right",
+ x=1,
+ ),
+)
+
+fig
+
+# %%
diff --git a/src/both_PLL_example.py b/src/both_PLL_example.py
deleted file mode 100644
index cfa9731..0000000
--- a/src/both_PLL_example.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# %% [markdown]
-# ## Both PLL mode example
-#
-# Time domain simulation with helper and main PLL mode.
-#
-# - Period error (**Helper PLL**)
-# - $\Delta{period} = N - (tag_{gtx}[n] - tag_{gtx}[n-1]) $
-# - where ideally $f_{helper} = \dfrac{f_{in} * (N-1)}{N}$
-#
-# - Phase error (**Main PLL**)
-# - $\text{Let } \Delta tag[n] = tag_{main}[n] - tag_{gtx}[n] \text{ mod N}$
-#
-# - $\Delta\phi[n] = \begin{cases}
-# \Delta tag[n] - N, & \text{if } \Delta tag > N/2 \\
-# \Delta tag[n], & otherwise
-# \end{cases} \quad$
-#
-#
-# - ADPLL PID (common for main and helper PLL)
-# - $P[n] = err[n] * K_P$
-# - $I[n] = I[n-1] + err[n] * K_I$
-# - $D[n] = (err[n] - err[n-1]) * K_D$
-# - $adpll[n] = \text{base adpll} + P[i] + I[n] + D[n] $
-# - where $\text{base adpll}$ is constant and obtain from frequency counter in HW
-
-# %%
-from plotly_resampler import FigureResampler, FigureWidgetResampler
-from plotly.subplots import make_subplots
-import plotly.graph_objects as go
-import numpy as np
-from wrpll_simulation.wrpll import WRPLL_simulator
-
-# %%
-# settings
-timestep = 1e-10
-total_steps = 200_000_000
-sim_mode = "both"
-adpll_period = 200e-6 # in seconds, the period that pll will trigger, (minimum > total DCXO frequency change delay)
-start_up_delay = 100e-6 # in seconds, the frequency adjustment is DISABLE until time > start_up_delay
-
-gtx_freq = 125_001_519
-
-
-helper_filter = {
- "KP": 2,
- "KI": 0.5,
- "KD": 0,
-}
-
-main_filter = {
- "KP": 12,
- "KI": 0,
- "KD": 0,
-}
-
-
-# simulation have RNG for
-# - gtx, main and helper jitter
-# - starting phase for main and helper
-# - base_adpll error
-
-wrpll_sim = WRPLL_simulator(
- timestep=timestep,
- total_steps=total_steps,
- sim_mode=sim_mode,
- helper_filter=helper_filter,
- main_filter=main_filter,
- gtx_freq=gtx_freq,
- adpll_write_period=adpll_period,
- start_up_delay=start_up_delay,
-)
-wrpll_sim.run()
-
-# %%
-# faster than pyplot with resampling feature
-# see https://github.com/predict-idlab/plotly-resampler
-
-fig = FigureWidgetResampler(make_subplots(rows=4, shared_xaxes=True))
-fig.add_trace(
- go.Scattergl(name="phase error"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.phase_err,
- row=1,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="freq error (ppm)"),
- hf_x=wrpll_sim.time,
- hf_y=(wrpll_sim.mainfreq - gtx_freq) * (1e6 / gtx_freq),
- row=2,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="period error"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.period_err,
- row=3,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="gtx"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.gtx + 1, row=4, col=1
-)
-fig.add_trace(
- go.Scattergl(name="main"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.main, row=4, col=1
-)
-fig.add_trace(
- go.Scattergl(name="helper"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.helper - 1,
- row=4,
- col=1,
-)
-
-
-fig.update_layout(
- xaxis4=dict(title="time (sec)"),
- yaxis1=dict(title="phase error"),
- yaxis2=dict(title="freq error (ppm)"),
- yaxis3=dict(title="beating period error"),
- yaxis4=dict(title="Signal"),
- height=1000,
- showlegend=True,
- title_text="PLL example",
- legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1,
- ),
-)
-
-fig
diff --git a/src/helper_PLL_example.py b/src/helper_PLL_example.py
deleted file mode 100644
index 4652ec3..0000000
--- a/src/helper_PLL_example.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# %% [markdown]
-# ## Helper PLL mode example
-#
-# Time domain simulation with helper PLL mode
-#
-# - Period error (**Helper PLL**)
-# - $\Delta{period} = N - (tag_{gtx}[n] - tag_{gtx}[n-1]) $
-# - where ideally $f_{helper} = \dfrac{f_{in} * (N-1)}{N}$
-#
-# - Phase error (**Main PLL**)
-# - $\text{Let } \Delta tag[n] = tag_{main}[n] - tag_{gtx}[n] \text{ mod N}$
-#
-# - $\Delta\phi[n] = \begin{cases}
-# \Delta tag[n] - N, & \text{if } \Delta tag > N/2 \\
-# \Delta tag[n], & otherwise
-# \end{cases} \quad$
-#
-#
-# - ADPLL PID (common for main and helper PLL)
-# - $P[n] = err[n] * K_P$
-# - $I[n] = I[n-1] + err[n] * K_I$
-# - $D[n] = (err[n] - err[n-1]) * K_D$
-# - $adpll[n] = \text{base adpll} + P[i] + I[n] + D[n] $
-# - where $\text{base adpll}$ is constant and obtain from frequency counter in HW
-
-# %%
-from plotly_resampler import FigureResampler, FigureWidgetResampler
-from plotly.subplots import make_subplots
-import plotly.graph_objects as go
-import numpy as np
-from wrpll_simulation.wrpll import WRPLL_simulator
-
-# %%
-# settings
-timestep = 1e-10
-total_steps = 100_000_000
-sim_mode = "helper_pll"
-adpll_period = 200e-6 # in seconds, the period that pll will trigger, (minimum > total DCXO frequency change delay)
-start_up_delay = 100e-6 # in seconds, the frequency adjustment is DISABLE until time > start_up_delay
-
-gtx_freq = 125_001_519
-
-helper_filter = {
- "KP": 2,
- "KI": 0.5,
- "KD": 0,
-}
-
-main_filter = { # unused
- "KP": 12,
- "KI": 0,
- "KD": 0,
-}
-
-# simulation have RNG for
-# - gtx, main and helper jitter
-# - starting phase for main and helper
-# - base_adpll error
-
-wrpll_sim = WRPLL_simulator(
- timestep=timestep,
- total_steps=total_steps,
- sim_mode=sim_mode,
- helper_filter=helper_filter,
- main_filter=main_filter,
- gtx_freq=gtx_freq,
- adpll_write_period=adpll_period,
- start_up_delay=start_up_delay,
-)
-wrpll_sim.run()
-
-# %%
-# faster than pyplot with resampling feature
-# see https://github.com/predict-idlab/plotly-resampler
-
-fig = FigureWidgetResampler(make_subplots(rows=2, shared_xaxes=True))
-fig.add_trace(
- go.Scattergl(name="period error"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.period_err,
- row=1,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="gtx"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.gtx + 1, row=2, col=1
-)
-fig.add_trace(
- go.Scattergl(name="main"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.main, row=2, col=1
-)
-fig.add_trace(
- go.Scattergl(name="helper"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.helper - 1,
- row=2,
- col=1,
-)
-
-
-fig.update_layout(
- xaxis2=dict(title="time (sec)"),
- yaxis1=dict(title="beating period error"),
- yaxis2=dict(title="Signal"),
- height=1000,
- showlegend=True,
- title_text="PLL example",
- legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1,
- ),
-)
-
-fig
diff --git a/src/main_PLL_example.py b/src/main_PLL_example.py
deleted file mode 100644
index 2182542..0000000
--- a/src/main_PLL_example.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# %% [markdown]
-# ## Main PLL mode example
-#
-# Time domain simulation with main PLL mode, and helper PLL is assumed to be locked
-#
-# (`helper_init_freq` variable need to be set)
-#
-#
-# - Period error (**Helper PLL**)
-# - $\Delta{period} = N - (tag_{gtx}[n] - tag_{gtx}[n-1]) $
-# - where ideally $f_{helper} = \dfrac{f_{in} * (N-1)}{N}$
-#
-# - Phase error (**Main PLL**)
-# - $\text{Let } \Delta tag[n] = tag_{main}[n] - tag_{gtx}[n] \text{ mod N}$
-#
-# - $\Delta\phi[n] = \begin{cases}
-# \Delta tag[n] - N, & \text{if } \Delta tag > N/2 \\
-# \Delta tag[n], & otherwise
-# \end{cases} \quad$
-#
-#
-# - ADPLL PID (common for main and helper PLL)
-# - $P[n] = err[n] * K_P$
-# - $I[n] = I[n-1] + err[n] * K_I$
-# - $D[n] = (err[n] - err[n-1]) * K_D$
-# - $adpll[n] = \text{base adpll} + P[i] + I[n] + D[n] $
-# - where $\text{base adpll}$ is constant and obtain from frequency counter in HW
-
-# %%
-from plotly_resampler import FigureResampler, FigureWidgetResampler
-from plotly.subplots import make_subplots
-import plotly.graph_objects as go
-import numpy as np
-from wrpll_simulation.wrpll import WRPLL_simulator
-
-# %%
-# settings
-timestep = 1e-10
-total_steps = 100_000_000
-sim_mode = "main_pll"
-adpll_period = 200e-6 # in seconds, the period that pll will trigger, (minimum > total DCXO frequency change delay)
-start_up_delay = 100e-6 # in seconds, the frequency adjustment is DISABLE until time > start_up_delay
-
-gtx_freq = 125_001_519
-
-helper_init_freq = gtx_freq * (4096 - 1) / 4096
-
-helper_filter = { # unused
- "KP": 2,
- "KI": 0.5,
- "KD": 0,
-}
-
-main_filter = {
- "KP": 12,
- "KI": 0,
- "KD": 0,
-}
-
-
-# simulation have RNG for
-# - gtx, main and helper jitter
-# - starting phase for main and helper
-# - base_adpll error
-
-
-wrpll_sim = WRPLL_simulator(
- timestep=timestep,
- total_steps=total_steps,
- sim_mode=sim_mode,
- helper_filter=helper_filter,
- main_filter=main_filter,
- gtx_freq=gtx_freq,
- adpll_write_period=adpll_period,
- start_up_delay=start_up_delay,
- helper_init_freq=helper_init_freq,
-)
-wrpll_sim.run()
-
-# %%
-# faster than pyplot with resampling feature
-# see https://github.com/predict-idlab/plotly-resampler
-
-fig = FigureWidgetResampler(make_subplots(rows=4, shared_xaxes=True))
-fig.add_trace(
- go.Scattergl(name="phase error"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.phase_err,
- row=1,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="freq error (ppm)"),
- hf_x=wrpll_sim.time,
- hf_y=(wrpll_sim.mainfreq - gtx_freq) * (1e6 / gtx_freq),
- row=2,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="period error"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.period_err,
- row=3,
- col=1,
-)
-
-fig.add_trace(
- go.Scattergl(name="gtx"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.gtx + 1, row=4, col=1
-)
-fig.add_trace(
- go.Scattergl(name="main"), hf_x=wrpll_sim.time, hf_y=wrpll_sim.main, row=4, col=1
-)
-fig.add_trace(
- go.Scattergl(name="helper"),
- hf_x=wrpll_sim.time,
- hf_y=wrpll_sim.helper - 1,
- row=4,
- col=1,
-)
-
-
-fig.update_layout(
- xaxis4=dict(title="time (sec)"),
- yaxis1=dict(title="phase error"),
- yaxis2=dict(title="freq error (ppm)"),
- yaxis3=dict(title="beating period error"),
- yaxis4=dict(title="Signal"),
- height=1000,
- showlegend=True,
- title_text="PLL example",
- legend=dict(
- orientation="h",
- yanchor="bottom",
- y=1.02,
- xanchor="right",
- x=1,
- ),
-)
-
-fig