Update April

This commit is contained in:
Silas Oettinghaus
2024-04-19 10:31:36 +02:00
parent 025498d120
commit ed17953407
30 changed files with 3261 additions and 1580 deletions

View File

@@ -4,7 +4,6 @@ classdef AWG
properties(Access=public)
preset
kover %oversampling factor e.g. 16
repetitions %repeat the signal to generate a longer sequence?
fdac %needed
@@ -32,7 +31,6 @@ classdef AWG
% Detailed explanation goes here
arguments
options.preset = 'none';
options.kover = 16;
options.repetitions = 1;
options.normalize = 1;
@@ -45,6 +43,7 @@ classdef AWG
options.lpf_active = 0;
options.lpf_type = 0;
options.f_cutoff = 32e9;
options.H_lpf Filter
end
fn = fieldnames(options);
@@ -54,40 +53,34 @@ classdef AWG
end
end
if options.preset == "M8196A"
% M8196A (92GBd) https://www.keysight.com/us/en/product/M8196A/92-gsa-s-arbitrary-waveform-generators.html
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.f_cutoff = 50e9;
elseif options.preset == "M8199B"
%https://www.keysight.com/us/en/assets/3120-1465/data-sheets/M8199A-128-256-GSa-s-Arbitrary-Waveform-Generator.pdf
% obj.fdac = 256e9;
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.f_cutoff = 80e9;
end
end
function signalclass_out = process(obj,signalclass_in)
len_in = length(signalclass_in.signal);
% actual processing of the signal (steps 1. - 3.)
% 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
lpf = Filter('filtdegree',5,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",obj.lpf_type);
signalclass_in = lpf.process(signalclass_in);
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
lbdesc = ['AWG preset ', obj.preset, 'k_over:',num2str(obj.kover),'. f_dac:',num2str(obj.fdac*1e-9),'GHz. Resolution:',num2str(obj.bit_resolution),' bits.'];
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

View File

@@ -0,0 +1,35 @@
classdef M8196A < AWG
properties
end
methods
function obj = M8196A()
%This is a ready to use AWG simulation that resembles the
%properties of the Keysighe M8196A % M8196A (92GBd) https://www.keysight.com/us/en/product/M8196A/92-gsa-s-arbitrary-waveform-generators.html
arguments
%options.bla = 1;
end
obj = obj@AWG();
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.bit_resolution = 5.5;
obj.fdac = 92e9;
obj.lpf_active = 1;
obj.f_cutoff = 32e9;
obj.lpf_type = filtertypes.gaussian;
obj.H_lpf = Filter('filtdegree',5,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",obj.lpf_type);
end
end
end

View File

@@ -0,0 +1,34 @@
classdef M8199B < AWG
properties
end
methods
function obj = M8199B()
%This is a ready to use AWG simulation that resembles the
%properties of the Keysighe M8199B https://www.keysight.com/us/en/assets/3120-1465/data-sheets/M8199A-128-256-GSa-s-Arbitrary-Waveform-Generator.pdf
arguments
%options.bla = 1;
end
obj = obj@AWG();
obj.dac_max = 0.5;
obj.dac_min = -.5;
obj.bit_resolution = 5.5;
obj.fdac = 256e9;
obj.lpf_active = 1;
obj.f_cutoff = 80e9;
obj.lpf_type = filtertypes.gaussian;
obj.H_lpf = Filter('filtdegree',5,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",obj.lpf_type);
end
end
end

View File

@@ -19,10 +19,16 @@ classdef PAMmapper
end
function signalclass_out = map(obj,signalclass_in)
signalclass_in.signal = obj.map_(signalclass_in.signal);
signalclass_in = signalclass_in.logbookentry();
signalclass_out = signalclass_in;
function out = map(obj,signal_in)
if isa(signal_in,'Signal')
signal_in.signal = obj.map_(signal_in.signal);
signal_in = signal_in.logbookentry();
out = signal_in;
else
out = signal_in;
end
end
function signalclass_out = demap(obj,signalclass_in)
@@ -157,7 +163,7 @@ classdef PAMmapper
case 2
% 4-ASK
data_out=[comp_real(:,:,2); ones(s1,s2)-comp_real(:,:,1)+comp_real(:,:,3)];
data_out=[comp_real(:,:,2); ones(s1,s2) - comp_real(:,:,1) + comp_real(:,:,3)];
case 3
@@ -179,16 +185,43 @@ classdef PAMmapper
end
function [data_out] = decide_pamlevel(obj,data_in)
function [data_out] = decide_pamlevel(obj,data_in,options)
arguments
obj
data_in Signal
options.symbol_levels = []
end
%A) normally return the preproduct of the decision
a = squeeze(repmat(real(data_in.signal),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten
b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in.signal) 1])); %Threshold in 3 Spalten
comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3
data_out = data_in;
data_out.signal = sum(comp_real,2);
%Option: return the actual level values/ just map onto given
%symbol levels
if ~isempty(options.symbol_levels)
data_out.signal = options.symbol_levels(data_out.signal+1);
end
end
data_out = sum(comp_real,2);
function [out] = separate_pamlevels(obj,data_in)
%A) normally return the preproduct of the decision
a = squeeze(repmat(real(data_in.signal),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten
b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in.signal) 1])); %Threshold in 3 Spalten
comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3
comp_real_sum = sum(comp_real,2);
%data_out = (data_out*2)-3;
out = NaN(length(data_in),length(obj.thresholds)+1);
for idx = 1:length(data_in)
out(idx,comp_real_sum(idx)+1) = data_in.signal(idx);
end
%data_out = pam_level_decision .* 1/sqrt(5);
end
end

View File

@@ -5,7 +5,7 @@ classdef Pulseformer
properties(Access=public)
fdac
fsym
pulseform
pulse
pulselength
rrcalpha
end
@@ -18,7 +18,7 @@ classdef Pulseformer
arguments
options.fdac double
options.fsym double
options.pulseform pulseform = pulseform.rrc
options.pulse pulseform = pulseform.rrc
options.pulselength double {mustBeInteger} = 32
options.rrcalpha double = 0.05
end
@@ -44,6 +44,9 @@ classdef Pulseformer
lbdesc = 'Applied Pulseshaping';
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write fs to signal
signalclass_in.fs = obj.fdac;
% write to output
signalclass_out = signalclass_in;
@@ -62,11 +65,11 @@ classdef Pulseformer
% Detailed explanation goes here
arguments(Input)
obj
data_in double
data_in
end
arguments(Output)
data_out double
data_out
end
if ~rem(obj.fdac,obj.fsym)
@@ -81,9 +84,9 @@ classdef Pulseformer
sps= up;
end
if obj.pulseform == pulseform.rrc
if obj.pulse == pulseform.rrc
%Bau das Filter (hier rrc)
racos_len = obj.pulselength*2 ;
racos_len = obj.pulselength*2;
alpha = obj.rrcalpha;
h = rcosdesign(alpha,racos_len,sps);
h = h./ max(h);
@@ -115,12 +118,13 @@ classdef Pulseformer
% %Apply Filter using Matlab build in fctn.
% data_out = upfirdn(data_in,h,up,dn);
h = rcosdesign(alpha,racos_len,sps);
h = h./ max(h);
%data_out_ = upfirdn(data_in,h,up,dn);
%
% %cut signal, which is longer due to fir filter
st = round(up/dn*racos_len/2); %we need to cut y_out
% en = round(st + (length(data_in)*up/dn) -1);
%
% data_out = data_out(st:en);
%scaling?! see pulsef module line 696