1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
function SNRdB = pulse2snr(P,N,M,ISILimit,NoiseRMS)
%SNR signal to noise ratio of pulse response and RMS noise
% Calculate SNR in dB from pulse response, considering UI centers
% only. Assume bang-bang phase detection. Ignore ISI below limit.
%
% The signal-to-noise ratio is calculated as follows
% 1. The sampling instants are determined by finding the bang-bang CDR lock
% point for the input pulse response using the Hula-Hoop algorithm.
% 2. The cursor is the point equidistant to the two points identified in step
% 1; the cursor's amplitude is the signal power.
% 3. All of the other samples an integer of samples per symbol away from the cursor
% that are greater than ISILimit in power are considered ISI noise.
% 4. ISI noise power is calculated as the root mean square (norm) of all ISI
% points.
% 5. Cross talk noise is determined based on peak amplitude position in each
% cross talk vector, if provided.
% 6. Total noise is the square-root of the squared sum of ISI noise power,
% random noise power (NoiseRMS), and cross-talk power.
% 7. Signal and total noise are weighted depending on the modulation scheme,
% used. See formulas in code.
%
% Inputs:
% P - Pulse response
% N - Samples per symbol
% M - Modulation, number of levels
% ISILimit - ISI limit, fraction of cursor. ISI values below this
% threshold are considered not to contribute to total noise.
% NoiseRMS - Noise RMS, V. Additional random noise power to be considered
% towards SNR calculation.
%
% Outputs:
% SNRdB - Signal to Noise ratio (dB)
% Copyright 2020 The MathWorks, Inc.
%Validate inputs
validateattributes(P,{'numeric'},{'2d','finite'},'SNR','P',1);
validateattributes(N,{'numeric'},...
{'scalar','finite','integer','positive'},...
'SNR','N',2);
validateattributes(M,{'numeric'},...
{'scalar','finite','integer','positive'},...
'SNR','M',3);
validateattributes(ISILimit,{'numeric'},...
{'scalar','finite','positive','real'},...
'SNR','ISILimit',4);
validateattributes(NoiseRMS,{'numeric'},...
{'scalar','finite','positive','real'},...
'SNR','NoiseRMS',5);
% Initialize ISI limit
if nargin < 4
ISILimit = 0.0;
end
% Initialize noise RMS
if nargin < 5
NoiseRMS = 0.0;
end
% Get number of points and number of aggressors
num_pts = size(P, 1) ;
num_aggr = size(P, 2) - 1;
% Look for Mueller-Muller lock point
i_curs = round(pulseRecoverClock(P(:,1), 2*N));
v_curs = P(i_curs, 1);
% Pre-/post-cursor positions, including cursor
i_isi_pre = i_curs:-N:1 ;
i_isi_post = i_curs:+N:num_pts;
% ISI position & amplitude, excluding cursor
i_isi = [i_isi_pre(end:-1:2) i_isi_post(2:1:end)];
v_isi = P(i_isi, 1);
% Ignore ISI below threshold
i_isi = i_isi(abs(v_isi) >= v_curs * ISILimit);
v_isi = P(i_isi, 1);
% ISI RMS
isi_rms = norm(v_isi);
% Account for Xtalk if it's available
if num_aggr > 0
% Find peak amplitude for all Xtalk pulses
[~, i_peak] = max(abs(P(:, 2:end)), [], 1);
% Shift Xtalk PRs to put peak to 1st position
for i_aggr = 1:1:num_aggr
P(:, i_aggr+1) = circshift(P(:, i_aggr+1), -(i_peak(i_aggr)-1));
end % i_aggr
% Sample Xtalk pulses, and calculate Xtalk RMS
xt_rms = norm(P(1:N:end, 2:end));
else
% Otherwise set Xtalk RMS to zero
xt_rms = 0.0;
end
% Scale SNR components
if M == 4
v_curs = ( 1 / 6) * v_curs ;
isi_rms = ( sqrt(5) / 6) * isi_rms;
xt_rms = ( sqrt(5) / 6) * xt_rms ;
else
v_curs = ( 1 / 2) * v_curs ;
isi_rms = ( 1 / 2) * isi_rms;
xt_rms = ( 1 / 2) * xt_rms ;
end
% Combine all noise sources
n_total = norm([isi_rms xt_rms NoiseRMS]);
% SNR calculation
SNRdB = 10*log10((v_curs^2) / (n_total^2));
end
|