Merge branch 'main' of cau-git.rz.uni-kiel.de:nt/mitarbeiter/silas/imdd_simulation

This commit is contained in:
Silas Oettinghaus
2026-03-24 18:01:13 +01:00
159 changed files with 2650 additions and 1451 deletions

344
AGENT_OVERVIEW.md Normal file
View File

@@ -0,0 +1,344 @@
# IM/DD Simulation Framework Overview
This file is for agents that encounter this repository for the first time.
Its goal is to explain what the codebase is for, where the main building
blocks live, and how a typical IM/DD workflow is assembled.
It is not a testing guide. The focus here is the simulation framework itself.
## What This Repository Is
This repository is a MATLAB-based simulation and analysis framework for
IM/DD optical communication systems.
At a high level, the codebase supports:
- generation of digital symbol and bit streams
- electrical transmitter modeling
- electro-optical modulation
- optical channel modeling
- photodetection and receiver front-end processing
- digital signal processing and sequence detection
- metric evaluation such as BER, GMI, AIR, EVM, and SNR
- project-specific simulation scripts and experimental analysis workflows
The codebase is not just one monolithic simulator. It is a toolkit of
reusable classes plus many project scripts that assemble those classes in
different ways.
## Mental Model
The easiest way to understand the repository is as a staged signal chain:
1. Information signal generation
2. Symbol mapping and pulse shaping
3. AWG / electrical drive path
4. Optical modulation
5. Fiber / channel propagation
6. Receiver front-end
7. Synchronization and DSP
8. Performance evaluation
The classes in `Classes/` implement the reusable blocks.
The scripts in `projects/` wire those blocks together into concrete systems.
## Suggested First File To Read
For a compact end-to-end example, start here:
- `projects/IMDD_base_system/minimal_example.m`
That file shows a reduced but representative full workflow:
- `PAMsource`
- `AWG`
- `EML`
- `Fiber`
- `Amplifier`
- `Photodiode`
- `Filter`
- `Scope`
- matched filtering
- synchronization
- equalization / MLSE
If you need to understand “how the system is intended to be used”, this is
one of the best entry points.
## Top-Level Structure
### `Classes/`
This is the core reusable framework.
Most simulation building blocks live here.
Subfolders are organized by role:
- `00_signals`
Base signal classes and core signal behavior.
This is the semantic foundation used by most of the rest of the codebase.
- `01_transmit`
Digital TX-side blocks such as bit/symbol generation, mapping, pulse
shaping, and AWG-related functionality.
- `02_etc`
General-purpose support blocks, especially filtering and amplification.
- `02_optical`
Optical-domain components such as modulators, multiplexing, fiber/channel
propagation, and related physical effects.
- `03_electrical`
Electrical-domain helper blocks and traces.
- `03_receive`
RX-side front-end blocks such as photodiodes and scopes/ADC behavior.
- `04_DSP`
Equalizers, timing recovery, postfilters, coding blocks, and sequence
detection such as MLSE.
- `05_Lab`
Instrument-control classes for real hardware.
These are not just simulations. They can talk to reachable devices.
- `DataBaseHandler`
Query/filter/result structures and database-facing helper classes.
- `Warehouse_class`
More specialized storage / plotting / result-handling infrastructure.
### `Functions/`
This holds free functions and workflow helpers that are not packaged as
classes.
Important subareas:
- `EQ_structures`
Higher-level DSP driver functions such as `ffe`, `vnle_postfilter_mlse`,
and related end-stage evaluation helpers.
- `Metrics`
BER, EVM, GMI, AIR, SNR, and related performance calculations.
- `EQ_visuals`
Diagnostic and visualization helpers for equalizers and result analysis.
- `channel_structures`
Channel-model helpers.
- `Job_Processing`
Scriptable processing helpers for bigger job/result workflows.
- `Theory`
Supporting theory calculations and one-off analytic utilities.
### `Datatypes/`
This contains enums and small type definitions used throughout the codebase.
Examples:
- normalization modes
- power notation
- filter types
- modulation / adaptation enums
When a class constructor takes a symbolic mode value, it is often defined here.
### `projects/`
This is where the reusable framework gets turned into concrete systems,
experiments, and studies.
The `projects/` folder is broad and includes:
- minimal examples
- paper-specific studies
- lab analysis scripts
- offline DSP pipelines
- experiment-specific workflows
These scripts are often the best place to understand intended usage patterns.
### `Tests/`
This contains the current MATLAB unit/integration test framework.
It validates parts of the reusable framework, not the full meaning of the
repository.
Use it as a quality tool, not as the primary documentation source for what
the simulation does.
## Core Signal Classes
The repository uses class-based signal objects instead of raw arrays whenever
possible.
Key signal classes:
- `Signal`
Base class with common signal behavior, metadata, logbook, arithmetic,
normalization, resampling, plotting, and utility methods.
- `Informationsignal`
Discrete/digital information-level representation.
- `Electricalsignal`
Electrical-domain signal representation.
- `Opticalsignal`
Optical-domain signal representation including optical metadata such as
wavelength and ASE-related quantities.
These classes are central because many other blocks accept or return them.
## Typical Workflow Composition
A representative IM/DD chain often looks like this:
1. `PAMsource`
Creates bits, mapped symbols, and shaped digital transmit signals.
2. `AWG`
Applies DAC-like processing, upsampling, quantization, and optional
filtering.
3. `EML`
Converts the electrical drive signal to an optical signal.
4. `Fiber`
Applies optical channel propagation.
5. `Amplifier`
Sets optical power / gain and can manipulate ASE handling.
6. `Photodiode`
Performs square-law detection and creates an electrical RX signal.
7. `Filter`
Applies electrical filtering.
8. `Scope`
Models ADC / sampling / quantization / optional RX-side LPF behavior.
9. `Pulseformer` in matched-filter mode
Used again on the RX side as matched filtering.
10. `tsynch`
Synchronizes the RX signal against transmitted symbols.
11. DSP blocks
Examples:
- `FFE`
- `EQ`
- `Postfilter`
- `MLSE`
- timing-recovery variants
12. Metrics
Performance is evaluated via helper functions and result structures.
## Two Important Layers
There are two distinct abstraction levels in the repo:
### 1. Block-level classes
Examples:
- `PAMsource`
- `Pulseformer`
- `AWG`
- `EML`
- `Fiber`
- `Photodiode`
- `Scope`
- `FFE`
- `MLSE`
These are the reusable simulation primitives.
### 2. Workflow-level functions/scripts
Examples:
- `projects/.../minimal_example.m`
- `Functions/EQ_structures/ffe.m`
- `Functions/EQ_structures/vnle_postfilter_mlse.m`
These assemble the primitives into practical runs and performance outputs.
When debugging behavior, it matters which layer you are in:
- if a signal object has the wrong shape or `fs`, look at block-level classes
- if BER/GMI pipelines behave unexpectedly, also inspect workflow-level DSP helpers
## Where To Look For What
If you want to understand:
- base signal semantics:
read `Classes/00_signals/*`
- transmitter generation:
read `Classes/01_transmit/*`
- optical propagation:
read `Classes/02_optical/*`
- receiver modeling:
read `Classes/03_receive/*`
- equalization and detection:
read `Classes/04_DSP/*` and `Functions/EQ_structures/*`
- metric definitions:
read `Functions/Metrics/*`
- intended end-to-end usage:
read `projects/IMDD_base_system/minimal_example.m`
## How To Approach The Repo As A New Agent
A good first-pass reading order is:
1. `projects/IMDD_base_system/minimal_example.m`
2. `Classes/00_signals/Signal.m`
3. `Classes/01_transmit/PAMsource.m`
4. `Classes/01_transmit/Pulseformer.m`
5. `Classes/01_transmit/AWG.m`
6. `Classes/02_optical/EML.m`
7. `Classes/02_optical/Fiber.m`
8. `Classes/03_receive/Photodiode.m`
9. `Classes/03_receive/Scope.m`
10. `Functions/EQ_structures/ffe.m`
11. `Functions/EQ_structures/vnle_postfilter_mlse.m`
12. `Classes/04_DSP/Equalizer/FFE.m`
13. `Classes/04_DSP/Sequence Detection/MLSE.m`
This gives both the architectural view and the runtime path.
## Practical Safety Note
Do not casually execute or test `Classes/05_Lab/*`.
Those are lab-device control classes, not harmless simulations.
In this environment, reachable device IPs can exist, and executing those
classes may change instrument set points and interfere with active experiments.
Treat `05_Lab` as operational code, not as a normal simulation subfolder.
## Final Summary
The repository is best understood as:
- a reusable class library for IM/DD system building blocks
- plus workflow helpers for DSP and analysis
- plus many project scripts that instantiate those blocks for concrete studies
If you are lost, do not start from `Tests/`.
Start from the minimal project workflow, then map each stage back to the
relevant class folder in `Classes/`.

View File

