Merge branch 'main' of cau-git.rz.uni-kiel.de:nt/mitarbeiter/silas/imdd_simulation
This commit is contained in:
344
AGENT_OVERVIEW.md
Normal file
344
AGENT_OVERVIEW.md
Normal 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/`.
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
182
TEST_TODO.md
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
function quantizeMapsToNearestConstellationLevel(testCase)
|
||||
mapper = PAMmapper(4, 0);
|
||||
signalIn = Electricalsignal([-4.0; -0.2; 0.4; 2.9], "fs", 1);
|
||||
|
||||
quantized = mapper.quantize(signalIn);
|
||||
expected = [-3; -1; 1; 3] ./ sqrt(5);
|
||||
|
||||
testCase.verifyEqual(quantized.signal, expected, "AbsTol", 1e-12);
|
||||
end
|
||||
|
||||
methods (Test, ParameterCombination = 'sequential')
|
||||
% Test with sequential combination of parameters
|
||||
function testBackToBackMapping(testCase, M, useprbs, O)
|
||||
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
|
||||
|
||||
% 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');
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
10
Tests/03_electrical/CTLE_test.m
Normal file
10
Tests/03_electrical/CTLE_test.m
Normal 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
|
||||
10
Tests/03_electrical/Electrical_Hybrid_test.m
Normal file
10
Tests/03_electrical/Electrical_Hybrid_test.m
Normal 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
|
||||
10
Tests/03_electrical/Electrical_Trace_BiDi_test.m
Normal file
10
Tests/03_electrical/Electrical_Trace_BiDi_test.m
Normal 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
|
||||
10
Tests/03_electrical/Electrical_Trace_test.m
Normal file
10
Tests/03_electrical/Electrical_Trace_test.m
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
10
Tests/04_DSP/T_04_DSP_Timing_Recovery_test.m
Normal file
10
Tests/04_DSP/T_04_DSP_Timing_Recovery_test.m
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user