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
lambda_nm = linspace(1240, 1360, 400);
@@ -181,6 +49,14 @@ for k = 1:size(scenarios, 1)
% 'HandleVisibility', 'off'); % Hide from legend
% Capture Wide Spec (k=1) bounds for the TikZ measurement lines
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
hp.FaceAlpha = 0.8;
end

View File

@@ -38,7 +38,7 @@ hold on;
lambda_levels = unique([50:-10:30, 30:-5:5]);
% 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, ...
'ShowText', 'off');
@@ -106,7 +106,7 @@ end
%% Export
% 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)
% 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²
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
f_max = 200e9;
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
% Test class for Electricalsignal
classdef Electricalsignal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals', 'electricalsignal'})
function constructorStoresSignalFsAndLogbook(testCase)
seed = Signal(1, "fs", 2);
seed = seed.logbookentry("electrical seed", seed);
methods (Test)
function testExample(testCase)
% Example test case for Electricalsignal
% Add your test code here
testCase.verifyTrue(true);
elec = Electricalsignal([1; -2; 3], "fs", 80e9, "logbook", seed.logbook);
testCase.verifyClass(elec, 'Electricalsignal');
testCase.verifyEqual(elec.signal, [1; -2; 3]);
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

View File

@@ -1,11 +1,82 @@
classdef Informationsignal_test < matlab.unittest.TestCase
% Test class for Informationsignal
classdef Informationsignal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals', 'informationsignal'})
function constructorWithoutOptionsUsesSignalDefaults(testCase)
info = Informationsignal([0; 1; 1; 0]);
methods (Test)
function testExample(testCase)
% Example test case for Informationsignal
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyClass(info, 'Informationsignal');
testCase.verifyEqual(info.signal, [0; 1; 1; 0]);
testCase.verifyEmpty(info.fs);
testCase.verifyEmpty(info.logbook);
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

View File

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

View File

@@ -1,11 +1,117 @@
classdef Signal_test < matlab.unittest.TestCase
% Test class for Signal
classdef Signal_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'signals'})
function constructorStoresSignalAndSamplingRate(testCase)
sig = Signal([1; 2; 3], "fs", 64e9);
methods (Test)
function testExample(testCase)
% Example test case for Signal
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(sig.signal, [1; 2; 3]);
testCase.verifyEqual(sig.fs, 64e9);
testCase.verifyEmpty(sig.logbook);
end
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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
classdef M8199B_test < matlab.unittest.TestCase
% Test class for M8199B
classdef M8199B_test < IMDDTestCase
% Auto-generated placeholder for M8199B.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/M8199B.m
methods (Test)
function testExample(testCase)
% Example test case for M8199B
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for M8199B are not implemented yet.");
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)
% Define method-level parameters for PRBS and bit pattern
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
function roundTripBitMappingForSupportedPamOrders(testCase)
modulationOrders = [2, 4, 8];
properties (TestParameter)
% Define test-level parameters for M and O
for M = modulationOrders
txBits = Informationsignal(allBitPatternsForOrder(M));
end
mapper = PAMmapper(M, 0);
mapped = mapper.map(txBits);
demapped = mapper.demap(mapped);
methods (TestMethodSetup)
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);
testCase.verifyEqual(double(demapped.signal), double(txBits.signal), ...
sprintf("Roundtrip mapping failed for PAM-%d.", M));
end
end
if M == 6
bitpattern = reshape(bitpattern, [], 1);
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
function roundTripPam6ClassicMapping(testCase)
txBits = Informationsignal(pam6BitStream());
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
testCase.Tx_bits = Informationsignal(bitpattern);
testCase.PAMmapper = PAMmapper(M, 0);
function roundTripPam6EthMapping(testCase)
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
function quantizeMapsToNearestConstellationLevel(testCase)
mapper = PAMmapper(4, 0);
signalIn = Electricalsignal([-4.0; -0.2; 0.4; 2.9], "fs", 1);
methods (Test, ParameterCombination = 'sequential')
% Test with sequential combination of parameters
function testBackToBackMapping(testCase, M, useprbs, O)
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
quantized = mapper.quantize(signalIn);
expected = [-3; -1; 1; 3] ./ sqrt(5);
% Map bits to symbols
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');
testCase.verifyEqual(quantized.signal, expected, "AbsTol", 1e-12);
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