@@ -1,135 +1,3 @@
% plot_dispersion_models
% ------------------------------------------------------------
% Visualizes exact and linearized chromatic dispersion D(λ)
% around the zero-dispersion wavelength (ZDW).
%
% Inputs:
% lambda0_nm - ZDW in nm
% S0 - dispersion slope at ZDW [ps/(nm^2·km)]
% ------------------------------------------------------------
%% ZDW 1
lambda0_nm = [1310];
S0 = [0.075,0.095]';
% wavelength axis around ZDW
lambda_nm = linspace(1240, 1360, 400);
% exact dispersion model
D_exact_1 = (S0./4) .* ( ...
lambda_nm - (lambda0_nm^4)./(lambda_nm.^3) );
%% ZDW 2
lambda0_nm = [1320];
% exact dispersion model
D_exact_2 = (S0./4) .* ( ...
lambda_nm - (lambda0_nm^4)./(lambda_nm.^3) );
%% plot
figure('Color','w'); hold on;
cols = [0.6510 0.8078 0.8902;...
0.1216 0.4706 0.7059;...
0.6980 0.8745 0.5412;...
0.2000 0.6275 0.1725];
plot(lambda_nm, D_exact_1(1,:), 'LineWidth',2, 'DisplayName',sprintf('$S_0=\SI{0.09}{\Dslope}$'),'Color',[0,0,0]);
plot(lambda_nm, D_exact_1(2,:), 'LineWidth',2, 'DisplayName',sprintf('$S_0=\SI{0.09}{\Dslope}$'),'Color',[0,0,0]);
% plot(lambda_nm, D_exact_2(1,:), 'LineWidth',2, 'HandleVisibility','on', 'DisplayName',sprintf('$S_0=\SI{0.09}{\Dslope}$'),'Color',[0,0,0]);
% plot(lambda_nm, D_exact_2(2,:), 'LineWidth',2, 'HandleVisibility','on', 'DisplayName',sprintf('$S_0=\SI{0.09}{\Dslope}$'),'Color',[0,0,0]);
xlabel('Wavelength $\lambda$ [nm]','Interpreter','latex');
ylabel('D($\lambda$) [ps/(nm km)]','Interpreter','latex');
title('Chromatic Dispersion Around the ZDW');
legend('Location','best');
grid on; box on;
xlim([min(lambda_nm) max(lambda_nm)])
ylim([-5 5]);
% mat2tikz_improved('C:\Users\Silas\Documents\6971e0b65b380ca6d71c837f\02_IMDD_System\tikz\dispersion\dispersion')
%%
%% plot_dispersion_dual_ZDW
% Visualizes two ZDW fiber types, each with an S0 tolerance range.
%% plot_dispersion_minimal_for_tikz
% Minimal setup for clean TikZ tuning
% 1. Parameters
lambda_nm = linspace(1240, 1360, 400);
S0_range = [0.075, 0.095];
ZDW_range = [1300, 1325];
% 2. Calculate Envelope and Nominal
[S_mesh, Z_mesh] = meshgrid(S0_range, ZDW_range);
D_all = zeros(length(lambda_nm), 4);
for i = 1:4
D_all(:,i) = (S_mesh(i)/4) .* (lambda_nm - (Z_mesh(i)^4)./(lambda_nm.^3));
end
D_env_min = min(D_all, [], 2);
D_env_max = max(D_all, [], 2);
D_nominal = (mean(S0_range)/4) .* (lambda_nm - (mean(ZDW_range)^4)./(lambda_nm.^3));
% 3. Plotting
figure('Color','w'); hold on;
env_col = [0.1216, 0.4706, 0.7059];
% Shaded area
[hl, hp] = boundedline(lambda_nm, (D_env_min+D_env_max)/2, ...
(D_env_max-D_env_min)/2, 'alpha', 'cmap', env_col);
set(hl, 'YData', D_nominal, 'Color', 'k', 'LineWidth', 1.5);
% Generate the outline and capture the handle
ho = outlinebounds(hl, hp);
% Change properties
set(ho, 'Color', 'k', ... % Make it black
'LineStyle', '--', ... % Make it dashed
'LineWidth', 0.5, ... % Make it thin
'HandleVisibility', 'off'); % Hide from legend
% 4. "Minimal" Measurement Lines (Tweak these in TikZ later)
% Vertical measurement at 1290nm
lambda_v = 1290;
[~, idx] = min(abs(lambda_nm - lambda_v));
y_bot = D_env_min(idx);
y_top = D_env_max(idx);
% Simple line - in TikZ this will be a single \draw command
line([lambda_v, lambda_v], [y_bot, y_top], 'Color', 'r', 'LineWidth', 1.2, 'Tag', 'VertArrow');
text(lambda_v + 2, (y_top+y_bot)/2, '$\Delta D$', 'Color', 'r', 'Interpreter', 'latex');
% Horizontal measurement at D=0
z1 = ZDW_range(1);
z2 = ZDW_range(2);
line([z1, z2], [0, 0], 'Color', [0.1 0.5 0.1], 'LineWidth', 1.2, 'Tag', 'HorizArrow');
text(mean(ZDW_range), 0.5, '$\Delta \lambda_0$', 'Color', [0.1 0.5 0.1], ...
'Interpreter', 'latex', 'HorizontalAlignment', 'center');
% 5. Aesthetics
xlabel('Wavelength $\lambda$ [nm]', 'Interpreter', 'latex');
ylabel('$D(\lambda)$ [ps/(nm km)]', 'Interpreter', 'latex');
grid on; box on;
xlim([1240 1360]); ylim([-5 5]);
line(xlim, [0 0], 'Color', [0.4 0.4 0.4], 'LineStyle', '--', 'HandleVisibility', 'off');
% Legend using the handles we have
legend([hp, hl], {'Worst-case Envelope', 'Nominal Realization'}, ...
'Location', 'northwest', 'Interpreter', 'latex');
% To export, run:
% matlab2tikz('dispersion.tex', 'standalone', true);
%% plot_dispersion_for_tikz
% Optimized for matlab2tikz compatibility with manual arrows
%% plot_dispersion_statistical_envelopes
% Visualizes hard spec limits vs. 98% statistical distribution
%% plot_dispersion_final_for_tikz %% plot_dispersion_final_for_tikz
lambda_nm = linspace(1240, 1360, 400); lambda_nm = linspace(1240, 1360, 400);
@@ -181,6 +49,14 @@ for k = 1:size(scenarios, 1)
% 'HandleVisibility', 'off'); % Hide from legend % 'HandleVisibility', 'off'); % Hide from legend
% Capture Wide Spec (k=1) bounds for the TikZ measurement lines % Capture Wide Spec (k=1) bounds for the TikZ measurement lines
hp.FaceAlpha = 0.5; hp.FaceAlpha = 0.5;
% ho = outlinebounds(hl, hp);
% % Change properties
% set(ho, 'Color', 'k', ... % Make it black
% 'LineStyle', '--', ... % Make it dashed
% 'LineWidth', 1, ... % Make it thin
% 'HandleVisibility', 'off'); % Hide from legend
% Capture Wide Spec (k=1) bounds for the TikZ measurement lines
hp.FaceAlpha = 0.5;
else else
hp.FaceAlpha = 0.8; hp.FaceAlpha = 0.8;
end end

View File

@@ -38,7 +38,7 @@ hold on;
lambda_levels = unique([50:-10:30, 30:-5:5]); lambda_levels = unique([50:-10:30, 30:-5:5]);
% Contour plot % Contour plot
[C,h] = contour(f_GHz, L_km, lambda_surface_nm, lambda_levels, ... [C,h] = contourf(f_GHz, L_km, lambda_surface_nm, lambda_levels, ...
'LineWidth', 1.2, ... 'LineWidth', 1.2, ...
'ShowText', 'off'); 'ShowText', 'off');
@@ -106,7 +106,7 @@ end
%% Export %% Export
% Hier erzwingen wir die rote Colormap für pgfplots, damit mat2tikz es nicht blau exportiert! % Hier erzwingen wir die rote Colormap für pgfplots, damit mat2tikz es nicht blau exportiert!
mat2tikz_improved("C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/02_IMDD_System/tikz/dispersion/dispersion_power_fading_contour2.tikz"); % mat2tikz_improved("C:/Users/Silas/Documents/6971e0b65b380ca6d71c837f/02_IMDD_System/tikz/dispersion/dispersion_power_fading_contour2.tikz");
function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0) function [lambda_vec, Dacc_vec] = lambda_for_first_null_full(f_target, L, lambda0, S0)
% lambda_for_first_null_full (stable, single-branch + validity checks) % lambda_for_first_null_full (stable, single-branch + validity checks)

View File

@@ -16,6 +16,9 @@ D_lambda = (S0/4) * (lambda*1e9 - (lambda0*1e9)^4/(lambda*1e9)^3); % ps/(nm·km)
D_si = D_lambda * 1e-6; % s/m² D_si = D_lambda * 1e-6; % s/m²
b2 = -D_si * lambda^2 / (2*pi*c); % s²/m b2 = -D_si * lambda^2 / (2*pi*c); % s²/m
Dacc = D_lambda * L;
fprintf('Accumulated Dispersion: %.2f ps/nm \n', Dacc / 1e3);
%% Frequency grid %% Frequency grid
f_max = 200e9; f_max = 200e9;
f = linspace(0, f_max, 5000); % [Hz] f = linspace(0, f_max, 5000); % [Hz]

182
TEST_TODO.md Normal file
View File

