classdef AWG %AWG Summary of this class goes here % Detailed explanation goes here properties(Access=public) kover %oversampling factor e.g. 16 upsampling_method repetitions %repeat the signal to generate a longer sequence? fdac %needed normalize2dac %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.upsampling_method upsampling_mode options.repetitions = 1; options.normalize2dac = 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); if signalclass_in.fs ~= obj.fdac signalclass_in = signalclass_in.resample("fs_in",signalclass_in.fs,"fs_out",obj.fdac); end % 1-3. actual processing of the signal (normalize->quantize->sample hold) signalclass_in.signal = obj.process_(signalclass_in.signal); % cast the inform. signal to electrical signal signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook); % normalize to 0dBm before applying the lowpass %signalclass_in = signalclass_in.normalize("mode","milliwatt"); signalclass_in = signalclass_in.setPower(12,"dBm"); % 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 % 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.normalize2dac % 0a Normalize the signal to full scale DAC range data_in = data_in - min(data_in); data_in = data_in/(max(data_in)-min(data_in)); data_in = data_in * (obj.dac_max-obj.dac_min); data_in = data_in + obj.dac_min; end % 1. Quantize the signal - Full Scale is between obj.dac_min % and dac_max. If signal is smaller in between, you won't use % the full bit-resolution. 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) if obj.upsampling_method == 1 % just use matlab function elec_out = resample(elec_out,obj.kover,1); elseif obj.upsampling_method == 2 % sample and hold elec_out = repmat(elec_out,obj.repetitions,obj.kover); elec_out = reshape(elec_out',[],1); else error('chosen upsampling method not implemented?'); end % 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