Initial ARSS. Need to improve and add functions.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
function spur = generate_spur(SpurParams, t, baseSignal)
|
||||
%GENERATE_SPUR create spur signals based on a parameter structure
|
||||
% spur = GENERATE_SPUR(SpurParams, t, baseSignal)
|
||||
% t : time vector (row or column)
|
||||
% baseSignal : (optional) complex baseband signal used for some spur
|
||||
% mechanisms such as mixer nonlinearity. If omitted the
|
||||
% function will only generate independent tones.
|
||||
%
|
||||
% SpurParams is a struct that may contain any of the following fields
|
||||
% .lo : struct with fields amp, freq, phase (optional) -
|
||||
% LO-related spur added to phase of signal
|
||||
% .mixer : struct with fields alpha2, alpha3 - coefficients for
|
||||
% 2nd/3rd order nonlinearity. Requires baseSignal input.
|
||||
% .adc : struct with fields amp, freq, phase - tone added after
|
||||
% ADC (complex). Does not require baseSignal.
|
||||
% .switch : struct with fields amp, freq - square/pulse spur
|
||||
% .pulse : struct with fields amp, freq, duty (0–1), phase -
|
||||
% periodic gating/pulse train (lock) added to output
|
||||
%
|
||||
% Example:
|
||||
% SpurParams = struct();
|
||||
% SpurParams.lo = struct('amp',0.01,'freq',1e6,'phase',0);
|
||||
% SpurParams.mixer= struct('alpha2',1e-4,'alpha3',1e-6);
|
||||
% SpurParams.adc = struct('amp',1e-3,'freq',2e6,'phase',0);
|
||||
% SpurParams.switch = struct('amp',5e-4,'freq',5e5);
|
||||
% SpurParams.pulse = struct('amp',0.02,'freq',500e3,'duty',0.1,'phase',0);
|
||||
% 위 설정은 LO 스퍼, 믹서 비선형, ADC 톤, 스위칭
|
||||
% 잡음에 더해 10% duty pulse train 락킹까지 포함합니다.
|
||||
%
|
||||
% The returned spur vector has the same dimensions as t. If baseSignal
|
||||
% is supplied the mixer nonlinearity is computed element‑wise using that
|
||||
% signal; otherwise only independent spur terms are returned.
|
||||
|
||||
if nargin < 3
|
||||
baseSignal = [];
|
||||
end
|
||||
% ensure t is row for consistent operations
|
||||
t = t(:)';
|
||||
spur = zeros(size(t));
|
||||
|
||||
if isfield(SpurParams, 'lo')
|
||||
p = SpurParams.lo;
|
||||
phase = 0;
|
||||
if isfield(p, 'phase'); phase = p.phase; end
|
||||
spur = spur + p.amp .* sin(2*pi*p.freq .* t + phase);
|
||||
end
|
||||
|
||||
if isfield(SpurParams, 'mixer') && ~isempty(baseSignal)
|
||||
m = SpurParams.mixer;
|
||||
% apply polynomial nonlinearity to the provided base signal
|
||||
if isfield(m, 'alpha2')
|
||||
spur = spur + m.alpha2 .* (baseSignal.^2);
|
||||
end
|
||||
if isfield(m, 'alpha3')
|
||||
spur = spur + m.alpha3 .* (baseSignal.^3);
|
||||
end
|
||||
end
|
||||
|
||||
if isfield(SpurParams, 'adc')
|
||||
a = SpurParams.adc;
|
||||
phase = 0;
|
||||
if isfield(a, 'phase'); phase = a.phase; end
|
||||
spur = spur + a.amp .* exp(1j*(2*pi*a.freq .* t + phase));
|
||||
end
|
||||
|
||||
if isfield(SpurParams, 'switch')
|
||||
s = SpurParams.switch;
|
||||
spur = spur + s.amp .* square(2*pi*s.freq .* t);
|
||||
end
|
||||
|
||||
if isfield(SpurParams, 'pulse')
|
||||
p = SpurParams.pulse;
|
||||
% duty default 50%
|
||||
duty = 0.5;
|
||||
if isfield(p,'duty'); duty = p.duty; end
|
||||
phase = 0;
|
||||
if isfield(p,'phase'); phase = p.phase; end
|
||||
% generate pulse train (0/1) scaled by amp
|
||||
% square with duty cycle multiplied then shifted to [0,1]
|
||||
pulse_wave = (square(2*pi*p.freq .* t + phase, duty*100)+1)/2;
|
||||
spur = spur + p.amp .* pulse_wave;
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user