@@ -0,0 +1,182 @@
# Test TODO
This file is the current backlog for building out the MATLAB test suite.
It should reflect the repository state now, not the original plan.
## Current Status
Fast profile status:
- `run_all_tests('profile','fast')`
- latest verified result: `Passed: 59 | Failed: 0 | Incomplete: 0`
- explicit placeholder tests remaining: `70`
Mandatory workflow for every future test-writing session:
1. Read the target class implementation in `Classes/...` before writing or changing tests.
2. Read the current placeholder or existing test in `Tests/...`.
3. Replace or extend the existing test. Do not create duplicate test files.
4. Use the existing `matlab.unittest` framework and extend `IMDDTestCase`.
5. Tag new tests with `TestTags`.
6. Run the relevant test entrypoint after implementation.
7. Do not consider the task complete until the test run result is checked.
## Completed Base Tests
These are already implemented and verified in the fast profile:
- `Classes/00_signals/Signal.m` -> `Tests/00_signals/Signal_test.m`
- `Classes/00_signals/Informationsignal.m` -> `Tests/00_signals/Informationsignal_test.m`
- `Classes/00_signals/Electricalsignal.m` -> `Tests/00_signals/Electricalsignal_test.m`
- `Classes/01_transmit/PAMmapper.m` -> `Tests/01_transmit/PAMmapper_test.m`
- `Classes/01_transmit/PAMsource.m` -> `Tests/01_transmit/PAMsource_test.m`
- `Classes/01_transmit/Pulseformer.m` -> `Tests/01_transmit/Pulseformer_test.m`
- `Classes/02_optical/Fiber.m` -> `Tests/02_optical/Fiber_test.m`
- `Classes/03_receive/Photodiode.m` -> `Tests/03_receive/Photodiode_test.m`
- `Classes/03_receive/Scope.m` -> `Tests/03_receive/Scope_test.m`
- `Classes/04_DSP/TransmissionPerformance.m` -> `Tests/04_DSP/TransmissionPerformance_test.m`
- `Classes/04_DSP/Equalizer/FFE.m` -> `Tests/04_DSP/Equalizer/FFE_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE.m` -> `Tests/04_DSP/Sequence Detection/MLSE_test.m`
- `Classes/04_DSP/Timing Recovery/Timing_Recovery.m` -> `Tests/04_DSP/Timing Recovery/T_04_DSP_Timing_Recovery_Timing_Recovery_test.m`
Notes:
- `Opticalsignal_test.m` still appears to be a placeholder and should be treated as unfinished.
- There are multiple `Timing_Recovery` class names in the repo, so the implemented base-class test currently uses the disambiguated file name:
`Tests/04_DSP/Timing Recovery/T_04_DSP_Timing_Recovery_Timing_Recovery_test.m`
## Next Priority Tests
Highest-value unfinished tests to implement next:
1. `Classes/00_signals/Opticalsignal.m`
`Tests/00_signals/Opticalsignal_test.m`
Focus:
- constructor metadata wiring
- `delay`
- `cspr`
- interaction with inherited signal behavior
2. `Classes/01_transmit/Signalgenerator.m`
`Tests/01_transmit/Signalgenerator_test.m`
Focus:
- constructor/config defaults
- deterministic generation path
- output type and shape
3. `Classes/02_etc/Filter.m`
`Tests/02_etc/Filter_test.m`
Focus:
- deterministic filter construction
- `process` behavior on small signals
- output rate/length invariants
4. `Classes/02_etc/Amplifier.m`
`Tests/02_etc/Amplifier_test.m`
Focus:
- gain behavior
- noise-free baseline
- output class and metadata behavior
5. `Classes/02_optical/EML.m`
`Tests/02_optical/EML_test.m`
Focus:
- deterministic modulation path
- output class and metadata
- small synthetic fixture only
6. `Classes/02_optical/Optical_Multiplex.m`
`Tests/02_optical/Optical_Multiplex_test.m`
Focus:
- combining channels
- output dimensions
- metadata handling
7. `Classes/02_optical/Optical_Demultiplex.m`
`Tests/02_optical/Optical_Demultiplex_test.m`
Focus:
- deterministic channel extraction
- output dimensions
- basic round-trip expectations with multiplexing if practical
8. `Classes/02_optical/Polarization_Controller.m`
`Tests/02_optical/Polarization_Controller_test.m`
Focus:
- deterministic transform behavior
- shape preservation
9. `Classes/02_optical/DP_Fiber.m`
`Tests/02_optical/DP_Fiber_test.m`
Focus:
- very small deterministic sanity checks only
- avoid long or GPU-heavy runs
## Next DSP Layer
After the items above, continue with these:
- `Classes/04_DSP/Coding/Duobinary.m`
`Tests/04_DSP/Coding/Duobinary_test.m`
- `Classes/04_DSP/Coding/MRDS_coding.m`
`Tests/04_DSP/Coding/MRDS_coding_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE_viterbi.m`
`Tests/04_DSP/Sequence Detection/MLSE_viterbi_test.m`
- `Classes/04_DSP/Sequence Detection/MLSE_new.m`
`Tests/04_DSP/Sequence Detection/MLSE_new_test.m`
- `Classes/04_DSP/Timing Recovery/Time_Shifter.m`
`Tests/04_DSP/Timing Recovery/Time_Shifter_test.m`
- `Classes/04_DSP/Timing Recovery/Godard_Timing_Recovery.m`
`Tests/04_DSP/Timing Recovery/Godard_Timing_Recovery_test.m`
- `Classes/04_DSP/Timing Recovery/MaxVar_Timing_Recovery.m`
`Tests/04_DSP/Timing Recovery/MaxVar_Timing_Recovery_test.m`
Then move on to the remaining equalizer variants:
- `EQ.m`
- `EQ_copy.m`
- `EQ_silas*.m`
- `FFE_*`
- `ML_MLSE*.m`
- `Postfilter.m`
- `VNLE.m`
## Lower Priority Areas
Leave these for later unless a current task depends on them:
- `Classes/Warehouse_class/*`
- `Classes/DataBaseHandler/*`
- template/example classes like `class_template`
## Excluded From Automated Testing
Do not create or run automated tests for lab device classes in this repository.
Excluded area:
- `Classes/05_Lab/*`
Reason:
- the device IPs are reachable in this environment
- executing these classes can change instrument set points
- this can interfere with external or ongoing experiments
Rule for future sessions:
- do not implement `Tests/05_Lab/*`
- do not run files that communicate with lab devices
- do not add these classes back into the active TODO backlog unless explicitly requested by the user for a controlled setup
## Session Prompt Checklist
Every future agent prompt should include these requirements:
- read the class implementation first
- read the current test file second
- implement the test in the existing file
- prefer deterministic synthetic fixtures
- avoid plotting and hardware unless required
- never run or implement `05_Lab` tests in normal agent sessions
- run `run_all_tests('profile','fast')` after implementation
- report the changed files and the verification result

View File

@@ -1,11 +1,79 @@
classdef Electricalsignal_test < matlab.unittest.TestCase classdef Electricalsignal_test < IMDDTestCase
% Test class for Electricalsignal methods (Test, TestTags = {'unit', 'fast', 'signals', 'electricalsignal'})
function constructorStoresSignalFsAndLogbook(testCase)
seed = Signal(1, "fs", 2);
seed = seed.logbookentry("electrical seed", seed);
methods (Test) elec = Electricalsignal([1; -2; 3], "fs", 80e9, "logbook", seed.logbook);
function testExample(testCase)
% Example test case for Electricalsignal testCase.verifyClass(elec, 'Electricalsignal');
% Add your test code here testCase.verifyEqual(elec.signal, [1; -2; 3]);
testCase.verifyTrue(true); testCase.verifyEqual(elec.fs, 80e9);
testCase.verifyEqual(elec.logbook, seed.logbook);
end
function inheritedArithmeticKeepsElectricalsignalTypeAndMetadata(testCase)
seed = Signal(0, "fs", 1);
seed = seed.logbookentry("lhs metadata", seed);
lhs = Electricalsignal([1; 2; 3], "fs", 64e9, "logbook", seed.logbook);
rhs = Electricalsignal([4; 5; 6], "fs", 32e9, "logbook", table());
sumSig = lhs + rhs;
testCase.verifyClass(sumSig, 'Electricalsignal');
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(sumSig.fs, lhs.fs);
testCase.verifyEqual(sumSig.logbook, lhs.logbook);
end
function informationCastPreservesSignalFsAndLogbook(testCase)
seed = Signal(3, "fs", 4);
seed = seed.logbookentry("electrical cast", seed);
elec = Electricalsignal([2; 0; -2], "fs", 96e9, "logbook", seed.logbook);
info = elec.Informationsignal("fs", elec.fs, "logbook", elec.logbook);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, elec.signal);
testCase.verifyEqual(info.fs, elec.fs);
testCase.verifyEqual(info.logbook, elec.logbook);
end
function power50MatchesInheritedElectricalPowerDefinition(testCase)
elec = Electricalsignal([1; -1; 1; -1], "fs", 1, "logbook", table());
expectedPowerDbm = 10 * log10(mean(abs(elec.signal).^2) / 50) + 30;
testCase.verifyEqual(elec.power50(), expectedPowerDbm, "AbsTol", 1e-12);
testCase.verifyEqual(elec.power50(), elec.power(), "AbsTol", 1e-12);
end
function csprUsesCarrierToTotalPowerRatioInDb(testCase)
elec = Electricalsignal([1; 3], "fs", 1, "logbook", table());
carrierPowerDbm = pow2db(abs(mean(elec.signal)).^2) + 30;
expectedCsprDb = carrierPowerDbm - elec.power();
testCase.verifyEqual(elec.cspr(), expectedCsprDb, "AbsTol", 1e-12);
end
function normalizeMilliwattSetsPowerToZeroDbmInto50Ohm(testCase)
elec = Electricalsignal([2; -2; 2; -2], "fs", 1, "logbook", table());
elec = elec.normalize("mode", normalization_mode.milliwatt);
testCase.verifyEqual(elec.power50(), 0, "AbsTol", 1e-12);
testCase.verifyClass(elec, 'Electricalsignal');
end
function setPowerSupportsMilliwattAndDbwTargets(testCase)
elec = Electricalsignal([1; -1; 1; -1], "fs", 1, "logbook", table());
elecMilliwatt = elec.setPower(2, power_notation.mW);
elecDbw = elec.setPower(-20, power_notation.dBW);
testCase.verifyEqual(elecMilliwatt.power50(), 10 * log10(2), "AbsTol", 1e-12);
testCase.verifyEqual(elecDbw.power50(), 10, "AbsTol", 1e-12);
end end
end end
end end

View File

