diff --git a/odfm_wifi.m b/odfm_wifi.m
new file mode 100644
index 0000000..6dcc128
--- /dev/null
+++ b/odfm_wifi.m
@@ -0,0 +1,28 @@
+function odfm_wifi()
+
+ndly = 16;
+nmav1 = 48;
+nmav2 = 64;
+
+hdly = [zeros(1,ndly) 1];
+hmav1 = ones(1,nmav1);
+hmav2 = ones(1,nmav2);
+
+x = 0.1*load_iq('/home/jens/mnt/cifs/Media/Raw/wifi_burst_5579999999_20000000_fc.wav');
+
+xdly = filter(hdly, 1, x);
+xc = x .* conj(xdly);
+xc = filter(hmav1, 1, xc);
+k = filter(hmav2, 1, abs(x).^2) + 1e-6;
+N = length(xc);
+
+plot(0:N-1, abs(xc)/nmav1*16, 0:N-1, abs(xc)./k); grid
+
+function x = load_iq(name)
+ xw = audioread(name);
+ x = xw(:,1) + j*xw(:,2);
+# x = randn(1,400) + j*randn(1,400);
+endfunction
+
+endfunction
+
\ No newline at end of file
diff --git a/parse_myparams.m b/parse_myparams.m
new file mode 100644
index 0000000..ec18786
--- /dev/null
+++ b/parse_myparams.m
@@ -0,0 +1,45 @@
+function params = parse_myparams (params_default, arglist)
+
+# Use:
+# params = parse_myparams (struct("A", 1, "B", 2), {"B", 42})
+# Returns : params = struct("A", 1, "B", 42)
+#
+
+% Parse parameters
+params = params_default;
+names = fieldnames(params);
+
+for k=1:2:length(arglist)-1,
+ found = false;
+ for n=1:length(names),
+ if strcmpi(arglist{k}, names{n})
+ params.(names{n}) = arglist{k+1};
+ found = true;
+ end
+ end
+ if ~found
+ error("Not found!");
+ endif
+end
+
+if nargout == 0
+ print_parameters(params);
+endif
+
+function print_parameters(params)
+align = 32;
+names = fieldnames(params);
+for n=1:length(names),
+ fprintf('%s', names{n});
+ remain = align - length(names{n});
+ if remain < 0
+ error('Invalid variable length!');
+ else
+ for j=1:remain
+ fprintf(' ');
+ end
+ fprintf('= %g\n', params.(names{n}));
+ end
+end
+endfunction
+endfunction
diff --git a/pll_burst_acars.m b/pll_burst_acars.m
new file mode 100644
index 0000000..c84a89b
--- /dev/null
+++ b/pll_burst_acars.m
@@ -0,0 +1,30 @@
+## Copyright (C) 2022 Jens
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} pll_burst_acars (@var{input1}, @var{input2})
+##
+## @seealso{}
+## @end deftypefn
+
+## Author: Jens
+## Created: 2022-05-04
+
+function pll_burst_acars ()
+[acars, fs] = audioread('/home/jens/acars_bb_iq.wav');
+x = acars(:,1) + j*acars(:,2);
+pll_burst_eval('fs', fs, 'ref', x);
+
+endfunction
diff --git a/pll_burst_eval.m b/pll_burst_eval.m
new file mode 100644
index 0000000..9b41661
--- /dev/null
+++ b/pll_burst_eval.m
@@ -0,0 +1,114 @@
+## Copyright (C) 2020 Jens
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see
+## .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} mc_pd_eval (@var{input1}, @var{input2})
+##
+## @seealso{}
+## @end deftypefn
+
+## Author: Jens
+## Created: 2020-08-07
+#
+# pll_burst_eval(0.5, 0.0, 10, 0)
+#
+# Usage:
+# x = siggen(2000, 48000, 8, 0.1);
+# pll_burst_eval(48000,0, x)
+#
+
+function retval = pll_burst_eval(varargin)
+
+params_default = struct("fs", 48000, "f", 0, "ref", [], "klead", 0.004, "klag", 0.00002, 'domega_max', 2000);
+params = parse_myparams(params_default, varargin);
+
+# Create variable from params
+fs = params.fs;
+f = params.f;
+ref = params.ref;
+klead = params.klead;
+klag = params.klag;
+
+domega_max = params.domega_max;
+domega_lo_max = +domega_max/fs;
+domega_lo_min = -domega_max/fs;
+
+N = length(ref);
+omega = f/fs;
+
+# Start processing
+lag = 0;
+phi_lo = 0;
+omega_err = 0;
+agc_state = 0;
+
+for n=1:N,
+ # Derotator LO
+ lo = exp(j*2*pi*phi_lo);
+
+ # AGC
+ [y, agc_state] = agc(agc_state, ref(n));
+
+ # Pahse detector
+ [perr, pd] = phase_det(lo, y);
+
+ # Process loop filter output kv
+ lag = lag + klag*perr;
+ kv = (lag + klead*perr);
+
+ # Calculate delta omega for LO
+ domega_lo = min(domega_lo_max, max(domega_lo_min, kv));
+ omega_lo = omega + domega_lo;
+ omega_err = omega_lo - omega;
+
+ # advance phase accumulator for LO
+ phi_lo = phi_lo + omega_lo;
+
+ _perr(n) = perr;
+ _omega_err(n) = omega_err;
+ _lo(n) = lo;
+ _ref_derote(n) = pd;
+ _agc_state(n) = agc_state;
+end
+
+f_err = fs*omega_err
+
+function [perr, pd] = phase_det(lo, ref)
+ pd = ref*conj(lo);
+ perr = imag(pd);
+endfunction
+
+function [y, state_out] = agc(state_in, x)
+ alpha = 0.1;
+ refi = 1.0;
+ eps = 1e-3;
+ state_out = (1-alpha)*state_in + alpha*abs(x);
+
+ c = refi/(eps + state_out);
+ y = x*c;
+endfunction
+
+close all;
+subplot(3, 1, 1)
+plot(1:N, imag(_lo), 1:N, imag(ref), 1:N, _agc_state); legend('Lo', 'ref', 'agc'); grid
+
+subplot(3, 1, 2)
+plot(1:N, real(_ref_derote), 1:N, imag(_ref_derote)); legend('Re_{Derot}', 'Im_{Derot}'); grid
+
+subplot(3, 1, 3)
+plot(1:N, _perr, 1:N, _omega_err); legend('p_{err}', 'f_{err}'); grid
+
+endfunction
diff --git a/pll_burst_siggen.m b/pll_burst_siggen.m
new file mode 100644
index 0000000..6e17469
--- /dev/null
+++ b/pll_burst_siggen.m
@@ -0,0 +1,32 @@
+## Copyright (C) 2022 Jens
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} pll_burst_siggen (@var{input1}, @var{input2})
+##
+## @seealso{}
+## @end deftypefn
+
+## Author: Jens
+## Created: 2022-05-04
+
+function pll_burst_siggen ()
+fs = 48000;
+f_dev = 8; # Hz
+p_dev = 0.1; # pi
+x = siggen(2000, fs, f_dev, p_dev);
+pll_burst_eval('fs', fs, 'ref', x);
+
+endfunction
diff --git a/siggen.m b/siggen.m
new file mode 100644
index 0000000..5c4a0cc
--- /dev/null
+++ b/siggen.m
@@ -0,0 +1,32 @@
+## Copyright (C) 2022 Jens
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see .
+
+## -*- texinfo -*-
+## @deftypefn {} {@var{retval} =} siggen (@var{input1}, @var{input2})
+##
+## @seealso{}
+## @end deftypefn
+
+## Author: Jens
+## Created: 2022-05-04
+
+function retval = siggen (N, fs, f, phi)
+
+omega = f/fs;
+
+retval = exp(j*2*pi*(omega*(0:N-1)+phi));
+
+
+endfunction