diff --git a/.DS_Store b/.DS_Store index a620921..8db142e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Classes/01_transmit/ChannelFreqResp.m b/Classes/01_transmit/ChannelFreqResp.m index d927257..592e932 100644 --- a/Classes/01_transmit/ChannelFreqResp.m +++ b/Classes/01_transmit/ChannelFreqResp.m @@ -47,9 +47,9 @@ classdef ChannelFreqResp < handle % Detailed explanation goes here arguments - options.Nacq = 4096; - options.Navg = 30; - options.Ncp = 100; + options.Nacq = 1024; + options.Navg = 64; + options.Ncp = 63; options.f_ref; options.f_observe; end @@ -188,8 +188,12 @@ classdef ChannelFreqResp < handle if 0 figure(7);hold on;plot(fnew,20*log10(abs(iH))) end + + % iH(1) is DC ---> iH(end) is High Freq. H_inv = [iH(1) iH fliplr(conj(iH)) conj(iH(1))]; + H_inv = [iH(1) iH iH(end) fliplr(conj(iH)) conj(iH(1))]; + obj.H_apply = H_inv; Target.signal = real((ifft( ( fft(real( Target.signal )) .* H_inv' ) ))); diff --git a/Classes/01_transmit/PAMmapper.m b/Classes/01_transmit/PAMmapper.m index 2a66d6d..9414d2e 100644 --- a/Classes/01_transmit/PAMmapper.m +++ b/Classes/01_transmit/PAMmapper.m @@ -6,6 +6,8 @@ classdef PAMmapper M unipolar thresholds + levels + scaling end methods @@ -17,6 +19,10 @@ classdef PAMmapper obj.thresholds = obj.get_demodulation_thresholds(); + obj.levels = obj.get_levels(); + + obj.scaling = rms(obj.get_levels()); + end @@ -111,6 +117,19 @@ classdef PAMmapper %28.03.2023 - Silas Oett. - Extracted from digi_demod.m % + % switch obj.M + % case 2 + % thres = 0; + % case 4 + % thres = [-2 0 2]; + % case 6 + % thres = [-3 5;-1 5;-3 -5;-1 -5;-5 3;-5 1;-5 -3;-5 -1;-1 3;-1 1;-1 -3;-1 -1;-3 3;-3 1;-3 -3;-3 -1;3 5;1 5;3 -5;1 -5;5 3;5 1;5 -3;5 -1;1 3;1 1;1 -3;1 -1;3 3;3 1;3 -3;3 -1]; + % case 8 + % thres = [-6 -4 -2 0 2 4 6]; + % case 16 + % thres = [-10 -8 -6 -4 -2 0 2 4 6 8 10]; + % end + switch obj.M @@ -159,6 +178,22 @@ classdef PAMmapper end + function levels = get_levels(obj) + switch obj.M + case 2 + levels = [-1 1]; + case 4 + levels = [-3 -1 1 3]; + case 6 + levels = [-5 -3 -1 1 3 5]; + case 8 + levels = [-7 -5 -3 -1 1 3 5 7]; + case 16 + levels = [-11 -9 -7 -5 -3 -1 1 3 5 7 9 11]; + end + end + + function [data_out] = demap_(obj,data_in) data_in= data_in'; if obj.M ~= 6 diff --git a/Classes/04_DSP/Coding/Duobinary.m b/Classes/04_DSP/Coding/Duobinary.m index 8049078..a9e76c1 100644 --- a/Classes/04_DSP/Coding/Duobinary.m +++ b/Classes/04_DSP/Coding/Duobinary.m @@ -11,27 +11,17 @@ classdef Duobinary function obj = Duobinary() %NAME Construct an instance of this class - % Detailed explanation goes here - - arguments - - end - - % % - % fn = fieldnames(options); - % for n = 1:numel(fn) - % try - % obj.(fn{n}) = options.(fn{n}); - % end - % end - - % do more stuff end - function signalclass = precode(~,signalclass) + function signal = precode(~,signal) + + if isa(signal,'Signal') + data = signal.signal; + else + data = signal; + end - data = signalclass.signal; u = unique(data); M = numel(u); @@ -66,21 +56,34 @@ classdef Duobinary bk = bk + b; if M == 4 - bk = bk ./ sqrt(5); + bk = bk ./ sqrt(5); elseif M == 6 bk = bk ./ sqrt(10); elseif M == 8 - bk = bk ./ sqrt(21); + bk = bk ./ sqrt(21); + end + + assert(isequal(unique(bk),u),'Check Duobinary Precoding'); %seems the signal is not the same as before + + + if isa(signal,'Signal') + signal.signal = bk; + else + signal = bk; end - signalclass.signal = bk; - assert(isequal(unique(signalclass.signal),u),'Check Duobinary Precoding'); %seems the signal is not the same as before - end - function signalclass = encode(~,signalclass) - - data = signalclass.signal; + function signal = encode(~,signal) + + if isa(signal,'Signal') + data = signal.signal; + else + data = signal; + end + + data = data./rms(data); + u = unique(data); M = numel(u); @@ -102,7 +105,7 @@ classdef Duobinary data = data ./ 2; assert(isequal((0:M-1)',unique(data)),'Check Duobinary Precoding'); %seems the signal is not unipolar - + % duobinary coding (1+D) coeff = [1,1]; @@ -119,7 +122,11 @@ classdef Duobinary data = data ./ sqrt(10.5); % 15-level constellation weighted with probability after DB code i.e. end - signalclass.signal = data; + if isa(signal,'Signal') + signal.signal = data; + else + signal = data; + end % Code to evaluate the s in sqrt(s): % M=6; @@ -138,7 +145,7 @@ classdef Duobinary data = signalclass.signal; u = unique(data); I = numel(u); %number of duobinary coded const. points - M = (I+1)/2; %PAM-M order + M = (I+1)/2; %PAM-M order %make unipolar if I == 7 @@ -166,11 +173,11 @@ classdef Duobinary data = data - round(mean(data)); if M == 4 - data = data ./ sqrt(5); + data = data ./ sqrt(5); elseif M == 6 data = data ./ sqrt(10); elseif M == 8 - data = data ./ sqrt(21); + data = data ./ sqrt(21); end signalclass.signal = data; @@ -180,7 +187,7 @@ classdef Duobinary data = signalclass.signal; u = unique(data); I = numel(u); %number of duobinary coded const. points - M = (I+1)/2; %PAM-M order + M = (I+1)/2; %PAM-M order %make unipolar if I == 7 @@ -206,11 +213,11 @@ classdef Duobinary %%FALSCH! for k = 1:length(data)-1 - d_ = data(k+1) - data_out(k); - - [~,b] = min(abs(d_-[0:M-1])); + d_ = data(k+1) - data_out(k); - data_out(k+1) = const(b); + [~,b] = min(abs(d_-[0:M-1])); + + data_out(k+1) = const(b); end @@ -219,13 +226,13 @@ classdef Duobinary data_out = data_out - round(mean(data_out)); if M == 4 - data_out = data_out ./ sqrt(5); + data_out = data_out ./ sqrt(5); elseif M == 6 data_out = data_out ./ sqrt(10); elseif M == 8 - data_out = data_out ./ sqrt(21); + data_out = data_out ./ sqrt(21); end - + signalclass.signal = data_out; diff --git a/Classes/04_DSP/Sequence Detection/MLSE.m b/Classes/04_DSP/Sequence Detection/MLSE.m new file mode 100644 index 0000000..29d1f8e --- /dev/null +++ b/Classes/04_DSP/Sequence Detection/MLSE.m @@ -0,0 +1,165 @@ +classdef MLSE + %MLSE calculates the most probable sequence for an input signal with given/ known channel impulse response of any length + + properties(Access=public) + M %PAM-M + DIR + trellis_states + duobinary_output + end + + methods (Access=public) + + function obj = MLSE(options) + %NAME Construct an instance of this class + % Detailed explanation goes here + + arguments + options.M double = 4; + options.DIR double = [1]; + options.trellis_states double = [-3 -1 1 3]; + options.duobinary_output logical = false; + + end + + % + fn = fieldnames(options); + for n = 1:numel(fn) + try + obj.(fn{n}) = options.(fn{n}); + end + end + + % do more stuff + + end + + function signalclass = process(obj,signalclass) + + data_in = signalclass.signal; + + data_out = obj.process_(data_in); + + signalclass.signal = data_out; + + end + + function data_out = process_(obj,data_in) + + + % remove unnecessary zeros at start of impulse response to keep + % number of trellis states minimal + DIR_nonzero = find(obj.DIR ~= 0); + if DIR_nonzero(1) > 1 + obj.DIR(1:DIR_nonzero(1)-1) = []; + end + + if length(obj.DIR) == 1 + obj.DIR = [0 obj.DIR]; + end + + % RMS normalization of input data + data_in = data_in ./ rms(data_in); + + % seems to be the only way to use combvec for a flexible amount + % of vectors. 'combs' contains all trellis states + pre_comb_mat = repmat(obj.trellis_states,length(obj.DIR)-1,1); + pre_comb_cell = mat2cell(pre_comb_mat,ones(1,size(pre_comb_mat,1)),size(pre_comb_mat,2)); + combs = fliplr(combvec(pre_comb_cell{:}).'); + + % Save first and last symbol of each state + first_sym = combs(:,1); + last_sym = combs(:,end); + states = sum(combs,2); + + % Calculate all possible input symbols for the desired impulse + % response. Row number is the index of the previous state, + % column number is the index of the next state + noise_free_received = zeros(length(states),length(states)); + count_row = 1; + count_col = 1; + for l1 = 1:length(states) + for l2 = 1:length(states) + if sum(combs(l2,2:end) == combs(l1,1:end-1)) == size(combs,2)-1 + noise_free_received(count_row,count_col) = sum(combs(l2,:).*obj.DIR(end:-1:2)) + last_sym(l1)*obj.DIR(1); + else + noise_free_received(count_row,count_col) = inf; + end + count_row = count_row + 1; + end + count_col = count_col + 1; + count_row = 1; + end + + % match amplitude levels of input signal to those of the calculated ideal symbols + % i.e. match the rms values of data_in to noise_free_received + if isreal(data_in) + if obj.M == round(obj.M) + data_in = data_in * rms(noise_free_received,'all','omitnan'); + end + end + + % initilaize the output vector + data_out = NaN(size(data_in)); + + sum_path_metrics = zeros(length(states),length(states)); + + % first trellis path + % euclidian distance as path metric + path_metrics = (abs(repmat(data_in(1),size(noise_free_received)) - noise_free_received)).^2; + sum_path_metrics = sum_path_metrics + path_metrics; % calculation of all possible sum path metrics + [sum_path_metrics_res(:,1),path_idx(:,1)] = min(sum_path_metrics,[],2); % find the best path to each state, store sum path metric and predecessor for each state + + % remaining trellis paths + for n = 2:length(data_in) + sum_path_metrics = repmat(sum_path_metrics_res(:,n-1).',length(states),1); + % path_metrics = (repmat(data_in(n),size(noise_free_received)) - noise_free_received).^2;%.*prob_mat; + path_metrics = (abs(repmat(data_in(n),size(noise_free_received)) - noise_free_received)).^2; + sum_path_metrics = sum_path_metrics + path_metrics; + [sum_path_metrics_res(:,n),path_idx(:,n)] = min(sum_path_metrics,[],2); + end + + %% trace back + ideal_path = NaN(1,length(data_in)+1); + % find ideal trellis path by going through the trellis + % backwards + [~,ideal_path(length(data_in)+1)] = min(sum_path_metrics_res(:,length(data_in))); + + % starting with the state that has the lowest sum path + % metric, follow the stored information about the + % predecessor + for h = length(data_in):-1:1 + ideal_path(h) = path_idx(ideal_path(h+1),h); + end + + idx_out = ideal_path(1:length(data_in)); + + if obj.duobinary_output + %use duobinary encoder, output is already scaled inside this + %one + data_out = Duobinary().encode(first_sym(idx_out)); + else + % + data_out(1:length(data_in)) = first_sym(idx_out); + % scale to rms = 1 using the standard sqrt() expressions + if obj.M == 4 + data_out = data_out./sqrt(5); + elseif obj.M == 6 + data_out = data_out./sqrt(10); + elseif obj.M == 8 + data_out = data_out./sqrt(21); + end + + end + + + end + end + + methods (Access=private) + % Cant be seen from outside! So put all your functions here that can/ + % shall not be called from outside + + + end +end diff --git a/Tests/00_signals/Electricalsignal_test.m b/Tests/00_signals/Electricalsignal_test.m new file mode 100644 index 0000000..2ea6ea4 --- /dev/null +++ b/Tests/00_signals/Electricalsignal_test.m @@ -0,0 +1,11 @@ +classdef Electricalsignal_test < matlab.unittest.TestCase + % Test class for Electricalsignal + + methods (Test) + function testExample(testCase) + % Example test case for Electricalsignal + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/00_signals/Informationsignal_test.m b/Tests/00_signals/Informationsignal_test.m new file mode 100644 index 0000000..46016a6 --- /dev/null +++ b/Tests/00_signals/Informationsignal_test.m @@ -0,0 +1,11 @@ +classdef Informationsignal_test < matlab.unittest.TestCase + % Test class for Informationsignal + + methods (Test) + function testExample(testCase) + % Example test case for Informationsignal + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/00_signals/Opticalsignal_test.m b/Tests/00_signals/Opticalsignal_test.m new file mode 100644 index 0000000..0a03c6a --- /dev/null +++ b/Tests/00_signals/Opticalsignal_test.m @@ -0,0 +1,11 @@ +classdef Opticalsignal_test < matlab.unittest.TestCase + % Test class for Opticalsignal + + methods (Test) + function testExample(testCase) + % Example test case for Opticalsignal + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/00_signals/Signal_test.m b/Tests/00_signals/Signal_test.m new file mode 100644 index 0000000..ffa47c0 --- /dev/null +++ b/Tests/00_signals/Signal_test.m @@ -0,0 +1,11 @@ +classdef Signal_test < matlab.unittest.TestCase + % Test class for Signal + + methods (Test) + function testExample(testCase) + % Example test case for Signal + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/AWG_test.m b/Tests/01_transmit/AWG_test.m new file mode 100644 index 0000000..0c9b773 --- /dev/null +++ b/Tests/01_transmit/AWG_test.m @@ -0,0 +1,11 @@ +classdef AWG_test < matlab.unittest.TestCase + % Test class for AWG + + methods (Test) + function testExample(testCase) + % Example test case for AWG + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/ChannelFreqResp_test.m b/Tests/01_transmit/ChannelFreqResp_test.m new file mode 100644 index 0000000..abcadfc --- /dev/null +++ b/Tests/01_transmit/ChannelFreqResp_test.m @@ -0,0 +1,11 @@ +classdef ChannelFreqResp_test < matlab.unittest.TestCase + % Test class for ChannelFreqResp + + methods (Test) + function testExample(testCase) + % Example test case for ChannelFreqResp + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/M8196A_test.m b/Tests/01_transmit/M8196A_test.m new file mode 100644 index 0000000..3884637 --- /dev/null +++ b/Tests/01_transmit/M8196A_test.m @@ -0,0 +1,11 @@ +classdef M8196A_test < matlab.unittest.TestCase + % Test class for M8196A + + methods (Test) + function testExample(testCase) + % Example test case for M8196A + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/M8199A_test.m b/Tests/01_transmit/M8199A_test.m new file mode 100644 index 0000000..545ba8d --- /dev/null +++ b/Tests/01_transmit/M8199A_test.m @@ -0,0 +1,11 @@ +classdef M8199A_test < matlab.unittest.TestCase + % Test class for M8199A + + methods (Test) + function testExample(testCase) + % Example test case for M8199A + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/M8199B_test.m b/Tests/01_transmit/M8199B_test.m new file mode 100644 index 0000000..45a3cc0 --- /dev/null +++ b/Tests/01_transmit/M8199B_test.m @@ -0,0 +1,11 @@ +classdef M8199B_test < matlab.unittest.TestCase + % Test class for M8199B + + methods (Test) + function testExample(testCase) + % Example test case for M8199B + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/PAMmapper_test.m b/Tests/01_transmit/PAMmapper_test.m new file mode 100644 index 0000000..70b37d8 --- /dev/null +++ b/Tests/01_transmit/PAMmapper_test.m @@ -0,0 +1,67 @@ +classdef PAMmapper_test < matlab.unittest.TestCase + + properties + Digi_Mod + Tx_bits + Rx_bits + % M = 8; % Modulation order + fsym = 112e9; % Symbol rate + + end + + properties (TestParameter) + M = {4,6,8}; + end + + methods (TestMethodSetup) + function setupModulation(testCase) + % Setup PRBS and bit pattern for the test case + O = 10; % Order of PRBS + N = 2^(O-1); % Length of PRBS + useprbs = 1; % Flag to use PRBS + randkey = 1; % Random key for random stream + + [~, seed] = prbs(O, 1); % Initialize first seed of PRBS + bitpattern = []; + if useprbs + for i = 1:log2(testCase.M) + [bitpattern(:, i), seed] = prbs(O, N, seed); + end + else + s = RandStream('twister', 'Seed', randkey); + for i = 1:log2(testCase.M) + bitpattern(:, i) = randi(s, [0 1], N, 1); + end + end + + if testCase.M == 6 + bitpattern = reshape(bitpattern, [], 1); + bitpattern = bitpattern(1:end-mod(length(bitpattern), 5)); + end + + testCase.Tx_bits = Informationsignal(bitpattern); + testCase.Digi_Mod = PAMmapper(testCase.M, 0); + end + end + + methods (Test) + function testBackToBackMapping(testCase) + % Test Bits -> Symbols -> Bits (Back-to-Back Mapping) + + % Map bits to symbols + Symbols = testCase.Digi_Mod.map(testCase.Tx_bits); + + % Demap symbols back to bits + testCase.Rx_bits = testCase.Digi_Mod.demap(Symbols); + + % Validate BER is zero + [~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, testCase.Rx_bits.signal, ... + "skip_front", 0, "skip_end", 0, "returnErrorLocation", 1); + + % Assert that BER is zero + testCase.verifyEqual(ber, 0, 'BER should be zero'); + testCase.verifyEqual(error_num, 0, 'No errors should occur in the mapping process'); + end + end + +end diff --git a/Tests/01_transmit/PAMsource_test.m b/Tests/01_transmit/PAMsource_test.m new file mode 100644 index 0000000..1e0e8c0 --- /dev/null +++ b/Tests/01_transmit/PAMsource_test.m @@ -0,0 +1,11 @@ +classdef PAMsource_test < matlab.unittest.TestCase + % Test class for PAMsource + + methods (Test) + function testExample(testCase) + % Example test case for PAMsource + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/Pulseformer_test.m b/Tests/01_transmit/Pulseformer_test.m new file mode 100644 index 0000000..0adc015 --- /dev/null +++ b/Tests/01_transmit/Pulseformer_test.m @@ -0,0 +1,11 @@ +classdef Pulseformer_test < matlab.unittest.TestCase + % Test class for Pulseformer + + methods (Test) + function testExample(testCase) + % Example test case for Pulseformer + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/01_transmit/Signalgenerator_test.m b/Tests/01_transmit/Signalgenerator_test.m new file mode 100644 index 0000000..23fe43c --- /dev/null +++ b/Tests/01_transmit/Signalgenerator_test.m @@ -0,0 +1,11 @@ +classdef Signalgenerator_test < matlab.unittest.TestCase + % Test class for Signalgenerator + + methods (Test) + function testExample(testCase) + % Example test case for Signalgenerator + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/02_etc/Amplifier_test.m b/Tests/02_etc/Amplifier_test.m new file mode 100644 index 0000000..e89bf93 --- /dev/null +++ b/Tests/02_etc/Amplifier_test.m @@ -0,0 +1,11 @@ +classdef Amplifier_test < matlab.unittest.TestCase + % Test class for Amplifier + + methods (Test) + function testExample(testCase) + % Example test case for Amplifier + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/02_etc/Filter_test.m b/Tests/02_etc/Filter_test.m new file mode 100644 index 0000000..133155b --- /dev/null +++ b/Tests/02_etc/Filter_test.m @@ -0,0 +1,11 @@ +classdef Filter_test < matlab.unittest.TestCase + % Test class for Filter + + methods (Test) + function testExample(testCase) + % Example test case for Filter + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/02_optical/EML_test.m b/Tests/02_optical/EML_test.m new file mode 100644 index 0000000..9c76f63 --- /dev/null +++ b/Tests/02_optical/EML_test.m @@ -0,0 +1,11 @@ +classdef EML_test < matlab.unittest.TestCase + % Test class for EML + + methods (Test) + function testExample(testCase) + % Example test case for EML + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/02_optical/Fiber_test.m b/Tests/02_optical/Fiber_test.m new file mode 100644 index 0000000..46acb59 --- /dev/null +++ b/Tests/02_optical/Fiber_test.m @@ -0,0 +1,11 @@ +classdef Fiber_test < matlab.unittest.TestCase + % Test class for Fiber + + methods (Test) + function testExample(testCase) + % Example test case for Fiber + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/03_receive/Photodiode_test.m b/Tests/03_receive/Photodiode_test.m new file mode 100644 index 0000000..1973be6 --- /dev/null +++ b/Tests/03_receive/Photodiode_test.m @@ -0,0 +1,11 @@ +classdef Photodiode_test < matlab.unittest.TestCase + % Test class for Photodiode + + methods (Test) + function testExample(testCase) + % Example test case for Photodiode + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/03_receive/Scope_test.m b/Tests/03_receive/Scope_test.m new file mode 100644 index 0000000..c0ea689 --- /dev/null +++ b/Tests/03_receive/Scope_test.m @@ -0,0 +1,11 @@ +classdef Scope_test < matlab.unittest.TestCase + % Test class for Scope + + methods (Test) + function testExample(testCase) + % Example test case for Scope + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Coding/Duobinary_test.m b/Tests/04_DSP/Coding/Duobinary_test.m new file mode 100644 index 0000000..c6be6b4 --- /dev/null +++ b/Tests/04_DSP/Coding/Duobinary_test.m @@ -0,0 +1,11 @@ +classdef Duobinary_test < matlab.unittest.TestCase + % Test class for Duobinary + + methods (Test) + function testExample(testCase) + % Example test case for Duobinary + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Coding/MRDS_coding_test.m b/Tests/04_DSP/Coding/MRDS_coding_test.m new file mode 100644 index 0000000..828d0e2 --- /dev/null +++ b/Tests/04_DSP/Coding/MRDS_coding_test.m @@ -0,0 +1,11 @@ +classdef MRDS_coding_test < matlab.unittest.TestCase + % Test class for MRDS_coding + + methods (Test) + function testExample(testCase) + % Example test case for MRDS_coding + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_copy_test.m b/Tests/04_DSP/Equalizer/EQ_copy_test.m new file mode 100644 index 0000000..a8439f6 --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_copy_test.m @@ -0,0 +1,11 @@ +classdef EQ_copy_test < matlab.unittest.TestCase + % Test class for EQ_copy + + methods (Test) + function testExample(testCase) + % Example test case for EQ_copy + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_silas_ofc_test.m b/Tests/04_DSP/Equalizer/EQ_silas_ofc_test.m new file mode 100644 index 0000000..4f7a45a --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_silas_ofc_test.m @@ -0,0 +1,11 @@ +classdef EQ_silas_ofc_test < matlab.unittest.TestCase + % Test class for EQ_silas_ofc + + methods (Test) + function testExample(testCase) + % Example test case for EQ_silas_ofc + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_silas_plain_test.m b/Tests/04_DSP/Equalizer/EQ_silas_plain_test.m new file mode 100644 index 0000000..4cb4bcc --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_silas_plain_test.m @@ -0,0 +1,11 @@ +classdef EQ_silas_plain_test < matlab.unittest.TestCase + % Test class for EQ_silas_plain + + methods (Test) + function testExample(testCase) + % Example test case for EQ_silas_plain + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_silas_sliding_window_dc_removal_test.m b/Tests/04_DSP/Equalizer/EQ_silas_sliding_window_dc_removal_test.m new file mode 100644 index 0000000..9777ed3 --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_silas_sliding_window_dc_removal_test.m @@ -0,0 +1,11 @@ +classdef EQ_silas_sliding_window_dc_removal_test < matlab.unittest.TestCase + % Test class for EQ_silas_sliding_window_dc_removal + + methods (Test) + function testExample(testCase) + % Example test case for EQ_silas_sliding_window_dc_removal + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_silas_test.m b/Tests/04_DSP/Equalizer/EQ_silas_test.m new file mode 100644 index 0000000..e86d7d4 --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_silas_test.m @@ -0,0 +1,11 @@ +classdef EQ_silas_test < matlab.unittest.TestCase + % Test class for EQ_silas + + methods (Test) + function testExample(testCase) + % Example test case for EQ_silas + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/EQ_test.m b/Tests/04_DSP/Equalizer/EQ_test.m new file mode 100644 index 0000000..4ebbcb5 --- /dev/null +++ b/Tests/04_DSP/Equalizer/EQ_test.m @@ -0,0 +1,11 @@ +classdef EQ_test < matlab.unittest.TestCase + % Test class for EQ + + methods (Test) + function testExample(testCase) + % Example test case for EQ + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/FFE_DCremoval_test.m b/Tests/04_DSP/Equalizer/FFE_DCremoval_test.m new file mode 100644 index 0000000..c88e70b --- /dev/null +++ b/Tests/04_DSP/Equalizer/FFE_DCremoval_test.m @@ -0,0 +1,11 @@ +classdef FFE_DCremoval_test < matlab.unittest.TestCase + % Test class for FFE_DCremoval + + methods (Test) + function testExample(testCase) + % Example test case for FFE_DCremoval + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/FFE_DFE_test.m b/Tests/04_DSP/Equalizer/FFE_DFE_test.m new file mode 100644 index 0000000..513545a --- /dev/null +++ b/Tests/04_DSP/Equalizer/FFE_DFE_test.m @@ -0,0 +1,11 @@ +classdef FFE_DFE_test < matlab.unittest.TestCase + % Test class for FFE_DFE + + methods (Test) + function testExample(testCase) + % Example test case for FFE_DFE + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/FFE_FFDCAVG_test.m b/Tests/04_DSP/Equalizer/FFE_FFDCAVG_test.m new file mode 100644 index 0000000..f72fcc2 --- /dev/null +++ b/Tests/04_DSP/Equalizer/FFE_FFDCAVG_test.m @@ -0,0 +1,11 @@ +classdef FFE_FFDCAVG_test < matlab.unittest.TestCase + % Test class for FFE_FFDCAVG + + methods (Test) + function testExample(testCase) + % Example test case for FFE_FFDCAVG + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/FFE_adaptive_decision_test.m b/Tests/04_DSP/Equalizer/FFE_adaptive_decision_test.m new file mode 100644 index 0000000..61c4617 --- /dev/null +++ b/Tests/04_DSP/Equalizer/FFE_adaptive_decision_test.m @@ -0,0 +1,11 @@ +classdef FFE_adaptive_decision_test < matlab.unittest.TestCase + % Test class for FFE_adaptive_decision + + methods (Test) + function testExample(testCase) + % Example test case for FFE_adaptive_decision + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/FFE_test.m b/Tests/04_DSP/Equalizer/FFE_test.m new file mode 100644 index 0000000..3028f6c --- /dev/null +++ b/Tests/04_DSP/Equalizer/FFE_test.m @@ -0,0 +1,11 @@ +classdef FFE_test < matlab.unittest.TestCase + % Test class for FFE + + methods (Test) + function testExample(testCase) + % Example test case for FFE + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Equalizer/VNLE_test.m b/Tests/04_DSP/Equalizer/VNLE_test.m new file mode 100644 index 0000000..8e7d253 --- /dev/null +++ b/Tests/04_DSP/Equalizer/VNLE_test.m @@ -0,0 +1,11 @@ +classdef VNLE_test < matlab.unittest.TestCase + % Test class for VNLE + + methods (Test) + function testExample(testCase) + % Example test case for VNLE + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/04_DSP/Sequence Detection/MLSE_test.m b/Tests/04_DSP/Sequence Detection/MLSE_test.m new file mode 100644 index 0000000..ad2dfab --- /dev/null +++ b/Tests/04_DSP/Sequence Detection/MLSE_test.m @@ -0,0 +1,11 @@ +classdef MLSE_test < matlab.unittest.TestCase + % Test class for MLSE + + methods (Test) + function testExample(testCase) + % Example test case for MLSE + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/class_template_test.m b/Tests/class_template_test.m new file mode 100644 index 0000000..a306d1c --- /dev/null +++ b/Tests/class_template_test.m @@ -0,0 +1,11 @@ +classdef class_template_test < matlab.unittest.TestCase + % Test class for class_template + + methods (Test) + function testExample(testCase) + % Example test case for class_template + % Add your test code here + testCase.verifyTrue(true); + end + end +end diff --git a/Tests/createTestFile.m b/Tests/createTestFile.m new file mode 100644 index 0000000..69011e8 --- /dev/null +++ b/Tests/createTestFile.m @@ -0,0 +1,23 @@ +function createTestFile(className, testFilePath) + % Open the file for writing + fid = fopen(testFilePath, 'w'); + + % Write the basic structure for the test class + fprintf(fid, 'classdef %s_test < matlab.unittest.TestCase\n', className); + fprintf(fid, ' %% Test class for %s\n\n', className); + + fprintf(fid, ' methods (Test)\n'); + fprintf(fid, ' function testExample(testCase)\n'); + fprintf(fid, ' %% Example test case for %s\n', className); + fprintf(fid, ' %% Add your test code here\n'); + fprintf(fid, ' testCase.verifyTrue(true);\n'); + fprintf(fid, ' end\n'); + fprintf(fid, ' end\n'); + + fprintf(fid, 'end\n'); + + % Close the file + fclose(fid); + + fprintf('Created test file: %s\n', testFilePath); +end \ No newline at end of file diff --git a/Tests/generateTests.m b/Tests/generateTests.m new file mode 100644 index 0000000..998f0a3 --- /dev/null +++ b/Tests/generateTests.m @@ -0,0 +1,46 @@ +function generateTests() + + if ismac + cd('/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation'); + else + + end + % Define the root folders for classes and tests + classesFolder = 'Classes'; % Folder containing the class files + testsFolder = 'Tests'; % Folder where test files should be created + + % Create the Test folder if it doesn't exist + if ~exist(testsFolder, 'dir') + mkdir(testsFolder); + end + + % Get all .m files in the Classes folder and its subfolders + classFiles = dir(fullfile(classesFolder, '**', '*.m')); + + % Iterate over all class files + for i = 1:length(classFiles) + classFilePath = fullfile(classFiles(i).folder, classFiles(i).name); + [~, className, ~] = fileparts(classFilePath); + + % Create corresponding test file name + testFileName = [className, '_test.m']; + testFilePath = strrep(classFilePath, classesFolder, testsFolder); % Replace folder + testFilePath = fullfile(fileparts(testFilePath), testFileName); % Append test filename + + % Check if the test file already exists + if ~exist(testFilePath, 'file') + % Create the test subfolder if it doesn't exist + testSubFolder = fileparts(testFilePath); + if ~exist(testSubFolder, 'dir') + mkdir(testSubFolder); + end + + % Write the skeleton test file + createTestFile(className, testFilePath); + end + end + + addpath(genpath(testsFolder)) +end + + diff --git a/projects/.DS_Store b/projects/.DS_Store new file mode 100644 index 0000000..8e96fb2 Binary files /dev/null and b/projects/.DS_Store differ diff --git a/projects/400G_FTN_setups/duobinary_example.mlx b/projects/400G_FTN_setups/duobinary_example.mlx new file mode 100644 index 0000000..1e310e7 Binary files /dev/null and b/projects/400G_FTN_setups/duobinary_example.mlx differ diff --git a/projects/standard_system/400G_simulative_setup.mat b/projects/standard_system/400G_simulative_setup.mat index 2ca032e..d60da59 100644 Binary files a/projects/standard_system/400G_simulative_setup.mat and b/projects/standard_system/400G_simulative_setup.mat differ diff --git a/projects/standard_system/imdd_minimal_2.m b/projects/standard_system/imdd_minimal_2.m index fce8f44..1a5bf4d 100644 --- a/projects/standard_system/imdd_minimal_2.m +++ b/projects/standard_system/imdd_minimal_2.m @@ -3,11 +3,17 @@ params = struct; params.M = [4]; -params.datarate = [440]; +params.datarate = [300]; params.rop = [0]; precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active -precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\standard_system\"; + +if ismac + precomp_path = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/standard_system"; +else + precomp_path = "C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\standard_system\"; +end + precomp_fn = "400G_simulative_setup"; usemrds = 0; @@ -46,7 +52,7 @@ for M = wh.parameter.M.values [Digi_sig,Symbols,Bits] = PAMsource("fsym",fsym,"M",M,"order",18,"useprbs",0,... "fs_out",M8199.fdac,"applyclipping",1,"clipfactor",1.7,... "applypulseform",0,"pulseformer",Pform,"randkey",pn_key,... - "db_precode",1,... + "db_precode",0,... "mrds_code",usemrds,"mrds_blocklength",512).process(); Digi_sig.eye(fsym,M); @@ -56,7 +62,7 @@ for M = wh.parameter.M.values freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs); Digi_sig = freqresp.buildOFDM(); elseif precomp_mode == 2 - Digi_sig = freqresp.precomp(Digi_sig,'maxampdb',3,'loadPath',precomp_path,'fileName',precomp_fn); + Digi_sig = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs).precomp(Digi_sig,'maxampdb',3,'loadPath',precomp_path,'fileName',precomp_fn); Digi_sig.spectrum("fignum",11,"displayname",'after precomp'); end @@ -165,7 +171,7 @@ for M = wh.parameter.M.values toc disp(['Simulated: ',num2str(cnt/endcnt*100),' %']); - wh.save('C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\MPI_August\auswertung\') + % wh.save('C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\MPI_August\auswertung\') end end diff --git a/projects/standard_system/testcode_duobinary.m b/projects/standard_system/testcode_duobinary.m deleted file mode 100644 index c41fcad..0000000 --- a/projects/standard_system/testcode_duobinary.m +++ /dev/null @@ -1,36 +0,0 @@ -% Define parameters -n = 1; % Define the memory length n+1 (e.g., 1 for duobinary, 2 for tribinary, 3 for tetrabinary) -M = 4; % Modulation order (e.g., 4 for QPSK) -d = randi([0 M-1], 1, 100); % Example input sequence d(k) - -% Pre-coding: bPR(k) = (d(k) - bPR(k-1)) mod M -bPR = zeros(size(d)); -%bPR(1) = d(1); % Initial condition for pre-coding - -for k = 1:numel(d)-1 - bPR(k+1) = mod( d(k) - bPR(k), M ); -end - -% Polybinary coding: Convolution with (1 + z^-1)^n -% Generate coefficients for the polybinary filter (1 + z^-1)^n -coeff = ones(1, n+1); % Initialize coefficients with ones - -for i = 2:n+1 - coeff(i) = nchoosek(n, i-1); % Binomial coefficient for expansion -end - -% Apply convolution to get the polybinary coded sequence -polybinary_data = conv(bPR, coeff, "same"); - -% Modulo operation for decoding to stay within M levels -d_reconstructed = mod(polybinary_data, M); - -% Check if reconstruction is correct -reconstruction_success = isequal(d, d_reconstructed); - -figure(111) -hold on -stairs(d_reconstructed) -stairs(d) - -disp(['Reconstruction success: ', num2str(reconstruction_success)]); \ No newline at end of file diff --git a/test/duobinary_minimal_example.m b/test/duobinary_minimal_example.m index cb13525..0b7c407 100644 --- a/test/duobinary_minimal_example.m +++ b/test/duobinary_minimal_example.m @@ -1,6 +1,8 @@ useprbs = 1; M = 8; randkey = 1; +fsym = 112e9; + %%%%% PRBS Generation in correct shape for Modulation Format %%%%%% O = 18; %order of prbs N = 2^(O-1); %length of prbs @@ -28,28 +30,33 @@ Tx_bits = Informationsignal(bitpattern); Symbols_tx = PAMmapper(M,0).map(Tx_bits); Symbols_tx.fs = fsym; -% Symbols = Duobinary().precode(Symbols_tx); +Symbols = Duobinary().precode(Symbols_tx); -Symbols = Duobinary().encode(Symbols_tx); +Symbols = Duobinary().encode(Symbols); % Symbols.spectrum("displayname","db","fignum",12) -Symbols = Duobinary().feedbackdetector(Symbols); +% Symbols = Duobinary().feedbackdetector(Symbols); % Symbols.eye(fsym,M); -% Symbols = Duobinary().decode(Symbols); +Symbols = Duobinary().decode(Symbols); Rx_bits = PAMmapper(M,0).demap(Symbols); -[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",1,"returnErrorLocation",1); +[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1); disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]); % figure;hold on -stairs(Rx_bits.signal(1:100,1),'LineWidth',2) -stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2); - -figure;hold on -stairs(Symbols_tx.signal(1:100,1),'LineWidth',2) -stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2); \ No newline at end of file +subplot(2,1,1) +title('Bits Compare') +stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits') +stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits'); +legend +subplot(2,1,2) +hold on +title('Symbols Compare') +stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols'); +stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols') +legend \ No newline at end of file diff --git a/test/mapping_minimal_example.m b/test/mapping_minimal_example.m new file mode 100644 index 0000000..b4f4f76 --- /dev/null +++ b/test/mapping_minimal_example.m @@ -0,0 +1,71 @@ + + +%%%%% SETTINGS %%%%%% +useprbs = 1; +M = 8; +randkey = 1; +fsym = 112e9; +viewresults = 0; + + +%%%%% PRBS Generation in correct shape for Modulation Format %%%%%% +O = 10; %order of prbs +N = 2^(O-1); %length of prbs +[~,seed] = prbs(O,1); %initialize first seed of prbs +bitpattern=[]; +if useprbs + for i = 1:log2(M) + [bitpattern(:,i),seed] = prbs(O,N,seed); + end +else + s = RandStream('twister','Seed',randkey); + for i = 1:log2(M) + bitpattern(:,i) = randi(s,[0 1], N, 1); + end +end +if M == 6 + bitpattern = reshape(bitpattern,[],1); + bitpattern = bitpattern(1:end-mod(length(bitpattern),5)); +end + +Tx_bits = Informationsignal(bitpattern); + + + +%%%%% ACTUAL TEST: Back to Back Mapping: Bits -> Symbols and Symbols -> Bits %%%%%% + +Digi_Mod = PAMmapper(M,0); + +Symbols = Digi_Mod.map(Tx_bits); + +Rx_bits = PAMmapper(M,0).demap(Symbols); + + + +%%%%% VALIDATION: BER is required to be zero %%%%%% + +[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1); + + + + +%%%%% For User: Show Debug Info and Results %%%%%% + +if viewresults + disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]); + + + figure + subplot(1,2,1) + hold on + title('Symbols Out') + stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols') + legend + grid + subplot(1,2,2) + u = unique(Symbols_tx.signal); + scatter(0,u,'filled','o','LineWidth',2,'MarkerFaceColor',linspecer(1)); + grid +end + + diff --git a/test/mlse_minimal_example.m b/test/mlse_minimal_example.m new file mode 100644 index 0000000..506d94a --- /dev/null +++ b/test/mlse_minimal_example.m @@ -0,0 +1,59 @@ +useprbs = 1; +M = 8; +randkey = 1; +fsym = 112e9; + +%%%%% PRBS Generation in correct shape for Modulation Format %%%%%% +O = 18; %order of prbs +N = 2^(O-1); %length of prbs +[~,seed] = prbs(O,1); %initialize first seed of prbs +bitpattern=[]; + +if useprbs + for i = 1:log2(M) + [bitpattern(:,i),seed] = prbs(O,N,seed); + end +else + s = RandStream('twister','Seed',randkey); + for i = 1:log2(M) + bitpattern(:,i) = randi(s,[0 1], N, 1); + end +end + +if M == 6 + bitpattern = reshape(bitpattern,[],1); + bitpattern = bitpattern(1:end-mod(length(bitpattern),5)); +end + +Tx_bits = Informationsignal(bitpattern); + +Digi_Mod = PAMmapper(M,0); +Symbols_tx = Digi_Mod.map(Tx_bits); +Symbols_tx.fs = fsym; + +Symbols = Duobinary().precode(Symbols_tx); + +Symbols = Duobinary().encode(Symbols); + +Symbols = MLSE("DIR",[1,1],"duobinary_output",1,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols); + +Symbols = Duobinary().decode(Symbols); + +Rx_bits = PAMmapper(M,0).demap(Symbols); + +[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1); + +disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]); +% +figure;hold on +subplot(2,1,1) +title('Bits Compare') +stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits') +stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits'); +legend +subplot(2,1,2) +hold on +title('Symbols Compare') +stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols'); +stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols') +legend \ No newline at end of file