@@ -1,11 +1,82 @@
classdef Informationsignal_test < matlab.unittest.TestCase classdef Informationsignal_test < IMDDTestCase
% Test class for Informationsignal methods (Test, TestTags = {'unit', 'fast', 'signals', 'informationsignal'})
function constructorWithoutOptionsUsesSignalDefaults(testCase)
info = Informationsignal([0; 1; 1; 0]);
methods (Test) testCase.verifyClass(info, 'Informationsignal');
function testExample(testCase) testCase.verifyEqual(info.signal, [0; 1; 1; 0]);
% Example test case for Informationsignal testCase.verifyEmpty(info.fs);
% Add your test code here testCase.verifyEmpty(info.logbook);
testCase.verifyTrue(true); end
function constructorWithOptionsCopiesFsAndLogbook(testCase)
seed = Signal(5, "fs", 2);
seed = seed.logbookentry("seed entry", seed);
info = Informationsignal([1; 0; 1], "fs", 32e9, "logbook", seed.logbook);
testCase.verifyEqual(info.signal, [1; 0; 1]);
testCase.verifyEqual(info.fs, 32e9);
testCase.verifyEqual(info.logbook, seed.logbook);
end
function inheritedArithmeticKeepsInformationsignalTypeAndMetadata(testCase)
lhs = Informationsignal([1; 2; 3], "fs", 64e9, "logbook", table());
rhs = Informationsignal([4; 5; 6], "fs", 1, "logbook", table());
sumSig = lhs + rhs;
testCase.verifyClass(sumSig, 'Informationsignal');
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(sumSig.fs, lhs.fs);
testCase.verifyEqual(sumSig.logbook, lhs.logbook);
end
function electricalsignalCastUsesRequestedFsAndLogbook(testCase)
seed = Signal(1, "fs", 4);
seed = seed.logbookentry("cast logbook", seed);
info = Informationsignal([0; 1; 0; 1]);
elec = info.Electricalsignal("fs", 128e9, "logbook", seed.logbook);
testCase.verifyClass(elec, 'Electricalsignal');
testCase.verifyEqual(elec.signal, info.signal);
testCase.verifyEqual(elec.fs, 128e9);
testCase.verifyEqual(elec.logbook, seed.logbook);
end
function opticalsignalCastFailsForInformationsignal(testCase)
info = Informationsignal([0; 1; 0; 1]);
didError = false;
try
info.Opticalsignal( ...
"fs", 64e9, ...
"logbook", info.logbook, ...
"lambda", 1310e-9, ...
"nase", 0, ...
"polrot", 0);
catch ME
didError = true;
testCase.verifySubstring(ME.message, ...
"Cannot convert from information- to opticalsignal.");
end
testCase.verifyTrue(didError, ...
"Informationsignal -> Opticalsignal should reject direct conversion.");
end
function electricalToInformationCastPreservesSignalAndMetadata(testCase)
seed = Signal(2, "fs", 8);
seed = seed.logbookentry("from electrical", seed);
elec = Electricalsignal([3; 1; 4], "fs", 96e9, "logbook", seed.logbook);
info = elec.Informationsignal("fs", elec.fs, "logbook", elec.logbook);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, elec.signal);
testCase.verifyEqual(info.fs, elec.fs);
testCase.verifyEqual(info.logbook, elec.logbook);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Opticalsignal_test < matlab.unittest.TestCase classdef Opticalsignal_test < IMDDTestCase
% Test class for Opticalsignal % Auto-generated placeholder for Opticalsignal.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/00_signals/Opticalsignal.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Opticalsignal testCase.assumeFail("Tests for Opticalsignal are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,117 @@
classdef Signal_test < matlab.unittest.TestCase classdef Signal_test < IMDDTestCase
% Test class for Signal methods (Test, TestTags = {'unit', 'fast', 'signals'})
function constructorStoresSignalAndSamplingRate(testCase)
sig = Signal([1; 2; 3], "fs", 64e9);
methods (Test) testCase.verifyEqual(sig.signal, [1; 2; 3]);
function testExample(testCase) testCase.verifyEqual(sig.fs, 64e9);
% Example test case for Signal testCase.verifyEmpty(sig.logbook);
% Add your test code here end
testCase.verifyTrue(true);
function arithmeticOperatorsSupportSignalOperands(testCase)
x = Signal([1; 2; 3]);
y = Signal([4; 5; 6]);
sumSig = x + y;
diffSig = y - x;
prodSig = x .* y;
testCase.verifyEqual(sumSig.signal, [5; 7; 9]);
testCase.verifyEqual(diffSig.signal, [3; 3; 3]);
testCase.verifyEqual(prodSig.signal, [4; 10; 18]);
end
function arithmeticOperatorsSupportNumericOperands(testCase)
x = Signal([1; 2; 3]);
sumSig = x + 2;
diffSig = x - 1;
prodSig = x .* 3;
testCase.verifyEqual(sumSig.signal, [3; 4; 5]);
testCase.verifyEqual(diffSig.signal, [0; 1; 2]);
testCase.verifyEqual(prodSig.signal, [3; 6; 9]);
end
function lengthReturnsSignalLength(testCase)
sig = Signal(zeros(11, 1));
testCase.verifyEqual(sig.length(), 11);
end
function normalizeRmsScalesSignalToUnitPower(testCase)
sig = Signal([1; -1; 1; -1]);
sig = sig.normalize("mode", normalization_mode.rms);
testCase.verifyEqual(mean(abs(sig.signal).^2), 1, "AbsTol", 1e-12);
end
function normalizeOneOneMapsSignalToMinusOneToOne(testCase)
sig = Signal([2; 4; 6]);
sig = sig.normalize("mode", normalization_mode.oneone);
testCase.verifyEqual(sig.signal, [-1; 0; 1], "AbsTol", 1e-12);
end
function logbookEntryAppendsRowAndDescription(testCase)
sig = Signal([1; 0; -1], "fs", 1);
sig = sig.logbookentry("unit-test entry", sig);
testCase.verifyEqual(height(sig.logbook), 1);
testCase.verifyEqual(string(sig.logbook.SignalType(1)), "Signal");
testCase.verifyEqual(string(sig.logbook.Description(1)), "unit-test entry");
testCase.verifyEqual(string(sig.logbook.ModifierName(1)), "Signal");
end
function resampleWithIdenticalRatesKeepsSignalAndFs(testCase)
original = [1; 2; 3; 4];
sig = Signal(original, "fs", 8);
sig = sig.resample("fs_in", 8, "fs_out", 8);
testCase.verifyEqual(sig.signal, original);
testCase.verifyEqual(sig.fs, 8);
testCase.verifyEqual(height(sig.logbook), 1);
end
function resampleToNewRateUpdatesSamplingRate(testCase)
sig = Signal((1:8).', "fs", 8);
sig = sig.resample("fs_in", 8, "fs_out", 16);
testCase.verifyEqual(sig.fs, 16);
testCase.verifyNotEmpty(sig.signal);
testCase.verifyEqual(height(sig.logbook), 1);
end
function castingRoundTripPreservesSignalThroughAllDomains(testCase)
infoIn = Informationsignal([0; 1; 1; 0]);
elecFromInfo = infoIn.Electricalsignal("fs", 64e9, "logbook", infoIn.logbook);
optFromElec = elecFromInfo.Opticalsignal( ...
"fs", elecFromInfo.fs, ...
"logbook", elecFromInfo.logbook, ...
"lambda", 1310e-9, ...
"nase", 0, ...
"polrot", 0);
elecFromOpt = optFromElec.Electricalsignal("fs", optFromElec.fs, "logbook", optFromElec.logbook);
infoOut = elecFromOpt.Informationsignal("fs", elecFromOpt.fs, "logbook", elecFromOpt.logbook);
testCase.verifyClass(elecFromInfo, 'Electricalsignal');
testCase.verifyClass(optFromElec, 'Opticalsignal');
testCase.verifyClass(elecFromOpt, 'Electricalsignal');
testCase.verifyClass(infoOut, 'Informationsignal');
testCase.verifyEqual(infoOut.signal, infoIn.signal);
testCase.verifyEqual(elecFromInfo.fs, 64e9);
testCase.verifyEqual(optFromElec.fs, 64e9);
testCase.verifyEqual(elecFromOpt.fs, 64e9);
testCase.verifyEqual(infoOut.fs, 64e9);
testCase.verifyEqual(optFromElec.lambda, 1310e-9);
testCase.verifyEqual(optFromElec.nase, 0);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef AWG_test < matlab.unittest.TestCase classdef AWG_test < IMDDTestCase
% Test class for AWG % Auto-generated placeholder for AWG.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/AWG.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for AWG testCase.assumeFail("Tests for AWG are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef ChannelFreqResp_test < matlab.unittest.TestCase classdef ChannelFreqResp_test < IMDDTestCase
% Test class for ChannelFreqResp % Auto-generated placeholder for ChannelFreqResp.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/ChannelFreqResp.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for ChannelFreqResp testCase.assumeFail("Tests for ChannelFreqResp are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef M8196A_test < matlab.unittest.TestCase classdef M8196A_test < IMDDTestCase
% Test class for M8196A % Auto-generated placeholder for M8196A.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8196A.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for M8196A testCase.assumeFail("Tests for M8196A are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef M8199A_test < matlab.unittest.TestCase classdef M8199A_test < IMDDTestCase
% Test class for M8199A % Auto-generated placeholder for M8199A.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8199A.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for M8199A testCase.assumeFail("Tests for M8199A are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef M8199B_test < matlab.unittest.TestCase classdef M8199B_test < IMDDTestCase
% Test class for M8199B % Auto-generated placeholder for M8199B.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8199B.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for M8199B testCase.assumeFail("Tests for M8199B are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,74 +1,69 @@
classdef PAMmapper_test < matlab.unittest.TestCase classdef PAMmapper_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pammapper'})
properties
Tx_bits
PAMmapper
end
properties (MethodSetupParameter) function roundTripBitMappingForSupportedPamOrders(testCase)
% Define method-level parameters for PRBS and bit pattern modulationOrders = [2, 4, 8];
useprbs = struct('false', 0, 'true', 1); % variations: {0, 1}
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
O = struct('O10', 10, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
end
properties (TestParameter) for M = modulationOrders
% Define test-level parameters for M and O txBits = Informationsignal(allBitPatternsForOrder(M));
end mapper = PAMmapper(M, 0);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
methods (TestMethodSetup) testCase.verifyEqual(double(demapped.signal), double(txBits.signal), ...
sprintf("Roundtrip mapping failed for PAM-%d.", M));
function setupModulation(testCase, useprbs, M, O)
% Setup PRBS and bit pattern for the test case using parameters
% Setup PRBS parameters
N = 2^(O-1); % Length of PRBS
randkey = 1; % Random key for random stream
[~, 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
end end
if M == 6 function roundTripPam6ClassicMapping(testCase)
bitpattern = reshape(bitpattern, [], 1); txBits = Informationsignal(pam6BitStream());
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
mapper = PAMmapper(6, 0);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
testCase.verifyEqual(demapped.signal, txBits.signal, ...
"PAM-6 classic mapping should be lossless for aligned inputs.");
end end
testCase.Tx_bits = Informationsignal(bitpattern); function roundTripPam6EthMapping(testCase)
testCase.PAMmapper = PAMmapper(M, 0); txBits = Informationsignal(pam6BitStream());
mapper = PAMmapper(6, 0, "eth_style", 1);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
expectedBits = txBits.signal(1:length(demapped.signal));
testCase.verifyEqual(demapped.signal, expectedBits, ...
"PAM-6 ETH mapping should be lossless for aligned inputs.");
end end
end function quantizeMapsToNearestConstellationLevel(testCase)
mapper = PAMmapper(4, 0);
signalIn = Electricalsignal([-4.0; -0.2; 0.4; 2.9], "fs", 1);
methods (Test, ParameterCombination = 'sequential') quantized = mapper.quantize(signalIn);
% Test with sequential combination of parameters expected = [-3; -1; 1; 3] ./ sqrt(5);
function testBackToBackMapping(testCase, M, useprbs, O)
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
% Map bits to symbols testCase.verifyEqual(quantized.signal, expected, "AbsTol", 1e-12);
Symbols = testCase.PAMmapper.map(testCase.Tx_bits);
% Demap symbols back to bits
Rx_bits = testCase.PAMmapper.demap(Symbols);
% Validate BER is zero
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, 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 end
end
function bits = allBitPatternsForOrder(M)
bitWidth = log2(M);
symbols = (0:M-1).';
bits = zeros(M, bitWidth);
for bitIdx = 1:bitWidth
bits(:, bitIdx) = bitget(symbols, bitWidth - bitIdx + 1);
end
end
function bits = pam6BitStream()
combinations = dec2bin(0:31, 5) - '0';
bits = reshape(combinations.', [], 1);
end end

View File

@@ -1,11 +1,104 @@
classdef PAMsource_test < matlab.unittest.TestCase classdef PAMsource_test < IMDDTestCase
% Test class for PAMsource methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pamsource'})
function constructorStoresProvidedOptions(testCase)
src = PAMsource( ...
"order", 5, ...
"useprbs", false, ...
"M", 4, ...
"fsym", 8, ...
"randkey", 17, ...
"applypulseform", false, ...
"fs_out", 8, ...
"applyclipping", false);
methods (Test) testCase.verifyEqual(src.order, 5);
function testExample(testCase) testCase.verifyFalse(src.useprbs);
% Example test case for PAMsource testCase.verifyEqual(src.M, 4);
% Add your test code here testCase.verifyEqual(src.fsym, 8);
testCase.verifyTrue(true); testCase.verifyEqual(src.randkey, 17);
testCase.verifyFalse(src.applypulseform);
testCase.verifyEqual(src.fs_out, 8);
testCase.verifyFalse(src.applyclipping);
testCase.verifyEmpty(src.pulseformer);
end
function deterministicProcessMatchesPamMapperAcrossOrders(testCase)
orders = [2, 4, 8];
sourceOrder = 5;
fs = 8;
seed = 17;
for M = orders
src = PAMsource( ...
"order", sourceOrder, ...
"useprbs", false, ...
"M", M, ...
"fsym", fs, ...
"randkey", seed, ...
"applypulseform", false, ...
"fs_out", fs, ...
"applyclipping", false);
[digiSig, symbols, bits] = src.process();
bitpattern = expectedBitpattern(M, sourceOrder, seed);
expectedBits = Informationsignal(bitpattern);
expectedSymbols = PAMmapper(M, 0).map(expectedBits);
testCase.verifyClass(digiSig, 'Informationsignal');
testCase.verifyClass(symbols, 'Informationsignal');
testCase.verifyClass(bits, 'Informationsignal');
testCase.verifyEqual(bits.signal, bitpattern);
testCase.verifyEqual(symbols.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.fs, fs);
end
end
function clippingLimitsAmplitudeToScaledConstellationRange(testCase)
M = 4;
sourceOrder = 5;
fs = 8;
seed = 3;
src = PAMsource( ...
"order", sourceOrder, ...
"useprbs", false, ...
"M", M, ...
"fsym", fs, ...
"randkey", seed, ...
"applypulseform", false, ...
"fs_out", fs, ...
"applyclipping", true, ...
"clipfactor", 0.5);
[digiSig, symbols, bits] = src.process();
expectedBits = expectedBitpattern(M, sourceOrder, seed);
expectedSymbols = PAMmapper(M, 0).map(Informationsignal(expectedBits));
lowerLimit = min(expectedSymbols.signal) * 0.5;
upperLimit = max(expectedSymbols.signal) * 0.5;
expectedClipped = expectedSymbols.signal;
expectedClipped(expectedClipped < lowerLimit) = lowerLimit;
expectedClipped(expectedClipped > upperLimit) = upperLimit;
testCase.verifyEqual(bits.signal, expectedBits);
testCase.verifyEqual(symbols.signal, expectedSymbols.signal);
testCase.verifyEqual(digiSig.signal, expectedClipped);
testCase.verifyEqual(digiSig.fs, fs);
testCase.verifyLessThanOrEqual(max(digiSig.signal), upperLimit);
testCase.verifyGreaterThanOrEqual(min(digiSig.signal), lowerLimit);
end end
end end
end end
function bitpattern = expectedBitpattern(M, order, seed)
bitWidth = log2(M);
N = 2^(order - 1);
s = RandStream('twister', 'Seed', seed);
bitpattern = zeros(N, bitWidth);
for idx = 1:bitWidth
bitpattern(:, idx) = randi(s, [0 1], N, 1);
end
end

View File

@@ -1,11 +1,120 @@
classdef Pulseformer_test < matlab.unittest.TestCase classdef Pulseformer_test < IMDDTestCase
% Test class for Pulseformer methods (Test, TestTags = {'unit', 'fast', 'transmit', 'pulseformer'})
function constructorStoresConfiguredProperties(testCase)
pf = Pulseformer( ...
"fdac", 64e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 12, ...
"alpha", 0.2, ...
"matched", 1);
methods (Test) testCase.verifyEqual(pf.fdac, 64e9);
function testExample(testCase) testCase.verifyEqual(pf.fsym, 16e9);
% Example test case for Pulseformer testCase.verifyEqual(pf.pulse, pulseform.rrc);
% Add your test code here testCase.verifyEqual(pf.pulselength, 12);
testCase.verifyTrue(true); testCase.verifyEqual(pf.alpha, 0.2);
testCase.verifyEqual(pf.matched, 1);
end
function processUsesSymbolRateFallbackAndUpdatesSignalMetadata(testCase)
fsym = 16e9;
fdac = 64e9;
tx = makeInformationsignal([1; 0; -1; 1; 1; 0], []);
pf = Pulseformer( ...
"fdac", fdac, ...
"fsym", fsym, ...
"pulse", pulseform.rc, ...
"pulselength", 8, ...
"alpha", 0.35, ...
"matched", 0);
rx = pf.process(tx);
expected = expectedPulseformerOutput(pf, tx);
testCase.verifyClass(rx, 'Informationsignal');
testCase.verifyEqual(rx.signal, expected, "AbsTol", 1e-12);
testCase.verifyEqual(rx.fs, fdac);
testCase.verifyEqual(height(rx.logbook), height(tx.logbook) + 1);
testCase.verifyEqual(string(rx.logbook.Description(end)), "Applied Pulseshaping");
end
function matchedAndUnmatchedProcessingPreserveTheSameRealWaveform(testCase)
tx = makeInformationsignal([1; 0; 0; -1; 1; -1; 0; 1], 16e9);
unmatched = Pulseformer( ...
"fdac", 32e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 10, ...
"alpha", 0.15, ...
"matched", 0);
matched = Pulseformer( ...
"fdac", 32e9, ...
"fsym", 16e9, ...
"pulse", pulseform.rrc, ...
"pulselength", 10, ...
"alpha", 0.15, ...
"matched", 1);
rxUnmatched = unmatched.process(tx);
rxMatched = matched.process(tx);
testCase.verifyEqual(length(rxUnmatched.signal), length(rxMatched.signal));
testCase.verifyEqual(rxUnmatched.signal, rxMatched.signal, "AbsTol", 1e-12);
testCase.verifyEqual(rxUnmatched.signal, expectedPulseformerOutput(unmatched, tx), "AbsTol", 1e-12);
testCase.verifyEqual(rxMatched.signal, expectedPulseformerOutput(matched, tx), "AbsTol", 1e-12);
end
function processPreservesLengthForIntegerRateConversion(testCase)
tx = makeInformationsignal((1:5).', []);
pf = Pulseformer( ...
"fdac", 20e9, ...
"fsym", 5e9, ...
"pulse", pulseform.rc, ...
"pulselength", 6, ...
"alpha", 0.25, ...
"matched", 0);
rx = pf.process(tx);
testCase.verifyEqual(length(rx.signal), 20);
testCase.verifyEqual(rx.fs, 20e9);
end end
end end
end end
function sig = makeInformationsignal(values, fs)
base = Signal(values);
sig = Informationsignal(values, "fs", fs, "logbook", base.logbook);
end
function expected = expectedPulseformerOutput(pf, signalclass_in)
if isprop(signalclass_in, 'fs') && ~isempty(signalclass_in.fs)
f_in = signalclass_in.fs;
else
f_in = pf.fsym;
end
[p, q] = rat(pf.fdac / f_in);
fs_intermediate = f_in * p;
sps_filter = fs_intermediate / pf.fsym;
if pf.pulse == pulseform.rc
filtertype = 'normal';
else
filtertype = 'sqrt';
end
h = rcosdesign(pf.alpha, pf.pulselength, sps_filter, filtertype);
if pf.matched
h = conj(fliplr(h));
end
data_out_ = upfirdn(signalclass_in.signal, h, p, q);
delay_samples_intermediate = (length(h) - 1) / 2;
delay_samples_out = delay_samples_intermediate / q;
st = floor(delay_samples_out) + 1;
len_out = ceil(length(signalclass_in.signal) * p / q);
expected = data_out_(st : st + len_out - 1);
end

View File

@@ -1,11 +1,10 @@
classdef Signalgenerator_test < matlab.unittest.TestCase classdef Signalgenerator_test < IMDDTestCase
% Test class for Signalgenerator % Auto-generated placeholder for Signalgenerator.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/Signalgenerator.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Signalgenerator testCase.assumeFail("Tests for Signalgenerator are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Amplifier_test < matlab.unittest.TestCase classdef Amplifier_test < IMDDTestCase
% Test class for Amplifier % Auto-generated placeholder for Amplifier.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_etc/Amplifier.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Amplifier testCase.assumeFail("Tests for Amplifier are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Filter_test < matlab.unittest.TestCase classdef Filter_test < IMDDTestCase
% Test class for Filter % Auto-generated placeholder for Filter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_etc/Filter.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Filter testCase.assumeFail("Tests for Filter are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef DP_Fiber_test < matlab.unittest.TestCase classdef DP_Fiber_test < IMDDTestCase
% Test class for DP_Fiber % Auto-generated placeholder for DP_Fiber.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/DP_Fiber.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for DP_Fiber testCase.assumeFail("Tests for DP_Fiber are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EML_test < matlab.unittest.TestCase classdef EML_test < IMDDTestCase
% Test class for EML % Auto-generated placeholder for EML.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/EML.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EML testCase.assumeFail("Tests for EML are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,87 @@
classdef Fiber_test < matlab.unittest.TestCase classdef Fiber_test < IMDDTestCase
% Test class for Fiber methods (Test, TestTags = {'unit', 'fast', 'optical', 'fiber'})
function zeroLengthPropagationLeavesSignalUnchanged(testCase)
fiber = Fiber("fsimu", 64e9, "fiber_length", 0, "alpha", 0, "D", 0, ...
"Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal([1 + 1i; -2 + 0.5i; 0.25 - 0.75i], 64e9, 1310e-9);
methods (Test) outputSig = fiber.process_(inputSig);
function testExample(testCase)
% Example test case for Fiber testCase.verifyClass(outputSig, 'Opticalsignal');
% Add your test code here testCase.verifyEqual(outputSig.signal, inputSig.signal, "AbsTol", 1e-12);
testCase.verifyTrue(true); testCase.verifyEqual(outputSig.lambda, inputSig.lambda);
testCase.verifyEqual(outputSig.fs, inputSig.fs);
end
function attenuationOnlyMatchesAnalyticalFieldScaling(testCase)
fs = 32e9;
lambda = 1310e-9;
fiberLengthKm = 2.5;
alphaDbPerKm = 0.2;
inputSignal = [1 + 2i; -0.5 + 0.25i; 0.75 - 1.25i; 2 - 1i];
fiber = Fiber("fsimu", fs, "fiber_length", fiberLengthKm, "alpha", alphaDbPerKm, ...
"D", 0, "Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal(inputSignal, fs, lambda);
outputSig = fiber.process_(inputSig);
alphaLin = alphaDbPerKm / 10 * log(10) / 1e3;
expected = inputSignal .* exp(-alphaLin / 2 * fiber.fiber_length);
testCase.verifyEqual(outputSig.signal, expected, "AbsTol", 1e-12);
end
function linearOnlyPropagationPreservesShapeAndEnergyWhenLossless(testCase)
fs = 64e9;
lambda = 1310e-9;
inputSignal = [1 + 0.5i; -1i; 0.75; 2 - 0.25i];
fiber = Fiber("fsimu", fs, "fiber_length", 0.3, "alpha", 0, ...
"D", 0, "Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal(inputSignal, fs, lambda);
outputSig = fiber.process_(inputSig);
testCase.verifySize(outputSig.signal, size(inputSignal));
testCase.verifyEqual(outputSig.signal, inputSignal, "AbsTol", 1e-12);
testCase.verifyEqual(norm(outputSig.signal), norm(inputSignal), "AbsTol", 1e-12);
end
function processAddsLogbookEntryAndReturnsOpticalsignal(testCase)
fs = 32e9;
lambda = 1310e-9;
fiber = Fiber("fsimu", fs, "fiber_length", 0, "alpha", 0, "D", 0, ...
"Dslope", 0, "lambda0", 1310, "gamma", 0);
inputSig = makeOpticalsignal([1; -1; 2], fs, lambda);
outputSig = fiber.process(inputSig);
testCase.verifyClass(outputSig, 'Opticalsignal');
testCase.verifyEqual(outputSig.signal, inputSig.signal, "AbsTol", 1e-12);
testCase.verifyEqual(height(outputSig.logbook), height(inputSig.logbook) + 1);
testCase.verifyEqual(string(outputSig.logbook.Description(end)), "Fiber ");
end end
end end
end end
function sig = makeOpticalsignal(values, fs, lambda)
sig = Opticalsignal(values, ...
"fs", fs, ...
"logbook", emptyLogbook(), ...
"lambda", lambda, ...
"nase", 0, ...
"polrot", 0);
end
function lb = emptyLogbook()
SignalType = [];
TimeStamp = [];
Length = [];
SignalPower = [];
Nase = [];
SignalCopy = [];
ModifierName = [];
ModifierCopy = {};
Description = [];
lb = table(SignalType, TimeStamp, Length, SignalPower, Nase, SignalCopy, ModifierName, ModifierCopy, Description);
end

View File

@@ -1,11 +1,10 @@
classdef Optical_Demultiplex_test < matlab.unittest.TestCase classdef Optical_Demultiplex_test < IMDDTestCase
% Test class for Optical_Demultiplex % Auto-generated placeholder for Optical_Demultiplex.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Optical_Demultiplex.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Optical_Demultiplex testCase.assumeFail("Tests for Optical_Demultiplex are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Optical_Multiplex_test < matlab.unittest.TestCase classdef Optical_Multiplex_test < IMDDTestCase
% Test class for Optical_Multiplex % Auto-generated placeholder for Optical_Multiplex.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Optical_Multiplex.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Optical_Multiplex testCase.assumeFail("Tests for Optical_Multiplex are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Polarization_Controller_test < matlab.unittest.TestCase classdef Polarization_Controller_test < IMDDTestCase
% Test class for Polarization_Controller % Auto-generated placeholder for Polarization_Controller.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Polarization_Controller.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Polarization_Controller testCase.assumeFail("Tests for Polarization_Controller are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +0,0 @@
classdef CNLSE_plain_test < matlab.unittest.TestCase
% Test class for CNLSE_plain
methods (Test)
function testExample(testCase)
% Example test case for CNLSE_plain
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef CNLSE_test < matlab.unittest.TestCase
% Test class for CNLSE
methods (Test)
function testExample(testCase)
% Example test case for CNLSE
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef canUseGPU_test < matlab.unittest.TestCase
% Test class for canUseGPU
methods (Test)
function testExample(testCase)
% Example test case for canUseGPU
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef getNLstepsize_original_test < matlab.unittest.TestCase
% Test class for getNLstepsize_original
methods (Test)
function testExample(testCase)
% Example test case for getNLstepsize_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef getNLstepsize_test < matlab.unittest.TestCase
% Test class for getNLstepsize
methods (Test)
function testExample(testCase)
% Example test case for getNLstepsize
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef lin_step_original_test < matlab.unittest.TestCase
% Test class for lin_step_original
methods (Test)
function testExample(testCase)
% Example test case for lin_step_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef lin_step_test < matlab.unittest.TestCase
% Test class for lin_step
methods (Test)
function testExample(testCase)
% Example test case for lin_step
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef nl_step_original_test < matlab.unittest.TestCase
% Test class for nl_step_original
methods (Test)
function testExample(testCase)
% Example test case for nl_step_original
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef nl_step_test < matlab.unittest.TestCase
% Test class for nl_step
methods (Test)
function testExample(testCase)
% Example test case for nl_step
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,11 +0,0 @@
classdef split_step_loop_test < matlab.unittest.TestCase
% Test class for split_step_loop
methods (Test)
function testExample(testCase)
% Example test case for split_step_loop
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -0,0 +1,10 @@
classdef CTLE_test < IMDDTestCase
% Auto-generated placeholder for CTLE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/CTLE.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for CTLE are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Hybrid_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Hybrid.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Hybrid.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Hybrid are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Trace_BiDi_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Trace_BiDi.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Trace_BiDi.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Trace_BiDi are not implemented yet.");
end
end
end

View File

@@ -0,0 +1,10 @@
classdef Electrical_Trace_test < IMDDTestCase
% Auto-generated placeholder for Electrical_Trace.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/03_electrical/Electrical_Trace.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Electrical_Trace are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,49 @@
classdef Photodiode_test < matlab.unittest.TestCase classdef Photodiode_test < IMDDTestCase
% Test class for Photodiode methods (Test, TestTags = {'unit', 'fast', 'receive', 'photodiode'})
function processZeroNoiseBaselineMatchesAnalyticalExpectation(testCase)
pd = Photodiode("fsimu", 0, "responsivity", 2.5, "dark_current", 0.75, "nep", 0, "randomkey", 1);
xin = [1 + 1i, 2 - 1i; 0.5, 0.25i];
methods (Test) yout = pd.process_(xin);
function testExample(testCase) expected = 2.5 * sum(abs(xin).^2, 2) + 0.75;
% Example test case for Photodiode
% Add your test code here testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
testCase.verifyTrue(true); end
function responsivityScalesDetectedPowerLinearly(testCase)
xin = [1 + 2i, 0.5 - 0.5i; 0.25, 1i];
pd1 = Photodiode("fsimu", 0, "responsivity", 1, "dark_current", 0, "nep", 0, "randomkey", 1);
pd2 = Photodiode("fsimu", 0, "responsivity", 3.5, "dark_current", 0, "nep", 0, "randomkey", 1);
y1 = pd1.process_(xin);
y2 = pd2.process_(xin);
testCase.verifyEqual(y2, 3.5 * y1, "AbsTol", 1e-12);
end
function darkCurrentAddsConstantOffset(testCase)
xin = [1; 0; 2];
pdNoDc = Photodiode("fsimu", 0, "responsivity", 1.2, "dark_current", 0, "nep", 0, "randomkey", 1);
pdWithDc = Photodiode("fsimu", 0, "responsivity", 1.2, "dark_current", 0.42, "nep", 0, "randomkey", 1);
yNoDc = pdNoDc.process_(xin);
yWithDc = pdWithDc.process_(xin);
testCase.verifyEqual(yWithDc - yNoDc, 0.42 * ones(size(xin, 1), 1), "AbsTol", 1e-12);
end
function identicalSeedsProduceIdenticalStochasticOutputs(testCase)
xin = [1 + 1i; 0.5; 2];
pd1 = Photodiode("fsimu", 1, "responsivity", 0, "dark_current", 0, "nep", 1e-12, "randomkey", 7);
pd2 = Photodiode("fsimu", 1, "responsivity", 0, "dark_current", 0, "nep", 1e-12, "randomkey", 7);
y1 = pd1.process_(xin);
y2 = pd2.process_(xin);
testCase.verifyEqual(y1, y2);
end end
end end
end end

View File

@@ -1,11 +1,49 @@
classdef Scope_test < matlab.unittest.TestCase classdef Scope_test < IMDDTestCase
% Test class for Scope methods (Test, TestTags = {'unit', 'fast', 'receive', 'scope'})
function quantizeMapsRealSignalToExpectedGrid(testCase)
scope = makeScope(10, 10, 2, 0, true);
xin = (0:9).';
methods (Test) quantized = scope.quantize(xin);
function testExample(testCase)
% Example test case for Scope expected = [0; 0; 8/3; 8/3; 16/3; 16/3; 16/3; 8; 8; 8];
% Add your test code here testCase.verifyEqual(quantized, expected, "AbsTol", 1e-12);
testCase.verifyTrue(true); end
function process_ResamplesQuantizesAndSubtractsDc(testCase)
scope = makeScope(40, 20, 3, 0, true);
xin = (1:40).';
yout = scope.process_(xin);
expected = scope.quantize(resample(xin, scope.fadc, scope.fsimu));
expected = expected - mean(expected, 1);
testCase.verifyEqual(length(yout), 20);
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
testCase.verifyEqual(mean(yout), 0, "AbsTol", 1e-12);
end
function processWithoutDcBlockingPreservesQuantizedMean(testCase)
scope = makeScope(40, 20, 3, 0, false);
xin = (1:40).';
yout = scope.process_(xin);
expected = scope.quantize(resample(xin, scope.fadc, scope.fsimu));
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
testCase.verifyGreaterThan(abs(mean(yout)), 1e-12);
end end
end end
end end
function scope = makeScope(fsimu, fadc, adcresolution, quantbuffer, block_dc)
scope = Scope( ...
"fsimu", fsimu, ...
"fadc", fadc, ...
"adcresolution", adcresolution, ...
"quantbuffer", quantbuffer, ...
"block_dc", block_dc, ...
"H_lpf", struct('fs', fadc));
end

View File

@@ -1,11 +0,0 @@
classdef CIC_filter_test < matlab.unittest.TestCase
% Test class for CIC_filter
methods (Test)
function testExample(testCase)
% Example test case for CIC_filter
% Add your test code here
testCase.verifyTrue(true);
end
end
end

View File

@@ -1,137 +1,10 @@
classdef Duobinary_test < matlab.unittest.TestCase classdef Duobinary_test < IMDDTestCase
% Auto-generated placeholder for Duobinary.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Coding/Duobinary.m
properties methods (Test, TestTags = {'placeholder', 'todo'})
%genereal properties of the test function testNotImplemented(testCase)
ber testCase.assumeFail("Tests for Duobinary are not implemented yet.");
errors
errorIndice
numbits
numsymbols
end
properties (MethodSetupParameter)
% Define method-level parameters for PRBS and bit pattern
% i.e.: useprbs = {0,1};
useprbs = struct('true', 0); % variations: {0, 1}
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
O = struct('O10', 10,'O11', 11,'O12', 12,'O13', 13, 'O15', 15, 'O17', 17, 'O18', 18, 'O19', 19); % variations: {10, 15, 17}
end
properties (TestParameter)
% Define test-level parameters for M and O
end
methods (TestMethodSetup, ParameterCombination = 'pairwise')
function setupTest(testCase, useprbs, M, O)
randkey = 1;
datarate = 448e9;
fsym = round(datarate / log2(M)) ;
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs
bitpattern=[];
if useprbs
%%%%% MOVE-IT PRMS %%%%
state = struct();
para = struct();
if M == 6
para.bl = 2^(O-2);
para.dimension = 5;
else
para.bl = 2^(O-1);
para.dimension = log2(M); %2.5bits/sym -> 2 bit/sym
end
para.rand = 0;
para.order = floor(O / log2(M));
para.skip =0;
para.bruijn = 0;
para.reset_prms = 0;
para.method = 1;
data_in = [];
global loop;
loop = 0;
[data_out,state_] = prms(data_in, state, para);
loop = 1;
[data_out,state_out] = prms(data_in, state_, para);
bitpattern = data_out';
%%%%% END MOVE-IT %%%%%%%
else
s = RandStream('twister','Seed',randkey);
for i = 1:log2(M)
bitpattern(:,i) = randi(s,[0 1], N, 1);
end end
end end
if M == 6
bitpattern = reshape(bitpattern',[],1);
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
end
testCase.numbits = length(bitpattern);
Tx_bits = Informationsignal(bitpattern);
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
Symbols_tx.fs = fsym;
testCase.numsymbols = length(Symbols_tx);
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
Symbols_tx.fs = fsym;
Symbols = Duobinary().precode(Symbols_tx);
Symbols = Duobinary().encode(Symbols);
Symbols = Duobinary().decode(Symbols);
Rx_bits = PAMmapper(M,0).demap(Symbols);
[bits,testCase.errors,testCase.ber,testCase.errorIndice] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
end
end
methods (Test)
% Test with sequential combination of parameters
function checkBerZero(testCase, useprbs, M, O)
% Assert that BER is zero
testCase.verifyEqual(testCase.ber, 0, ['Numer of Errors is not zero, found ',num2str(testCase.errors), ' errors at position ', num2str(testCase.errorIndice),' out of ', num2str(2^O)]);
end
function checkBerCloseToZero(testCase, useprbs, M, O)
testCase.verifyLessThan(testCase.errors, 5, ['Found more than 5 errors. Found ',num2str(testCase.errors),' errors.']);
% if ~isempty(testCase.errorIndice)
% testCase.verifyEqual(testCase.errorIndice, 2^O , ['Error is NOT at the End but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
% testCase.verifyEqual(testCase.errorIndice,1, ['Error is NOT at the Beginning but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
% end
end
function checkSystemFailure(testCase, useprbs, M, O)
testCase.verifyLessThan(testCase.ber, 0.1, ['BER is higher than 10%. Soemthing is completely wrong! (BER is ',num2str(testCase.ber),')']);
end
end
end end

View File

@@ -1,11 +1,10 @@
classdef MRDS_coding_test < matlab.unittest.TestCase classdef MRDS_coding_test < IMDDTestCase
% Test class for MRDS_coding % Auto-generated placeholder for MRDS_coding.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Coding/MRDS_coding.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for MRDS_coding testCase.assumeFail("Tests for MRDS_coding are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_copy_test < matlab.unittest.TestCase classdef EQ_copy_test < IMDDTestCase
% Test class for EQ_copy % Auto-generated placeholder for EQ_copy.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_copy.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ_copy testCase.assumeFail("Tests for EQ_copy are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_ofc_test < matlab.unittest.TestCase classdef EQ_silas_ofc_test < IMDDTestCase
% Test class for EQ_silas_ofc % Auto-generated placeholder for EQ_silas_ofc.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_ofc.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ_silas_ofc testCase.assumeFail("Tests for EQ_silas_ofc are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_plain_test < matlab.unittest.TestCase classdef EQ_silas_plain_test < IMDDTestCase
% Test class for EQ_silas_plain % Auto-generated placeholder for EQ_silas_plain.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_plain.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ_silas_plain testCase.assumeFail("Tests for EQ_silas_plain are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_sliding_window_dc_removal_test < matlab.unittest.TestCase classdef EQ_silas_sliding_window_dc_removal_test < IMDDTestCase
% Test class for EQ_silas_sliding_window_dc_removal % Auto-generated placeholder for EQ_silas_sliding_window_dc_removal.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas_sliding_window_dc_removal.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ_silas_sliding_window_dc_removal testCase.assumeFail("Tests for EQ_silas_sliding_window_dc_removal are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_test < matlab.unittest.TestCase classdef EQ_silas_test < IMDDTestCase
% Test class for EQ_silas % Auto-generated placeholder for EQ_silas.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ_silas.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ_silas testCase.assumeFail("Tests for EQ_silas are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef EQ_test < matlab.unittest.TestCase classdef EQ_test < IMDDTestCase
% Test class for EQ % Auto-generated placeholder for EQ.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/EQ.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for EQ testCase.assumeFail("Tests for EQ are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_adaptive_mu_test < matlab.unittest.TestCase classdef FFE_DCremoval_adaptive_mu_test < IMDDTestCase
% Test class for FFE_DCremoval_adaptive_mu % Auto-generated placeholder for FFE_DCremoval_adaptive_mu.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval_adaptive_mu.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_DCremoval_adaptive_mu testCase.assumeFail("Tests for FFE_DCremoval_adaptive_mu are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_level_test < matlab.unittest.TestCase classdef FFE_DCremoval_level_test < IMDDTestCase
% Test class for FFE_DCremoval_level % Auto-generated placeholder for FFE_DCremoval_level.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval_level.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_DCremoval_level testCase.assumeFail("Tests for FFE_DCremoval_level are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_test < matlab.unittest.TestCase classdef FFE_DCremoval_test < IMDDTestCase
% Test class for FFE_DCremoval % Auto-generated placeholder for FFE_DCremoval.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DCremoval.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_DCremoval testCase.assumeFail("Tests for FFE_DCremoval are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_DFE_test < matlab.unittest.TestCase classdef FFE_DFE_test < IMDDTestCase
% Test class for FFE_DFE % Auto-generated placeholder for FFE_DFE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_DFE.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_DFE testCase.assumeFail("Tests for FFE_DFE are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_FFDCAVG_test < matlab.unittest.TestCase classdef FFE_FFDCAVG_test < IMDDTestCase
% Test class for FFE_FFDCAVG % Auto-generated placeholder for FFE_FFDCAVG.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_FFDCAVG.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_FFDCAVG testCase.assumeFail("Tests for FFE_FFDCAVG are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_Kalman_Feedback_test < matlab.unittest.TestCase classdef FFE_Kalman_Feedback_test < IMDDTestCase
% Test class for FFE_Kalman_Feedback % Auto-generated placeholder for FFE_Kalman_Feedback.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_Kalman_Feedback.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_Kalman_Feedback testCase.assumeFail("Tests for FFE_Kalman_Feedback are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_Kalman_test < matlab.unittest.TestCase classdef FFE_Kalman_test < IMDDTestCase
% Test class for FFE_Kalman % Auto-generated placeholder for FFE_Kalman.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_Kalman.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_Kalman testCase.assumeFail("Tests for FFE_Kalman are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_MLSE_test < matlab.unittest.TestCase classdef FFE_MLSE_test < IMDDTestCase
% Test class for FFE_MLSE % Auto-generated placeholder for FFE_MLSE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_MLSE.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_MLSE testCase.assumeFail("Tests for FFE_MLSE are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef FFE_adaptive_decision_test < matlab.unittest.TestCase classdef FFE_adaptive_decision_test < IMDDTestCase
% Test class for FFE_adaptive_decision % Auto-generated placeholder for FFE_adaptive_decision.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/FFE_adaptive_decision.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for FFE_adaptive_decision testCase.assumeFail("Tests for FFE_adaptive_decision are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,78 @@
classdef FFE_test < matlab.unittest.TestCase classdef FFE_test < IMDDTestCase
% Test class for FFE methods (Test, TestTags = {'unit', 'fast', 'dsp', 'ffe'})
function constructorStoresDefaultsAndInitialState(testCase)
ffe = FFE();
methods (Test) testCase.verifyEqual(ffe.sps, 2);
function testExample(testCase) testCase.verifyEqual(ffe.order, 15);
% Example test case for FFE testCase.verifyEqual(ffe.len_tr, 4096);
% Add your test code here testCase.verifyEqual(ffe.mu_tr, 0);
testCase.verifyTrue(true); testCase.verifyEqual(ffe.epochs_tr, 5);
testCase.verifyEqual(ffe.adaption_technique, adaption_method.lms);
testCase.verifyEqual(ffe.dd_mode, 1);
testCase.verifyEqual(ffe.mu_dd, 1e-5);
testCase.verifyEqual(ffe.epochs_dd, 5);
testCase.verifyFalse(ffe.decide);
testCase.verifyEqual(ffe.e, zeros(ffe.order, 1));
testCase.verifyEqual(ffe.error, 0);
end
function noUpdateModeKeepsWeightsAtZeroAndPreservesSamplingRate(testCase)
x = makeSignal([-1; 1; -1; 1], 32e9);
d = makeSignal([-1; 1; -1; 1], 8e9);
ffe = FFE( ...
"sps", 1, ...
"order", 1, ...
"len_tr", length(x), ...
"mu_tr", 0, ...
"epochs_tr", 1, ...
"mu_dd", 0, ...
"epochs_dd", 1, ...
"dd_mode", 0, ...
"decide", false, ...
"adaption_technique", adaption_method.lms);
[y, noi] = ffe.process(x, d);
testCase.verifyEqual(ffe.e, 0);
testCase.verifyEqual(ffe.e_tr, 0);
testCase.verifyEqual(y.signal, zeros(size(x.signal)), "AbsTol", 1e-12);
testCase.verifyEqual(y.fs, d.fs);
testCase.verifyEqual(noi.signal, -d.signal, "AbsTol", 1e-12);
testCase.verifyEqual(length(y.signal), length(x.signal));
end
function trainingModeLearnsFromTinySyntheticChannel(testCase)
x = makeSignal([1; -1; 1; -1], 16e9);
d = makeSignal([1; -1; 1; -1], 4e9);
ffe = FFE( ...
"sps", 1, ...
"order", 1, ...
"len_tr", length(x), ...
"mu_tr", 0.5, ...
"epochs_tr", 1, ...
"mu_dd", 0, ...
"epochs_dd", 1, ...
"dd_mode", 0, ...
"decide", false, ...
"adaption_technique", adaption_method.lms);
[y, noi] = ffe.process(x, d);
testCase.verifyEqual(y.fs, d.fs);
testCase.verifyClass(y, 'Informationsignal');
testCase.verifyClass(noi, 'Informationsignal');
testCase.verifyNotEqual(ffe.e, 0);
testCase.verifyNotEqual(ffe.e_tr, 0);
testCase.verifyNotEqual(y.signal, zeros(size(x.signal)));
testCase.verifyEqual(length(y.signal), length(x.signal));
end end
end end
end end
function sig = makeSignal(values, fs)
base = Signal(values);
sig = Informationsignal(values, "fs", fs, "logbook", base.logbook);
end

View File

@@ -1,11 +1,10 @@
classdef ML_MLSE_GPU_test < matlab.unittest.TestCase classdef ML_MLSE_GPU_test < IMDDTestCase
% Test class for ML_MLSE_GPU % Auto-generated placeholder for ML_MLSE_GPU.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/ML_MLSE_GPU.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for ML_MLSE_GPU testCase.assumeFail("Tests for ML_MLSE_GPU are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef ML_MLSE_test < matlab.unittest.TestCase classdef ML_MLSE_test < IMDDTestCase
% Test class for ML_MLSE % Auto-generated placeholder for ML_MLSE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/ML_MLSE.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for ML_MLSE testCase.assumeFail("Tests for ML_MLSE are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Postfilter_test < matlab.unittest.TestCase classdef Postfilter_test < IMDDTestCase
% Test class for Postfilter % Auto-generated placeholder for Postfilter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/Postfilter.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Postfilter testCase.assumeFail("Tests for Postfilter are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef VNLE_test < matlab.unittest.TestCase classdef VNLE_test < IMDDTestCase
% Test class for VNLE % Auto-generated placeholder for VNLE.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Equalizer/VNLE.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for VNLE testCase.assumeFail("Tests for VNLE are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef MLSE_new_test < matlab.unittest.TestCase classdef MLSE_new_test < IMDDTestCase
% Test class for MLSE_new % Auto-generated placeholder for MLSE_new.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Sequence Detection/MLSE_new.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for MLSE_new testCase.assumeFail("Tests for MLSE_new are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,84 @@
classdef MLSE_test < matlab.unittest.TestCase classdef MLSE_test < IMDDTestCase
% Test class for MLSE methods (Test, TestTags = {'unit', 'fast', 'dsp', 'mlse'})
function constructorStoresConfiguration(testCase)
mlse = MLSE( ...
"M", 4, ...
"DIR", [1 0.35], ...
"trellis_states", [-3 -1 1 3], ...
"duobinary_output", false, ...
"trellis_state_mode", 2, ...
"trellis_exclusion", 0, ...
"scale_mode", 0, ...
"debug", 0);
methods (Test) testCase.verifyEqual(mlse.M, 4);
function testExample(testCase) testCase.verifyEqual(mlse.DIR, [1 0.35]);
% Example test case for MLSE testCase.verifyEqual(mlse.trellis_states, [-3 -1 1 3]);
% Add your test code here testCase.verifyFalse(mlse.duobinary_output);
testCase.verifyTrue(true); testCase.verifyEqual(mlse.trellis_state_mode, 2);
testCase.verifyEqual(mlse.trellis_exclusion, 0);
testCase.verifyEqual(mlse.scale_mode, 0);
testCase.verifyEqual(mlse.debug, 0);
end
function processRecoversKnownPAM4Sequence(testCase)
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
txSignal = Informationsignal(txSymbols, "fs", 1);
rxSignal = Signal(rxSymbols, "fs", 1);
hdSignal = mlse.process(rxSignal, txSignal);
rxBits = PAMmapper(4, 0).demap(hdSignal);
testCase.verifyClass(hdSignal, "Signal");
testCase.verifyEqual(hdSignal.fs, rxSignal.fs);
testCase.verifyEqual(rxBits.signal, txBits, ...
"MLSE should recover the transmitted PAM-4 bits on the deterministic fixture.");
end
function processReturnsExpectedShapesAndFiniteMetric(testCase)
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
[viterbiSymbols, llr, gmi] = mlse.process_(rxSymbols, txSymbols);
rxBits = PAMmapper(4, 0).demap(viterbiSymbols(:));
expectedSymbols = txSymbols(:) ./ rms(txSymbols(:));
testCase.verifyEqual(numel(viterbiSymbols), numel(rxSymbols));
testCase.verifyEqual(size(llr), [numel(rxSymbols), 2]);
testCase.verifyTrue(isfinite(gmi));
testCase.verifyEqual(viterbiSymbols(:), expectedSymbols, "AbsTol", 1e-12);
testCase.verifyEqual(rxBits, txBits, ...
"Lower-level MLSE output should decode the same deterministic fixture.");
end end
end end
end end
function [txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture()
txBits = [ ...
0 0; ...
0 1; ...
1 1; ...
1 0; ...
0 1; ...
1 0; ...
0 0; ...
1 1];
mapper = PAMmapper(4, 0);
txSignal = Informationsignal(txBits);
txSymbols = mapper.map(txSignal).signal;
channel = [1 0.35];
rxSymbols = filter(channel, 1, txSymbols);
rxSymbols = rxSymbols + 0.01 * [0; 1; -1; 2; -2; 1; -1; 0];
mlse = MLSE( ...
"M", 4, ...
"DIR", channel, ...
"trellis_states", mapper.levels, ...
"duobinary_output", false, ...
"trellis_state_mode", 2, ...
"trellis_exclusion", 0, ...
"scale_mode", 0, ...
"debug", 0);
end

View File

@@ -1,11 +1,10 @@
classdef MLSE_viterbi_test < matlab.unittest.TestCase classdef MLSE_viterbi_test < IMDDTestCase
% Test class for MLSE_viterbi % Auto-generated placeholder for MLSE_viterbi.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Sequence Detection/MLSE_viterbi.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for MLSE_viterbi testCase.assumeFail("Tests for MLSE_viterbi are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -0,0 +1,10 @@
classdef T_04_DSP_Timing_Recovery_test < IMDDTestCase
% Auto-generated placeholder for Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing_Recovery.m
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Godard_Timing_Recovery_test < matlab.unittest.TestCase classdef Godard_Timing_Recovery_test < IMDDTestCase
% Test class for Godard_Timing_Recovery % Auto-generated placeholder for Godard_Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Godard_Timing_Recovery.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Godard_Timing_Recovery testCase.assumeFail("Tests for Godard_Timing_Recovery are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef MaxVar_Timing_Recovery_test < matlab.unittest.TestCase classdef MaxVar_Timing_Recovery_test < IMDDTestCase
% Test class for MaxVar_Timing_Recovery % Auto-generated placeholder for MaxVar_Timing_Recovery.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/MaxVar_Timing_Recovery.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for MaxVar_Timing_Recovery testCase.assumeFail("Tests for MaxVar_Timing_Recovery are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -0,0 +1,38 @@
classdef T_04_DSP_Timing_Recovery_Timing_Recovery_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'timing-recovery'})
function constructorAppliesDefaultConfiguration(testCase)
tr = Timing_Recovery();
testCase.verifyEqual(tr.modulation, 'PAM/PSK/QAM');
testCase.verifyEqual(tr.timing_error_detector, 'Gardner');
testCase.verifyEqual(tr.sps, 2);
testCase.verifyEqual(tr.damping_factor, 1.0);
testCase.verifyEqual(tr.normalized_loop_bandwidth, 0.005);
testCase.verifyEqual(tr.detector_gain, 1);
end
function constructorStoresConfiguredProperties(testCase)
tr = Timing_Recovery( ...
"modulation", 'PAM/PSK/QAM', ...
"timing_error_detector", 'Gardner', ...
"sps", 4, ...
"damping_factor", 0.75, ...
"normalized_loop_bandwidth", 0.02, ...
"detector_gain", 1.5);
testCase.verifyEqual(tr.modulation, 'PAM/PSK/QAM');
testCase.verifyEqual(tr.timing_error_detector, 'Gardner');
testCase.verifyEqual(tr.sps, 4);
testCase.verifyEqual(tr.damping_factor, 0.75);
testCase.verifyEqual(tr.normalized_loop_bandwidth, 0.02);
testCase.verifyEqual(tr.detector_gain, 1.5);
end
function processSignalsMissingCommunicationsToolboxClearly(testCase)
tr = Timing_Recovery("sps", 2);
inputSignal = Informationsignal([1; -1; 1; -1], "fs", 2);
testCase.verifyError(@() tr.process(inputSignal), 'MATLAB:undefinedVarOrClass');
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Time_Shifter_test < matlab.unittest.TestCase classdef Time_Shifter_test < IMDDTestCase
% Test class for Time_Shifter % Auto-generated placeholder for Time_Shifter.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Time_Shifter.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Time_Shifter testCase.assumeFail("Tests for Time_Shifter are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_GPT_test < matlab.unittest.TestCase classdef Timing_Recovery_GPT_test < IMDDTestCase
% Test class for Timing_Recovery_GPT % Auto-generated placeholder for Timing_Recovery_GPT.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Timing_Recovery_GPT.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Timing_Recovery_GPT testCase.assumeFail("Tests for Timing_Recovery_GPT are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_Move_It_test < matlab.unittest.TestCase classdef Timing_Recovery_Move_It_test < IMDDTestCase
% Test class for Timing_Recovery_Move_It % Auto-generated placeholder for Timing_Recovery_Move_It.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Timing Recovery/Timing_Recovery_Move_It.m
methods (Test) methods (Test, TestTags = {'placeholder', 'todo'})
function testExample(testCase) function testNotImplemented(testCase)
% Example test case for Timing_Recovery_Move_It testCase.assumeFail("Tests for Timing_Recovery_Move_It are not implemented yet.");
% Add your test code here
testCase.verifyTrue(true);
end end
end end
end end

Some files were not shown because too many files have changed in this diff Show More