View File

@@ -1,11 +1,104 @@
classdef PAMsource_test < matlab.unittest.TestCase
% Test class for PAMsource
classdef PAMsource_test < IMDDTestCase
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)
function testExample(testCase)
% Example test case for PAMsource
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(src.order, 5);
testCase.verifyFalse(src.useprbs);
testCase.verifyEqual(src.M, 4);
testCase.verifyEqual(src.fsym, 8);
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
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
% Test class for Pulseformer
classdef Pulseformer_test < IMDDTestCase
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)
function testExample(testCase)
% Example test case for Pulseformer
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(pf.fdac, 64e9);
testCase.verifyEqual(pf.fsym, 16e9);
testCase.verifyEqual(pf.pulse, pulseform.rrc);
testCase.verifyEqual(pf.pulselength, 12);
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
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
% Test class for Signalgenerator
classdef Signalgenerator_test < IMDDTestCase
% Auto-generated placeholder for Signalgenerator.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/01_transmit/Signalgenerator.m
methods (Test)
function testExample(testCase)
% Example test case for Signalgenerator
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Signalgenerator are not implemented yet.");
end
end
end

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,87 @@
classdef Fiber_test < matlab.unittest.TestCase
% Test class for Fiber
classdef Fiber_test < IMDDTestCase
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)
function testExample(testCase)
% Example test case for Fiber
% Add your test code here
testCase.verifyTrue(true);
outputSig = fiber.process_(inputSig);
testCase.verifyClass(outputSig, 'Opticalsignal');
testCase.verifyEqual(outputSig.signal, inputSig.signal, "AbsTol", 1e-12);
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
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
% Test class for Optical_Demultiplex
classdef Optical_Demultiplex_test < IMDDTestCase
% Auto-generated placeholder for Optical_Demultiplex.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Optical_Demultiplex.m
methods (Test)
function testExample(testCase)
% Example test case for Optical_Demultiplex
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Optical_Demultiplex are not implemented yet.");
end
end
end

View File

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

View File

@@ -1,11 +1,10 @@
classdef Polarization_Controller_test < matlab.unittest.TestCase
% Test class for Polarization_Controller
classdef Polarization_Controller_test < IMDDTestCase
% Auto-generated placeholder for Polarization_Controller.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/02_optical/Polarization_Controller.m
methods (Test)
function testExample(testCase)
% Example test case for Polarization_Controller
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Polarization_Controller are not implemented yet.");
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
% Test class for Photodiode
classdef Photodiode_test < IMDDTestCase
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)
function testExample(testCase)
% Example test case for Photodiode
% Add your test code here
testCase.verifyTrue(true);
yout = pd.process_(xin);
expected = 2.5 * sum(abs(xin).^2, 2) + 0.75;
testCase.verifyEqual(yout, expected, "AbsTol", 1e-12);
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

View File

