Files
imdd_silas/Classes/01_transmit/AWG.m
Silas Oettinghaus ed17953407 Update April
2024-04-19 10:31:36 +02:00

189 lines
6.2 KiB
Matlab

classdef AWG
%AWG Summary of this class goes here
% Detailed explanation goes here
properties(Access=public)
kover %oversampling factor e.g. 16
repetitions %repeat the signal to generate a longer sequence?
fdac %needed
normalize %want to normalize at first? either 0 or 1
bit_resolution %bit res. of quantizer (e.g. 5 bit)
dac_min
dac_max
skew_active = 0;
awg_skew ; %skew vector for each output channel
lpf_active = 0;
lpf_type ;
f_cutoff ;
signal_length;
H_lpf;
end
methods (Access=public)
function obj = AWG(options)
%AWG Construct an instance of this class
% Detailed explanation goes here
arguments
options.kover = 16;
options.repetitions = 1;
options.normalize = 1;
options.fdac = 92e9;
options.bit_resolution = 5.5
options.dac_min = -0.5;
options.dac_max = 0.5;
options.skew_active = 0;
options.awg_skew = 0;
options.lpf_active = 0;
options.lpf_type = 0;
options.f_cutoff = 32e9;
options.H_lpf Filter
end
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
end
function signalclass_out = process(obj,signalclass_in)
len_in = length(signalclass_in.signal);
% 1-3. actual processing of the signal (normalize->quantize->sample hold)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% 4. Apply LPF on the signal
if obj.lpf_active
if isa(obj.H_lpf,'Filter')
%4.A) user already specified a complete filter class when
% initializing the AWG module
signalclass_in = obj.H_lpf.process(signalclass_in);
else
%4.B) just use a standard filter
lpf = Filter('filtdegree',5,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",obj.lpf_type);
signalclass_in = lpf.process(signalclass_in);
end
end
% cast the inform. signal to electrical signal
signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook);
% append to logbook
current_class = class(obj);
lbdesc = ['AWG ', current_class , '// k_over:',num2str(obj.kover),'. f_dac:',num2str(obj.fdac*1e-9),'GHz. Resolution:',num2str(obj.bit_resolution),' bits.'];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
len_out = length(signalclass_out.signal);
if len_out ~= len_in * obj.kover
warning("AWG: Output length maybe not correct.")
end
end
function elec_out = process_(obj,data_in)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
arguments(Input)
obj
data_in
end
arguments(Output)
elec_out
end
obj.signal_length = length(data_in);
if obj.normalize
% 0a Normalize the signal to 1 Vpp and set the amplitude of the signal
data_in = data_in/(max(data_in)-min(data_in));
else
% 0b Cut the Signal at -1 and 1 and scale to amplitude
data_in(data_in > 1) = 1;
data_in(data_in < -1) = -1;
end
% 1. Quantize the signal
if obj.bit_resolution>0
elec_out = obj.quantization(data_in) ;
else
elec_out = data_in;
end
% 2. Sample and hold + repeat (data_out: 1xsignal length)
elec_out = repmat(elec_out,obj.repetitions,obj.kover);
elec_out = reshape(elec_out',[],1);
% 3. Add skew (not implemented so far)
if obj.skew_active
elec_out = obj.skew(elec_out);
end
end
end
methods (Access=private)
function quant_out = quantization(obj,x_in)
steps = round(2^obj.bit_resolution) + rem(round(2^obj.bit_resolution),2) ;
if isreal(x_in)
% shift signal and clip to quantizer intervall
x_in = min(max(x_in-obj.dac_min,0),obj.dac_max-obj.dac_min);
% quantize signal
x_in = round((steps-1)/(obj.dac_max-obj.dac_min)*x_in);
% scale and shift back
quant_out = x_in*(obj.dac_max-obj.dac_min)/(steps-1) +obj.dac_min;
else
% shift signal and clip to quantizer intervall
x_in = min(max(real(x_in)-obj.dac_min,0),obj.dac_max-obj.dac_min) + ...
1i*min(max(imag(x_in)-obj.dac_min,0),obj.dac_max-obj.dac_min);
% quantize signal and shift back signal
x_in = round((steps-1)/(obj.max-obj.dac_min)*x_in);
% scale and shift back
quant_out = x_in*(obj.dac_max-obj.dac_min)/(steps-1) +(1+1i)*obj.dac_min;
end
end
function skew_out = skew(obj,x_in)
% Exact delay calculation
% Calculate transfer function
fsimu = obj.kover*obj.fdac;
faxis = linspace(fsimu/2, fsimu/2, length(x_in)+1);
faxis = fftshift(faxis(1:end-1));
skew_out = ifft(fft(x_in) .* exp(-1i*2*pi*obj.awg_skew*faxis)' );
skew_out = real(skew_out) ; % get rid of negligible imaginary part
end
end
end