Files
matlab/garage_ip.m
T
2019-01-07 14:54:30 +00:00

215 lines
5.0 KiB
Matlab
Executable File

## Copyright (C) 2018 Jens Ahrensfeld
##
## 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 <http://www.gnu.org/licenses/>.
## -*- texinfo -*-
## @deftypefn {Function File} {@var{retval} =} garage (@var{input1}, @var{input2})
##
## @seealso{}
## @end deftypefn
## Author: Jens Ahrensfeld <ahrensfeld@w2ess001vm>
## Created: 2018-12-06
function [bits] = garage_ip (varargin)
params = struct ('x', [], 'sampleRate', 48000, 'numSamplesPerSym', 16, 'loopFilterGain', 1.0, 'with_filter', 0, 'k_noise', 0.0);
units = struct ('x', '', 'sampleRate', '1/s', 'numSamplesPerSym', 'sps', 'loopFilterGain', '', 'with_filter', '', 'k_noise', '');
% Parse parameters
names = fieldnames(params);
for k=1:nargin-1,
for n=1:length(names),
if strcmpi(varargin{k}, names{n})
params.(names{n}) = varargin{k+1};
end
end
end
print_parameters(params, units)
k_n = params.k_noise; % NOise
k_s = 1.0; % Sym
numSamplesPerSym = params.numSamplesPerSym;
fs = params.sampleRate;
baud_init = fs / numSamplesPerSym;
numSyms = 100;
numBursts = 3;
numSymsPauseBetweenBurst = 25;
syms = rand(numSyms, 1) > 0.5;
bit = 0;
id_bit = 0;
% Line coding
syms_m = manchester(syms);
% Upconvert
if isempty(params.x)
x = zeros(1, 2*numSymsPauseBetweenBurst*numSamplesPerSym);
for k=1:numBursts
for n=1:2*numSyms,
for m=1:numSamplesPerSym,
x = [x syms_m(n)];
end
end
x = [x zeros(1, numSymsPauseBetweenBurst*numSamplesPerSym)];
end
x = [x zeros(1, 20*numSymsPauseBetweenBurst*numSamplesPerSym)];
% Channel
y = resample (x, 3200, baud_init);
%y = x;
if params.with_filter
[b,a] = butter(2, numSamplesPerSym/4*baud_init/fs);
y = k_s*filter(b, a, y) + k_n*randn(1, length(y));
else
y = k_s*y + k_n*randn(1, length(y));
end
else
x = params.x;
y = x;
end
N = length(y);
baud = baud_init;
bit = 0;
% The master clock counter
countReload = numSamplesPerSym-1;
count = countReload;
smp = [];
smp_n = [];
bits = [];
hyst_thr = 0.1;
v_min = 0; % Threshold max
v_max = 0; % Threshold min
rho_thr = 0.999; % Threshold forgetting factor
alpha_thr = 0.002; % Min/Max update factor
k_leadLag = params.loopFilterGain; % Overall loopfilter gain (scales k_lead and k_lag)
k_lead = 0.1; % Symbol syncronizer loop filter lead
k_lag = 0.0001; % Symbol syncronizer loop filter lag
lag_accu = 0; % Symbol syncronizer loop filter
k_leak = 0.0; % Lag forgetting factor
loopThreshold = 0.02; % Processing threshold
ns = 1; % Start sample source
n = 1; % Start sample sink
err = 0; % Error
alpha_sig = 0.5/numSamplesPerSym;
v_sig = 0;
k_id = 1/numSamplesPerSym;
id_accu = 0;
dc_corr = 0;
zbit = -1;
while ns < N
% Get next interpolated sample
is = fix(ns);
mu = ns - is;
ys = (1-mu).*y(is) + mu.*y(is+1) - dc_corr;
% Calculate Runing Min/Max
v_min = v_min * rho_thr;
v_max = v_max * rho_thr;
if ys < v_min
v_min = ys;
elseif ys > v_max
v_max = ys;
end
% Calculate DC offset correction
dc_corr = dc_corr + alpha_thr*(v_max + v_min);
% Signal detection
v_sig = (1-alpha_sig)*v_sig + alpha_sig*ys*ys;
isSignal = v_sig >= loopThreshold;
% Integrate and dump
id_accu = id_accu + k_id*ys;
if count == fix(numSamplesPerSym/2)
id_bit = id_accu >= 0.0;
id_accu = 0;
if isSignal
bits = [bits id_bit];
end
end
% Zero crossing detector
bitChg = 0;
if isSignal
if (bit == 1)
if ys < -hyst_thr
bit = 0;
bitChg = 1;
end
else
if ys > +hyst_thr
bit = 1;
bitChg = 1;
end
end
end
% Calc error on zero crossing
err = 0;
if (bitChg)
err = -(count - fix(numSamplesPerSym/2));
end
% Sample bit at baud rate = fs/numSamplesPerSym
if count == 0 && isSignal
if isSignal
smp = [smp ys];
smp_n = [smp_n n];
end
end;
if count > 0
count = count - 1;
else
count = countReload;
end
vcorr = k_leadLag*k_lead*err + lag_accu;
lag_accu = lag_accu + k_leadLag*k_lag*err;
lag_accu = lag_accu * (1-k_leak);
baud = fs/((1+lag_accu)*numSamplesPerSym);
k_id = 1/((1+lag_accu)*numSamplesPerSym);
_err(n) = err;
_err_baud(n) = baud - baud_init;
_id_accu(n) = id_accu;
_id_bit(n) = id_bit;
_cnt(n) = vcorr;
_v_tr(n) = v_sig;
_ys(n) = ys;
n = n + 1;
ns = ns + (1+vcorr);
end
bits = bits';
n = 1:length(_ys);
% Plot
subplot(3, 1, 1)
plot(n, _ys, '-o', n, _v_tr, 'm', smp_n, smp, 'ro'); grid;
subplot(3, 1, 2)
plot(n, _err, n, _err_baud); grid; legend('err_{smp}', 'err_{baud}')
subplot(3, 1, 3)
plot(n, _id_accu, n, _id_bit); grid; legend('accu_{id}', 'bit_{id}')
endfunction