diff --git a/Classes/Moveit_wrapper.m b/Classes/Moveit_wrapper.m new file mode 100644 index 0000000..a518303 --- /dev/null +++ b/Classes/Moveit_wrapper.m @@ -0,0 +1,179 @@ +classdef Moveit_wrapper < handle + % + + properties(Access=public) + moveit_function_name + para + state = struct() + comment + end + + methods (Access=public) + function obj = Moveit_wrapper(moveit_function_name,options) + % + + arguments + moveit_function_name + options.para + end + + obj.moveit_function_name = moveit_function_name; + fn = fieldnames(options); + for n = 1:numel(fn) + try + obj.(fn{n}) = options.(fn{n}); + end + end + + % Ensure the function exists + if ~exist(obj.moveit_function_name, 'file') + error('Function "%s" does not exist.', obj.moveit_function_name); + end + + % Step 1: Get default parameters by calling moveit module + if isempty(obj.para) + global loop; + loop = 0; % Request parameter structure + [obj.para, obj.comment] = feval(obj.moveit_function_name); + end + + end + + function signalclass_out = process(obj,signal_in) + + isSignalClass = 0; + if isa(signal_in,"Signal") + signalclass_out = signal_in; + signal_in = signal_in.signal; + isSignalClass = 1; + end + input_len = length(signal_in); + + signal_in = signal_in.'; + + % INIT MOVEIT + global loop; + loop = 0; + signal_out = obj.moveit_init(signal_in); + + % RUN MOVEIT + global loop; + loop = 1; + signal_out = obj.moveit_init(signal_out); + + % CHECK IF SIGNAL CHANGED + if input_len ~= length(signal_out) + warning(['Signal length changed in moveit function: ', obj.moveit_function_name]); + end + + if isSignalClass + % append to logbook + lbdesc = ['Logbookentry']; + signalclass_out = signalclass_out.logbookentry(lbdesc); + signalclass_out.signal = signal_out; + end + + end + + function open_settings(obj) + % Opens a settings dialog for modifying Moveit parameters with appropriate input types. + % Inserts separators when the level value changes. + + fieldNames = fieldnames(obj.para); + settingsCell = {}; + previousLevel = -inf; % Track previous level for separators + + % Create input arguments for settingsdlg + for i = 1:numel(fieldNames) + fieldName = fieldNames{i}; + value = obj.para.(fieldName); + + % Get description from comment structure if available + if isfield(obj.comment, fieldName) + description = obj.comment.(fieldName); + else + description = fieldName; % Default to field name if no description + end + + % Get level for this parameter + if isfield(obj.comment.level, fieldName) + currentLevel = obj.comment.level.(fieldName); + else + currentLevel = 1; % Default level + end + + % Insert separator if the level changes + if currentLevel ~= previousLevel + settingsCell{end+1} = 'separator'; + settingsCell{end+1} = ['Level ', num2str(currentLevel)]; + end + previousLevel = currentLevel; + + % Determine input type from obj.comment.type + if + inputType = obj.comment.type.(fieldName); + else + inputType = 'number'; % Default type + end + + % Add field description + settingsCell{end+1} = {description; fieldName}; + + % Define the input type + if strcmp(inputType, 'boolean') + % Checkbox input + settingsCell{end+1} = logical(value); % Enable checkbox + elseif contains(inputType, '|') + % Dropdown selection (options separated by '|') + dropdownOptions = strsplit(inputType, '|'); + settingsCell{end+1} = dropdownOptions; + else + % Default: Numeric input + settingsCell{end+1} = value; + end + end + + % Open settings dialog + [newValues, button] = settingsdlg(... + 'title', ['Settings: ', obj.moveit_function_name], ... + 'description', ['Adjust parameters for ', obj.moveit_function_name], ... + settingsCell{:} ... + ); + + % Update obj.para with new values only if "OK" was pressed + if strcmp(button, 'OK') + fieldNames = fieldnames(newValues); + for i = 1:numel(fieldNames) + if fieldNames{i} + + end + obj.para.(fieldNames{i}) = newValues.(fieldNames{i}); + end + end + end + + end + + + methods (Access=private) + + function data_out = moveit_init(obj,data_in) + arguments(Input) + obj + data_in double + end + % Step 2: Initialize the function + [data_out, obj.state] = feval(obj.moveit_function_name, data_in, obj.state, obj.para); + end + + function data_out = moveit_simulation_computation(obj,data_in) + arguments(Input) + obj + data_in double + end + % Step 3: Process input signal + [data_out, obj.state] = feval(obj.moveit_function_name, data_in, obj.state, obj.para); + end + + end +end diff --git a/Classes/Warehouse_class/classes/StorageParameter.m b/Classes/Warehouse_class/classes/StorageParameter.m new file mode 100644 index 0000000..97ef06a --- /dev/null +++ b/Classes/Warehouse_class/classes/StorageParameter.m @@ -0,0 +1,44 @@ +classdef StorageParameter < handle + %PARAMETER Summary of this class goes here + % Detailed explanation goes here + + properties + name + values + indices + length + getPhysForIndex = dictionary; + getIndexForPhys = dictionary; + end + + methods + function obj = StorageParameter(name, values) + %PARAMETER Construct + obj.name = name; + obj.values = values; + obj.indices = [1:numel(obj.values)]; + obj.length = length(obj.values); + obj = obj.buildIndexForPhysDict(); + obj = obj.buildPhysForIndexDict(); + end + + function obj = buildPhysForIndexDict(obj) + %take Index + %return Phys + for idx = 1:numel(obj.values) + obj.getPhysForIndex(idx) = obj.values(idx); + end + end + + + function obj = buildIndexForPhysDict(obj) + %take Phys + %return Index + for idx = 1:numel(obj.values) + obj.getIndexForPhys(obj.values(idx)) = idx; + end + end + + end +end + diff --git a/Functions/moveit_wrapper_.m b/Functions/moveit_wrapper_.m new file mode 100644 index 0000000..d48daa0 --- /dev/null +++ b/Functions/moveit_wrapper_.m @@ -0,0 +1,40 @@ +function [data_out, state_out] = moveit_wrapper(func_name, data_in, para) + % Generic wrapper for legacy MATLAB functions using loop-based execution + % + % Usage: + % [data_out, state_out] = wrapper('quantize', data_in, para); + % + % Inputs: + % - func_name: Name of the function as a string (e.g., 'quantize') + % - data_in: Input signal or empty for initialization + % - para: Structure with parameters (optional) + % + % Outputs: + % - data_out: Processed output signal + % - state_out: Internal state of the function + + global loop; + + % Ensure the function exists + if ~exist(func_name, 'file') + error('Function "%s" does not exist.', func_name); + end + + % Step 1: Get default parameters if not provided + if nargin < 3 || isempty(para) + loop = 0; % Request parameter structure + [para, comment] = feval(func_name); + end + + % Initialize state + state = struct(); + + % Step 2: Initialize the function + loop = 0; + [~, state_] = feval(func_name, data_in, state, para); + + % Step 3: Process input signal + loop = 1; + [data_out, state_out] = feval(func_name, data_in, state_, para); + +end diff --git a/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_128GBd_2PAM__20250217T161301.h5 b/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_128GBd_2PAM__20250217T161301.h5 new file mode 100644 index 0000000..a66cf34 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_128GBd_2PAM__20250217T161301.h5 differ diff --git a/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_32GBd_2PAM__20250217T161634.h5 b/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_32GBd_2PAM__20250217T161634.h5 new file mode 100644 index 0000000..c29a4a2 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_-0dBm_P_PD_5p8dBm_W03C34-0409E03_32GBd_2PAM__20250217T161634.h5 differ diff --git a/projects/Messung_Zürich/Pmod_10p006dBm_P_PD_6p4732dBm_W03C34-0409E03_128GBd_4PAM__20250218T195459.h5 b/projects/Messung_Zürich/Pmod_10p006dBm_P_PD_6p4732dBm_W03C34-0409E03_128GBd_4PAM__20250218T195459.h5 new file mode 100755 index 0000000..483c5e4 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_10p006dBm_P_PD_6p4732dBm_W03C34-0409E03_128GBd_4PAM__20250218T195459.h5 differ diff --git a/projects/Messung_Zürich/Pmod_10p01dBm_P_PD_6p4727dBm_W03C34-0409E03_160GBd_2PAM__20250218T195221.h5 b/projects/Messung_Zürich/Pmod_10p01dBm_P_PD_6p4727dBm_W03C34-0409E03_160GBd_2PAM__20250218T195221.h5 new file mode 100755 index 0000000..1730dcf Binary files /dev/null and b/projects/Messung_Zürich/Pmod_10p01dBm_P_PD_6p4727dBm_W03C34-0409E03_160GBd_2PAM__20250218T195221.h5 differ diff --git a/projects/Messung_Zürich/Pmod_7p9772dBm_P_PD_6p477dBm_W03C34-0409E03_200GBd_2PAM__20250218T181515.h5 b/projects/Messung_Zürich/Pmod_7p9772dBm_P_PD_6p477dBm_W03C34-0409E03_200GBd_2PAM__20250218T181515.h5 new file mode 100755 index 0000000..d385cd8 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_7p9772dBm_P_PD_6p477dBm_W03C34-0409E03_200GBd_2PAM__20250218T181515.h5 differ diff --git a/projects/Messung_Zürich/Pmod_7p9943dBm_P_PD_6p4526dBm_W03C34-0409E03_160GBd_2PAM__20250218T181637.h5 b/projects/Messung_Zürich/Pmod_7p9943dBm_P_PD_6p4526dBm_W03C34-0409E03_160GBd_2PAM__20250218T181637.h5 new file mode 100755 index 0000000..ee78ab4 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_7p9943dBm_P_PD_6p4526dBm_W03C34-0409E03_160GBd_2PAM__20250218T181637.h5 differ diff --git a/projects/Messung_Zürich/Pmod_8p0011dBm_P_PD_6p4762dBm_W03C34-0409E03_64GBd_4PAM__20250218T181158.h5 b/projects/Messung_Zürich/Pmod_8p0011dBm_P_PD_6p4762dBm_W03C34-0409E03_64GBd_4PAM__20250218T181158.h5 new file mode 100755 index 0000000..9bf3ad0 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_8p0011dBm_P_PD_6p4762dBm_W03C34-0409E03_64GBd_4PAM__20250218T181158.h5 differ diff --git a/projects/Messung_Zürich/Pmod_8p0023dBm_P_PD_6p4776dBm_W03C34-0409E03_64GBd_2PAM__20250218T181323.h5 b/projects/Messung_Zürich/Pmod_8p0023dBm_P_PD_6p4776dBm_W03C34-0409E03_64GBd_2PAM__20250218T181323.h5 new file mode 100755 index 0000000..b0cdc20 Binary files /dev/null and b/projects/Messung_Zürich/Pmod_8p0023dBm_P_PD_6p4776dBm_W03C34-0409E03_64GBd_2PAM__20250218T181323.h5 differ diff --git a/projects/Messung_Zürich/Pmod_9p994dBm_P_PD_7p4733dBm_W03C34-0409E03_128GBd_4PAM__20250218T195746.h5 b/projects/Messung_Zürich/Pmod_9p994dBm_P_PD_7p4733dBm_W03C34-0409E03_128GBd_4PAM__20250218T195746.h5 new file mode 100755 index 0000000..ba0471f Binary files /dev/null and b/projects/Messung_Zürich/Pmod_9p994dBm_P_PD_7p4733dBm_W03C34-0409E03_128GBd_4PAM__20250218T195746.h5 differ diff --git a/projects/Messung_Zürich/dsp_ief_file.m b/projects/Messung_Zürich/dsp_ief_file.m new file mode 100644 index 0000000..28946ea --- /dev/null +++ b/projects/Messung_Zürich/dsp_ief_file.m @@ -0,0 +1,91 @@ + +% Get the script folder +scriptFolder = fileparts(mfilename('fullpath')); + +% Find the HDF5 file in the folder +files = dir(fullfile(scriptFolder, '*.h5')); +if isempty(files) + error('No HDF5 files found in the script folder.'); +end + +% Select the first matching file (modify as needed) +filename = files(6).name; +% filename = 'Pmod_8p0023dBm_P_PD_6p4776dBm_W03C34-0409E03_64GBd_2PAM__20250218T181323.h5'; + +% Extract parameters from the filename using an updated regex +tokens = regexp(filename, 'Pmod_([-0-9p]+)dBm_P_PD_([-0-9p]+)dBm_.*?_(\d+)GBd_(\d+)PAM__\d+T\d+', 'tokens'); +if isempty(tokens) + error('Filename format not recognized.'); +end + +tokens = tokens{1}; + +% Convert values +P_laser = str2double(strrep(tokens{1}, 'p', '.')); +P_pd = str2double(strrep(tokens{2}, 'p', '.')); +fsym = str2double(tokens{3}) * 1e9; % Convert GBd to Hz +M = str2double(tokens{4}); + +% Display results +fprintf('Loaded file: %s\n', filename); +fprintf('P_laser: %.3f dBm\n', P_laser); +fprintf('P_pd: %.3f dBm\n', P_pd); +fprintf('fsym: %.3f Hz\n', fsym); +fprintf('M: %d\n', M); + +%%% Load Data +folder = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/Messung_Zürich"; + +filepath = fullfile(folder,filename); +ief_ = h5info(filepath); + +fs_rx = h5readatt(filepath,'/','fs'); %sampling frequency at Rx +fs_tx = h5readatt(filepath, '/','fs_Tx'); %sampling frequency at Tx +fsym = h5readatt(filepath, '/','R'); %Baudrate +M = h5readatt(filepath, '/','M'); % PAM- 'M' +ROF = h5readatt(filepath, '/','ROF'); +PulseShape =h5readatt(filepath, '/','PulseShape'); + +yOrg = h5readatt(filepath, ief_.Groups(4).Groups(1).Name, 'YOrg'); +yInc = h5readatt(filepath, ief_.Groups(4).Groups(1).Name, 'YInc'); + +plotDisplayName = sprintf('P_{cw} = %.3f dBm, P_{PD} = %.3f dBm, f_{sym} = %.3f GBd, M = %d', ... + P_laser, P_pd, fsym / 1e9, M); + +dataRx = double(h5read(filepath, '/Waveforms/Channel 2/Channel 2Data')); % rohdaten des CH4 +bitsTx = h5read(filepath, '/Settings/dataTx'); %Binär +bitsTx = reshape(bitsTx,log2(M),[])'; + + +%%% Build Tx Signal (Bits, Pam Map, Symbols) +Tx_bits = Informationsignal(bitsTx); +Tx_symbols = PAMmapper(M,0,"eth_style",1).map(Tx_bits); +Tx_symbols.fs = fsym; +% Tx_symbols.plot("fignum",1,"displayname",'Rx Signal'); +% Tx_symbols.move_it_spectrum("fignum",2,"displayname",'tx spectrum'); +% Tx_symbols.spectrum("fignum",3,"displayname",'Rx Signal','normalizeTo0dB',0); + + +%%% Build Rx Signal (Rx, normalize,remove mean) +dataRx = dataRx*yInc+yOrg; +Rx_Sig = Informationsignal(dataRx,"fs",fs_rx); +Rx_Sig = Rx_Sig.normalize("mode","rms"); +% Rx_Sig.power(); +% Rx_Sig.eye(fsym,M,"fignum",4,"displayname",'eye diagram'); +% Rx_Sig.plot("fignum",5,"displayname",'Rx Signal'); +% Rx_Sig.move_it_spectrum("fignum",6,"displayname",'tx spectrum'); +Rx_Sig.spectrum("fignum",3,"displayname",'Rx Signal','normalizeTo0dB',0); + +%%%%%% Sample to 2x fsym %%%%%% +Rx_Sig_resamp = Rx_Sig.resample("fs_out",2*fsym); + +%%%%%% Sync Rx signal with reference (S is a cell array with all occurences) %%%%%% +[Rx_Sig_sync,S,isFlipped] = Rx_Sig_resamp.tsynch("reference",Tx_symbols,"fs_ref",fsym,"debug_plots",0); + +eq_vnle_dfe = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",1,"ideal_dfe",0); + +[result] = vnle(eq_vnle_dfe,M,Rx_Sig_sync,Tx_symbols,Tx_bits,"precode_mode",db_mode.no_db,"showAnalysis",1,'eth_style',1); + + + + diff --git a/test/matched_filter_minimal.m b/test/matched_filter_minimal.m new file mode 100644 index 0000000..9a5d413 --- /dev/null +++ b/test/matched_filter_minimal.m @@ -0,0 +1,51 @@ +%%% Run parameters +% TX +M = 4; +fsym = 32e9; + +apply_pulsef = 1; +fdac = 256e9; +fadc = 256e9; +random_key = 1; + +precomp = 0; +db_precode = 0; + +db_encode = 0; + +rcalpha = 0.05; +kover = 16; +vbias_rel = 0.5; +u_pi = 2.9; +vbias = -vbias_rel*u_pi; +laser_wavelength = 1293; +laser_linewidth = 0; +tx_bw_nyquist = 0.8; + +% 1) PRBS Generation +O = 18; %order of prbs +N = 2^(O-1); %length of prbs + +rcalpha = 1; +Pform = Pulseformer("fsym",fsym,"fdac",fdac,"pulse","rrc","pulselength",1024,"alpha",rcalpha); + + + +[Digi_sig,Symbols,Tx_bits] = PAMsource(... + "fsym",fsym,"M",M,"order",18,"useprbs",0,... + "fs_out",fdac,... + "applyclipping",0,"clipfactor",1.5,... + "applypulseform",apply_pulsef,"pulseformer",Pform,... + "randkey",random_key,... + "db_precode",db_precode,"db_encode",db_encode,... + "mrds_code",0,"mrds_blocklength",512).process(); + +Digi_sig.spectrum("displayname",'Signal after shaping','fignum',1); +% Digi_sig.move_it_spectrum("displayname",'Signal after shaping','fignum',2); + +% Digi_sig = Digi_sig.resample("fs_out",fsym); + +MF = Pulseformer("fsym",fsym,"fdac",fdac,"pulse","rrc","pulselength",1024,"alpha",rcalpha,"matched",0); +Digi_sig = MF.process(Digi_sig); + +Digi_sig.spectrum("displayname",'Signal after shaping','fignum',1); diff --git a/test/test_mapping_eth.m b/test/test_mapping_eth.m new file mode 100644 index 0000000..c3e1cc9 --- /dev/null +++ b/test/test_mapping_eth.m @@ -0,0 +1,29 @@ + +% Setup PRBS parameters +O = 12; +M = 2; +N = 2^(O-1); % Length of PRBS +randkey = 1; % Random key for random stream + +[~, seed] = prbs(O, 1); % Initialize first seed of PRBS +bitpattern = []; + +s = RandStream('twister', 'Seed', randkey); +for i = 1:log2(M) + bitpattern(:, i) = randi(s, [0 1], N, 1); +end + +Tx_bits = Informationsignal(bitpattern); + +Digi_Mod = PAMmapper(M, 0,"eth_style",1); + +% Map bits to symbols +Symbols = Digi_Mod.map(Tx_bits); + +% Demap symbols back to bits +Rx_bits = Digi_Mod.demap(Symbols); + +[~, error_num, ber, ~] = calc_ber(Tx_bits.signal, Rx_bits.signal, ... + "skip_front", 0, "skip_end", 0, "returnErrorLocation", 1); + +fprintf('BER VNLE: %.1E \n',ber); \ No newline at end of file