classdef TransmissionPerformance % TransmissionPerformance % % This class calculates the best possible net data rate (in bits/s) % from a given gross rate (bits/s) and a measured channel quality % parameter (either bit error ratio (BER) or NGMI). The class uses % lookup tables for three different FEC modes: % % 1. SD+HD concatenated (uses overall code rate and an NGMI threshold) % 2. SD+HD concatenated with punctured LDPC (uses overall code rate and an NGMI threshold) % 3. HD-only (uses a code rate and a BER threshold) % % The basic algorithm is as follows: % 1. Given a measured quality (NGMI or BER) for each measurement, find in % the table the first (i.e. “best”) entry that is satisfied by the % measured value. For NGMI the condition is measured NGMI >= threshold, % while for BER the condition is measured BER <= threshold. % 2. Use the corresponding overall code rate to compute: % % net rate = gross rate * code rate. % % USAGE EXAMPLE (array inputs): % % tp = TransmissionPerformance; % % Suppose we have 3 measurements: % % Gross rates: 10, 15, and 20 Gbps % % Measured NGMI: 0.92, 0.88, and 0.85 % % Measured BER: 1e-4, 7e-3, and 2e-2 % netrates = tp.calculatenetrate([10e9 15e9 20e9], ... % 'NGMI', [0.92 0.88 0.85], ... % 'BER', [1e-4 7e-3 2e-2]); % % The returned structure netrates will contain the net rates (and the % used code rates and thresholds) for each mode in vector form. properties (Constant) %% Lookup Table for SD+HD concatenated (using NGMI) % Overall code rate and NGMI threshold for each row. OVERALLCODERATES_SDHD = [0.7519, 0.7602, 0.7684, 0.7766, 0.7850, ... 0.7932, 0.8014, 0.8098, 0.8180, 0.8262, ... 0.8345, 0.8428, 0.8510, 0.8593, 0.8676, ... 0.8733, 0.8790, 0.8848, 0.8905, 0.8962, ... 0.9019, 0.9077, 0.9134, 0.9191, 0.9248, ... 0.9306, 0.9363, 0.9420, 0.9477, 0.9535]; NGMITHRESHOLDS_SDHD = [0.8116, 0.8167, 0.8241, 0.8317, 0.8401, ... 0.8459, 0.8512, 0.8574, 0.8685, 0.8746, ... 0.8829, 0.8892, 0.8958, 0.9022, 0.9090,... 0.9150, 0.9210, 0.9270, 0.9330, 0.9390, ... 0.9450, 0.9510, 0.9570, 0.9630, 0.9690, ... 0.9750, 0.9810, 0.9870, 0.9930, 0.9990]; ISPUNCT_LDPI = [zeros(1,15),ones(1,15)]; %% Lookup Table for HD-only mode (using BER) % For HD-only, the table gives the code rate and the maximum acceptable BER. CODE_RATES_HD = [0.7500, 0.8000, 0.8123, 0.8333, 0.8571, ... 0.8750, 0.8889, 0.9000, 0.9091, 0.9167, 0.9412]; BERTHRESHOLDS_HD = [2.12e-2, 1.76e-2, 1.62e-2, 1.44e-2, 1.25e-2, ... 1.03e-2, 9.29e-3, 8.33e-3, 7.54e-3, 7.04e-3, 4.70e-3]; %% LUT for KP4-FEC and Inner Code https://grouper.ieee.org/groups/802/3/dj/public/23_03/patra_3dj_01b_2303.pdf CODE_RATE_KP4_AND_INNER = [0.885799]; BERTHRESHOLDS_KP4_AND_INNER = 4.85e-3; end methods function netrates = calculateNetRate(obj, grossRate, varargin) % calculatenetrate Calculate the net data rate(s) from measured data. % % netrates = tp.calculatenetrate(grossRate, 'BER', berValue, 'NGMI', ngmiValue) % % INPUTS: % grossRate - (scalar or vector) gross data rate(s) [bits/s] % % Optional name/value pairs: % 'BER' - (scalar or vector) measured bit error ratio(s) % 'NGMI' - (scalar or vector) measured NGMI value(s) % % At least one of 'BER' or 'NGMI' must be provided. % % OUTPUT: % netrates - a structure with the following fields (if available): % .SDHD - for SD+HD concatenated (using NGMI) % .SDHD_LDPC - for SD+HD with punctured LDPC (using NGMI) % .HD - for HD-only (using BER) % % Each sub-structure contains fields: % .CodeRate - the chosen overall code rate from the table (vector) % .Threshold - the threshold value used from the table (vector) % . - net rate computed as grossRate * CodeRate (vector) % Parse inputs. p = inputParser; addRequired(p, 'grossRate', @(x) isnumeric(x)); addParameter(p, 'BER', [], @(x) isnumeric(x)); addParameter(p, 'NGMI', [], @(x) isnumeric(x)); parse(p, grossRate, varargin{:}); ber = p.Results.BER; ngmi = p.Results.NGMI; if isempty(ber) && isempty(ngmi) error('At least one of ''BER'' or ''NGMI'' must be provided.'); end % Determine the number of measurements. numMeasurements = max([numel(grossRate), numel(ngmi), numel(ber)]); % Broadcast scalars if needed. if isscalar(grossRate) && numMeasurements > 1 grossRate = repmat(grossRate, 1, numMeasurements); elseif numel(grossRate) ~= numMeasurements error('grossRate must be scalar or have %d elements.', numMeasurements); end if ~isempty(ngmi) if isscalar(ngmi) && numMeasurements > 1 ngmi = repmat(ngmi, 1, numMeasurements); elseif numel(ngmi) ~= numMeasurements error('NGMI must be scalar or have %d elements.', numMeasurements); end end if ~isempty(ber) if isscalar(ber) && numMeasurements > 1 ber = repmat(ber, 1, numMeasurements); elseif numel(ber) ~= numMeasurements error('BER must be scalar or have %d elements.', numMeasurements); end end % Initialize the output structure. netrates = struct; if ~isempty(ngmi) netrates.SDHD.GrossRate = NaN(1, numMeasurements); netrates.SDHD.NetRate = NaN(1, numMeasurements); netrates.SDHD.punctLDPI = NaN(1, numMeasurements); netrates.SDHD.CodeRate = NaN(1, numMeasurements); netrates.SDHD.Threshold = NaN(1, numMeasurements); end if ~isempty(ber) netrates.HD.GrossRate = NaN(1, numMeasurements); netrates.HD.NetRate = NaN(1, numMeasurements); netrates.HD.CodeRate = NaN(1, numMeasurements); netrates.HD.Threshold = NaN(1, numMeasurements); netrates.KP4_hamming.GrossRate = NaN(1, numMeasurements); netrates.KP4_hamming.NetRate = NaN(1, numMeasurements); netrates.KP4_hamming.CodeRate = NaN(1, numMeasurements); netrates.KP4_hamming.Threshold = NaN(1, numMeasurements); end % Process each measurement individually. for i = 1:numMeasurements % --- NGMI-based modes --- if ~isempty(ngmi) % SD+HD concatenated mode. idx = find(obj.NGMITHRESHOLDS_SDHD <= ngmi(i), 1, 'last'); if ~isempty(idx) codeRate = obj.OVERALLCODERATES_SDHD(idx); netrates.SDHD.NetRate(i) = grossRate(i) * codeRate; netrates.SDHD.GrossRate(i) = grossRate(i) ; netrates.SDHD.CodeRate(i) = codeRate; netrates.SDHD.Threshold(i) = obj.NGMITHRESHOLDS_SDHD(idx); netrates.SDHD.punctLDPI(i) = obj.ISPUNCT_LDPI(idx); end end % --- BER-based mode (HD-only) --- if ~isempty(ber) % Loop through the BER thresholds from the best (highest code rate) % to the worst until the measured BER is acceptable. idxBER = []; for j = length(obj.BERTHRESHOLDS_HD):-1:1 if ber(i) <= obj.BERTHRESHOLDS_HD(j) idxBER = j; break; end end if ~isempty(idxBER) codeRate = obj.CODE_RATES_HD(idxBER); netrates.HD.NetRate(i) = grossRate(i) * codeRate; netrates.HD.GrossRate(i) = grossRate(i) ; netrates.HD.CodeRate(i) = codeRate; netrates.HD.Threshold(i) = obj.BERTHRESHOLDS_HD(idxBER); end idxBER = []; for j = length(obj.BERTHRESHOLDS_KP4_AND_INNER):-1:1 if ber(i) <= obj.BERTHRESHOLDS_KP4_AND_INNER(j) idxBER = j; break; end end if ~isempty(idxBER) codeRate = obj.CODE_RATE_KP4_AND_INNER(idxBER); netrates.KP4_hamming.NetRate(i) = grossRate(i) * codeRate; netrates.KP4_hamming.GrossRate(i) = grossRate(i) ; netrates.KP4_hamming.CodeRate(i) = codeRate; netrates.KP4_hamming.Threshold(i) = obj.BERTHRESHOLDS_KP4_AND_INNER(idxBER); end end end end end end