@@ -1,11 +1,49 @@
classdef Scope_test < matlab.unittest.TestCase
% Test class for Scope
classdef Scope_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'receive', 'scope'})
function quantizeMapsRealSignalToExpectedGrid(testCase)
scope = makeScope(10, 10, 2, 0, true);
xin = (0:9).';
methods (Test)
function testExample(testCase)
% Example test case for Scope
% Add your test code here
testCase.verifyTrue(true);
quantized = scope.quantize(xin);
expected = [0; 0; 8/3; 8/3; 16/3; 16/3; 16/3; 8; 8; 8];
testCase.verifyEqual(quantized, expected, "AbsTol", 1e-12);
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
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
%genereal properties of the test
ber
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);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Duobinary are not implemented yet.");
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

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_ofc_test < matlab.unittest.TestCase
% Test class for EQ_silas_ofc
classdef EQ_silas_ofc_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for EQ_silas_ofc
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_ofc are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_plain_test < matlab.unittest.TestCase
% Test class for EQ_silas_plain
classdef EQ_silas_plain_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for EQ_silas_plain
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_plain are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef EQ_silas_sliding_window_dc_removal_test < matlab.unittest.TestCase
% Test class for EQ_silas_sliding_window_dc_removal
classdef EQ_silas_sliding_window_dc_removal_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for EQ_silas_sliding_window_dc_removal
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for EQ_silas_sliding_window_dc_removal are not implemented yet.");
end
end
end

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_adaptive_mu_test < matlab.unittest.TestCase
% Test class for FFE_DCremoval_adaptive_mu
classdef FFE_DCremoval_adaptive_mu_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for FFE_DCremoval_adaptive_mu
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DCremoval_adaptive_mu are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef FFE_DCremoval_level_test < matlab.unittest.TestCase
% Test class for FFE_DCremoval_level
classdef FFE_DCremoval_level_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for FFE_DCremoval_level
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_DCremoval_level are not implemented yet.");
end
end
end

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
classdef FFE_Kalman_Feedback_test < matlab.unittest.TestCase
% Test class for FFE_Kalman_Feedback
classdef FFE_Kalman_Feedback_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for FFE_Kalman_Feedback
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_Kalman_Feedback are not implemented yet.");
end
end
end

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
classdef FFE_adaptive_decision_test < matlab.unittest.TestCase
% Test class for FFE_adaptive_decision
classdef FFE_adaptive_decision_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for FFE_adaptive_decision
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for FFE_adaptive_decision are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,78 @@
classdef FFE_test < matlab.unittest.TestCase
% Test class for FFE
classdef FFE_test < IMDDTestCase
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'ffe'})
function constructorStoresDefaultsAndInitialState(testCase)
ffe = FFE();
methods (Test)
function testExample(testCase)
% Example test case for FFE
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(ffe.sps, 2);
testCase.verifyEqual(ffe.order, 15);
testCase.verifyEqual(ffe.len_tr, 4096);
testCase.verifyEqual(ffe.mu_tr, 0);
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
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
% Test class for ML_MLSE_GPU
classdef ML_MLSE_GPU_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for ML_MLSE_GPU
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for ML_MLSE_GPU are not implemented yet.");
end
end
end

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,84 @@
classdef MLSE_test < matlab.unittest.TestCase
% Test class for MLSE
classdef MLSE_test < IMDDTestCase
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)
function testExample(testCase)
% Example test case for MLSE
% Add your test code here
testCase.verifyTrue(true);
testCase.verifyEqual(mlse.M, 4);
testCase.verifyEqual(mlse.DIR, [1 0.35]);
testCase.verifyEqual(mlse.trellis_states, [-3 -1 1 3]);
testCase.verifyFalse(mlse.duobinary_output);
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
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
% Test class for MLSE_viterbi
classdef MLSE_viterbi_test < IMDDTestCase
% Auto-generated placeholder for MLSE_viterbi.
% Target: C:/Users/Silas/Documents/MATLAB/imdd_simulation/Classes/04_DSP/Sequence Detection/MLSE_viterbi.m
methods (Test)
function testExample(testCase)
% Example test case for MLSE_viterbi
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for MLSE_viterbi are not implemented yet.");
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
% Test class for Godard_Timing_Recovery
classdef Godard_Timing_Recovery_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for Godard_Timing_Recovery
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Godard_Timing_Recovery are not implemented yet.");
end
end
end

View File

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

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_GPT_test < matlab.unittest.TestCase
% Test class for Timing_Recovery_GPT
classdef Timing_Recovery_GPT_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for Timing_Recovery_GPT
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery_GPT are not implemented yet.");
end
end
end

View File

@@ -1,11 +1,10 @@
classdef Timing_Recovery_Move_It_test < matlab.unittest.TestCase
% Test class for Timing_Recovery_Move_It
classdef Timing_Recovery_Move_It_test < IMDDTestCase
% 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)
function testExample(testCase)
% Example test case for Timing_Recovery_Move_It
% Add your test code here
testCase.verifyTrue(true);
methods (Test, TestTags = {'placeholder', 'todo'})
function testNotImplemented(testCase)
testCase.assumeFail("Tests for Timing_Recovery_Move_It are not implemented yet.");
end
end
end

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