File Comparison Report
C:\Users\richardm\OneDrive - Samtec\COM\COM\src\com_ieee8023_93a_450.m vs. C:\Users\richardm\OneDrive - Samtec\COM\COM\src\com_ieee8023_93a_440.m
richardm
02-May-2024
Files
Left File | Right File | |
File name | com_ieee8023_93a_450 | com_ieee8023_93a_440 |
File path | C:\Users\richardm\OneDrive - Samtec\COM\COM\src | C:\Users\richardm\OneDrive - Samtec\COM\COM\src |
Last modified | 02-May-2024 14:31:33 | 26-Mar-2024 14:35:57 |
Environment
MATLAB | 9.14 (R2023a) |
Comparison Results
+ | Insertion | − | Deletion | ≠ | Modification |
1 | function results=com_ieee8023_93a(varargin) | 1 | function results=com_ieee8023_93a(varargin) | ||
≠ | 2 | % This is NOT an official IEEE document. | ≠ | 2 | % This is NOT an official IEEE document.op.mlse |
3 | %% Implementation example of annex 93A IEEE Std 802.3™ | 3 | %% Implementation example of annex 93A IEEE Std 802.3™ | ||
4 | % http://www.ieee802.org/3/ck/public/adhoc/index.html | 4 | % http://www.ieee802.org/3/ck/public/adhoc/index.html | ||
5 | % result=com_ieee8023_93a(config_file, num_fext, num_next [, <s4p files>]) | 5 | % result=com_ieee8023_93a(config_file, num_fext, num_next [, <s4p files>]) | ||
6 | % - config_file: xls, xls, mat file which contains configuration settings | 6 | % - config_file: xls, xls, mat file which contains configuration settings | ||
7 | % - num_fext: number of FEXT s4p files in the listfigure(300+package_testcase_i); | 7 | % - num_fext: number of FEXT s4p files in the listfigure(300+package_testcase_i); | ||
8 | % - num_next: number of NEXT s4p files in the list | 8 | % - num_next: number of NEXT s4p files in the list | ||
9 | % - <s4p_files>: (1+num_fext+num_nefxt) file names. If not supplied, program | 9 | % - <s4p_files>: (1+num_fext+num_nefxt) file names. If not supplied, program | ||
10 | % will ask for each of the files interactively.opupu | 10 | % will ask for each of the files interactively.opupu | ||
11 | % | 11 | % | ||
12 | % This program is intended for the development of standard specifications | 12 | % This program is intended for the development of standard specifications | ||
13 | % and reflects activity of IEEE P802.3bj, .3by, .3bm, .3bs, .3cd, .3ck | 13 | % and reflects activity of IEEE P802.3bj, .3by, .3bm, .3bs, .3cd, .3ck | ||
14 | % found in Annex 93A IEEE Std 802.3™ and project =updates | 14 | % found in Annex 93A IEEE Std 802.3™ and project =updates | ||
15 | % original proposal for COM may be found at | 15 | % original proposal for COM may be found at | ||
16 | % http://www.ieee802.org/3/bj/public/jul12/mellitz_01_0712.pdf in July 2012 | 16 | % http://www.ieee802.org/3/bj/public/jul12/mellitz_01_0712.pdf in July 2012 | ||
17 | % from the following authors and affiliations in 2012. | 17 | % from the following authors and affiliations in 2012. | ||
18 | % Richard Mellitz, Intel Corporation | 18 | % Richard Mellitz, Intel Corporation | ||
19 | % Charles Moore, Avago Technologies | 19 | % Charles Moore, Avago Technologies | ||
20 | % Mike Dudek, QLogic Corporation | 20 | % Mike Dudek, QLogic Corporation | ||
21 | % Mike Peng Li, Altera Corporation | 21 | % Mike Peng Li, Altera Corporation | ||
22 | % Adee Ran, Intel Corporation | 22 | % Adee Ran, Intel Corporation | ||
23 | % | 23 | % | ||
24 | % Some of the authors and Contributors: | 24 | % Some of the authors and Contributors: | ||
25 | % Adee Ran | 25 | % Adee Ran | ||
26 | % Richard Mellitz | 26 | % Richard Mellitz | ||
27 | % Yasuo Hidaka | 27 | % Yasuo Hidaka | ||
28 | % John Ewen | 28 | % John Ewen | ||
29 | % Bill Kirkland | 29 | % Bill Kirkland | ||
30 | % Adam Gregory | 30 | % Adam Gregory | ||
31 | % Howard Heck | 31 | % Howard Heck | ||
32 | % Jingbo Li | 32 | % Jingbo Li | ||
33 | % Adam Healey | 33 | % Adam Healey | ||
34 | % Matt Brown | 34 | % Matt Brown | ||
35 | % Sameh Elnagar | 35 | % Sameh Elnagar | ||
36 | % Hossein Shakiba | 36 | % Hossein Shakiba | ||
37 | zzz_list_of_changes() | 37 | zzz_list_of_changes() | ||
38 | 38 | ||||
39 | %% Opening Preface | 39 | %% Opening Preface | ||
40 | % acquire parsing command string and set up OP control structure. Then read in files | 40 | % acquire parsing command string and set up OP control structure. Then read in files | ||
41 | close(findall(0, 'tag', 'TMWWaitbar', '-or', 'tag', 'COM')); | 41 | close(findall(0, 'tag', 'TMWWaitbar', '-or', 'tag', 'COM')); | ||
42 | try % version number at end of call string | 42 | try % version number at end of call string | ||
43 | cmdfile=mfilename; | 43 | cmdfile=mfilename; | ||
44 | hindx=strfind(mfilename,'_'); | 44 | hindx=strfind(mfilename,'_'); | ||
45 | ver=cmdfile(hindx(end)+1:end); | 45 | ver=cmdfile(hindx(end)+1:end); | ||
46 | output_args.code_revision = [ver(1), '.',ver(2:end)]; | 46 | output_args.code_revision = [ver(1), '.',ver(2:end)]; | ||
47 | catch | 47 | catch | ||
48 | output_args.code_revision =''; | 48 | output_args.code_revision =''; | ||
49 | end | 49 | end | ||
50 | teststr=''; | 50 | teststr=''; | ||
51 | OP.TESTING=0; | 51 | OP.TESTING=0; | ||
52 | if OP.TESTING == 1 % set to 1 or pre release | 52 | if OP.TESTING == 1 % set to 1 or pre release | ||
53 | teststr='testing'; | 53 | teststr='testing'; | ||
54 | testmsg=sprintf('Evaluation Copy: COM%s%s\n',output_args.code_revision,teststr); | 54 | testmsg=sprintf('Evaluation Copy: COM%s%s\n',output_args.code_revision,teststr); | ||
55 | htest = msgbox(testmsg); | 55 | htest = msgbox(testmsg); | ||
56 | set(htest,'Color','y', 'tag', 'COM');movegui(htest,'northeast'); | 56 | set(htest,'Color','y', 'tag', 'COM');movegui(htest,'northeast'); | ||
57 | end | 57 | end | ||
58 | disp('This is NOT an official IEEE document.') | 58 | disp('This is NOT an official IEEE document.') | ||
59 | fprintf('Revision:<strong> %s%s </strong>This is a computation example for exploring COM and ERL \n',output_args.code_revision,teststr) | 59 | fprintf('Revision:<strong> %s%s </strong>This is a computation example for exploring COM and ERL \n',output_args.code_revision,teststr) | ||
60 | disp(' for projects like IEEE P802.3bj/b/bs/cd/ck with some exploratory extensions and is not normative or official') | 60 | disp(' for projects like IEEE P802.3bj/b/bs/cd/ck with some exploratory extensions and is not normative or official') | ||
61 | t0=tic; | 61 | t0=tic; | ||
62 | set(0,'defaulttextinterpreter','none') % prevents subscripting character in displayed messages | 62 | set(0,'defaulttextinterpreter','none') % prevents subscripting character in displayed messages | ||
63 | % reset to tex on exit | 63 | % reset to tex on exit | ||
64 | %% file_setup | 64 | %% file_setup | ||
65 | %% | 65 | %% | ||
66 | % need to see what happens for version 8 | 66 | % need to see what happens for version 8 | ||
67 | if verLessThan('matlab', '7.4.1') | 67 | if verLessThan('matlab', '7.4.1') | ||
68 | error('Matlab version 7.4 or higher required') | 68 | error('Matlab version 7.4 or higher required') | ||
69 | end | 69 | end | ||
70 | 70 | ||||
71 | results=[]; | 71 | results=[]; | ||
72 | 72 | ||||
73 | %% New Command Line parser | 73 | %% New Command Line parser | ||
74 | [config_file,num_fext,num_next,Remember_keyword,OP,varargin]=COM_CommandLine_Parse(OP,varargin{:}); | 74 | [config_file,num_fext,num_next,Remember_keyword,OP,varargin]=COM_CommandLine_Parse(OP,varargin{:}); | ||
75 | 75 | ||||
76 | 76 | ||||
77 | %% get the first 3 arguments and allow for interactive input. | 77 | %% get the first 3 arguments and allow for interactive input. | ||
78 | if isempty(config_file) | 78 | if isempty(config_file) | ||
79 | config_file=input('Enter config XLS file or return will just pop a window to ask for the XLS file]: ','s'); | 79 | config_file=input('Enter config XLS file or return will just pop a window to ask for the XLS file]: ','s'); | ||
80 | if isempty(config_file) | 80 | if isempty(config_file) | ||
81 | [config_file, config_file_path] = uigetfile([{ '*.xls;*.xlsx'} ; {'*.mat'}],'INPUT CONFIG FILE .xls'); | 81 | [config_file, config_file_path] = uigetfile([{ '*.xls;*.xlsx'} ; {'*.mat'}],'INPUT CONFIG FILE .xls'); | ||
82 | else | 82 | else | ||
83 | [config_file_path,cname,cext]=fileparts(config_file); | 83 | [config_file_path,cname,cext]=fileparts(config_file); | ||
84 | config_file=[cname cext]; | 84 | config_file=[cname cext]; | ||
85 | end | 85 | end | ||
86 | if config_file==0 | 86 | if config_file==0 | ||
87 | % cancel - exit gracefully | 87 | % cancel - exit gracefully | ||
88 | return; | 88 | return; | ||
89 | end | 89 | end | ||
90 | config_file = fullfile(config_file_path, config_file); | 90 | config_file = fullfile(config_file_path, config_file); | ||
91 | end | 91 | end | ||
92 | output_args.config_file = config_file; | 92 | output_args.config_file = config_file; | ||
93 | OP.SAVE_KEYWORD_FILE=0; | 93 | OP.SAVE_KEYWORD_FILE=0; | ||
94 | if OP.SAVE_KEYWORD_FILE | 94 | if OP.SAVE_KEYWORD_FILE | ||
95 | if exist('keyworklog.mat','file')==2 | 95 | if exist('keyworklog.mat','file')==2 | ||
96 | delete('keyworklog.mat'); | 96 | delete('keyworklog.mat'); | ||
97 | end | 97 | end | ||
98 | end | 98 | end | ||
99 | [param, OP] = read_ParamConfigFile(config_file,OP); | 99 | [param, OP] = read_ParamConfigFile(config_file,OP); | ||
100 | if OP.CONFIG2MAT_ONLY | 100 | if OP.CONFIG2MAT_ONLY | ||
101 | return; | 101 | return; | ||
102 | end | 102 | end | ||
103 | if isempty(num_fext) | 103 | if isempty(num_fext) | ||
104 | if OP.RX_CALIBRATION | 104 | if OP.RX_CALIBRATION | ||
105 | num_fext=1; | 105 | num_fext=1; | ||
106 | disp('First prompt is for the measured test thru channel and following prompt is for Rx noise path channel') | 106 | disp('First prompt is for the measured test thru channel and following prompt is for Rx noise path channel') | ||
107 | else | 107 | else | ||
108 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 % OP.ERL=2 is for package ERL, param.tfx = 1 means fixture time not set and need to be determinind for test fixture channel | 108 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 % OP.ERL=2 is for package ERL, param.tfx = 1 means fixture time not set and need to be determinind for test fixture channel | ||
109 | num_fext=1; | 109 | num_fext=1; | ||
110 | disp('First prompt is for the s2p measured data following prompt is for s4p of of the test fixtrure channel') | 110 | disp('First prompt is for the s2p measured data following prompt is for s4p of of the test fixtrure channel') | ||
111 | elseif ~OP.ERL_ONLY | 111 | elseif ~OP.ERL_ONLY | ||
112 | num_fext=input('How many FEXT channels are to be entered? [return means no FEXT] '); | 112 | num_fext=input('How many FEXT channels are to be entered? [return means no FEXT] '); | ||
113 | else | 113 | else | ||
114 | num_fext=0; | 114 | num_fext=0; | ||
115 | end | 115 | end | ||
116 | end | 116 | end | ||
117 | if isempty(num_fext)==1, num_fext=0; end | 117 | if isempty(num_fext)==1, num_fext=0; end | ||
118 | end | 118 | end | ||
119 | if isempty(num_next) | 119 | if isempty(num_next) | ||
120 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 % OP.ERL=2 is for package ERL, param.tfx = 1 means fixture time not set and need to be determinind for test fixture channel | 120 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 % OP.ERL=2 is for package ERL, param.tfx = 1 means fixture time not set and need to be determinind for test fixture channel | ||
121 | num_next=0; | 121 | num_next=0; | ||
122 | else | 122 | else | ||
123 | if OP.RX_CALIBRATION | 123 | if OP.RX_CALIBRATION | ||
124 | num_next=0; | 124 | num_next=0; | ||
125 | elseif ~OP.ERL_ONLY | 125 | elseif ~OP.ERL_ONLY | ||
126 | num_next=input('How many NEXT channels are to be entered? [return means no NEXT] '); | 126 | num_next=input('How many NEXT channels are to be entered? [return means no NEXT] '); | ||
127 | else | 127 | else | ||
128 | num_next=0; | 128 | num_next=0; | ||
129 | end | 129 | end | ||
130 | end | 130 | end | ||
131 | if isempty(num_next)==1, num_next=0; end | 131 | if isempty(num_next)==1, num_next=0; end | ||
132 | end | 132 | end | ||
133 | % Allow string inputs for running compiled version from OS command-line | 133 | % Allow string inputs for running compiled version from OS command-line | ||
134 | if ischar(num_fext), num_fext=str2double(num_fext); end | 134 | if ischar(num_fext), num_fext=str2double(num_fext); end | ||
135 | if ischar(num_next), num_next=str2double(num_next); end | 135 | if ischar(num_next), num_next=str2double(num_next); end | ||
136 | xtk=num_fext+num_next; % total number of crosstalk aggressors | 136 | xtk=num_fext+num_next; % total number of crosstalk aggressors | ||
137 | param.num_next=num_next; | 137 | param.num_next=num_next; | ||
138 | param.num_fext=num_fext; | 138 | param.num_fext=num_fext; | ||
139 | param.num_s4p_files=num_fext+num_next+1; | 139 | param.num_s4p_files=num_fext+num_next+1; | ||
140 | % checking for data when running for rx compliance BBN calibration | 140 | % checking for data when running for rx compliance BBN calibration | ||
141 | if OP.RX_CALIBRATION == 1 | 141 | if OP.RX_CALIBRATION == 1 | ||
142 | if num_fext ~=1 | 142 | if num_fext ~=1 | ||
143 | h = msgbox('One and only noise path channel is required'); set(h,'Color',[1 .85 0]); | 143 | h = msgbox('One and only noise path channel is required'); set(h,'Color',[1 .85 0]); | ||
144 | movegui(h,'northwest') | 144 | movegui(h,'northwest') | ||
145 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 145 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
146 | if OP.DEBUG ~= 1 | 146 | if OP.DEBUG ~= 1 | ||
147 | return | 147 | return | ||
148 | end | 148 | end | ||
149 | end | 149 | end | ||
150 | h = msgbox('Please make sure the measured "sigma_RJ", A_DD, and SNR_TX" fields in the config xls file have been modified from the Tx measurement. '); set(h,'Color',[0 1 1]); | 150 | h = msgbox('Please make sure the measured "sigma_RJ", A_DD, and SNR_TX" fields in the config xls file have been modified from the Tx measurement. '); set(h,'Color',[0 1 1]); | ||
151 | movegui(h,'southeast') | 151 | movegui(h,'southeast') | ||
152 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 152 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
153 | end | 153 | end | ||
154 | 154 | ||||
155 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 | 155 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2 | ||
156 | if num_fext ~=1 | 156 | if num_fext ~=1 | ||
157 | h = msgbox('One and only test channel is required'); set(h,'Color',[1 .85 0]); | 157 | h = msgbox('One and only test channel is required'); set(h,'Color',[1 .85 0]); | ||
158 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 158 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
159 | movegui(h,'northwest') | 159 | movegui(h,'northwest') | ||
160 | if OP.DEBUG ~= 1 | 160 | if OP.DEBUG ~= 1 | ||
161 | return | 161 | return | ||
162 | end | 162 | end | ||
163 | end | 163 | end | ||
164 | h = msgbox('The test fixture file is use to gate measurements '); set(h,'Color',[0 1 1]); | 164 | h = msgbox('The test fixture file is use to gate measurements '); set(h,'Color',[0 1 1]); | ||
165 | movegui(h,'southeast') | 165 | movegui(h,'southeast') | ||
166 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 166 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
167 | end | 167 | end | ||
168 | 168 | ||||
169 | 169 | ||||
170 | % create result directory if needed | 170 | % create result directory if needed | ||
171 | if ~exist(OP.RESULT_DIR,'dir'); mkdir(OP.RESULT_DIR); end | 171 | if ~exist(OP.RESULT_DIR,'dir'); mkdir(OP.RESULT_DIR); end | ||
172 | % allow finite impulse response input rather that s-parameters with | 172 | % allow finite impulse response input rather that s-parameters with | ||
173 | % OP.EXTERNAL = true. However the use_external_IR function is not provided | 173 | % OP.EXTERNAL = true. However the use_external_IR function is not provided | ||
174 | if ~isempty(varargin) % process case where file names are passed in function call | 174 | if ~isempty(varargin) % process case where file names are passed in function call | ||
175 | if strfind(upper(char(varargin(1))),'EXTERNAL_IR') ~= 0 | 175 | if strfind(upper(char(varargin(1))),'EXTERNAL_IR') ~= 0 | ||
176 | error('External IR mode is no longer supported'); | 176 | error('External IR mode is no longer supported'); | ||
177 | %OP.EXTERNAL = true; | 177 | %OP.EXTERNAL = true; | ||
178 | %OP.GET_FD = 0; | 178 | %OP.GET_FD = 0; | ||
179 | %ir1a= varargin(2); | 179 | %ir1a= varargin(2); | ||
180 | %ex_var = varargin(3); | 180 | %ex_var = varargin(3); | ||
181 | %[chdata OP param ] = use_external_IR(param, OP ,num_fext,num_next,0,ir1a,ex_var); | 181 | %[chdata OP param ] = use_external_IR(param, OP ,num_fext,num_next,0,ir1a,ex_var); | ||
182 | else | 182 | else | ||
183 | if OP.TDMODE | 183 | if OP.TDMODE | ||
184 | OP.GET_FD=false; | 184 | OP.GET_FD=false; | ||
185 | end | 185 | end | ||
186 | if length(varargin) < xtk +1 % check that number of varargin arguments passed is at least number of crosstalk files+1 (thru) | 186 | if length(varargin) < xtk +1 % check that number of varargin arguments passed is at least number of crosstalk files+1 (thru) | ||
187 | error('files must include next + fext + a thru'); | 187 | error('files must include next + fext + a thru'); | ||
188 | end | 188 | end | ||
189 | %% eveluate any extra arguments as possible modifications of parameters | 189 | %% eveluate any extra arguments as possible modifications of parameters | ||
190 | extra_args = varargin(xtk+2:end); | 190 | extra_args = varargin(xtk+2:end); | ||
191 | for k=1:2:floor(length(extra_args)/2)*2 | 191 | for k=1:2:floor(length(extra_args)/2)*2 | ||
192 | try | 192 | try | ||
193 | orig_value_is_str = 1; | 193 | orig_value_is_str = 1; | ||
194 | orig_value=eval(extra_args{k}); | 194 | orig_value=eval(extra_args{k}); | ||
195 | if ~ischar(orig_value) | 195 | if ~ischar(orig_value) | ||
196 | orig_value_is_str = 0; | 196 | orig_value_is_str = 0; | ||
197 | orig_value=mat2str(orig_value); | 197 | orig_value=mat2str(orig_value); | ||
198 | end | 198 | end | ||
199 | catch eval_err | 199 | catch eval_err | ||
200 | if isequal(eval_err.identifier, 'MATLAB:nonExistentField') | 200 | if isequal(eval_err.identifier, 'MATLAB:nonExistentField') | ||
201 | % trying to modify a nonexistent parameter - probably a | 201 | % trying to modify a nonexistent parameter - probably a | ||
202 | % typo. save the user from his error. | 202 | % typo. save the user from his error. | ||
203 | error('COM:BadExtraParameter', 'Attempted override of a non-existing parameter %s.', extra_args{k}); | 203 | error('COM:BadExtraParameter', 'Attempted override of a non-existing parameter %s.', extra_args{k}); | ||
204 | else | 204 | else | ||
205 | % unexpected condition | 205 | % unexpected condition | ||
206 | rethrow(eval_err); | 206 | rethrow(eval_err); | ||
207 | end | 207 | end | ||
208 | end | 208 | end | ||
209 | try | 209 | try | ||
210 | if orig_value_is_str | 210 | if orig_value_is_str | ||
211 | mod_string = sprintf('%s = ''%s'';', extra_args{k}, extra_args{k+1}); | 211 | mod_string = sprintf('%s = ''%s'';', extra_args{k}, extra_args{k+1}); | ||
212 | else | 212 | else | ||
213 | mod_string = sprintf('%s = %s;', extra_args{k}, extra_args{k+1}); | 213 | mod_string = sprintf('%s = %s;', extra_args{k}, extra_args{k+1}); | ||
214 | end | 214 | end | ||
215 | eval(mod_string); | 215 | eval(mod_string); | ||
216 | fname=['mod_str' num2str(k)]; | 216 | fname=['mod_str' num2str(k)]; | ||
217 | % begin yasuo patch 2/11/2018 | 217 | % begin yasuo patch 2/11/2018 | ||
218 | % output_args.(fname)=mod_string; | 218 | % output_args.(fname)=mod_string; | ||
219 | % If mod_string contains a comma, enclose it by double quotes to avoid misaligned column in the CSV output. | 219 | % If mod_string contains a comma, enclose it by double quotes to avoid misaligned column in the CSV output. | ||
220 |
| 220 |
| ||
221 | % re-patch yasuo 3/18/2019 | 221 | % re-patch yasuo 3/18/2019 | ||
222 | % v2.56 if contains(mod_string,',') | 222 | % v2.56 if contains(mod_string,',') | ||
223 | % v2.57 if isempty(strfind(mod_string,',')) | 223 | % v2.57 if isempty(strfind(mod_string,',')) | ||
224 | % Here, if-condition was inverted by the change of function from 'contains()' to 'isempty()'. | 224 | % Here, if-condition was inverted by the change of function from 'contains()' to 'isempty()'. | ||
225 | % So, it is changed back by adding an '~' operator. | 225 | % So, it is changed back by adding an '~' operator. | ||
226 | % if isempty(strfind(mod_string,',')) | 226 | % if isempty(strfind(mod_string,',')) | ||
227 | if ~isempty(strfind(mod_string,',')) | 227 | if ~isempty(strfind(mod_string,',')) | ||
228 | output_args.(fname)=['"' mod_string '"']; | 228 | output_args.(fname)=['"' mod_string '"']; | ||
229 | else | 229 | else | ||
230 | output_args.(fname)=mod_string; | 230 | output_args.(fname)=mod_string; | ||
231 | end | 231 | end | ||
232 | fprintf('Applied parameter modification: %s (override %s)\n', mod_string, orig_value); | 232 | fprintf('Applied parameter modification: %s (override %s)\n', mod_string, orig_value); | ||
233 | catch eval_err | 233 | catch eval_err | ||
234 | error(eval_err.identifier, 'Error evaluating "%s".', mod_string); | 234 | error(eval_err.identifier, 'Error evaluating "%s".', mod_string); | ||
235 | end | 235 | end | ||
236 | end | 236 | end | ||
237 | end | 237 | end | ||
238 | end | 238 | end | ||
239 | %% Parameters computationally defined by values from the settings files | 239 | %% Parameters computationally defined by values from the settings files | ||
240 | param.ui=1/param.fb; | 240 | param.ui=1/param.fb; | ||
241 | param.sample_dt = param.ui/param.samples_per_ui; | 241 | param.sample_dt = param.ui/param.samples_per_ui; | ||
242 | param.sigma_X=sqrt( (param.levels^2-1)/ (3*(param.levels-1)^2) ); | 242 | param.sigma_X=sqrt( (param.levels^2-1)/ (3*(param.levels-1)^2) ); | ||
243 | factor_3db=0.473037; | 243 | factor_3db=0.473037; | ||
244 | param.fb_BT_cutoff=factor_3db*param.f_r; | 244 | param.fb_BT_cutoff=factor_3db*param.f_r; | ||
245 | param.fb_BW_cutoff=param.f_r; | 245 | param.fb_BW_cutoff=param.f_r; | ||
246 | param.Tx_rd_sel=1; | 246 | param.Tx_rd_sel=1; | ||
247 | param.Rx_rd_sel=2; | 247 | param.Rx_rd_sel=2; | ||
248 | if isempty(param.snpPortsOrder) || any(isnan(param.snpPortsOrder)) | 248 | if isempty(param.snpPortsOrder) || any(isnan(param.snpPortsOrder)) | ||
249 | param.snpPortsOrder = [1 3 2 4]; % default order normally used. | 249 | param.snpPortsOrder = [1 3 2 4]; % default order normally used. | ||
250 | end | 250 | end | ||
251 | %% size adjust vector parameters which may be entered as one element | 251 | %% size adjust vector parameters which may be entered as one element | ||
252 | param=parameter_size_adjustment(param,OP); | 252 | param=parameter_size_adjustment(param,OP); | ||
253 | 253 | ||||
254 | %% get input models | 254 | %% get input models | ||
255 | param.FLAG.S2P=0; | 255 | param.FLAG.S2P=0; | ||
256 | if OP.TDMODE | 256 | if OP.TDMODE | ||
257 | OP.FIXTURE_CALIBRATION= 0; | 257 | OP.FIXTURE_CALIBRATION= 0; | ||
258 | [chdata, param] = get_TD_files(param, OP, num_fext, num_next, varargin); | 258 | [chdata, param] = get_TD_files(param, OP, num_fext, num_next, varargin); | ||
259 | else | 259 | else | ||
260 | OP.FIXTURE_CALIBRATION= 0; | 260 | OP.FIXTURE_CALIBRATION= 0; | ||
261 | [chdata, param] = get_s4p_files(param, OP, num_fext, num_next, varargin); | 261 | [chdata, param] = get_s4p_files(param, OP, num_fext, num_next, varargin); | ||
262 | if any(strcmpi({chdata.ext},'.s2p')) | 262 | if any(strcmpi({chdata.ext},'.s2p')) | ||
263 | param.FLAG.S2P=1; | 263 | param.FLAG.S2P=1; | ||
264 | end | 264 | end | ||
265 | end | 265 | end | ||
266 | 266 | ||||
267 | OP.SAVE_CMD_STR=1; | 267 | OP.SAVE_CMD_STR=1; | ||
268 | if OP.SAVE_CMD_STR | 268 | if OP.SAVE_CMD_STR | ||
269 | cmd_str = save_cmd_line([Remember_keyword ''',''' config_file], chdata, num_fext,num_next,mfilename ); | 269 | cmd_str = save_cmd_line([Remember_keyword ''',''' config_file], chdata, num_fext,num_next,mfilename ); | ||
270 | setappdata(0,'cmd_str',cmd_str); | 270 | setappdata(0,'cmd_str',cmd_str); | ||
271 | end | 271 | end | ||
272 | %% from here on, multiple package test cases are run. results will be saved separately. | 272 | %% from here on, multiple package test cases are run. results will be saved separately. | ||
273 | results = cell(size(OP.pkg_len_select)); | 273 | results = cell(size(OP.pkg_len_select)); | ||
274 | COM = inf; | 274 | COM = inf; | ||
275 | min_COM=inf; % reset COM prior to calibration | 275 | min_COM=inf; % reset COM prior to calibration | ||
276 | % min_VEO = inf; | 276 | % min_VEO = inf; | ||
277 | min_VEO_mV = inf; | 277 | min_VEO_mV = inf; | ||
278 | max_VEC_dB = -inf; | 278 | max_VEC_dB = -inf; | ||
279 | threshold_DER=inf; | 279 | threshold_DER=inf; | ||
280 | % begin yasuo patch 3/18/2019 | 280 | % begin yasuo patch 3/18/2019 | ||
281 | threshold_DER_max = 0; % reset worst DER | 281 | threshold_DER_max = 0; % reset worst DER | ||
282 | % end yasuo patch | 282 | % end yasuo patch | ||
283 | sigma_bn=0; | 283 | sigma_bn=0; | ||
284 | DO_ONCE=true; | 284 | DO_ONCE=true; | ||
285 | low_COM_found = 0; | 285 | low_COM_found = 0; | ||
286 | % at this point only the impulse responses are needed. However vestiges of FD may be intermingled | 286 | % at this point only the impulse responses are needed. However vestiges of FD may be intermingled | ||
287 | while (OP.RX_CALIBRATION==1 || DO_ONCE==true) | 287 | while (OP.RX_CALIBRATION==1 || DO_ONCE==true) | ||
288 | if ~DO_ONCE | 288 | if ~DO_ONCE | ||
289 | if abs(min_COM - param.pass_threshold)<0.1 || (sigma_bn==0 && min_COM < param.pass_threshold) | 289 | if abs(min_COM - param.pass_threshold)<0.1 || (sigma_bn==0 && min_COM < param.pass_threshold) | ||
290 | break; | 290 | break; | ||
291 | elseif min_COM > param.pass_threshold | 291 | elseif min_COM > param.pass_threshold | ||
292 | % increase noise level linearly until low COM found; then perform binary search. | 292 | % increase noise level linearly until low COM found; then perform binary search. | ||
293 | if low_COM_found | 293 | if low_COM_found | ||
294 | if OP.sigma_bn_STEP>0 % previous increase too small | 294 | if OP.sigma_bn_STEP>0 % previous increase too small | ||
295 | OP.sigma_bn_STEP = OP.sigma_bn_STEP/2; % gearshift | 295 | OP.sigma_bn_STEP = OP.sigma_bn_STEP/2; % gearshift | ||
296 | else % previously decrease too large | 296 | else % previously decrease too large | ||
297 | OP.sigma_bn_STEP = -OP.sigma_bn_STEP/2; % gearshift and change direction | 297 | OP.sigma_bn_STEP = -OP.sigma_bn_STEP/2; % gearshift and change direction | ||
298 | end | 298 | end | ||
299 | end | 299 | end | ||
300 | else % binary searchparam.Pkg_len_TX | 300 | else % binary searchparam.Pkg_len_TX | ||
301 | low_COM_found=1; | 301 | low_COM_found=1; | ||
302 | if OP.sigma_bn_STEP>0 % previous increase too large | 302 | if OP.sigma_bn_STEP>0 % previous increase too large | ||
303 | OP.sigma_bn_STEP = -OP.sigma_bn_STEP/2; % gearshift and change direction | 303 | OP.sigma_bn_STEP = -OP.sigma_bn_STEP/2; % gearshift and change direction | ||
304 | else % previously decrease too small | 304 | else % previously decrease too small | ||
305 | OP.sigma_bn_STEP = OP.sigma_bn_STEP/2; % gearshift | 305 | OP.sigma_bn_STEP = OP.sigma_bn_STEP/2; % gearshift | ||
306 | end | 306 | end | ||
307 | end | 307 | end | ||
308 | min_COM = inf; % ignore previous iterations | 308 | min_COM = inf; % ignore previous iterations | ||
309 | min_VEO_mV = inf; | 309 | min_VEO_mV = inf; | ||
310 | max_VEC_dB = -inf; | 310 | max_VEC_dB = -inf; | ||
311 | sigma_bn = sigma_bn + OP.sigma_bn_STEP; | 311 | sigma_bn = sigma_bn + OP.sigma_bn_STEP; | ||
312 | end | 312 | end | ||
313 | msgctr=1; | 313 | msgctr=1; | ||
314 | for package_testcase_i = 1:length(OP.pkg_len_select) | 314 | for package_testcase_i = 1:length(OP.pkg_len_select) | ||
315 | CSV_FILE=sprintf('%s%s_case%d_results.csv', OP.RESULT_DIR, chdata(1).base, package_testcase_i); | 315 | CSV_FILE=sprintf('%s%s_case%d_results.csv', OP.RESULT_DIR, chdata(1).base, package_testcase_i); | ||
316 | package_testcase=OP.pkg_len_select(package_testcase_i); | 316 | package_testcase=OP.pkg_len_select(package_testcase_i); | ||
317 | param.Pkg_len_TX = param.z_p_tx_cases(package_testcase,:); | 317 | param.Pkg_len_TX = param.z_p_tx_cases(package_testcase,:); | ||
318 | param.Pkg_len_NEXT = param.z_p_next_cases(package_testcase,:); | 318 | param.Pkg_len_NEXT = param.z_p_next_cases(package_testcase,:); | ||
319 | param.Pkg_len_FEXT = param.z_p_fext_cases(package_testcase,:); | 319 | param.Pkg_len_FEXT = param.z_p_fext_cases(package_testcase,:); | ||
320 | param.Pkg_len_RX = param.z_p_rx_cases(package_testcase,:); | 320 | param.Pkg_len_RX = param.z_p_rx_cases(package_testcase,:); | ||
321 | param.AC_CM_RMS_TX= param.AC_CM_RMS(package_testcase); | 321 | param.AC_CM_RMS_TX= param.AC_CM_RMS(package_testcase); | ||
322 | if param.PKG_Tx_FFE_preset ~=0 | 322 | if param.PKG_Tx_FFE_preset ~=0 | ||
323 | param.Pkg_TXFFE_preset= param.PKG_Tx_FFE_preset(package_testcase,:); | 323 | param.Pkg_TXFFE_preset= param.PKG_Tx_FFE_preset(package_testcase,:); | ||
324 | else | 324 | else | ||
325 | param.Pkg_TXFFE_preset=0; | 325 | param.Pkg_TXFFE_preset=0; | ||
326 | end | 326 | end | ||
327 | % ki=package_testcase; | 327 | % ki=package_testcase; | ||
328 | % % param.Pkg_Zc=[ param.pkg_Z_c(ki,1); param.pkg_Z_c(ki,2) ]; | 328 | % % param.Pkg_Zc=[ param.pkg_Z_c(ki,1); param.pkg_Z_c(ki,2) ]; | ||
329 | % param.Pkg_Zc=[ param.pkg_Z_c(ki,:) ];SDDp2p | 329 | % param.Pkg_Zc=[ param.pkg_Z_c(ki,:) ];SDDp2p | ||
330 | param.Pkg_Zc= param.pkg_Z_c; | 330 | param.Pkg_Zc= param.pkg_Z_c; | ||
331 | [cmele,centries] = size(param.Pkg_Zc); | 331 | [cmele,centries] = size(param.Pkg_Zc); | ||
332 | [mele, ncases] = size(param.Pkg_len_TX); | 332 | [mele, ncases] = size(param.Pkg_len_TX); | ||
333 | if cmele ~=1 && centries ~=2 && mele ~= 1 | 333 | if cmele ~=1 && centries ~=2 && mele ~= 1 | ||
334 | param.Pkg_Zc=reshape(param.Pkg_Zc,2,4); | 334 | param.Pkg_Zc=reshape(param.Pkg_Zc,2,4); | ||
335 | end | 335 | end | ||
336 | param.package_testcase_i = package_testcase_i; | 336 | param.package_testcase_i = package_testcase_i; | ||
337 |
| 337 |
| ||
338 | %% Fill in chdata | 338 | %% Fill in chdata | ||
339 | if OP.TDMODE | 339 | if OP.TDMODE | ||
340 | [chdata, param ] = read_PR_files(param, OP, chdata); | 340 | [chdata, param ] = read_PR_files(param, OP, chdata); | ||
341 | [chdata, param, SDDch, SDDp2p ] = TD_FD_fillin(param, OP, chdata); % fill in fd data to keep rest of SW happy | 341 | [chdata, param, SDDch, SDDp2p ] = TD_FD_fillin(param, OP, chdata); % fill in fd data to keep rest of SW happy | ||
342 | else | 342 | else | ||
343 | %fill in chada with s-parameters | 343 | %fill in chada with s-parameters | ||
344 | [chdata, SDDch, SDDp2p ] = read_s4p_files(param, OP, chdata); | 344 | [chdata, SDDch, SDDp2p ] = read_s4p_files(param, OP, chdata); | ||
345 | [chdata, param] = process_sxp(param, OP, chdata, SDDch); | 345 | [chdata, param] = process_sxp(param, OP, chdata, SDDch); | ||
346 | end | 346 | end | ||
347 | if OP.BREAD_CRUMBS | 347 | if OP.BREAD_CRUMBS | ||
348 | output_args.RL.f=chdata(1).faxis; % RIM 07/19/2019 only use the first index | 348 | output_args.RL.f=chdata(1).faxis; % RIM 07/19/2019 only use the first index | ||
349 | output_args.RL.rl1=chdata(1).sdd11_raw; % RIM 07/19/2019 only use the first index | 349 | output_args.RL.rl1=chdata(1).sdd11_raw; % RIM 07/19/2019 only use the first index | ||
350 | if isfield(chdata(1),'sdd22_raw')% RIM 10/15/2019 only use the first index | 350 | if isfield(chdata(1),'sdd22_raw')% RIM 10/15/2019 only use the first index | ||
351 | output_args.RL.r22=chdata(1).sdd22_raw; % RIM 07/19/2019 only use the first index | 351 | output_args.RL.r22=chdata(1).sdd22_raw; % RIM 07/19/2019 only use the first index | ||
352 | end | 352 | end | ||
353 | if isfield(chdata(1),'TX_RL')% RIM 10/09/2020 report Tx RL with RD | 353 | if isfield(chdata(1),'TX_RL')% RIM 10/09/2020 report Tx RL with RD | ||
354 | output_args.RL.TXRL=chdata(1).TX_RL; %R IM 10/09/2020 report Tx RL with RD | 354 | output_args.RL.TXRL=chdata(1).TX_RL; %R IM 10/09/2020 report Tx RL with RD | ||
355 | end | 355 | end | ||
356 | end | 356 | end | ||
357 | if param.FLAG.S2P, OP.ERL_ONLY =1;end | 357 | if param.FLAG.S2P, OP.ERL_ONLY =1;end | ||
358 |
| 358 |
| ||
359 | %% Process TDR & ERL | 359 | %% Process TDR & ERL | ||
360 | [output_args,ERL,min_ERL]=TDR_ERL_Processing(output_args,OP,package_testcase_i,chdata,param); | 360 | [output_args,ERL,min_ERL]=TDR_ERL_Processing(output_args,OP,package_testcase_i,chdata,param); | ||
361 | if OP.ERL_ONLY | 361 | if OP.ERL_ONLY | ||
362 | results = cell(1); | 362 | results = cell(1); | ||
363 | results{1} = output_args; | 363 | results{1} = output_args; | ||
364 | rt=toc(t0); | 364 | rt=toc(t0); | ||
365 | output_args.rtmin=rt/60; | 365 | output_args.rtmin=rt/60; | ||
366 | if 1 | 366 | if 1 | ||
367 | fprintf('run time = %g min\n',output_args.rtmin) | 367 | fprintf('run time = %g min\n',output_args.rtmin) | ||
368 | end | 368 | end | ||
369 | if OP.CSV_REPORT ==1 | 369 | if OP.CSV_REPORT ==1 | ||
370 | Write_CSV(output_args,CSV_FILE); | 370 | Write_CSV(output_args,CSV_FILE); | ||
371 | end | 371 | end | ||
372 | break; | 372 | break; | ||
373 | end | 373 | end | ||
374 |
| 374 |
| ||
375 | %% FD processing s-parameter | 375 | %% FD processing s-parameter | ||
376 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 376 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
377 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 377 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
378 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 378 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
379 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 379 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
380 | % at this point sdd21 responses and faxis (frequency) array are defined | 380 | % at this point sdd21 responses and faxis (frequency) array are defined | ||
381 | %most operations now wrapped into FD_Processing function | 381 | %most operations now wrapped into FD_Processing function | ||
382 | param.number_of_s4p_files=length(chdata); | 382 | param.number_of_s4p_files=length(chdata); | ||
383 | %ICN=0; | 383 | %ICN=0; | ||
384 | output_args.ICN_mV=0; | 384 | output_args.ICN_mV=0; | ||
385 | output_args.MDNEXT_ICN_92_46_mV=0; | 385 | output_args.MDNEXT_ICN_92_46_mV=0; | ||
386 | output_args.MDFEXT_ICN_92_47_mV=0; | 386 | output_args.MDFEXT_ICN_92_47_mV=0; | ||
387 | if OP.WC_PORTZ | 387 | if OP.WC_PORTZ | ||
388 | param.SNR_TX=param.SNDR(param.Tx_rd_sel); | 388 | param.SNR_TX=param.SNDR(param.Tx_rd_sel); | ||
389 | else | 389 | else | ||
390 | param.SNR_TX=param.SNDR(package_testcase); | 390 | param.SNR_TX=param.SNDR(package_testcase); | ||
391 | end | 391 | end | ||
392 |
| 392 |
| ||
393 | %TD Mode now also calls FD_Processing but skips the main parts | 393 | %TD Mode now also calls FD_Processing but skips the main parts | ||
394 | [chdata,output_args]=FD_Processing(chdata,output_args,param,OP,SDDp2p,DO_ONCE); | 394 | [chdata,output_args]=FD_Processing(chdata,output_args,param,OP,SDDp2p,DO_ONCE); | ||
395 |
| 395 |
| ||
396 | %% Convert from Frequency Domain to Time Domain | 396 | %% Convert from Frequency Domain to Time Domain | ||
397 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 397 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
398 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 398 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
399 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 399 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
400 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 400 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
401 | if DO_ONCE | 401 | if DO_ONCE | ||
402 | if ~OP.TDMODE | 402 | if ~OP.TDMODE | ||
403 | chdata=COM_FD_to_TD(chdata,param,OP); | 403 | chdata=COM_FD_to_TD(chdata,param,OP); | ||
404 | output_args.VMC_HF_mV=chdata(1).VCM_HF_struct.DCn*1000; | 404 | output_args.VMC_HF_mV=chdata(1).VCM_HF_struct.DCn*1000; | ||
405 | output_args.SCMR_dB=chdata(1).SCMR; | 405 | output_args.SCMR_dB=chdata(1).SCMR; | ||
406 | end | 406 | end | ||
407 | end | 407 | end | ||
408 |
| 408 |
| ||
409 | %% Determine equalization settings | 409 | %% Determine equalization settings | ||
410 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 410 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
411 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 411 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
412 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 412 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
413 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 413 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
414 | %--------------------- | 414 | %--------------------- | ||
415 | do_C2M=0; | 415 | do_C2M=0; | ||
416 | if param.T_O~=0 && param.Min_VEO_Test~=0 | 416 | if param.T_O~=0 && param.Min_VEO_Test~=0 | ||
417 | do_C2M=1; | 417 | do_C2M=1; | ||
418 | end | 418 | end | ||
− | 419 | OP.COMPUTE_COM=false; |
| ||
420 | fom_result = optimize_fom(OP,param, chdata, sigma_bn,do_C2M); | 419 | fom_result = optimize_fom(OP,param, chdata, sigma_bn,do_C2M); | ||
421 | if fom_result.eq_failed ; return; end % RIM 12-20-2023 | 420 | if fom_result.eq_failed ; return; end % RIM 12-20-2023 | ||
≠ | 422 | OP.COMPUTE_COM=true; | ≠ | 421 |
|
423 | %% Apply Equalization (returns pulse response with CTLE, TXLE, RXFFE) | 422 | %% Apply Equalization (returns pulse response with CTLE, TXLE, RXFFE) | ||
424 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 423 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
425 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 424 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
426 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 425 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
427 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 426 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
− | 428 |
|
| ||
429 | A_s=abs(fom_result.A_s); % this is the "s" in SNR (PAM4 gain in handled in last sections | 427 | A_s=abs(fom_result.A_s); % this is the "s" in SNR (PAM4 gain in handled in last sections | ||
430 | param.use_bmax=fom_result.best_bmax.'; | 428 | param.use_bmax=fom_result.best_bmax.'; | ||
431 | %AJG021820 | 429 | %AJG021820 | ||
432 | param.use_bmin=fom_result.best_bmin.'; | 430 | param.use_bmin=fom_result.best_bmin.'; | ||
433 | % Recommended Delta_y no larger than As/1000 or 0.01 mV | 431 | % Recommended Delta_y no larger than As/1000 or 0.01 mV | ||
434 | param.current_ffegain=fom_result.best_current_ffegain; | 432 | param.current_ffegain=fom_result.best_current_ffegain; | ||
435 | if OP.force_pdf_bin_size | 433 | if OP.force_pdf_bin_size | ||
436 | param.delta_y = OP.BinSize; | 434 | param.delta_y = OP.BinSize; | ||
437 | else | 435 | else | ||
438 | param.delta_y = min(A_s/1000, OP.BinSize); | 436 | param.delta_y = min(A_s/1000, OP.BinSize); | ||
439 | end | 437 | end | ||
440 | % the pdf for PAM4 uses the full swing SBR but assigns voltage for the PDF accordingly | 438 | % the pdf for PAM4 uses the full swing SBR but assigns voltage for the PDF accordingly | ||
441 | if OP.RX_CALIBRATION, param.number_of_s4p_files=1; end | 439 | if OP.RX_CALIBRATION, param.number_of_s4p_files=1; end | ||
442 |
| 440 |
| ||
443 | chdata=Apply_EQ(param,fom_result,chdata,OP); | 441 | chdata=Apply_EQ(param,fom_result,chdata,OP); | ||
| + | 442 |
| ||
≠ | 444 | PSD_results=[]; % need to define because passed to Create_Noise_PDF for backward compatability | ≠ | 443 | PSD_results=[]; |
445 | if (strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 444 | if (strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
446 | OP.WO_TXFFE=1; | 445 | OP.WO_TXFFE=1; | ||
− | 447 | PSD_results.w=fom_result.RxFFE; |
| ||
≠ | 448 | % chdata(1).eq_pulse_response includes rx FFE from Apply_EQ as | ≠ | 446 | % chdata(1).eq_pulse_response includes rx FFE from Apply_EQ |
− | 449 | % well as CTLE (CTF) and tx FFE |
| ||
450 | PSD_results.S_rn=fom_result.PSD_results.S_rn; % get_PSDs will adjust S_rn for Rxffe | ||||
451 | PSD_results = get_PSDs(PSD_results,chdata(1).eq_pulse_response,fom_result.t_s, fom_result.txffe,param.ctle_gdc_values(fom_result.ctle),param.g_DC_HP_values(fom_result.best_G_high_pass),param,chdata,OP); | 447 | PSD_results = get_PSDs(PSD_results,chdata(1).eq_pulse_response,fom_result.t_s, fom_result.txffe,param.ctle_gdc_values(fom_result.ctle),param.g_DC_HP_values(fom_result.best_G_high_pass),param,chdata,OP); | ||
452 | OP.WO_TXFFE=0; | 448 | OP.WO_TXFFE=0; | ||
− | 453 | PSD_results.S_xn=fom_result.PSD_results.S_xn; % get_PSDs will adjust S_xn for Rxffe |
| ||
454 | PSD_results.S_tn=fom_result.PSD_results.S_tn; % get_PSDs will adjust S_tn for Rxffe | ||||
455 | PSD_results.S_jn =fom_result.PSD_results.S_jn; % get_PSDs will adjust S_jn for Rxffe | ||||
456 | PSD_results.S_rj_jn = fom_result.PSD_results.S_rj_jn;% get_PSDs will adjust S_rj_jn for Rxffe | ||||
457 | PSD_results = get_PSDs(PSD_results,chdata(1).eq_pulse_response,fom_result.t_s, fom_result.txffe,param.ctle_gdc_values(fom_result.ctle),param.g_DC_HP_values(fom_result.best_G_high_pass),param,chdata,OP); | 449 | PSD_results = get_PSDs(PSD_results,chdata(1).eq_pulse_response,fom_result.t_s, fom_result.txffe,param.ctle_gdc_values(fom_result.ctle),param.g_DC_HP_values(fom_result.best_G_high_pass),param,chdata,OP); | ||
458 | output_args.noiseRMS_mV.rn=PSD_results.S_rn_rms*1000; | 450 | output_args.noiseRMS_mV.rn=PSD_results.S_rn_rms*1000; | ||
− | 459 | output_args.noiseRMS_mV.tn=PSD_results.S_tn_rms*1000; |
| ||
≠ | 460 | output_args.noiseRMS_mV.xn=PSD_results.S_xn_rms*1000; | ≠ | 451 | output_args.noiseRMS_mV.xn=PSD_results.xn_rms*1000; |
≠ | 461 | output_args.noiseRMS_mV.tn=PSD_results.S_tn_rms*1000; | ≠ | 452 | output_args.noiseRMS_mV.tn=PSD_results.tn_rms*1000; |
≠ | 462 | output_args.noiseRMS_mV.jn=PSD_results.S_jn_rms*1000; | ≠ | 453 | output_args.noiseRMS_mV.jn=PSD_results.jn_rms*1000; |
463 | end | 454 | end | ||
464 | %% Create ISI PDF & Individual Crosstalk PDFs | 455 | %% Create ISI PDF & Individual Crosstalk PDFs | ||
465 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 456 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
466 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 457 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
467 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 458 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
468 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 459 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
469 | if ~OP.DISPLAY_WINDOW, fprintf('processing COM PDF '); end | 460 | if ~OP.DISPLAY_WINDOW, fprintf('processing COM PDF '); end | ||
470 | for i=1:param.number_of_s4p_files | 461 | for i=1:param.number_of_s4p_files | ||
471 | if ~OP.DISPLAY_WINDOW, fprintf('%d ', i); end | 462 | if ~OP.DISPLAY_WINDOW, fprintf('%d ', i); end | ||
472 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | 463 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | ||
473 | 464 | ||||
474 | pdf = get_pdf(chdata(i), param.delta_y, fom_result.t_s, param, OP,fom_result.PSD_results.iphase(i)) ; | 465 | pdf = get_pdf(chdata(i), param.delta_y, fom_result.t_s, param, OP,fom_result.PSD_results.iphase(i)) ; | ||
475 | else | 466 | else | ||
476 | pdf = get_pdf(chdata(i), param.delta_y, fom_result.t_s, param, OP,[]); | 467 | pdf = get_pdf(chdata(i), param.delta_y, fom_result.t_s, param, OP,[]); | ||
477 | end | 468 | end | ||
478 | if OP.DEBUG && OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | 469 | if OP.DEBUG && OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | ||
479 | figure(150+package_testcase_i);set(gcf,'Tag','COM'); | 470 | figure(150+package_testcase_i);set(gcf,'Tag','COM'); | ||
480 | subplot(2,1,2); | 471 | subplot(2,1,2); | ||
481 | pdf0.x=pdf.x(pdf.y~=0); | 472 | pdf0.x=pdf.x(pdf.y~=0); | ||
482 | pdf0.y=pdf.y(pdf.y~=0); | 473 | pdf0.y=pdf.y(pdf.y~=0); | ||
483 | semilogy(pdf0.x, pdf0.y,'disp', chdata(i).base); | 474 | semilogy(pdf0.x, pdf0.y,'disp', chdata(i).base); | ||
484 | current_ylim=ylim; ylim([param.specBER/100, current_ylim(2)]); | 475 | current_ylim=ylim; ylim([param.specBER/100, current_ylim(2)]); | ||
485 | hold on; title('PDF') | 476 | hold on; title('PDF') | ||
486 | recolor_plots(gca); | 477 | recolor_plots(gca); | ||
487 | end | 478 | end | ||
488 |
| 479 |
| ||
489 | chdata(i).pdfr=pdf; | 480 | chdata(i).pdfr=pdf; | ||
490 | % reporting | 481 | % reporting | ||
491 | a=find(cumsum(chdata(i).pdfr.y) >1e-12,1,'first'); | 482 | a=find(cumsum(chdata(i).pdfr.y) >1e-12,1,'first'); | ||
492 | chdata(i).maxquickpdf=(chdata(i).pdfr.y(a)); | 483 | chdata(i).maxquickpdf=(chdata(i).pdfr.y(a)); | ||
493 |
| 484 |
| ||
494 | end | 485 | end | ||
495 | if ~OP.DISPLAY_WINDOW, fprintf('\n'); end | 486 | if ~OP.DISPLAY_WINDOW, fprintf('\n'); end | ||
496 |
| 487 |
| ||
497 | %% Return final PDF & CDF and Package all noise parameters in Noise_Struct | 488 | %% Return final PDF & CDF and Package all noise parameters in Noise_Struct | ||
498 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 489 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
499 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 490 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
500 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 491 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
501 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 492 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
502 | [PDF,CDF,Noise_Struct]=Create_Noise_PDF(A_s,param,fom_result,chdata,OP,sigma_bn,PSD_results); | 493 | [PDF,CDF,Noise_Struct]=Create_Noise_PDF(A_s,param,fom_result,chdata,OP,sigma_bn,PSD_results); | ||
503 | combined_interference_and_noise_pdf=PDF; | 494 | combined_interference_and_noise_pdf=PDF; | ||
504 | combined_interference_and_noise_cdf=CDF; | 495 | combined_interference_and_noise_cdf=CDF; | ||
505 | 496 | ||||
506 |
| 497 |
| ||
507 | %% Calculate COM and other associated outputs | 498 | %% Calculate COM and other associated outputs | ||
508 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 499 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
509 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 500 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
510 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 501 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
511 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 502 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
512 | % The noise and interference amplitude, A_ni, is the magnitude of the value of y0 | 503 | % The noise and interference amplitude, A_ni, is the magnitude of the value of y0 | ||
513 | % that satisfies the relationship P(y0) = DER_0 | 504 | % that satisfies the relationship P(y0) = DER_0 | ||
514 | A_ni_ix=find(combined_interference_and_noise_cdf>param.specBER, 1, 'first'); | 505 | A_ni_ix=find(combined_interference_and_noise_cdf>param.specBER, 1, 'first'); | ||
515 | A_ni = abs(combined_interference_and_noise_pdf.x(A_ni_ix)); | 506 | A_ni = abs(combined_interference_and_noise_pdf.x(A_ni_ix)); | ||
516 | 507 | ||||
517 | % begin yasuo patch 3/18/2019 | 508 | % begin yasuo patch 3/18/2019 | ||
518 | % estimate DER at threshold COM | 509 | % estimate DER at threshold COM | ||
519 | threshold_ix=find(combined_interference_and_noise_pdf.x>-A_s/(10^(param.pass_threshold/20)),1); | 510 | threshold_ix=find(combined_interference_and_noise_pdf.x>-A_s/(10^(param.pass_threshold/20)),1); | ||
520 | threshold_DER=combined_interference_and_noise_cdf(threshold_ix); | 511 | threshold_DER=combined_interference_and_noise_cdf(threshold_ix); | ||
521 | threshold_DER_max = max(threshold_DER_max, threshold_DER); | 512 | threshold_DER_max = max(threshold_DER_max, threshold_DER); | ||
522 | % end yasuo patch | 513 | % end yasuo patch | ||
523 |
| 514 |
| ||
524 | if OP.RX_CALIBRATION ==0 && OP.EW == 1 | 515 | if OP.RX_CALIBRATION ==0 && OP.EW == 1 | ||
525 | [Left_EW,Right_EW,eye_contour,EH_T_C2M,EH_B_C2M]=COM_eye_width(chdata,param.delta_y,fom_result,param,OP,Noise_Struct,0); | 516 | [Left_EW,Right_EW,eye_contour,EH_T_C2M,EH_B_C2M]=COM_eye_width(chdata,param.delta_y,fom_result,param,OP,Noise_Struct,0); | ||
526 | EW_UI=floor((Left_EW+Right_EW))/param.samples_for_C2M; | 517 | EW_UI=floor((Left_EW+Right_EW))/param.samples_for_C2M; | ||
527 | if OP.DISPLAY_WINDOW && OP.DEBUG | 518 | if OP.DISPLAY_WINDOW && OP.DEBUG | ||
528 | figure_name = 'Eye at DER0 estimate'; | 519 | figure_name = 'Eye at DER0 estimate'; | ||
529 | fig=findobj('Name', figure_name); | 520 | fig=findobj('Name', figure_name); | ||
530 | if isempty(fig), fig=figure('Name', figure_name); end | 521 | if isempty(fig), fig=figure('Name', figure_name); end | ||
531 | figure(fig);set(gcf,'Tag','COM'); | 522 | figure(fig);set(gcf,'Tag','COM'); | ||
532 | movegui(fig,'southwest') | 523 | movegui(fig,'southwest') | ||
533 | plot(eye_contour) | 524 | plot(eye_contour) | ||
534 | xlabel('UI %') | 525 | xlabel('UI %') | ||
535 | ylabel('V') | 526 | ylabel('V') | ||
536 | end | 527 | end | ||
537 |
| 528 |
| ||
538 | else | 529 | else | ||
539 | EW_UI=0; | 530 | EW_UI=0; | ||
540 | eye_contour=[]; | 531 | eye_contour=[]; | ||
541 | end | 532 | end | ||
542 | if OP.MLSE==0 | 533 | if OP.MLSE==0 | ||
543 | if param.T_O ~=0 | 534 | if param.T_O ~=0 | ||
544 | eye_opening=EH_T_C2M-EH_B_C2M; | 535 | eye_opening=EH_T_C2M-EH_B_C2M; | ||
545 | A_ni=2*A_s-eye_opening; | 536 | A_ni=2*A_s-eye_opening; | ||
546 | %eq 124E-4 | 537 | %eq 124E-4 | ||
547 | vec_arg=2*A_s/eye_opening; | 538 | vec_arg=2*A_s/eye_opening; | ||
548 | if vec_arg<eps | 539 | if vec_arg<eps | ||
549 | vec_arg=eps; | 540 | vec_arg=eps; | ||
550 | end | 541 | end | ||
551 | VEC_dB = 20*log10(vec_arg); | 542 | VEC_dB = 20*log10(vec_arg); | ||
552 | COM=20*log10(2*A_s/A_ni); | 543 | COM=20*log10(2*A_s/A_ni); | ||
553 | VEO_mV=eye_opening*1000; | 544 | VEO_mV=eye_opening*1000; | ||
554 | min_COM = min(min_COM, COM); | 545 | min_COM = min(min_COM, COM); | ||
555 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | 546 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | ||
556 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | 547 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | ||
557 | else | 548 | else | ||
558 | VEO_mV = 1000*(A_s-A_ni)*2; | 549 | VEO_mV = 1000*(A_s-A_ni)*2; | ||
559 | vec_arg=(A_s-A_ni)/A_s; | 550 | vec_arg=(A_s-A_ni)/A_s; | ||
560 | if vec_arg<eps | 551 | if vec_arg<eps | ||
561 | vec_arg=eps; | 552 | vec_arg=eps; | ||
562 | end | 553 | end | ||
563 | VEC_dB = -20*log10(vec_arg); | 554 | VEC_dB = -20*log10(vec_arg); | ||
564 | COM=20*log10(A_s/A_ni); | 555 | COM=20*log10(A_s/A_ni); | ||
565 | min_COM = min(min_COM, COM); | 556 | min_COM = min(min_COM, COM); | ||
566 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | 557 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | ||
567 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | 558 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | ||
568 | end | 559 | end | ||
569 | MLSE_results=struct; | 560 | MLSE_results=struct; | ||
570 | else % MLSE case added U3 option | 561 | else % MLSE case added U3 option | ||
571 | if OP.MLSE==1 | 562 | if OP.MLSE==1 | ||
572 | [MLSE_results] = MLSE(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF); | 563 | [MLSE_results] = MLSE(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF); | ||
573 | elseif OP.MLSE==2 | 564 | elseif OP.MLSE==2 | ||
574 | [MLSE_results] = MLSE_instu(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF); | 565 | [MLSE_results] = MLSE_instu(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF); | ||
575 | elseif OP.MLSE==3 | 566 | elseif OP.MLSE==3 | ||
≠ | 576 | [MLSE_results] = MLSE_U1_c(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF,PSD_results); | ≠ | 567 | [MLSE_results] = MLSE_U3(param,fom_result.DFE_taps(1),A_s,A_ni,PDF,CDF,PSD_results); |
577 | else | 568 | else | ||
578 | warning('unsuported MLSE option') | 569 | warning('unsuported MLSE option') | ||
579 | end | 570 | end | ||
580 | if param.T_O ~=0 | 571 | if param.T_O ~=0 | ||
581 | eye_opening=EH_T_C2M-EH_B_C2M; | 572 | eye_opening=EH_T_C2M-EH_B_C2M; | ||
582 | A_ni=2*A_s-eye_opening; | 573 | A_ni=2*A_s-eye_opening; | ||
583 | %eq 124E-4 | 574 | %eq 124E-4 | ||
584 | vec_arg=2*A_s/eye_opening; | 575 | vec_arg=2*A_s/eye_opening; | ||
585 | if vec_arg<eps | 576 | if vec_arg<eps | ||
586 | vec_arg=eps; | 577 | vec_arg=eps; | ||
587 | end | 578 | end | ||
588 | VEC_dB_orig = 20*log10(vec_arg); % was negative in 400 beta1 ... Fixed 2-2-23 | 579 | VEC_dB_orig = 20*log10(vec_arg); % was negative in 400 beta1 ... Fixed 2-2-23 | ||
589 | VEC_dB=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1)+VEC_dB_orig; | 580 | VEC_dB=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1)+VEC_dB_orig; | ||
590 | COM_orig=20*log10(2*A_s/A_ni); | 581 | COM_orig=20*log10(2*A_s/A_ni); | ||
591 | COM=MLSE_results.COM_CDF; | 582 | COM=MLSE_results.COM_CDF; | ||
592 | VEO_mV=eye_opening*1000; | 583 | VEO_mV=eye_opening*1000; | ||
593 | min_COM = min(min_COM, COM); | 584 | min_COM = min(min_COM, COM); | ||
594 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | 585 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | ||
595 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | 586 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | ||
596 | output_args.delta_COM=MLSE_results.delta_com_CDF; | 587 | output_args.delta_COM=MLSE_results.delta_com_CDF; | ||
597 | output_args.delta_VEC=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1); | 588 | output_args.delta_VEC=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1); | ||
598 | else | 589 | else | ||
599 | VEO_mV = 1000*(A_s-A_ni)*2; | 590 | VEO_mV = 1000*(A_s-A_ni)*2; | ||
600 | vec_arg=(A_s-A_ni)/A_s; | 591 | vec_arg=(A_s-A_ni)/A_s; | ||
601 | if vec_arg<eps | 592 | if vec_arg<eps | ||
602 | vec_arg=eps; | 593 | vec_arg=eps; | ||
603 | end | 594 | end | ||
604 | VEC_dB_orig = -20*log10(vec_arg); | 595 | VEC_dB_orig = -20*log10(vec_arg); | ||
605 | VEC_dB=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1)+VEC_dB_orig; | 596 | VEC_dB=MLSE_results.delta_com_CDF-20*log10( (10^(MLSE_results.delta_com_CDF/20)-1)*10^(VEC_dB_orig/20)+1)+VEC_dB_orig; | ||
606 | COM_orig=20*log10(A_s/A_ni); | 597 | COM_orig=20*log10(A_s/A_ni); | ||
607 | COM=MLSE_results.COM_CDF; | 598 | COM=MLSE_results.COM_CDF; | ||
608 | min_COM = min(min_COM, COM); | 599 | min_COM = min(min_COM, COM); | ||
609 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | 600 | min_VEO_mV = min(min_VEO_mV,VEO_mV); | ||
610 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | 601 | max_VEC_dB = max(max_VEC_dB, VEC_dB); | ||
611 | output_args.delta_COM=MLSE_results.delta_com_CDF; | 602 | output_args.delta_COM=MLSE_results.delta_com_CDF; | ||
612 | end | 603 | end | ||
613 | end | 604 | end | ||
614 |
| 605 |
| ||
615 | %% Create COM_SNR_Struct to hold the main COM outputs | 606 | %% Create COM_SNR_Struct to hold the main COM outputs | ||
616 | COM_SNR_Struct.A_s=A_s; | 607 | COM_SNR_Struct.A_s=A_s; | ||
617 | COM_SNR_Struct.A_ni=A_ni; | 608 | COM_SNR_Struct.A_ni=A_ni; | ||
618 | COM_SNR_Struct.threshold_DER=threshold_DER; | 609 | COM_SNR_Struct.threshold_DER=threshold_DER; | ||
619 | COM_SNR_Struct.EW_UI=EW_UI; | 610 | COM_SNR_Struct.EW_UI=EW_UI; | ||
620 | COM_SNR_Struct.COM=COM; | 611 | COM_SNR_Struct.COM=COM; | ||
621 | COM_SNR_Struct.VEC_dB=VEC_dB; | 612 | COM_SNR_Struct.VEC_dB=VEC_dB; | ||
622 | if OP.MLSE == 0 | 613 | if OP.MLSE == 0 | ||
623 | COM_SNR_Struct.COM_orig=[]; | 614 | COM_SNR_Struct.COM_orig=[]; | ||
624 | COM_SNR_Struct.VEC_dB_orig=[]; | 615 | COM_SNR_Struct.VEC_dB_orig=[]; | ||
625 | else | 616 | else | ||
626 | COM_SNR_Struct.COM_orig=COM_orig; | 617 | COM_SNR_Struct.COM_orig=COM_orig; | ||
627 | COM_SNR_Struct.VEC_dB_orig=VEC_dB_orig; | 618 | COM_SNR_Struct.VEC_dB_orig=VEC_dB_orig; | ||
628 | end | 619 | end | ||
629 | COM_SNR_Struct.VEO_mV=VEO_mV; | 620 | COM_SNR_Struct.VEO_mV=VEO_mV; | ||
630 | COM_SNR_Struct.combined_interference_and_noise_pdf=combined_interference_and_noise_pdf; | 621 | COM_SNR_Struct.combined_interference_and_noise_pdf=combined_interference_and_noise_pdf; | ||
631 | COM_SNR_Struct.combined_interference_and_noise_cdf=combined_interference_and_noise_cdf; | 622 | COM_SNR_Struct.combined_interference_and_noise_cdf=combined_interference_and_noise_cdf; | ||
632 | COM_SNR_Struct.eye_contour=eye_contour; | 623 | COM_SNR_Struct.eye_contour=eye_contour; | ||
633 |
| 624 |
| ||
634 |
| 625 |
| ||
635 | %% Save TD | 626 | %% Save TD | ||
636 | if OP.SAVE_TD | 627 | if OP.SAVE_TD | ||
637 | sbr=timeseries(fom_result.sbr,fom_result.t); | 628 | sbr=timeseries(fom_result.sbr,fom_result.t); | ||
638 | if ~OP.TDMODE | 629 | if ~OP.TDMODE | ||
639 | fir=timeseries(fom_result.IR,fom_result.t); | 630 | fir=timeseries(fom_result.IR,fom_result.t); | ||
640 | end | 631 | end | ||
641 | for i=1:param.number_of_s4p_files | 632 | for i=1:param.number_of_s4p_files | ||
642 | Pulses(i).uneq_responce= timeseries(chdata(i).uneq_pulse_response, chdata(i).t ); | 633 | Pulses(i).uneq_responce= timeseries(chdata(i).uneq_pulse_response, chdata(i).t ); | ||
643 | Pulses(i).eq_responce= timeseries(chdata(i).eq_pulse_response, chdata(i).t ); | 634 | Pulses(i).eq_responce= timeseries(chdata(i).eq_pulse_response, chdata(i).t ); | ||
644 | if ~OP.TDMODE | 635 | if ~OP.TDMODE | ||
645 | FIR(i).uneq_imp_response= timeseries(chdata(i).uneq_imp_response, chdata(i).t ); | 636 | FIR(i).uneq_imp_response= timeseries(chdata(i).uneq_imp_response, chdata(i).t ); | ||
646 | FIR(i).eq_imp_response= timeseries(chdata(i).eq_imp_response, chdata(i).t ); | 637 | FIR(i).eq_imp_response= timeseries(chdata(i).eq_imp_response, chdata(i).t ); | ||
647 | end | 638 | end | ||
648 | end | 639 | end | ||
649 | if OP.TDMODE | 640 | if OP.TDMODE | ||
650 | save( [OP.RESULT_DIR 'sbr_fir_' param.base '.mat'],'sbr','Pulses'); | 641 | save( [OP.RESULT_DIR 'sbr_fir_' param.base '.mat'],'sbr','Pulses'); | ||
651 | else | 642 | else | ||
652 | save( [OP.RESULT_DIR 'sbr_fir_' param.base '.mat'],'sbr','fir','Pulses','FIR') | 643 | save( [OP.RESULT_DIR 'sbr_fir_' param.base '.mat'],'sbr','fir','Pulses','FIR') | ||
653 | end | 644 | end | ||
654 | end | 645 | end | ||
655 |
| 646 |
| ||
656 | %% Bathtub/Contribution Plot | 647 | %% Bathtub/Contribution Plot | ||
657 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | 648 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | ||
658 | Bathtub_Contribution_Wrapper(COM_SNR_Struct,Noise_Struct,param,chdata,OP); | 649 | Bathtub_Contribution_Wrapper(COM_SNR_Struct,Noise_Struct,param,chdata,OP); | ||
659 | end | 650 | end | ||
660 |
| 651 |
| ||
661 | %% Msg management | 652 | %% Msg management | ||
662 | if ~exist('msg','var') | 653 | if ~exist('msg','var') | ||
663 | msg=[]; | 654 | msg=[]; | ||
664 | end | 655 | end | ||
665 | if OP.DEBUG | 656 | if OP.DEBUG | ||
666 | [ncases, mele]=size(param.z_p_tx_cases); | 657 | [ncases, mele]=size(param.z_p_tx_cases); | ||
667 | switch param.flex | 658 | switch param.flex | ||
668 | case 4 | 659 | case 4 | ||
669 | msg = sprintf('%s: Case %g: z_p=(%g:%g:%g:%g, %g:%g:%g:%g, %g:%g:%g:%g, %g:%g:%g:%g) (TX, RX, NEXT, FEXT):\n', ... | 660 | msg = sprintf('%s: Case %g: z_p=(%g:%g:%g:%g, %g:%g:%g:%g, %g:%g:%g:%g, %g:%g:%g:%g) (TX, RX, NEXT, FEXT):\n', ... | ||
670 | msg,package_testcase_i, param.Pkg_len_TX, param.Pkg_len_RX, param.Pkg_len_NEXT, param.Pkg_len_FEXT ... | 661 | msg,package_testcase_i, param.Pkg_len_TX, param.Pkg_len_RX, param.Pkg_len_NEXT, param.Pkg_len_FEXT ... | ||
671 | ); | 662 | ); | ||
672 | case 2 | 663 | case 2 | ||
673 | msg = sprintf('%s: Case %g: z_p=(%g:%g, %g:%g, %g:%g, %g:%g) (TX, RX, NEXT, FEXT):\n', ... | 664 | msg = sprintf('%s: Case %g: z_p=(%g:%g, %g:%g, %g:%g, %g:%g) (TX, RX, NEXT, FEXT):\n', ... | ||
674 | msg,package_testcase_i, param.Pkg_len_TX(1:2), param.Pkg_len_RX(1:2), param.Pkg_len_NEXT(1:2), param.Pkg_len_FEXT(1:2) ... | 665 | msg,package_testcase_i, param.Pkg_len_TX(1:2), param.Pkg_len_RX(1:2), param.Pkg_len_NEXT(1:2), param.Pkg_len_FEXT(1:2) ... | ||
675 | ); | 666 | ); | ||
676 | otherwise | 667 | otherwise | ||
677 | msg = sprintf('%s: Case %g: z_p=(%g, %g, %g, %g) (TX, RX, NEXT, FEXT):', ... | 668 | msg = sprintf('%s: Case %g: z_p=(%g, %g, %g, %g) (TX, RX, NEXT, FEXT):', ... | ||
678 | msg, package_testcase_i, param.Pkg_len_TX, param.Pkg_len_RX, param.Pkg_len_NEXT, param.Pkg_len_FEXT ... | 669 | msg, package_testcase_i, param.Pkg_len_TX, param.Pkg_len_RX, param.Pkg_len_NEXT, param.Pkg_len_FEXT ... | ||
679 | ); | 670 | ); | ||
680 |
| 671 |
| ||
681 | end | 672 | end | ||
682 | else | 673 | else | ||
683 | msg = sprintf('Case %d:', package_testcase_i ); | 674 | msg = sprintf('Case %d:', package_testcase_i ); | ||
684 | end | 675 | end | ||
685 |
| 676 |
| ||
686 | if OP.TDMODE | 677 | if OP.TDMODE | ||
687 | min_ERL=inf; | 678 | min_ERL=inf; | ||
688 | ERL=[inf inf]; | 679 | ERL=[inf inf]; | ||
689 | end | 680 | end | ||
690 | [msg] = end_display_control(msg,param,OP,output_args,COM,min_ERL,ERL, VEO_mV,VEC_dB,threshold_DER,OP.DISPLAY_WINDOW); % {} forces no ERL print | 681 | [msg] = end_display_control(msg,param,OP,output_args,COM,min_ERL,ERL, VEO_mV,VEC_dB,threshold_DER,OP.DISPLAY_WINDOW); % {} forces no ERL print | ||
691 |
| 682 |
| ||
692 |
| 683 |
| ||
693 | %% Output Args | 684 | %% Output Args | ||
694 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 685 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
695 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 686 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
696 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 687 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
697 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | 688 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
698 | output_args=Output_Arg_Fill(output_args,sigma_bn,Noise_Struct,COM_SNR_Struct,param,chdata,fom_result,OP); | 689 | output_args=Output_Arg_Fill(output_args,sigma_bn,Noise_Struct,COM_SNR_Struct,param,chdata,fom_result,OP); | ||
699 | rt=toc(t0); | 690 | rt=toc(t0); | ||
700 | output_args.rtmin=rt/60; | 691 | output_args.rtmin=rt/60; | ||
701 |
| 692 |
| ||
702 | if OP.BREAD_CRUMBS | 693 | if OP.BREAD_CRUMBS | ||
703 | output_args.OP=OP; | 694 | output_args.OP=OP; | ||
704 | output_args.param=param; | 695 | output_args.param=param; | ||
705 | output_args.chdata=chdata; | 696 | output_args.chdata=chdata; | ||
706 | output_args.fom_result = fom_result; | 697 | output_args.fom_result = fom_result; | ||
707 | output_args.PDF=PDF; % for exploration | 698 | output_args.PDF=PDF; % for exploration | ||
708 | output_args.CDF=CDF; % for exploration | 699 | output_args.CDF=CDF; % for exploration | ||
709 | output_args.MLSE_results=MLSE_results; | 700 | output_args.MLSE_results=MLSE_results; | ||
710 | output_args.PSD_results=PSD_results; | 701 | output_args.PSD_results=PSD_results; | ||
711 | end | 702 | end | ||
712 | % results{package_testcase_i} = output_args;% moved RIM 04-14-2023 | 703 | % results{package_testcase_i} = output_args;% moved RIM 04-14-2023 | ||
713 |
| 704 |
| ||
714 | %% making csv file | 705 | %% making csv file | ||
715 | if OP.CSV_REPORT ==1 | 706 | if OP.CSV_REPORT ==1 | ||
716 | Write_CSV(output_args,CSV_FILE); | 707 | Write_CSV(output_args,CSV_FILE); | ||
717 | end | 708 | end | ||
718 | %% making mat file | 709 | %% making mat file | ||
719 | if(OP.DEBUG) | 710 | if(OP.DEBUG) | ||
720 | save (sprintf('%s%s_case%d_results.mat', OP.RESULT_DIR, chdata(1).base, package_testcase_i), ... | 711 | save (sprintf('%s%s_case%d_results.mat', OP.RESULT_DIR, chdata(1).base, package_testcase_i), ... | ||
721 | 'output_args','param','OP'); | 712 | 'output_args','param','OP'); | ||
722 | end | 713 | end | ||
723 | if 1 | 714 | if 1 | ||
724 | fprintf(' Die to die loss = %g dB \n',output_args.IL_db_die_to_die_at_Fnq) | 715 | fprintf(' Die to die loss = %g dB \n',output_args.IL_db_die_to_die_at_Fnq) | ||
725 | fprintf('run time = %g min \n',output_args.rtmin) | 716 | fprintf('run time = %g min \n',output_args.rtmin) | ||
726 | end | 717 | end | ||
727 |
| 718 |
| ||
728 | if nargout==0 | 719 | if nargout==0 | ||
729 | fprintf('<strong>--- Testcase %d results ---</strong>\n', package_testcase_i); | 720 | fprintf('<strong>--- Testcase %d results ---</strong>\n', package_testcase_i); | ||
730 | disp(output_args) | 721 | disp(output_args) | ||
731 | end | 722 | end | ||
732 |
| 723 |
| ||
733 | if OP.BREAD_CRUMBS | 724 | if OP.BREAD_CRUMBS | ||
734 | [my_path,rootname]=fileparts(chdata(1).filename); | 725 | [my_path,rootname]=fileparts(chdata(1).filename); | ||
735 | if ~isempty(OP.BREAD_CRUMBS_FIELDS) | 726 | if ~isempty(OP.BREAD_CRUMBS_FIELDS) | ||
736 | %Attempt to reduce the size of output_args.chdata by removing certain fields | 727 | %Attempt to reduce the size of output_args.chdata by removing certain fields | ||
737 | try | 728 | try | ||
738 | output_args.chdata=Bread_Crumb_Chdata_Reduction(output_args.chdata,OP.BREAD_CRUMBS_FIELDS); | 729 | output_args.chdata=Bread_Crumb_Chdata_Reduction(output_args.chdata,OP.BREAD_CRUMBS_FIELDS); | ||
739 | catch | 730 | catch | ||
740 | fprintf('Failed to reduce output_args.chdata\n'); | 731 | fprintf('Failed to reduce output_args.chdata\n'); | ||
741 | end | 732 | end | ||
742 | end | 733 | end | ||
743 | save (sprintf('%s%s_case%d_results.mat', OP.RESULT_DIR, rootname, package_testcase), ... | 734 | save (sprintf('%s%s_case%d_results.mat', OP.RESULT_DIR, rootname, package_testcase), ... | ||
744 | 'output_args','param','OP'); | 735 | 'output_args','param','OP'); | ||
745 | end | 736 | end | ||
746 |
| 737 |
| ||
747 | results{package_testcase_i} = output_args; % moved to after chdata field reduction RIM 04-14-2023 | 738 | results{package_testcase_i} = output_args; % moved to after chdata field reduction RIM 04-14-2023 | ||
748 | end | 739 | end | ||
749 | [tmp] = end_display_control('WC All cases',param,OP,output_args,min_COM,min_ERL,ERL,min_VEO_mV,max_VEC_dB,threshold_DER,0); | 740 | [tmp] = end_display_control('WC All cases',param,OP,output_args,min_COM,min_ERL,ERL,min_VEO_mV,max_VEC_dB,threshold_DER,0); | ||
750 | %% | 741 | %% | ||
751 | 742 | ||||
752 | if OP.RX_CALIBRATION ==1 | 743 | if OP.RX_CALIBRATION ==1 | ||
753 | sigma_hp= Noise_Struct.sigma_hp; % added for clause 162 else sigma_bn = sigma_hp (RIM 09-30-2022) | 744 | sigma_hp= Noise_Struct.sigma_hp; % added for clause 162 else sigma_bn = sigma_hp (RIM 09-30-2022) | ||
754 | display ([' LOOP with [sigma_bn sigma_hp] = [' num2str(sigma_bn) ' ' num2str(sigma_hp) '] performed with COM = ' num2str(min_COM) ]) | 745 | display ([' LOOP with [sigma_bn sigma_hp] = [' num2str(sigma_bn) ' ' num2str(sigma_hp) '] performed with COM = ' num2str(min_COM) ]) | ||
755 | end | 746 | end | ||
756 | DO_ONCE=false; | 747 | DO_ONCE=false; | ||
757 | end | 748 | end | ||
758 | 749 | ||||
759 | %% Final cleanup | 750 | %% Final cleanup | ||
760 | if OP.DISPLAY_WINDOW | 751 | if OP.DISPLAY_WINDOW | ||
761 | savefigs(param, OP); | 752 | savefigs(param, OP); | ||
762 | set(0,'defaulttextinterpreter','tex'); % reset defaut text interpreter to tex | 753 | set(0,'defaulttextinterpreter','tex'); % reset defaut text interpreter to tex | ||
763 | end | 754 | end | ||
764 | 755 | ||||
765 | if OP.RX_CALIBRATION==1 % updated for clause 162 else sigma_bn = sigma_hp (RIM 09-30-2022) | 756 | if OP.RX_CALIBRATION==1 % updated for clause 162 else sigma_bn = sigma_hp (RIM 09-30-2022) | ||
766 | if ~param.f_hp==0 | 757 | if ~param.f_hp==0 | ||
767 | fprintf ('Set Tx calibration noise(sigma_hp) rms voltage to %g mV\n', sigma_hp*1000); | 758 | fprintf ('Set Tx calibration noise(sigma_hp) rms voltage to %g mV\n', sigma_hp*1000); | ||
768 | if OP.DISPLAY_WINDOW | 759 | if OP.DISPLAY_WINDOW | ||
769 | message=sprintf('Set Tx calibration noise (sigma_hp) rms voltage to %g mV.',sigma_hp*1000); | 760 | message=sprintf('Set Tx calibration noise (sigma_hp) rms voltage to %g mV.',sigma_hp*1000); | ||
770 | hlast = msgbox(message,'sigma_hp','help'); | 761 | hlast = msgbox(message,'sigma_hp','help'); | ||
771 | set(hlast,'Color','y', 'tag', 'COM'); | 762 | set(hlast,'Color','y', 'tag', 'COM'); | ||
772 | end | 763 | end | ||
773 | else | 764 | else | ||
774 | fprintf ('Set calibration noise (sigma_bn)rms voltage to %g mV\n', sigma_bn*1000); | 765 | fprintf ('Set calibration noise (sigma_bn)rms voltage to %g mV\n', sigma_bn*1000); | ||
775 | if OP.DISPLAY_WINDOW | 766 | if OP.DISPLAY_WINDOW | ||
776 | message=sprintf('Set calibration noise rms (sigma_bn) voltage to %g mV.',sigma_bn*1000); | 767 | message=sprintf('Set calibration noise rms (sigma_bn) voltage to %g mV.',sigma_bn*1000); | ||
777 | hlast = msgbox(message,'sigma_bn','help'); | 768 | hlast = msgbox(message,'sigma_bn','help'); | ||
778 | set(hlast,'Color','y', 'tag', 'COM'); | 769 | set(hlast,'Color','y', 'tag', 'COM'); | ||
779 | end | 770 | end | ||
780 | end | 771 | end | ||
781 | end | 772 | end | ||
782 | 773 | ||||
783 | if length(results)==1, results = results{1}; end | 774 | if length(results)==1, results = results{1}; end | ||
784 | redo_cmd_str=' redo string is: eval([''My_var_0 = '' getappdata(0,''cmd_str'')])'; | 775 | redo_cmd_str=' redo string is: eval([''My_var_0 = '' getappdata(0,''cmd_str'')])'; | ||
785 | disp(redo_cmd_str); | 776 | disp(redo_cmd_str); | ||
786 | if isdeployed | 777 | if isdeployed | ||
787 | if OP.exit_if_deployed | 778 | if OP.exit_if_deployed | ||
788 | quit | 779 | quit | ||
789 | end | 780 | end | ||
790 | end | 781 | end | ||
791 | %% | 782 | %% | ||
792 | %-------------------------------------------------------------------------- | 783 | %-------------------------------------------------------------------------- | ||
793 | %--------------- Helper functions ----------------------------------------- | 784 | %--------------- Helper functions ----------------------------------------- | ||
794 | %-------------------------------------------------------------------------- | 785 | %-------------------------------------------------------------------------- | ||
795 | function chdata=Apply_EQ(param,fom_result,chdata,OP) | 786 | function chdata=Apply_EQ(param,fom_result,chdata,OP) | ||
796 | 787 | ||||
797 | FB=param.fb; | 788 | FB=param.fb; | ||
798 | FZ=param.CTLE_fz(fom_result.ctle); | 789 | FZ=param.CTLE_fz(fom_result.ctle); | ||
799 | FP1=param.CTLE_fp1(fom_result.ctle); | 790 | FP1=param.CTLE_fp1(fom_result.ctle); | ||
800 | FP2=param.CTLE_fp2(fom_result.ctle); | 791 | FP2=param.CTLE_fp2(fom_result.ctle); | ||
801 | GDC=param.ctle_gdc_values(fom_result.ctle); | 792 | GDC=param.ctle_gdc_values(fom_result.ctle); | ||
802 | if ~isempty(param.f_HP) | 793 | if ~isempty(param.f_HP) | ||
803 | FHP=param.f_HP(fom_result.best_G_high_pass); | 794 | FHP=param.f_HP(fom_result.best_G_high_pass); | ||
804 | end | 795 | end | ||
805 | if ~isempty(param.g_DC_HP_values) | 796 | if ~isempty(param.g_DC_HP_values) | ||
806 | GDCHP=param.g_DC_HP_values(fom_result.best_G_high_pass); | 797 | GDCHP=param.g_DC_HP_values(fom_result.best_G_high_pass); | ||
807 | end | 798 | end | ||
808 | if ~isempty(param.f_HP_Z) | 799 | if ~isempty(param.f_HP_Z) | ||
809 | FHPZ=param.f_HP_Z(fom_result.ctle); | 800 | FHPZ=param.f_HP_Z(fom_result.ctle); | ||
810 | end | 801 | end | ||
811 | if ~isempty(param.f_HP_P) | 802 | if ~isempty(param.f_HP_P) | ||
812 | FHPP=param.f_HP_P(fom_result.ctle); | 803 | FHPP=param.f_HP_P(fom_result.ctle); | ||
813 | end | 804 | end | ||
814 | %Handle the scenario where the pulse response is not long enough to | 805 | %Handle the scenario where the pulse response is not long enough to | ||
815 | %contain all DFE taps. the SBR recorded in fom_result has the proper | 806 | %contain all DFE taps. the SBR recorded in fom_result has the proper | ||
816 | %length | 807 | %length | ||
817 | SBR_Len=length(fom_result.sbr); | 808 | SBR_Len=length(fom_result.sbr); | ||
818 | if length(chdata(1).uneq_imp_response)<SBR_Len | 809 | if length(chdata(1).uneq_imp_response)<SBR_Len | ||
819 | samples_added=SBR_Len-length(chdata(1).uneq_imp_response); | 810 | samples_added=SBR_Len-length(chdata(1).uneq_imp_response); | ||
820 | chdata(1).uneq_imp_response(end+1:SBR_Len)=0; | 811 | chdata(1).uneq_imp_response(end+1:SBR_Len)=0; | ||
821 | chdata(1).uneq_pulse_response(end+1:SBR_Len)=0; | 812 | chdata(1).uneq_pulse_response(end+1:SBR_Len)=0; | ||
822 | chdata(1).t(end+1:SBR_Len)=(1:samples_added)/param.fb/param.samples_per_ui+chdata(1).t(end); | 813 | chdata(1).t(end+1:SBR_Len)=(1:samples_added)/param.fb/param.samples_per_ui+chdata(1).t(end); | ||
823 | end | 814 | end | ||
824 | for i=1:param.number_of_s4p_files | 815 | for i=1:param.number_of_s4p_files | ||
825 | % get quick PDF results but only for THRU when in Rx calibration | 816 | % get quick PDF results but only for THRU when in Rx calibration | ||
826 | uneq_ir=chdata(i).uneq_imp_response;% includes packages, Hx, and Hr | 817 | uneq_ir=chdata(i).uneq_imp_response;% includes packages, Hx, and Hr | ||
827 | if OP.INCLUDE_CTLE==1 | 818 | if OP.INCLUDE_CTLE==1 | ||
828 | switch param.CTLE_type | 819 | switch param.CTLE_type | ||
829 | case 'CL93' | 820 | case 'CL93' | ||
830 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | 821 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | ||
831 | case 'CL120d' | 822 | case 'CL120d' | ||
832 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | 823 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | ||
833 | eq_ir = TD_CTLE(eq_ir, FB, FHP, FHP, 100e100 , GDCHP, param.samples_per_ui); | 824 | eq_ir = TD_CTLE(eq_ir, FB, FHP, FHP, 100e100 , GDCHP, param.samples_per_ui); | ||
834 | case 'CL120e' % z has been adjusted for gain | 825 | case 'CL120e' % z has been adjusted for gain | ||
835 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | 826 | eq_ir = TD_CTLE(uneq_ir, FB, FZ, FP1, FP2, GDC, param.samples_per_ui); | ||
836 | eq_ir = TD_CTLE(eq_ir,FB, FHPZ, FHPP,1e99, 0, param.samples_per_ui); | 827 | eq_ir = TD_CTLE(eq_ir,FB, FHPZ, FHPP,1e99, 0, param.samples_per_ui); | ||
837 | end | 828 | end | ||
838 | else | 829 | else | ||
839 | eq_ir=uneq_ir; | 830 | eq_ir=uneq_ir; | ||
840 | end | 831 | end | ||
841 | chdata(i).eq_imp_response=eq_ir; | 832 | chdata(i).eq_imp_response=eq_ir; | ||
842 | eq_pulse=filter(ones(1, param.samples_per_ui), 1, chdata(i).eq_imp_response); | 833 | eq_pulse=filter(ones(1, param.samples_per_ui), 1, chdata(i).eq_imp_response); | ||
843 | 834 | ||||
844 | if isequal(chdata(i).type, 'FEXT') || isequal(chdata(i).type, 'THRU') | 835 | if isequal(chdata(i).type, 'FEXT') || isequal(chdata(i).type, 'THRU') | ||
845 | eq_pulse = FFE( fom_result.txffe ,fom_result.cur-1 , param.samples_per_ui, eq_pulse ); | 836 | eq_pulse = FFE( fom_result.txffe ,fom_result.cur-1 , param.samples_per_ui, eq_pulse ); | ||
846 | end | 837 | end | ||
847 | % chdata(i).ctle_imp_response | 838 | % chdata(i).ctle_imp_response | ||
848 | if OP.RxFFE | 839 | if OP.RxFFE | ||
849 | if isequal(upper(OP.FFE_OPT_METHOD),'MMSE') | 840 | if isequal(upper(OP.FFE_OPT_METHOD),'MMSE') | ||
850 | chdata(i).ctle_imp_response = FFE( fom_result.RxFFE ,fom_result.cur-1 , param.samples_per_ui, eq_ir ); | 841 | chdata(i).ctle_imp_response = FFE( fom_result.RxFFE ,fom_result.cur-1 , param.samples_per_ui, eq_ir ); | ||
851 | end | 842 | end | ||
852 | [ eq_pulse, C]=force(eq_pulse,param,OP,fom_result.t_s,fom_result.RxFFE); | 843 | [ eq_pulse, C]=force(eq_pulse,param,OP,fom_result.t_s,fom_result.RxFFE); | ||
853 | end | 844 | end | ||
854 | chdata(i).eq_pulse_response=eq_pulse;% includes packages, Hf, and Hr, Ht, and Hffe(from tx) | 845 | chdata(i).eq_pulse_response=eq_pulse;% includes packages, Hf, and Hr, Ht, and Hffe(from tx) | ||
855 | end | 846 | end | ||
856 | function Bathtub_Contribution_Wrapper(COM_SNR_Struct,Noise_Struct,param,chdata,OP) | 847 | function Bathtub_Contribution_Wrapper(COM_SNR_Struct,Noise_Struct,param,chdata,OP) | ||
857 | 848 | ||||
858 | % display bathtub curves in one axis per test case. | 849 | % display bathtub curves in one axis per test case. | ||
859 | case_number=param.package_testcase_i; | 850 | case_number=param.package_testcase_i; | ||
860 | if ~OP.COM_CONTRIBUTION_CURVES | 851 | if ~OP.COM_CONTRIBUTION_CURVES | ||
861 | figure_name = 'Voltage bathtub curves'; | 852 | figure_name = 'Voltage bathtub curves'; | ||
862 | fig=findobj('Name', figure_name); | 853 | fig=findobj('Name', figure_name); | ||
863 | if isempty(fig), fig=figure('Name', figure_name); end | 854 | if isempty(fig), fig=figure('Name', figure_name); end | ||
864 | figure(fig);set(gcf,'Tag','COM'); | 855 | figure(fig);set(gcf,'Tag','COM'); | ||
865 | movegui(fig,'south') | 856 | movegui(fig,'south') | ||
866 | hax = subplot(length(OP.pkg_len_select), 1, case_number); | 857 | hax = subplot(length(OP.pkg_len_select), 1, case_number); | ||
867 | plot_bathtub_curves( hax ... | 858 | plot_bathtub_curves( hax ... | ||
868 | , COM_SNR_Struct.A_s ... | 859 | , COM_SNR_Struct.A_s ... | ||
869 | , Noise_Struct.sci_pdf ... | 860 | , Noise_Struct.sci_pdf ... | ||
870 | , Noise_Struct.cci_pdf ... | 861 | , Noise_Struct.cci_pdf ... | ||
871 | , Noise_Struct.isi_and_xtalk_pdf ... | 862 | , Noise_Struct.isi_and_xtalk_pdf ... | ||
872 | , Noise_Struct.noise_pdf ... | 863 | , Noise_Struct.noise_pdf ... | ||
873 | , Noise_Struct.jitt_pdf ... | 864 | , Noise_Struct.jitt_pdf ... | ||
874 | , COM_SNR_Struct.combined_interference_and_noise_pdf ... | 865 | , COM_SNR_Struct.combined_interference_and_noise_pdf ... | ||
875 | , param.delta_y ... | 866 | , param.delta_y ... | ||
876 | ); | 867 | ); | ||
877 | set(hax, 'tag', 'BTC'); | 868 | set(hax, 'tag', 'BTC'); | ||
878 | title(hax, sprintf('case %d VBC: %s ', case_number, regexprep([chdata(1).base,' '],'_',' '))); | 869 | title(hax, sprintf('case %d VBC: %s ', case_number, regexprep([chdata(1).base,' '],'_',' '))); | ||
879 | ylim(hax, [param.specBER/10 1]); | 870 | ylim(hax, [param.specBER/10 1]); | ||
880 | % show BER target line | 871 | % show BER target line | ||
881 | hp=plot(get(hax, 'xlim'), param.specBER*[1 1], 'r:'); | 872 | hp=plot(get(hax, 'xlim'), param.specBER*[1 1], 'r:'); | ||
882 | set(get(get(hp,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | 873 | set(get(get(hp,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | ||
883 | else | 874 | else | ||
884 | figure_name = 'COM Contributions (Rough Allocations)'; | 875 | figure_name = 'COM Contributions (Rough Allocations)'; | ||
885 | fig=findobj('Name', figure_name); | 876 | fig=findobj('Name', figure_name); | ||
886 | if isempty(fig), fig=figure('Name', figure_name); end | 877 | if isempty(fig), fig=figure('Name', figure_name); end | ||
887 | figure(fig);set(gcf,'Tag','COM'); | 878 | figure(fig);set(gcf,'Tag','COM'); | ||
888 | movegui(fig,'south') | 879 | movegui(fig,'south') | ||
889 | hax = subplot(length(OP.pkg_len_select), 1, case_number); | 880 | hax = subplot(length(OP.pkg_len_select), 1, case_number); | ||
890 |
| 881 |
| ||
891 | plot_pie_com( hax ... | 882 | plot_pie_com( hax ... | ||
892 | , COM_SNR_Struct.A_s ... | 883 | , COM_SNR_Struct.A_s ... | ||
893 | , Noise_Struct.sci_pdf ... | 884 | , Noise_Struct.sci_pdf ... | ||
894 | , Noise_Struct.cci_pdf ... | 885 | , Noise_Struct.cci_pdf ... | ||
895 | , Noise_Struct.isi_and_xtalk_pdf ... | 886 | , Noise_Struct.isi_and_xtalk_pdf ... | ||
896 | , Noise_Struct.noise_pdf ... | 887 | , Noise_Struct.noise_pdf ... | ||
897 | , COM_SNR_Struct.combined_interference_and_noise_pdf ... | 888 | , COM_SNR_Struct.combined_interference_and_noise_pdf ... | ||
898 | , param.delta_y, param... | 889 | , param.delta_y, param... | ||
899 | ); | 890 | ); | ||
900 | set(hax, 'tag', 'BTC'); | 891 | set(hax, 'tag', 'BTC'); | ||
901 | title(hax, sprintf('case %d rough COM impact: %s ', case_number, regexprep([chdata(1).base,' '],'_',' '))); | 892 | title(hax, sprintf('case %d rough COM impact: %s ', case_number, regexprep([chdata(1).base,' '],'_',' '))); | ||
902 | end | 893 | end | ||
903 | 894 | ||||
904 | if OP.DEBUG && OP.DISPLAY_WINDOW && OP.RX_CALIBRATION==0 | 895 | if OP.DEBUG && OP.DISPLAY_WINDOW && OP.RX_CALIBRATION==0 | ||
905 | btc_axes = findobj('tag', 'BTC'); | 896 | btc_axes = findobj('tag', 'BTC'); | ||
906 | if ~isempty(btc_axes), linkaxes(btc_axes, 'x'); end | 897 | if ~isempty(btc_axes), linkaxes(btc_axes, 'x'); end | ||
907 | end | 898 | end | ||
908 | function H_bt=Bessel_Thomson_Filter(param,f,use_BT) | 899 | function H_bt=Bessel_Thomson_Filter(param,f,use_BT) | ||
909 | 900 | ||||
910 | if use_BT | 901 | if use_BT | ||
911 | a = bessel( param.BTorder ); | 902 | a = bessel( param.BTorder ); | ||
912 | acoef=fliplr( a ); | 903 | acoef=fliplr( a ); | ||
913 | H_bt =a(1)./ polyval(acoef, (1i*f./(param.fb_BT_cutoff*param.fb))); | 904 | H_bt =a(1)./ polyval(acoef, (1i*f./(param.fb_BT_cutoff*param.fb))); | ||
914 | else | 905 | else | ||
915 | H_bt=ones(1,length(f)); | 906 | H_bt=ones(1,length(f)); | ||
916 | end | 907 | end | ||
917 |
| 908 |
| ||
918 |
| 909 |
| ||
919 | function chdata=Bread_Crumb_Chdata_Reduction(chdata,fields_file) | 910 | function chdata=Bread_Crumb_Chdata_Reduction(chdata,fields_file) | ||
920 | 911 | ||||
921 | %This optional function reduces the size of output_args.chdata by parsing user supplied fields in a txt file | 912 | %This optional function reduces the size of output_args.chdata by parsing user supplied fields in a txt file | ||
922 | %The first line of the file must be #reduce or #include | 913 | %The first line of the file must be #reduce or #include | ||
923 | %All subsequent lines are field names in chdata | 914 | %All subsequent lines are field names in chdata | ||
924 | %If using #reduce, the list of fields are the fields to remove from chdata | 915 | %If using #reduce, the list of fields are the fields to remove from chdata | ||
925 | %If using #include, the list of fields are the fields to include in chdata | 916 | %If using #include, the list of fields are the fields to include in chdata | ||
926 | % | 917 | % | ||
927 | %Example file to remove the fields "sdd12_raw" "sdd21_raw" "sdd22_raw" "sdd11_raw" | 918 | %Example file to remove the fields "sdd12_raw" "sdd21_raw" "sdd22_raw" "sdd11_raw" | ||
928 | %#reduce | 919 | %#reduce | ||
929 | %sdd12_raw | 920 | %sdd12_raw | ||
930 | %sdd21_raw | 921 | %sdd21_raw | ||
931 | %sdd22_raw | 922 | %sdd22_raw | ||
932 | %sdd11_raw | 923 | %sdd11_raw | ||
933 | % | 924 | % | ||
934 | 925 | ||||
935 | fid=fopen(fields_file,'r'); | 926 | fid=fopen(fields_file,'r'); | ||
936 | file_data=textscan(fid,'%s','Delimiter','\n'); | 927 | file_data=textscan(fid,'%s','Delimiter','\n'); | ||
937 | 928 | ||||
938 | file_data=file_data{1}; | 929 | file_data=file_data{1}; | ||
939 | fclose(fid); | 930 | fclose(fid); | ||
940 | 931 | ||||
941 | %remove blank lines | 932 | %remove blank lines | ||
942 | L=cellfun('length',file_data); | 933 | L=cellfun('length',file_data); | ||
943 | file_data=file_data(L~=0); | 934 | file_data=file_data(L~=0); | ||
944 | 935 | ||||
945 | %first line must be '#reduce' or '#include' | 936 | %first line must be '#reduce' or '#include' | ||
946 | type=file_data{1}; | 937 | type=file_data{1}; | ||
947 | field_names=file_data(2:end); | 938 | field_names=file_data(2:end); | ||
948 | switch lower(type) | 939 | switch lower(type) | ||
949 | case '#reduce' | 940 | case '#reduce' | ||
950 | remove_fields=field_names; | 941 | remove_fields=field_names; | ||
951 | case '#include' | 942 | case '#include' | ||
952 | all_fields=fieldnames(chdata); | 943 | all_fields=fieldnames(chdata); | ||
953 | remove_fields=setdiff(all_fields,field_names); | 944 | remove_fields=setdiff(all_fields,field_names); | ||
954 | otherwise | 945 | otherwise | ||
955 | error('Bad first line. Must be "#reduce" or "#include"'); | 946 | error('Bad first line. Must be "#reduce" or "#include"'); | ||
956 | end | 947 | end | ||
957 | 948 | ||||
958 | %remove the "remove_fields" from chdata | 949 | %remove the "remove_fields" from chdata | ||
959 | for j=1:length(remove_fields) | 950 | for j=1:length(remove_fields) | ||
960 | this_field=remove_fields{j}; | 951 | this_field=remove_fields{j}; | ||
961 | if isfield(chdata,this_field) | 952 | if isfield(chdata,this_field) | ||
962 | chdata=rmfield(chdata,this_field); | 953 | chdata=rmfield(chdata,this_field); | ||
963 | end | 954 | end | ||
964 | end | 955 | end | ||
965 | function [p_burst,p_error_propagation]=Burst_Probability_Calc(COM_SNR_Struct,DFE_taps,param,OP) | 956 | function [p_burst,p_error_propagation]=Burst_Probability_Calc(COM_SNR_Struct,DFE_taps,param,OP) | ||
966 | 957 | ||||
967 | % an error burst of length N will cause each of the first N taps tap to mis-correct and create a PAM (2 or | 958 | % an error burst of length N will cause each of the first N taps tap to mis-correct and create a PAM (2 or | ||
968 | % 4) noise term - depending on the N'th previous symbol, with double the tap voltage. From this we calculate | 959 | % 4) noise term - depending on the N'th previous symbol, with double the tap voltage. From this we calculate | ||
969 | % the probability of staying in error state, i.e. burst of length N+1. | 960 | % the probability of staying in error state, i.e. burst of length N+1. | ||
970 | 961 | ||||
971 | A_s=COM_SNR_Struct.A_s; | 962 | A_s=COM_SNR_Struct.A_s; | ||
972 | % initialize loop with uncorrelated noise and BER | 963 | % initialize loop with uncorrelated noise and BER | ||
973 | error_propagation_noise_pdf{1}=COM_SNR_Struct.combined_interference_and_noise_pdf; % PDF for burst of length 1 is the uncorrelated PDF | 964 | error_propagation_noise_pdf{1}=COM_SNR_Struct.combined_interference_and_noise_pdf; % PDF for burst of length 1 is the uncorrelated PDF | ||
974 | 965 | ||||
975 | % Assume an error will occur if the noise excceds the available signal | 966 | % Assume an error will occur if the noise excceds the available signal | ||
976 | % reduced by some dB. reduction is by COM threshold minus Error | 967 | % reduced by some dB. reduction is by COM threshold minus Error | ||
977 | % propagation margin (a positive EP margin reduces uncorrelated error probability | 968 | % propagation margin (a positive EP margin reduces uncorrelated error probability | ||
978 | % below target BER). | 969 | % below target BER). | ||
979 | error_threshold = A_s./10^((param.pass_threshold-OP.COM_EP_margin)/20); | 970 | error_threshold = A_s./10^((param.pass_threshold-OP.COM_EP_margin)/20); | ||
980 | % Find the probability of this event by integration of the PDF. Use 1e-20 as a floor probabilty if noise PDF isn't wide enough. | 971 | % Find the probability of this event by integration of the PDF. Use 1e-20 as a floor probabilty if noise PDF isn't wide enough. | ||
981 | x_error_propagation = find(error_propagation_noise_pdf{1}.x >= error_threshold, 1, 'first'); | 972 | x_error_propagation = find(error_propagation_noise_pdf{1}.x >= error_threshold, 1, 'first'); | ||
982 | if isempty(x_error_propagation) | 973 | if isempty(x_error_propagation) | ||
983 | p_error_propagation(1) = 1e-20; | 974 | p_error_propagation(1) = 1e-20; | ||
984 | else | 975 | else | ||
985 | p_error_propagation(1) = sum(error_propagation_noise_pdf{1}.y(x_error_propagation:end)); % uncorrelated BER | 976 | p_error_propagation(1) = sum(error_propagation_noise_pdf{1}.y(x_error_propagation:end)); % uncorrelated BER | ||
986 | end | 977 | end | ||
987 | 978 | ||||
988 | sorted_abs_dfe_taps = sort(abs(DFE_taps), 'descend'); | 979 | sorted_abs_dfe_taps = sort(abs(DFE_taps), 'descend'); | ||
989 | for k=2:min(param.ndfe, OP.nburst) | 980 | for k=2:min(param.ndfe, OP.nburst) | ||
990 | % (arrays kept to allow tracking during development, though not really needed) | 981 | % (arrays kept to allow tracking during development, though not really needed) | ||
991 | if OP.use_simple_EP_model | 982 | if OP.use_simple_EP_model | ||
992 | post_error_dfe_noise_pdf{k} = get_pdf_from_sampled_signal( 2*A_s*max(sorted_abs_dfe_taps), param.levels, param.delta_y ); %#ok<AGROW> | 983 | post_error_dfe_noise_pdf{k} = get_pdf_from_sampled_signal( 2*A_s*max(sorted_abs_dfe_taps), param.levels, param.delta_y ); %#ok<AGROW> | ||
993 | error_propagation_noise_pdf{k} = conv_fct(error_propagation_noise_pdf{1}, post_error_dfe_noise_pdf{k}); %#ok<AGROW> | 984 | error_propagation_noise_pdf{k} = conv_fct(error_propagation_noise_pdf{1}, post_error_dfe_noise_pdf{k}); %#ok<AGROW> | ||
994 | else | 985 | else | ||
995 | post_error_dfe_noise_pdf{k} = get_pdf_from_sampled_signal( 2*A_s*sorted_abs_dfe_taps(k-1), param.levels, param.delta_y ); %#ok<AGROW> | 986 | post_error_dfe_noise_pdf{k} = get_pdf_from_sampled_signal( 2*A_s*sorted_abs_dfe_taps(k-1), param.levels, param.delta_y ); %#ok<AGROW> | ||
996 | error_propagation_noise_pdf{k} = conv_fct(error_propagation_noise_pdf{k-1}, post_error_dfe_noise_pdf{k}); %#ok<AGROW> | 987 | error_propagation_noise_pdf{k} = conv_fct(error_propagation_noise_pdf{k-1}, post_error_dfe_noise_pdf{k}); %#ok<AGROW> | ||
997 | end | 988 | end | ||
998 |
| 989 |
| ||
999 | % Assume an error will propagate if this noise exceeds the threshold defined above | 990 | % Assume an error will propagate if this noise exceeds the threshold defined above | ||
1000 | x_error_propagation = find(error_propagation_noise_pdf{k}.x >= error_threshold, 1, 'first'); | 991 | x_error_propagation = find(error_propagation_noise_pdf{k}.x >= error_threshold, 1, 'first'); | ||
1001 | if isempty(x_error_propagation) | 992 | if isempty(x_error_propagation) | ||
1002 | p_error_propagation(k) = 1e-20; %#ok<AGROW> | 993 | p_error_propagation(k) = 1e-20; %#ok<AGROW> | ||
1003 | else | 994 | else | ||
1004 | p_error_propagation(k) = sum(error_propagation_noise_pdf{k}.y(x_error_propagation:end)); %#ok<AGROW> | 995 | p_error_propagation(k) = sum(error_propagation_noise_pdf{k}.y(x_error_propagation:end)); %#ok<AGROW> | ||
1005 | end | 996 | end | ||
1006 | end | 997 | end | ||
1007 | 998 | ||||
1008 | % Assume an uncorrelated error will occur if the original noise exceeds | 999 | % Assume an uncorrelated error will occur if the original noise exceeds | ||
1009 | % the available signal reduced by pass_threhsold dB. Find the probability | 1000 | % the available signal reduced by pass_threhsold dB. Find the probability | ||
1010 | % of this event by partial sum of the PDF. | 1001 | % of this event by partial sum of the PDF. | ||
1011 | % p_uncorrelated_error_i = find(combined_interference_and_noise_pdf.x >= A_s./10^(param.pass_threshold/20), 1, 'first'); | 1002 | % p_uncorrelated_error_i = find(combined_interference_and_noise_pdf.x >= A_s./10^(param.pass_threshold/20), 1, 'first'); | ||
1012 | % p_uncorrelated_error = sum(combined_interference_and_noise_pdf.y(p_uncorrelated_error_i:end)); | 1003 | % p_uncorrelated_error = sum(combined_interference_and_noise_pdf.y(p_uncorrelated_error_i:end)); | ||
1013 | 1004 | ||||
1014 | % probability of bursts of different lengths | 1005 | % probability of bursts of different lengths | ||
1015 | p_burst = cumprod(p_error_propagation); | 1006 | p_burst = cumprod(p_error_propagation); | ||
1016 | function H_bw=Butterworth_Filter(param,f,use_BW) | 1007 | function H_bw=Butterworth_Filter(param,f,use_BW) | ||
1017 | 1008 | ||||
1018 | if use_BW | 1009 | if use_BW | ||
1019 | H_bw = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(param.fb_BW_cutoff*param.fb)); | 1010 | H_bw = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(param.fb_BW_cutoff*param.fb)); | ||
1020 | else | 1011 | else | ||
1021 | H_bw=ones(1,length(f)); | 1012 | H_bw=ones(1,length(f)); | ||
1022 | end | 1013 | end | ||
1023 | function [CDF_ev] = CDF_ev(val,PDF,CDF) | 1014 | function [CDF_ev] = CDF_ev(val,PDF,CDF) | ||
1024 | index=find(PDF.x >= -val,1,'first'); | 1015 | index=find(PDF.x >= -val,1,'first'); | ||
1025 | CDF_ev=CDF(index); | 1016 | CDF_ev=CDF(index); | ||
1026 | function [CDF_inv_ev] = CDF_inv_ev(val,PDF,CDF) | 1017 | function [CDF_inv_ev] = CDF_inv_ev(val,PDF,CDF) | ||
1027 | index=find(CDF >= val,1,'first'); | 1018 | index=find(CDF >= val,1,'first'); | ||
1028 | if isempty(index) | 1019 | if isempty(index) | ||
1029 | CDF_inv_ev=PDF.x(end); | 1020 | CDF_inv_ev=PDF.x(end); | ||
1030 | else | 1021 | else | ||
1031 | CDF_inv_ev=PDF.x(index); | 1022 | CDF_inv_ev=PDF.x(index); | ||
1032 | end | 1023 | end | ||
1033 | function [config_file,num_fext,num_next,Remember_keyword,OP,varargin]=COM_CommandLine_Parse(OP,varargin) | 1024 | function [config_file,num_fext,num_next,Remember_keyword,OP,varargin]=COM_CommandLine_Parse(OP,varargin) | ||
1034 | 1025 | ||||
1035 | 1026 | ||||
1036 | keywords={'Legacy' 'TD' 'Config2Mat'}; | 1027 | keywords={'Legacy' 'TD' 'Config2Mat'}; | ||
1037 | Remember_keyword='Legacy'; | 1028 | Remember_keyword='Legacy'; | ||
1038 | OP.TDMODE=false; | 1029 | OP.TDMODE=false; | ||
1039 | OP.GET_FD=true; | 1030 | OP.GET_FD=true; | ||
1040 | OP.CONFIG2MAT_ONLY=false; | 1031 | OP.CONFIG2MAT_ONLY=false; | ||
1041 | config_file=''; | 1032 | config_file=''; | ||
1042 | num_fext=[]; | 1033 | num_fext=[]; | ||
1043 | num_next=[]; | 1034 | num_next=[]; | ||
1044 | if ~isempty(varargin) | 1035 | if ~isempty(varargin) | ||
1045 | if ~ischar(varargin{1}) | 1036 | if ~ischar(varargin{1}) | ||
1046 | error('First input must be a string'); | 1037 | error('First input must be a string'); | ||
1047 | end | 1038 | end | ||
1048 | keyword_idx=find(strcmpi(keywords,varargin{1})); | 1039 | keyword_idx=find(strcmpi(keywords,varargin{1})); | ||
1049 | if isempty(keyword_idx) | 1040 | if isempty(keyword_idx) | ||
1050 | %Legacy Mode | 1041 | %Legacy Mode | ||
1051 | [config_file,varargin]=varargin_extractor(varargin{:}); | 1042 | [config_file,varargin]=varargin_extractor(varargin{:}); | ||
1052 | [num_fext,varargin]=varargin_extractor(varargin{:}); | 1043 | [num_fext,varargin]=varargin_extractor(varargin{:}); | ||
1053 | [num_next,varargin]=varargin_extractor(varargin{:}); | 1044 | [num_next,varargin]=varargin_extractor(varargin{:}); | ||
1054 | else | 1045 | else | ||
1055 | %Keyword Mode | 1046 | %Keyword Mode | ||
1056 | my_keyword=varargin{1}; | 1047 | my_keyword=varargin{1}; | ||
1057 | Remember_keyword=my_keyword; | 1048 | Remember_keyword=my_keyword; | ||
1058 | varargin(1)=[]; | 1049 | varargin(1)=[]; | ||
1059 | switch my_keyword | 1050 | switch my_keyword | ||
1060 |
| 1051 |
| ||
1061 | case 'Legacy' | 1052 | case 'Legacy' | ||
1062 | [config_file,varargin]=varargin_extractor(varargin{:}); | 1053 | [config_file,varargin]=varargin_extractor(varargin{:}); | ||
1063 | [num_fext,varargin]=varargin_extractor(varargin{:}); | 1054 | [num_fext,varargin]=varargin_extractor(varargin{:}); | ||
1064 | [num_next,varargin]=varargin_extractor(varargin{:}); | 1055 | [num_next,varargin]=varargin_extractor(varargin{:}); | ||
1065 | case 'TD' | 1056 | case 'TD' | ||
1066 | OP.TDMODE=true; | 1057 | OP.TDMODE=true; | ||
1067 | OP.GET_FD=false; | 1058 | OP.GET_FD=false; | ||
1068 | [config_file,varargin]=varargin_extractor(varargin{:}); | 1059 | [config_file,varargin]=varargin_extractor(varargin{:}); | ||
1069 | [num_fext,varargin]=varargin_extractor(varargin{:}); | 1060 | [num_fext,varargin]=varargin_extractor(varargin{:}); | ||
1070 | [num_next,varargin]=varargin_extractor(varargin{:}); | 1061 | [num_next,varargin]=varargin_extractor(varargin{:}); | ||
1071 | case 'Config2Mat' | 1062 | case 'Config2Mat' | ||
1072 | OP.CONFIG2MAT_ONLY=true; | 1063 | OP.CONFIG2MAT_ONLY=true; | ||
1073 | [config_file,varargin]=varargin_extractor(varargin{:}); | 1064 | [config_file,varargin]=varargin_extractor(varargin{:}); | ||
1074 | end | 1065 | end | ||
1075 | end | 1066 | end | ||
1076 | end | 1067 | end | ||
1077 | function chdata=COM_FD_to_TD(chdata,param,OP) | 1068 | function chdata=COM_FD_to_TD(chdata,param,OP) | ||
1078 | 1069 | ||||
1079 | % get impulse responses which in interim step between equation for X(f) and | 1070 | % get impulse responses which in interim step between equation for X(f) and | ||
1080 | % H^(k)(t) without TX FFE or CTLE. These will we added later. | 1071 | % H^(k)(t) without TX FFE or CTLE. These will we added later. | ||
1081 | case_number=param.package_testcase_i; | 1072 | case_number=param.package_testcase_i; | ||
1082 | for i=1:param.number_of_s4p_files | 1073 | for i=1:param.number_of_s4p_files | ||
1083 | % RIM 2-01-2023 moved to FD_Processing | 1074 | % RIM 2-01-2023 moved to FD_Processing | ||
1084 | % if OP.INCLUDE_FILTER % apply RX filtRaised_Cosine_Filterer | 1075 | % if OP.INCLUDE_FILTER % apply RX filtRaised_Cosine_Filterer | ||
1085 | % % Equation 93A-20 %% | 1076 | % % Equation 93A-20 %% | ||
1086 | % % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(i).faxis./(param.f_r*param.fb)); | 1077 | % % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(i).faxis./(param.f_r*param.fb)); | ||
1087 | % f=chdata(i).faxis; | 1078 | % f=chdata(i).faxis; | ||
1088 | % % | 1079 | % % | ||
1089 | % H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | 1080 | % H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | ||
1090 | % H_bw=Butterworth_Filter(param,f,OP.Butterworth); | 1081 | % H_bw=Butterworth_Filter(param,f,OP.Butterworth); | ||
1091 | % H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine); % conditionally include the RCos filter for all IR conversion using COM_FD_to_TD | 1082 | % H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine); % conditionally include the RCos filter for all IR conversion using COM_FD_to_TD | ||
1092 | % H_txffe= Tx_FFE_Filter(param,f,param.Pkg_TXFFE_preset); % RIM 08-18-2022 to add forced TX ffe per package case | 1083 | % H_txffe= Tx_FFE_Filter(param,f,param.Pkg_TXFFE_preset); % RIM 08-18-2022 to add forced TX ffe per package case | ||
1093 | % H_r=H_bw.*H_bt.*H_RCos.*H_txffe; % RIM 08-18-2022 to add forced TX ffe per package case | 1084 | % H_r=H_bw.*H_bt.*H_RCos.*H_txffe; % RIM 08-18-2022 to add forced TX ffe per package case | ||
1094 | % chdata(i).sdd21=chdata(i).sdd21.*H_r; | 1085 | % chdata(i).sdd21=chdata(i).sdd21.*H_r; | ||
1095 | % if OP.DISPLAY_WINDOW | 1086 | % if OP.DISPLAY_WINDOW | ||
1096 | % if i==1 | 1087 | % if i==1 | ||
1097 | % figure(300+param.package_testcase_i); | 1088 | % figure(300+param.package_testcase_i); | ||
1098 | % subplot(3,1,1) | 1089 | % subplot(3,1,1) | ||
1099 | % plot(chdata(i).faxis/1e9, 20*log10(abs(squeeze(chdata(i).sdd21))), 'k-','linewidth',2, 'Disp','VTF (no Tx/Rx eq)') | 1090 | % plot(chdata(i).faxis/1e9, 20*log10(abs(squeeze(chdata(i).sdd21))), 'k-','linewidth',2, 'Disp','VTF (no Tx/Rx eq)') | ||
1100 | % try | 1091 | % try | ||
1101 | % legend('NumColumns',2) | 1092 | % legend('NumColumns',2) | ||
1102 | % legend('location','south') | 1093 | % legend('location','south') | ||
1103 | % catch | 1094 | % catch | ||
1104 | % end | 1095 | % end | ||
1105 | % end | 1096 | % end | ||
1106 | % end | 1097 | % end | ||
1107 | % end | 1098 | % end | ||
1108 | [chdata(i).uneq_imp_response, ... | 1099 | [chdata(i).uneq_imp_response, ... | ||
1109 | chdata(i).t, ... | 1100 | chdata(i).t, ... | ||
1110 | chdata(i).causality_correction_dB, ... | 1101 | chdata(i).causality_correction_dB, ... | ||
1111 | chdata(i).truncation_dB] = s21_to_impulse_DC(chdata(i).sdd21 ,chdata(i).faxis, param.sample_dt, OP) ; | 1102 | chdata(i).truncation_dB] = s21_to_impulse_DC(chdata(i).sdd21 ,chdata(i).faxis, param.sample_dt, OP) ; | ||
1112 | if ~OP.RX_CALIBRATION || i==1 % DC (common to differentail model is not good used for RX_Calibrataion channel | 1103 | if ~OP.RX_CALIBRATION || i==1 % DC (common to differentail model is not good used for RX_Calibrataion channel | ||
1113 | chdata(i).uneq_imp_response=chdata(i).uneq_imp_response*chdata(i).A; % adjust IRx for amplitude | 1104 | chdata(i).uneq_imp_response=chdata(i).uneq_imp_response*chdata(i).A; % adjust IRx for amplitude | ||
1114 | [chdata(i).uneq_CD_imp_response, ... | 1105 | [chdata(i).uneq_CD_imp_response, ... | ||
1115 | chdata(i).t_DC, ... | 1106 | chdata(i).t_DC, ... | ||
1116 | chdata(i).causality_correction_DC_dB, ... | 1107 | chdata(i).causality_correction_DC_dB, ... | ||
1117 | chdata(i).truncation__DC_dB] = s21_to_impulse_DC(chdata(i).sdc21 ,chdata(i).faxis, param.sample_dt, OP) ; | 1108 | chdata(i).truncation__DC_dB] = s21_to_impulse_DC(chdata(i).sdc21 ,chdata(i).faxis, param.sample_dt, OP) ; | ||
1118 | end | 1109 | end | ||
1119 | % adjust voltage derive here once it's decided what to use | 1110 | % adjust voltage derive here once it's decided what to use | ||
1120 | %------------------------------------------------------------ | 1111 | %------------------------------------------------------------ | ||
1121 | % next find Pulse response (SBR) for each channel h^(k)(t) | 1112 | % next find Pulse response (SBR) for each channel h^(k)(t) | ||
1122 | if ~OP.DISPLAY_WINDOW && i==1, fprintf('processing COM PDF '); end | 1113 | if ~OP.DISPLAY_WINDOW && i==1, fprintf('processing COM PDF '); end | ||
1123 | 1114 | ||||
1124 | chdata(i).uneq_pulse_response=filter(ones(1, param.samples_per_ui), 1, chdata(i).uneq_imp_response); | 1115 | chdata(i).uneq_pulse_response=filter(ones(1, param.samples_per_ui), 1, chdata(i).uneq_imp_response); | ||
1125 | chdata(i).uneq_pulse_DC_response=filter(ones(1, param.samples_per_ui), 1, chdata(i).uneq_CD_imp_response); | 1116 | chdata(i).uneq_pulse_DC_response=filter(ones(1, param.samples_per_ui), 1, chdata(i).uneq_CD_imp_response); | ||
1126 | chdata(i).uneq_pulse_CD_response=chdata(i).uneq_pulse_DC_response*chdata(i).A; | 1117 | chdata(i).uneq_pulse_CD_response=chdata(i).uneq_pulse_DC_response*chdata(i).A; | ||
1127 | if 1 % not really CD but DC = DC if the channel already has a the Tx added | 1118 | if 1 % not really CD but DC = DC if the channel already has a the Tx added | ||
1128 | % really need to add eq to the DC responce to calc rss. This is a first pass estimate | 1119 | % really need to add eq to the DC responce to calc rss. This is a first pass estimate | ||
1129 | rss=-inf; | 1120 | rss=-inf; | ||
1130 | for im=1:param.samples_per_ui | 1121 | for im=1:param.samples_per_ui | ||
1131 | rss=max(rss, norm( chdata(i).uneq_pulse_CD_response(im:param.samples_per_ui:end))); | 1122 | rss=max(rss, norm( chdata(i).uneq_pulse_CD_response(im:param.samples_per_ui:end))); | ||
1132 | end | 1123 | end | ||
1133 | chdata(i).CD_CM_RMS=rss*sqrt(param.sigma_X); | 1124 | chdata(i).CD_CM_RMS=rss*sqrt(param.sigma_X); | ||
1134 | chdata(i).VCM_HF_struct= get_cm_noise(param.samples_per_ui,chdata(i).uneq_pulse_CD_response,param.levels,param.specBER); | 1125 | chdata(i).VCM_HF_struct= get_cm_noise(param.samples_per_ui,chdata(i).uneq_pulse_CD_response,param.levels,param.specBER); | ||
1135 | chdata(i).SCMR=10*log10(max(chdata(1).uneq_pulse_response)^2/chdata(i).VCM_HF_struct.DCn^2); | 1126 | chdata(i).SCMR=10*log10(max(chdata(1).uneq_pulse_response)^2/chdata(i).VCM_HF_struct.DCn^2); | ||
1136 | end | 1127 | end | ||
1137 | if OP.DEBUG && OP.DISPLAY_WINDOW | 1128 | if OP.DEBUG && OP.DISPLAY_WINDOW | ||
1138 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | 1129 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | ||
1139 | figure(150+case_number);set(gcf,'Tag','COM'); | 1130 | figure(150+case_number);set(gcf,'Tag','COM'); | ||
1140 | screen_size=get(0,'ScreenSize'); | 1131 | screen_size=get(0,'ScreenSize'); | ||
1141 | pos = get(gcf, 'OuterPosition'); | 1132 | pos = get(gcf, 'OuterPosition'); | ||
1142 | set(gcf, 'OuterPosition', ... | 1133 | set(gcf, 'OuterPosition', ... | ||
1143 | screen_size([3 4 3 4]).*[1 1 0 0] + pos([3 4 3 4]).*[-1 -1 1 1] ... | 1134 | screen_size([3 4 3 4]).*[1 1 0 0] + pos([3 4 3 4]).*[-1 -1 1 1] ... | ||
1144 | - (case_number-1)*[0 20 0 0]); | 1135 | - (case_number-1)*[0 20 0 0]); | ||
1145 | %movegui(gcf,'northeast') | 1136 | %movegui(gcf,'northeast') | ||
1146 | 1137 | ||||
1147 | set(gcf, 'Name', sprintf('Case %d PR & PDF - %s', case_number, chdata(i).base)); | 1138 | set(gcf, 'Name', sprintf('Case %d PR & PDF - %s', case_number, chdata(i).base)); | ||
1148 | subplot(2,1,1); hold on; % all plots on the same axes | 1139 | subplot(2,1,1); hold on; % all plots on the same axes | ||
1149 | hp=plot(chdata(i).t, chdata(i).uneq_pulse_response,'Disp', chdata(i).base); | 1140 | hp=plot(chdata(i).t, chdata(i).uneq_pulse_response,'Disp', chdata(i).base); | ||
1150 | hold on; % leave on for s-parameter problem finding. RIM 10-02-2023 | 1141 | hold on; % leave on for s-parameter problem finding. RIM 10-02-2023 | ||
1151 | hp1=plot(chdata(i).t_DC, chdata(i).uneq_pulse_CD_response,'Disp', [ 'CD ' chdata(i).base ]) ; | 1142 | hp1=plot(chdata(i).t_DC, chdata(i).uneq_pulse_CD_response,'Disp', [ 'CD ' chdata(i).base ]) ; | ||
1152 | end | 1143 | end | ||
1153 | % hide thru PR in order to show xtalk in a reasonable | 1144 | % hide thru PR in order to show xtalk in a reasonable | ||
1154 | % scale. thru is shown in another plot. | 1145 | % scale. thru is shown in another plot. | ||
1155 | if isequal(chdata(i).type, 'THRU' ) && ~OP.RX_CALIBRATION %|| OP.RX_CALIBRATION % RIM 06-14-2022 | 1146 | if isequal(chdata(i).type, 'THRU' ) && ~OP.RX_CALIBRATION %|| OP.RX_CALIBRATION % RIM 06-14-2022 | ||
1156 | % set(hp, 'visible', 'off'); | 1147 | % set(hp, 'visible', 'off'); | ||
1157 | % set(get(get(hp,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | 1148 | % set(get(get(hp,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | ||
1158 | end | 1149 | end | ||
1159 | title(sprintf('Unequalized Crosstalk and CD Conversion \n Pulse Responses')) | 1150 | title(sprintf('Unequalized Crosstalk and CD Conversion \n Pulse Responses')) | ||
1160 | ylabel('Volts') | 1151 | ylabel('Volts') | ||
1161 | xlabel('seconds') | 1152 | xlabel('seconds') | ||
1162 | 1153 | ||||
1163 | recolor_plots(gca); | 1154 | recolor_plots(gca); | ||
1164 | else | 1155 | else | ||
1165 | if param.ndfe~=0 | 1156 | if param.ndfe~=0 | ||
1166 | fprintf('%s\tUnequalized pulse peak = %.1f mV\n', chdata(i).base, 1000*max(abs(chdata(i).uneq_pulse_response))); | 1157 | fprintf('%s\tUnequalized pulse peak = %.1f mV\n', chdata(i).base, 1000*max(abs(chdata(i).uneq_pulse_response))); | ||
1167 | end | 1158 | end | ||
1168 | end | 1159 | end | ||
1169 | 1160 | ||||
1170 | fprintf('%s\tCausality correction = %.1f dB', chdata(i).base, chdata(i).causality_correction_dB); | 1161 | fprintf('%s\tCausality correction = %.1f dB', chdata(i).base, chdata(i).causality_correction_dB); | ||
1171 | if OP.ENFORCE_CAUSALITY | 1162 | if OP.ENFORCE_CAUSALITY | ||
1172 | fprintf('\n'); | 1163 | fprintf('\n'); | ||
1173 | else | 1164 | else | ||
1174 | fprintf(' (not applied)\n'); | 1165 | fprintf(' (not applied)\n'); | ||
1175 | end | 1166 | end | ||
1176 | fprintf('%s\tTruncation ratio = %.1f dB\n', chdata(i).base, chdata(i).truncation_dB); | 1167 | fprintf('%s\tTruncation ratio = %.1f dB\n', chdata(i).base, chdata(i).truncation_dB); | ||
1177 | 1168 | ||||
1178 | end | 1169 | end | ||
1179 | function [Left_EW,Right_EW,eye_contour,out_VT,out_VB]=COM_eye_width(chdata,delta_y,fom_result,param,OP,Struct_Noise,pdf_range_flag) | 1170 | function [Left_EW,Right_EW,eye_contour,out_VT,out_VB]=COM_eye_width(chdata,delta_y,fom_result,param,OP,Struct_Noise,pdf_range_flag) | ||
1180 | 1171 | ||||
1181 | 1172 | ||||
1182 | debug_plot=0; | 1173 | debug_plot=0; | ||
1183 | 1174 | ||||
1184 | 1175 | ||||
1185 | samp_UI=param.samples_for_C2M; | 1176 | samp_UI=param.samples_for_C2M; | ||
1186 | half_UI=get_center_of_UI(samp_UI); | 1177 | half_UI=get_center_of_UI(samp_UI); | ||
1187 | T_O=floor((param.T_O/1000)*param.samples_for_C2M); | 1178 | T_O=floor((param.T_O/1000)*param.samples_for_C2M); | ||
1188 | start_sample=half_UI-T_O; | 1179 | start_sample=half_UI-T_O; | ||
1189 | end_sample=half_UI+T_O; | 1180 | end_sample=half_UI+T_O; | ||
1190 | 1181 | ||||
1191 | 1182 | ||||
1192 | %pdf_range is a placeholder to allow fractional UI calculation for optimize | 1183 | %pdf_range is a placeholder to allow fractional UI calculation for optimize | ||
1193 | %C2M speedup. For regular COM_eye_width calls, pdf_range will be empty | 1184 | %C2M speedup. For regular COM_eye_width calls, pdf_range will be empty | ||
1194 | %which will force pdf_range=1:samp_UI for stanard full UI calculation. | 1185 | %which will force pdf_range=1:samp_UI for stanard full UI calculation. | ||
1195 | if pdf_range_flag | 1186 | if pdf_range_flag | ||
1196 | pdf_range=[start_sample end_sample]; | 1187 | pdf_range=[start_sample end_sample]; | ||
1197 | else | 1188 | else | ||
1198 | pdf_range=[]; | 1189 | pdf_range=[]; | ||
1199 | end | 1190 | end | ||
1200 | 1191 | ||||
1201 | %pdf_full is self ISI pdf for each sample point | 1192 | %pdf_full is self ISI pdf for each sample point | ||
1202 | %h_j_full is the v/t calculation for each sample point | 1193 | %h_j_full is the v/t calculation for each sample point | ||
1203 | %the center vector for each should be identical to the standard COM variables | 1194 | %the center vector for each should be identical to the standard COM variables | ||
1204 | [pdf_full_1,h_j_full,A_s_vec] = get_pdf_full(chdata(1), delta_y, fom_result.t_s, param, OP,pdf_range) ; | 1195 | [pdf_full_1,h_j_full,A_s_vec] = get_pdf_full(chdata(1), delta_y, fom_result.t_s, param, OP,pdf_range) ; | ||
1205 | 1196 | ||||
1206 | 1197 | ||||
1207 | 1198 | ||||
1208 | if isempty(pdf_range) | 1199 | if isempty(pdf_range) | ||
1209 | pdf_range=1:samp_UI; | 1200 | pdf_range=1:samp_UI; | ||
1210 | else | 1201 | else | ||
1211 | pdf_range=min(pdf_range):max(pdf_range); | 1202 | pdf_range=min(pdf_range):max(pdf_range); | ||
1212 | end | 1203 | end | ||
1213 | 1204 | ||||
1214 | %Test doing Level PDFs | 1205 | %Test doing Level PDFs | ||
1215 | Levels = 2*(0:param.levels-1)/(param.levels-1)-1; | 1206 | Levels = 2*(0:param.levels-1)/(param.levels-1)-1; | ||
1216 | %A_s_vec=A_s_vec*(param.levels-1)/param.R_LM; | 1207 | %A_s_vec=A_s_vec*(param.levels-1)/param.R_LM; | ||
1217 | A_s_vec=A_s_vec*(param.levels-1); | 1208 | A_s_vec=A_s_vec*(param.levels-1); | ||
1218 | 1209 | ||||
1219 | %add signal vector into pdf | 1210 | %add signal vector into pdf | ||
1220 | for n=1:param.levels | 1211 | for n=1:param.levels | ||
1221 | pdf_full{n}=pdf_full_1; | 1212 | pdf_full{n}=pdf_full_1; | ||
1222 | for j=pdf_range | 1213 | for j=pdf_range | ||
1223 | pdf_full{n}(j).x=pdf_full{n}(j).x+A_s_vec(j)*Levels(n); | 1214 | pdf_full{n}(j).x=pdf_full{n}(j).x+A_s_vec(j)*Levels(n); | ||
1224 | pdf_full{n}(j).Min=pdf_full{n}(j).x(1)/pdf_full{n}(j).BinSize; | 1215 | pdf_full{n}(j).Min=pdf_full{n}(j).x(1)/pdf_full{n}(j).BinSize; | ||
1225 | end | 1216 | end | ||
1226 | end | 1217 | end | ||
1227 | 1218 | ||||
1228 | 1219 | ||||
1229 | % figure; | 1220 | % figure; | ||
1230 | % hold on; | 1221 | % hold on; | ||
1231 | %This loop builds the same PDF/CDF structures from regular COM, but it is | 1222 | %This loop builds the same PDF/CDF structures from regular COM, but it is | ||
1232 | %computed for every sample point | 1223 | %computed for every sample point | ||
1233 | for n=1:param.levels | 1224 | for n=1:param.levels | ||
1234 | for j=pdf_range | 1225 | for j=pdf_range | ||
1235 | sigma_G_full(j) = norm([param.sigma_RJ*param.sigma_X*norm(h_j_full(:,j)), Struct_Noise.sigma_N, Struct_Noise.sigma_TX]); | 1226 | sigma_G_full(j) = norm([param.sigma_RJ*param.sigma_X*norm(h_j_full(:,j)), Struct_Noise.sigma_N, Struct_Noise.sigma_TX]); | ||
1236 | gaussian_noise_pdf_full(j) = normal_dist(sigma_G_full(j), Struct_Noise.ber_q, delta_y); | 1227 | gaussian_noise_pdf_full(j) = normal_dist(sigma_G_full(j), Struct_Noise.ber_q, delta_y); | ||
1237 | gaussian_noise_pdf_full(j) = conv_fct(gaussian_noise_pdf_full(j), Struct_Noise.ne_noise_pdf); | 1228 | gaussian_noise_pdf_full(j) = conv_fct(gaussian_noise_pdf_full(j), Struct_Noise.ne_noise_pdf); | ||
1238 | p_DD_full(j) = get_pdf_from_sampled_signal(param.A_DD*h_j_full(:,j), param.levels, delta_y); | 1229 | p_DD_full(j) = get_pdf_from_sampled_signal(param.A_DD*h_j_full(:,j), param.levels, delta_y); | ||
1239 | noise_pdf_full(j)=conv_fct(gaussian_noise_pdf_full(j), p_DD_full(j)); | 1230 | noise_pdf_full(j)=conv_fct(gaussian_noise_pdf_full(j), p_DD_full(j)); | ||
1240 | isi_and_xtalk_pdf_full(j) = conv_fct_MeanNotZero(pdf_full{n}(j), Struct_Noise.cci_pdf); | 1231 | isi_and_xtalk_pdf_full(j) = conv_fct_MeanNotZero(pdf_full{n}(j), Struct_Noise.cci_pdf); | ||
1241 | % change from adam gregory to include crosstalk | 1232 | % change from adam gregory to include crosstalk | ||
1242 | % combined_interference_and_noise_pdf_full = conv_fct(pdf_full(j), noise_pdf_full(j)); | 1233 | % combined_interference_and_noise_pdf_full = conv_fct(pdf_full(j), noise_pdf_full(j)); | ||
1243 | combined_interference_and_noise_pdf_full{n}(j) = conv_fct_MeanNotZero(isi_and_xtalk_pdf_full(j), noise_pdf_full(j)); | 1234 | combined_interference_and_noise_pdf_full{n}(j) = conv_fct_MeanNotZero(isi_and_xtalk_pdf_full(j), noise_pdf_full(j)); | ||
1244 |
| 1235 |
| ||
1245 | %PDF to CDF | 1236 | %PDF to CDF | ||
1246 | combined_interference_and_noise_cdf_full{n}(j)=pdf_to_cdf(combined_interference_and_noise_pdf_full{n}(j)); | 1237 | combined_interference_and_noise_cdf_full{n}(j)=pdf_to_cdf(combined_interference_and_noise_pdf_full{n}(j)); | ||
1247 |
| 1238 |
| ||
1248 | end | 1239 | end | ||
1249 | end | 1240 | end | ||
1250 | %hold off; | 1241 | %hold off; | ||
1251 | 1242 | ||||
1252 | 1243 | ||||
1253 | %For the given BER, find the top & bottom voltage level in the CDF | 1244 | %For the given BER, find the top & bottom voltage level in the CDF | ||
1254 | for n=1:param.levels | 1245 | for n=1:param.levels | ||
1255 | A_ni_bottom{n}=zeros(1,samp_UI); | 1246 | A_ni_bottom{n}=zeros(1,samp_UI); | ||
1256 | A_ni_top{n}=zeros(1,samp_UI); | 1247 | A_ni_top{n}=zeros(1,samp_UI); | ||
1257 | for j=pdf_range | 1248 | for j=pdf_range | ||
1258 | [A_ni_top{n}(j),A_ni_bottom{n}(j)]=cdf_to_ber_contour(combined_interference_and_noise_cdf_full{n}(j),param.specBER); | 1249 | [A_ni_top{n}(j),A_ni_bottom{n}(j)]=cdf_to_ber_contour(combined_interference_and_noise_cdf_full{n}(j),param.specBER); | ||
1259 | end | 1250 | end | ||
1260 | end | 1251 | end | ||
1261 | %plot(1:samp_UI,cursor_vector-A_ni_top,1:samp_UI,-cursor_vector+A_ni_bottom) | 1252 | %plot(1:samp_UI,cursor_vector-A_ni_top,1:samp_UI,-cursor_vector+A_ni_bottom) | ||
1262 | 1253 | ||||
1263 | for n=1:param.levels-1 | 1254 | for n=1:param.levels-1 | ||
1264 | eye_contour{n}(:,1)=A_ni_top{n+1}; | 1255 | eye_contour{n}(:,1)=A_ni_top{n+1}; | ||
1265 | eye_contour{n}(:,2)=A_ni_bottom{n}; | 1256 | eye_contour{n}(:,2)=A_ni_bottom{n}; | ||
1266 | end | 1257 | end | ||
1267 | 1258 | ||||
1268 | 1259 | ||||
1269 | for n=1:param.levels-1 | 1260 | for n=1:param.levels-1 | ||
1270 | %eye_contour holds the top eye in the 1st column & bottom eye in the 2nd column | 1261 | %eye_contour holds the top eye in the 1st column & bottom eye in the 2nd column | ||
1271 | %define vref as middle of top eye height and bottom eye height. Now | 1262 | %define vref as middle of top eye height and bottom eye height. Now | ||
1272 | %that all eyes are created, vref is non-zero except for middle eye | 1263 | %that all eyes are created, vref is non-zero except for middle eye | ||
1273 | EH_top=eye_contour{n}(half_UI,1); | 1264 | EH_top=eye_contour{n}(half_UI,1); | ||
1274 | EH_bot=eye_contour{n}(half_UI,2); | 1265 | EH_bot=eye_contour{n}(half_UI,2); | ||
1275 | EH=EH_top-EH_bot; | 1266 | EH=EH_top-EH_bot; | ||
1276 | vref=EH_top/2+EH_bot/2; | 1267 | vref=EH_top/2+EH_bot/2; | ||
1277 | %This function finds left/right eye width by finding the vref crossings of | 1268 | %This function finds left/right eye width by finding the vref crossings of | ||
1278 | %the top and bottom eye contours | 1269 | %the top and bottom eye contours | ||
1279 | [Left_EW(n),Right_EW(n)]=find_eye_width(eye_contour{n},half_UI,samp_UI,vref); | 1270 | [Left_EW(n),Right_EW(n)]=find_eye_width(eye_contour{n},half_UI,samp_UI,vref); | ||
1280 | end | 1271 | end | ||
1281 | 1272 | ||||
1282 | %For reporting to .csv, need eye contour to be a matrix instead of cell | 1273 | %For reporting to .csv, need eye contour to be a matrix instead of cell | ||
1283 | eye_contour_tmp=eye_contour; | 1274 | eye_contour_tmp=eye_contour; | ||
1284 | eye_contour=[]; | 1275 | eye_contour=[]; | ||
1285 | for n=1:param.levels-1 | 1276 | for n=1:param.levels-1 | ||
1286 | eye_contour(:,(n-1)*2+1:n*2)=eye_contour_tmp{n}; | 1277 | eye_contour(:,(n-1)*2+1:n*2)=eye_contour_tmp{n}; | ||
1287 | end | 1278 | end | ||
1288 | 1279 | ||||
1289 | 1280 | ||||
1290 | %Find VEC eye height | 1281 | %Find VEC eye height | ||
1291 | out_VT=[]; | 1282 | out_VT=[]; | ||
1292 | out_VB=[]; | 1283 | out_VB=[]; | ||
1293 | if param.T_O ~=0 | 1284 | if param.T_O ~=0 | ||
1294 |
| 1285 |
| ||
1295 | switch lower(OP.Histogram_Window_Weight) | 1286 | switch lower(OP.Histogram_Window_Weight) | ||
1296 | case {'gaussian' 'norm' 'normal' 'guassian'} | 1287 | case {'gaussian' 'norm' 'normal' 'guassian'} | ||
1297 | %build a gaussian window of weights that are multiplied by each pdf in the T_O range | 1288 | %build a gaussian window of weights that are multiplied by each pdf in the T_O range | ||
1298 | %Sigma = T_O/QL. Default QL=2.5. This gives a nice descent to near 0 at the edge of the window | 1289 | %Sigma = T_O/QL. Default QL=2.5. This gives a nice descent to near 0 at the edge of the window | ||
1299 | QL_sigma=T_O/param.QL; | 1290 | QL_sigma=T_O/param.QL; | ||
1300 | weights=exp(-1/2 * ([-T_O:T_O]/QL_sigma).^2); | 1291 | weights=exp(-1/2 * ([-T_O:T_O]/QL_sigma).^2); | ||
1301 | case 'triangle' | 1292 | case 'triangle' | ||
1302 | %triangle window. linear slope from 0 to 1 and back down to 0 | 1293 | %triangle window. linear slope from 0 to 1 and back down to 0 | ||
1303 | %for the weights | 1294 | %for the weights | ||
1304 | t_slope=1/(T_O); | 1295 | t_slope=1/(T_O); | ||
1305 | weights=[0:t_slope:1 1-t_slope:-t_slope:0]; | 1296 | weights=[0:t_slope:1 1-t_slope:-t_slope:0]; | ||
1306 | case 'rectangle' | 1297 | case 'rectangle' | ||
1307 | %default = rectangle. all weights = 1 | 1298 | %default = rectangle. all weights = 1 | ||
1308 | weights(1:2*T_O+1)=1; | 1299 | weights(1:2*T_O+1)=1; | ||
1309 | case 'dual_rayleigh' | 1300 | case 'dual_rayleigh' | ||
1310 | QL_sigma=T_O/param.QL; | 1301 | QL_sigma=T_O/param.QL; | ||
1311 | X=-T_O:T_O; | 1302 | X=-T_O:T_O; | ||
1312 | weights=(X+T_O)/QL_sigma^2.*exp(-1/2 * ((X+T_O)/QL_sigma).^2)... | 1303 | weights=(X+T_O)/QL_sigma^2.*exp(-1/2 * ((X+T_O)/QL_sigma).^2)... | ||
1313 | -(X-T_O)/QL_sigma^2.*exp(-1/2 * ((X-T_O)/QL_sigma).^2); | 1304 | -(X-T_O)/QL_sigma^2.*exp(-1/2 * ((X-T_O)/QL_sigma).^2); | ||
1314 | weights=weights/max(weights); | 1305 | weights=weights/max(weights); | ||
1315 | otherwise | 1306 | otherwise | ||
1316 | error('%s not recognized for Histogram_Window_Weight',OP.Histogram_Window_Weight) | 1307 | error('%s not recognized for Histogram_Window_Weight',OP.Histogram_Window_Weight) | ||
1317 | end | 1308 | end | ||
1318 | 1309 | ||||
1319 | for n=1:param.levels | 1310 | for n=1:param.levels | ||
1320 | out_pdf{n}=[]; | 1311 | out_pdf{n}=[]; | ||
1321 | for j=start_sample:end_sample | 1312 | for j=start_sample:end_sample | ||
1322 | target_pdf=combined_interference_and_noise_pdf_full{n}(j); | 1313 | target_pdf=combined_interference_and_noise_pdf_full{n}(j); | ||
1323 | target_pdf.y=target_pdf.y*weights(j-start_sample+1); | 1314 | target_pdf.y=target_pdf.y*weights(j-start_sample+1); | ||
1324 | if isempty(out_pdf{n}) | 1315 | if isempty(out_pdf{n}) | ||
1325 | out_pdf{n}=target_pdf; | 1316 | out_pdf{n}=target_pdf; | ||
1326 | else | 1317 | else | ||
1327 | out_pdf{n} = combine_pdf_same_voltage_axis(out_pdf{n}, target_pdf); | 1318 | out_pdf{n} = combine_pdf_same_voltage_axis(out_pdf{n}, target_pdf); | ||
1328 | end | 1319 | end | ||
1329 | end | 1320 | end | ||
1330 | out_pdf{n}.y=out_pdf{n}.y/sum(out_pdf{n}.y); | 1321 | out_pdf{n}.y=out_pdf{n}.y/sum(out_pdf{n}.y); | ||
1331 | end | 1322 | end | ||
1332 |
| 1323 |
| ||
1333 | for n=1:param.levels | 1324 | for n=1:param.levels | ||
1334 | out_cdf{n}=pdf_to_cdf(out_pdf{n}); | 1325 | out_cdf{n}=pdf_to_cdf(out_pdf{n}); | ||
1335 | end | 1326 | end | ||
1336 |
| 1327 |
| ||
1337 | for n=1:param.levels | 1328 | for n=1:param.levels | ||
1338 | [A_ni_top_O(n),A_ni_bottom_O(n)]=cdf_to_ber_contour(out_cdf{n},param.specBER); | 1329 | [A_ni_top_O(n),A_ni_bottom_O(n)]=cdf_to_ber_contour(out_cdf{n},param.specBER); | ||
1339 | end | 1330 | end | ||
1340 |
| 1331 |
| ||
1341 | for n=1:param.levels-1 | 1332 | for n=1:param.levels-1 | ||
1342 | OUT_VT_L(n,1)=A_ni_top_O(n+1); | 1333 | OUT_VT_L(n,1)=A_ni_top_O(n+1); | ||
1343 | OUT_VT_L(n,2)=A_ni_bottom_O(n); | 1334 | OUT_VT_L(n,2)=A_ni_bottom_O(n); | ||
1344 | end | 1335 | end | ||
1345 |
| 1336 |
| ||
1346 | %Report the top/bottom eye height of the worst eye | 1337 | %Report the top/bottom eye height of the worst eye | ||
1347 | EH_VT=OUT_VT_L(:,1)-OUT_VT_L(:,2); | 1338 | EH_VT=OUT_VT_L(:,1)-OUT_VT_L(:,2); | ||
1348 | [mineh,min_idx]=min(EH_VT); | 1339 | [mineh,min_idx]=min(EH_VT); | ||
1349 | out_VT=OUT_VT_L(min_idx,1); | 1340 | out_VT=OUT_VT_L(min_idx,1); | ||
1350 | out_VB=OUT_VT_L(min_idx,2); | 1341 | out_VB=OUT_VT_L(min_idx,2); | ||
1351 |
| 1342 |
| ||
1352 | % CDF_Mean=mean(A_s_vec(start_sample:end_sample)); | 1343 | % CDF_Mean=mean(A_s_vec(start_sample:end_sample)); | ||
1353 | % out_VT=2*CDF_Mean-A_ni_top_O; | 1344 | % out_VT=2*CDF_Mean-A_ni_top_O; | ||
1354 | % out_VB=-1*A_ni_bottom_O; | 1345 | % out_VB=-1*A_ni_bottom_O; | ||
1355 |
| 1346 |
| ||
1356 | if debug_plot | 1347 | if debug_plot | ||
1357 | figure; | 1348 | figure; | ||
1358 | hold on; | 1349 | hold on; | ||
1359 | for j=start_sample:end_sample | 1350 | for j=start_sample:end_sample | ||
1360 | plot(combined_interference_and_noise_pdf_full(j).x,combined_interference_and_noise_pdf_full(j).y); | 1351 | plot(combined_interference_and_noise_pdf_full(j).x,combined_interference_and_noise_pdf_full(j).y); | ||
1361 | end | 1352 | end | ||
1362 | plot(out_pdf.x,out_pdf.y,'color','k','LineWidth',2); | 1353 | plot(out_pdf.x,out_pdf.y,'color','k','LineWidth',2); | ||
1363 | hold off; | 1354 | hold off; | ||
1364 | end | 1355 | end | ||
1365 | end | 1356 | end | ||
1366 | 1357 | ||||
1367 | 1358 | ||||
1368 | 1359 | ||||
1369 | 1360 | ||||
1370 | function [PDF,CDF,NS]=Create_Noise_PDF(A_s,param,fom_result,chdata,OP,sigma_bn,PSD_results) | 1361 | function [PDF,CDF,NS]=Create_Noise_PDF(A_s,param,fom_result,chdata,OP,sigma_bn,PSD_results) | ||
1371 | 1362 | ||||
1372 | %This block was originally in main COM function but was moved here for | 1363 | %This block was originally in main COM function but was moved here for | ||
1373 | %cleanup. It returns the combined interference and noise PDF & CDF as well | 1364 | %cleanup. It returns the combined interference and noise PDF & CDF as well | ||
1374 | %as a structure "NS" that contains all the noise parameters that are used | 1365 | %as a structure "NS" that contains all the noise parameters that are used | ||
1375 | %in other places in COM | 1366 | %in other places in COM | ||
1376 | 1367 | ||||
1377 | if OP.RX_CALIBRATION | 1368 | if OP.RX_CALIBRATION | ||
1378 | ctle_gain2 = (10.^(param.ctle_gdc_values(fom_result.ctle)/20) + 1i*chdata(2).faxis/param.CTLE_fz(fom_result.ctle)) ./ ... | 1369 | ctle_gain2 = (10.^(param.ctle_gdc_values(fom_result.ctle)/20) + 1i*chdata(2).faxis/param.CTLE_fz(fom_result.ctle)) ./ ... | ||
1379 | ((1+1i*chdata(2).faxis/param.CTLE_fp1(fom_result.ctle)).*(1+1i*chdata(2).faxis/param.CTLE_fp2(fom_result.ctle))); | 1370 | ((1+1i*chdata(2).faxis/param.CTLE_fp1(fom_result.ctle)).*(1+1i*chdata(2).faxis/param.CTLE_fp2(fom_result.ctle))); | ||
1380 | switch param.CTLE_type | 1371 | switch param.CTLE_type | ||
1381 | case 'CL93' | 1372 | case 'CL93' | ||
1382 | H_low2=1; | 1373 | H_low2=1; | ||
1383 | case 'CL120d' % this clause uses two gain indexes | 1374 | case 'CL120d' % this clause uses two gain indexes | ||
1384 | H_low2=(10.^(param.g_DC_HP_values(fom_result.best_G_high_pass)/20) + 1i*chdata(2).faxis/param.f_HP(fom_result.best_G_high_pass))./(1 + 1i*chdata(2).faxis/param.f_HP(fom_result.best_G_high_pass)); | 1375 | H_low2=(10.^(param.g_DC_HP_values(fom_result.best_G_high_pass)/20) + 1i*chdata(2).faxis/param.f_HP(fom_result.best_G_high_pass))./(1 + 1i*chdata(2).faxis/param.f_HP(fom_result.best_G_high_pass)); | ||
1385 | case 'CL120e' % Z1 has been adjusted | 1376 | case 'CL120e' % Z1 has been adjusted | ||
1386 | H_low2=(1 + 1i*chdata(2).faxis/f_HP_P(fom_result.ctle))./(1 + 1i*chdata(2).faxis/f_HP_Z(fom_result.ctle)); | 1377 | H_low2=(1 + 1i*chdata(2).faxis/f_HP_P(fom_result.ctle))./(1 + 1i*chdata(2).faxis/f_HP_Z(fom_result.ctle)); | ||
1387 | end | 1378 | end | ||
1388 | H_ctf2=H_low2.*ctle_gain2; | 1379 | H_ctf2=H_low2.*ctle_gain2; | ||
1389 | [ sigma_ne, NS.sigma_hp] = get_sigma_noise( H_ctf2, param, chdata, sigma_bn ); | 1380 | [ sigma_ne, NS.sigma_hp] = get_sigma_noise( H_ctf2, param, chdata, sigma_bn ); | ||
1390 | else | 1381 | else | ||
1391 | sigma_ne=0; | 1382 | sigma_ne=0; | ||
1392 | end | 1383 | end | ||
1393 | 1384 | ||||
1394 | NS.sigma_N = fom_result.sigma_N; % eta zero noise | 1385 | NS.sigma_N = fom_result.sigma_N; % eta zero noise | ||
1395 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 1386 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
1396 | if ~OP.SNR_TXwC0 | 1387 | if ~OP.SNR_TXwC0 | ||
1397 | % Equation 93A-30 %% h0(ts0)= A_s*R_lm/(L-1) | 1388 | % Equation 93A-30 %% h0(ts0)= A_s*R_lm/(L-1) | ||
1398 | NS.sigma_TX = (param.levels-1)*A_s/param.R_LM*10^(-param.SNR_TX/20); % SNR_Tx and RLM | 1389 | NS.sigma_TX = (param.levels-1)*A_s/param.R_LM*10^(-param.SNR_TX/20); % SNR_Tx and RLM | ||
1399 | else | 1390 | else | ||
1400 | NS.sigma_TX = (param.levels-1)*A_s/fom_result.txffe(fom_result.cur) /param.R_LM*10^(-param.SNR_TX/20); % SNR_Tx from Adee | 1391 | NS.sigma_TX = (param.levels-1)*A_s/fom_result.txffe(fom_result.cur) /param.R_LM*10^(-param.SNR_TX/20); % SNR_Tx from Adee | ||
1401 | end | 1392 | end | ||
− | 1402 | NS.sigma_G = norm([param.sigma_RJ*param.sigma_X*norm(fom_result.h_J), NS.sigma_N, NS.sigma_TX]); |
| ||
1403 | NS.sigma_rjit= param.sigma_RJ*param.sigma_X*norm(fom_result.h_J); | ||||
1404 | else | 1393 | else | ||
≠ | 1405 | NS.sigma_TX =PSD_results.S_tn_rms; | ≠ | 1394 | NS.sigma_TX =PSD_results.tn_rms; |
− | 1406 | NS.sigma_G = PSD_results.S_G_rms; |
| ||
1407 | NS.sigma_rjit=PSD_results.S_rj_rms ; | ||||
1408 | NS.sigma_N=PSD_results.S_rn_rms ; % Commit request 4p4_8, healey_3dj_COM_01_240416 | ||||
1409 | end | 1395 | end | ||
1410 | % Equation 93A-41 %% | 1396 | % Equation 93A-41 %% | ||
− | 1411 |
| |||
| + | 1397 | NS.sigma_G = norm([param.sigma_RJ*param.sigma_X*norm(fom_result.h_J), NS.sigma_N, NS.sigma_TX]); | ||
1398 | NS.sigma_rjit= param.sigma_RJ*param.sigma_X*norm(fom_result.h_J); | ||||
1412 | 1399 | ||||
1413 | % Equation 93A-42 %% | 1400 | % Equation 93A-42 %% | ||
1414 | % number of sigmas needed depends on the required BER. | 1401 | % number of sigmas needed depends on the required BER. | ||
1415 | if param.Noise_Crest_Factor == 0 | 1402 | if param.Noise_Crest_Factor == 0 | ||
1416 | NS.ber_q = sqrt(2)*erfcinv(2*param.specBER); | 1403 | NS.ber_q = sqrt(2)*erfcinv(2*param.specBER); | ||
1417 | else | 1404 | else | ||
1418 | NS.ber_q=param.Noise_Crest_Factor; | 1405 | NS.ber_q=param.Noise_Crest_Factor; | ||
1419 | end | 1406 | end | ||
1420 | NS.gaussian_noise_pdf = normal_dist(NS.sigma_G, NS.ber_q, param.delta_y); | 1407 | NS.gaussian_noise_pdf = normal_dist(NS.sigma_G, NS.ber_q, param.delta_y); | ||
1421 | % enable overriding the Q factor of the BBN instrument. | 1408 | % enable overriding the Q factor of the BBN instrument. | ||
1422 | if OP.force_BBN_Q_factor | 1409 | if OP.force_BBN_Q_factor | ||
1423 | NS.ne_noise_pdf = normal_dist(sigma_ne, OP.BBN_Q_factor, param.delta_y); | 1410 | NS.ne_noise_pdf = normal_dist(sigma_ne, OP.BBN_Q_factor, param.delta_y); | ||
1424 | else | 1411 | else | ||
1425 | NS.ne_noise_pdf = normal_dist(sigma_ne, NS.ber_q, param.delta_y); | 1412 | NS.ne_noise_pdf = normal_dist(sigma_ne, NS.ber_q, param.delta_y); | ||
1426 | end | 1413 | end | ||
1427 | NS.gaussian_noise_pdf = conv_fct(NS.gaussian_noise_pdf, NS.ne_noise_pdf); | 1414 | NS.gaussian_noise_pdf = conv_fct(NS.gaussian_noise_pdf, NS.ne_noise_pdf); | ||
1428 | 1415 | ||||
1429 | % p_DD is computed using the procedure defined in 93A.1.7.1 with h(n)=A_DD*h_J(n) | 1416 | % p_DD is computed using the procedure defined in 93A.1.7.1 with h(n)=A_DD*h_J(n) | ||
1430 | NS.p_DD = get_pdf_from_sampled_signal(param.A_DD*fom_result.h_J, param.levels, param.delta_y); | 1417 | NS.p_DD = get_pdf_from_sampled_signal(param.A_DD*fom_result.h_J, param.levels, param.delta_y); | ||
1431 | 1418 | ||||
≠ | 1432 | % Equation 93A-43 % only used for reporting bathtub curves | ≠ | 1419 | % Equation 93A-43 |
1433 | NS.noise_pdf=conv_fct(NS.gaussian_noise_pdf, NS.p_DD); | 1420 | NS.noise_pdf=conv_fct(NS.gaussian_noise_pdf, NS.p_DD); | ||
| + | 1421 | |||
1434 | gaussian_rjitt_pdf = normal_dist(NS.sigma_rjit, NS.ber_q, param.delta_y); | 1422 | gaussian_rjitt_pdf = normal_dist(NS.sigma_rjit, NS.ber_q, param.delta_y); | ||
1435 | NS.jitt_pdf=conv_fct(gaussian_rjitt_pdf, NS.p_DD); | 1423 | NS.jitt_pdf=conv_fct(gaussian_rjitt_pdf, NS.p_DD); | ||
1436 | 1424 | ||||
1437 | % Implementation of 93A.1.7.3 combination procedure | 1425 | % Implementation of 93A.1.7.3 combination procedure | ||
1438 | % (effectively Equation 93A-44) %% | 1426 | % (effectively Equation 93A-44) %% | ||
1439 | 1427 | ||||
1440 | % Self-Channel Interference is thru residual result | 1428 | % Self-Channel Interference is thru residual result | ||
1441 | NS.sci_pdf = chdata(1).pdfr; | 1429 | NS.sci_pdf = chdata(1).pdfr; | ||
1442 | sci_mxi=find(cumsum(NS.sci_pdf.y)>=param.specBER, 1, 'first'); | 1430 | sci_mxi=find(cumsum(NS.sci_pdf.y)>=param.specBER, 1, 'first'); | ||
1443 | NS.thru_peak_interference_at_BER=abs(NS.sci_pdf.x(sci_mxi)); | 1431 | NS.thru_peak_interference_at_BER=abs(NS.sci_pdf.x(sci_mxi)); | ||
1444 | sci_msi=find(cumsum(NS.sci_pdf.y)>=param.specBER, 1, 'first'); | 1432 | sci_msi=find(cumsum(NS.sci_pdf.y)>=param.specBER, 1, 'first'); | ||
1445 | NS.sci_sigma=abs(NS.sci_pdf.x(sci_msi)/(erfcinv(2*param.specBER)*sqrt(2))); | 1433 | NS.sci_sigma=abs(NS.sci_pdf.x(sci_msi)/(erfcinv(2*param.specBER)*sqrt(2))); | ||
1446 | if OP.RX_CALIBRATION ==0 | 1434 | if OP.RX_CALIBRATION ==0 | ||
1447 | % Co-Channel Interference PDFs (for information only): | 1435 | % Co-Channel Interference PDFs (for information only): | ||
1448 | % initialize to deltas | 1436 | % initialize to deltas | ||
1449 | MDNEXT_cci_pdf = d_cpdf(param.delta_y, 0, 1); | 1437 | MDNEXT_cci_pdf = d_cpdf(param.delta_y, 0, 1); | ||
1450 | MDFEXT_cci_pdf = d_cpdf(param.delta_y, 0, 1); | 1438 | MDFEXT_cci_pdf = d_cpdf(param.delta_y, 0, 1); | ||
1451 | % serially convolve FEXT/NEXT PDFs | 1439 | % serially convolve FEXT/NEXT PDFs | ||
1452 | for k=2:param.number_of_s4p_files | 1440 | for k=2:param.number_of_s4p_files | ||
1453 | if isequal(chdata(k).type, 'NEXT') | 1441 | if isequal(chdata(k).type, 'NEXT') | ||
1454 | MDNEXT_cci_pdf = conv_fct(MDNEXT_cci_pdf, chdata(k).pdfr); | 1442 | MDNEXT_cci_pdf = conv_fct(MDNEXT_cci_pdf, chdata(k).pdfr); | ||
1455 | else % ... must be FEXT | 1443 | else % ... must be FEXT | ||
1456 | MDFEXT_cci_pdf = conv_fct(MDFEXT_cci_pdf, chdata(k).pdfr); | 1444 | MDFEXT_cci_pdf = conv_fct(MDFEXT_cci_pdf, chdata(k).pdfr); | ||
1457 | end | 1445 | end | ||
1458 | end | 1446 | end | ||
1459 |
| 1447 |
| ||
1460 | % find "peaks" of MDNEXT/MDFEXT for reporting | 1448 | % find "peaks" of MDNEXT/MDFEXT for reporting | ||
1461 | mdnxi=find(cumsum(MDNEXT_cci_pdf.y)>=param.specBER, 1, 'first'); | 1449 | mdnxi=find(cumsum(MDNEXT_cci_pdf.y)>=param.specBER, 1, 'first'); | ||
1462 | NS.MDNEXT_peak_interference=abs(MDNEXT_cci_pdf.x(mdnxi)); | 1450 | NS.MDNEXT_peak_interference=abs(MDNEXT_cci_pdf.x(mdnxi)); | ||
1463 | mdfxi=find(cumsum(MDFEXT_cci_pdf.y)>=param.specBER, 1, 'first'); | 1451 | mdfxi=find(cumsum(MDFEXT_cci_pdf.y)>=param.specBER, 1, 'first'); | ||
1464 | NS.MDFEXT_peak_interference=abs(MDFEXT_cci_pdf.x(mdfxi)); | 1452 | NS.MDFEXT_peak_interference=abs(MDFEXT_cci_pdf.x(mdfxi)); | ||
1465 |
| 1453 |
| ||
1466 | % Combined crosstalk effect | 1454 | % Combined crosstalk effect | ||
1467 | NS.cci_pdf = conv_fct(MDFEXT_cci_pdf, MDNEXT_cci_pdf); | 1455 | NS.cci_pdf = conv_fct(MDFEXT_cci_pdf, MDNEXT_cci_pdf); | ||
1468 | cci_mxi=find(cumsum(NS.cci_pdf.y)>=param.specBER, 1, 'first'); | 1456 | cci_mxi=find(cumsum(NS.cci_pdf.y)>=param.specBER, 1, 'first'); | ||
1469 | cci_msi=find(cumsum(NS.cci_pdf.y)>=param.specBER, 1, 'first'); | 1457 | cci_msi=find(cumsum(NS.cci_pdf.y)>=param.specBER, 1, 'first'); | ||
1470 | NS.cci_sigma=abs(NS.cci_pdf.x(cci_msi)/(erfcinv(2*param.specBER)*sqrt(2))); | 1458 | NS.cci_sigma=abs(NS.cci_pdf.x(cci_msi)/(erfcinv(2*param.specBER)*sqrt(2))); | ||
1471 | NS.crosstalk_peak_interference_at_BER=abs(NS.cci_pdf.x(cci_mxi)); | 1459 | NS.crosstalk_peak_interference_at_BER=abs(NS.cci_pdf.x(cci_mxi)); | ||
1472 | % combine cci and sci | 1460 | % combine cci and sci | ||
1473 | NS.isi_and_xtalk_pdf = conv_fct(NS.sci_pdf, NS.cci_pdf); | 1461 | NS.isi_and_xtalk_pdf = conv_fct(NS.sci_pdf, NS.cci_pdf); | ||
1474 | else | 1462 | else | ||
1475 | % for calibration there is no cci | 1463 | % for calibration there is no cci | ||
1476 | NS.isi_and_xtalk_pdf=NS.sci_pdf; | 1464 | NS.isi_and_xtalk_pdf=NS.sci_pdf; | ||
1477 | end | 1465 | end | ||
1478 | 1466 | ||||
1479 | mxi=find(cumsum(NS.isi_and_xtalk_pdf.y)>=param.specBER, 1, 'first'); | 1467 | mxi=find(cumsum(NS.isi_and_xtalk_pdf.y)>=param.specBER, 1, 'first'); | ||
1480 | NS.peak_interference_at_BER=abs(NS.isi_and_xtalk_pdf.x(mxi)); | 1468 | NS.peak_interference_at_BER=abs(NS.isi_and_xtalk_pdf.x(mxi)); | ||
1481 | 1469 | ||||
1482 | 1470 | ||||
1483 | % Equation 93A-45 | 1471 | % Equation 93A-45 | ||
1484 | combined_interference_and_noise_pdf = conv_fct(NS.isi_and_xtalk_pdf, NS.noise_pdf); | 1472 | combined_interference_and_noise_pdf = conv_fct(NS.isi_and_xtalk_pdf, NS.noise_pdf); | ||
1485 | PDF=combined_interference_and_noise_pdf; | 1473 | PDF=combined_interference_and_noise_pdf; | ||
1486 | 1474 | ||||
1487 | % Equation 93A-37 | 1475 | % Equation 93A-37 | ||
1488 | combined_interference_and_noise_cdf=cumsum(combined_interference_and_noise_pdf.y); | 1476 | combined_interference_and_noise_cdf=cumsum(combined_interference_and_noise_pdf.y); | ||
1489 | CDF=combined_interference_and_noise_cdf; | 1477 | CDF=combined_interference_and_noise_cdf; | ||
1490 | function [hctf] = FD_CTLE(freq, fb, f_z, f_p1, f_p2, kacdc_dB) | 1478 | function [hctf] = FD_CTLE(freq, fb, f_z, f_p1, f_p2, kacdc_dB) | ||
1491 | hctf = ( 10.^(kacdc_dB/20) + 1i*freq/f_z ) ./ ( (1+1i*freq/f_p1) .* (1+1i*freq/f_p2)) ; | 1479 | hctf = ( 10.^(kacdc_dB/20) + 1i*freq/f_z ) ./ ( (1+1i*freq/f_p1) .* (1+1i*freq/f_p2)) ; | ||
1492 | 1480 | ||||
1493 | function [chdata,output_args]=FD_Processing(chdata,output_args,param,OP,SDDp2p,DO_ONCE) | 1481 | function [chdata,output_args]=FD_Processing(chdata,output_args,param,OP,SDDp2p,DO_ONCE) | ||
1494 | %This function calculates various frequency domain metrics | 1482 | %This function calculates various frequency domain metrics | ||
1495 | %Mainly IL_fit, FOM_ILD, ICN, ICN_Fext, and ICN_Next | 1483 | %Mainly IL_fit, FOM_ILD, ICN, ICN_Fext, and ICN_Next | ||
1496 | db = @(x) 20*log10(abs(x)); | 1484 | db = @(x) 20*log10(abs(x)); | ||
1497 | package_testcase=OP.pkg_len_select(param.package_testcase_i); | 1485 | package_testcase=OP.pkg_len_select(param.package_testcase_i); | ||
1498 | if OP.WC_PORTZ | 1486 | if OP.WC_PORTZ | ||
1499 | A_thru = param.a_thru(param.Tx_rd_sel); | 1487 | A_thru = param.a_thru(param.Tx_rd_sel); | ||
1500 | A_fext = param.a_fext(param.Tx_rd_sel); | 1488 | A_fext = param.a_fext(param.Tx_rd_sel); | ||
1501 | A_next = param.a_next(param.Tx_rd_sel); | 1489 | A_next = param.a_next(param.Tx_rd_sel); | ||
1502 | else | 1490 | else | ||
1503 | A_thru = param.a_thru(package_testcase); | 1491 | A_thru = param.a_thru(package_testcase); | ||
1504 | A_fext = param.a_fext(package_testcase); | 1492 | A_fext = param.a_fext(package_testcase); | ||
1505 | A_next = param.a_next(package_testcase); | 1493 | A_next = param.a_next(package_testcase); | ||
1506 | end | 1494 | end | ||
1507 | for i=1:param.number_of_s4p_files | 1495 | for i=1:param.number_of_s4p_files | ||
1508 | if isequal(chdata(i).type, 'THRU') | 1496 | if isequal(chdata(i).type, 'THRU') | ||
1509 | chdata(i).A=A_thru; | 1497 | chdata(i).A=A_thru; | ||
1510 | chdata(i).Aicn=A_thru; | 1498 | chdata(i).Aicn=A_thru; | ||
1511 | elseif isequal(chdata(i).type, 'FEXT') | 1499 | elseif isequal(chdata(i).type, 'FEXT') | ||
1512 | chdata(i).A=A_fext; | 1500 | chdata(i).A=A_fext; | ||
1513 | chdata(i).Aicn=param.a_icn_fext; | 1501 | chdata(i).Aicn=param.a_icn_fext; | ||
1514 | elseif isequal(chdata(i).type, 'NEXT') | 1502 | elseif isequal(chdata(i).type, 'NEXT') | ||
1515 | chdata(i).A=A_next; | 1503 | chdata(i).A=A_next; | ||
1516 | chdata(i).Aicn=param.a_icn_next; | 1504 | chdata(i).Aicn=param.a_icn_next; | ||
1517 | end | 1505 | end | ||
1518 | end | 1506 | end | ||
1519 | if OP.TDMODE | 1507 | if OP.TDMODE | ||
1520 | for i=1:param.number_of_s4p_files % freq delta for integration | 1508 | for i=1:param.number_of_s4p_files % freq delta for integration | ||
1521 | chdata(i).delta_f=chdata(i).faxis(11)-chdata(i).faxis(10); | 1509 | chdata(i).delta_f=chdata(i).faxis(11)-chdata(i).faxis(10); | ||
1522 | end | 1510 | end | ||
1523 | end | 1511 | end | ||
1524 | if ~DO_ONCE | 1512 | if ~DO_ONCE | ||
1525 | return; | 1513 | return; | ||
1526 | end | 1514 | end | ||
1527 | %Any new output_args fields set in this function should be initialized here as empty | 1515 | %Any new output_args fields set in this function should be initialized here as empty | ||
1528 | output_args.fitted_IL_dB_at_Fnq = []; | 1516 | output_args.fitted_IL_dB_at_Fnq = []; | ||
1529 | output_args.cable__assembley_loss=[]; | 1517 | output_args.cable__assembley_loss=[]; | ||
1530 | output_args.loss_with_PCB=[]; | 1518 | output_args.loss_with_PCB=[]; | ||
1531 | output_args.VIP_to_VMP_IL_dB_at_Fnq=[]; | 1519 | output_args.VIP_to_VMP_IL_dB_at_Fnq=[]; | ||
1532 | output_args.IL_dB_channel_only_at_Fnq=[]; | 1520 | output_args.IL_dB_channel_only_at_Fnq=[]; | ||
1533 | output_args.VTF_loss_dB_at_Fnq=[]; | 1521 | output_args.VTF_loss_dB_at_Fnq=[]; | ||
1534 | output_args.IL_db_die_to_die_at_Fnq=[]; | 1522 | output_args.IL_db_die_to_die_at_Fnq=[]; | ||
1535 | output_args.FOM_TDILN=[]; | 1523 | output_args.FOM_TDILN=[]; | ||
1536 | output_args.TD_ILN=[]; | 1524 | output_args.TD_ILN=[]; | ||
1537 | output_args.FOM_RILN=[]; | 1525 | output_args.FOM_RILN=[]; | ||
1538 | output_args.FOM_ILD=[]; | 1526 | output_args.FOM_ILD=[]; | ||
1539 | %TD_Mode is just a pass through to set the empty values and return | 1527 | %TD_Mode is just a pass through to set the empty values and return | ||
1540 | if ~OP.GET_FD | 1528 | if ~OP.GET_FD | ||
1541 | return; | 1529 | return; | ||
1542 | end | 1530 | end | ||
1543 | case_number=param.package_testcase_i; | 1531 | case_number=param.package_testcase_i; | ||
1544 | f2=param.f2; | 1532 | f2=param.f2; | ||
1545 | f1=param.f1; | 1533 | f1=param.f1; | ||
1546 | MDFEXT_ICN=0; MDNEXT_ICN=0; | 1534 | MDFEXT_ICN=0; MDNEXT_ICN=0; | ||
1547 | for i=1:param.number_of_s4p_files | 1535 | for i=1:param.number_of_s4p_files | ||
1548 | if OP.INCLUDE_FILTER % apply RX filtRaised_Cosine_Filterer | 1536 | if OP.INCLUDE_FILTER % apply RX filtRaised_Cosine_Filterer | ||
1549 | % Equation 93A-20 %% | 1537 | % Equation 93A-20 %% | ||
1550 | % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(i).faxis./(param.f_r*param.fb)); | 1538 | % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(i).faxis./(param.f_r*param.fb)); | ||
1551 | f=chdata(i).faxis; | 1539 | f=chdata(i).faxis; | ||
1552 | % | 1540 | % | ||
1553 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | 1541 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | ||
1554 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | 1542 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | ||
1555 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine); % conditionally include the RCos filter for all IR conversion using COM_FD_to_TD | 1543 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine); % conditionally include the RCos filter for all IR conversion using COM_FD_to_TD | ||
1556 | H_txffe= Tx_FFE_Filter(param,f,param.Pkg_TXFFE_preset); % RIM 08-18-2022 to add forced TX ffe per package case | 1544 | H_txffe= Tx_FFE_Filter(param,f,param.Pkg_TXFFE_preset); % RIM 08-18-2022 to add forced TX ffe per package case | ||
1557 | H_r=H_bw.*H_bt.*H_RCos.*H_txffe; % RIM 08-18-2022 to add forced TX ffe per package case | 1545 | H_r=H_bw.*H_bt.*H_RCos.*H_txffe; % RIM 08-18-2022 to add forced TX ffe per package case | ||
1558 | chdata(i).sdd21=chdata(i).sdd21.*H_r; | 1546 | chdata(i).sdd21=chdata(i).sdd21.*H_r; | ||
1559 | if OP.DISPLAY_WINDOW | 1547 | if OP.DISPLAY_WINDOW | ||
1560 | if i==1 | 1548 | if i==1 | ||
1561 | figure(300+param.package_testcase_i); | 1549 | figure(300+param.package_testcase_i); | ||
1562 | subplot(3,1,1) | 1550 | subplot(3,1,1) | ||
1563 | hold on | 1551 | hold on | ||
1564 | plot(chdata(i).faxis/1e9, 20*log10(abs(squeeze(chdata(i).sdd21))), 'k-','linewidth',2, 'Disp',sprintf('VTF (no Tx/Rx eq)')') | 1552 | plot(chdata(i).faxis/1e9, 20*log10(abs(squeeze(chdata(i).sdd21))), 'k-','linewidth',2, 'Disp',sprintf('VTF (no Tx/Rx eq)')') | ||
1565 | try | 1553 | try | ||
1566 | legend('NumColumns',2) | 1554 | legend('NumColumns',2) | ||
1567 | legend('location','south') | 1555 | legend('location','south') | ||
1568 | catch | 1556 | catch | ||
1569 | end | 1557 | end | ||
1570 | end | 1558 | end | ||
1571 | end | 1559 | end | ||
1572 | end | 1560 | end | ||
1573 | end | 1561 | end | ||
1574 | for i=1:param.number_of_s4p_files | 1562 | for i=1:param.number_of_s4p_files | ||
1575 | if i == 2 | 1563 | if i == 2 | ||
1576 | PSXT(1:length(chdata(i).sdd21f))=0; | 1564 | PSXT(1:length(chdata(i).sdd21f))=0; | ||
1577 | MDFEXT(1:length(chdata(i).sdd21f))=0; | 1565 | MDFEXT(1:length(chdata(i).sdd21f))=0; | ||
1578 | MDNEXT(1:length(chdata(i).sdd21f))=0; | 1566 | MDNEXT(1:length(chdata(i).sdd21f))=0; | ||
1579 | end | 1567 | end | ||
1580 | a=find(chdata(i).faxis(:)>=f2,1,'first');% RIM 01-12-21 | 1568 | a=find(chdata(i).faxis(:)>=f2,1,'first');% RIM 01-12-21 | ||
1581 | if isempty(a) | 1569 | if isempty(a) | ||
1582 | f2=chdata(i).faxis(end); | 1570 | f2=chdata(i).faxis(end); | ||
1583 | index_f2=length(chdata(i).faxis); | 1571 | index_f2=length(chdata(i).faxis); | ||
1584 | else | 1572 | else | ||
1585 | index_f2=a(1); | 1573 | index_f2=a(1); | ||
1586 | end | 1574 | end | ||
1587 | b=find(chdata(i).faxis(:)<=f1,1,'last');% RIM 01-12-21 | 1575 | b=find(chdata(i).faxis(:)<=f1,1,'last');% RIM 01-12-21 | ||
1588 | if isempty(b) | 1576 | if isempty(b) | ||
1589 | f1=chdata(i).faxis(1); | 1577 | f1=chdata(i).faxis(1); | ||
1590 | index_f1=1; | 1578 | index_f1=1; | ||
1591 | else | 1579 | else | ||
1592 | index_f1=b(1); | 1580 | index_f1=b(1); | ||
1593 | end | 1581 | end | ||
1594 | % R is the frequency dependent parameter for the sinc function use in the | 1582 | % R is the frequency dependent parameter for the sinc function use in the | ||
1595 | % PWF for ICN | 1583 | % PWF for ICN | ||
1596 | temp_angle=(param.samples_per_ui*param.sample_dt)*pi.*chdata(i).faxis; | 1584 | temp_angle=(param.samples_per_ui*param.sample_dt)*pi.*chdata(i).faxis; | ||
1597 | if(chdata(i).faxis(1)==0) | 1585 | if(chdata(i).faxis(1)==0) | ||
1598 | temp_angle(1)=1e-20;% we don't want to divide by zero | 1586 | temp_angle(1)=1e-20;% we don't want to divide by zero | ||
1599 | end | 1587 | end | ||
1600 | SINC = sin(temp_angle)./temp_angle; | 1588 | SINC = sin(temp_angle)./temp_angle; | ||
1601 | PWF_data=SINC.^2; | 1589 | PWF_data=SINC.^2; | ||
1602 | PWF_trf=(1+(chdata(i).faxis/chdata(i).ftr).^4).^-1; | 1590 | PWF_trf=(1+(chdata(i).faxis/chdata(i).ftr).^4).^-1; | ||
1603 | %// bw1=2.613126; bw2=3.4142136; bw3=2.613126; | 1591 | %// bw1=2.613126; bw2=3.4142136; bw3=2.613126; | ||
1604 | fr=param.f_r*param.fb; | 1592 | fr=param.f_r*param.fb; | ||
1605 | PWF_rx=(1+(chdata(i).faxis/fr).^8).^-1; | 1593 | PWF_rx=(1+(chdata(i).faxis/fr).^8).^-1; | ||
1606 | PWF_highpass=1; | 1594 | PWF_highpass=1; | ||
1607 | % Equation 93A-57 % | 1595 | % Equation 93A-57 % | ||
1608 | PWF=PWF_data.*PWF_trf.*PWF_rx.*PWF_highpass; % power weight function | 1596 | PWF=PWF_data.*PWF_trf.*PWF_rx.*PWF_highpass; % power weight function | ||
1609 | % freq delta for integration | 1597 | % freq delta for integration | ||
1610 | chdata(i).delta_f=chdata(i).faxis(11)-chdata(i).faxis(10); | 1598 | chdata(i).delta_f=chdata(i).faxis(11)-chdata(i).faxis(10); | ||
1611 | % from ba spec, this is basically ICN | 1599 | % from ba spec, this is basically ICN | ||
1612 | faxis_GHz = chdata(i).faxis/1e9; | 1600 | faxis_GHz = chdata(i).faxis/1e9; | ||
1613 | if isequal(chdata(i).type, 'THRU') | 1601 | if isequal(chdata(i).type, 'THRU') | ||
1614 | [ILD_magft chdata(i).fit_orig] = get_ILN(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2)); | 1602 | [ILD_magft chdata(i).fit_orig] = get_ILN(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2)); | ||
1615 | % find fitted loss values by interpolation using full data, no indexing - Adee 2022-08-28 | 1603 | % find fitted loss values by interpolation using full data, no indexing - Adee 2022-08-28 | ||
1616 | [~, chdata(i).fit_orig] = get_ILN(chdata(i).sdd21f, chdata(i).faxis); | 1604 | [~, chdata(i).fit_orig] = get_ILN(chdata(i).sdd21f, chdata(i).faxis); | ||
1617 | fit_loss = interp1(chdata(i).faxis, -chdata(i).fit_orig, 1/param.ui/2); | 1605 | fit_loss = interp1(chdata(i).faxis, -chdata(i).fit_orig, 1/param.ui/2); | ||
1618 | chdata(i).fit_ILatNq = fit_loss; | 1606 | chdata(i).fit_ILatNq = fit_loss; | ||
1619 | output_args.fitted_IL_dB_at_Fnq = fit_loss; | 1607 | output_args.fitted_IL_dB_at_Fnq = fit_loss; | ||
1620 | IL_interp = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21f)), 1/param.ui/2); | 1608 | IL_interp = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21f)), 1/param.ui/2); | ||
1621 | chdata(i).ILatNq = IL_interp; | 1609 | chdata(i).ILatNq = IL_interp; | ||
1622 | if OP.include_pcb | 1610 | if OP.include_pcb | ||
1623 | cable_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21_orig)), 1/param.ui/2); | 1611 | cable_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21_orig)), 1/param.ui/2); | ||
1624 | loss_with_PCB = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21_raw)), 1/param.ui/2); | 1612 | loss_with_PCB = interp1(chdata(i).faxis, -20*log10(abs(chdata(i).sdd21_raw)), 1/param.ui/2); | ||
1625 | output_args.cable__assembley_loss=cable_loss; | 1613 | output_args.cable__assembley_loss=cable_loss; | ||
1626 | output_args.loss_with_PCB=loss_with_PCB; | 1614 | output_args.loss_with_PCB=loss_with_PCB; | ||
1627 | end | 1615 | end | ||
1628 | Nq_loss=chdata(i).ILatNq; | 1616 | Nq_loss=chdata(i).ILatNq; | ||
1629 | output_args.IL_dB_channel_only_at_Fnq=Nq_loss; | 1617 | output_args.IL_dB_channel_only_at_Fnq=Nq_loss; | ||
1630 | % time domain ref RR = complex fit pulse | 1618 | % time domain ref RR = complex fit pulse | ||
1631 | if OP.COMPUTE_TDILN || OP.COMPUTE_RILN | 1619 | if OP.COMPUTE_TDILN || OP.COMPUTE_RILN | ||
1632 | [ILD chdata(i).fit, TD_ILN ] = get_ILN_cmp_td(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2),OP,param,chdata(i).A); | 1620 | [ILD chdata(i).fit, TD_ILN ] = get_ILN_cmp_td(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2),OP,param,chdata(i).A); | ||
1633 | FOM_TDILN = TD_ILN.SNR_ISI_FOM_PDF; | 1621 | FOM_TDILN = TD_ILN.SNR_ISI_FOM_PDF; | ||
1634 | FOM_ILN_complex= TD_ILN.FOM; | 1622 | FOM_ILN_complex= TD_ILN.FOM; | ||
1635 | end | 1623 | end | ||
1636 | if OP.COMPUTE_TDILN || OP.COMPUTE_RILN | 1624 | if OP.COMPUTE_TDILN || OP.COMPUTE_RILN | ||
1637 | [ILD chdata(i).fit, TD_ILN ] = get_ILN_cmp_td(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2),OP,param,chdata(i).A); | 1625 | [ILD chdata(i).fit, TD_ILN ] = get_ILN_cmp_td(chdata(i).sdd21f(index_f1:index_f2), chdata(i).faxis(index_f1:index_f2),OP,param,chdata(i).A); | ||
1638 | FOM_TDILN = TD_ILN.SNR_ISI_FOM_PDF; | 1626 | FOM_TDILN = TD_ILN.SNR_ISI_FOM_PDF; | ||
1639 | FOM_ILN_complex= TD_ILN.FOM; | 1627 | FOM_ILN_complex= TD_ILN.FOM; | ||
1640 | end | 1628 | end | ||
1641 | if OP.COMPUTE_TDILN | 1629 | if OP.COMPUTE_TDILN | ||
1642 | output_args.FOM_TDILN=FOM_TDILN; | 1630 | output_args.FOM_TDILN=FOM_TDILN; | ||
1643 | output_args.TD_ILN=TD_ILN; % struct | 1631 | output_args.TD_ILN=TD_ILN; % struct | ||
1644 | end | 1632 | end | ||
1645 | if OP.COMPUTE_RILN | 1633 | if OP.COMPUTE_RILN | ||
1646 | % Get RIL, RILN, and TD_RILN | 1634 | % Get RIL, RILN, and TD_RILN | ||
1647 | [RIL_struct]= capture_RIL_RILN(chdata); | 1635 | [RIL_struct]= capture_RIL_RILN(chdata); | ||
1648 | FOM_RILN=sqrt(chdata(i).delta_f/(param.f2-param.f1)*sum( PWF(index_f1:index_f2-1).*RIL_struct.RILN_dB(index_f1:index_f2-1)'.^2)); | 1636 | FOM_RILN=sqrt(chdata(i).delta_f/(param.f2-param.f1)*sum( PWF(index_f1:index_f2-1).*RIL_struct.RILN_dB(index_f1:index_f2-1)'.^2)); | ||
1649 | output_args.FOM_RILN=FOM_RILN; | 1637 | output_args.FOM_RILN=FOM_RILN; | ||
1650 | %---start. plotting ILN based on ILD and RILN % Hansel 10/18/2021 | 1638 | %---start. plotting ILN based on ILD and RILN % Hansel 10/18/2021 | ||
1651 | plot_tdomain_debug= 0; % must have OP.COMPUTE_TDILN = 1 to use | 1639 | plot_tdomain_debug= 0; % must have OP.COMPUTE_TDILN = 1 to use | ||
1652 | if plot_tdomain_debug== 1 | 1640 | if plot_tdomain_debug== 1 | ||
1653 | figure(988); set(gcf,'Tag','COM') | 1641 | figure(988); set(gcf,'Tag','COM') | ||
1654 | ax_1= subplot(3,1,1); | 1642 | ax_1= subplot(3,1,1); | ||
1655 | plot(TD_ILN.REF.t*1e9, TD_ILN.REF.PR*1e3,'disp','ref'); | 1643 | plot(TD_ILN.REF.t*1e9, TD_ILN.REF.PR*1e3,'disp','ref'); | ||
1656 | hold on; | 1644 | hold on; | ||
1657 | plot(TD_ILN.FIT.t*1e9, TD_ILN.FIT.PR*1e3,'disp','fit'); | 1645 | plot(TD_ILN.FIT.t*1e9, TD_ILN.FIT.PR*1e3,'disp','fit'); | ||
1658 | hold on; | 1646 | hold on; | ||
1659 | plot(TD_ILN.t*1e9, TD_ILN.ILN*1e3, 'k','disp','ref - fit (IL noise)'); | 1647 | plot(TD_ILN.t*1e9, TD_ILN.ILN*1e3, 'k','disp','ref - fit (IL noise)'); | ||
1660 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | 1648 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | ||
1661 | grid on; | 1649 | grid on; | ||
1662 | box on; | 1650 | box on; | ||
1663 | legend('REF', 'FIT', 'TD\_ILN: ref - fit (IL noise)'); | 1651 | legend('REF', 'FIT', 'TD\_ILN: ref - fit (IL noise)'); | ||
1664 | xlabel('Time [nsec]'); | 1652 | xlabel('Time [nsec]'); | ||
1665 | ylabel('Pulse Response [mV]'); | 1653 | ylabel('Pulse Response [mV]'); | ||
1666 |
| 1654 |
| ||
1667 | ax_2= subplot(3,1,2); | 1655 | ax_2= subplot(3,1,2); | ||
1668 | plot(TD_RILN.REF.t*1e9, TD_RILN.REF.PR*1e3); | 1656 | plot(TD_RILN.REF.t*1e9, TD_RILN.REF.PR*1e3); | ||
1669 | hold on; | 1657 | hold on; | ||
1670 | plot(TD_RILN.t*1e9, TD_RILN.ILN*1e3, 'r'); | 1658 | plot(TD_RILN.t*1e9, TD_RILN.ILN*1e3, 'r'); | ||
1671 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | 1659 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | ||
1672 | grid on; | 1660 | grid on; | ||
1673 | box on; | 1661 | box on; | ||
1674 | legend('REF', 'TD\_RILN'); | 1662 | legend('REF', 'TD\_RILN'); | ||
1675 | xlabel('Time [nsec]'); | 1663 | xlabel('Time [nsec]'); | ||
1676 | ylabel('Pulse Response [mV]'); | 1664 | ylabel('Pulse Response [mV]'); | ||
1677 | ax_3= subplot(3,1,3); | 1665 | ax_3= subplot(3,1,3); | ||
1678 | plot(TD_ILN.t*1e9, TD_ILN.ILN*1e3, 'k'); | 1666 | plot(TD_ILN.t*1e9, TD_ILN.ILN*1e3, 'k'); | ||
1679 | hold on; | 1667 | hold on; | ||
1680 | plot(TD_RILN.t*1e9, TD_RILN.ILN*1e3, 'r'); | 1668 | plot(TD_RILN.t*1e9, TD_RILN.ILN*1e3, 'r'); | ||
1681 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | 1669 | ylim([min(TD_RILN.ILN) max(TD_RILN.ILN)]*1e3); | ||
1682 | grid on; | 1670 | grid on; | ||
1683 | box on; | 1671 | box on; | ||
1684 | legend( 'TD\_ILN: ref - fit (IL noise)', 'TD\_RILN'); | 1672 | legend( 'TD\_ILN: ref - fit (IL noise)', 'TD\_RILN'); | ||
1685 | xlabel('Time [nsec]'); | 1673 | xlabel('Time [nsec]'); | ||
1686 | ylabel('Pulse Response [mV]'); | 1674 | ylabel('Pulse Response [mV]'); | ||
1687 |
| 1675 |
| ||
1688 | linkaxes([ax_1, ax_2, ax_3], 'x'); | 1676 | linkaxes([ax_1, ax_2, ax_3], 'x'); | ||
1689 | ax_1.XLim = [0 max(TD_RILN.t)*1e9 ]; | 1677 | ax_1.XLim = [0 max(TD_RILN.t)*1e9 ]; | ||
1690 | end | 1678 | end | ||
1691 | %---end. plotting ILN based on ILD and RILN | 1679 | %---end. plotting ILN based on ILD and RILN | ||
1692 | end | 1680 | end | ||
1693 | % Equation 93A-56 % | 1681 | % Equation 93A-56 % | ||
1694 | FOM_ILD=sqrt(chdata(i).delta_f/(param.f2-param.f1)*sum( PWF(index_f1:index_f2).*ILD_magft.^2)); | 1682 | FOM_ILD=sqrt(chdata(i).delta_f/(param.f2-param.f1)*sum( PWF(index_f1:index_f2).*ILD_magft.^2)); | ||
1695 | output_args.FOM_ILD=FOM_ILD; | 1683 | output_args.FOM_ILD=FOM_ILD; | ||
1696 | if OP.DEBUG | 1684 | if OP.DEBUG | ||
1697 | if OP.DISPLAY_WINDOW | 1685 | if OP.DISPLAY_WINDOW | ||
1698 | figure(300+case_number); | 1686 | figure(300+case_number); | ||
1699 | set(gcf,'Tag','COM') | 1687 | set(gcf,'Tag','COM') | ||
1700 | screen_size=get(0,'ScreenSize'); | 1688 | screen_size=get(0,'ScreenSize'); | ||
1701 | pos = get(gcf, 'OuterPosition'); | 1689 | pos = get(gcf, 'OuterPosition'); | ||
1702 | set(gcf, 'Name', [sprintf('%.3gdB IL Channel: ',Nq_loss) 'Raw frequency-domain data'], 'OuterPosition', ... | 1690 | set(gcf, 'Name', [sprintf('%.3gdB IL Channel: ',Nq_loss) 'Raw frequency-domain data'], 'OuterPosition', ... | ||
1703 | screen_size([3 4 3 4]).*[0 1 0 0] + pos([3 4 3 4]).*[0 -2 1 2] ...IL fit | 1691 | screen_size([3 4 3 4]).*[0 1 0 0] + pos([3 4 3 4]).*[0 -2 1 2] ...IL fit | ||
1704 | - (case_number-1)*[0 20 0 0]); | 1692 | - (case_number-1)*[0 20 0 0]); | ||
1705 | subplot(3,1,1) | 1693 | subplot(3,1,1) | ||
1706 | title('Losses') | 1694 | title('Losses') | ||
1707 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21f))), 'b', 'LineWidth', 3, 'Disp','IL passed s-params') | 1695 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21f))), 'b', 'LineWidth', 3, 'Disp','IL passed s-params') | ||
1708 | hold on | 1696 | hold on | ||
1709 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21p_nodie))), 'm-', 'Disp','IL die to die (w pkg/brds)') | 1697 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21p_nodie))), 'm-', 'Disp','IL die to die (w pkg/brds)') | ||
1710 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21p))), 'b-', 'Disp','IL dB VIP to VMP') | 1698 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21p))), 'b-', 'Disp','IL dB VIP to VMP') | ||
1711 | ylim(get(gca, 'ylim')); | 1699 | ylim(get(gca, 'ylim')); | ||
1712 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd11))),'c','Disp','RL11') | 1700 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd11))),'c','Disp','RL11') | ||
1713 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd22))),'m','Disp','RL22') | 1701 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd22))),'m','Disp','RL22') | ||
1714 | subplot(3,1,3) | 1702 | subplot(3,1,3) | ||
1715 | plot(faxis_GHz(index_f1:index_f2), ILD_magft,'Disp','ILD') | 1703 | plot(faxis_GHz(index_f1:index_f2), ILD_magft,'Disp','ILD') | ||
1716 | if OP.PLOT_CM | 1704 | if OP.PLOT_CM | ||
1717 | if case_number ==1 | 1705 | if case_number ==1 | ||
1718 | h350=figure(350);set(gcf,'Tag','COM') | 1706 | h350=figure(350);set(gcf,'Tag','COM') | ||
1719 | screen_size=get(0,'ScreenSize'); | 1707 | screen_size=get(0,'ScreenSize'); | ||
1720 | pos = get(gcf, 'OuterPosition'); | 1708 | pos = get(gcf, 'OuterPosition'); | ||
1721 | set(gcf, 'OuterPosition',screen_size([3 4 3 4]).*[1 1 0 0] + pos([3 4 3 4]).*[-2 -2 2 1]) | 1709 | set(gcf, 'OuterPosition',screen_size([3 4 3 4]).*[1 1 0 0] + pos([3 4 3 4]).*[-2 -2 2 1]) | ||
1722 | movegui(gcf,'center'); | 1710 | movegui(gcf,'center'); | ||
1723 | htabgroup350 = uitabgroup(h350); | 1711 | htabgroup350 = uitabgroup(h350); | ||
1724 | htab1 = uitab(htabgroup350, 'Title', 'CM Through Losses'); | 1712 | htab1 = uitab(htabgroup350, 'Title', 'CM Through Losses'); | ||
1725 | hax1 = axes('Parent', htab1); | 1713 | hax1 = axes('Parent', htab1); | ||
1726 | set(h350,'CurrentAxes',hax1) | 1714 | set(h350,'CurrentAxes',hax1) | ||
1727 | hold on | 1715 | hold on | ||
1728 | set(gcf,'Tag','COM') | 1716 | set(gcf,'Tag','COM') | ||
1729 | screen_size=get(0,'ScreenSize'); | 1717 | screen_size=get(0,'ScreenSize'); | ||
1730 | pos = get(gcf, 'OuterPosition'); | 1718 | pos = get(gcf, 'OuterPosition'); | ||
1731 | title('IL & CM Losses') | 1719 | title('IL & CM Losses') | ||
1732 | base=strrep(chdata(i).base,'_',' '); | 1720 | base=strrep(chdata(i).base,'_',' '); | ||
1733 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21f))), 'b', 'LineWidth', 3, 'Disp', [ 'sdd21(IL) TP0-TP5 ' base]) | 1721 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21f))), 'b', 'LineWidth', 3, 'Disp', [ 'sdd21(IL) TP0-TP5 ' base]) | ||
1734 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdc21_raw))), 'LineWidth', 2, 'Disp',[ 'sdc21 TP0-TP5 ' base]) | 1722 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdc21_raw))), 'LineWidth', 2, 'Disp',[ 'sdc21 TP0-TP5 ' base]) | ||
1735 | ylabel('dB') | 1723 | ylabel('dB') | ||
1736 | xlabel('GHz') | 1724 | xlabel('GHz') | ||
1737 | legend show | 1725 | legend show | ||
1738 | legend('Location','eastoutside') | 1726 | legend('Location','eastoutside') | ||
1739 | hold on | 1727 | hold on | ||
1740 | grid on | 1728 | grid on | ||
1741 | if param.number_of_s4p_files > 1 | 1729 | if param.number_of_s4p_files > 1 | ||
1742 | htab2 = uitab(htabgroup350, 'Title', 'CM Crosstalk Losses'); | 1730 | htab2 = uitab(htabgroup350, 'Title', 'CM Crosstalk Losses'); | ||
1743 | hax2 = axes('Parent', htab2); | 1731 | hax2 = axes('Parent', htab2); | ||
1744 | htab3 = uitab(htabgroup350, 'Title', 'Crosstalk Losses'); | 1732 | htab3 = uitab(htabgroup350, 'Title', 'Crosstalk Losses'); | ||
1745 | hax3 = axes('Parent', htab3); | 1733 | hax3 = axes('Parent', htab3); | ||
1746 | end | 1734 | end | ||
1747 |
| 1735 |
| ||
1748 | end | 1736 | end | ||
1749 | end | 1737 | end | ||
1750 | else | 1738 | else | ||
1751 | display(['Insertion Loss at Nyquist = ', num2str(chdata(i).ILatNq)]) | 1739 | display(['Insertion Loss at Nyquist = ', num2str(chdata(i).ILatNq)]) | ||
1752 | end | 1740 | end | ||
1753 | end | 1741 | end | ||
1754 | else % NEXT or FEXT | 1742 | else % NEXT or FEXT | ||
1755 | if isequal(chdata(i).type, 'FEXT') | 1743 | if isequal(chdata(i).type, 'FEXT') | ||
1756 | MDFEXT=sqrt(abs(chdata(i).sdd21f).^2+MDFEXT.^2); % power sum xtk | 1744 | MDFEXT=sqrt(abs(chdata(i).sdd21f).^2+MDFEXT.^2); % power sum xtk | ||
1757 | MDFEXT_ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( chdata(i).Aicn^2*PWF(index_f1:index_f2).*abs(MDFEXT(index_f1:index_f2)).^2)); %eq 46 | 1745 | MDFEXT_ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( chdata(i).Aicn^2*PWF(index_f1:index_f2).*abs(MDFEXT(index_f1:index_f2)).^2)); %eq 46 | ||
1758 | output_args.MDFEXT_ICN_92_47_mV=MDFEXT_ICN*1000; | 1746 | output_args.MDFEXT_ICN_92_47_mV=MDFEXT_ICN*1000; | ||
1759 | elseif isequal(chdata(i).type, 'NEXT') | 1747 | elseif isequal(chdata(i).type, 'NEXT') | ||
1760 | MDNEXT=sqrt(abs(chdata(i).sdd21f).^2+MDNEXT.^2); % power sum xtk | 1748 | MDNEXT=sqrt(abs(chdata(i).sdd21f).^2+MDNEXT.^2); % power sum xtk | ||
1761 | MDNEXT_ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( chdata(i).Aicn^2*PWF(index_f1:index_f2).*abs(MDNEXT(index_f1:index_f2)).^2)); %eq 47 | 1749 | MDNEXT_ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( chdata(i).Aicn^2*PWF(index_f1:index_f2).*abs(MDNEXT(index_f1:index_f2)).^2)); %eq 47 | ||
1762 | output_args.MDNEXT_ICN_92_46_mV=MDNEXT_ICN*1000; | 1750 | output_args.MDNEXT_ICN_92_46_mV=MDNEXT_ICN*1000; | ||
1763 | end | 1751 | end | ||
1764 | PSXT=sqrt((abs(chdata(i).sdd21f)*chdata(i).Aicn).^2+PSXT.^2); % power sum xtk | 1752 | PSXT=sqrt((abs(chdata(i).sdd21f)*chdata(i).Aicn).^2+PSXT.^2); % power sum xtk | ||
1765 | ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( PWF(index_f1:index_f2).*abs(PSXT(index_f1:index_f2)).^2)); | 1753 | ICN=sqrt(2*chdata(i).delta_f/param.f2*sum( PWF(index_f1:index_f2).*abs(PSXT(index_f1:index_f2)).^2)); | ||
1766 | output_args.ICN_mV=ICN*1000; | 1754 | output_args.ICN_mV=ICN*1000; | ||
1767 | ICN_test=norm([MDFEXT_ICN MDNEXT_ICN]); | 1755 | ICN_test=norm([MDFEXT_ICN MDNEXT_ICN]); | ||
1768 | if OP.PLOT_CM && OP.DISPLAY_WINDOW | 1756 | if OP.PLOT_CM && OP.DISPLAY_WINDOW | ||
1769 | if case_number ==1 | 1757 | if case_number ==1 | ||
1770 | % htab2 = uitab(htabgroup350, 'Title', 'CM Crosstalk Losses'); | 1758 | % htab2 = uitab(htabgroup350, 'Title', 'CM Crosstalk Losses'); | ||
1771 | % hax2 = axes('Parent', htab2); | 1759 | % hax2 = axes('Parent', htab2); | ||
1772 | set(h350,'CurrentAxes',hax2) | 1760 | set(h350,'CurrentAxes',hax2) | ||
1773 | hold on | 1761 | hold on | ||
1774 | title('CM Losses') | 1762 | title('CM Losses') | ||
1775 | base=strrep(chdata(i).base,'_',' '); | 1763 | base=strrep(chdata(i).base,'_',' '); | ||
1776 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdc21_raw))), 'LineWidth', 2, 'Disp',[ 'sdc21 TP0-TP5 ' base ]) | 1764 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdc21_raw))), 'LineWidth', 2, 'Disp',[ 'sdc21 TP0-TP5 ' base ]) | ||
1777 | legend('Location','eastoutside') | 1765 | legend('Location','eastoutside') | ||
1778 | hold on | 1766 | hold on | ||
1779 | grid on | 1767 | grid on | ||
1780 | set(h350,'CurrentAxes',hax3) | 1768 | set(h350,'CurrentAxes',hax3) | ||
1781 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21_raw))), 'LineWidth', 2, 'Disp',[ 'sdd21 TP0-TP5 ' base ]) | 1769 | plot(faxis_GHz, 20*log10(abs(squeeze(chdata(i).sdd21_raw))), 'LineWidth', 2, 'Disp',[ 'sdd21 TP0-TP5 ' base ]) | ||
1782 | legend('Location','eastoutside') | 1770 | legend('Location','eastoutside') | ||
1783 | hold on | 1771 | hold on | ||
1784 | grid on | 1772 | grid on | ||
1785 | end | 1773 | end | ||
1786 | end | 1774 | end | ||
1787 | end | 1775 | end | ||
1788 | end % for loop | 1776 | end % for loop | ||
1789 | ICN_test=norm([MDFEXT_ICN MDNEXT_ICN]); | 1777 | ICN_test=norm([MDFEXT_ICN MDNEXT_ICN]); | ||
1790 | if OP.DEBUG && OP.DISPLAY_WINDOW | 1778 | if OP.DEBUG && OP.DISPLAY_WINDOW | ||
1791 | figure(300+case_number);set(gcf,'Tag','COM'); | 1779 | figure(300+case_number);set(gcf,'Tag','COM'); | ||
1792 | if param.number_of_s4p_files > 1 | 1780 | if param.number_of_s4p_files > 1 | ||
1793 | scale=1/chdata(2).Aicn; %chdata(i).sdd21f not scalled | 1781 | scale=1/chdata(2).Aicn; %chdata(i).sdd21f not scalled | ||
1794 | subplot(3,1,1) | 1782 | subplot(3,1,1) | ||
1795 | hold on | 1783 | hold on | ||
1796 | plot(faxis_GHz, 20*log10(abs(PSXT*scale)),'r','Disp','PSXTK') | 1784 | plot(faxis_GHz, 20*log10(abs(PSXT*scale)),'r','Disp','PSXTK') | ||
1797 | icrxi=find(chdata(i).faxis >=param.fb/2,1,'first'); | 1785 | icrxi=find(chdata(i).faxis >=param.fb/2,1,'first'); | ||
1798 | subplot(3,1,2) | 1786 | subplot(3,1,2) | ||
1799 | grid on | 1787 | grid on | ||
1800 | ILtemp=20*log10(abs(chdata(1).sdd21f)); | 1788 | ILtemp=20*log10(abs(chdata(1).sdd21f)); | ||
1801 | IL4ICR=interp1(chdata(1).faxis,ILtemp,chdata(i).faxis); | 1789 | IL4ICR=interp1(chdata(1).faxis,ILtemp,chdata(i).faxis); | ||
1802 | scale=1/chdata(2).Aicn; % chdata(i).sdd21f not scalled | 1790 | scale=1/chdata(2).Aicn; % chdata(i).sdd21f not scalled | ||
1803 | ICR=-20*log10(abs(PSXT*scale))+IL4ICR; | 1791 | ICR=-20*log10(abs(PSXT*scale))+IL4ICR; | ||
1804 | semilogx(faxis_GHz, ICR,'Disp', 'ICR') | 1792 | semilogx(faxis_GHz, ICR,'Disp', 'ICR') | ||
1805 | hold on | 1793 | hold on | ||
1806 | stem(faxis_GHz(icrxi), ICR(icrxi),'g', 'disp', 'f_{Baud}/2') | 1794 | stem(faxis_GHz(icrxi), ICR(icrxi),'g', 'disp', 'f_{Baud}/2') | ||
1807 | end | 1795 | end | ||
1808 | subplot(3,1,1) | 1796 | subplot(3,1,1) | ||
1809 | title([param.base ' Losses']); ylabel('dB'); xlabel('GHz') | 1797 | title([param.base ' Losses']); ylabel('dB'); xlabel('GHz') | ||
1810 | grid on; legend show | 1798 | grid on; legend show | ||
1811 | subplot(3,1,2) | 1799 | subplot(3,1,2) | ||
1812 | title([param.base ' ICR']); ylabel('dB'); xlabel('GHz') | 1800 | title([param.base ' ICR']); ylabel('dB'); xlabel('GHz') | ||
1813 | ylim([0 80]) | 1801 | ylim([0 80]) | ||
1814 | xlim([.1 100]) | 1802 | xlim([.1 100]) | ||
1815 | grid on; %legend show | 1803 | grid on; %legend show | ||
1816 | subplot(3,1,3) | 1804 | subplot(3,1,3) | ||
1817 | title([param.base ' ILD']); ylabel('dB'); xlabel('GHz') | 1805 | title([param.base ' ILD']); ylabel('dB'); xlabel('GHz') | ||
1818 | ylim([-3 3]) | 1806 | ylim([-3 3]) | ||
1819 | grid on; legend show | 1807 | grid on; legend show | ||
1820 | end | 1808 | end | ||
1821 | % find loss values by interpolation using full data, no indexing - Adee 2022-08-28 | 1809 | % find loss values by interpolation using full data, no indexing - Adee 2022-08-28 | ||
1822 | total_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21)), 1/param.ui/2); | 1810 | total_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21)), 1/param.ui/2); | ||
1823 | d2d_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21p_nodie)), 1/param.ui/2); | 1811 | d2d_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21p_nodie)), 1/param.ui/2); | ||
1824 | VIP_VMP_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21p)), 1/param.ui/2); | 1812 | VIP_VMP_loss = interp1(chdata(i).faxis, -20*log10(abs(chdata(1).sdd21p)), 1/param.ui/2); | ||
1825 | output_args.VTF_loss_dB_at_Fnq=total_loss; | 1813 | output_args.VTF_loss_dB_at_Fnq=total_loss; | ||
1826 | output_args.IL_db_die_to_die_at_Fnq=d2d_loss; | 1814 | output_args.IL_db_die_to_die_at_Fnq=d2d_loss; | ||
1827 | output_args.VIP_to_VMP_IL_dB_at_Fnq=VIP_VMP_loss; | 1815 | output_args.VIP_to_VMP_IL_dB_at_Fnq=VIP_VMP_loss; | ||
1828 | function [ V0 ] = FFE( C , cmx,spui, V ) | 1816 | function [ V0 ] = FFE( C , cmx,spui, V ) | ||
1829 | % C FFE taps | 1817 | % C FFE taps | ||
1830 | % cmx number of precursors taps | 1818 | % cmx number of precursors taps | ||
1831 | % spui samples per ui | 1819 | % spui samples per ui | ||
1832 | % V input signal | 1820 | % V input signal | ||
1833 | %speed ups implemented: | 1821 | %speed ups implemented: | ||
1834 | %1) ignore C(i)=0. No need to circshift and then multiply by 0 | 1822 | %1) ignore C(i)=0. No need to circshift and then multiply by 0 | ||
1835 | %2) change ishift to shift an extra -cmx. This avoids extra circshift at the end | 1823 | %2) change ishift to shift an extra -cmx. This avoids extra circshift at the end | ||
1836 | 1824 | ||||
1837 | V0=0; | 1825 | V0=0; | ||
1838 | if iscolumn(V); V=V.';end | 1826 | if iscolumn(V); V=V.';end | ||
1839 | for i=1:length(C) | 1827 | for i=1:length(C) | ||
1840 | if C(i)~=0 | 1828 | if C(i)~=0 | ||
1841 | ishift=(i-1-cmx)*spui; | 1829 | ishift=(i-1-cmx)*spui; | ||
1842 | V0=circshift(V',[ishift,0])*C(i)+V0; | 1830 | V0=circshift(V',[ishift,0])*C(i)+V0; | ||
1843 | end | 1831 | end | ||
1844 | end | 1832 | end | ||
1845 | %V0=circshift(V0,[(-cmx)*spui,0]); | 1833 | %V0=circshift(V0,[(-cmx)*spui,0]); | ||
1846 | % disp(max(V0)); | 1834 | % disp(max(V0)); | ||
1847 | 1835 | ||||
1848 | 1836 | ||||
1849 | % begin yasuo patch 12/11/2018 | 1837 | % begin yasuo patch 12/11/2018 | ||
1850 | % calculate sigma (standard deviation) value of PDF | 1838 | % calculate sigma (standard deviation) value of PDF | ||
1851 | function [ V0 ] = FFE_Fast( C,V_shift ) | 1839 | function [ V0 ] = FFE_Fast( C,V_shift ) | ||
1852 | % C FFE taps | 1840 | % C FFE taps | ||
1853 | % V input signal separated into length(C) columns with circshift already performed | 1841 | % V input signal separated into length(C) columns with circshift already performed | ||
1854 | % This function is only to speed up FFE in optimize_fom. Since the signal that is being | 1842 | % This function is only to speed up FFE in optimize_fom. Since the signal that is being | ||
1855 | % shifted is the same for all loops of TXFFE taps, a lot of time can be | 1843 | % shifted is the same for all loops of TXFFE taps, a lot of time can be | ||
1856 | % saved by pre-shifting it and remembering it across loops | 1844 | % saved by pre-shifting it and remembering it across loops | ||
1857 | % Another speed up: only multiply by indices of C that are not 0 | 1845 | % Another speed up: only multiply by indices of C that are not 0 | ||
1858 | 1846 | ||||
1859 | V0=0; | 1847 | V0=0; | ||
1860 | for i=1:length(C) | 1848 | for i=1:length(C) | ||
1861 | if C(i)~=0 | 1849 | if C(i)~=0 | ||
1862 | V0=V_shift(:,i)*C(i)+V0; | 1850 | V0=V_shift(:,i)*C(i)+V0; | ||
1863 | end | 1851 | end | ||
1864 | end | 1852 | end | ||
1865 | function idx = FOM_rxffe_floating_taps(param,h,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,isi_start,isi_end) | 1853 | function idx = FOM_rxffe_floating_taps(param,h,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,isi_start,isi_end) | ||
1866 | 1854 | ||||
1867 | hisi=h(isi_start:isi_end); | 1855 | hisi=h(isi_start:isi_end); | ||
1868 | hisi=hisi(param.N_tail_start:param.N_bmax); | 1856 | hisi=hisi(param.N_tail_start:param.N_bmax); | ||
1869 | bank_size = param.N_bf; | 1857 | bank_size = param.N_bf; | ||
1870 | num_groups = param.N_bg; | 1858 | num_groups = param.N_bg; | ||
1871 | 1859 | ||||
1872 | 1860 | ||||
1873 | %start with one by one Floating Tap | 1861 | %start with one by one Floating Tap | ||
1874 | num_isi=length(hisi); | 1862 | num_isi=length(hisi); | ||
1875 | max_isi=num_isi-bank_size+1; | 1863 | max_isi=num_isi-bank_size+1; | ||
1876 | valid_tap_locations=1:max_isi; | 1864 | valid_tap_locations=1:max_isi; | ||
1877 | all_idx=[]; | 1865 | all_idx=[]; | ||
1878 | for j=1:num_groups | 1866 | for j=1:num_groups | ||
1879 | best_FOM=ones(1,length(valid_tap_locations))*-Inf; | 1867 | best_FOM=ones(1,length(valid_tap_locations))*-Inf; | ||
1880 | for k=1:length(valid_tap_locations) | 1868 | for k=1:length(valid_tap_locations) | ||
1881 | this_location=valid_tap_locations(k); | 1869 | this_location=valid_tap_locations(k); | ||
1882 | new_idx = [all_idx this_location:this_location+bank_size-1]; | 1870 | new_idx = [all_idx this_location:this_location+bank_size-1]; | ||
1883 | new_idx=sort(new_idx); | 1871 | new_idx=sort(new_idx); | ||
1884 | new_idx = new_idx+param.N_tail_start-1; | 1872 | new_idx = new_idx+param.N_tail_start-1; | ||
1885 | %calculate FOM for each one | 1873 | %calculate FOM for each one | ||
1886 | [~,best_FOM(k),~,~] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,new_idx); | 1874 | [~,best_FOM(k),~,~] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,new_idx); | ||
1887 | end | 1875 | end | ||
1888 | %choose the location with best FOM | 1876 | %choose the location with best FOM | ||
1889 | %add it to the "all_idx" list and remove it from valid locations | 1877 | %add it to the "all_idx" list and remove it from valid locations | ||
1890 | [~,best_FOM_idx]=max(best_FOM); | 1878 | [~,best_FOM_idx]=max(best_FOM); | ||
1891 | start_tap = valid_tap_locations(best_FOM_idx); | 1879 | start_tap = valid_tap_locations(best_FOM_idx); | ||
1892 | all_idx=[all_idx start_tap:start_tap+bank_size-1]; | 1880 | all_idx=[all_idx start_tap:start_tap+bank_size-1]; | ||
1893 | remove_range=best_FOM_idx:best_FOM_idx+bank_size-1; | 1881 | remove_range=best_FOM_idx:best_FOM_idx+bank_size-1; | ||
1894 | remove_range(remove_range>length(valid_tap_locations))=[]; | 1882 | remove_range(remove_range>length(valid_tap_locations))=[]; | ||
1895 | valid_tap_locations(remove_range)=[]; | 1883 | valid_tap_locations(remove_range)=[]; | ||
1896 |
| 1884 |
| ||
1897 | %Also remove illegal taps from valid locations | 1885 | %Also remove illegal taps from valid locations | ||
1898 | %illegal taps are ones that would overlap with the chosen bank | 1886 | %illegal taps are ones that would overlap with the chosen bank | ||
1899 | bad_tap=start_tap-bank_size+1:start_tap-1; | 1887 | bad_tap=start_tap-bank_size+1:start_tap-1; | ||
1900 | bad_tap(bad_tap<1)=[]; | 1888 | bad_tap(bad_tap<1)=[]; | ||
1901 | for n=1:length(bad_tap) | 1889 | for n=1:length(bad_tap) | ||
1902 | bad_tap_idx=find(valid_tap_locations==bad_tap(n)); | 1890 | bad_tap_idx=find(valid_tap_locations==bad_tap(n)); | ||
1903 | if ~isempty(bad_tap_idx) | 1891 | if ~isempty(bad_tap_idx) | ||
1904 | valid_tap_locations(bad_tap_idx)=[]; | 1892 | valid_tap_locations(bad_tap_idx)=[]; | ||
1905 | end | 1893 | end | ||
1906 | end | 1894 | end | ||
1907 | end | 1895 | end | ||
1908 | 1896 | ||||
1909 | %put idx back in the right location (adding N_tail_start) | 1897 | %put idx back in the right location (adding N_tail_start) | ||
1910 | idx = all_idx+param.N_tail_start-1; | 1898 | idx = all_idx+param.N_tail_start-1; | ||
1911 | idx = sort(idx); | 1899 | idx = sort(idx); | ||
1912 | function [ V0 ] = Fract_T_FFE( V , skew_step) | 1900 | function [ V0 ] = Fract_T_FFE( V , skew_step) | ||
1913 | % skew_step sub UI skew assuming param.samples_per_ui | 1901 | % skew_step sub UI skew assuming param.samples_per_ui | ||
1914 | % V input signal | 1902 | % V input signal | ||
1915 | % V0 output signal | 1903 | % V0 output signal | ||
1916 | % Richard Mellitz 8/17/2021 | 1904 | % Richard Mellitz 8/17/2021 | ||
1917 | V0=0; | 1905 | V0=0; | ||
1918 | if iscolumn(V); V=V.';end | 1906 | if iscolumn(V); V=V.';end | ||
1919 | ishift=skew_step; | 1907 | ishift=skew_step; | ||
1920 | V0=circshift(V',[ishift,0])'+V; | 1908 | V0=circshift(V',[ishift,0])'+V; | ||
1921 | V0=V0/2; | 1909 | V0=V0/2; | ||
1922 | function out=Full_Grid_Matrix(in) | 1910 | function out=Full_Grid_Matrix(in) | ||
1923 | 1911 | ||||
1924 | %create a full grid matrix of input variables | 1912 | %create a full grid matrix of input variables | ||
1925 | %used to create the full grid of all txffe cases | 1913 | %used to create the full grid of all txffe cases | ||
1926 | %example: | 1914 | %example: | ||
1927 | %Full_Grid_Matrix({ [1 2] [100 200] }) | 1915 | %Full_Grid_Matrix({ [1 2] [100 200] }) | ||
1928 | %out = | 1916 | %out = | ||
1929 | % 1 100 | 1917 | % 1 100 | ||
1930 | % 1 200 | 1918 | % 1 200 | ||
1931 | % 2 100 | 1919 | % 2 100 | ||
1932 | % 2 200 | 1920 | % 2 200 | ||
1933 | % | 1921 | % | ||
1934 | %input can also be mixed between numeric and cell of char | 1922 | %input can also be mixed between numeric and cell of char | ||
1935 | %example: | 1923 | %example: | ||
1936 | %Full_Grid_Matrix({ [1 2] {'A' 'B'} }) | 1924 | %Full_Grid_Matrix({ [1 2] {'A' 'B'} }) | ||
1937 | %out = | 1925 | %out = | ||
1938 | % {[1]} {'A'} | 1926 | % {[1]} {'A'} | ||
1939 | % {[1]} {'B'} | 1927 | % {[1]} {'B'} | ||
1940 | % {[2]} {'A'} | 1928 | % {[2]} {'A'} | ||
1941 | % {[2]} {'B'} | 1929 | % {[2]} {'B'} | ||
1942 | 1930 | ||||
1943 | if ~iscell(in) | 1931 | if ~iscell(in) | ||
1944 | error('input must be cell array of individual sweep variables'); | 1932 | error('input must be cell array of individual sweep variables'); | ||
1945 | end | 1933 | end | ||
1946 | 1934 | ||||
1947 | num_columns=length(in); | 1935 | num_columns=length(in); | ||
1948 | num_cases=prod(cellfun('length',in)); | 1936 | num_cases=prod(cellfun('length',in)); | ||
1949 | 1937 | ||||
1950 | cell_output=0; | 1938 | cell_output=0; | ||
1951 | cell_indices=cellfun(@(x) iscell(x),in); | 1939 | cell_indices=cellfun(@(x) iscell(x),in); | ||
1952 | if any(cell_indices) | 1940 | if any(cell_indices) | ||
1953 | cell_output=1; | 1941 | cell_output=1; | ||
1954 | end | 1942 | end | ||
1955 | if cell_output | 1943 | if cell_output | ||
1956 | for k=find(~cell_indices) | 1944 | for k=find(~cell_indices) | ||
1957 | in{k}=num2cell(in{k}); | 1945 | in{k}=num2cell(in{k}); | ||
1958 | end | 1946 | end | ||
1959 | end | 1947 | end | ||
1960 | 1948 | ||||
1961 | if cell_output | 1949 | if cell_output | ||
1962 | out=cell(num_cases,num_columns); | 1950 | out=cell(num_cases,num_columns); | ||
1963 | else | 1951 | else | ||
1964 | out=zeros(num_cases,num_columns); | 1952 | out=zeros(num_cases,num_columns); | ||
1965 | end | 1953 | end | ||
1966 | 1954 | ||||
1967 | %num_repetitions controls how many times each element of the column | 1955 | %num_repetitions controls how many times each element of the column | ||
1968 | %repeats. The first column is always just a copy of itself since every | 1956 | %repeats. The first column is always just a copy of itself since every | ||
1969 | %case will vary. | 1957 | %case will vary. | ||
1970 | num_repetitions=1; | 1958 | num_repetitions=1; | ||
1971 | for k=num_columns:-1:1 | 1959 | for k=num_columns:-1:1 | ||
1972 | this_column=in{k}(:); | 1960 | this_column=in{k}(:); | ||
1973 | %copy the column into a matrix to create the repetitions needed | 1961 | %copy the column into a matrix to create the repetitions needed | ||
1974 | B=repmat(this_column,[1 num_repetitions]); | 1962 | B=repmat(this_column,[1 num_repetitions]); | ||
1975 | %reshape into single column (actual repetitions) | 1963 | %reshape into single column (actual repetitions) | ||
1976 | C=reshape(B',[numel(B) 1]); | 1964 | C=reshape(B',[numel(B) 1]); | ||
1977 | %repeat the single column to build the entire length required | 1965 | %repeat the single column to build the entire length required | ||
1978 | num_repeats=num_cases/length(C); | 1966 | num_repeats=num_cases/length(C); | ||
1979 | D=repmat(C,[num_repeats 1]); | 1967 | D=repmat(C,[num_repeats 1]); | ||
1980 | out(:,k)=D; | 1968 | out(:,k)=D; | ||
1981 | %determine how many repetitions the next column needs | 1969 | %determine how many repetitions the next column needs | ||
1982 | num_repetitions=num_repetitions*length(this_column); | 1970 | num_repetitions=num_repetitions*length(this_column); | ||
1983 | end | 1971 | end | ||
1984 | function pdf=Init_PDF_Fast( EmptyPDF, values, probs) | 1972 | function pdf=Init_PDF_Fast( EmptyPDF, values, probs) | ||
1985 | % p=cpdf(type, ...) | 1973 | % p=cpdf(type, ...) | ||
1986 | % | 1974 | % | ||
1987 | % CPDF is a probability mass function for discrete distributions or an | 1975 | % CPDF is a probability mass function for discrete distributions or an | ||
1988 | % approxmation of a PDF for continuous distributions. | 1976 | % approxmation of a PDF for continuous distributions. | ||
1989 | % | 1977 | % | ||
1990 | % cpdf is internally normalized so that the sum of probabilities is 1 | 1978 | % cpdf is internally normalized so that the sum of probabilities is 1 | ||
1991 | % (regardless of bin size). | 1979 | % (regardless of bin size). | ||
1992 | 1980 | ||||
1993 | % Internal fields: | 1981 | % Internal fields: | ||
1994 | % Min: *bin number* of minimum value. | 1982 | % Min: *bin number* of minimum value. | ||
1995 | % BinSize: size of PDF bins. Bin center is the representative value. | 1983 | % BinSize: size of PDF bins. Bin center is the representative value. | ||
1996 | % Vec: vector of probabilities per bin. | 1984 | % Vec: vector of probabilities per bin. | ||
1997 | 1985 | ||||
1998 | pdf=EmptyPDF; | 1986 | pdf=EmptyPDF; | ||
1999 | 1987 | ||||
2000 | rounded_values_div_binsize=round(values/pdf.BinSize); | 1988 | rounded_values_div_binsize=round(values/pdf.BinSize); | ||
2001 | %values=pdf.BinSize*rounded_values_div_binsize; | 1989 | %values=pdf.BinSize*rounded_values_div_binsize; | ||
2002 | 1990 | ||||
2003 | % %speed up for small values round to 0 (because they are all much smaller than binsize) | 1991 | % %speed up for small values round to 0 (because they are all much smaller than binsize) | ||
2004 | % if all(values==0) | 1992 | % if all(values==0) | ||
2005 | % return; | 1993 | % return; | ||
2006 | % end | 1994 | % end | ||
2007 | % | 1995 | % | ||
2008 | % %speed up for all values rounded to the same bin | 1996 | % %speed up for all values rounded to the same bin | ||
2009 | % %The output pdf is the same as the | 1997 | % %The output pdf is the same as the | ||
2010 | % %empty pdf, but the x value is non-zero (but still scalar) | 1998 | % %empty pdf, but the x value is non-zero (but still scalar) | ||
2011 | % if all(values==values(1)) | 1999 | % if all(values==values(1)) | ||
2012 | % pdf.Min=rounded_values_div_binsize(1); | 2000 | % pdf.Min=rounded_values_div_binsize(1); | ||
2013 | % pdf.x=values(1); | 2001 | % pdf.x=values(1); | ||
2014 | % return; | 2002 | % return; | ||
2015 | % end | 2003 | % end | ||
2016 | % | 2004 | % | ||
2017 | % %The code below requires that values is | 2005 | % %The code below requires that values is | ||
2018 | % %sorted. Generally this should be true, but check to be sure | 2006 | % %sorted. Generally this should be true, but check to be sure | ||
2019 | % if ~issorted(values) | 2007 | % if ~issorted(values) | ||
2020 | % [values,si]=sort(values); | 2008 | % [values,si]=sort(values); | ||
2021 | % rounded_values_div_binsize=rounded_values_div_binsize(si); | 2009 | % rounded_values_div_binsize=rounded_values_div_binsize(si); | ||
2022 | % probs=probs(si); | 2010 | % probs=probs(si); | ||
2023 | % end | 2011 | % end | ||
2024 | 2012 | ||||
2025 | 2013 | ||||
2026 | %pdf.x=values(1):pdf.BinSize:values(end); | 2014 | %pdf.x=values(1):pdf.BinSize:values(end); | ||
2027 | pdf.x=pdf.BinSize*rounded_values_div_binsize(1):pdf.BinSize:pdf.BinSize*rounded_values_div_binsize(end); | 2015 | pdf.x=pdf.BinSize*rounded_values_div_binsize(1):pdf.BinSize:pdf.BinSize*rounded_values_div_binsize(end); | ||
2028 | pdf.Min=rounded_values_div_binsize(1); | 2016 | pdf.Min=rounded_values_div_binsize(1); | ||
2029 | 2017 | ||||
2030 | pdf.y=zeros(size(pdf.x)); | 2018 | pdf.y=zeros(size(pdf.x)); | ||
2031 | %The rounded values divided by binsize will reveal the bin number if | 2019 | %The rounded values divided by binsize will reveal the bin number if | ||
2032 | %pdf.Min is subtracted from it | 2020 | %pdf.Min is subtracted from it | ||
2033 | bin_placement=rounded_values_div_binsize-pdf.Min+1; | 2021 | bin_placement=rounded_values_div_binsize-pdf.Min+1; | ||
2034 | %Can avoid one addition by inserting the first probability | 2022 | %Can avoid one addition by inserting the first probability | ||
2035 | %actually helps when calling this 2 million times | 2023 | %actually helps when calling this 2 million times | ||
2036 | pdf.y(bin_placement(1))=probs(1); | 2024 | pdf.y(bin_placement(1))=probs(1); | ||
2037 | for k=2:length(values) | 2025 | for k=2:length(values) | ||
2038 | pdf.y(bin_placement(k)) = pdf.y(bin_placement(k))+probs(k); | 2026 | pdf.y(bin_placement(k)) = pdf.y(bin_placement(k))+probs(k); | ||
2039 | end | 2027 | end | ||
2040 | 2028 | ||||
2041 | 2029 | ||||
2042 | %Have already ensured that sum(pdf.y)=1 | 2030 | %Have already ensured that sum(pdf.y)=1 | ||
2043 | %pdf.y=pdf.y/sum(pdf.y); | 2031 | %pdf.y=pdf.y/sum(pdf.y); | ||
2044 | 2032 | ||||
2045 | % if any(~isreal(pdf.y)) || any(pdf.y<0) | 2033 | % if any(~isreal(pdf.y)) || any(pdf.y<0) | ||
2046 | % error('PDF must be real and nonnegative'); | 2034 | % error('PDF must be real and nonnegative'); | ||
2047 | % end | 2035 | % end | ||
2048 | 2036 | ||||
2049 | % pMax=pdf.Min+length(pdf.y)-1; | 2037 | % pMax=pdf.Min+length(pdf.y)-1; | ||
2050 | % pdf.x = values(1):pdf.BinSize:pMax*pdf.BinSize; | 2038 | % pdf.x = values(1):pdf.BinSize:pMax*pdf.BinSize; | ||
2051 | function [MLSE_results] = MLSE(param,alpha,A_s,A_ni,PDF,CDF) | 2039 | function [MLSE_results] = MLSE(param,alpha,A_s,A_ni,PDF,CDF) | ||
2052 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | 2040 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | ||
2053 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | 2041 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | ||
2054 | % Based on oif2022.580.00 / IEEE802. shakiba_3dj_01_230116 by Hossein Shakiba | 2042 | % Based on oif2022.580.00 / IEEE802. shakiba_3dj_01_230116 by Hossein Shakiba | ||
2055 | 2043 | ||||
2056 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | 2044 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | ||
2057 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | 2045 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | ||
2058 | 2046 | ||||
2059 | %% step 0 | 2047 | %% step 0 | ||
2060 | COM_from_matlab=20*log10(A_s/A_ni); | 2048 | COM_from_matlab=20*log10(A_s/A_ni); | ||
2061 | L=param.levels; | 2049 | L=param.levels; | ||
2062 | DER0=param.specBER; | 2050 | DER0=param.specBER; | ||
2063 | %% step 1 from slide 6/5 | 2051 | %% step 1 from slide 6/5 | ||
2064 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | 2052 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | ||
2065 | main=A_peak; | 2053 | main=A_peak; | ||
2066 | k_DER=qfuncinv(param.specBER); | 2054 | k_DER=qfuncinv(param.specBER); | ||
2067 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | 2055 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | ||
2068 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | 2056 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | ||
2069 | COM=SNR_dB-10*log10((L^2-1)/3*k_DER^2); | 2057 | COM=SNR_dB-10*log10((L^2-1)/3*k_DER^2); | ||
2070 | % sprintf('COM from Matlab %g dB\n COM from slide 6 using Gaussian asumptions %g dB\n', COM_from_matlab ,COM) | 2058 | % sprintf('COM from Matlab %g dB\n COM from slide 6 using Gaussian asumptions %g dB\n', COM_from_matlab ,COM) | ||
2071 | if A_s >= A_ni | 2059 | if A_s >= A_ni | ||
2072 | %% step 2 slide 10/8 | 2060 | %% step 2 slide 10/8 | ||
2073 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | 2061 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | ||
2074 | %% step 2 slide 10/8 | 2062 | %% step 2 slide 10/8 | ||
2075 | % DER_DFE= 2/ ( L/(L-1) -qfunc( (1-2*alpha)*main/(L-1)/sigma_noise ) )*(qfunc(main/(L-1)/sigma_noise)); | 2063 | % DER_DFE= 2/ ( L/(L-1) -qfunc( (1-2*alpha)*main/(L-1)/sigma_noise ) )*(qfunc(main/(L-1)/sigma_noise)); | ||
2076 | % DER_DFE_CDF=2/ ( L/(L-1)-CDF_ev( (1-2*alpha)*main/(L-1),PDF,CDF ) )*CDF_ev((main/(L-1)),PDF,CDF); | 2064 | % DER_DFE_CDF=2/ ( L/(L-1)-CDF_ev( (1-2*alpha)*main/(L-1),PDF,CDF ) )*CDF_ev((main/(L-1)),PDF,CDF); | ||
2077 | %% step 3 side 11/9 | 2065 | %% step 3 side 11/9 | ||
2078 | j=1:200; | 2066 | j=1:200; | ||
2079 | DER_MLSE=2*sum( j .* ((L-1)/L).^j .* qfunc( sqrt(1+(j-1)*(1-alpha)^2+alpha^2).* main/((L-1)*sigma_noise ) )); | 2067 | DER_MLSE=2*sum( j .* ((L-1)/L).^j .* qfunc( sqrt(1+(j-1)*(1-alpha)^2+alpha^2).* main/((L-1)*sigma_noise ) )); | ||
2080 | DER_MLSE_CDF=0; jj=1; | 2068 | DER_MLSE_CDF=0; jj=1; | ||
2081 | DER_delta = inf; | 2069 | DER_delta = inf; | ||
2082 | while DER_delta > .001 | 2070 | while DER_delta > .001 | ||
2083 | last_DER_MLSE_CDF=DER_MLSE_CDF; | 2071 | last_DER_MLSE_CDF=DER_MLSE_CDF; | ||
2084 | DER_MLSE_CDF=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDF; | 2072 | DER_MLSE_CDF=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDF; | ||
2085 | DER_delta= 1-last_DER_MLSE_CDF/DER_MLSE_CDF; | 2073 | DER_delta= 1-last_DER_MLSE_CDF/DER_MLSE_CDF; | ||
2086 | jj=jj+1; | 2074 | jj=jj+1; | ||
2087 | end | 2075 | end | ||
2088 | %% step 4 slide 12/10 | 2076 | %% step 4 slide 12/10 | ||
2089 | SNR_DFE_eqivalent=SNR_DFE*(... | 2077 | SNR_DFE_eqivalent=SNR_DFE*(... | ||
2090 | (L-1)*sigma_noise/main * qfuncinv(... | 2078 | (L-1)*sigma_noise/main * qfuncinv(... | ||
2091 | 1/2 *DER_MLSE*(L/(L-1) - qfunc((1-2*alpha)*main/(L-1)*sigma_noise )) ... | 2079 | 1/2 *DER_MLSE*(L/(L-1) - qfunc((1-2*alpha)*main/(L-1)*sigma_noise )) ... | ||
2092 | ) ... | 2080 | ) ... | ||
2093 | )^2; | 2081 | )^2; | ||
2094 | SNR_DFE_eqivalent_CDF=SNR_DFE*(... | 2082 | SNR_DFE_eqivalent_CDF=SNR_DFE*(... | ||
2095 | (L-1)/main * CDF_inv_ev(... | 2083 | (L-1)/main * CDF_inv_ev(... | ||
2096 | 1/2 *DER_MLSE_CDF*(L/(L-1) - CDF_ev((1-2*alpha)*main/(L-1),PDF,CDF )) ... | 2084 | 1/2 *DER_MLSE_CDF*(L/(L-1) - CDF_ev((1-2*alpha)*main/(L-1),PDF,CDF )) ... | ||
2097 | ,PDF, CDF ) ... | 2085 | ,PDF, CDF ) ... | ||
2098 | )^2; | 2086 | )^2; | ||
2099 | 2087 | ||||
2100 | %% step 5 slide 13/11 | 2088 | %% step 5 slide 13/11 | ||
2101 | delta_com=10*log10(SNR_DFE_eqivalent/SNR_DFE); | 2089 | delta_com=10*log10(SNR_DFE_eqivalent/SNR_DFE); | ||
2102 | delta_com_CDF=10*log10(SNR_DFE_eqivalent_CDF/SNR_DFE); | 2090 | delta_com_CDF=10*log10(SNR_DFE_eqivalent_CDF/SNR_DFE); | ||
2103 | new_com_CDF=COM_from_matlab+delta_com_CDF; | 2091 | new_com_CDF=COM_from_matlab+delta_com_CDF; | ||
2104 | else | 2092 | else | ||
2105 | warning('MLSE not applied because there is more noise than signal') | 2093 | warning('MLSE not applied because there is more noise than signal') | ||
2106 | DER_MLSE=[]; | 2094 | DER_MLSE=[]; | ||
2107 | DER_MLSE_CDF=[]; | 2095 | DER_MLSE_CDF=[]; | ||
2108 | SNR_DFE_eqivalent=[]; | 2096 | SNR_DFE_eqivalent=[]; | ||
2109 | SNR_DFE_eqivalent_CDF=[]; | 2097 | SNR_DFE_eqivalent_CDF=[]; | ||
2110 | new_com_CDF=COM_from_matlab; | 2098 | new_com_CDF=COM_from_matlab; | ||
2111 | delta_com_CDF=0; | 2099 | delta_com_CDF=0; | ||
2112 | delta_com=0; | 2100 | delta_com=0; | ||
2113 | SNR_DFE=[]; | 2101 | SNR_DFE=[]; | ||
2114 | end | 2102 | end | ||
− | 2115 |
| |||
2116 | %% | ||||
2117 | MLSE_results.COM_from_matlab=COM_from_matlab; | ||||
2118 | MLSE_results.SNR_DFE=SNR_DFE; | ||||
2119 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | ||||
2120 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | ||||
2121 | MLSE_results.sigma_noise=sigma_noise; | ||||
2122 | MLSE_results.SNR_dB=SNR_dB ; | ||||
2123 | MLSE_results.SNR_DFE_eqivalent_Gaussian=SNR_DFE_eqivalent; | ||||
2124 | MLSE_results.SNR_DFE_eqivalent_CDF=SNR_DFE_eqivalent_CDF; | ||||
2125 | MLSE_results.COM_Gaussian=new_com_CDF; | ||||
2126 | MLSE_results.COM_CDF=new_com_CDF; | ||||
2127 | MLSE_results.k_DER=k_DER; | ||||
2128 | MLSE_results.delta_com_CDF=delta_com_CDF; | ||||
2129 | MLSE_results.delta_com_Gaussian=delta_com; | ||||
2130 | 2103 | ||||
− | 2131 |
| |||
2132 | |||||
2133 | function [MLSE_results] = MLSE_U1_c(param,alpha,A_s,A_ni,PDF,CDF,PSD_results) | ||||
2134 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | ||||
2135 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | ||||
2136 | % Based IEEE802.3dj presenations shakiba_3dj_01_230116 and shakiba_3dj_elec_01a_230504 | ||||
2137 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | ||||
2138 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | ||||
2139 | %% step 0 | ||||
2140 | COM_from_matlab=20*log10(A_s/A_ni); | ||||
2141 | L=param.levels; | ||||
2142 | DER0=param.specBER; | ||||
2143 | %% step 1 from slide 6 shakiba_3dj_01_230116 | ||||
2144 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | ||||
2145 | main=A_peak; | ||||
2146 | k_DER=qfuncinv(param.specBER); | ||||
2147 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | ||||
2148 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | ||||
2149 | % if A_s >= A_ni | ||||
2150 | if 1 | ||||
2151 | %% step 2 slide 10 shakiba_3dj_01_230116 | ||||
2152 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | ||||
2153 | %% step 2 slide 10 not used | ||||
2154 | % DER_DFE= 2/ ( L/(L-1) -qfunc( (1-2*alpha)*main/(L-1)/sigma_noise ) )*(qfunc(main/(L-1)/sigma_noise)); | ||||
2155 | DER_DFE_CDF=2*(L-1)/L*(CDF_ev(main/(L-1),PDF,CDF ) ); | ||||
2156 | %% step 3 side 18 shakiba_3dj_elec_01a_230504 | ||||
2157 | S_n=PSD_results.Sn_rho; % total agregate noise PSD | ||||
2158 | Rn=ifft(S_n)*param.fb; | ||||
2159 | Rho_row=Rn/Rn(1); | ||||
2160 | Rn_len=length(Rn); | ||||
2161 | alphas_row=[ 1 ones(1,Rn_len-2)*(1-alpha) alpha]; | ||||
2162 | for j=1:Rn_len | ||||
2163 | alphas_row(j)=alphas_row(j)*(-1)^(j+1); | ||||
2164 | end | ||||
2165 | rho_noiseEE_row=Rho_row.*alphas_row; | ||||
2166 | rho_noiseEE=toeplitz(rho_noiseEE_row,rho_noiseEE_row); | ||||
2167 | for j=1:Rn_len | ||||
2168 | rho_noiseEE(j,j)=(1-alpha)^2; | ||||
2169 | end | ||||
2170 | rho_noiseEE(1,1)=1; | ||||
2171 | rho_noiseEE(Rn_len,Rn_len)=alpha^2; | ||||
2172 | rho_noiseEE=rho_noiseEE*sigma_noise^2; | ||||
2173 | % determine complete matrix | ||||
2174 | PDFnoiseiEE=(conv_fct( scalePDF(PDF,(1-alpha) ) , scalePDF( PDF,alpha) )); | ||||
2175 | CDFnoiseiEE=cumsum(PDFnoiseiEE.y); | ||||
2176 | %% shakiba_3dj_elec_01a_230504 slide 17 | ||||
2177 | j=1:Rn_len; | ||||
2178 | DER_MLSE=[]; | ||||
2179 | DER_MLSE_CDF=0; jj=1; | ||||
2180 | DER_MLSE_CDFold=0; | ||||
2181 | DER_delta = inf; | ||||
2182 | % slight modified for PAM4 DER vs SER | ||||
2183 | while DER_delta > .0001 && jj<=Rn_len || jj==1 | ||||
2184 | last_DER_MLSE_CDF=DER_MLSE_CDF; | ||||
2185 | rho_noiseJEE=rho_noiseEE(1:jj,1:jj); | ||||
2186 | DER_MLSE_CDF= ... | ||||
2187 | 2*( (L-1)/L )^jj *( CDF_ev( main/(L-1) * sqrt(trace(rho_noiseJEE))/sqrt(sum(sum((rho_noiseJEE))))*3/2 ,PDF,CDF) )+DER_MLSE_CDF; | ||||
2188 | DER_MLSE_CDFold=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDFold; | ||||
2189 | DER_delta= abs(last_DER_MLSE_CDF-DER_MLSE_CDF)/DER_MLSE_CDF; | ||||
2190 | jj=jj+1; | ||||
2191 | end | ||||
2192 | %% shakiba_3dj_elec_01a_230504 slide 19 | ||||
2193 | SNR_DFE_eqivalent_CDF=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1/2*L/(L-1)*DER_MLSE_CDF ,PDFnoiseiEE, CDFnoiseiEE) )^2 ; | ||||
2194 | % SNR_DFE_eqivalent_CDF1=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1-1/2*L/(L-1)*DER_MLSE_CDF1 ,PDF, CDF ) )^2 ; | ||||
2195 | SNR_DFE_eqivalent_CDFold=SNR_DFE*(... | ||||
2196 | (L-1)/main * CDF_inv_ev(... | ||||
2197 | 1/2 *DER_MLSE_CDFold*(L/(L-1) - CDF_ev((1-2*alpha)*main/(L-1),PDF,CDF )) ... | ||||
2198 | ,PDF, CDF ) ... | ||||
2199 | )^2; | ||||
2200 | %% step 5 shakiba_3dj_01_230116 slide 13 | ||||
2201 | delta_com=[]; | ||||
2202 | delta_com_CDF=10*log10(SNR_DFE_eqivalent_CDF/SNR_DFE); | ||||
2203 | delta_com_CDFold=10*log10(SNR_DFE_eqivalent_CDFold/SNR_DFE); | ||||
2204 | new_com_CDF=COM_from_matlab+delta_com_CDF; | ||||
2205 | else | ||||
2206 | warning('MLSE not applied because there is more noise than signal') | ||||
2207 | DER_MLSE=[]; | ||||
2208 | DER_MLSE_CDF=[]; | ||||
2209 | SNR_DFE_eqivalent=[]; | ||||
2210 | SNR_DFE_eqivalent_CDF=[]; | ||||
2211 | new_com_CDF=COM_from_matlab; | ||||
2212 | delta_com_CDF=0; | ||||
2213 | delta_com=0; | ||||
2214 | SNR_DFE=[]; | ||||
2215 | end | ||||
2216 | SNR_DFE_eqivalent=[]; | ||||
2217 | %% | 2104 | %% | ||
2218 | MLSE_results.COM_from_matlab=COM_from_matlab; | 2105 | MLSE_results.COM_from_matlab=COM_from_matlab; | ||
2219 | MLSE_results.SNR_DFE=SNR_DFE; | 2106 | MLSE_results.SNR_DFE=SNR_DFE; | ||
2220 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | 2107 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | ||
2221 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | 2108 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | ||
2222 | MLSE_results.sigma_noise=sigma_noise; | 2109 | MLSE_results.sigma_noise=sigma_noise; | ||
2223 | MLSE_results.SNR_dB=SNR_dB ; | 2110 | MLSE_results.SNR_dB=SNR_dB ; | ||
2224 | MLSE_results.SNR_DFE_eqivalent_Gaussian=SNR_DFE_eqivalent; | 2111 | MLSE_results.SNR_DFE_eqivalent_Gaussian=SNR_DFE_eqivalent; | ||
2225 | MLSE_results.SNR_DFE_eqivalent_CDF=SNR_DFE_eqivalent_CDF; | 2112 | MLSE_results.SNR_DFE_eqivalent_CDF=SNR_DFE_eqivalent_CDF; | ||
2226 | MLSE_results.COM_Gaussian=new_com_CDF; | 2113 | MLSE_results.COM_Gaussian=new_com_CDF; | ||
2227 | MLSE_results.COM_CDF=new_com_CDF; | 2114 | MLSE_results.COM_CDF=new_com_CDF; | ||
2228 | MLSE_results.k_DER=k_DER; | 2115 | MLSE_results.k_DER=k_DER; | ||
2229 | MLSE_results.delta_com_CDF=delta_com_CDF; | 2116 | MLSE_results.delta_com_CDF=delta_com_CDF; | ||
2230 | MLSE_results.delta_com_Gaussian=delta_com; | 2117 | MLSE_results.delta_com_Gaussian=delta_com; | ||
2231 | 2118 | ||||
2232 | 2119 | ||||
2233 | 2120 | ||||
2234 | function [MLSE_results] = MLSE_U3(param,alpha,A_s,A_ni,PDF,CDF,PSD_results) | 2121 | function [MLSE_results] = MLSE_U3(param,alpha,A_s,A_ni,PDF,CDF,PSD_results) | ||
2235 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | 2122 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | ||
2236 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | 2123 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | ||
2237 | % Based IEEE802.3dj presenations shakiba_3dj_01_230116 and shakiba_3dj_elec_01a_230504 | 2124 | % Based IEEE802.3dj presenations shakiba_3dj_01_230116 and shakiba_3dj_elec_01a_230504 | ||
2238 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | 2125 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | ||
2239 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | 2126 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | ||
2240 | %% step 0 | 2127 | %% step 0 | ||
2241 | COM_from_matlab=20*log10(A_s/A_ni); | 2128 | COM_from_matlab=20*log10(A_s/A_ni); | ||
2242 | L=param.levels; | 2129 | L=param.levels; | ||
2243 | DER0=param.specBER; | 2130 | DER0=param.specBER; | ||
2244 | %% step 1 from slide 6 shakiba_3dj_01_230116 | 2131 | %% step 1 from slide 6 shakiba_3dj_01_230116 | ||
2245 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | 2132 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | ||
2246 | main=A_peak; | 2133 | main=A_peak; | ||
2247 | k_DER=qfuncinv(param.specBER); | 2134 | k_DER=qfuncinv(param.specBER); | ||
2248 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | 2135 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | ||
2249 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | 2136 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | ||
2250 | % if A_s >= A_ni | 2137 | % if A_s >= A_ni | ||
2251 | if 1 | 2138 | if 1 | ||
2252 | %% step 2 slide 10 shakiba_3dj_01_230116 | 2139 | %% step 2 slide 10 shakiba_3dj_01_230116 | ||
2253 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | 2140 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | ||
2254 | %% step 2 slide 10 not used | 2141 | %% step 2 slide 10 not used | ||
2255 | % DER_DFE= 2/ ( L/(L-1) -qfunc( (1-2*alpha)*main/(L-1)/sigma_noise ) )*(qfunc(main/(L-1)/sigma_noise)); | 2142 | % DER_DFE= 2/ ( L/(L-1) -qfunc( (1-2*alpha)*main/(L-1)/sigma_noise ) )*(qfunc(main/(L-1)/sigma_noise)); | ||
2256 | DER_DFE_CDF=2*(L-1)/L*(CDF_ev(main/(L-1),PDF,CDF ) ); | 2143 | DER_DFE_CDF=2*(L-1)/L*(CDF_ev(main/(L-1),PDF,CDF ) ); | ||
2257 | %% step 3 side 18 shakiba_3dj_elec_01a_230504 | 2144 | %% step 3 side 18 shakiba_3dj_elec_01a_230504 | ||
2258 | S_n=PSD_results.S_n; % total agregate noise PSD | 2145 | S_n=PSD_results.S_n; % total agregate noise PSD | ||
2259 | Rn=ifft(S_n)*param.fb; | 2146 | Rn=ifft(S_n)*param.fb; | ||
2260 | Rho_row=Rn/Rn(1); | 2147 | Rho_row=Rn/Rn(1); | ||
2261 | Rn_len=length(Rn); | 2148 | Rn_len=length(Rn); | ||
2262 | alphas_row=[ 1 ones(1,Rn_len-2)*(1-alpha) alpha]; | 2149 | alphas_row=[ 1 ones(1,Rn_len-2)*(1-alpha) alpha]; | ||
2263 | for j=1:Rn_len | 2150 | for j=1:Rn_len | ||
2264 | alphas_row(j)=alphas_row(j)*(-1)^(j+1); | 2151 | alphas_row(j)=alphas_row(j)*(-1)^(j+1); | ||
2265 | end | 2152 | end | ||
2266 | rho_noiseEE_row=Rho_row.*alphas_row; | 2153 | rho_noiseEE_row=Rho_row.*alphas_row; | ||
2267 | rho_noiseEE=toeplitz(rho_noiseEE_row,rho_noiseEE_row); | 2154 | rho_noiseEE=toeplitz(rho_noiseEE_row,rho_noiseEE_row); | ||
2268 | for j=1:Rn_len | 2155 | for j=1:Rn_len | ||
2269 | rho_noiseEE(j,j)=(1-alpha)^2; | 2156 | rho_noiseEE(j,j)=(1-alpha)^2; | ||
2270 | end | 2157 | end | ||
2271 | rho_noiseEE(1,1)=1; | 2158 | rho_noiseEE(1,1)=1; | ||
2272 | rho_noiseEE(Rn_len,Rn_len)=alpha^2; | 2159 | rho_noiseEE(Rn_len,Rn_len)=alpha^2; | ||
2273 | rho_noiseEE=rho_noiseEE*sigma_noise^2; | 2160 | rho_noiseEE=rho_noiseEE*sigma_noise^2; | ||
2274 | % determine complete matrix | 2161 | % determine complete matrix | ||
2275 | PDFnoiseiEE=(conv_fct( scalePDF(PDF,(1-alpha) ) , scalePDF( PDF,alpha) )); | 2162 | PDFnoiseiEE=(conv_fct( scalePDF(PDF,(1-alpha) ) , scalePDF( PDF,alpha) )); | ||
2276 | CDFnoiseiEE=cumsum(PDFnoiseiEE.y); | 2163 | CDFnoiseiEE=cumsum(PDFnoiseiEE.y); | ||
2277 | %% shakiba_3dj_elec_01a_230504 slide 17 | 2164 | %% shakiba_3dj_elec_01a_230504 slide 17 | ||
2278 | j=1:Rn_len; | 2165 | j=1:Rn_len; | ||
2279 | DER_MLSE=[]; | 2166 | DER_MLSE=[]; | ||
2280 | DER_MLSE_CDF=0; jj=1; | 2167 | DER_MLSE_CDF=0; jj=1; | ||
2281 | DER_MLSE_CDFold=0; | 2168 | DER_MLSE_CDFold=0; | ||
2282 | DER_delta = inf; | 2169 | DER_delta = inf; | ||
2283 | % slight modified for PAM4 DER vs SER | 2170 | % slight modified for PAM4 DER vs SER | ||
2284 | while DER_delta > .0001 && jj<=Rn_len || jj==1 | 2171 | while DER_delta > .0001 && jj<=Rn_len || jj==1 | ||
2285 | last_DER_MLSE_CDF=DER_MLSE_CDF; | 2172 | last_DER_MLSE_CDF=DER_MLSE_CDF; | ||
2286 | rho_noiseJEE=rho_noiseEE(1:jj,1:jj); | 2173 | rho_noiseJEE=rho_noiseEE(1:jj,1:jj); | ||
2287 | DER_MLSE_CDF= ... | 2174 | DER_MLSE_CDF= ... | ||
2288 | 2*( (L-1)/L )^jj *( CDF_ev( main/(L-1) * sqrt(trace(rho_noiseJEE))/sqrt(sum(sum((rho_noiseJEE))))*3/2 ,PDF,CDF) )+DER_MLSE_CDF; | 2175 | 2*( (L-1)/L )^jj *( CDF_ev( main/(L-1) * sqrt(trace(rho_noiseJEE))/sqrt(sum(sum((rho_noiseJEE))))*3/2 ,PDF,CDF) )+DER_MLSE_CDF; | ||
2289 | DER_MLSE_CDFold=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDFold; | 2176 | DER_MLSE_CDFold=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDFold; | ||
2290 | DER_delta= abs(last_DER_MLSE_CDF-DER_MLSE_CDF)/DER_MLSE_CDF; | 2177 | DER_delta= abs(last_DER_MLSE_CDF-DER_MLSE_CDF)/DER_MLSE_CDF; | ||
2291 | jj=jj+1; | 2178 | jj=jj+1; | ||
2292 | end | 2179 | end | ||
2293 | %% shakiba_3dj_elec_01a_230504 slide 19 | 2180 | %% shakiba_3dj_elec_01a_230504 slide 19 | ||
2294 | SNR_DFE_eqivalent_CDF=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1/2*L/(L-1)*DER_MLSE_CDF ,PDFnoiseiEE, CDFnoiseiEE) )^2 ; | 2181 | SNR_DFE_eqivalent_CDF=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1/2*L/(L-1)*DER_MLSE_CDF ,PDFnoiseiEE, CDFnoiseiEE) )^2 ; | ||
2295 | % SNR_DFE_eqivalent_CDF1=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1-1/2*L/(L-1)*DER_MLSE_CDF1 ,PDF, CDF ) )^2 ; | 2182 | % SNR_DFE_eqivalent_CDF1=SNR_DFE*( (L-1)/main * CDF_inv_ev( 1-1/2*L/(L-1)*DER_MLSE_CDF1 ,PDF, CDF ) )^2 ; | ||
2296 | SNR_DFE_eqivalent_CDFold=SNR_DFE*(... | 2183 | SNR_DFE_eqivalent_CDFold=SNR_DFE*(... | ||
2297 | (L-1)/main * CDF_inv_ev(... | 2184 | (L-1)/main * CDF_inv_ev(... | ||
2298 | 1/2 *DER_MLSE_CDFold*(L/(L-1) - CDF_ev((1-2*alpha)*main/(L-1),PDF,CDF )) ... | 2185 | 1/2 *DER_MLSE_CDFold*(L/(L-1) - CDF_ev((1-2*alpha)*main/(L-1),PDF,CDF )) ... | ||
2299 | ,PDF, CDF ) ... | 2186 | ,PDF, CDF ) ... | ||
2300 | )^2; | 2187 | )^2; | ||
2301 | %% step 5 shakiba_3dj_01_230116 slide 13 | 2188 | %% step 5 shakiba_3dj_01_230116 slide 13 | ||
2302 | delta_com=[]; | 2189 | delta_com=[]; | ||
2303 | delta_com_CDF=10*log10(SNR_DFE_eqivalent_CDF/SNR_DFE); | 2190 | delta_com_CDF=10*log10(SNR_DFE_eqivalent_CDF/SNR_DFE); | ||
2304 | delta_com_CDFold=10*log10(SNR_DFE_eqivalent_CDFold/SNR_DFE); | 2191 | delta_com_CDFold=10*log10(SNR_DFE_eqivalent_CDFold/SNR_DFE); | ||
2305 | new_com_CDF=COM_from_matlab+delta_com_CDF; | 2192 | new_com_CDF=COM_from_matlab+delta_com_CDF; | ||
2306 | else | 2193 | else | ||
2307 | warning('MLSE not applied because there is more noise than signal') | 2194 | warning('MLSE not applied because there is more noise than signal') | ||
2308 | DER_MLSE=[]; | 2195 | DER_MLSE=[]; | ||
2309 | DER_MLSE_CDF=[]; | 2196 | DER_MLSE_CDF=[]; | ||
2310 | SNR_DFE_eqivalent=[]; | 2197 | SNR_DFE_eqivalent=[]; | ||
2311 | SNR_DFE_eqivalent_CDF=[]; | 2198 | SNR_DFE_eqivalent_CDF=[]; | ||
2312 | new_com_CDF=COM_from_matlab; | 2199 | new_com_CDF=COM_from_matlab; | ||
2313 | delta_com_CDF=0; | 2200 | delta_com_CDF=0; | ||
2314 | delta_com=0; | 2201 | delta_com=0; | ||
2315 | SNR_DFE=[]; | 2202 | SNR_DFE=[]; | ||
2316 | end | 2203 | end | ||
2317 | SNR_DFE_eqivalent=[]; | 2204 | SNR_DFE_eqivalent=[]; | ||
2318 | %% | 2205 | %% | ||
2319 | MLSE_results.COM_from_matlab=COM_from_matlab; | 2206 | MLSE_results.COM_from_matlab=COM_from_matlab; | ||
2320 | MLSE_results.SNR_DFE=SNR_DFE; | 2207 | MLSE_results.SNR_DFE=SNR_DFE; | ||
2321 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | 2208 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | ||
2322 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | 2209 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | ||
2323 | MLSE_results.sigma_noise=sigma_noise; | 2210 | MLSE_results.sigma_noise=sigma_noise; | ||
2324 | MLSE_results.SNR_dB=SNR_dB ; | 2211 | MLSE_results.SNR_dB=SNR_dB ; | ||
2325 | MLSE_results.SNR_DFE_eqivalent_Gaussian=SNR_DFE_eqivalent; | 2212 | MLSE_results.SNR_DFE_eqivalent_Gaussian=SNR_DFE_eqivalent; | ||
2326 | MLSE_results.SNR_DFE_eqivalent_CDF=SNR_DFE_eqivalent_CDF; | 2213 | MLSE_results.SNR_DFE_eqivalent_CDF=SNR_DFE_eqivalent_CDF; | ||
2327 | MLSE_results.COM_Gaussian=new_com_CDF; | 2214 | MLSE_results.COM_Gaussian=new_com_CDF; | ||
2328 | MLSE_results.COM_CDF=new_com_CDF; | 2215 | MLSE_results.COM_CDF=new_com_CDF; | ||
2329 | MLSE_results.k_DER=k_DER; | 2216 | MLSE_results.k_DER=k_DER; | ||
2330 | MLSE_results.delta_com_CDF=delta_com_CDF; | 2217 | MLSE_results.delta_com_CDF=delta_com_CDF; | ||
2331 | MLSE_results.delta_com_Gaussian=delta_com; | 2218 | MLSE_results.delta_com_Gaussian=delta_com; | ||
2332 | 2219 | ||||
2333 | 2220 | ||||
2334 | 2221 | ||||
2335 | function [MLSE_results] = MLSE_instu(param,alpha,A_s,A_ni,PDF,CDF) | 2222 | function [MLSE_results] = MLSE_instu(param,alpha,A_s,A_ni,PDF,CDF) | ||
2336 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | 2223 | % OP.MLSE= 1 ... COM and VEC will be adjusted with MLSE CDF | ||
2337 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | 2224 | % OP.MLSE= 2 ... COM and VEC will be adjusted with MLSE Gaussian assumptions | ||
2338 | % Based on oif2022.580.00 / IEEE802. shakiba_3dj_01_230116 by Hossein Shakiba | 2225 | % Based on oif2022.580.00 / IEEE802. shakiba_3dj_01_230116 by Hossein Shakiba | ||
2339 | 2226 | ||||
2340 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | 2227 | qfuncinv = @(x) sqrt(2)*erfcinv(2*x); | ||
2341 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | 2228 | qfunc = @(x) 0.5*erfc(x/sqrt(2)); | ||
2342 | 2229 | ||||
2343 | %% step 0 | 2230 | %% step 0 | ||
2344 | COM_from_matlab=20*log10(A_s/A_ni); | 2231 | COM_from_matlab=20*log10(A_s/A_ni); | ||
2345 | L=param.levels; | 2232 | L=param.levels; | ||
2346 | DER0=param.specBER; | 2233 | DER0=param.specBER; | ||
2347 | %% step 1 from slide 6/5 | 2234 | %% step 1 from slide 6/5 | ||
2348 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | 2235 | A_peak=(L-1)*A_s; % slide 6 A_s is main in appendix a | ||
2349 | main=A_peak; | 2236 | main=A_peak; | ||
2350 | k_DER=qfuncinv(param.specBER); | 2237 | k_DER=qfuncinv(param.specBER); | ||
2351 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | 2238 | sigma_noise=sqrt(sum(PDF.y.*PDF.x.^2)); | ||
2352 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | 2239 | SNR_dB=10*log10( 1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2) ; | ||
2353 | COM=SNR_dB-10*log10((L^2-1)/3*k_DER^2); | 2240 | COM=SNR_dB-10*log10((L^2-1)/3*k_DER^2); | ||
2354 | % sprintf('COM from Matlab %g dB\n COM from slide 6 using Gaussian asumptions %g dB\n', COM_from_matlab ,COM) | 2241 | % sprintf('COM from Matlab %g dB\n COM from slide 6 using Gaussian asumptions %g dB\n', COM_from_matlab ,COM) | ||
2355 | if A_s >= A_ni | 2242 | if A_s >= A_ni | ||
2356 | %% step 2 slide 10/8 | 2243 | %% step 2 slide 10/8 | ||
2357 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | 2244 | SNR_DFE=1/3*(L+1)/(L-1)*(A_peak^2)/sigma_noise^2; | ||
2358 | %% step 2 slide 10/8 | 2245 | %% step 2 slide 10/8 | ||
2359 | snr_dfe = @(der,PDF,CDF) -10*log10((A_s./CDF_inv_ev(der,PDF,CDF)).^2)+10*log10((L^2-1)/3*qfuncinv(der).^2) ; | 2246 | snr_dfe = @(der,PDF,CDF) -10*log10((A_s./CDF_inv_ev(der,PDF,CDF)).^2)+10*log10((L^2-1)/3*qfuncinv(der).^2) ; | ||
2360 | 2247 | ||||
2361 | %% step 3 side 11/9 | 2248 | %% step 3 side 11/9 | ||
2362 | j=1:200; | 2249 | j=1:200; | ||
2363 | DER_MLSE=2*sum( j .* ((L-1)/L).^j .* qfunc( sqrt(1+(j-1)*(1-alpha)^2+alpha^2).* main/((L-1)*sigma_noise ) )); | 2250 | DER_MLSE=2*sum( j .* ((L-1)/L).^j .* qfunc( sqrt(1+(j-1)*(1-alpha)^2+alpha^2).* main/((L-1)*sigma_noise ) )); | ||
2364 | DER_MLSE_CDF=0; jj=1; | 2251 | DER_MLSE_CDF=0; jj=1; | ||
2365 | DER_delta = inf; | 2252 | DER_delta = inf; | ||
2366 | while DER_delta > .001 | 2253 | while DER_delta > .001 | ||
2367 | last_DER_MLSE_CDF=DER_MLSE_CDF; | 2254 | last_DER_MLSE_CDF=DER_MLSE_CDF; | ||
2368 | DER_MLSE_CDF=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDF; | 2255 | DER_MLSE_CDF=2*( jj .* ((L-1)/L).^jj .* CDF_ev( sqrt(1+(jj-1)*(1-alpha)^2+alpha^2).* main/((L-1) ),PDF,CDF ))+DER_MLSE_CDF; | ||
2369 | DER_delta= 1-last_DER_MLSE_CDF/DER_MLSE_CDF; | 2256 | DER_delta= 1-last_DER_MLSE_CDF/DER_MLSE_CDF; | ||
2370 | jj=jj+1; | 2257 | jj=jj+1; | ||
2371 | end | 2258 | end | ||
2372 | %% | 2259 | %% | ||
2373 | dscale=.05; | 2260 | dscale=.05; | ||
2374 | scale=1; | 2261 | scale=1; | ||
2375 | last_scale_tune=inf; | 2262 | last_scale_tune=inf; | ||
2376 | scale_tune=inf; | 2263 | scale_tune=inf; | ||
2377 | while abs(scale_tune) >= .1 | 2264 | while abs(scale_tune) >= .1 | ||
2378 | istart=-PDF.Min+1; | 2265 | istart=-PDF.Min+1; | ||
2379 | scale=scale-dscale; | 2266 | scale=scale-dscale; | ||
2380 | PDF_SCALED = scalePDF(PDF,scale); | 2267 | PDF_SCALED = scalePDF(PDF,scale); | ||
2381 | cdf_scaled=pdf_to_cdf(PDF_SCALED); | 2268 | cdf_scaled=pdf_to_cdf(PDF_SCALED); | ||
2382 | test_snr=snr_dfe(DER_MLSE_CDF,PDF_SCALED,cdf_scaled.y); | 2269 | test_snr=snr_dfe(DER_MLSE_CDF,PDF_SCALED,cdf_scaled.y); | ||
2383 | test_DER=2*(L-1)/L* (CDF_ev(main/(L-1),PDF_SCALED,cdf_scaled.y) ); | 2270 | test_DER=2*(L-1)/L* (CDF_ev(main/(L-1),PDF_SCALED,cdf_scaled.y) ); | ||
2384 | scale_tune=(test_DER-DER_MLSE_CDF)/DER_MLSE_CDF; | 2271 | scale_tune=(test_DER-DER_MLSE_CDF)/DER_MLSE_CDF; | ||
2385 | if sign(scale_tune) ~= sign(last_scale_tune) | 2272 | if sign(scale_tune) ~= sign(last_scale_tune) | ||
2386 | % scale=scale+dscale % back up | 2273 | % scale=scale+dscale % back up | ||
2387 | dscale=-dscale/2; | 2274 | dscale=-dscale/2; | ||
2388 | end | 2275 | end | ||
2389 | last_scale_tune=scale_tune; | 2276 | last_scale_tune=scale_tune; | ||
2390 | end | 2277 | end | ||
2391 | new_com_CDF=10*log10((A_s./CDF_inv_ev(DER0,PDF_SCALED,cdf_scaled.y)).^2); | 2278 | new_com_CDF=10*log10((A_s./CDF_inv_ev(DER0,PDF_SCALED,cdf_scaled.y)).^2); | ||
2392 | delta_com=new_com_CDF-10*log10((A_s./CDF_inv_ev(DER0,PDF,CDF)).^2); | 2279 | delta_com=new_com_CDF-10*log10((A_s./CDF_inv_ev(DER0,PDF,CDF)).^2); | ||
2393 | else | 2280 | else | ||
2394 | warning('MLSE not applied because there is more noise than signal') | 2281 | warning('MLSE not applied because there is more noise than signal') | ||
2395 | DER_MLSE=[]; | 2282 | DER_MLSE=[]; | ||
2396 | DER_MLSE_CDF=[]; | 2283 | DER_MLSE_CDF=[]; | ||
2397 | SNR_DFE_eqivalent=[]; | 2284 | SNR_DFE_eqivalent=[]; | ||
2398 | SNR_DFE_eqivalent_CDF=[]; | 2285 | SNR_DFE_eqivalent_CDF=[]; | ||
2399 | new_com_CDF=COM_from_matlab; | 2286 | new_com_CDF=COM_from_matlab; | ||
2400 | delta_com_CDF=0; | 2287 | delta_com_CDF=0; | ||
2401 | delta_com=0; | 2288 | delta_com=0; | ||
2402 | SNR_DFE=[]; | 2289 | SNR_DFE=[]; | ||
2403 | PDF_SCALED=[]; | 2290 | PDF_SCALED=[]; | ||
2404 | cdf_scaled=[]; | 2291 | cdf_scaled=[]; | ||
2405 | end | 2292 | end | ||
2406 | 2293 | ||||
2407 | %% | 2294 | %% | ||
2408 | MLSE_results.COM_from_matlab=COM_from_matlab; | 2295 | MLSE_results.COM_from_matlab=COM_from_matlab; | ||
2409 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | 2296 | MLSE_results.DER_MLSE_Gaussian=DER_MLSE; | ||
2410 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | 2297 | MLSE_results.DER_MLSE_CDF=DER_MLSE_CDF; | ||
2411 | MLSE_results.sigma_noise=sigma_noise; | 2298 | MLSE_results.sigma_noise=sigma_noise; | ||
2412 | MLSE_results.k_DER=k_DER; | 2299 | MLSE_results.k_DER=k_DER; | ||
2413 | MLSE_results.COM_CDF=new_com_CDF; | 2300 | MLSE_results.COM_CDF=new_com_CDF; | ||
2414 | MLSE_results.delta_com_CDF=delta_com; | 2301 | MLSE_results.delta_com_CDF=delta_com; | ||
2415 | MLSE_results.delta_com_Gaussian=delta_com; | 2302 | MLSE_results.delta_com_Gaussian=delta_com; | ||
2416 | MLSE_results.PDF=PDF_SCALED; | 2303 | MLSE_results.PDF=PDF_SCALED; | ||
2417 | MLSE_results.CDF=cdf_scaled.y; | 2304 | MLSE_results.CDF=cdf_scaled.y; | ||
2418 | MLSE_results.PDF_scale=scale; | 2305 | MLSE_results.PDF_scale=scale; | ||
2419 | 2306 | ||||
2420 | 2307 | ||||
2421 | 2308 | ||||
2422 | 2309 | ||||
2423 | function MMSE_results = MMSE(PSD_results,sbr, cursor_i ,param, OP ) | 2310 | function MMSE_results = MMSE(PSD_results,sbr, cursor_i ,param, OP ) | ||
2424 | if 1 | 2311 | if 1 | ||
2425 | num_ui=param.num_ui_RXFF_noise; | 2312 | num_ui=param.num_ui_RXFF_noise; | ||
2426 | M=param.samples_per_ui; | 2313 | M=param.samples_per_ui; | ||
2427 | L=param.levels; | 2314 | L=param.levels; | ||
2428 | sigma_X2=(L^2-1)/(3*(L-1)^2); | 2315 | sigma_X2=(L^2-1)/(3*(L-1)^2); | ||
2429 | fb=param.fb; | 2316 | fb=param.fb; | ||
2430 | R_LM=param.R_LM; | 2317 | R_LM=param.R_LM; | ||
2431 | end | 2318 | end | ||
2432 | h=sbr(mod(cursor_i,M)+1:end-mod(cursor_i,M)); % align to sample point | 2319 | h=sbr(mod(cursor_i,M)+1:end-mod(cursor_i,M)); % align to sample point | ||
2433 | h=sbr(mod(cursor_i - 1,M)+1:end); % align to sample point % from Tobey (Pei-Rong Li 02/29/2024) | 2320 | h=sbr(mod(cursor_i - 1,M)+1:end); % align to sample point % from Tobey (Pei-Rong Li 02/29/2024) | ||
2434 | h=reshape(h,1,[]); % make row vectors | 2321 | h=reshape(h,1,[]); % make row vectors | ||
2435 | h=[ h(1:floor(length(h)/M)*M) ]; | 2322 | h=[ h(1:floor(length(h)/M)*M) ]; | ||
2436 | h= [h zeros(1,num_ui*M-length(h)) ]; | 2323 | h= [h zeros(1,num_ui*M-length(h)) ]; | ||
2437 | h=h(1:M:end);% resample | 2324 | h=h(1:M:end);% resample | ||
2438 | N=length(h); | 2325 | N=length(h); | ||
2439 | dw=param.RxFFE_cmx ; % equalizer precuror tapsindx(1:N)=(1:N)-5-1; | 2326 | dw=param.RxFFE_cmx ; % equalizer precuror tapsindx(1:N)=(1:N)-5-1; | ||
2440 | dh=(cursor_i-mod(cursor_i,M))/M ; % precuror taps in h | 2327 | dh=(cursor_i-mod(cursor_i,M))/M ; % precuror taps in h | ||
2441 | if param.N_bg == 0 | 2328 | if param.N_bg == 0 | ||
2442 | Nw= param.RxFFE_cmx+1+param.RxFFE_cpx; % total number of equalizer taps | 2329 | Nw= param.RxFFE_cmx+1+param.RxFFE_cpx; % total number of equalizer taps | ||
2443 | bmax=param.bmax; | 2330 | bmax=param.bmax; | ||
2444 | bmin=param.bmin ; | 2331 | bmin=param.bmin ; | ||
2445 | wmax= [ ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max param.ffe_pre_tap1_max 1.0 param.ffe_post_tap1_max ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ]; | 2332 | wmax= [ ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max param.ffe_pre_tap1_max 1.0 param.ffe_post_tap1_max ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ]; | ||
2446 | wmin= [ -ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max -param.ffe_pre_tap1_max 1.0 -param.ffe_post_tap1_max -ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ]; | 2333 | wmin= [ -ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max -param.ffe_pre_tap1_max 1.0 -param.ffe_post_tap1_max -ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ]; | ||
2447 | idx=[]; | 2334 | idx=[]; | ||
2448 | else | 2335 | else | ||
2449 | Nfloating_taps=param.N_bf*param.N_bg; | 2336 | Nfloating_taps=param.N_bf*param.N_bg; | ||
2450 | Nmax=param.N_bmax; | 2337 | Nmax=param.N_bmax; | ||
2451 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | 2338 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | ||
2452 | Ng=param.N_bg; | 2339 | Ng=param.N_bg; | ||
2453 | Nf=param.N_bf; | 2340 | Nf=param.N_bf; | ||
2454 | Nw= dw+Nmax+1;% total span of equalizer taps including floating taps | 2341 | Nw= dw+Nmax+1;% total span of equalizer taps including floating taps | ||
2455 | Nwft=param.RxFFE_cmx+1+param.RxFFE_cpx+Nfloating_taps;% total number of equalizer taps including floating taps | 2342 | Nwft=param.RxFFE_cmx+1+param.RxFFE_cpx+Nfloating_taps;% total number of equalizer taps including floating taps | ||
2456 | % hisi=h(dh+2:((dh-dw)+Nw)); | 2343 | % hisi=h(dh+2:((dh-dw)+Nw)); | ||
2457 | % [idx]=findbankloc( hisi ,param.N_tail_start,param.N_bmax,Nf,inf,param.bmaxg,Ng ); % using maximum power in hisi | 2344 | % [idx]=findbankloc( hisi ,param.N_tail_start,param.N_bmax,Nf,inf,param.bmaxg,Ng ); % using maximum power in hisi | ||
2458 | % idx=sort(idx); | 2345 | % idx=sort(idx); | ||
2459 | bmax=param.bmax; | 2346 | bmax=param.bmax; | ||
2460 | bmin=param.bmin ; | 2347 | bmin=param.bmin ; | ||
2461 | wmax= [ ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max param.ffe_pre_tap1_max 1.0 param.ffe_post_tap1_max ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ones(1,Nfloating_taps)*param.bmaxg ]; | 2348 | wmax= [ ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max param.ffe_pre_tap1_max 1.0 param.ffe_post_tap1_max ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max ones(1,Nfloating_taps)*param.bmaxg ]; | ||
2462 | wmin= [ -ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max -param.ffe_pre_tap1_max 1.0 -param.ffe_post_tap1_max -ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max -ones(1,Nfloating_taps)*param.bmaxg ]; | 2349 | wmin= [ -ones(1,param.RxFFE_cmx-1)*param.ffe_tapn_max -param.ffe_pre_tap1_max 1.0 -param.ffe_post_tap1_max -ones(1,param.RxFFE_cpx-1)*param.ffe_tapn_max -ones(1,Nfloating_taps)*param.bmaxg ]; | ||
2463 | end | 2350 | end | ||
2464 | Nb=param.ndfe; % DFE taps | 2351 | Nb=param.ndfe; % DFE taps | ||
2465 | d=dw+dh; % used for index in algorithms | 2352 | d=dw+dh; % used for index in algorithms | ||
2466 | indx(1:N)=(1:N)-dh-1; | 2353 | indx(1:N)=(1:N)-dh-1; | ||
2467 | S_n=PSD_results.S_n; % total agregate noise PSD | 2354 | S_n=PSD_results.S_n; % total agregate noise PSD | ||
2468 | Rn=ifft(S_n)*fb; | 2355 | Rn=ifft(S_n)*fb; | ||
2469 | %% HH and R | 2356 | %% HH and R | ||
2470 | 2357 | ||||
2471 | %Test routine finding rxffe floating taps using best FOM for each bank | 2358 | %Test routine finding rxffe floating taps using best FOM for each bank | ||
2472 | isi_start = dh+2; | 2359 | isi_start = dh+2; | ||
2473 | isi_end = (dh-dw)+Nw; | 2360 | isi_end = (dh-dw)+Nw; | ||
2474 | hc1=[ h zeros(1,Nw-1) ]; | 2361 | hc1=[ h zeros(1,Nw-1) ]; | ||
2475 | hr1=[ h(1) zeros(1,Nw-1)]; | 2362 | hr1=[ h(1) zeros(1,Nw-1)]; | ||
2476 | H=toeplitz(hc1,hr1); | 2363 | H=toeplitz(hc1,hr1); | ||
2477 | Rnn=toeplitz(Rn(1:Nw),Rn(1:Nw)); | 2364 | Rnn=toeplitz(Rn(1:Nw),Rn(1:Nw)); | ||
2478 | if param.N_bg ~= 0 | 2365 | if param.N_bg ~= 0 | ||
2479 | switch lower(OP.RXFFE_FLOAT_CTL) | 2366 | switch lower(OP.RXFFE_FLOAT_CTL) | ||
2480 | case 'isi' | 2367 | case 'isi' | ||
2481 | hisi=h(dh+2:((dh-dw)+Nw)); | 2368 | hisi=h(dh+2:((dh-dw)+Nw)); | ||
2482 | [idx]=findbankloc( hisi ,param.N_tail_start,param.N_bmax,param.N_bf,inf,param.bmaxg,param.N_bg ); % using maximum power in hisi | 2369 | [idx]=findbankloc( hisi ,param.N_tail_start,param.N_bmax,param.N_bf,inf,param.bmaxg,param.N_bg ); % using maximum power in hisi | ||
2483 | idx=sort(idx); | 2370 | idx=sort(idx); | ||
2484 | otherwise | 2371 | otherwise | ||
2485 | idx = FOM_rxffe_floating_taps(param,h,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,isi_start,isi_end); | 2372 | idx = FOM_rxffe_floating_taps(param,h,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,isi_start,isi_end); | ||
2486 | idx=sort(idx); | 2373 | idx=sort(idx); | ||
2487 | end | 2374 | end | ||
2488 | end | 2375 | end | ||
2489 | [sigma_e,FOM,w,idx] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,idx); | 2376 | [sigma_e,FOM,w,idx] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,idx); | ||
2490 | MMSE_results.sigma_e=sigma_e; % | 2377 | MMSE_results.sigma_e=sigma_e; % | ||
2491 | MMSE_results.FOM=FOM; | 2378 | MMSE_results.FOM=FOM; | ||
2492 | Craw=w/w(dw+1); % returned Rx FFE taps | 2379 | Craw=w/w(dw+1); % returned Rx FFE taps | ||
2493 | % re-align Cmod to floating tap locations | 2380 | % re-align Cmod to floating tap locations | ||
2494 | if param.N_bg ~= 0 | 2381 | if param.N_bg ~= 0 | ||
2495 | C=Craw; | 2382 | C=Craw; | ||
2496 | C(Nfix+1:Nmax+param.ffe_pre_tap_len+1)=0;% from Tobey (Pei-Rong Li 02/28/2024) | 2383 | C(Nfix+1:Nmax+param.ffe_pre_tap_len+1)=0;% from Tobey (Pei-Rong Li 02/28/2024) | ||
2497 | C(idx-param.N_tail_start+1+Nfix)=Craw(Nfix+(1:Nfloating_taps)); | 2384 | C(idx-param.N_tail_start+1+Nfix)=Craw(Nfix+(1:Nfloating_taps)); | ||
2498 | else | 2385 | else | ||
2499 | C=Craw; | 2386 | C=Craw; | ||
2500 | end | 2387 | end | ||
2501 | MMSE_results.floating_tap_locations=idx; | 2388 | MMSE_results.floating_tap_locations=idx; | ||
2502 | MMSE_results.C=C; | 2389 | MMSE_results.C=C; | ||
2503 | 2390 | ||||
2504 | 2391 | ||||
2505 | 2392 | ||||
2506 | 2393 | ||||
2507 | function [sigma_e,FOM,w,idx,Nw] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,idx) | 2394 | function [sigma_e,FOM,w,idx,Nw] = MMSE_FOM(param,H,Nb,Rnn,dw,d,wmax,wmin,bmin,bmax,sigma_X2,idx) | ||
2508 | if isempty(idx) | 2395 | if isempty(idx) | ||
2509 | Nw= param.RxFFE_cmx+1+param.RxFFE_cpx; % total number of equalizer taps | 2396 | Nw= param.RxFFE_cmx+1+param.RxFFE_cpx; % total number of equalizer taps | ||
2510 | bmax=param.bmax; | 2397 | bmax=param.bmax; | ||
2511 | bmin=param.bmin ; | 2398 | bmin=param.bmin ; | ||
2512 | else | 2399 | else | ||
2513 | Nfloating_taps=param.N_bf*param.N_bg; | 2400 | Nfloating_taps=param.N_bf*param.N_bg; | ||
2514 | %If using the routine that finds RXFFE floating taps bank-by-bank, the number of total floating taps can be less than the final amount | 2401 | %If using the routine that finds RXFFE floating taps bank-by-bank, the number of total floating taps can be less than the final amount | ||
2515 | Nfloating_taps = length(idx); | 2402 | Nfloating_taps = length(idx); | ||
2516 | Nmax=param.N_bmax; | 2403 | Nmax=param.N_bmax; | ||
2517 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | 2404 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | ||
2518 | Ng=param.N_bg; | 2405 | Ng=param.N_bg; | ||
2519 | Nf=param.N_bf; | 2406 | Nf=param.N_bf; | ||
2520 | Nw= dw+Nmax+1;% total span of equalizer taps including floating taps | 2407 | Nw= dw+Nmax+1;% total span of equalizer taps including floating taps | ||
2521 | Nwft=param.RxFFE_cmx+1+param.RxFFE_cpx+Nfloating_taps;% total number of equalizer taps including floating taps | 2408 | Nwft=param.RxFFE_cmx+1+param.RxFFE_cpx+Nfloating_taps;% total number of equalizer taps including floating taps | ||
2522 | end | 2409 | end | ||
2523 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | 2410 | Nfix=param.RxFFE_cmx+1+param.RxFFE_cpx; | ||
2524 | %Rnn=toeplitz(Rn(1:Nw),Rn(1:Nw)); | 2411 | %Rnn=toeplitz(Rn(1:Nw),Rn(1:Nw)); | ||
2525 | % hc1=[ h zeros(1,Nw-1) ]; | 2412 | % hc1=[ h zeros(1,Nw-1) ]; | ||
2526 | % hr1=[ h(1) zeros(1,Nw-1)]; | 2413 | % hr1=[ h(1) zeros(1,Nw-1)]; | ||
2527 | % H=toeplitz(hc1,hr1); | 2414 | % H=toeplitz(hc1,hr1); | ||
2528 | 2415 | ||||
2529 | if param.N_bg ~= 0 | 2416 | if param.N_bg ~= 0 | ||
2530 | H=H( :,[1:Nfix idx-param.N_tail_start+1+Nfix]); % from Tobey (Pei-Rong Li 02/28/2024) | 2417 | H=H( :,[1:Nfix idx-param.N_tail_start+1+Nfix]); % from Tobey (Pei-Rong Li 02/28/2024) | ||
2531 | end | 2418 | end | ||
2532 | %% HH and R | 2419 | %% HH and R | ||
2533 | HH= H'*H; | 2420 | HH= H'*H; | ||
2534 | if param.N_bg ~= 0 | 2421 | if param.N_bg ~= 0 | ||
2535 | Rnn=Rnn( [1:Nfix idx-param.N_tail_start+1+Nfix],[1:Nfix idx-param.N_tail_start+1+Nfix]); | 2422 | Rnn=Rnn( [1:Nfix idx-param.N_tail_start+1+Nfix],[1:Nfix idx-param.N_tail_start+1+Nfix]); | ||
2536 | end | 2423 | end | ||
2537 | R=HH+Rnn/sigma_X2; | 2424 | R=HH+Rnn/sigma_X2; | ||
2538 | %% hb and h0 | 2425 | %% hb and h0 | ||
2539 | Hb= H(d+2:d+Nb+1,:); | 2426 | Hb= H(d+2:d+Nb+1,:); | ||
2540 | h0=H(d+1,:); | 2427 | h0=H(d+1,:); | ||
2541 | % display(floor(h0)); | 2428 | % display(floor(h0)); | ||
2542 | 2429 | ||||
2543 | %% Ib and zb (slide 10) | 2430 | %% Ib and zb (slide 10) | ||
2544 | ib=eye(Nb); | 2431 | ib=eye(Nb); | ||
2545 | zb=zeros(1,Nb); | 2432 | zb=zeros(1,Nb); | ||
2546 | wbl= [ R -Hb' -h0';... | 2433 | wbl= [ R -Hb' -h0';... | ||
2547 | -Hb ib zb'; ... | 2434 | -Hb ib zb'; ... | ||
2548 | h0 zb 0]\[h0'; zb' ;1]; | 2435 | h0 zb 0]\[h0'; zb' ;1]; | ||
2549 | 2436 | ||||
2550 | %% re-adjust Nw to number of used taps | 2437 | %% re-adjust Nw to number of used taps | ||
2551 | if param.N_bg ~= 0 | 2438 | if param.N_bg ~= 0 | ||
2552 | Nw=Nwft; | 2439 | Nw=Nwft; | ||
2553 | end | 2440 | end | ||
2554 | %% check equalized pulse | 2441 | %% check equalized pulse | ||
2555 | w=wbl(1:Nw); | 2442 | w=wbl(1:Nw); | ||
2556 | b=wbl(Nw+1:length(wbl)-1); % dfe taps before limits are applied | 2443 | b=wbl(Nw+1:length(wbl)-1); % dfe taps before limits are applied | ||
2557 | 2444 | ||||
2558 | %% apply blim (slide 11) <---- need help here How do I get to RxFFE tap coefficents, C? | 2445 | %% apply blim (slide 11) <---- need help here How do I get to RxFFE tap coefficents, C? | ||
2559 | blim = min(bmax(:), max(bmin(:), b)); | 2446 | blim = min(bmax(:), max(bmin(:), b)); | ||
2560 | if (Nb > 0) && ~isequal(b, blim) | 2447 | if (Nb > 0) && ~isequal(b, blim) | ||
2561 | wl = [R, -h0'; h0, 0]\[h0'+Hb'*blim; 1]; | 2448 | wl = [R, -h0'; h0, 0]\[h0'+Hb'*blim; 1]; | ||
2562 | w = wl(1:Nw); | 2449 | w = wl(1:Nw); | ||
2563 | end | 2450 | end | ||
2564 | 2451 | ||||
2565 | %If doing floating RXFFE one bank at a time, the length of w may be less than wmin and wmax | 2452 | %If doing floating RXFFE one bank at a time, the length of w may be less than wmin and wmax | ||
2566 | %so need to chop off the extra indices on wmax and wmin | 2453 | %so need to chop off the extra indices on wmax and wmin | ||
2567 | if length(w)<length(wmax) | 2454 | if length(w)<length(wmax) | ||
2568 | wmax=wmax(1:length(w)); | 2455 | wmax=wmax(1:length(w)); | ||
2569 | wmin=wmin(1:length(w)); | 2456 | wmin=wmin(1:length(w)); | ||
2570 | end | 2457 | end | ||
2571 | wlim = min(wmax(:)*w(1+dw), max(wmin(:)*w(1+dw), w)); | 2458 | wlim = min(wmax(:)*w(1+dw), max(wmin(:)*w(1+dw), w)); | ||
2572 | if ~isequal(w, wlim) | 2459 | if ~isequal(w, wlim) | ||
2573 | wlim = wlim/(h0*wlim); % Ensure the equalized pulse amplitude is 1. | 2460 | wlim = wlim/(h0*wlim); % Ensure the equalized pulse amplitude is 1. | ||
2574 | if Nb > 0 | 2461 | if Nb > 0 | ||
2575 | b = Hb*wlim; % Update the feedback coefficients. | 2462 | b = Hb*wlim; % Update the feedback coefficients. | ||
2576 | blim = min(bmax(:), max(bmin(:), b)); | 2463 | blim = min(bmax(:), max(bmin(:), b)); | ||
2577 | end | 2464 | end | ||
≠ | 2578 | % wl = [R, -h0'; h0, 0]\[h0'+Hb'*blim; 1]; | ≠ | 2465 | wl = [R, -h0'; h0, 0]\[h0'+Hb'*blim; 1]; |
≠ | 2579 | % wl = wl(1:Nw); | ≠ | 2466 | wl = wl(1:Nw); |
≠ | 2580 | % w = min(wmax(:)*wl(1+dw), max(wmin(:)*wl(1+dw), wl)); | ≠ | 2467 | w = min(wmax(:)*wl(1+dw), max(wmin(:)*wl(1+dw), wl)); |
2581 | end | 2468 | end | ||
≠ | 2582 | % w=w(1:Nw) ; | ≠ | 2469 | w=w(1:Nw) ; |
≠ | 2583 | % sigma_e=sqrt(w'*R*w+1+b'*b-2*w'*h0'-2*w'*Hb'*b); % from Tobey (Pei-Rong Li 02/29/2024) | ≠ | 2470 | sigma_e=sqrt(w'*R*w+1+b'*b-2*w'*h0'-2*w'*Hb'*b); % from Tobey (Pei-Rong Li 02/29/2024) |
− | 2584 | w=wlim; |
| ||
2585 | b=blim; | ||||
2586 | sigma_e=sqrt(sigma_X2*(w'*R*w+1+b'*b-2*w'*h0'-2*w'*Hb'*b)); % Commit request 4p4_5 from healey_3dj_COM_01_240416 | ||||
≠ | 2587 | FOM=20*log10((param.R_LM/(param.levels-1)/sigma_e)); | ≠ | 2471 | FOM=20*log10((param.R_LM/(param.levels-1)/sigma_e)); |
2588 | function output_args=Output_Arg_Fill(output_args,sigma_bn,Noise_Struct,COM_SNR_Struct,param,chdata,fom_result,OP) | 2472 | function output_args=Output_Arg_Fill(output_args,sigma_bn,Noise_Struct,COM_SNR_Struct,param,chdata,fom_result,OP) | ||
2589 | 2473 | ||||
2590 | %not all output_args are filled here but most are | 2474 | %not all output_args are filled here but most are | ||
2591 | 2475 | ||||
2592 | switch lower(OP.TDECQ) | 2476 | switch lower(OP.TDECQ) | ||
2593 | case { false 'none' } % should be the default | 2477 | case { false 'none' } % should be the default | ||
2594 | output_args.VMA=[]; | 2478 | output_args.VMA=[]; | ||
2595 | case 'vma' | 2479 | case 'vma' | ||
2596 | est_vma=vma(fom_result.sbr,param.samples_per_ui); | 2480 | est_vma=vma(fom_result.sbr,param.samples_per_ui); | ||
2597 | output_args.VMA=est_vma.VMA; | 2481 | output_args.VMA=est_vma.VMA; | ||
2598 | otherwise | 2482 | otherwise | ||
2599 | error('%s not recognized for Histogram_Window_Weigh this feature is limited',OP.TDECQ) | 2483 | error('%s not recognized for Histogram_Window_Weigh this feature is limited',OP.TDECQ) | ||
2600 | end | 2484 | end | ||
2601 | 2485 | ||||
2602 | fileset_str=str2csv({chdata.base}); | 2486 | fileset_str=str2csv({chdata.base}); | ||
2603 | output_args.file_names=sprintf('"%s"', fileset_str); | 2487 | output_args.file_names=sprintf('"%s"', fileset_str); | ||
2604 | % [ahealey] Echo the termination parameters in the output arguments.. | 2488 | % [ahealey] Echo the termination parameters in the output arguments.. | ||
2605 | for odt_param = {'R_diepad', 'C_diepad', 'L_comp', 'C_bump'} | 2489 | for odt_param = {'R_diepad', 'C_diepad', 'L_comp', 'C_bump'} | ||
2606 | output_args.(odt_param{:}) = param.(odt_param{:}); | 2490 | output_args.(odt_param{:}) = param.(odt_param{:}); | ||
2607 | end | 2491 | end | ||
2608 | % [ahealey] End of modifications. | 2492 | % [ahealey] End of modifications. | ||
2609 | for pkg_params = {'levels', 'Pkg_len_TX', 'Pkg_len_NEXT', 'Pkg_len_FEXT', 'Pkg_len_RX','R_diepad','pkg_Z_c','C_v'} | 2493 | for pkg_params = {'levels', 'Pkg_len_TX', 'Pkg_len_NEXT', 'Pkg_len_FEXT', 'Pkg_len_RX','R_diepad','pkg_Z_c','C_v'} | ||
2610 | output_args.(pkg_params{:})= param.(pkg_params{:}); | 2494 | output_args.(pkg_params{:})= param.(pkg_params{:}); | ||
2611 | end | 2495 | end | ||
2612 | output_args.baud_rate_GHz=param.fb/1e9; | 2496 | output_args.baud_rate_GHz=param.fb/1e9; | ||
2613 | output_args.f_Nyquist_GHz = param.fb/2e9; | 2497 | output_args.f_Nyquist_GHz = param.fb/2e9; | ||
2614 | output_args.BER=param.specBER; | 2498 | output_args.BER=param.specBER; | ||
2615 | output_args.FOM = fom_result.FOM; | 2499 | output_args.FOM = fom_result.FOM; | ||
2616 | output_args.sigma_N=Noise_Struct.sigma_N; | 2500 | output_args.sigma_N=Noise_Struct.sigma_N; | ||
2617 | output_args.DFE4_RSS=norm(fom_result.DFE_taps(4:end)); | 2501 | output_args.DFE4_RSS=norm(fom_result.DFE_taps(4:end)); | ||
2618 | output_args.DFE2_RSS=norm(fom_result.DFE_taps(2:end)); | 2502 | output_args.DFE2_RSS=norm(fom_result.DFE_taps(2:end)); | ||
2619 | output_args.tail_RSS=fom_result.tail_RSS; | 2503 | output_args.tail_RSS=fom_result.tail_RSS; | ||
2620 | output_args.channel_operating_margin_dB=COM_SNR_Struct.COM; | 2504 | output_args.channel_operating_margin_dB=COM_SNR_Struct.COM; | ||
2621 | output_args.available_signal_after_eq_mV=1000*COM_SNR_Struct.A_s; | 2505 | output_args.available_signal_after_eq_mV=1000*COM_SNR_Struct.A_s; | ||
2622 | output_args.peak_uneq_pulse_mV=1000*max(abs(chdata(1).uneq_pulse_response)); | 2506 | output_args.peak_uneq_pulse_mV=1000*max(abs(chdata(1).uneq_pulse_response)); | ||
2623 | try | 2507 | try | ||
2624 | output_args.uneq_FIR_peak_time=chdata(1).t(chdata(1).uneq_imp_response==max(chdata(1).uneq_imp_response)); | 2508 | output_args.uneq_FIR_peak_time=chdata(1).t(chdata(1).uneq_imp_response==max(chdata(1).uneq_imp_response)); | ||
2625 | catch | 2509 | catch | ||
2626 | output_args.uneq_FIR_peak_time=[]; | 2510 | output_args.uneq_FIR_peak_time=[]; | ||
2627 | end | 2511 | end | ||
2628 | output_args.steady_state_voltage_mV = 1000*fom_result.A_f; % RIM 7/03/2019 use peak from optimize_FOM | 2512 | output_args.steady_state_voltage_mV = 1000*fom_result.A_f; % RIM 7/03/2019 use peak from optimize_FOM | ||
2629 | its=find(chdata(1).eq_pulse_response>=max(chdata(1).eq_pulse_response),1,'first'); | 2513 | its=find(chdata(1).eq_pulse_response>=max(chdata(1).eq_pulse_response),1,'first'); | ||
2630 | isumend=min(its+param.N_v*param.samples_per_ui,length(chdata(1).eq_pulse_response)); | 2514 | isumend=min(its+param.N_v*param.samples_per_ui,length(chdata(1).eq_pulse_response)); | ||
2631 | output_args.steady_state_voltage_weq_mV = 1000*sum(chdata(1).eq_pulse_response(1:isumend) )/param.samples_per_ui; | 2515 | output_args.steady_state_voltage_weq_mV = 1000*sum(chdata(1).eq_pulse_response(1:isumend) )/param.samples_per_ui; | ||
2632 | 2516 | ||||
2633 | if OP.RX_CALIBRATION== 1 | 2517 | if OP.RX_CALIBRATION== 1 | ||
2634 | output_args.sigma_bn=sigma_bn; | 2518 | output_args.sigma_bn=sigma_bn; | ||
2635 | else | 2519 | else | ||
2636 | output_args.sigma_bn=[]; | 2520 | output_args.sigma_bn=[]; | ||
2637 | end | 2521 | end | ||
2638 | output_args.Peak_ISI_XTK_and_Noise_interference_at_BER_mV=1000*COM_SNR_Struct.A_ni; | 2522 | output_args.Peak_ISI_XTK_and_Noise_interference_at_BER_mV=1000*COM_SNR_Struct.A_ni; | ||
2639 | output_args.peak_ISI_XTK_interference_at_BER_mV=1000*Noise_Struct.peak_interference_at_BER; | 2523 | output_args.peak_ISI_XTK_interference_at_BER_mV=1000*Noise_Struct.peak_interference_at_BER; | ||
2640 | output_args.peak_ISI_interference_at_BER_mV=1000*Noise_Struct.thru_peak_interference_at_BER; | 2524 | output_args.peak_ISI_interference_at_BER_mV=1000*Noise_Struct.thru_peak_interference_at_BER; | ||
2641 | output_args.equivalent_ICI_sigma_assuming_PDF_is_Gaussian_mV=Noise_Struct.sci_sigma*1000; | 2525 | output_args.equivalent_ICI_sigma_assuming_PDF_is_Gaussian_mV=Noise_Struct.sci_sigma*1000; | ||
2642 | 2526 | ||||
2643 | if OP.RX_CALIBRATION == 0 | 2527 | if OP.RX_CALIBRATION == 0 | ||
2644 | output_args.peak_MDXTK_interference_at_BER_mV=1000*Noise_Struct.crosstalk_peak_interference_at_BER; | 2528 | output_args.peak_MDXTK_interference_at_BER_mV=1000*Noise_Struct.crosstalk_peak_interference_at_BER; | ||
2645 | output_args.peak_MDNEXT_interference_at_BER_mV=1000*Noise_Struct.MDNEXT_peak_interference; | 2529 | output_args.peak_MDNEXT_interference_at_BER_mV=1000*Noise_Struct.MDNEXT_peak_interference; | ||
2646 | output_args.peak_MDFEXT_interference_at_BER_mV=1000*Noise_Struct.MDFEXT_peak_interference; | 2530 | output_args.peak_MDFEXT_interference_at_BER_mV=1000*Noise_Struct.MDFEXT_peak_interference; | ||
2647 | else | 2531 | else | ||
2648 | output_args.peak_MDXTK_interference_at_BER_mV=[]; | 2532 | output_args.peak_MDXTK_interference_at_BER_mV=[]; | ||
2649 | output_args.peak_MDNEXT_interference_at_BER_mV=[]; | 2533 | output_args.peak_MDNEXT_interference_at_BER_mV=[]; | ||
2650 | output_args.peak_MDFEXT_interference_at_BER_mV=[]; | 2534 | output_args.peak_MDFEXT_interference_at_BER_mV=[]; | ||
2651 | end | 2535 | end | ||
2652 | %output_args.ICN_mV=ICN*1000; | 2536 | %output_args.ICN_mV=ICN*1000; | ||
2653 | % output_args.ICN_test_mV=ICN_test*1000; | 2537 | % output_args.ICN_test_mV=ICN_test*1000; | ||
2654 | xtk=param.num_next+param.num_fext; | 2538 | xtk=param.num_next+param.num_fext; | ||
2655 | if xtk>0 && OP.RX_CALIBRATION ==0 && OP.TDMODE==0 | 2539 | if xtk>0 && OP.RX_CALIBRATION ==0 && OP.TDMODE==0 | ||
2656 | %output_args.MDNEXT_ICN_92_46_mV=MDNEXT_ICN*1000; | 2540 | %output_args.MDNEXT_ICN_92_46_mV=MDNEXT_ICN*1000; | ||
2657 | %output_args.MDFEXT_ICN_92_47_mV=MDFEXT_ICN*1000; | 2541 | %output_args.MDFEXT_ICN_92_47_mV=MDFEXT_ICN*1000; | ||
2658 | output_args.equivalent_ICN_assuming_Gaussian_PDF_mV=Noise_Struct.cci_sigma*1000; | 2542 | output_args.equivalent_ICN_assuming_Gaussian_PDF_mV=Noise_Struct.cci_sigma*1000; | ||
2659 | else | 2543 | else | ||
2660 | output_args.MDNEXT_ICN_92_46_mV=0; | 2544 | output_args.MDNEXT_ICN_92_46_mV=0; | ||
2661 | output_args.MDFEXT_ICN_92_47_mV=0; | 2545 | output_args.MDFEXT_ICN_92_47_mV=0; | ||
2662 | output_args.equivalent_ICN_assuming_PDF_is_Gaussian_mV=0; | 2546 | output_args.equivalent_ICN_assuming_PDF_is_Gaussian_mV=0; | ||
2663 | end | 2547 | end | ||
2664 | %output_args.SNR_ISI_XTK_normalized_1_sigma=20*log10(A_s/(peak_interference_at_BER/qfuncinv(param.specBER))); modified by Yasuo Hidaka, 8/7/17 | 2548 | %output_args.SNR_ISI_XTK_normalized_1_sigma=20*log10(A_s/(peak_interference_at_BER/qfuncinv(param.specBER))); modified by Yasuo Hidaka, 8/7/17 | ||
2665 | if 1 | 2549 | if 1 | ||
2666 | output_args.SNR_ISI_XTK_normalized_1_sigma=20*log10(COM_SNR_Struct.A_s/(Noise_Struct.peak_interference_at_BER/sqrt(2)/erfcinv(2*param.specBER))); | 2550 | output_args.SNR_ISI_XTK_normalized_1_sigma=20*log10(COM_SNR_Struct.A_s/(Noise_Struct.peak_interference_at_BER/sqrt(2)/erfcinv(2*param.specBER))); | ||
2667 | output_args.SNR_ISI_est=fom_result.SNR_ISI; | 2551 | output_args.SNR_ISI_est=fom_result.SNR_ISI; | ||
2668 | output_args.Pmax_by_Vf_est=fom_result.Pmax_by_Vf; | 2552 | output_args.Pmax_by_Vf_est=fom_result.Pmax_by_Vf; | ||
2669 | output_args.Tr_measured_from_step_ps=fom_result.Tr_measured_from_step/1e-12; | 2553 | output_args.Tr_measured_from_step_ps=fom_result.Tr_measured_from_step/1e-12; | ||
2670 | end | 2554 | end | ||
2671 | 2555 | ||||
2672 | 2556 | ||||
2673 | switch param.CTLE_type | 2557 | switch param.CTLE_type | ||
2674 | case 'CL93' | 2558 | case 'CL93' | ||
2675 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle)]; | 2559 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle)]; | ||
2676 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | 2560 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | ||
2677 | output_args.g_DC_HP=[]; | 2561 | output_args.g_DC_HP=[]; | ||
2678 | output_args.HP_poles_zero=[]; | 2562 | output_args.HP_poles_zero=[]; | ||
2679 | case 'CL120d' | 2563 | case 'CL120d' | ||
2680 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle)]; | 2564 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle)]; | ||
2681 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | 2565 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | ||
2682 | output_args.g_DC_HP=param.g_DC_HP_values(fom_result.best_G_high_pass); | 2566 | output_args.g_DC_HP=param.g_DC_HP_values(fom_result.best_G_high_pass); | ||
2683 | output_args.HP_poles_zero=param.f_HP(fom_result.best_G_high_pass); | 2567 | output_args.HP_poles_zero=param.f_HP(fom_result.best_G_high_pass); | ||
2684 | case 'CL120e' | 2568 | case 'CL120e' | ||
2685 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.f_HP_Z(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle) param.f_HP_P(fom_result.ctle)]; | 2569 | output_args.CTLE_zero_poles=[param.CTLE_fz(fom_result.ctle) param.f_HP_Z(fom_result.ctle) param.CTLE_fp2(fom_result.ctle) param.CTLE_fp1(fom_result.ctle) param.f_HP_P(fom_result.ctle)]; | ||
2686 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | 2570 | output_args.CTLE_DC_gain_dB=param.ctle_gdc_values(fom_result.ctle); | ||
2687 | output_args.g_DC_HP=[]; | 2571 | output_args.g_DC_HP=[]; | ||
2688 | output_args.HP_poles_zero=[]; | 2572 | output_args.HP_poles_zero=[]; | ||
2689 | end | 2573 | end | ||
2690 | output_args.TXLE_taps=fom_result.txffe; | 2574 | output_args.TXLE_taps=fom_result.txffe; | ||
2691 | if length(output_args.TXLE_taps) >= 3 | 2575 | if length(output_args.TXLE_taps) >= 3 | ||
2692 | output_args.Pre2Pmax = -output_args.TXLE_taps(end-2)/output_args.TXLE_taps(end-1); | 2576 | output_args.Pre2Pmax = -output_args.TXLE_taps(end-2)/output_args.TXLE_taps(end-1); | ||
2693 | else | 2577 | else | ||
2694 | output_args.Pre2Pmax=[]; | 2578 | output_args.Pre2Pmax=[]; | ||
2695 | end | 2579 | end | ||
2696 | output_args.DFE_taps=fom_result.DFE_taps; | 2580 | output_args.DFE_taps=fom_result.DFE_taps; | ||
2697 | if param.Floating_DFE || param.Floating_RXFFE | 2581 | if param.Floating_DFE || param.Floating_RXFFE | ||
2698 | output_args.floating_tap_locations=fom_result.floating_tap_locations; | 2582 | output_args.floating_tap_locations=fom_result.floating_tap_locations; | ||
2699 | else | 2583 | else | ||
2700 | output_args.floating_tap_locations=[]; | 2584 | output_args.floating_tap_locations=[]; | ||
2701 | end | 2585 | end | ||
2702 | 2586 | ||||
2703 | if OP.RxFFE | 2587 | if OP.RxFFE | ||
2704 | output_args.RxFFE=fom_result.RxFFE; | 2588 | output_args.RxFFE=fom_result.RxFFE; | ||
2705 | output_args.RxFFEgain=param.current_ffegain; | 2589 | output_args.RxFFEgain=param.current_ffegain; | ||
2706 | else % Yasou Hidaka 11/20/2018 help to align csv file columns | 2590 | else % Yasou Hidaka 11/20/2018 help to align csv file columns | ||
2707 | output_args.RxFFE=[]; | 2591 | output_args.RxFFE=[]; | ||
2708 | output_args.RxFFEgain=[]; | 2592 | output_args.RxFFEgain=[]; | ||
2709 | end | 2593 | end | ||
2710 | 2594 | ||||
2711 | output_args.itick=fom_result.itick; | 2595 | output_args.itick=fom_result.itick; | ||
2712 | 2596 | ||||
2713 | % Calculation of error propagation and burst probability | 2597 | % Calculation of error propagation and burst probability | ||
2714 | if OP.nburst>0 | 2598 | if OP.nburst>0 | ||
2715 | [p_burst,p_error_propagation]=Burst_Probability_Calc(COM_SNR_Struct,fom_result.DFE_taps,param,OP); | 2599 | [p_burst,p_error_propagation]=Burst_Probability_Calc(COM_SNR_Struct,fom_result.DFE_taps,param,OP); | ||
2716 | output_args.error_propagation_probability = p_error_propagation; | 2600 | output_args.error_propagation_probability = p_error_propagation; | ||
2717 | output_args.burst_probabilities = p_burst; | 2601 | output_args.burst_probabilities = p_burst; | ||
2718 | else | 2602 | else | ||
2719 | output_args.error_propagation_probability = []; | 2603 | output_args.error_propagation_probability = []; | ||
2720 | output_args.burst_probabilities = []; | 2604 | output_args.burst_probabilities = []; | ||
2721 | end | 2605 | end | ||
2722 | 2606 | ||||
2723 | 2607 | ||||
2724 | %begin yasuo patch 12/11/2018 | 2608 | %begin yasuo patch 12/11/2018 | ||
2725 | % collect sigma values to report | 2609 | % collect sigma values to report | ||
2726 | % pdf2sgm() is a function to calculate sigma value from PDF | 2610 | % pdf2sgm() is a function to calculate sigma value from PDF | ||
2727 | % It is added at the end of this file code. | 2611 | % It is added at the end of this file code. | ||
2728 | % I am not sure if an equivalent function already exists. | 2612 | % I am not sure if an equivalent function already exists. | ||
2729 | output_args.sgm_Ani__isi_xt_noise = pdf2sgm(COM_SNR_Struct.combined_interference_and_noise_pdf); | 2613 | output_args.sgm_Ani__isi_xt_noise = pdf2sgm(COM_SNR_Struct.combined_interference_and_noise_pdf); | ||
2730 | output_args.sgm_isi_xt = pdf2sgm(Noise_Struct.isi_and_xtalk_pdf); | 2614 | output_args.sgm_isi_xt = pdf2sgm(Noise_Struct.isi_and_xtalk_pdf); | ||
2731 | output_args.sgm_noise__gaussian_noise_p_DD = pdf2sgm(Noise_Struct.noise_pdf); | 2615 | output_args.sgm_noise__gaussian_noise_p_DD = pdf2sgm(Noise_Struct.noise_pdf); | ||
2732 | output_args.sgm_p_DD = pdf2sgm(Noise_Struct.p_DD); | 2616 | output_args.sgm_p_DD = pdf2sgm(Noise_Struct.p_DD); | ||
2733 | output_args.sgm_gaussian_noise = pdf2sgm(Noise_Struct.gaussian_noise_pdf); | 2617 | output_args.sgm_gaussian_noise = pdf2sgm(Noise_Struct.gaussian_noise_pdf); | ||
2734 | output_args.sgm_G = Noise_Struct.sigma_G; | 2618 | output_args.sgm_G = Noise_Struct.sigma_G; | ||
2735 | output_args.sgm_rjit = Noise_Struct.sigma_rjit; | 2619 | output_args.sgm_rjit = Noise_Struct.sigma_rjit; | ||
2736 | output_args.sgm_N = Noise_Struct.sigma_N; | 2620 | output_args.sgm_N = Noise_Struct.sigma_N; | ||
2737 | output_args.sgm_TX = Noise_Struct.sigma_TX; | 2621 | output_args.sgm_TX = Noise_Struct.sigma_TX; | ||
2738 | output_args.sgm_isi = pdf2sgm(Noise_Struct.sci_pdf); | 2622 | output_args.sgm_isi = pdf2sgm(Noise_Struct.sci_pdf); | ||
2739 | if OP.RX_CALIBRATION == 0 | 2623 | if OP.RX_CALIBRATION == 0 | ||
2740 | output_args.sgm_xt = pdf2sgm(Noise_Struct.cci_pdf); | 2624 | output_args.sgm_xt = pdf2sgm(Noise_Struct.cci_pdf); | ||
2741 | else | 2625 | else | ||
2742 | output_args.sgm_xt=[]; | 2626 | output_args.sgm_xt=[]; | ||
2743 | end | 2627 | end | ||
2744 | % end yasuo patch | 2628 | % end yasuo patch | ||
2745 | 2629 | ||||
2746 | % r259 putting COM, VEO and loss last in report | 2630 | % r259 putting COM, VEO and loss last in report | ||
2747 | % output_args.VEO_normalized = (A_s-A_ni)/A_s; | 2631 | % output_args.VEO_normalized = (A_s-A_ni)/A_s; | ||
2748 | output_args.VEC_dB = COM_SNR_Struct.VEC_dB; | 2632 | output_args.VEC_dB = COM_SNR_Struct.VEC_dB; | ||
2749 | output_args.VEO_mV = COM_SNR_Struct.VEO_mV; | 2633 | output_args.VEO_mV = COM_SNR_Struct.VEO_mV; | ||
2750 | if OP.RX_CALIBRATION ==0 && OP.EW == 1 | 2634 | if OP.RX_CALIBRATION ==0 && OP.EW == 1 | ||
2751 | output_args.EW_UI_est=COM_SNR_Struct.EW_UI; | 2635 | output_args.EW_UI_est=COM_SNR_Struct.EW_UI; | ||
2752 | output_args.eye_contour=COM_SNR_Struct.eye_contour; | 2636 | output_args.eye_contour=COM_SNR_Struct.eye_contour; | ||
2753 | output_args.VEO_window_mUI= param.T_O; | 2637 | output_args.VEO_window_mUI= param.T_O; | ||
2754 | else | 2638 | else | ||
2755 | output_args.EW_UI_est=[]; | 2639 | output_args.EW_UI_est=[]; | ||
2756 | output_args.eye_contour=[]; | 2640 | output_args.eye_contour=[]; | ||
2757 | output_args.VEO_window_mUI= []; | 2641 | output_args.VEO_window_mUI= []; | ||
2758 | end | 2642 | end | ||
2759 | 2643 | ||||
2760 | if sum(param.AC_CM_RMS) ~= 0 | 2644 | if sum(param.AC_CM_RMS) ~= 0 | ||
2761 | output_args.sigma_ACCM_at_tp0_mV=chdata(1).sigma_ACCM_at_tp0*1000; | 2645 | output_args.sigma_ACCM_at_tp0_mV=chdata(1).sigma_ACCM_at_tp0*1000; | ||
2762 | fprintf(' AC RMS at TP0 = %.3g mV \n',output_args.sigma_ACCM_at_tp0_mV) | 2646 | fprintf(' AC RMS at TP0 = %.3g mV \n',output_args.sigma_ACCM_at_tp0_mV) | ||
2763 | output_args.sigma_AC_CCM_at_rxpkg_output_mV=chdata(1).CD_CM_RMS*1000; % | 2647 | output_args.sigma_AC_CCM_at_rxpkg_output_mV=chdata(1).CD_CM_RMS*1000; % | ||
2764 | else | 2648 | else | ||
2765 | output_args.sigma_ACCM_at_tp0_mV=[]; | 2649 | output_args.sigma_ACCM_at_tp0_mV=[]; | ||
2766 | output_args.sigma_AC_CCM_at_rxpkg_output_mV=[]; | 2650 | output_args.sigma_AC_CCM_at_rxpkg_output_mV=[]; | ||
2767 | end | 2651 | end | ||
2768 | if OP.MLSE | 2652 | if OP.MLSE | ||
2769 | output_args.COM_orig=COM_SNR_Struct.COM_orig; | 2653 | output_args.COM_orig=COM_SNR_Struct.COM_orig; | ||
2770 | output_args.VEC_dB_orig=COM_SNR_Struct.VEC_dB_orig; | 2654 | output_args.VEC_dB_orig=COM_SNR_Struct.VEC_dB_orig; | ||
2771 | end | 2655 | end | ||
2772 | % | 2656 | % | ||
2773 | output_args.COM_dB=COM_SNR_Struct.COM; | 2657 | output_args.COM_dB=COM_SNR_Struct.COM; | ||
2774 | % end yasuo patch | 2658 | % end yasuo patch | ||
2775 | % begin yasuo patch 3/18/2019 | 2659 | % begin yasuo patch 3/18/2019 | ||
2776 | output_args.DER_thresh = COM_SNR_Struct.threshold_DER; | 2660 | output_args.DER_thresh = COM_SNR_Struct.threshold_DER; | ||
2777 | % end yasuo patch | 2661 | % end yasuo patch | ||
2778 | function [ seq syms syms_nrz ] = PRBS13Q( ) | 2662 | function [ seq syms syms_nrz ] = PRBS13Q( ) | ||
2779 | %UNTITLED Summary of this function goes here | 2663 | %UNTITLED Summary of this function goes here | ||
2780 | % Detailed explanation goes here | 2664 | % Detailed explanation goes here | ||
2781 | 2665 | ||||
2782 | 2666 | ||||
2783 | taps = ([13 12 2 1]); | 2667 | taps = ([13 12 2 1]); | ||
2784 | seed =([0 0 0 0 0 1 0 1 0 1 0 1 1]); | 2668 | seed =([0 0 0 0 0 1 0 1 0 1 0 1 1]); | ||
2785 | [seq_nrz c] =LFSR(seed,taps); | 2669 | [seq_nrz c] =LFSR(seed,taps); | ||
2786 | seq_nrz=2*(seq_nrz-0.5); | 2670 | seq_nrz=2*(seq_nrz-0.5); | ||
2787 | seq=pam(seq_nrz); | 2671 | seq=pam(seq_nrz); | ||
2788 | % syms=round(2*(seq+1)); | 2672 | % syms=round(2*(seq+1)); | ||
2789 | syms((round(2*(seq+1))/2==2))=3; | 2673 | syms((round(2*(seq+1))/2==2))=3; | ||
2790 | syms((round(2*(seq+1))/2==1.5))=2; | 2674 | syms((round(2*(seq+1))/2==1.5))=2; | ||
2791 | syms((round(2*(seq+1))/2==.5))=1; | 2675 | syms((round(2*(seq+1))/2==.5))=1; | ||
2792 | syms((round(2*(seq+1))/2==0))=0; | 2676 | syms((round(2*(seq+1))/2==0))=0; | ||
2793 | 2677 | ||||
2794 | % syms_nrz=((seq_nrz+1)/2); | 2678 | % syms_nrz=((seq_nrz+1)/2); | ||
2795 | 2679 | ||||
2796 | syms_nrz=seq_nrz; | 2680 | syms_nrz=seq_nrz; | ||
2797 | 2681 | ||||
2798 | 2682 | ||||
2799 | function[seq c]=LFSR(s,t) | 2683 | function[seq c]=LFSR(s,t) | ||
2800 | %s=initial state of LFSR, you can choose any lenght of LFSR | 2684 | %s=initial state of LFSR, you can choose any lenght of LFSR | ||
2801 | %Instruction:========== | 2685 | %Instruction:========== | ||
2802 | %Save LFSR.m in your current directory and type following | 2686 | %Save LFSR.m in your current directory and type following | ||
2803 | %on Command window for simulating 5 bit LFSR with tap [5 2] | 2687 | %on Command window for simulating 5 bit LFSR with tap [5 2] | ||
2804 | %--------------------- | 2688 | %--------------------- | ||
2805 | %>>s=[1 1 0 0 1] | 2689 | %>>s=[1 1 0 0 1] | ||
2806 | %>>t=[5 2] | 2690 | %>>t=[5 2] | ||
2807 | %>>[seq c] =LFSR(s,t) | 2691 | %>>[seq c] =LFSR(s,t) | ||
2808 | %--------------------------- | 2692 | %--------------------------- | ||
2809 | %seq = generated sequence | 2693 | %seq = generated sequence | ||
2810 | %c will be matrix containing the states of LFSR raw wise | 2694 | %c will be matrix containing the states of LFSR raw wise | ||
2811 | % | 2695 | % | ||
2812 | %----------------------------------------------------------- | 2696 | %----------------------------------------------------------- | ||
2813 | %If any doubt, confusion or feedback please contact me | 2697 | %If any doubt, confusion or feedback please contact me | ||
2814 | % NIKESH BAJAJ | 2698 | % NIKESH BAJAJ | ||
2815 | % bajaj.nikkey@gmail.com (+91-9915522564) | 2699 | % bajaj.nikkey@gmail.com (+91-9915522564) | ||
2816 | % Asst. Professor at Lovely Profesional University | 2700 | % Asst. Professor at Lovely Profesional University | ||
2817 | % Masters from Aligarh Muslim University,INDIA | 2701 | % Masters from Aligarh Muslim University,INDIA | ||
2818 | %-------------------------------------------------- | 2702 | %-------------------------------------------------- | ||
2819 | n=length(s); | 2703 | n=length(s); | ||
2820 | c(1,:)=s; | 2704 | c(1,:)=s; | ||
2821 | m=length(t); | 2705 | m=length(t); | ||
2822 | for k=1:2^n-2; | 2706 | for k=1:2^n-2; | ||
2823 | b(1)=xor(s(t(1)), s(t(2))); | 2707 | b(1)=xor(s(t(1)), s(t(2))); | ||
2824 | if m>2; | 2708 | if m>2; | ||
2825 | for i=1:m-2; | 2709 | for i=1:m-2; | ||
2826 | b(i+1)=xor(s(t(i+2)), b(i)); | 2710 | b(i+1)=xor(s(t(i+2)), b(i)); | ||
2827 | end | 2711 | end | ||
2828 | end | 2712 | end | ||
2829 | j=1:n-1; | 2713 | j=1:n-1; | ||
2830 | s(n+1-j)=s(n-j); | 2714 | s(n+1-j)=s(n-j); | ||
2831 | s(1)=b(m-1); | 2715 | s(1)=b(m-1); | ||
2832 | c(k+1,:)=s; | 2716 | c(k+1,:)=s; | ||
2833 | end | 2717 | end | ||
2834 | seq=c(:,n)'; | 2718 | seq=c(:,n)'; | ||
2835 | 2719 | ||||
2836 | function [ dataout ] = pam( data ) | 2720 | function [ dataout ] = pam( data ) | ||
2837 | % mapping data usng Grey Coding | 2721 | % mapping data usng Grey Coding | ||
2838 | for i=1:2:floor(length(data)/2)*2 | 2722 | for i=1:2:floor(length(data)/2)*2 | ||
2839 | if data(i:i+1)==[ -1 -1 ] | 2723 | if data(i:i+1)==[ -1 -1 ] | ||
2840 | dataout(ceil(i/2)) = -1; | 2724 | dataout(ceil(i/2)) = -1; | ||
2841 | elseif data(i:i+1)==[ -1 1 ] | 2725 | elseif data(i:i+1)==[ -1 1 ] | ||
2842 | dataout(ceil(i/2)) = -1/3; | 2726 | dataout(ceil(i/2)) = -1/3; | ||
2843 | elseif data(i:i+1)==[ 1 1 ] | 2727 | elseif data(i:i+1)==[ 1 1 ] | ||
2844 | dataout(ceil(i/2)) = 1/3; | 2728 | dataout(ceil(i/2)) = 1/3; | ||
2845 | elseif data(i:i+1)==[ 1 -1 ] | 2729 | elseif data(i:i+1)==[ 1 -1 ] | ||
2846 | dataout(ceil(i/2)) = 1; | 2730 | dataout(ceil(i/2)) = 1; | ||
2847 | end | 2731 | end | ||
2848 | end | 2732 | end | ||
2849 | function RILN_TD_struct=RILN_TD(sdd21,RIL,faxis_f2,OP,param,A_T) | 2733 | function RILN_TD_struct=RILN_TD(sdd21,RIL,faxis_f2,OP,param,A_T) | ||
2850 | db = @(x) 20*log10(abs(x)); | 2734 | db = @(x) 20*log10(abs(x)); | ||
2851 | disp('computing TD_RILN...') | 2735 | disp('computing TD_RILN...') | ||
2852 | sdd21=squeeze(sdd21); | 2736 | sdd21=squeeze(sdd21); | ||
2853 | if iscolumn(sdd21) | 2737 | if iscolumn(sdd21) | ||
2854 | sdd21=sdd21.'; | 2738 | sdd21=sdd21.'; | ||
2855 | end | 2739 | end | ||
2856 | RIL=squeeze(RIL); | 2740 | RIL=squeeze(RIL); | ||
2857 | if iscolumn(RIL) | 2741 | if iscolumn(RIL) | ||
2858 | RIL=RIL.'; | 2742 | RIL=RIL.'; | ||
2859 | end | 2743 | end | ||
2860 | print_for_codereview=1; | 2744 | print_for_codereview=1; | ||
2861 | if exist('OP','var') | 2745 | if exist('OP','var') | ||
2862 | X=sinc(faxis_f2*param.ui)*param.ui*1e9; | 2746 | X=sinc(faxis_f2*param.ui)*param.ui*1e9; | ||
2863 |
| 2747 |
| ||
2864 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | 2748 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | ||
2865 | H_bw=Butterworth_Filter(param,faxis_f2,1); | 2749 | H_bw=Butterworth_Filter(param,faxis_f2,1); | ||
2866 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 2750 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
2867 | H_tw=Tukey_Window(faxis_f2,param); | 2751 | H_tw=Tukey_Window(faxis_f2,param); | ||
2868 | H_tw=ones(1,length(faxis_f2) ); | 2752 | H_tw=ones(1,length(faxis_f2) ); | ||
2869 | [RILN_TD_struct.REF.FIR, ... | 2753 | [RILN_TD_struct.REF.FIR, ... | ||
2870 | RILN_TD_struct.REF.t, ... | 2754 | RILN_TD_struct.REF.t, ... | ||
2871 | RILN_TD_struct.REF.causality_correction_dB, ... | 2755 | RILN_TD_struct.REF.causality_correction_dB, ... | ||
2872 | RILN_TD_struct.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 2756 | RILN_TD_struct.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
2873 | RILN_TD_struct.REF.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF.FIR); | 2757 | RILN_TD_struct.REF.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF.FIR); | ||
2874 | [RILN_TD_struct.FIT.FIR, ... | 2758 | [RILN_TD_struct.FIT.FIR, ... | ||
2875 | RILN_TD_struct.FIT.t, ... | 2759 | RILN_TD_struct.FIT.t, ... | ||
2876 | RILN_TD_struct.FIT.causality_correction_dB, ... | 2760 | RILN_TD_struct.FIT.causality_correction_dB, ... | ||
2877 | RILN_TD_struct.FIT.truncation_dB] = s21_to_impulse_DC(RIL.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 2761 | RILN_TD_struct.FIT.truncation_dB] = s21_to_impulse_DC(RIL.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
2878 | RILN_TD_struct.FIT.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.FIT.FIR); | 2762 | RILN_TD_struct.FIT.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.FIT.FIR); | ||
2879 | ipeak=find(RILN_TD_struct.REF.PR==max(RILN_TD_struct.REF.PR),1,'first'); | 2763 | ipeak=find(RILN_TD_struct.REF.PR==max(RILN_TD_struct.REF.PR),1,'first'); | ||
2880 | NrangeUI=1000; | 2764 | NrangeUI=1000; | ||
2881 | range_end=min(ipeak+param.samples_per_ui*NrangeUI,min(length(RILN_TD_struct.FIT.FIR), length(RILN_TD_struct.REF.FIR) ) ) ; | 2765 | range_end=min(ipeak+param.samples_per_ui*NrangeUI,min(length(RILN_TD_struct.FIT.FIR), length(RILN_TD_struct.REF.FIR) ) ) ; | ||
2882 | range=ipeak:range_end; | 2766 | range=ipeak:range_end; | ||
2883 | RILN_TD_struct.ILN=RILN_TD_struct.FIT.PR(range)-RILN_TD_struct.REF.PR(range); | 2767 | RILN_TD_struct.ILN=RILN_TD_struct.FIT.PR(range)-RILN_TD_struct.REF.PR(range); | ||
2884 | RILN_TD_struct.t=RILN_TD_struct.FIT.t(range); | 2768 | RILN_TD_struct.t=RILN_TD_struct.FIT.t(range); | ||
2885 | RILN_TD_struct.FOM=-inf; | 2769 | RILN_TD_struct.FOM=-inf; | ||
2886 | RILN_TD_struct.FOM_PDF=-inf; | 2770 | RILN_TD_struct.FOM_PDF=-inf; | ||
2887 | rms_fom=-inf; | 2771 | rms_fom=-inf; | ||
2888 | for im=1:param.samples_per_ui | 2772 | for im=1:param.samples_per_ui | ||
2889 | RILN_TD_struct.FOM=max(RILN_TD_struct.FOM, norm( RILN_TD_struct.ILN(im:param.samples_per_ui:end))); | 2773 | RILN_TD_struct.FOM=max(RILN_TD_struct.FOM, norm( RILN_TD_struct.ILN(im:param.samples_per_ui:end))); | ||
2890 | [ pdf ] = get_pdf_from_sampled_signal( RILN_TD_struct.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | 2774 | [ pdf ] = get_pdf_from_sampled_signal( RILN_TD_struct.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | ||
2891 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | 2775 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | ||
2892 | cdf=pdf; cdf.y=cumsum(pdf.y); | 2776 | cdf=pdf; cdf.y=cumsum(pdf.y); | ||
2893 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | 2777 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | ||
2894 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | 2778 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | ||
2895 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | 2779 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | ||
2896 | if print_for_codereview % remove once all checked out | 2780 | if print_for_codereview % remove once all checked out | ||
2897 | h=figure(191);set(gcf,'Tag','COM'); | 2781 | h=figure(191);set(gcf,'Tag','COM'); | ||
2898 | semilogy(-cdf.x,cdf.y); | 2782 | semilogy(-cdf.x,cdf.y); | ||
2899 | % xlim ([0,-cdf.x(1)]) | 2783 | % xlim ([0,-cdf.x(1)]) | ||
2900 | ylim([param.specBER 1]);title ('CDF of RILN') | 2784 | ylim([param.specBER 1]);title ('CDF of RILN') | ||
2901 | hold on | 2785 | hold on | ||
2902 | end | 2786 | end | ||
2903 | if rms>rms_fom | 2787 | if rms>rms_fom | ||
2904 | rms_fom=rms; | 2788 | rms_fom=rms; | ||
2905 | RILN_TD_struct.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | 2789 | RILN_TD_struct.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | ||
2906 | RILN_TD_struct.PDF=pdf; | 2790 | RILN_TD_struct.PDF=pdf; | ||
2907 | end | 2791 | end | ||
2908 | end | 2792 | end | ||
2909 | pdf_from_norm=normal_dist(RILN_TD_struct.FOM, 7 , OP.BinSize); | 2793 | pdf_from_norm=normal_dist(RILN_TD_struct.FOM, 7 , OP.BinSize); | ||
2910 | RILN_TD_struct.SNR_ISI_FOM=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM); | 2794 | RILN_TD_struct.SNR_ISI_FOM=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM); | ||
2911 | RILN_TD_struct.SNR_ISI_FOM_PDF=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM_PDF); | 2795 | RILN_TD_struct.SNR_ISI_FOM_PDF=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM_PDF); | ||
2912 | if print_for_codereview % remove once all checked out | 2796 | if print_for_codereview % remove once all checked out | ||
2913 | figure(9003);set(gcf,'Tag','COM'); | 2797 | figure(9003);set(gcf,'Tag','COM'); | ||
2914 | plot(RILN_TD_struct.t,RILN_TD_struct.ILN,'disp','td riln') | 2798 | plot(RILN_TD_struct.t,RILN_TD_struct.ILN,'disp','td riln') | ||
2915 | hold on | 2799 | hold on | ||
2916 | plot(RILN_TD_struct.FIT.t,RILN_TD_struct.FIT.PR,'disp','fit') | 2800 | plot(RILN_TD_struct.FIT.t,RILN_TD_struct.FIT.PR,'disp','fit') | ||
2917 | plot(RILN_TD_struct.REF.t,RILN_TD_struct.REF.PR,'disp','ref') | 2801 | plot(RILN_TD_struct.REF.t,RILN_TD_struct.REF.PR,'disp','ref') | ||
2918 | hold off | 2802 | hold off | ||
2919 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',RILN_TD_struct.SNR_ISI_FOM,RILN_TD_struct.SNR_ISI_FOM_PDF) | 2803 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',RILN_TD_struct.SNR_ISI_FOM,RILN_TD_struct.SNR_ISI_FOM_PDF) | ||
2920 | figure(9004);set(gcf,'Tag','COM'); | 2804 | figure(9004);set(gcf,'Tag','COM'); | ||
2921 | semilogy(RILN_TD_struct.PDF.x,RILN_TD_struct.PDF.y,'disp','actual PDF') | 2805 | semilogy(RILN_TD_struct.PDF.x,RILN_TD_struct.PDF.y,'disp','actual PDF') | ||
2922 | hold on | 2806 | hold on | ||
2923 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | 2807 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | ||
2924 | ylim([param.specBER max([RILN_TD_struct.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | 2808 | ylim([param.specBER max([RILN_TD_struct.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | ||
2925 | grid on | 2809 | grid on | ||
2926 | legend('show') | 2810 | legend('show') | ||
2927 | end | 2811 | end | ||
2928 | end | 2812 | end | ||
2929 | function is_illegal=RXFFE_Illegal(C,param,last_index) | 2813 | function is_illegal=RXFFE_Illegal(C,param,last_index) | ||
2930 | 2814 | ||||
2931 | %check if RXFFE taps are illegal | 2815 | %check if RXFFE taps are illegal | ||
2932 | %C = RXFFE taps | 2816 | %C = RXFFE taps | ||
2933 | %param = COM param struct | 2817 | %param = COM param struct | ||
2934 | %last_index is used when computing illegality prior to Backoff. It will be set so taps | 2818 | %last_index is used when computing illegality prior to Backoff. It will be set so taps | ||
2935 | % in the Backoff region are not considered in the legality check. | 2819 | % in the Backoff region are not considered in the legality check. | ||
2936 | 2820 | ||||
2937 | %If last index is omitted, set it to length(C) | 2821 | %If last index is omitted, set it to length(C) | ||
2938 | if nargin<3 | 2822 | if nargin<3 | ||
2939 | last_index=length(C); | 2823 | last_index=length(C); | ||
2940 | end | 2824 | end | ||
2941 | 2825 | ||||
2942 | is_illegal=0; | 2826 | is_illegal=0; | ||
2943 | 2827 | ||||
2944 | %Check cursor tap | 2828 | %Check cursor tap | ||
2945 | Ccur_i=param.RxFFE_cmx+1; | 2829 | Ccur_i=param.RxFFE_cmx+1; | ||
2946 | if C(Ccur_i) < param.ffe_main_cursor_min | 2830 | if C(Ccur_i) < param.ffe_main_cursor_min | ||
2947 | is_illegal=1; | 2831 | is_illegal=1; | ||
2948 | return; | 2832 | return; | ||
2949 | end | 2833 | end | ||
2950 | 2834 | ||||
2951 | %Check postcursors | 2835 | %Check postcursors | ||
2952 | if param.ffe_post_tap_len ~=0 | 2836 | if param.ffe_post_tap_len ~=0 | ||
2953 | if abs(C(Ccur_i +1)) > param.ffe_post_tap1_max | 2837 | if abs(C(Ccur_i +1)) > param.ffe_post_tap1_max | ||
2954 | is_illegal=1; | 2838 | is_illegal=1; | ||
2955 | return; | 2839 | return; | ||
2956 | end | 2840 | end | ||
2957 | if (param.ffe_post_tap_len > 1) | 2841 | if (param.ffe_post_tap_len > 1) | ||
2958 | if sum(abs(C((Ccur_i +2):last_index)) > param.ffe_tapn_max) | 2842 | if sum(abs(C((Ccur_i +2):last_index)) > param.ffe_tapn_max) | ||
2959 | is_illegal=1; | 2843 | is_illegal=1; | ||
2960 | return; | 2844 | return; | ||
2961 | end | 2845 | end | ||
2962 | end | 2846 | end | ||
2963 | end | 2847 | end | ||
2964 | 2848 | ||||
2965 | %Check precursors | 2849 | %Check precursors | ||
2966 | if param.ffe_pre_tap_len ~=0 | 2850 | if param.ffe_pre_tap_len ~=0 | ||
2967 | if abs(C(Ccur_i -1)) > param.ffe_pre_tap1_max | 2851 | if abs(C(Ccur_i -1)) > param.ffe_pre_tap1_max | ||
2968 | is_illegal=1; | 2852 | is_illegal=1; | ||
2969 | return; | 2853 | return; | ||
2970 | end | 2854 | end | ||
2971 | if (param.ffe_pre_tap_len > 1) | 2855 | if (param.ffe_pre_tap_len > 1) | ||
2972 | % if sum(abs(C((Ccur_i +2):end)) > param.ffe_tapn_max) , continue; end | 2856 | % if sum(abs(C((Ccur_i +2):end)) > param.ffe_tapn_max) , continue; end | ||
2973 | if sum(abs(C(1:(Ccur_i - 2))) > param.ffe_tapn_max) | 2857 | if sum(abs(C(1:(Ccur_i - 2))) > param.ffe_tapn_max) | ||
2974 | is_illegal=1; | 2858 | is_illegal=1; | ||
2975 | return; | 2859 | return; | ||
2976 | end % 11.22.2018 Yasou Hadaka | 2860 | end % 11.22.2018 Yasou Hadaka | ||
2977 | end | 2861 | end | ||
2978 | end | 2862 | end | ||
2979 | function S =R_series2(zref,f,R) | 2863 | function S =R_series2(zref,f,R) | ||
2980 | r=ones(1,length(f))*R; | 2864 | r=ones(1,length(f))*R; | ||
2981 | S.Parameters(1,1,:) = r./(r + 2*zref); | 2865 | S.Parameters(1,1,:) = r./(r + 2*zref); | ||
2982 | S.Parameters(2,2,:) = r./(r + 2*zref); | 2866 | S.Parameters(2,2,:) = r./(r + 2*zref); | ||
2983 | S.Parameters(2,1,:) = (2*zref)./(r + 2*zref); | 2867 | S.Parameters(2,1,:) = (2*zref)./(r + 2*zref); | ||
2984 | S.Parameters(1,2,:) = (2*zref)./(r + 2*zref); | 2868 | S.Parameters(1,2,:) = (2*zref)./(r + 2*zref); | ||
2985 | % Sm=sparameters(S.Parameters,f,zref); | 2869 | % Sm=sparameters(S.Parameters,f,zref); | ||
2986 | 2870 | ||||
2987 | function H_tw=Raised_Cosine_Filter(param,f,use_RC) | 2871 | function H_tw=Raised_Cosine_Filter(param,f,use_RC) | ||
2988 | 2872 | ||||
2989 | if use_RC | 2873 | if use_RC | ||
2990 | H_tw = Tukey_Window(f,param ,param.RC_Start, param.RC_end);% add tw filter; | 2874 | H_tw = Tukey_Window(f,param ,param.RC_Start, param.RC_end);% add tw filter; | ||
2991 | else | 2875 | else | ||
2992 | H_tw=ones(1,length(f)); | 2876 | H_tw=ones(1,length(f)); | ||
2993 | end | 2877 | end | ||
2994 | function SLD=SL(S,f,R) | 2878 | function SLD=SL(S,f,R) | ||
2995 | % source load impact return loss add to S21 | 2879 | % source load impact return loss add to S21 | ||
2996 | % S and SLD are the same structure | 2880 | % S and SLD are the same structure | ||
2997 | % S.Parameters | 2881 | % S.Parameters | ||
2998 | % S.Impedance | 2882 | % S.Impedance | ||
2999 | % S.NumPorts | 2883 | % S.NumPorts | ||
3000 | % S.Frequencies | 2884 | % S.Frequencies | ||
3001 | SLD=S; % assign the fields | 2885 | SLD=S; % assign the fields | ||
3002 | zref=100; | 2886 | zref=100; | ||
3003 | if R==0 | 2887 | if R==0 | ||
3004 | warndlg('Termination should not be set to zero'); | 2888 | warndlg('Termination should not be set to zero'); | ||
3005 | SLD=S; | 2889 | SLD=S; | ||
3006 | return | 2890 | return | ||
3007 | end | 2891 | end | ||
3008 | 2892 | ||||
3009 | if R > zref | 2893 | if R > zref | ||
3010 | spr =R_series2(zref,f,(R-zref)); % make series sparameter | 2894 | spr =R_series2(zref,f,(R-zref)); % make series sparameter | ||
3011 | % SLD=sparameters(cascadesparams(S.Parameters,spr.Parameters),f,S.Impedance); % Casdeade | 2895 | % SLD=sparameters(cascadesparams(S.Parameters,spr.Parameters),f,S.Impedance); % Casdeade | ||
3012 | [ SLD.Parameters(1,1,:), SLD.Parameters(1,2,:), SLD.Parameters(2,1,:), SLD.Parameters(2,2,:)] = ... | 2896 | [ SLD.Parameters(1,1,:), SLD.Parameters(1,2,:), SLD.Parameters(2,1,:), SLD.Parameters(2,2,:)] = ... | ||
3013 | combines4p( ... | 2897 | combines4p( ... | ||
3014 | spr.Parameters(1,1,:), spr.Parameters(1,2,:), spr.Parameters(2,1,:), spr.Parameters(2,2,:),... | 2898 | spr.Parameters(1,1,:), spr.Parameters(1,2,:), spr.Parameters(2,1,:), spr.Parameters(2,2,:),... | ||
3015 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ... | 2899 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ... | ||
3016 | ); | 2900 | ); | ||
3017 | elseif R < zref | 2901 | elseif R < zref | ||
3018 | spr =r_parrelell2(zref,f,-R*zref/(R-zref)); % make parrellel sparameter | 2902 | spr =r_parrelell2(zref,f,-R*zref/(R-zref)); % make parrellel sparameter | ||
3019 | % SLD=sparameters(cascadesparams(S.Parameters,spr.Parameters),f,S.Impedance); | 2903 | % SLD=sparameters(cascadesparams(S.Parameters,spr.Parameters),f,S.Impedance); | ||
3020 | [ SLD.Parameters(1,1,:), SLD.Parameters(1,2,:), SLD.Parameters(2,1,:), SLD.Parameters(2,2,:)] = ... | 2904 | [ SLD.Parameters(1,1,:), SLD.Parameters(1,2,:), SLD.Parameters(2,1,:), SLD.Parameters(2,2,:)] = ... | ||
3021 | combines4p( ... | 2905 | combines4p( ... | ||
3022 | spr.Parameters(1,1,:), spr.Parameters(1,2,:), spr.Parameters(2,1,:), spr.Parameters(2,2,:),... | 2906 | spr.Parameters(1,1,:), spr.Parameters(1,2,:), spr.Parameters(2,1,:), spr.Parameters(2,2,:),... | ||
3023 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ... | 2907 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ... | ||
3024 | ); | 2908 | ); | ||
3025 | else | 2909 | else | ||
3026 | SLD=S; | 2910 | SLD=S; | ||
3027 | end | 2911 | end | ||
3028 | 2912 | ||||
3029 | %% | 2913 | %% | ||
3030 | 2914 | ||||
3031 | function S_RN_of_f = S_RN(f,G_DC,G_DC2,param) | 2915 | function S_RN_of_f = S_RN(f,G_DC,G_DC2,param) | ||
3032 | p1=param.CTLE_fp1(1); | 2916 | p1=param.CTLE_fp1(1); | ||
3033 | z1=param.CTLE_fz(1); | 2917 | z1=param.CTLE_fz(1); | ||
3034 | p2=param.CTLE_fp2(1); | 2918 | p2=param.CTLE_fp2(1); | ||
3035 | zlf=param.f_HP(1); | 2919 | zlf=param.f_HP(1); | ||
3036 | plf=param.f_HP(1); | 2920 | plf=param.f_HP(1); | ||
3037 | f_b=param.fb; | 2921 | f_b=param.fb; | ||
3038 | f_r=param.f_r; | 2922 | f_r=param.f_r; | ||
3039 | eta_0=param.eta_0; | 2923 | eta_0=param.eta_0; | ||
3040 | H_CTF = ( 10^(G_DC/20)+ 1i*f/z1 ) .*( 10^(G_DC2/20) + 1i*f/zlf )./ ( ( 1+1i*f/p1) .* ( 1+1i*f/p2) .* ( 1+1i*f/plf)); | 2924 | H_CTF = ( 10^(G_DC/20)+ 1i*f/z1 ) .*( 10^(G_DC2/20) + 1i*f/zlf )./ ( ( 1+1i*f/p1) .* ( 1+1i*f/p2) .* ( 1+1i*f/plf)); | ||
3041 | H_R =1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(f_r*f_b)); | 2925 | H_R =1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(f_r*f_b)); | ||
3042 | S_RN_of_f = eta_0/2.*abs( H_CTF.*H_R).^2; %EQ healey_3dj_01_2401 slide 5 | 2926 | S_RN_of_f = eta_0/2.*abs( H_CTF.*H_R).^2; %EQ healey_3dj_01_2401 slide 5 | ||
3043 | if 0 | 2927 | if 0 | ||
3044 | figure | 2928 | figure | ||
3045 | set(gcf, 'tag', 'COM');movegui(gcf,'southeast'); | 2929 | set(gcf, 'tag', 'COM');movegui(gcf,'southeast'); | ||
3046 | % see if it looks correct | 2930 | % see if it looks correct | ||
3047 | semilogx(f/1e9, 20*log10( abs( H_CTF.*H_R)) ); | 2931 | semilogx(f/1e9, 20*log10( abs( H_CTF.*H_R)) ); | ||
3048 | ylabel('dB'); | 2932 | ylabel('dB'); | ||
3049 | xlabel('GHz'); | 2933 | xlabel('GHz'); | ||
3050 | title( 'H_ctf with H_r') | 2934 | title( 'H_ctf with H_r') | ||
3051 | grid on | 2935 | grid on | ||
3052 | ylim([-30 0]) | 2936 | ylim([-30 0]) | ||
3053 | end | 2937 | end | ||
3054 | 2938 | ||||
3055 | function [output_args,ERL,min_ERL]=TDR_ERL_Processing(output_args,OP,package_testcase_i,chdata,param) | 2939 | function [output_args,ERL,min_ERL]=TDR_ERL_Processing(output_args,OP,package_testcase_i,chdata,param) | ||
3056 | 2940 | ||||
3057 | %Fill TDR data | 2941 | %Fill TDR data | ||
3058 | if package_testcase_i == 1 | 2942 | if package_testcase_i == 1 | ||
3059 | if OP.TDR | 2943 | if OP.TDR | ||
3060 | output_args.Z11est=chdata(1).TDR11.avgZport; | 2944 | output_args.Z11est=chdata(1).TDR11.avgZport; | ||
3061 | if ~param.FLAG.S2P | 2945 | if ~param.FLAG.S2P | ||
3062 | output_args.Z22est=chdata(1).TDR22.avgZport; | 2946 | output_args.Z22est=chdata(1).TDR22.avgZport; | ||
3063 | else | 2947 | else | ||
3064 | output_args.Z22est=[]; | 2948 | output_args.Z22est=[]; | ||
3065 | end | 2949 | end | ||
3066 | if OP.AUTO_TFX | 2950 | if OP.AUTO_TFX | ||
3067 | output_args.tfx_estimate=param.tfx(2);% 11/03/2021 RIM added for nbx estimate | 2951 | output_args.tfx_estimate=param.tfx(2);% 11/03/2021 RIM added for nbx estimate | ||
3068 | else | 2952 | else | ||
3069 | output_args.tfx_estimate=[]; | 2953 | output_args.tfx_estimate=[]; | ||
3070 | end | 2954 | end | ||
3071 | else | 2955 | else | ||
3072 | output_args.Z11est=[]; | 2956 | output_args.Z11est=[]; | ||
3073 | output_args.Z22est=[]; | 2957 | output_args.Z22est=[]; | ||
3074 | output_args.tfx_estimate=[]; | 2958 | output_args.tfx_estimate=[]; | ||
3075 | end | 2959 | end | ||
3076 | end | 2960 | end | ||
3077 | 2961 | ||||
3078 | % Process ERL | 2962 | % Process ERL | ||
3079 | if package_testcase_i == 1 | 2963 | if package_testcase_i == 1 | ||
3080 | if OP.ERL | 2964 | if OP.ERL | ||
3081 | output_args.ERL11=chdata(1).TDR11.ERL; | 2965 | output_args.ERL11=chdata(1).TDR11.ERL; | ||
3082 | if ~param.FLAG.S2P | 2966 | if ~param.FLAG.S2P | ||
3083 | output_args.ERL22=chdata(1).TDR22.ERL; | 2967 | output_args.ERL22=chdata(1).TDR22.ERL; | ||
3084 | else | 2968 | else | ||
3085 | output_args.ERL22=[]; | 2969 | output_args.ERL22=[]; | ||
3086 | end | 2970 | end | ||
3087 | % output_args.ERL11RMS=chdata(1).TDR11.ERLRMS; | 2971 | % output_args.ERL11RMS=chdata(1).TDR11.ERLRMS; | ||
3088 | % if ~param.FLAG.S2P,output_args.ERL22RMS=chdata(1).TDR22.ERLRMS; | 2972 | % if ~param.FLAG.S2P,output_args.ERL22RMS=chdata(1).TDR22.ERLRMS; | ||
3089 | else | 2973 | else | ||
3090 | output_args.ERL11=[]; | 2974 | output_args.ERL11=[]; | ||
3091 | output_args.ERL22=[]; | 2975 | output_args.ERL22=[]; | ||
3092 | end | 2976 | end | ||
3093 | end | 2977 | end | ||
3094 | if OP.ERL | 2978 | if OP.ERL | ||
3095 | if OP.TDR_W_TXPKG | 2979 | if OP.TDR_W_TXPKG | ||
3096 | min_ERL=output_args.ERL22; | 2980 | min_ERL=output_args.ERL22; | ||
3097 | ERL= [ nan output_args.ERL22 ]; | 2981 | ERL= [ nan output_args.ERL22 ]; | ||
3098 | else | 2982 | else | ||
3099 | if ~isfield(output_args,'ERL22') || isempty(output_args.ERL22) | 2983 | if ~isfield(output_args,'ERL22') || isempty(output_args.ERL22) | ||
3100 | min_ERL=output_args.ERL11; | 2984 | min_ERL=output_args.ERL11; | ||
3101 | ERL= [ output_args.ERL11 nan ]; | 2985 | ERL= [ output_args.ERL11 nan ]; | ||
3102 | else | 2986 | else | ||
3103 | min_ERL=min(output_args.ERL11,output_args.ERL22); | 2987 | min_ERL=min(output_args.ERL11,output_args.ERL22); | ||
3104 | ERL= [ output_args.ERL11 output_args.ERL22 ]; | 2988 | ERL= [ output_args.ERL11 output_args.ERL22 ]; | ||
3105 | end | 2989 | end | ||
3106 | end | 2990 | end | ||
3107 | output_args.ERL=min_ERL; | 2991 | output_args.ERL=min_ERL; | ||
3108 | else | 2992 | else | ||
3109 | min_ERL=[]; | 2993 | min_ERL=[]; | ||
3110 | ERL= []; | 2994 | ERL= []; | ||
3111 | output_args.ERL=[]; | 2995 | output_args.ERL=[]; | ||
3112 | end | 2996 | end | ||
3113 | if OP.ERL_ONLY | 2997 | if OP.ERL_ONLY | ||
3114 | if OP.BREAD_CRUMBS | 2998 | if OP.BREAD_CRUMBS | ||
3115 | output_args.OP=OP; | 2999 | output_args.OP=OP; | ||
3116 | output_args.param=param; | 3000 | output_args.param=param; | ||
3117 | output_args.chdata=chdata; | 3001 | output_args.chdata=chdata; | ||
3118 | %This seems to be the intent of setting fom_result.ran=0. Add it | 3002 | %This seems to be the intent of setting fom_result.ran=0. Add it | ||
3119 | %to output_args so there is a fom_result field. | 3003 | %to output_args so there is a fom_result field. | ||
3120 | fom_result.ran=0; | 3004 | fom_result.ran=0; | ||
3121 | output_args.fom_result=fom_result; | 3005 | output_args.fom_result=fom_result; | ||
3122 | end | 3006 | end | ||
3123 | output_args.Z_t=param.Z_t; | 3007 | output_args.Z_t=param.Z_t; | ||
3124 | fileset_str=str2csv({chdata(1).base}); | 3008 | fileset_str=str2csv({chdata(1).base}); | ||
3125 | output_args.file_names=sprintf('"%s"', fileset_str); | 3009 | output_args.file_names=sprintf('"%s"', fileset_str); | ||
3126 | if OP.DISPLAY_WINDOW | 3010 | if OP.DISPLAY_WINDOW | ||
3127 | savefigs(param, OP); | 3011 | savefigs(param, OP); | ||
3128 | end | 3012 | end | ||
3129 | end | 3013 | end | ||
3130 | function [impulse_response, p1_ctle, p2_ctle, z_ctle] = TD_CTLE(ir_in, fb, f_z, f_p1, f_p2, kacdc_dB, oversampling) | 3014 | function [impulse_response, p1_ctle, p2_ctle, z_ctle] = TD_CTLE(ir_in, fb, f_z, f_p1, f_p2, kacdc_dB, oversampling) | ||
3131 | %% Equation 93A-22 implemented in z-space and applied to the impulse response. | 3015 | %% Equation 93A-22 implemented in z-space and applied to the impulse response. | ||
3132 | p1_ctle = -2*pi*f_p1; | 3016 | p1_ctle = -2*pi*f_p1; | ||
3133 | p2_ctle = -2*pi*f_p2; | 3017 | p2_ctle = -2*pi*f_p2; | ||
3134 | z_ctle = -2*pi*f_z*10^(kacdc_dB/20); | 3018 | z_ctle = -2*pi*f_z*10^(kacdc_dB/20); | ||
3135 | k_ctle = -p2_ctle; | 3019 | k_ctle = -p2_ctle; | ||
3136 | bilinear_fs = 2*fb*oversampling; | 3020 | bilinear_fs = 2*fb*oversampling; | ||
3137 | p2d = (1+p2_ctle/bilinear_fs)./(1-p2_ctle/bilinear_fs); | 3021 | p2d = (1+p2_ctle/bilinear_fs)./(1-p2_ctle/bilinear_fs); | ||
3138 | p1d = (1+p1_ctle/bilinear_fs)./(1-p1_ctle/bilinear_fs); | 3022 | p1d = (1+p1_ctle/bilinear_fs)./(1-p1_ctle/bilinear_fs); | ||
3139 | zd = (1+z_ctle/bilinear_fs)./(1-z_ctle/bilinear_fs); | 3023 | zd = (1+z_ctle/bilinear_fs)./(1-z_ctle/bilinear_fs); | ||
3140 | % kd = (bilinear_fs-z_ctle)/((bilinear_fs-p1_ctle)*(bilinear_fs-p2_ctle)); | 3024 | % kd = (bilinear_fs-z_ctle)/((bilinear_fs-p1_ctle)*(bilinear_fs-p2_ctle)); | ||
3141 | % allow for different pole zeros RIM 9-29-2015 | 3025 | % allow for different pole zeros RIM 9-29-2015 | ||
3142 | kd = (bilinear_fs-z_ctle)./((bilinear_fs-p1_ctle)*(bilinear_fs-p2_ctle))*f_p1/f_z; | 3026 | kd = (bilinear_fs-z_ctle)./((bilinear_fs-p1_ctle)*(bilinear_fs-p2_ctle))*f_p1/f_z; | ||
3143 | B_filt =k_ctle*kd*poly([zd, -1]); | 3027 | B_filt =k_ctle*kd*poly([zd, -1]); | ||
3144 | A_filt=poly([p1d, p2d]); | 3028 | A_filt=poly([p1d, p2d]); | ||
3145 | impulse_response=filter(B_filt,A_filt,ir_in); | 3029 | impulse_response=filter(B_filt,A_filt,ir_in); | ||
3146 | 3030 | ||||
3147 | function [chdata, param, SDDch,SDDp2p] = TD_FD_fillin(param, OP, chdata) | 3031 | function [chdata, param, SDDch,SDDp2p] = TD_FD_fillin(param, OP, chdata) | ||
3148 | Over_sample=2; | 3032 | Over_sample=2; | ||
3149 | num_files=length(chdata); | 3033 | num_files=length(chdata); | ||
3150 | for i=1:num_files | 3034 | for i=1:num_files | ||
3151 | V=chdata(i).uneq_pulse_response; | 3035 | V=chdata(i).uneq_pulse_response; | ||
3152 | T=chdata(i).t; | 3036 | T=chdata(i).t; | ||
3153 | dt=T(2)-T(1); | 3037 | dt=T(2)-T(1); | ||
3154 | f=0:1/max(T):1/dt; | 3038 | f=0:1/max(T):1/dt; | ||
3155 | chdata(i).faxis=f; | 3039 | chdata(i).faxis=f; | ||
3156 | f75=find(f >= param.fb*.75,1,'first'); | 3040 | f75=find(f >= param.fb*.75,1,'first'); | ||
3157 | fnq=find(f >= param.fb*.5,1,'first'); | 3041 | fnq=find(f >= param.fb*.5,1,'first'); | ||
3158 | chdata(i).fmaxi = length(f); | 3042 | chdata(i).fmaxi = length(f); | ||
3159 | chdata(i).faxis = f; | 3043 | chdata(i).faxis = f; | ||
3160 | UI=param.ui; % unit interval | 3044 | UI=param.ui; % unit interval | ||
3161 | M=param.samples_per_ui; % sample per UI | 3045 | M=param.samples_per_ui; % sample per UI | ||
3162 | N_v=param.N_v; % number of UI for Vf determination | 3046 | N_v=param.N_v; % number of UI for Vf determination | ||
3163 |
| 3047 |
| ||
3164 | % filters | 3048 | % filters | ||
3165 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | 3049 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | ||
3166 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | 3050 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | ||
3167 | H_ftr=H_bw.*H_bt; | 3051 | H_ftr=H_bw.*H_bt; | ||
3168 | H_ftr=H_ftr(:); | 3052 | H_ftr=H_ftr(:); | ||
3169 | % fd of PR | 3053 | % fd of PR | ||
3170 | prr=sin(f*UI*pi)./(f*UI*pi); %nremoving sinc function to avoid using sig proc toolbox | 3054 | prr=sin(f*UI*pi)./(f*UI*pi); %nremoving sinc function to avoid using sig proc toolbox | ||
3171 | prr = prr(:); | 3055 | prr = prr(:); | ||
3172 | if f(1)==0, prr(1)=1; end %remove NaN | 3056 | if f(1)==0, prr(1)=1; end %remove NaN | ||
3173 | fd=fft(V); | 3057 | fd=fft(V); | ||
3174 | fd=fd(1:floor(length(fd)/2)); % un process freq domain response | 3058 | fd=fd(1:floor(length(fd)/2)); % un process freq domain response | ||
3175 |
| 3059 |
| ||
3176 | %% get Vf | 3060 | %% get Vf | ||
3177 | shifting_vector=kron(ones(1,200) ,[ 1 zeros(1,M-1) ]) ; | 3061 | shifting_vector=kron(ones(1,200) ,[ 1 zeros(1,M-1) ]) ; | ||
3178 | step_response=filter(V,1, shifting_vector); | 3062 | step_response=filter(V,1, shifting_vector); | ||
3179 | Vf=step_response(end); | 3063 | Vf=step_response(end); | ||
3180 | STEP=timeseries(step_response(1:length(shifting_vector)),T(1:length(shifting_vector))); | 3064 | STEP=timeseries(step_response(1:length(shifting_vector)),T(1:length(shifting_vector))); | ||
3181 | %% | 3065 | %% | ||
3182 | % ILest=20.*log10(abs(fd(1:f75)/Vf/M/Over_sample)) - 20.*log10(abs(prr(1:f75))) - 20*log10(abs(squeeze(H_ftr(1:f75)))) ; %removing db function to avoid using sig proc toolbox | 3066 | % ILest=20.*log10(abs(fd(1:f75)/Vf/M/Over_sample)) - 20.*log10(abs(prr(1:f75))) - 20*log10(abs(squeeze(H_ftr(1:f75)))) ; %removing db function to avoid using sig proc toolbox | ||
3183 | % figure | 3067 | % figure | ||
3184 | % plot(f(1:f75),ILest) | 3068 | % plot(f(1:f75),ILest) | ||
3185 |
| 3069 |
| ||
3186 | IL_conv=fd(1:f75)/Vf/M/Over_sample ./ prr(1:f75) ./ H_ftr(1:f75) ; %removing db function to avoid using sig proc toolbox | 3070 | IL_conv=fd(1:f75)/Vf/M/Over_sample ./ prr(1:f75) ./ H_ftr(1:f75) ; %removing db function to avoid using sig proc toolbox | ||
3187 | % set same variables as get_s4p_files | 3071 | % set same variables as get_s4p_files | ||
3188 | IL_fields={'sdd12_raw' 'sdd21_raw' 'sdd12_orig' 'sdd21_orig' 'sdd12' 'sdd21' 'sdd21p' 'sdd21f'}; | 3072 | IL_fields={'sdd12_raw' 'sdd21_raw' 'sdd12_orig' 'sdd21_orig' 'sdd12' 'sdd21' 'sdd21p' 'sdd21f'}; | ||
3189 | Zero_fields={'sdd22_raw' 'sdd11_raw' 'sdc12_raw' 'sdc21_raw' 'sdc22_raw' 'sdc11_raw' ... | 3073 | Zero_fields={'sdd22_raw' 'sdd11_raw' 'sdc12_raw' 'sdc21_raw' 'sdc22_raw' 'sdc11_raw' ... | ||
3190 | 'sdd11_orig' 'sdd22_orig' 'sdd11' 'sdd22' 'sdc12' 'sdc21' 'sdc11' 'sdc22' 'sdc21p'}; | 3074 | 'sdd11_orig' 'sdd22_orig' 'sdd11' 'sdd22' 'sdc12' 'sdc21' 'sdc11' 'sdc22' 'sdc21p'}; | ||
3191 | zero_vector=zeros(length(IL_conv),1); | 3075 | zero_vector=zeros(length(IL_conv),1); | ||
3192 | for j=1:length(IL_fields) | 3076 | for j=1:length(IL_fields) | ||
3193 | chdata(i).(IL_fields{j})=IL_conv; | 3077 | chdata(i).(IL_fields{j})=IL_conv; | ||
3194 | end | 3078 | end | ||
3195 | for j=1:length(Zero_fields) | 3079 | for j=1:length(Zero_fields) | ||
3196 | chdata(i).(Zero_fields{j})=zero_vector; | 3080 | chdata(i).(Zero_fields{j})=zero_vector; | ||
3197 | end | 3081 | end | ||
3198 |
| 3082 |
| ||
3199 | if i==1 | 3083 | if i==1 | ||
3200 | SDDch(:,1,2)=chdata.sdd12_raw; | 3084 | SDDch(:,1,2)=chdata.sdd12_raw; | ||
3201 | SDDch(:,2,1)=chdata.sdd21_raw; | 3085 | SDDch(:,2,1)=chdata.sdd21_raw; | ||
3202 | SDDch(:,1,1)=chdata.sdd11_raw; | 3086 | SDDch(:,1,1)=chdata.sdd11_raw; | ||
3203 | SDDch(:,2,2)=chdata.sdd22_raw; | 3087 | SDDch(:,2,2)=chdata.sdd22_raw; | ||
3204 | SDDp2p= zeros(length(IL_conv),1); | 3088 | SDDp2p= zeros(length(IL_conv),1); | ||
3205 | end | 3089 | end | ||
3206 | chdata(i).TX_RL=[]; | 3090 | chdata(i).TX_RL=[]; | ||
3207 | chdata(i).TDR11=[]; | 3091 | chdata(i).TDR11=[]; | ||
3208 | chdata(i).PDTR11=[]; | 3092 | chdata(i).PDTR11=[]; | ||
3209 | chdata(i).TDR22=[]; | 3093 | chdata(i).TDR22=[]; | ||
3210 | chdata(i).PDTR22=[]; | 3094 | chdata(i).PDTR22=[]; | ||
3211 | end | 3095 | end | ||
3212 | 3096 | ||||
3213 | 3097 | ||||
3214 | function H_tw=Tukey_Window(f,param,fr,fb) | 3098 | function H_tw=Tukey_Window(f,param,fr,fb) | ||
3215 | % RIM 05/26/2022 added optional fr and fb | 3099 | % RIM 05/26/2022 added optional fr and fb | ||
3216 | % fr is the start of the raised cosine window | 3100 | % fr is the start of the raised cosine window | ||
3217 | % fb is the end of the raised cosine window | 3101 | % fb is the end of the raised cosine window | ||
3218 | if ~exist('fr','var') && ~exist('fb','var') | 3102 | if ~exist('fr','var') && ~exist('fb','var') | ||
3219 | fb=param.fb; | 3103 | fb=param.fb; | ||
3220 | fr=param.f_r*param.fb; | 3104 | fr=param.f_r*param.fb; | ||
3221 | end | 3105 | end | ||
3222 | fperiod=2*(fb-fr); | 3106 | fperiod=2*(fb-fr); | ||
3223 | H_tw = [ ones(1,length(f(f<fr))) ... | 3107 | H_tw = [ ones(1,length(f(f<fr))) ... | ||
3224 | 0.5*cos(2*pi*(f( f>=fr & f<=fb) -fb ) /fperiod-pi)+.5 ... | 3108 | 0.5*cos(2*pi*(f( f>=fr & f<=fb) -fb ) /fperiod-pi)+.5 ... | ||
3225 | zeros(1,length(f(f>fb)) )]; | 3109 | zeros(1,length(f(f>fb)) )]; | ||
3226 | H_tw=H_tw(1:length(f)); | 3110 | H_tw=H_tw(1:length(f)); | ||
3227 | if 0 | 3111 | if 0 | ||
3228 | plot(f/1e9,H_tw) | 3112 | plot(f/1e9,H_tw) | ||
3229 | end | 3113 | end | ||
3230 | 3114 | ||||
3231 | 3115 | ||||
3232 | 3116 | ||||
3233 | %% moved output control to functions | 3117 | %% moved output control to functions | ||
3234 | function [H_TxFFE] = Tx_FFE_Filter(varargin) | 3118 | function [H_TxFFE] = Tx_FFE_Filter(varargin) | ||
3235 | % Author: Richard Mellitz | 3119 | % Author: Richard Mellitz | ||
3236 | % Date: 7/29/2022 | 3120 | % Date: 7/29/2022 | ||
3237 | % generate FD tx ffe system function | 3121 | % generate FD tx ffe system function | ||
3238 | % varagins... | 3122 | % varagins... | ||
3239 | % param - stucture | 3123 | % param - stucture | ||
3240 | % param.fb baud rate | 3124 | % param.fb baud rate | ||
3241 | % param.Tx_FFE Tx FFE coef | 3125 | % param.Tx_FFE Tx FFE coef | ||
3242 | % f - freq array | 3126 | % f - freq array | ||
3243 | % Use_Tx_FFE = flag to use or not | 3127 | % Use_Tx_FFE = flag to use or not | ||
3244 | % H_TxFFE is system function for Tx_FFE | 3128 | % H_TxFFE is system function for Tx_FFE | ||
3245 | db = @(x) 20*log10(abs(x)); | 3129 | db = @(x) 20*log10(abs(x)); | ||
3246 | [param,varargin]=varargin_extractor(varargin{:}); | 3130 | [param,varargin]=varargin_extractor(varargin{:}); | ||
3247 | [f,varargin]=varargin_extractor(varargin{:}); | 3131 | [f,varargin]=varargin_extractor(varargin{:}); | ||
3248 | [Use_Tx_FFE,varargin]=varargin_extractor(varargin{:}); | 3132 | [Use_Tx_FFE,varargin]=varargin_extractor(varargin{:}); | ||
3249 | if isempty(Use_Tx_FFE) | 3133 | if isempty(Use_Tx_FFE) | ||
3250 | Use_Tx_FFE=0; | 3134 | Use_Tx_FFE=0; | ||
3251 | end | 3135 | end | ||
3252 | if isempty(param) | 3136 | if isempty(param) | ||
3253 | param.fb=106.25e9; | 3137 | param.fb=106.25e9; | ||
3254 | Tx_FFE=[1 ]; | 3138 | Tx_FFE=[1 ]; | ||
3255 | else | 3139 | else | ||
3256 | if ~isfield(param, 'Pkg_TXFFE_preset') | 3140 | if ~isfield(param, 'Pkg_TXFFE_preset') | ||
3257 | Tx_FFE=[ 1 ]; | 3141 | Tx_FFE=[ 1 ]; | ||
3258 | else | 3142 | else | ||
3259 | Tx_FFE=param.Pkg_TXFFE_preset; | 3143 | Tx_FFE=param.Pkg_TXFFE_preset; | ||
3260 | end | 3144 | end | ||
3261 | end | 3145 | end | ||
3262 | if isempty(f) | 3146 | if isempty(f) | ||
3263 | f=0:10e6:param.fb; | 3147 | f=0:10e6:param.fb; | ||
3264 | end | 3148 | end | ||
3265 | 3149 | ||||
3266 | 3150 | ||||
3267 | if Use_Tx_FFE ~=0 | 3151 | if Use_Tx_FFE ~=0 | ||
3268 | [mcur,icur] = max(Tx_FFE); | 3152 | [mcur,icur] = max(Tx_FFE); | ||
3269 | H_TxFFE=zeros(1,length(f)); | 3153 | H_TxFFE=zeros(1,length(f)); | ||
3270 | for ii=1:length(Tx_FFE) | 3154 | for ii=1:length(Tx_FFE) | ||
3271 | H_TxFFE = Tx_FFE(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb)+H_TxFFE; | 3155 | H_TxFFE = Tx_FFE(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb)+H_TxFFE; | ||
3272 | end | 3156 | end | ||
3273 | else | 3157 | else | ||
3274 | H_TxFFE=ones(1,length(f)); | 3158 | H_TxFFE=ones(1,length(f)); | ||
3275 | end | 3159 | end | ||
3276 | % figure (1102320) | 3160 | % figure (1102320) | ||
3277 | % plot(f/1e9,db(H_TxFFE)) | 3161 | % plot(f/1e9,db(H_TxFFE)) | ||
3278 | % hold on | 3162 | % hold on | ||
3279 | function C= WIENER_HOPF_MMSE(vsampled ,param, OP , chdata, txffe, Noise_XC,ivs) | 3163 | function C= WIENER_HOPF_MMSE(vsampled ,param, OP , chdata, txffe, Noise_XC,ivs) | ||
3280 | cmx=param.RxFFE_cmx; | 3164 | cmx=param.RxFFE_cmx; | ||
3281 | cpx=param.RxFFE_cpx; | 3165 | cpx=param.RxFFE_cpx; | ||
3282 | % do this early on so we can reuse the old code | 3166 | % do this early on so we can reuse the old code | ||
3283 | % to be replaced with MMSE function from healey... | 3167 | % to be replaced with MMSE function from healey... | ||
3284 | if param.N_bg ~=0 % must be floating taps | 3168 | if param.N_bg ~=0 % must be floating taps | ||
3285 | cpx=param.N_bmax; % N_f in spreadsheet | 3169 | cpx=param.N_bmax; % N_f in spreadsheet | ||
3286 | end | 3170 | end | ||
3287 | num_taps=cmx+cpx+1; | 3171 | num_taps=cmx+cpx+1; | ||
3288 | ndfe=param.ndfe; | 3172 | ndfe=param.ndfe; | ||
3289 | spui=param.samples_per_ui; | 3173 | spui=param.samples_per_ui; | ||
3290 | %% Start of WIENER-HOPF MMSE EQ code | 3174 | %% Start of WIENER-HOPF MMSE EQ code | ||
3291 | R_n = zeros(num_taps,num_taps); | 3175 | R_n = zeros(num_taps,num_taps); | ||
3292 | R_xt = zeros(num_taps,num_taps); | 3176 | R_xt = zeros(num_taps,num_taps); | ||
3293 | 3177 | ||||
3294 | if OP.Do_Colored_Noise | 3178 | if OP.Do_Colored_Noise | ||
3295 | % Form Noise Autocorrelation matrix | 3179 | % Form Noise Autocorrelation matrix | ||
3296 | Noise_XC = reshape (Noise_XC,1,[]); | 3180 | Noise_XC = reshape (Noise_XC,1,[]); | ||
3297 | len = length(Noise_XC); | 3181 | len = length(Noise_XC); | ||
3298 | if len < num_taps, Noise_XC = [Noise_XC,zeros(1,num_taps-len)]; end | 3182 | if len < num_taps, Noise_XC = [Noise_XC,zeros(1,num_taps-len)]; end | ||
3299 | Noise_XC = Noise_XC(1:num_taps); | 3183 | Noise_XC = Noise_XC(1:num_taps); | ||
3300 | R_n = toeplitz (Noise_XC,Noise_XC); | 3184 | R_n = toeplitz (Noise_XC,Noise_XC); | ||
3301 | end | 3185 | end | ||
3302 | %% Calculate Cross Talk Correlation matrix at T intervals. | 3186 | %% Calculate Cross Talk Correlation matrix at T intervals. | ||
3303 | if OP.Do_XT_Noise | 3187 | if OP.Do_XT_Noise | ||
3304 | % Calculate variance of Tx signal based on +/-1 outer limits | 3188 | % Calculate variance of Tx signal based on +/-1 outer limits | ||
3305 | Tx_sigma = sqrt( (param.levels^2-1)/(3*(param.levels-1)^2) ); | 3189 | Tx_sigma = sqrt( (param.levels^2-1)/(3*(param.levels-1)^2) ); | ||
3306 | for jj = 2:length(chdata) | 3190 | for jj = 2:length(chdata) | ||
3307 | if isequal(chdata(jj).type, 'FEXT') || isequal(chdata(jj).type, 'NEXT') | 3191 | if isequal(chdata(jj).type, 'FEXT') || isequal(chdata(jj).type, 'NEXT') | ||
3308 | if isequal(chdata(jj).type, 'FEXT') | 3192 | if isequal(chdata(jj).type, 'FEXT') | ||
3309 | % len = length(chdata(jj).ctle_imp_response); | 3193 | % len = length(chdata(jj).ctle_imp_response); | ||
3310 | % ch_imp = ifft( fft(reshape(chdata(jj).ctle_imp_response,1,[])) .* fft(reshape(upsample(txffe, param.samples_per_ui),1,[]),len) ); | 3194 | % ch_imp = ifft( fft(reshape(chdata(jj).ctle_imp_response,1,[])) .* fft(reshape(upsample(txffe, param.samples_per_ui),1,[]),len) ); | ||
3311 | ch_imp= FFE( txffe , cmx,param.samples_per_ui, chdata(jj).ctle_imp_response).'; | 3195 | ch_imp= FFE( txffe , cmx,param.samples_per_ui, chdata(jj).ctle_imp_response).'; | ||
3312 | ch_imp = filter(ones(param.samples_per_ui, 1), 1, ch_imp); | 3196 | ch_imp = filter(ones(param.samples_per_ui, 1), 1, ch_imp); | ||
3313 | elseif isequal(chdata(jj).type, 'NEXT') | 3197 | elseif isequal(chdata(jj).type, 'NEXT') | ||
3314 | ch_imp = chdata(jj).ctle_imp_response; | 3198 | ch_imp = chdata(jj).ctle_imp_response; | ||
3315 | ch_imp = filter(ones(param.samples_per_ui, 1), 1, ch_imp); | 3199 | ch_imp = filter(ones(param.samples_per_ui, 1), 1, ch_imp); | ||
3316 | end | 3200 | end | ||
3317 | norms = zeros(1,spui); | 3201 | norms = zeros(1,spui); | ||
3318 | for ii = 1:spui | 3202 | for ii = 1:spui | ||
3319 | norms(ii) = norm(ch_imp(ii:spui:end)); | 3203 | norms(ii) = norm(ch_imp(ii:spui:end)); | ||
3320 | end | 3204 | end | ||
3321 | % Pick out sampling phase with largest noise contribution | 3205 | % Pick out sampling phase with largest noise contribution | ||
3322 | [~,cursor] = max(norms); | 3206 | [~,cursor] = max(norms); | ||
3323 | sub_sample_ch = ch_imp(cursor:spui:end); | 3207 | sub_sample_ch = ch_imp(cursor:spui:end); | ||
3324 | xc = xcorr(sub_sample_ch,num_taps)* Tx_sigma^2; | 3208 | xc = xcorr(sub_sample_ch,num_taps)* Tx_sigma^2; | ||
3325 | xc = xc(num_taps+1:end); | 3209 | xc = xc(num_taps+1:end); | ||
3326 | xc = xc(1:num_taps); | 3210 | xc = xc(1:num_taps); | ||
3327 | R = toeplitz (xc,xc); | 3211 | R = toeplitz (xc,xc); | ||
3328 | R_xt = R_xt + R; | 3212 | R_xt = R_xt + R; | ||
3329 | end | 3213 | end | ||
3330 | end | 3214 | end | ||
3331 | end | 3215 | end | ||
3332 | %% Noise + Cross Talk contribution to R matrix | 3216 | %% Noise + Cross Talk contribution to R matrix | ||
3333 | R_n_xc = zeros(num_taps+ndfe); | 3217 | R_n_xc = zeros(num_taps+ndfe); | ||
3334 | R_n_xc(1:num_taps,1:num_taps) = R_n + R_xt ; | 3218 | R_n_xc(1:num_taps,1:num_taps) = R_n + R_xt ; | ||
3335 | %% For least means squares, we want to solve | 3219 | %% For least means squares, we want to solve | ||
3336 | % | 3220 | % | ||
3337 | % ro = |Ryy Ryx| * w | 3221 | % ro = |Ryy Ryx| * w | ||
3338 | % |Rxy Rxx| | 3222 | % |Rxy Rxx| | ||
3339 | % see Cioffi chapter 3, 3.7.3 | 3223 | % see Cioffi chapter 3, 3.7.3 | ||
3340 | 3224 | ||||
3341 | himp = vsampled; | 3225 | himp = vsampled; | ||
3342 | RefTap = cmx+1; | 3226 | RefTap = cmx+1; | ||
3343 | Signal_Variance = mean ( [-1, -1/3, 1/3, 1].^2 ); | 3227 | Signal_Variance = mean ( [-1, -1/3, 1/3, 1].^2 ); | ||
3344 | Ryy.r = [1:num_taps]; | 3228 | Ryy.r = [1:num_taps]; | ||
3345 | Ryy.c = [1:num_taps]; | 3229 | Ryy.c = [1:num_taps]; | ||
3346 | Ryx.r = 1:num_taps; | 3230 | Ryx.r = 1:num_taps; | ||
3347 | Ryx.c = num_taps + (1:ndfe); | 3231 | Ryx.c = num_taps + (1:ndfe); | ||
3348 | Rxy.r = num_taps + (1:ndfe); | 3232 | Rxy.r = num_taps + (1:ndfe); | ||
3349 | Rxy.c = 1:num_taps; | 3233 | Rxy.c = 1:num_taps; | ||
3350 | Rxx.r = num_taps+(1:ndfe); | 3234 | Rxx.r = num_taps+(1:ndfe); | ||
3351 | Rxx.c = num_taps+(1:ndfe); | 3235 | Rxx.c = num_taps+(1:ndfe); | ||
3352 | himp = reshape (himp,1,[]); | 3236 | himp = reshape (himp,1,[]); | ||
3353 | %% ro is simply the channel response reversed in time | 3237 | %% ro is simply the channel response reversed in time | ||
3354 | himp_lr = fliplr(himp); % make sure himp has enough pre/post cursors, e.g. numtaps+ndfe | 3238 | himp_lr = fliplr(himp); % make sure himp has enough pre/post cursors, e.g. numtaps+ndfe | ||
3355 | himp_lr = [zeros(1,num_taps+ndfe), himp_lr, zeros(1,num_taps+ndfe)]; | 3239 | himp_lr = [zeros(1,num_taps+ndfe), himp_lr, zeros(1,num_taps+ndfe)]; | ||
3356 | [~,pk] = max(himp_lr); | 3240 | [~,pk] = max(himp_lr); | ||
3357 | r_indx = (1:num_taps) - RefTap; | 3241 | r_indx = (1:num_taps) - RefTap; | ||
3358 | ro = [himp_lr(pk+r_indx), zeros(1,ndfe)].'; | 3242 | ro = [himp_lr(pk+r_indx), zeros(1,ndfe)].'; | ||
3359 | ro = ro*Signal_Variance; | 3243 | ro = ro*Signal_Variance; | ||
3360 | %% Setup up the covariance matrix | 3244 | %% Setup up the covariance matrix | ||
3361 | R = zeros(num_taps+ndfe); | 3245 | R = zeros(num_taps+ndfe); | ||
3362 | % Form Ryy | 3246 | % Form Ryy | ||
3363 | % Note: important to use whole impulse response | 3247 | % Note: important to use whole impulse response | ||
3364 | % not just the part that spans the FFE. | 3248 | % not just the part that spans the FFE. | ||
3365 | [ryy,lags] = xcorr(himp,himp, num_taps-1); | 3249 | [ryy,lags] = xcorr(himp,himp, num_taps-1); | ||
3366 | R(Ryy.r,Ryy.c) = toeplitz (ryy(num_taps:end)); | 3250 | R(Ryy.r,Ryy.c) = toeplitz (ryy(num_taps:end)); | ||
3367 | 3251 | ||||
3368 | % Form Rxx | 3252 | % Form Rxx | ||
3369 | R(Rxx.r,Rxx.c) = diag(ones(1,ndfe)); | 3253 | R(Rxx.r,Rxx.c) = diag(ones(1,ndfe)); | ||
3370 | 3254 | ||||
3371 | % Form Ryx columns | 3255 | % Form Ryx columns | ||
3372 | Ryx_indxs = (1:num_taps)-1; | 3256 | Ryx_indxs = (1:num_taps)-1; | ||
3373 | for jj = 0:ndfe-1 | 3257 | for jj = 0:ndfe-1 | ||
3374 | % R(Ryx.r,Ryx.c(jj+1) ) = himp_lr(pk+1 + Ryx_indxs -jj ).'; | 3258 | % R(Ryx.r,Ryx.c(jj+1) ) = himp_lr(pk+1 + Ryx_indxs -jj ).'; | ||
3375 | R(Ryx.r,Ryx.c(jj+1) ) = himp_lr(pk-cmx-1 + Ryx_indxs -jj ).'; | 3259 | R(Ryx.r,Ryx.c(jj+1) ) = himp_lr(pk-cmx-1 + Ryx_indxs -jj ).'; | ||
3376 | end | 3260 | end | ||
3377 | % Form Rxy rows | 3261 | % Form Rxy rows | ||
3378 | R(Rxy.r,Rxy.c ) = R(Ryx.r,Ryx.c )'; | 3262 | R(Rxy.r,Rxy.c ) = R(Ryx.r,Ryx.c )'; | ||
3379 | 3263 | ||||
3380 | % add in Signal Variance | 3264 | % add in Signal Variance | ||
3381 | R = R*Signal_Variance; | 3265 | R = R*Signal_Variance; | ||
3382 | Rtmp = R; | 3266 | Rtmp = R; | ||
3383 | % Add in Xt and colored noise terms | 3267 | % Add in Xt and colored noise terms | ||
3384 | R = R + R_n_xc; | 3268 | R = R + R_n_xc; | ||
3385 | 3269 | ||||
3386 | % SNR = 25 dB | 3270 | % SNR = 25 dB | ||
3387 | SNR = OP.FFE_SNR; | 3271 | SNR = OP.FFE_SNR; | ||
3388 | Noise_var = max(vsampled)^2*Signal_Variance/10^(SNR/10); | 3272 | Noise_var = max(vsampled)^2*Signal_Variance/10^(SNR/10); | ||
3389 | R_noise = diag(ones(1,num_taps))*Noise_var; | 3273 | R_noise = diag(ones(1,num_taps))*Noise_var; | ||
3390 | if ~OP.Do_Colored_Noise && ~OP.Do_XT_Noise | 3274 | if ~OP.Do_Colored_Noise && ~OP.Do_XT_Noise | ||
3391 | R(Ryy.r,Ryy.c) = R(Ryy.r,Ryy.c) + R_noise; | 3275 | R(Ryy.r,Ryy.c) = R(Ryy.r,Ryy.c) + R_noise; | ||
3392 | end | 3276 | end | ||
3393 | 3277 | ||||
3394 | 3278 | ||||
3395 | %% Solve for equalizer weights | 3279 | %% Solve for equalizer weights | ||
3396 | w = inv(R)*ro; | 3280 | w = inv(R)*ro; | ||
3397 | C = w; | 3281 | C = w; | ||
3398 | %% Deal with 1st post Cursor DFE weight saturation | 3282 | %% Deal with 1st post Cursor DFE weight saturation | ||
3399 | % ro = Rw by moving "saturated" weights over to the LHS | 3283 | % ro = Rw by moving "saturated" weights over to the LHS | ||
3400 | DFE_h1_indx = num_taps+1; | 3284 | DFE_h1_indx = num_taps+1; | ||
3401 | Indx_full = 1:length(C); | 3285 | Indx_full = 1:length(C); | ||
3402 | ws = C; | 3286 | ws = C; | ||
3403 | if ndfe>0 && abs(C(DFE_h1_indx)) > param.bmax(1) | 3287 | if ndfe>0 && abs(C(DFE_h1_indx)) > param.bmax(1) | ||
3404 | rtmp = reshape (ro,[],1); | 3288 | rtmp = reshape (ro,[],1); | ||
3405 | Rtmp = R; | 3289 | Rtmp = R; | ||
3406 | % Move saturated DFE weights over to left hand side of equation | 3290 | % Move saturated DFE weights over to left hand side of equation | ||
3407 | ws = zeros (size(C)); | 3291 | ws = zeros (size(C)); | ||
3408 | ws (DFE_h1_indx) = sign(C(DFE_h1_indx))*param.bmax(1); | 3292 | ws (DFE_h1_indx) = sign(C(DFE_h1_indx))*param.bmax(1); | ||
3409 | rtmp = rtmp - Rtmp*ws; | 3293 | rtmp = rtmp - Rtmp*ws; | ||
3410 | 3294 | ||||
3411 | % and remove the corresponding column from R | 3295 | % and remove the corresponding column from R | ||
3412 | Rtmp(:,DFE_h1_indx) = []; | 3296 | Rtmp(:,DFE_h1_indx) = []; | ||
3413 | Indx_full (DFE_h1_indx) = []; | 3297 | Indx_full (DFE_h1_indx) = []; | ||
3414 | % now Rtmp isn't square so have to use the R'R trick | 3298 | % now Rtmp isn't square so have to use the R'R trick | ||
3415 | % Probably a little dicey "theoretically" because | 3299 | % Probably a little dicey "theoretically" because | ||
3416 | % w = inv(R)*ro is already the mmse solution | 3300 | % w = inv(R)*ro is already the mmse solution | ||
3417 | % now we at doing a R'R operation, but hey | 3301 | % now we at doing a R'R operation, but hey | ||
3418 | % seems to work | 3302 | % seems to work | ||
3419 | % Alternative, since R is now over specified, more rows than | 3303 | % Alternative, since R is now over specified, more rows than | ||
3420 | % columns, one could try removing one of the DFE rows from the | 3304 | % columns, one could try removing one of the DFE rows from the | ||
3421 | % Rxy Rxx portion of the R matrix. | 3305 | % Rxy Rxx portion of the R matrix. | ||
3422 | 3306 | ||||
3423 | w_partial = inv(Rtmp'*Rtmp)*(Rtmp'*rtmp); | 3307 | w_partial = inv(Rtmp'*Rtmp)*(Rtmp'*rtmp); | ||
3424 | ws (Indx_full,:) = w_partial; | 3308 | ws (Indx_full,:) = w_partial; | ||
3425 | C = ws; | 3309 | C = ws; | ||
3426 | end | 3310 | end | ||
3427 | % From Cioffi, Chapter 3 | 3311 | % From Cioffi, Chapter 3 | ||
3428 | var_ffe_dfe = Signal_Variance-ws.'*ro; | 3312 | var_ffe_dfe = Signal_Variance-ws.'*ro; | ||
3429 | SNR_Eq = 10*log10(Signal_Variance/var_ffe_dfe-1); | 3313 | SNR_Eq = 10*log10(Signal_Variance/var_ffe_dfe-1); | ||
3430 | 3314 | ||||
3431 | %% Scale FFE gain to target output voltage | 3315 | %% Scale FFE gain to target output voltage | ||
3432 | Target_ouput = vsampled(ivs)*10^(param.current_ffegain/20); | 3316 | Target_ouput = vsampled(ivs)*10^(param.current_ffegain/20); | ||
3433 | C = C*Target_ouput; | 3317 | C = C*Target_ouput; | ||
3434 | C = C(1:num_taps); | 3318 | C = C(1:num_taps); | ||
3435 | %% End MMSE dfe code | 3319 | %% End MMSE dfe code | ||
3436 | function Write_CSV(output_args,csv_file) | 3320 | function Write_CSV(output_args,csv_file) | ||
3437 | 3321 | ||||
3438 | items = fieldnames(output_args); | 3322 | items = fieldnames(output_args); | ||
3439 | item_value_strings = cell(size(items)); | 3323 | item_value_strings = cell(size(items)); | ||
3440 | for field_id=1:length(items) | 3324 | for field_id=1:length(items) | ||
3441 | field_name=items{field_id}; | 3325 | field_name=items{field_id}; | ||
3442 | field_value=output_args.(field_name); | 3326 | field_value=output_args.(field_name); | ||
3443 | if isstruct(output_args.(field_name)) | 3327 | if isstruct(output_args.(field_name)) | ||
3444 | field_value='struct'; | 3328 | field_value='struct'; | ||
3445 | end | 3329 | end | ||
3446 | if ischar(field_value) | 3330 | if ischar(field_value) | ||
3447 | item_value_strings{field_id}=field_value; | 3331 | item_value_strings{field_id}=field_value; | ||
3448 | elseif isempty(field_value) | 3332 | elseif isempty(field_value) | ||
3449 | item_value_strings{field_id}=''; | 3333 | item_value_strings{field_id}=''; | ||
3450 | elseif numel(field_value)==1 | 3334 | elseif numel(field_value)==1 | ||
3451 | item_value_strings{field_id}=num2str(field_value); | 3335 | item_value_strings{field_id}=num2str(field_value); | ||
3452 | else | 3336 | else | ||
3453 | item_value_strings{field_id}=sprintf('"%s"', mat2str(field_value)); | 3337 | item_value_strings{field_id}=sprintf('"%s"', mat2str(field_value)); | ||
3454 | end | 3338 | end | ||
3455 | end | 3339 | end | ||
3456 | 3340 | ||||
3457 | header_string = str2csv(items); | 3341 | header_string = str2csv(items); | ||
3458 | data_string = str2csv(item_value_strings); | 3342 | data_string = str2csv(item_value_strings); | ||
3459 | fid = fopen(csv_file,'w'); | 3343 | fid = fopen(csv_file,'w'); | ||
3460 | fprintf(fid,'%s\n', header_string); | 3344 | fprintf(fid,'%s\n', header_string); | ||
3461 | fprintf(fid,'%s\n', data_string); | 3345 | fprintf(fid,'%s\n', data_string); | ||
3462 | fclose(fid); | 3346 | fclose(fid); | ||
3463 | function [ s11out, s12out, s21out, s22out ] = add_brd(chdata, param, OP) | 3347 | function [ s11out, s12out, s21out, s22out ] = add_brd(chdata, param, OP) | ||
3464 | %% Used in Clause 92 for adding board trace between TP0 and TP2 | 3348 | %% Used in Clause 92 for adding board trace between TP0 and TP2 | ||
3465 | 3349 | ||||
3466 | switch chdata.type | 3350 | switch chdata.type | ||
3467 | case 'THRU' | 3351 | case 'THRU' | ||
3468 | z_bp_tx = param.z_bp_tx; | 3352 | z_bp_tx = param.z_bp_tx; | ||
3469 | z_bp_rx = param.z_bp_rx; | 3353 | z_bp_rx = param.z_bp_rx; | ||
3470 | case 'NEXT' | 3354 | case 'NEXT' | ||
3471 | z_bp_tx = param.z_bp_rx; | 3355 | z_bp_tx = param.z_bp_rx; | ||
3472 | z_bp_rx = param.z_bp_next; | 3356 | z_bp_rx = param.z_bp_next; | ||
3473 | case 'FEXT' | 3357 | case 'FEXT' | ||
3474 | z_bp_tx = param.z_bp_fext; | 3358 | z_bp_tx = param.z_bp_fext; | ||
3475 | z_bp_rx = param.z_bp_rx; | 3359 | z_bp_rx = param.z_bp_rx; | ||
3476 | end | 3360 | end | ||
3477 | % Same cap on each tx and rx three is a data stratue for bifrucation but | 3361 | % Same cap on each tx and rx three is a data stratue for bifrucation but | ||
3478 | % logic no implemented here RIM 06/28/2019 | 3362 | % logic no implemented here RIM 06/28/2019 | ||
3479 | zref=param.Z0; | 3363 | zref=param.Z0; | ||
3480 | c1=param.C_0; | 3364 | c1=param.C_0; | ||
3481 | c2=param.C_1; | 3365 | c2=param.C_1; | ||
3482 | f=chdata.faxis; | 3366 | f=chdata.faxis; | ||
3483 | f(f<eps)=eps; | 3367 | f(f<eps)=eps; | ||
3484 | s11pad1t= -1i*2*pi.*f*c1(1)*zref./(2+1i*2*pi.*f*c1(1)*zref); | 3368 | s11pad1t= -1i*2*pi.*f*c1(1)*zref./(2+1i*2*pi.*f*c1(1)*zref); | ||
3485 | s21pad1t= 2./(2+1i*2*pi.*f*c1(1)*zref); | 3369 | s21pad1t= 2./(2+1i*2*pi.*f*c1(1)*zref); | ||
3486 | s11pad2t= -1i*2*pi.*f*c2(1)*zref./(2+1i*2*pi.*f*c2(1)*zref); | 3370 | s11pad2t= -1i*2*pi.*f*c2(1)*zref./(2+1i*2*pi.*f*c2(1)*zref); | ||
3487 | s21pad2t= 2./(2+1i*2*pi.*f*c2(1)*zref); | 3371 | s21pad2t= 2./(2+1i*2*pi.*f*c2(1)*zref); | ||
3488 | [ s11tx, s12tx, s21tx, s22tx ] = synth_tline(chdata.faxis, param.brd_Z_c(1), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_tx); | 3372 | [ s11tx, s12tx, s21tx, s22tx ] = synth_tline(chdata.faxis, param.brd_Z_c(1), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_tx); | ||
3489 | % add Tx caps | 3373 | % add Tx caps | ||
3490 | [s11tx, s12tx, s21tx, s22tx ]= ... | 3374 | [s11tx, s12tx, s21tx, s22tx ]= ... | ||
3491 | combines4p( s11pad1t, s21pad1t, s21pad1t, s11pad1t, s11tx, s12tx, s21tx, s22tx ); | 3375 | combines4p( s11pad1t, s21pad1t, s21pad1t, s11pad1t, s11tx, s12tx, s21tx, s22tx ); | ||
3492 | [s11tx, s12tx, s21tx, s22tx ]= ... | 3376 | [s11tx, s12tx, s21tx, s22tx ]= ... | ||
3493 | combines4p( s11tx, s12tx, s21tx, s22tx,s11pad2t, s21pad2t, s21pad2t, s11pad2t ); | 3377 | combines4p( s11tx, s12tx, s21tx, s22tx,s11pad2t, s21pad2t, s21pad2t, s11pad2t ); | ||
3494 | 3378 | ||||
3495 | 3379 | ||||
3496 | s11pad1r= -1i*2*pi.*f*c1(2)*zref./(2+1i*2*pi.*f*c1(2)*zref); | 3380 | s11pad1r= -1i*2*pi.*f*c1(2)*zref./(2+1i*2*pi.*f*c1(2)*zref); | ||
3497 | s21pad1r= 2./(2+1i*2*pi.*f*c1(2)*zref); | 3381 | s21pad1r= 2./(2+1i*2*pi.*f*c1(2)*zref); | ||
3498 | s11pad2r= -1i*2*pi.*f*c2(2)*zref./(2+1i*2*pi.*f*c2(2)*zref); | 3382 | s11pad2r= -1i*2*pi.*f*c2(2)*zref./(2+1i*2*pi.*f*c2(2)*zref); | ||
3499 | s21pad2r= 2./(2+1i*2*pi.*f*c2(2)*zref); | 3383 | s21pad2r= 2./(2+1i*2*pi.*f*c2(2)*zref); | ||
3500 | [ s11rx, s12rx, s21rx, s22rx ] = synth_tline(chdata.faxis, param.brd_Z_c(2), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_rx); | 3384 | [ s11rx, s12rx, s21rx, s22rx ] = synth_tline(chdata.faxis, param.brd_Z_c(2), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_rx); | ||
3501 | % add Rx caps | 3385 | % add Rx caps | ||
3502 | [s11rx, s12rx, s21rx, s22rx ]= ... | 3386 | [s11rx, s12rx, s21rx, s22rx ]= ... | ||
3503 | combines4p( s11pad2r, s21pad2r, s21pad2r, s11pad2r, s11rx, s12rx, s21rx, s22rx ); | 3387 | combines4p( s11pad2r, s21pad2r, s21pad2r, s11pad2r, s11rx, s12rx, s21rx, s22rx ); | ||
3504 | [s11rx, s12rx, s21rx, s22rx ]= ... | 3388 | [s11rx, s12rx, s21rx, s22rx ]= ... | ||
3505 | combines4p( s11rx, s12rx, s21rx, s22rx,s11pad1r, s21pad1r, s21pad1r, s11pad1r ); | 3389 | combines4p( s11rx, s12rx, s21rx, s22rx,s11pad1r, s21pad1r, s21pad1r, s11pad1r ); | ||
3506 | 3390 | ||||
3507 | 3391 | ||||
3508 | switch OP.include_pcb | 3392 | switch OP.include_pcb | ||
3509 | case 1 | 3393 | case 1 | ||
3510 | [ s11out1, s12out1, s21out1, s22out1 ]=combines4p( s11tx, s12tx, s21tx, s22tx, chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw ); | 3394 | [ s11out1, s12out1, s21out1, s22out1 ]=combines4p( s11tx, s12tx, s21tx, s22tx, chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw ); | ||
3511 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out1, s12out1, s21out1, s22out1, s11rx, s12rx, s21rx, s22rx); | 3395 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out1, s12out1, s21out1, s22out1, s11rx, s12rx, s21rx, s22rx); | ||
3512 | case 2 | 3396 | case 2 | ||
3513 | [ s11out, s12out, s21out, s22out ]=combines4p( chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw, s11rx, s12rx, s21rx, s22rx); | 3397 | [ s11out, s12out, s21out, s22out ]=combines4p( chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw, s11rx, s12rx, s21rx, s22rx); | ||
3514 | end | 3398 | end | ||
3515 | 3399 | ||||
3516 | function [ s11out, s12out, s21out, s22out ] = add_brdorig(chdata, param, OP) | 3400 | function [ s11out, s12out, s21out, s22out ] = add_brdorig(chdata, param, OP) | ||
3517 | % Used in Clause 92 for adding board trace between TP0 and TP2 | 3401 | % Used in Clause 92 for adding board trace between TP0 and TP2 | ||
3518 | switch chdata.type | 3402 | switch chdata.type | ||
3519 | case 'THRU' | 3403 | case 'THRU' | ||
3520 | z_bp_tx = param.z_bp_tx; | 3404 | z_bp_tx = param.z_bp_tx; | ||
3521 | case 'NEXT' | 3405 | case 'NEXT' | ||
3522 | z_bp_tx = param.z_bp_next; | 3406 | z_bp_tx = param.z_bp_next; | ||
3523 | case 'FEXT' | 3407 | case 'FEXT' | ||
3524 | z_bp_tx = param.z_bp_fext; | 3408 | z_bp_tx = param.z_bp_fext; | ||
3525 | end | 3409 | end | ||
3526 | 3410 | ||||
3527 | [ s11tx, s12tx, s21tx, s22tx ] = synth_tline(chdata.faxis, param.brd_Z_c(1), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_tx); | 3411 | [ s11tx, s12tx, s21tx, s22tx ] = synth_tline(chdata.faxis, param.brd_Z_c(1), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, z_bp_tx); | ||
3528 | [ s11rx, s12rx, s21rx, s22rx ] = synth_tline(chdata.faxis, param.brd_Z_c(2), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, param.z_bp_rx); | 3412 | [ s11rx, s12rx, s21rx, s22rx ] = synth_tline(chdata.faxis, param.brd_Z_c(2), param.Z0, param.brd_gamma0_a1_a2, param.brd_tau, param.z_bp_rx); | ||
3529 | 3413 | ||||
3530 | switch OP.include_pcb | 3414 | switch OP.include_pcb | ||
3531 | case 1 | 3415 | case 1 | ||
3532 | [ s11out1, s12out1, s21out1, s22out1 ]=combines4p( s11tx, s12tx, s21tx, s22tx, chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw ); | 3416 | [ s11out1, s12out1, s21out1, s22out1 ]=combines4p( s11tx, s12tx, s21tx, s22tx, chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw ); | ||
3533 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out1, s12out1, s21out1, s22out1, s11rx, s12rx, s21rx, s22rx); | 3417 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out1, s12out1, s21out1, s22out1, s11rx, s12rx, s21rx, s22rx); | ||
3534 | case 2 | 3418 | case 2 | ||
3535 | [ s11out, s12out, s21out, s22out ]=combines4p( chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw, s11rx, s12rx, s21rx, s22rx); | 3419 | [ s11out, s12out, s21out, s22out ]=combines4p( chdata.sdd11_raw, chdata.sdd12_raw, chdata.sdd21_raw, chdata.sdd22_raw, s11rx, s12rx, s21rx, s22rx); | ||
3536 | end | 3420 | end | ||
3537 | 3421 | ||||
3538 | function [hisi,tap_coef,hisi_ref]=applyDFEbk(hisi,hisi_ref,idx,tap_bk,curval,bmaxg,dfe_delta) | 3422 | function [hisi,tap_coef,hisi_ref]=applyDFEbk(hisi,hisi_ref,idx,tap_bk,curval,bmaxg,dfe_delta) | ||
3539 | % hrem=applyDFEbk(hsis,idx,tap_bk,bmaxg) | 3423 | % hrem=applyDFEbk(hsis,idx,tap_bk,bmaxg) | ||
3540 | % applying a bank of DFE at desired location | 3424 | % applying a bank of DFE at desired location | ||
3541 | % hisi: waveform with cursor values; | 3425 | % hisi: waveform with cursor values; | ||
3542 | % idx: starting index of the bank; | 3426 | % idx: starting index of the bank; | ||
3543 | % tap_bk: number of taps in bank; | 3427 | % tap_bk: number of taps in bank; | ||
3544 | % bmaxg: maxmum coefficient in bank; | 3428 | % bmaxg: maxmum coefficient in bank; | ||
3545 | 3429 | ||||
3546 | if nargin<6 | 3430 | if nargin<6 | ||
3547 | dfe_delta=0; | 3431 | dfe_delta=0; | ||
3548 | end | 3432 | end | ||
3549 | 3433 | ||||
3550 | rng=idx:idx+tap_bk-1; | 3434 | rng=idx:idx+tap_bk-1; | ||
3551 | flt_curval=hisi(rng); | 3435 | flt_curval=hisi(rng); | ||
3552 | 3436 | ||||
3553 | %floor(abs(floatingcursors/sbr(cursor_i))./param.dfe_delta).*param.dfe_delta.*sign(floatingcursors)*sbr(cursor_i); | 3437 | %floor(abs(floatingcursors/sbr(cursor_i))./param.dfe_delta).*param.dfe_delta.*sign(floatingcursors)*sbr(cursor_i); | ||
3554 | 3438 | ||||
3555 | if dfe_delta~=0 | 3439 | if dfe_delta~=0 | ||
3556 | flt_curval_q=floor(abs(flt_curval/curval)./dfe_delta) .* ... | 3440 | flt_curval_q=floor(abs(flt_curval/curval)./dfe_delta) .* ... | ||
3557 | dfe_delta.*sign(flt_curval)*curval; | 3441 | dfe_delta.*sign(flt_curval)*curval; | ||
3558 | else | 3442 | else | ||
3559 | flt_curval_q=hisi(rng); | 3443 | flt_curval_q=hisi(rng); | ||
3560 | end | 3444 | end | ||
3561 | 3445 | ||||
3562 | tap_coef=min(abs(flt_curval_q/curval),bmaxg).*sign(flt_curval_q); | 3446 | tap_coef=min(abs(flt_curval_q/curval),bmaxg).*sign(flt_curval_q); | ||
3563 | hisi(rng)= hisi(rng) - curval*tap_coef; | 3447 | hisi(rng)= hisi(rng) - curval*tap_coef; | ||
3564 | hisi_ref(rng)=0; | 3448 | hisi_ref(rng)=0; | ||
3565 | 3449 | ||||
3566 | %AJG021820 | 3450 | %AJG021820 | ||
3567 | function [ a] = bessel( n ) | 3451 | function [ a] = bessel( n ) | ||
3568 | % bessel polynomial | 3452 | % bessel polynomial | ||
3569 | for ii= 0:n | 3453 | for ii= 0:n | ||
3570 | a(ii+1) = factorial(2*n-ii) / (2^(n-ii)*factorial(ii)*factorial(n-ii)); | 3454 | a(ii+1) = factorial(2*n-ii) / (2^(n-ii)*factorial(ii)*factorial(n-ii)); | ||
3571 | end | 3455 | end | ||
3572 | 3456 | ||||
3573 | 3457 | ||||
3574 | function [delay_sec, delay_idx]= calculate_delay_CausalityEnforcement(freq, sdd21, param, OP) | 3458 | function [delay_sec, delay_idx]= calculate_delay_CausalityEnforcement(freq, sdd21, param, OP) | ||
3575 | % History: | 3459 | % History: | ||
3576 | % 1. 14th October, 2021 (Intial release) | 3460 | % 1. 14th October, 2021 (Intial release) | ||
3577 | 3461 | ||||
3578 | % Definition: | 3462 | % Definition: | ||
3579 | % This function captures the channel delay through the time domain using causality enforcement. | 3463 | % This function captures the channel delay through the time domain using causality enforcement. | ||
3580 | % Following are the steps being followed. | 3464 | % Following are the steps being followed. | ||
3581 | % Step 1. Cascade negative frequencies | 3465 | % Step 1. Cascade negative frequencies | ||
3582 | % Step 2. Extract magnitude | 3466 | % Step 2. Extract magnitude | ||
3583 | % Step 3. IFFT of the magnitude | 3467 | % Step 3. IFFT of the magnitude | ||
3584 | % Step 4. Multiply by the sign(t) | 3468 | % Step 4. Multiply by the sign(t) | ||
3585 | % Step 5. Calculate the phase of the 1j*causal_phase | 3469 | % Step 5. Calculate the phase of the 1j*causal_phase | ||
3586 | % Step 6. casual_function= |original|*exp(-1j*causal_phase) | 3470 | % Step 6. casual_function= |original|*exp(-1j*causal_phase) | ||
3587 | % Step 7. f-domain to t-domain pulse response | 3471 | % Step 7. f-domain to t-domain pulse response | ||
3588 | % Step 8. Calculate the delay | 3472 | % Step 8. Calculate the delay | ||
3589 | 3473 | ||||
3590 | % Author: | 3474 | % Author: | ||
3591 | % Hansel Dsilva (dsilvahansel@gmail.com or hanseldsilva@achronix.com) | 3475 | % Hansel Dsilva (dsilvahansel@gmail.com or hanseldsilva@achronix.com) | ||
3592 | 3476 | ||||
3593 | % Reference: | 3477 | % Reference: | ||
3594 | % 1] "IEEE Standard for Electrical Characterization of Printed Circuit Board and Related Interconnects at Frequencies up to 50 GHz," in IEEE Std 370-2020 , vol., no., pp.1-147, 8 Jan. 2021, doi: 10.1109/IEEESTD.2021.9316329. | 3478 | % 1] "IEEE Standard for Electrical Characterization of Printed Circuit Board and Related Interconnects at Frequencies up to 50 GHz," in IEEE Std 370-2020 , vol., no., pp.1-147, 8 Jan. 2021, doi: 10.1109/IEEESTD.2021.9316329. | ||
3595 | 3479 | ||||
3596 | % Input: | 3480 | % Input: | ||
3597 | % freq %frequency in hertz (odd number points) | 3481 | % freq %frequency in hertz (odd number points) | ||
3598 | % sdd21 %insertion loss in complex (odd number points) | 3482 | % sdd21 %insertion loss in complex (odd number points) | ||
3599 | % param %COM native structure passed | 3483 | % param %COM native structure passed | ||
3600 | % OP %COM native structure passed | 3484 | % OP %COM native structure passed | ||
3601 | 3485 | ||||
3602 | % Output: | 3486 | % Output: | ||
3603 | % delay_sec %channel delay in seconds | 3487 | % delay_sec %channel delay in seconds | ||
3604 | % delay_idx %channel delay index | 3488 | % delay_idx %channel delay index | ||
3605 | 3489 | ||||
3606 | if iscolumn(sdd21) | 3490 | if iscolumn(sdd21) | ||
3607 | sdd21= sdd21.'; | 3491 | sdd21= sdd21.'; | ||
3608 | end | 3492 | end | ||
3609 | if iscolumn(freq) | 3493 | if iscolumn(freq) | ||
3610 | freq= freq.'; | 3494 | freq= freq.'; | ||
3611 | end | 3495 | end | ||
3612 | 3496 | ||||
3613 | %---start. Step 1. Cascade negative frequencies | 3497 | %---start. Step 1. Cascade negative frequencies | ||
3614 | % sdd21_conj= zeros(1, length(freq)+ length(freq) - 1); | 3498 | % sdd21_conj= zeros(1, length(freq)+ length(freq) - 1); | ||
3615 | sdd21_conj= [sdd21, conj(sdd21(end:-1:2))];%For some reason this only works | 3499 | sdd21_conj= [sdd21, conj(sdd21(end:-1:2))];%For some reason this only works | ||
3616 | % sdd21_conj = [real(sdd21(1)), sdd21(2:end-1), real(sdd21(end)), flipud(conj(sdd21(2:end-1)))]; | 3500 | % sdd21_conj = [real(sdd21(1)), sdd21(2:end-1), real(sdd21(end)), flipud(conj(sdd21(2:end-1)))]; | ||
3617 | %---end. Step 1. Cascade negative frequencies | 3501 | %---end. Step 1. Cascade negative frequencies | ||
3618 | 3502 | ||||
3619 | %---start. Step 2. Extract magnitude | 3503 | %---start. Step 2. Extract magnitude | ||
3620 | sdd21_mag_conj = real(log(abs(sdd21_conj))); | 3504 | sdd21_mag_conj = real(log(abs(sdd21_conj))); | ||
3621 | %---end. Step 2. Extract magnitude | 3505 | %---end. Step 2. Extract magnitude | ||
3622 | 3506 | ||||
3623 | %---start. Step 3. IFFT of the magnitude | 3507 | %---start. Step 3. IFFT of the magnitude | ||
3624 | sdd21_mag_time = ifft(sdd21_mag_conj); | 3508 | sdd21_mag_time = ifft(sdd21_mag_conj); | ||
3625 | %---end. Step 3. IFFT of the magnitude | 3509 | %---end. Step 3. IFFT of the magnitude | ||
3626 | 3510 | ||||
3627 | %---start. Step 4. Multiply by the sign(t) | 3511 | %---start. Step 4. Multiply by the sign(t) | ||
3628 | sdd21_mag_time(1:length(freq))= +1j*sdd21_mag_time(1:length(freq)); | 3512 | sdd21_mag_time(1:length(freq))= +1j*sdd21_mag_time(1:length(freq)); | ||
3629 | sdd21_mag_time(length(freq)+1:end)= -1j*sdd21_mag_time(length(freq)+1:end); | 3513 | sdd21_mag_time(length(freq)+1:end)= -1j*sdd21_mag_time(length(freq)+1:end); | ||
3630 | %---end. Step 4. Multiply by the sign(t) | 3514 | %---end. Step 4. Multiply by the sign(t) | ||
3631 | 3515 | ||||
3632 | %---start. Step 5. Calculate the phase of the original_signal and the 1j*causal_phase | 3516 | %---start. Step 5. Calculate the phase of the original_signal and the 1j*causal_phase | ||
3633 | sdd21_phase_causality_enforced = real(fft(sdd21_mag_time)); | 3517 | sdd21_phase_causality_enforced = real(fft(sdd21_mag_time)); | ||
3634 | %---end. Step 5. Calculate the phase of the original_signal and the 1j*causal_phase | 3518 | %---end. Step 5. Calculate the phase of the original_signal and the 1j*causal_phase | ||
3635 | 3519 | ||||
3636 | %---start. Step 6. casual_function= |original|*exp(-1j*causal_phase) | 3520 | %---start. Step 6. casual_function= |original|*exp(-1j*causal_phase) | ||
3637 | sdd21_causality_enforced= abs(sdd21_conj).*exp(-1j*sdd21_phase_causality_enforced); | 3521 | sdd21_causality_enforced= abs(sdd21_conj).*exp(-1j*sdd21_phase_causality_enforced); | ||
3638 | sdd21_causality_enforced= sdd21_causality_enforced(1:length(freq)); | 3522 | sdd21_causality_enforced= sdd21_causality_enforced(1:length(freq)); | ||
3639 | %---end. Step 6. casual_function= |original|*exp(-1j*causal_phase) | 3523 | %---end. Step 6. casual_function= |original|*exp(-1j*causal_phase) | ||
3640 | 3524 | ||||
3641 | %---start. Step 7. f-domain to t-domain pulse response | 3525 | %---start. Step 7. f-domain to t-domain pulse response | ||
3642 | %------Note. Do not use s21_to_impulse() for we do not want to truncate | 3526 | %------Note. Do not use s21_to_impulse() for we do not want to truncate | ||
3643 | %--------- Extrapolation has been already done by the COM tool | 3527 | %--------- Extrapolation has been already done by the COM tool | ||
3644 | freq_array= freq; | 3528 | freq_array= freq; | ||
3645 | time_step= param.sample_dt; | 3529 | time_step= param.sample_dt; | ||
3646 | fmax=1/time_step/2; | 3530 | fmax=1/time_step/2; | ||
3647 | freq_step=(freq_array(3)-freq_array(2))/1; | 3531 | freq_step=(freq_array(3)-freq_array(2))/1; | ||
3648 | fout=0:1/round(fmax/freq_step)*fmax:fmax; | 3532 | fout=0:1/round(fmax/freq_step)*fmax:fmax; | ||
3649 | 3533 | ||||
3650 | ILin=sdd21; | 3534 | ILin=sdd21; | ||
3651 | IL=interp_Sparam(ILin,freq_array,fout, ... | 3535 | IL=interp_Sparam(ILin,freq_array,fout, ... | ||
3652 | OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | 3536 | OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | ||
3653 | IL_nan = find(isnan(IL)); | 3537 | IL_nan = find(isnan(IL)); | ||
3654 | for in=IL_nan | 3538 | for in=IL_nan | ||
3655 | IL(in)=IL(in-1); | 3539 | IL(in)=IL(in-1); | ||
3656 | end | 3540 | end | ||
3657 | IL = IL(:); | 3541 | IL = IL(:); | ||
3658 | % add padding for time steps | 3542 | % add padding for time steps | ||
3659 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | 3543 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | ||
3660 | sdd21_PR = filter(ones(1, param.samples_per_ui), 1, real(ifft(IL_symmetric)));%real(ifft(IL_symmetric)); | 3544 | sdd21_PR = filter(ones(1, param.samples_per_ui), 1, real(ifft(IL_symmetric)));%real(ifft(IL_symmetric)); | ||
3661 | clear IL IL_nan IL_symmetric | 3545 | clear IL IL_nan IL_symmetric | ||
3662 | 3546 | ||||
3663 | ILin=sdd21_causality_enforced; | 3547 | ILin=sdd21_causality_enforced; | ||
3664 | IL=interp_Sparam(ILin,freq_array,fout, ... | 3548 | IL=interp_Sparam(ILin,freq_array,fout, ... | ||
3665 | OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | 3549 | OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | ||
3666 | IL_nan = find(isnan(IL)); | 3550 | IL_nan = find(isnan(IL)); | ||
3667 | for in=IL_nan | 3551 | for in=IL_nan | ||
3668 | IL(in)=IL(in-1); | 3552 | IL(in)=IL(in-1); | ||
3669 | end | 3553 | end | ||
3670 | IL = IL(:); | 3554 | IL = IL(:); | ||
3671 | % add padding for time steps | 3555 | % add padding for time steps | ||
3672 | % IL_symmetric = [IL(1:end-1); 0; flipud(conj(IL(2:end-1)))]; | 3556 | % IL_symmetric = [IL(1:end-1); 0; flipud(conj(IL(2:end-1)))]; | ||
3673 | % IL_symmetric = [IL(1:end); flipud(conj(IL(2:end-1)))]; | 3557 | % IL_symmetric = [IL(1:end); flipud(conj(IL(2:end-1)))]; | ||
3674 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | 3558 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | ||
3675 | sdd21_causality_enforced_PR = filter(ones(1, param.samples_per_ui), 1, real(ifft(IL_symmetric)));%real(ifft(IL_symmetric)); | 3559 | sdd21_causality_enforced_PR = filter(ones(1, param.samples_per_ui), 1, real(ifft(IL_symmetric)));%real(ifft(IL_symmetric)); | ||
3676 | clear IL IL_nan IL_symmetric | 3560 | clear IL IL_nan IL_symmetric | ||
3677 | 3561 | ||||
3678 | clear time_step fmax freq_step freq_array | 3562 | clear time_step fmax freq_step freq_array | ||
3679 | 3563 | ||||
3680 | freq_step=(fout(3)-fout(2))/1; | 3564 | freq_step=(fout(3)-fout(2))/1; | ||
3681 | L= length(sdd21_PR); | 3565 | L= length(sdd21_PR); | ||
3682 | t_base = (0:L-1)/(freq_step*L); | 3566 | t_base = (0:L-1)/(freq_step*L); | ||
3683 | clear fout freq_step L | 3567 | clear fout freq_step L | ||
3684 | %---end. Step 7. f-domain to t-domain pulse response | 3568 | %---end. Step 7. f-domain to t-domain pulse response | ||
3685 | 3569 | ||||
3686 | %---start. Step 8. Calculate the delay | 3570 | %---start. Step 8. Calculate the delay | ||
3687 | %------start. Remove the last 5% of the waveform for noise due to IFFT | 3571 | %------start. Remove the last 5% of the waveform for noise due to IFFT | ||
3688 | sdd21_causality_enforced_PR_reduced= sdd21_PR(1:floor(end*95/100)); | 3572 | sdd21_causality_enforced_PR_reduced= sdd21_PR(1:floor(end*95/100)); | ||
3689 | sdd21_PR_reduced= sdd21_causality_enforced_PR(1:floor(end*95/100)); | 3573 | sdd21_PR_reduced= sdd21_causality_enforced_PR(1:floor(end*95/100)); | ||
3690 | %------end. Remove the last 5% of the waveform for noise due to IFFT | 3574 | %------end. Remove the last 5% of the waveform for noise due to IFFT | ||
3691 | 3575 | ||||
3692 | %---start. calculate the difference in index between the peaks | 3576 | %---start. calculate the difference in index between the peaks | ||
3693 | [~, peak_x_idx] = max(sdd21_causality_enforced_PR_reduced); | 3577 | [~, peak_x_idx] = max(sdd21_causality_enforced_PR_reduced); | ||
3694 | [~, peak_y_idx] = max(sdd21_PR_reduced); | 3578 | [~, peak_y_idx] = max(sdd21_PR_reduced); | ||
3695 | peak_idx_difference = peak_x_idx - peak_y_idx; | 3579 | peak_idx_difference = peak_x_idx - peak_y_idx; | ||
3696 | %---end. calculate the difference in index between the peaks | 3580 | %---end. calculate the difference in index between the peaks | ||
3697 | 3581 | ||||
3698 | if peak_idx_difference~=0 | 3582 | if peak_idx_difference~=0 | ||
3699 | search_bounds = min(peak_x_idx, peak_y_idx);%<----one may fix it to 1e3; using minimum of the peaks in assuming the other signal has zero delay | 3583 | search_bounds = min(peak_x_idx, peak_y_idx);%<----one may fix it to 1e3; using minimum of the peaks in assuming the other signal has zero delay | ||
3700 | error_value = length(sdd21_causality_enforced_PR_reduced); | 3584 | error_value = length(sdd21_causality_enforced_PR_reduced); | ||
3701 | error_idx = 0; | 3585 | error_idx = 0; | ||
3702 | % i= 1; | 3586 | % i= 1; | ||
3703 | for shift_value= peak_idx_difference-search_bounds:peak_idx_difference+search_bounds | 3587 | for shift_value= peak_idx_difference-search_bounds:peak_idx_difference+search_bounds | ||
3704 | sdd21_PR_reduced_shifted = circshift(sdd21_PR_reduced,shift_value); | 3588 | sdd21_PR_reduced_shifted = circshift(sdd21_PR_reduced,shift_value); | ||
3705 | current_error = norm(sdd21_PR_reduced_shifted-sdd21_PR_reduced); | 3589 | current_error = norm(sdd21_PR_reduced_shifted-sdd21_PR_reduced); | ||
3706 | if (error_value > current_error) | 3590 | if (error_value > current_error) | ||
3707 | error_idx = shift_value; | 3591 | error_idx = shift_value; | ||
3708 | error_value = current_error; | 3592 | error_value = current_error; | ||
3709 | end | 3593 | end | ||
3710 | % error_idx_H(i)= error_idx; | 3594 | % error_idx_H(i)= error_idx; | ||
3711 | % i= i+ 1; | 3595 | % i= i+ 1; | ||
3712 | end | 3596 | end | ||
3713 | %plot(error_idx_H); | 3597 | %plot(error_idx_H); | ||
3714 |
| 3598 |
| ||
3715 | if error_idx==0 | 3599 | if error_idx==0 | ||
3716 | error('An odd case has occured when calcualting the channel delay. Please contact the tool developer.'); | 3600 | error('An odd case has occured when calcualting the channel delay. Please contact the tool developer.'); | ||
3717 | end | 3601 | end | ||
3718 |
| 3602 |
| ||
3719 | delay_idx = error_idx; | 3603 | delay_idx = error_idx; | ||
3720 | else | 3604 | else | ||
3721 | delay_idx= 1; | 3605 | delay_idx= 1; | ||
3722 | end | 3606 | end | ||
3723 | 3607 | ||||
3724 | delay_sec= t_base(abs(delay_idx)); | 3608 | delay_sec= t_base(abs(delay_idx)); | ||
3725 | 3609 | ||||
3726 | 3610 | ||||
3727 | function [return_struct]= capture_RIL_RILN(chdata) | 3611 | function [return_struct]= capture_RIL_RILN(chdata) | ||
3728 | % History: | 3612 | % History: | ||
3729 | % 1. 12th April, 2019 (Intial release) | 3613 | % 1. 12th April, 2019 (Intial release) | ||
3730 | % | 3614 | % | ||
3731 | % 2. 11th October, 2021 | 3615 | % 2. 11th October, 2021 | ||
3732 | % - Details: | 3616 | % - Details: | ||
3733 | % 1] Revised the equation of RIL for missing conj(rho_port1) and conj(rho_port2). | 3617 | % 1] Revised the equation of RIL for missing conj(rho_port1) and conj(rho_port2). | ||
3734 | % 2] Revised the selection criteria for the solution of the quadratic | 3618 | % 2] Revised the selection criteria for the solution of the quadratic | ||
3735 | % equation in finding the reflection coefficient (rho). | 3619 | % equation in finding the reflection coefficient (rho). | ||
3736 | % - Impact: | 3620 | % - Impact: | ||
3737 | % => Zero impact in |RIL|, while impact on angle(RIL). | 3621 | % => Zero impact in |RIL|, while impact on angle(RIL). | ||
3738 | % - Previous: | 3622 | % - Previous: | ||
3739 | % %---start. For passive networks the reflection coefficient should be less than one | 3623 | % %---start. For passive networks the reflection coefficient should be less than one | ||
3740 | % if all(abs(solution_1(idx_start:end))< 1) && ~all(abs(solution_2(idx_start:end))< 1) | 3624 | % if all(abs(solution_1(idx_start:end))< 1) && ~all(abs(solution_2(idx_start:end))< 1) | ||
3741 | % rho_port2= solution_1; | 3625 | % rho_port2= solution_1; | ||
3742 | % elseif all(abs(solution_2(idx_start:end))< 1) && ~all(abs(solution_1(idx_start:end))< 1) | 3626 | % elseif all(abs(solution_2(idx_start:end))< 1) && ~all(abs(solution_1(idx_start:end))< 1) | ||
3743 | % rho_port2= solution_2; | 3627 | % rho_port2= solution_2; | ||
3744 | % else | 3628 | % else | ||
3745 | % rho_port2= solution_1; | 3629 | % rho_port2= solution_1; | ||
3746 | % % error('Please contact the tool developer. It appears a odd case has appeared.'); | 3630 | % % error('Please contact the tool developer. It appears a odd case has appeared.'); | ||
3747 | % end | 3631 | % end | ||
3748 | % %---end. For passive networks the reflection coefficient should be less than one | 3632 | % %---end. For passive networks the reflection coefficient should be less than one | ||
3749 | % | 3633 | % | ||
3750 | % RIL= conj((1- rho_port1).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- rho_port2).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | 3634 | % RIL= conj((1- rho_port1).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- rho_port2).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | ||
3751 | % - Change: | 3635 | % - Change: | ||
3752 | % %---start. Given the real part of the impedance is to be positive | 3636 | % %---start. Given the real part of the impedance is to be positive | ||
3753 | % Z_solution_1= (solution_1*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_1); | 3637 | % Z_solution_1= (solution_1*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_1); | ||
3754 | % Z_solution_2= (solution_2*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_2); | 3638 | % Z_solution_2= (solution_2*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_2); | ||
3755 | % | 3639 | % | ||
3756 | % rho_port2= zeros(length(solution_1), 1); | 3640 | % rho_port2= zeros(length(solution_1), 1); | ||
3757 | % for solution_idx= 1:length(solution_1) | 3641 | % for solution_idx= 1:length(solution_1) | ||
3758 | % if real(Z_solution_1(solution_idx))>0 && real(Z_solution_2(solution_idx))<=0 | 3642 | % if real(Z_solution_1(solution_idx))>0 && real(Z_solution_2(solution_idx))<=0 | ||
3759 | % rho_port2(solution_idx, 1)= solution_1(solution_idx); | 3643 | % rho_port2(solution_idx, 1)= solution_1(solution_idx); | ||
3760 | % elseif real(Z_solution_2(solution_idx))>0 && real(Z_solution_1(solution_idx))<=0 | 3644 | % elseif real(Z_solution_2(solution_idx))>0 && real(Z_solution_1(solution_idx))<=0 | ||
3761 | % rho_port2(solution_idx, 1)= solution_2(solution_idx); | 3645 | % rho_port2(solution_idx, 1)= solution_2(solution_idx); | ||
3762 | % else | 3646 | % else | ||
3763 | % error('An odd case has occured. Please contact the tool developer.'); | 3647 | % error('An odd case has occured. Please contact the tool developer.'); | ||
3764 | % end | 3648 | % end | ||
3765 | % end | 3649 | % end | ||
3766 | % %---end. Given the real part of the impedance is to be positive | 3650 | % %---end. Given the real part of the impedance is to be positive | ||
3767 | % RIL= conj((1- conj(rho_port1)).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- conj(rho_port2)).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | 3651 | % RIL= conj((1- conj(rho_port1)).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- conj(rho_port2)).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | ||
3768 | 3652 | ||||
3769 | % Definition: | 3653 | % Definition: | ||
3770 | % This function captures the reflectionless insertion loss (RIL) and reflective insertion loss nois (RILN) for any arbitary S-parameter | 3654 | % This function captures the reflectionless insertion loss (RIL) and reflective insertion loss nois (RILN) for any arbitary S-parameter | ||
3771 | 3655 | ||||
3772 | % Author: | 3656 | % Author: | ||
3773 | % Hansel Dsilva (dsilvahansel@gmail.com or hanseldsilva@achronix.com) | 3657 | % Hansel Dsilva (dsilvahansel@gmail.com or hanseldsilva@achronix.com) | ||
3774 | % Acknowledgement: Adam Gregory, Richard Mellitz, Beomtaek Lee and Amit Kumar. | 3658 | % Acknowledgement: Adam Gregory, Richard Mellitz, Beomtaek Lee and Amit Kumar. | ||
3775 | 3659 | ||||
3776 | % This function has been shared by Hansel for others to evaluate for reflectionless insertion loss (RIL) and reflective insertion loss nois (RILN) for any arbitary S-parameter. | 3660 | % This function has been shared by Hansel for others to evaluate for reflectionless insertion loss (RIL) and reflective insertion loss nois (RILN) for any arbitary S-parameter. | ||
3777 | 3661 | ||||
3778 | % Reference: | 3662 | % Reference: | ||
3779 | % 1] H. Dsilva et al., "Finding Reflective Insertion Loss Noise and Reflectionless Insertion Loss," 2020 DesignCon. | 3663 | % 1] H. Dsilva et al., "Finding Reflective Insertion Loss Noise and Reflectionless Insertion Loss," 2020 DesignCon. | ||
3780 | % 2] H. Dsilva, A. Jain, J. Sasikala and A. Kumar, "Novel Signal Integrity Application of Power Wave Scattering Matrix theory," 2019 IEEE MTT-S International Microwave and RF Conference (IMARC), 2019, pp. 1-7, doi: 10.1109/IMaRC45935.2019.9118701. | 3664 | % 2] H. Dsilva, A. Jain, J. Sasikala and A. Kumar, "Novel Signal Integrity Application of Power Wave Scattering Matrix theory," 2019 IEEE MTT-S International Microwave and RF Conference (IMARC), 2019, pp. 1-7, doi: 10.1109/IMaRC45935.2019.9118701. | ||
3781 | 3665 | ||||
3782 | % Input: | 3666 | % Input: | ||
3783 | % 1] SCH: S-matrix structure | 3667 | % 1] SCH: S-matrix structure | ||
3784 | % SCH.Frequencies= faxis; | 3668 | % SCH.Frequencies= faxis; | ||
3785 | % SCH.Parameters(1,1,:)= sdd11; | 3669 | % SCH.Parameters(1,1,:)= sdd11; | ||
3786 | % SCH.Parameters(2,2,:)= sdd22; | 3670 | % SCH.Parameters(2,2,:)= sdd22; | ||
3787 | % SCH.Parameters(1,2,:)= sdd12; | 3671 | % SCH.Parameters(1,2,:)= sdd12; | ||
3788 | % SCH.Parameters(2,1,:)= sdd21; | 3672 | % SCH.Parameters(2,1,:)= sdd21; | ||
3789 | % SCH.NumPorts= 2; | 3673 | % SCH.NumPorts= 2; | ||
3790 | % SCH.Impedance= 100; | 3674 | % SCH.Impedance= 100; | ||
3791 | 3675 | ||||
3792 | % Output: Struct returned has the following, | 3676 | % Output: Struct returned has the following, | ||
3793 | % return_struct.RIL %Reflectionless Insertion Loss as a complex number | 3677 | % return_struct.RIL %Reflectionless Insertion Loss as a complex number | ||
3794 | % return_struct.RIL_dB %Reflectionless Insertion Loss in decibel | 3678 | % return_struct.RIL_dB %Reflectionless Insertion Loss in decibel | ||
3795 | % return_struct.RILN %Reflective Insertion Loss Noise as a complex number | 3679 | % return_struct.RILN %Reflective Insertion Loss Noise as a complex number | ||
3796 | % return_struct.RILN_dB %Reflective Insertion Loss Noise in decibel | 3680 | % return_struct.RILN_dB %Reflective Insertion Loss Noise in decibel | ||
3797 | % return_struct.Z_port1 %Frequency dependent, complex values of impedance for termination of port 1 | 3681 | % return_struct.Z_port1 %Frequency dependent, complex values of impedance for termination of port 1 | ||
3798 | % return_struct.Z_port2 %Frequency dependent, complex values of impedance for termination of port 2 | 3682 | % return_struct.Z_port2 %Frequency dependent, complex values of impedance for termination of port 2 | ||
3799 | % return_struct.rho_port1 %Frequency dependent, complex values of the reflection coefficient of port 1 | 3683 | % return_struct.rho_port1 %Frequency dependent, complex values of the reflection coefficient of port 1 | ||
3800 | % return_struct.rho_port2 %Frequency dependent, complex values of reflection coefficient of port 2 | 3684 | % return_struct.rho_port2 %Frequency dependent, complex values of reflection coefficient of port 2 | ||
3801 | % return_struct.freq %Frequency axis | 3685 | % return_struct.freq %Frequency axis | ||
3802 | 3686 | ||||
3803 | SCH.Parameters(1,1,:)=chdata(1).sdd11_orig; | 3687 | SCH.Parameters(1,1,:)=chdata(1).sdd11_orig; | ||
3804 | SCH.Parameters(2,2,:)=chdata(1).sdd22_orig; | 3688 | SCH.Parameters(2,2,:)=chdata(1).sdd22_orig; | ||
3805 | SCH.Parameters(1,2,:)=chdata(1).sdd12_orig; | 3689 | SCH.Parameters(1,2,:)=chdata(1).sdd12_orig; | ||
3806 | SCH.Parameters(2,1,:)=chdata(1).sdd21_orig; | 3690 | SCH.Parameters(2,1,:)=chdata(1).sdd21_orig; | ||
3807 | SCH.Frequencies=chdata(1).faxis; | 3691 | SCH.Frequencies=chdata(1).faxis; | ||
3808 | SCH.Impedance=100;%<------------------in a future release, may want to parameterize this based on the read .sNp | 3692 | SCH.Impedance=100;%<------------------in a future release, may want to parameterize this based on the read .sNp | ||
3809 | SCH.NumPorts= 2; | 3693 | SCH.NumPorts= 2; | ||
3810 | 3694 | ||||
3811 | %---start. allowed is only a 2-port network having a transmitter and receiver | 3695 | %---start. allowed is only a 2-port network having a transmitter and receiver | ||
3812 | if size(SCH.Parameters, 1)~=2 | 3696 | if size(SCH.Parameters, 1)~=2 | ||
3813 | fprintf('Size of given S matrix is %d.', size(SCH.Parameters, 3) ); | 3697 | fprintf('Size of given S matrix is %d.', size(SCH.Parameters, 3) ); | ||
3814 | error('Allowed is only a 2-port network having a transmitter and receiver.'); | 3698 | error('Allowed is only a 2-port network having a transmitter and receiver.'); | ||
3815 | end | 3699 | end | ||
3816 | %---end. allowed is only a 2-port network having a transmitter and receiver | 3700 | %---end. allowed is only a 2-port network having a transmitter and receiver | ||
3817 | 3701 | ||||
3818 | %---start. do not include the DC point given sinusoidals at DC are not | 3702 | %---start. do not include the DC point given sinusoidals at DC are not | ||
3819 | %defined | 3703 | %defined | ||
3820 | if SCH.Frequencies(1)==0 | 3704 | if SCH.Frequencies(1)==0 | ||
3821 | idx_start= 2; | 3705 | idx_start= 2; | ||
3822 | else | 3706 | else | ||
3823 | idx_start= 1; | 3707 | idx_start= 1; | ||
3824 | end | 3708 | end | ||
3825 | %---end. do not include the DC point given sinusoidals at DC are not | 3709 | %---end. do not include the DC point given sinusoidals at DC are not | ||
3826 | %defined | 3710 | %defined | ||
3827 | 3711 | ||||
3828 | Sdd11= squeeze(SCH.Parameters(1,1,idx_start:end)); | 3712 | Sdd11= squeeze(SCH.Parameters(1,1,idx_start:end)); | ||
3829 | Sdd12= squeeze(SCH.Parameters(1,2,idx_start:end)); | 3713 | Sdd12= squeeze(SCH.Parameters(1,2,idx_start:end)); | ||
3830 | Sdd21= squeeze(SCH.Parameters(2,1,idx_start:end)); | 3714 | Sdd21= squeeze(SCH.Parameters(2,1,idx_start:end)); | ||
3831 | Sdd22= squeeze(SCH.Parameters(2,2,idx_start:end)); | 3715 | Sdd22= squeeze(SCH.Parameters(2,2,idx_start:end)); | ||
3832 | 3716 | ||||
3833 | a= -Sdd22+ Sdd11.*Sdd22.*conj(Sdd11)- Sdd21.*Sdd12.*conj(Sdd11); | 3717 | a= -Sdd22+ Sdd11.*Sdd22.*conj(Sdd11)- Sdd21.*Sdd12.*conj(Sdd11); | ||
3834 | b= 1+ Sdd22.*conj(Sdd22)+... | 3718 | b= 1+ Sdd22.*conj(Sdd22)+... | ||
3835 | Sdd11.*Sdd22.*conj(Sdd21).*conj(Sdd12)-... | 3719 | Sdd11.*Sdd22.*conj(Sdd21).*conj(Sdd12)-... | ||
3836 | Sdd21.*Sdd12.*conj(Sdd21).*conj(Sdd12)-... | 3720 | Sdd21.*Sdd12.*conj(Sdd21).*conj(Sdd12)-... | ||
3837 | Sdd11.*Sdd22.*conj(Sdd11).*conj(Sdd22)+... | 3721 | Sdd11.*Sdd22.*conj(Sdd11).*conj(Sdd22)+... | ||
3838 | Sdd12.*Sdd21.*conj(Sdd11).*conj(Sdd22)-... | 3722 | Sdd12.*Sdd21.*conj(Sdd11).*conj(Sdd22)-... | ||
3839 | Sdd11.*conj(Sdd11); | 3723 | Sdd11.*conj(Sdd11); | ||
3840 | c= -conj(Sdd22)-... | 3724 | c= -conj(Sdd22)-... | ||
3841 | Sdd11.*conj(Sdd21).*conj(Sdd12)+... | 3725 | Sdd11.*conj(Sdd21).*conj(Sdd12)+... | ||
3842 | Sdd11.*conj(Sdd11).*conj(Sdd22); | 3726 | Sdd11.*conj(Sdd11).*conj(Sdd22); | ||
3843 | 3727 | ||||
3844 | solution_1= (-b+sqrt((b.^2)-(4*a.*c)))./(2*a); | 3728 | solution_1= (-b+sqrt((b.^2)-(4*a.*c)))./(2*a); | ||
3845 | solution_2= (-b-sqrt((b.^2)-(4*a.*c)))./(2*a); | 3729 | solution_2= (-b-sqrt((b.^2)-(4*a.*c)))./(2*a); | ||
3846 | 3730 | ||||
3847 | clear a b c | 3731 | clear a b c | ||
3848 | 3732 | ||||
3849 | %---start. Given the real part of the impedance is to be positive | 3733 | %---start. Given the real part of the impedance is to be positive | ||
3850 | Z_solution_1= (solution_1*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_1); | 3734 | Z_solution_1= (solution_1*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_1); | ||
3851 | Z_solution_2= (solution_2*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_2); | 3735 | Z_solution_2= (solution_2*conj(SCH.Impedance)+ SCH.Impedance)./(1-solution_2); | ||
3852 | 3736 | ||||
3853 | rho_port2= zeros(length(solution_1), 1); | 3737 | rho_port2= zeros(length(solution_1), 1); | ||
3854 | for solution_idx= 1:length(solution_1) | 3738 | for solution_idx= 1:length(solution_1) | ||
3855 | if real(Z_solution_1(solution_idx))>0 && real(Z_solution_2(solution_idx))<=0 | 3739 | if real(Z_solution_1(solution_idx))>0 && real(Z_solution_2(solution_idx))<=0 | ||
3856 | rho_port2(solution_idx, 1)= solution_1(solution_idx); | 3740 | rho_port2(solution_idx, 1)= solution_1(solution_idx); | ||
3857 | elseif real(Z_solution_2(solution_idx))>0 && real(Z_solution_1(solution_idx))<=0 | 3741 | elseif real(Z_solution_2(solution_idx))>0 && real(Z_solution_1(solution_idx))<=0 | ||
3858 | rho_port2(solution_idx, 1)= solution_2(solution_idx); | 3742 | rho_port2(solution_idx, 1)= solution_2(solution_idx); | ||
3859 | else | 3743 | else | ||
3860 | error('An odd case has occured. Please contact the tool developer.'); | 3744 | error('An odd case has occured. Please contact the tool developer.'); | ||
3861 | end | 3745 | end | ||
3862 | end | 3746 | end | ||
3863 | %---end. Given the real part of the impedance is to be positive | 3747 | %---end. Given the real part of the impedance is to be positive | ||
3864 | 3748 | ||||
3865 | rho_port1= conj(Sdd11+ ((rho_port2.*Sdd21.*Sdd12)./(1-(rho_port2.*Sdd22)))); | 3749 | rho_port1= conj(Sdd11+ ((rho_port2.*Sdd21.*Sdd12)./(1-(rho_port2.*Sdd22)))); | ||
3866 | 3750 | ||||
3867 | %---start. calculate the equivalent port impedance | 3751 | %---start. calculate the equivalent port impedance | ||
3868 | Z_port1= (rho_port1*conj(SCH.Impedance)+ SCH.Impedance)./(1-rho_port1); | 3752 | Z_port1= (rho_port1*conj(SCH.Impedance)+ SCH.Impedance)./(1-rho_port1); | ||
3869 | Z_port2= (rho_port2*conj(SCH.Impedance)+ SCH.Impedance)./(1-rho_port2); | 3753 | Z_port2= (rho_port2*conj(SCH.Impedance)+ SCH.Impedance)./(1-rho_port2); | ||
3870 | %---end. calculate the equivalent port impedance | 3754 | %---end. calculate the equivalent port impedance | ||
3871 | 3755 | ||||
3872 | 3756 | ||||
3873 | % %---start. The reflectionless insertion loss is the insertion loss corresponding | 3757 | % %---start. The reflectionless insertion loss is the insertion loss corresponding | ||
3874 | % %to zero reflections. | 3758 | % %to zero reflections. | ||
3875 | RIL= conj((1- conj(rho_port1)).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- conj(rho_port2)).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | 3759 | RIL= conj((1- conj(rho_port1)).*(sqrt(abs(1- rho_port1.*conj(rho_port1)))./abs(1-rho_port1) )).*( Sdd21.*(1- rho_port2.*Sdd22)+ (Sdd22- conj(rho_port2)).*rho_port2.*Sdd21 )./ ( ((1- conj(rho_port2)).*(sqrt(abs(1- rho_port2.*conj(rho_port2)))./abs(1-rho_port2) )) .* ( -rho_port1.*rho_port2.*Sdd21.*Sdd12+ (1- rho_port2.*Sdd22).*(1- rho_port1.*Sdd11) ) ); | ||
3876 | %---end. The reflectionless insertion loss is the insertion loss corresponding | 3760 | %---end. The reflectionless insertion loss is the insertion loss corresponding | ||
3877 | %to zero reflections. | 3761 | %to zero reflections. | ||
3878 | 3762 | ||||
3879 | %---start. Calculate RILN (Reflective Insertion Loss Noise) | 3763 | %---start. Calculate RILN (Reflective Insertion Loss Noise) | ||
3880 | RILN= RIL- Sdd21; | 3764 | RILN= RIL- Sdd21; | ||
3881 | RILN_dB= 20*log10(abs(Sdd21))- 20*log10(abs(RIL)); | 3765 | RILN_dB= 20*log10(abs(Sdd21))- 20*log10(abs(RIL)); | ||
3882 | %---end. Calculate RILN (Reflective Insertion Loss Noise) | 3766 | %---end. Calculate RILN (Reflective Insertion Loss Noise) | ||
3883 | 3767 | ||||
3884 | %---start. preparing returns struct | 3768 | %---start. preparing returns struct | ||
3885 | return_struct.RIL= RIL; %Reflectionless Insertion Loss as a complex number | 3769 | return_struct.RIL= RIL; %Reflectionless Insertion Loss as a complex number | ||
3886 | return_struct.RIL_dB= 20*log10(abs(RIL)); %Reflectionless Insertion Loss in decibel | 3770 | return_struct.RIL_dB= 20*log10(abs(RIL)); %Reflectionless Insertion Loss in decibel | ||
3887 | return_struct.RILN= RILN; %Reflective Insertion Loss Noise as a complex number | 3771 | return_struct.RILN= RILN; %Reflective Insertion Loss Noise as a complex number | ||
3888 | return_struct.RILN_dB= RILN_dB; %Reflective Insertion Loss Noise in decibel | 3772 | return_struct.RILN_dB= RILN_dB; %Reflective Insertion Loss Noise in decibel | ||
3889 | return_struct.Z_port1= Z_port1; %Frequency dependent, complex values of impedance for termination of port 1 | 3773 | return_struct.Z_port1= Z_port1; %Frequency dependent, complex values of impedance for termination of port 1 | ||
3890 | return_struct.Z_port2= Z_port2; %Frequency dependent, complex values of impedance for termination of port 2 | 3774 | return_struct.Z_port2= Z_port2; %Frequency dependent, complex values of impedance for termination of port 2 | ||
3891 | return_struct.rho_port1= rho_port1; %Frequency dependent, complex values of the reflection coefficient of port 1 | 3775 | return_struct.rho_port1= rho_port1; %Frequency dependent, complex values of the reflection coefficient of port 1 | ||
3892 | return_struct.rho_port2= rho_port2; %Frequency dependent, complex values of reflection coefficient of port 2 | 3776 | return_struct.rho_port2= rho_port2; %Frequency dependent, complex values of reflection coefficient of port 2 | ||
3893 | return_struct.freq= SCH.Frequencies(idx_start:end); %Frequency axis | 3777 | return_struct.freq= SCH.Frequencies(idx_start:end); %Frequency axis | ||
3894 | %---end. preparing returns struct | 3778 | %---end. preparing returns struct | ||
3895 | function [noise_bottom,noise_top]=cdf_to_ber_contour(cdf,specBER) | 3779 | function [noise_bottom,noise_top]=cdf_to_ber_contour(cdf,specBER) | ||
3896 | 3780 | ||||
3897 | 3781 | ||||
3898 | %For the given BER, find the top & bottom voltage level in the CDF | 3782 | %For the given BER, find the top & bottom voltage level in the CDF | ||
3899 | 3783 | ||||
3900 | %for the top, just find the first index at the spec BER | 3784 | %for the top, just find the first index at the spec BER | ||
3901 | nidx=find(cdf.y>specBER, 1, 'first'); | 3785 | nidx=find(cdf.y>specBER, 1, 'first'); | ||
3902 | noise_bottom = cdf.x(nidx); | 3786 | noise_bottom = cdf.x(nidx); | ||
3903 | %for top, flip the cdf. need to operate on row vector for fliplr: cdf.y(:)' | 3787 | %for top, flip the cdf. need to operate on row vector for fliplr: cdf.y(:)' | ||
3904 | nidx=find(fliplr(cdf.y(:)')>specBER, 1, 'first'); | 3788 | nidx=find(fliplr(cdf.y(:)')>specBER, 1, 'first'); | ||
3905 | %the true index without flipping | 3789 | %the true index without flipping | ||
3906 | nidx=length(cdf.y)-nidx+1; | 3790 | nidx=length(cdf.y)-nidx+1; | ||
3907 | noise_top = cdf.x(nidx); | 3791 | noise_top = cdf.x(nidx); | ||
3908 | function p=comb_fct(p1, p2) | 3792 | function p=comb_fct(p1, p2) | ||
3909 | if p1.BinSize ~= p2.BinSize | 3793 | if p1.BinSize ~= p2.BinSize | ||
3910 | error('bin size must be equal') | 3794 | error('bin size must be equal') | ||
3911 | end | 3795 | end | ||
3912 | 3796 | ||||
3913 | p=p1; | 3797 | p=p1; | ||
3914 | p.BinSize=p1.BinSize; | 3798 | p.BinSize=p1.BinSize; | ||
3915 | %p.Min=p1.Min+p2.Min; | 3799 | %p.Min=p1.Min+p2.Min; | ||
3916 | p.Min=min(p1.Min,p2.Min); | 3800 | p.Min=min(p1.Min,p2.Min); | ||
3917 | difsz=abs(p1.Min-p2.Min); | 3801 | difsz=abs(p1.Min-p2.Min); | ||
3918 | lp1=length(p1.y); | 3802 | lp1=length(p1.y); | ||
3919 | lp2=length(p2.y); | 3803 | lp2=length(p2.y); | ||
3920 | if p1.Min == p.Min | 3804 | if p1.Min == p.Min | ||
3921 | p2.y(difsz+1:lp2+difsz)=p2.y; | 3805 | p2.y(difsz+1:lp2+difsz)=p2.y; | ||
3922 | p2.y(1:difsz)=0; | 3806 | p2.y(1:difsz)=0; | ||
3923 | p2.y(lp2+difsz+1:lp1)=0; | 3807 | p2.y(lp2+difsz+1:lp1)=0; | ||
3924 | elseif p2.Min == p.Min | 3808 | elseif p2.Min == p.Min | ||
3925 | p1.y(difsz+1:lp1+difsz)=p1.y; | 3809 | p1.y(difsz+1:lp1+difsz)=p1.y; | ||
3926 | p1.y(1:difsz)=0; | 3810 | p1.y(1:difsz)=0; | ||
3927 | p1.y(lp1+difsz+1:lp2)=0; | 3811 | p1.y(lp1+difsz+1:lp2)=0; | ||
3928 | end | 3812 | end | ||
3929 | % p.y=conv(p1.y, p2.y); | 3813 | % p.y=conv(p1.y, p2.y); | ||
3930 | p.y=(p1.y+p2.y); | 3814 | p.y=(p1.y+p2.y); | ||
3931 | % p.y=p.y/sum(p.y); | 3815 | % p.y=p.y/sum(p.y); | ||
3932 | % p.x =p.Min*p.BinSize:p.BinSize:-p.Min*p.BinSize; | 3816 | % p.x =p.Min*p.BinSize:p.BinSize:-p.Min*p.BinSize; | ||
3933 | p.x =(p.Min:-p.Min)*p.BinSize; % modified by Yasuo Hidaka, 9/4/2016 | 3817 | p.x =(p.Min:-p.Min)*p.BinSize; % modified by Yasuo Hidaka, 9/4/2016 | ||
3934 | 3818 | ||||
3935 | 3819 | ||||
3936 | function out_pdf=combine_pdf_same_voltage_axis(pdf1,pdf2) | 3820 | function out_pdf=combine_pdf_same_voltage_axis(pdf1,pdf2) | ||
3937 | 3821 | ||||
3938 | if pdf1.BinSize ~= pdf2.BinSize | 3822 | if pdf1.BinSize ~= pdf2.BinSize | ||
3939 | error('bin size must be equal') | 3823 | error('bin size must be equal') | ||
3940 | end | 3824 | end | ||
3941 | 3825 | ||||
3942 | x1=pdf1.x; | 3826 | x1=pdf1.x; | ||
3943 | y1=pdf1.y; | 3827 | y1=pdf1.y; | ||
3944 | x2=pdf2.x; | 3828 | x2=pdf2.x; | ||
3945 | y2=pdf2.y; | 3829 | y2=pdf2.y; | ||
3946 | %find the pdf with a larger min, force it to have the same min, and insert | 3830 | %find the pdf with a larger min, force it to have the same min, and insert | ||
3947 | %probability = 0 | 3831 | %probability = 0 | ||
3948 | min1=pdf1.x(1); | 3832 | min1=pdf1.x(1); | ||
3949 | min2=pdf2.x(1); | 3833 | min2=pdf2.x(1); | ||
3950 | shift_amount=round(abs(min1-min2)/pdf1.BinSize); | 3834 | shift_amount=round(abs(min1-min2)/pdf1.BinSize); | ||
3951 | if min1<min2 | 3835 | if min1<min2 | ||
3952 | x2=[pdf1.x(1:shift_amount) pdf2.x]; | 3836 | x2=[pdf1.x(1:shift_amount) pdf2.x]; | ||
3953 | y2=[zeros(1,shift_amount) pdf2.y]; | 3837 | y2=[zeros(1,shift_amount) pdf2.y]; | ||
3954 | else | 3838 | else | ||
3955 | x1=[pdf2.x(1:shift_amount) pdf1.x]; | 3839 | x1=[pdf2.x(1:shift_amount) pdf1.x]; | ||
3956 | y1=[zeros(1,shift_amount) pdf1.y]; | 3840 | y1=[zeros(1,shift_amount) pdf1.y]; | ||
3957 | end | 3841 | end | ||
3958 | %find the pdf with smaller max, force it to have the same max, and insert | 3842 | %find the pdf with smaller max, force it to have the same max, and insert | ||
3959 | %probability=0 | 3843 | %probability=0 | ||
3960 | L1=length(x1); | 3844 | L1=length(x1); | ||
3961 | L2=length(x2); | 3845 | L2=length(x2); | ||
3962 | Ldiff=abs(L1-L2); | 3846 | Ldiff=abs(L1-L2); | ||
3963 | if L1>L2 | 3847 | if L1>L2 | ||
3964 | out_x=x1; | 3848 | out_x=x1; | ||
3965 | y2=[y2 zeros(1,Ldiff)]; | 3849 | y2=[y2 zeros(1,Ldiff)]; | ||
3966 | else | 3850 | else | ||
3967 | out_x=x2; | 3851 | out_x=x2; | ||
3968 | y1=[y1 zeros(1,Ldiff)]; | 3852 | y1=[y1 zeros(1,Ldiff)]; | ||
3969 | end | 3853 | end | ||
3970 | %now the 2 pdfs have the same voltage axis, add probabilities together | 3854 | %now the 2 pdfs have the same voltage axis, add probabilities together | ||
3971 | %renormalization is not handled here, so the output pdf will not have sum=1 | 3855 | %renormalization is not handled here, so the output pdf will not have sum=1 | ||
3972 | %It is the responsibility of the calling function to handle renormalization | 3856 | %It is the responsibility of the calling function to handle renormalization | ||
3973 | %if needed | 3857 | %if needed | ||
3974 | out_y=y1+y2; | 3858 | out_y=y1+y2; | ||
3975 | out_pdf.x=out_x; | 3859 | out_pdf.x=out_x; | ||
3976 | out_pdf.y=out_y; | 3860 | out_pdf.y=out_y; | ||
3977 | out_pdf.BinSize=pdf1.BinSize; | 3861 | out_pdf.BinSize=pdf1.BinSize; | ||
3978 | function [ s11out, s12out, s21out, s22out ] = combines4p( s11in1, s12in1, s21in1, s22in1, s11in2, s12in2, s21in2, s22in2) | 3862 | function [ s11out, s12out, s21out, s22out ] = combines4p( s11in1, s12in1, s21in1, s22in1, s11in2, s12in2, s21in2, s22in2) | ||
3979 | 3863 | ||||
3980 | %original method: | 3864 | %original method: | ||
3981 | % s1=zeros(2,2,length(s11in1)); s2=s1; t3=s1; | 3865 | % s1=zeros(2,2,length(s11in1)); s2=s1; t3=s1; | ||
3982 | % for i=1:length(s11in1) | 3866 | % for i=1:length(s11in1) | ||
3983 | % s1(:,:,i)=[s11in1(i) s12in1(i); s21in1(i) s22in1(i) ]; | 3867 | % s1(:,:,i)=[s11in1(i) s12in1(i); s21in1(i) s22in1(i) ]; | ||
3984 | % s2(:,:,i)=[s11in2(i) s12in2(i); s21in2(i) s22in2(i) ]; | 3868 | % s2(:,:,i)=[s11in2(i) s12in2(i); s21in2(i) s22in2(i) ]; | ||
3985 | % end | 3869 | % end | ||
3986 | % t1=stot(s1); | 3870 | % t1=stot(s1); | ||
3987 | % t2=stot(s2); | 3871 | % t2=stot(s2); | ||
3988 | % for i=1:length(s11in1) | 3872 | % for i=1:length(s11in1) | ||
3989 | % t3(:,:,i)=t1(:,:,i)*t2(:,:,i); | 3873 | % t3(:,:,i)=t1(:,:,i)*t2(:,:,i); | ||
3990 | % end | 3874 | % end | ||
3991 | % s3=ttos(t3); | 3875 | % s3=ttos(t3); | ||
3992 | % s11out=s3(1,1,:); | 3876 | % s11out=s3(1,1,:); | ||
3993 | % s11out=transpose(s11out(:)); | 3877 | % s11out=transpose(s11out(:)); | ||
3994 | % s12out=s3(1,2,:); | 3878 | % s12out=s3(1,2,:); | ||
3995 | % s12out=transpose(s12out(:)); | 3879 | % s12out=transpose(s12out(:)); | ||
3996 | % s21out=s3(2,1,:); | 3880 | % s21out=s3(2,1,:); | ||
3997 | % s21out=transpose(s21out(:)); | 3881 | % s21out=transpose(s21out(:)); | ||
3998 | % s22out=s3(2,2,:); | 3882 | % s22out=s3(2,2,:); | ||
3999 | % s22out=transpose(s22out(:)); | 3883 | % s22out=transpose(s22out(:)); | ||
4000 | 3884 | ||||
4001 | 3885 | ||||
4002 | %vectorized method: | 3886 | %vectorized method: | ||
4003 | s1(1,1,:)=s11in1; | 3887 | s1(1,1,:)=s11in1; | ||
4004 | s1(1,2,:)=s12in1; | 3888 | s1(1,2,:)=s12in1; | ||
4005 | s1(2,1,:)=s21in1; | 3889 | s1(2,1,:)=s21in1; | ||
4006 | s1(2,2,:)=s22in1; | 3890 | s1(2,2,:)=s22in1; | ||
4007 | s2(1,1,:)=s11in2; | 3891 | s2(1,1,:)=s11in2; | ||
4008 | s2(1,2,:)=s12in2; | 3892 | s2(1,2,:)=s12in2; | ||
4009 | s2(2,1,:)=s21in2; | 3893 | s2(2,1,:)=s21in2; | ||
4010 | s2(2,2,:)=s22in2; | 3894 | s2(2,2,:)=s22in2; | ||
4011 | 3895 | ||||
4012 | 3896 | ||||
4013 | N = (1-s1(2,2,:).*s2(1,1,:)) ; | 3897 | N = (1-s1(2,2,:).*s2(1,1,:)) ; | ||
4014 | s11out = s1(1,1,:)+(s1(1,2,:).*s1(2,1,:).*s2(1,1,:))./N ; | 3898 | s11out = s1(1,1,:)+(s1(1,2,:).*s1(2,1,:).*s2(1,1,:))./N ; | ||
4015 | s12out = s1(1,2,:).*s2(1,2,:)./N ; | 3899 | s12out = s1(1,2,:).*s2(1,2,:)./N ; | ||
4016 | s21out = s2(2,1,:).*s1(2,1,:)./N; | 3900 | s21out = s2(2,1,:).*s1(2,1,:)./N; | ||
4017 | s22out = s2(2,2,:)+(s2(1,2,:).*s2(2,1,:).*s1(2,2,:))./N ; | 3901 | s22out = s2(2,2,:)+(s2(1,2,:).*s2(2,1,:).*s1(2,2,:))./N ; | ||
4018 | 3902 | ||||
4019 | s11out=transpose(squeeze(s11out)); | 3903 | s11out=transpose(squeeze(s11out)); | ||
4020 | s12out=transpose(squeeze(s12out)); | 3904 | s12out=transpose(squeeze(s12out)); | ||
4021 | s21out=transpose(squeeze(s21out)); | 3905 | s21out=transpose(squeeze(s21out)); | ||
4022 | s22out=transpose(squeeze(s22out)); | 3906 | s22out=transpose(squeeze(s22out)); | ||
4023 | function p=conv_fct(p1, p2) | 3907 | function p=conv_fct(p1, p2) | ||
4024 | if p1.BinSize ~= p2.BinSize | 3908 | if p1.BinSize ~= p2.BinSize | ||
4025 | error('bin size must be equal') | 3909 | error('bin size must be equal') | ||
4026 | end | 3910 | end | ||
4027 | 3911 | ||||
4028 | p=p1; | 3912 | p=p1; | ||
4029 | %p.BinSize=p1.BinSize; | 3913 | %p.BinSize=p1.BinSize; | ||
4030 | %p.Min=p1.Min+p2.Min; | 3914 | %p.Min=p1.Min+p2.Min; | ||
4031 | p.Min=round(p1.Min+p2.Min); % modified by Yasuo Hidaka, 9/4/2016 | 3915 | p.Min=round(p1.Min+p2.Min); % modified by Yasuo Hidaka, 9/4/2016 | ||
4032 | p.y=conv2(p1.y, p2.y); | 3916 | p.y=conv2(p1.y, p2.y); | ||
4033 | %p.x =p.Min*p.BinSize:p.BinSize:-p.Min*p.BinSize; | 3917 | %p.x =p.Min*p.BinSize:p.BinSize:-p.Min*p.BinSize; | ||
4034 | %p.x =(p.Min:-p.Min)*p.BinSize; % modified by Yasuo Hidaka, 9/4/2016 | 3918 | %p.x =(p.Min:-p.Min)*p.BinSize; % modified by Yasuo Hidaka, 9/4/2016 | ||
4035 | pMax=p.Min+length(p.y)-1; | 3919 | pMax=p.Min+length(p.y)-1; | ||
4036 | p.x =(p.Min*p.BinSize:p.BinSize:pMax*p.BinSize); | 3920 | p.x =(p.Min*p.BinSize:p.BinSize:pMax*p.BinSize); | ||
4037 | 3921 | ||||
4038 | 3922 | ||||
4039 | 3923 | ||||
4040 | 3924 | ||||
4041 | function p=conv_fct_MeanNotZero(p1, p2) | 3925 | function p=conv_fct_MeanNotZero(p1, p2) | ||
4042 | 3926 | ||||
4043 | if p1.BinSize ~= p2.BinSize | 3927 | if p1.BinSize ~= p2.BinSize | ||
4044 | error('bin size must be equal') | 3928 | error('bin size must be equal') | ||
4045 | end | 3929 | end | ||
4046 | 3930 | ||||
4047 | p=p1; | 3931 | p=p1; | ||
4048 | %p.BinSize=p1.BinSize; | 3932 | %p.BinSize=p1.BinSize; | ||
4049 | %p.Min=p1.Min+p2.Min; | 3933 | %p.Min=p1.Min+p2.Min; | ||
4050 | p.Min=round(p1.Min+p2.Min); % modified by Yasuo Hidaka, 9/4/2016 | 3934 | p.Min=round(p1.Min+p2.Min); % modified by Yasuo Hidaka, 9/4/2016 | ||
4051 | p.y=conv2(p1.y, p2.y); | 3935 | p.y=conv2(p1.y, p2.y); | ||
4052 | 3936 | ||||
4053 | %This is equivalent to (p.Min:p.Min+length(p.y)-1)*p.BinSize | 3937 | %This is equivalent to (p.Min:p.Min+length(p.y)-1)*p.BinSize | ||
4054 | %But it is faster to pre-multiply BinSize instead of multiplying the entire | 3938 | %But it is faster to pre-multiply BinSize instead of multiplying the entire | ||
4055 | %vector by BinSize | 3939 | %vector by BinSize | ||
4056 | pMax=p.Min+length(p.y)-1; | 3940 | pMax=p.Min+length(p.y)-1; | ||
4057 | p.x =(p.Min*p.BinSize:p.BinSize:pMax*p.BinSize); | 3941 | p.x =(p.Min*p.BinSize:p.BinSize:pMax*p.BinSize); | ||
4058 | function [cursor_i,no_zero_crossing,sbr_peak_i,zxi]=cursor_sample_index(sbr,param,OP,peak_search_range) | 3942 | function [cursor_i,no_zero_crossing,sbr_peak_i,zxi]=cursor_sample_index(sbr,param,OP,peak_search_range) | ||
4059 | 3943 | ||||
4060 | %IN: | 3944 | %IN: | ||
4061 | %sbr = pulse response | 3945 | %sbr = pulse response | ||
4062 | %param = COM "param" struct | 3946 | %param = COM "param" struct | ||
4063 | %OP = COM "OP" struct | 3947 | %OP = COM "OP" struct | ||
4064 | %peak_search_range= a limited range to search for the peak (for speed up) | 3948 | %peak_search_range= a limited range to search for the peak (for speed up) | ||
4065 | % it is usually +/- 20 UI | 3949 | % it is usually +/- 20 UI | ||
4066 | % | 3950 | % | ||
4067 | %OUT: | 3951 | %OUT: | ||
4068 | %cursor_i = sampling location | 3952 | %cursor_i = sampling location | ||
4069 | %no_zero_crossing = flag that reveals if sampling is not possible. | 3953 | %no_zero_crossing = flag that reveals if sampling is not possible. | ||
4070 | % When this function is called in optimize_fom, it signals to quit the current case | 3954 | % When this function is called in optimize_fom, it signals to quit the current case | ||
4071 | %sbr_peak_i = index of the pulse peak. Note: tens of thousands of calls to max(sbr) are very | 3955 | %sbr_peak_i = index of the pulse peak. Note: tens of thousands of calls to max(sbr) are very | ||
4072 | % time consuming, so saving the peak in one spot is advantageous | 3956 | % time consuming, so saving the peak in one spot is advantageous | ||
4073 | %zxi = zero crossing index (returned because RXFFE uses it) | 3957 | %zxi = zero crossing index (returned because RXFFE uses it) | ||
4074 | 3958 | ||||
4075 | no_zero_crossing=0; | 3959 | no_zero_crossing=0; | ||
4076 | %need to set cursor_i to empty in case no_zero_crossing flag is set | 3960 | %need to set cursor_i to empty in case no_zero_crossing flag is set | ||
4077 | cursor_i=[]; | 3961 | cursor_i=[]; | ||
4078 | 3962 | ||||
4079 | %get peak of pulse and peak index | 3963 | %get peak of pulse and peak index | ||
4080 | [max_of_sbr, sbr_peak_tmp]=max(sbr(peak_search_range)); | 3964 | [max_of_sbr, sbr_peak_tmp]=max(sbr(peak_search_range)); | ||
4081 | sbr_peak_i=sbr_peak_tmp+peak_search_range(1)-1; | 3965 | sbr_peak_i=sbr_peak_tmp+peak_search_range(1)-1; | ||
4082 | 3966 | ||||
4083 | 3967 | ||||
4084 | % initial guess at cursor location (t_s) - based on approximate zero crossing | 3968 | % initial guess at cursor location (t_s) - based on approximate zero crossing | ||
4085 | %limit search space for speed up | 3969 | %limit search space for speed up | ||
4086 | search_start=sbr_peak_i-4*param.samples_per_ui; | 3970 | search_start=sbr_peak_i-4*param.samples_per_ui; | ||
4087 | if search_start<1 | 3971 | if search_start<1 | ||
4088 | search_start=1; | 3972 | search_start=1; | ||
4089 | end | 3973 | end | ||
4090 | %Find zero crossings | 3974 | %Find zero crossings | ||
4091 | zxi = find(diff(sign(sbr(search_start:sbr_peak_i)-.01*max_of_sbr))>=1)+search_start-1; | 3975 | zxi = find(diff(sign(sbr(search_start:sbr_peak_i)-.01*max_of_sbr))>=1)+search_start-1; | ||
4092 | 3976 | ||||
4093 | %Note: the original implementation of zxi: | 3977 | %Note: the original implementation of zxi: | ||
4094 | % zxi = find(diff(sign(sbr-.01*max(sbr)))>=1); | 3978 | % zxi = find(diff(sign(sbr-.01*max(sbr)))>=1); | ||
4095 | % zxi = zxi(zxi<sbr_peak_i); | 3979 | % zxi = zxi(zxi<sbr_peak_i); | ||
4096 | % zxi = zxi(sbr_peak_i - zxi < 4*param.samples_per_ui); | 3980 | % zxi = zxi(sbr_peak_i - zxi < 4*param.samples_per_ui); | ||
4097 | % The changes to limit search space and remember max(sbr) give 10x speed up | 3981 | % The changes to limit search space and remember max(sbr) give 10x speed up | ||
4098 | % A test case of 25k runs, reduced from 1.2s to 0.1s | 3982 | % A test case of 25k runs, reduced from 1.2s to 0.1s | ||
4099 | 3983 | ||||
4100 | 3984 | ||||
4101 | if isempty(zxi) | 3985 | if isempty(zxi) | ||
4102 | %if no zero crossing, the calling program must respond (since sample point will be empty) | 3986 | %if no zero crossing, the calling program must respond (since sample point will be empty) | ||
4103 | no_zero_crossing=1; | 3987 | no_zero_crossing=1; | ||
4104 | return; | 3988 | return; | ||
4105 | elseif length(zxi)>1 | 3989 | elseif length(zxi)>1 | ||
4106 | %only need the last zero crossing | 3990 | %only need the last zero crossing | ||
4107 | zxi=zxi(end); | 3991 | zxi=zxi(end); | ||
4108 | end | 3992 | end | ||
4109 | if param.ndfe==0 | 3993 | if param.ndfe==0 | ||
4110 | max_dfe1=0; | 3994 | max_dfe1=0; | ||
4111 | else | 3995 | else | ||
4112 | max_dfe1=param.bmax(1); | 3996 | max_dfe1=param.bmax(1); | ||
4113 | end | 3997 | end | ||
4114 | % adjust cursor_i to Solve equation 93A-25 %% | 3998 | % adjust cursor_i to Solve equation 93A-25 %% | ||
4115 | % Muller-Mueller criterion with DFE | 3999 | % Muller-Mueller criterion with DFE | ||
4116 | mm_range = zxi+(0:2*param.samples_per_ui); | 4000 | mm_range = zxi+(0:2*param.samples_per_ui); | ||
4117 | switch OP.CDR | 4001 | switch OP.CDR | ||
4118 | case 'Mod-MM' | 4002 | case 'Mod-MM' | ||
4119 | mm_metric = ... | 4003 | mm_metric = ... | ||
4120 | abs(sbr(mm_range+param.samples_per_ui)-max_dfe1*sbr(mm_range)); | 4004 | abs(sbr(mm_range+param.samples_per_ui)-max_dfe1*sbr(mm_range)); | ||
4121 | otherwise % MM | 4005 | otherwise % MM | ||
4122 | %MM is generally: first precursor = 0 | 4006 | %MM is generally: first precursor = 0 | ||
4123 | %but the actual requirement is for first precursor = first postcursor (after DFE is applied) | 4007 | %but the actual requirement is for first precursor = first postcursor (after DFE is applied) | ||
4124 | %if first postcursor doesn't exceed max_dfe, then this equates to first precursor = 0 | 4008 | %if first postcursor doesn't exceed max_dfe, then this equates to first precursor = 0 | ||
4125 | %in cases where first postcursor exceeds max_dfe, the mismatch is balanced out so that | 4009 | %in cases where first postcursor exceeds max_dfe, the mismatch is balanced out so that | ||
4126 | %first precursor = first postcursor - max_dfe | 4010 | %first precursor = first postcursor - max_dfe | ||
4127 | mm_metric = ... | 4011 | mm_metric = ... | ||
4128 | abs(sbr(mm_range-param.samples_per_ui) - max(sbr(mm_range+param.samples_per_ui)-max_dfe1*sbr(mm_range), 0)); | 4012 | abs(sbr(mm_range-param.samples_per_ui) - max(sbr(mm_range+param.samples_per_ui)-max_dfe1*sbr(mm_range), 0)); | ||
4129 | end | 4013 | end | ||
4130 | [~, mm_cursor_offset] = min(mm_metric); | 4014 | [~, mm_cursor_offset] = min(mm_metric); | ||
4131 | 4015 | ||||
4132 | %cursor_i = the sample location | 4016 | %cursor_i = the sample location | ||
4133 | cursor_i = zxi+mm_cursor_offset-1; | 4017 | cursor_i = zxi+mm_cursor_offset-1; | ||
4134 | function pdf=d_cpdf( binsize, values, probs) | 4018 | function pdf=d_cpdf( binsize, values, probs) | ||
4135 | % p=cpdf(type, ...) | 4019 | % p=cpdf(type, ...) | ||
4136 | % | 4020 | % | ||
4137 | % CPDF is a probability mass function for discrete distributions or an | 4021 | % CPDF is a probability mass function for discrete distributions or an | ||
4138 | % approxmation of a PDF for continuous distributions. | 4022 | % approxmation of a PDF for continuous distributions. | ||
4139 | % | 4023 | % | ||
4140 | % cpdf is internally normalized so that the sum of probabilities is 1 | 4024 | % cpdf is internally normalized so that the sum of probabilities is 1 | ||
4141 | % (regardless of bin size). | 4025 | % (regardless of bin size). | ||
4142 | 4026 | ||||
4143 | % Internal fields: | 4027 | % Internal fields: | ||
4144 | % Min: *bin number* of minimum value. | 4028 | % Min: *bin number* of minimum value. | ||
4145 | % BinSize: size of PDF bins. Bin center is the representative value. | 4029 | % BinSize: size of PDF bins. Bin center is the representative value. | ||
4146 | % Vec: vector of probabilities per bin. | 4030 | % Vec: vector of probabilities per bin. | ||
4147 | 4031 | ||||
4148 | %speed up for initializing empty pdf | 4032 | %speed up for initializing empty pdf | ||
4149 | if all(values==0) | 4033 | if all(values==0) | ||
4150 | pdf.BinSize=binsize; | 4034 | pdf.BinSize=binsize; | ||
4151 | pdf.Min=0; | 4035 | pdf.Min=0; | ||
4152 | pdf.y=1; | 4036 | pdf.y=1; | ||
4153 | pdf.x=0; | 4037 | pdf.x=0; | ||
4154 | return; | 4038 | return; | ||
4155 | end | 4039 | end | ||
4156 | 4040 | ||||
4157 | if ~issorted(values) | 4041 | if ~issorted(values) | ||
4158 | [values,si]=sort(values); | 4042 | [values,si]=sort(values); | ||
4159 | probs=probs(si); | 4043 | probs=probs(si); | ||
4160 | end | 4044 | end | ||
4161 | values=binsize*round(values/binsize); | 4045 | values=binsize*round(values/binsize); | ||
4162 | t=(values(1):binsize:values(end)); | 4046 | t=(values(1):binsize:values(end)); | ||
4163 | pdf.Min=values(1)/binsize; | 4047 | pdf.Min=values(1)/binsize; | ||
4164 | pdf.y=zeros(size(t)); | 4048 | pdf.y=zeros(size(t)); | ||
4165 | for k=1:length(values) | 4049 | for k=1:length(values) | ||
4166 | if k==1 | 4050 | if k==1 | ||
4167 | bin=1; | 4051 | bin=1; | ||
4168 | elseif k==length(values) | 4052 | elseif k==length(values) | ||
4169 | bin=length(t); | 4053 | bin=length(t); | ||
4170 | else | 4054 | else | ||
4171 | [UNUSED_OUTPUT, bin]=min(abs(t-values(k))); %#ok<ASGLU> | 4055 | [UNUSED_OUTPUT, bin]=min(abs(t-values(k))); %#ok<ASGLU> | ||
4172 | end | 4056 | end | ||
4173 | pdf.y(bin) = pdf.y(bin)+probs(k); | 4057 | pdf.y(bin) = pdf.y(bin)+probs(k); | ||
4174 | end | 4058 | end | ||
4175 | 4059 | ||||
4176 | pdf.BinSize=binsize; | 4060 | pdf.BinSize=binsize; | ||
4177 | pdf.y=pdf.y/sum(pdf.y); | 4061 | pdf.y=pdf.y/sum(pdf.y); | ||
4178 | if any(~isreal(pdf.y)) || any(pdf.y<0) | 4062 | if any(~isreal(pdf.y)) || any(pdf.y<0) | ||
4179 | error('PDF must be real and nonnegative'); | 4063 | error('PDF must be real and nonnegative'); | ||
4180 | end | 4064 | end | ||
4181 | support=find(pdf.y); | 4065 | support=find(pdf.y); | ||
4182 | pdf.y=pdf.y(support(1):support(end)); | 4066 | pdf.y=pdf.y(support(1):support(end)); | ||
4183 | pdf.Min=pdf.Min+(support(1)-1); | 4067 | pdf.Min=pdf.Min+(support(1)-1); | ||
4184 | pdf.x=(pdf.Min:-pdf.Min)*binsize; | 4068 | pdf.x=(pdf.Min:-pdf.Min)*binsize; | ||
4185 | function clip_output=dfe_clipper(input,max_threshold,min_threshold) | 4069 | function clip_output=dfe_clipper(input,max_threshold,min_threshold) | ||
4186 | 4070 | ||||
4187 | if isrow(input) | 4071 | if isrow(input) | ||
4188 | max_threshold=max_threshold(:).'; | 4072 | max_threshold=max_threshold(:).'; | ||
4189 | min_threshold=min_threshold(:).'; | 4073 | min_threshold=min_threshold(:).'; | ||
4190 | else | 4074 | else | ||
4191 | max_threshold=max_threshold(:); | 4075 | max_threshold=max_threshold(:); | ||
4192 | min_threshold=min_threshold(:); | 4076 | min_threshold=min_threshold(:); | ||
4193 | end | 4077 | end | ||
4194 | 4078 | ||||
4195 | clip_output=input; | 4079 | clip_output=input; | ||
4196 | clip_output(input>max_threshold)=max_threshold(input>max_threshold); | 4080 | clip_output(input>max_threshold)=max_threshold(input>max_threshold); | ||
4197 | clip_output(input<min_threshold)=min_threshold(input<min_threshold); | 4081 | clip_output(input<min_threshold)=min_threshold(input<min_threshold); | ||
4198 | 4082 | ||||
4199 | 4083 | ||||
4200 | function [msg] = end_display_control(msg,param,OP,output_args,COM,min_ERL,ERL,VEO_mV,VEC_dB,threshold_DER,DISPLAY_WINDOW) | 4084 | function [msg] = end_display_control(msg,param,OP,output_args,COM,min_ERL,ERL,VEO_mV,VEC_dB,threshold_DER,DISPLAY_WINDOW) | ||
4201 | [ncases, mele]=size(param.z_p_tx_cases); | 4085 | [ncases, mele]=size(param.z_p_tx_cases); | ||
4202 | if mele ==2 | 4086 | if mele ==2 | ||
4203 | param.flex=2; | 4087 | param.flex=2; | ||
4204 | elseif mele==4 | 4088 | elseif mele==4 | ||
4205 | param.flex=4; | 4089 | param.flex=4; | ||
4206 | elseif mele==1 | 4090 | elseif mele==1 | ||
4207 | param.flex=1; | 4091 | param.flex=1; | ||
4208 | else | 4092 | else | ||
4209 | error(springf('config file syntax error')) | 4093 | error(springf('config file syntax error')) | ||
4210 | end | 4094 | end | ||
4211 | 4095 | ||||
4212 | 4096 | ||||
4213 | if DISPLAY_WINDOW && ~OP.RX_CALIBRATION | 4097 | if DISPLAY_WINDOW && ~OP.RX_CALIBRATION | ||
4214 | % display bathtub curves in one axis per test case. | 4098 | % display bathtub curves in one axis per test case. | ||
4215 | % h=findall(0, 'Name', 'COM results'); | 4099 | % h=findall(0, 'Name', 'COM results'); | ||
4216 | if ~exist('h','var') | 4100 | if ~exist('h','var') | ||
4217 | msgtext = cell(1, length(OP.pkg_len_select)); | 4101 | msgtext = cell(1, length(OP.pkg_len_select)); | ||
4218 | msgcolor = 'g'; | 4102 | msgcolor = 'g'; | ||
4219 | else | 4103 | else | ||
4220 | msgtext=get(findobj(h, 'type', 'text'), 'string'); | 4104 | msgtext=get(findobj(h, 'type', 'text'), 'string'); | ||
4221 | msgcolor = get(h, 'color'); | 4105 | msgcolor = get(h, 'color'); | ||
4222 | close(h); % will be recreated | 4106 | close(h); % will be recreated | ||
4223 | end | 4107 | end | ||
4224 | msgctr=size(msgtext,1)+1; | 4108 | msgctr=size(msgtext,1)+1; | ||
4225 | if ~OP.ERL_ONLY | 4109 | if ~OP.ERL_ONLY | ||
4226 | switch OP.PHY | 4110 | switch OP.PHY | ||
4227 | case 'C2M' | 4111 | case 'C2M' | ||
4228 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | 4112 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | ||
4229 | msg=sprintf('%s: EH = %.3f mV (pass)\n', ... | 4113 | msg=sprintf('%s: EH = %.3f mV (pass)\n', ... | ||
4230 | msg, VEO_mV); | 4114 | msg, VEO_mV); | ||
4231 | else | 4115 | else | ||
4232 | msg=sprintf('%s: EH = %.3f mV (FAIL)\n', ... | 4116 | msg=sprintf('%s: EH = %.3f mV (FAIL)\n', ... | ||
4233 | msg, VEO_mV); | 4117 | msg, VEO_mV); | ||
4234 | msgcolor = 'r'; | 4118 | msgcolor = 'r'; | ||
4235 | end | 4119 | end | ||
4236 |
| 4120 |
| ||
4237 | if VEC_dB <= param.VEC_pass_threshold | 4121 | if VEC_dB <= param.VEC_pass_threshold | ||
4238 | msg=sprintf('%s: VEC = %.3f dB (pass)\n', ... | 4122 | msg=sprintf('%s: VEC = %.3f dB (pass)\n', ... | ||
4239 | (msg), VEC_dB); | 4123 | (msg), VEC_dB); | ||
4240 | else | 4124 | else | ||
4241 | msg=sprintf('%s: VEC = %.3f dB (FAIL)\n', ... | 4125 | msg=sprintf('%s: VEC = %.3f dB (FAIL)\n', ... | ||
4242 | (msg), VEC_dB); | 4126 | (msg), VEC_dB); | ||
4243 | msgcolor = 'r'; | 4127 | msgcolor = 'r'; | ||
4244 | end | 4128 | end | ||
4245 | case 'C2C' | 4129 | case 'C2C' | ||
4246 | if COM >= param.pass_threshold | 4130 | if COM >= param.pass_threshold | ||
4247 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (pass)\n', ... | 4131 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (pass)\n', ... | ||
4248 | % msg, COM); | 4132 | % msg, COM); | ||
4249 | msg=sprintf('%s: COM = %.3f dB (pass)\n', ... | 4133 | msg=sprintf('%s: COM = %.3f dB (pass)\n', ... | ||
4250 | msg, COM); | 4134 | msg, COM); | ||
4251 | else | 4135 | else | ||
4252 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | 4136 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | ||
4253 | % msg, COM); | 4137 | % msg, COM); | ||
4254 | msg=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | 4138 | msg=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | ||
4255 | msg, COM); | 4139 | msg, COM); | ||
4256 | msgcolor = 'r'; | 4140 | msgcolor = 'r'; | ||
4257 | end | 4141 | end | ||
4258 | % begin yasuo patch 3/18/2019 | 4142 | % begin yasuo patch 3/18/2019 | ||
4259 | msg=sprintf('%s: DER = %.3e at COM threshold \n', msg, threshold_DER); | 4143 | msg=sprintf('%s: DER = %.3e at COM threshold \n', msg, threshold_DER); | ||
4260 | % end yasuo patch | 4144 | % end yasuo patch | ||
4261 | case 'C2Mcom' | 4145 | case 'C2Mcom' | ||
4262 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | 4146 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | ||
4263 | msg=sprintf('%s: EH = %.3f mV (pass)\n', ... | 4147 | msg=sprintf('%s: EH = %.3f mV (pass)\n', ... | ||
4264 | msg, VEO_mV); | 4148 | msg, VEO_mV); | ||
4265 | else | 4149 | else | ||
4266 | msg=sprintf('%s: EH = %.3f mV (FAIL)\n', ... | 4150 | msg=sprintf('%s: EH = %.3f mV (FAIL)\n', ... | ||
4267 | msg, VEO_mV); | 4151 | msg, VEO_mV); | ||
4268 | msgcolor = 'r'; | 4152 | msgcolor = 'r'; | ||
4269 | end | 4153 | end | ||
4270 |
| 4154 |
| ||
4271 | if VEC_dB <= param.VEC_pass_threshold | 4155 | if VEC_dB <= param.VEC_pass_threshold | ||
4272 | msg=sprintf('%s: VEC = %.3f dB (pass)\n', ... | 4156 | msg=sprintf('%s: VEC = %.3f dB (pass)\n', ... | ||
4273 | (msg), VEC_dB); | 4157 | (msg), VEC_dB); | ||
4274 | else | 4158 | else | ||
4275 | msg=sprintf('%s: VEC = %.3f dB (FAIL)\n', ... | 4159 | msg=sprintf('%s: VEC = %.3f dB (FAIL)\n', ... | ||
4276 | (msg), VEC_dB); | 4160 | (msg), VEC_dB); | ||
4277 | msgcolor = 'r'; | 4161 | msgcolor = 'r'; | ||
4278 | end | 4162 | end | ||
4279 | if COM >= param.pass_threshold | 4163 | if COM >= param.pass_threshold | ||
4280 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (pass)\n', ... | 4164 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (pass)\n', ... | ||
4281 | % msg, COM); | 4165 | % msg, COM); | ||
4282 | msg=sprintf('%s: COM = %.3f dB (pass)\n', ... | 4166 | msg=sprintf('%s: COM = %.3f dB (pass)\n', ... | ||
4283 | msg, COM); | 4167 | msg, COM); | ||
4284 | else | 4168 | else | ||
4285 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | 4169 | % msgtext{package_testcase_i}=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | ||
4286 | % msg, COM); | 4170 | % msg, COM); | ||
4287 | msg=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | 4171 | msg=sprintf('%s: COM = %.3f dB (FAIL)\n', ... | ||
4288 | msg, COM); | 4172 | msg, COM); | ||
4289 | msgcolor = 'r'; | 4173 | msgcolor = 'r'; | ||
4290 | end | 4174 | end | ||
4291 | % begin yasuo patch 3/18/2019 | 4175 | % begin yasuo patch 3/18/2019 | ||
4292 | msg=sprintf('%s: DER = %.3e at COM threshold \n', msg, threshold_DER); | 4176 | msg=sprintf('%s: DER = %.3e at COM threshold \n', msg, threshold_DER); | ||
4293 | % end yasuo patch | 4177 | % end yasuo patch | ||
4294 | end | 4178 | end | ||
4295 | end | 4179 | end | ||
4296 | if OP.ERL | 4180 | if OP.ERL | ||
4297 | if ~isempty(ERL) | 4181 | if ~isempty(ERL) | ||
4298 | if min_ERL >= param.ERL_pass_threshold | 4182 | if min_ERL >= param.ERL_pass_threshold | ||
4299 | % msgtext{package_testcase_i+1}=[sprintf(' PASS ... ERL = %.3f dB\n', min_ERL)]; | 4183 | % msgtext{package_testcase_i+1}=[sprintf(' PASS ... ERL = %.3f dB\n', min_ERL)]; | ||
4300 | msg=[sprintf('%s: PASS ... ERL = %.3f dB (%.3f dB,%.3f dB) \n',msg, min_ERL, ERL)]; | 4184 | msg=[sprintf('%s: PASS ... ERL = %.3f dB (%.3f dB,%.3f dB) \n',msg, min_ERL, ERL)]; | ||
4301 | else | 4185 | else | ||
4302 | % msgtext{package_testcase_i+1}=[ sprintf(' FAIL ... ERL = %.3f dB\n', min_ERL) ]; | 4186 | % msgtext{package_testcase_i+1}=[ sprintf(' FAIL ... ERL = %.3f dB\n', min_ERL) ]; | ||
4303 | msg=[ sprintf('%s: FAIL ... ERL = %.3f dB (%.3f dB,%.3f dB) \n',msg, min_ERL, ERL) ]; | 4187 | msg=[ sprintf('%s: FAIL ... ERL = %.3f dB (%.3f dB,%.3f dB) \n',msg, min_ERL, ERL) ]; | ||
4304 | msgcolor = 'r'; | 4188 | msgcolor = 'r'; | ||
4305 | end | 4189 | end | ||
4306 | end | 4190 | end | ||
4307 | end | 4191 | end | ||
4308 | h=msgbox(msg, ['COM r' output_args.code_revision ' results']); | 4192 | h=msgbox(msg, ['COM r' output_args.code_revision ' results']); | ||
4309 | set(h, 'color', msgcolor, 'tag', 'COM'); | 4193 | set(h, 'color', msgcolor, 'tag', 'COM'); | ||
4310 | movegui(h, 'center'); | 4194 | movegui(h, 'center'); | ||
4311 | else % no windows | 4195 | else % no windows | ||
4312 | % display(['max noise at BER = ' num2str(peak_interference_at_BER)]) | 4196 | % display(['max noise at BER = ' num2str(peak_interference_at_BER)]) | ||
4313 | % display(['signal after eq = ' num2str(A_s/(param.levels-1))]) | 4197 | % display(['signal after eq = ' num2str(A_s/(param.levels-1))]) | ||
4314 | if ~OP.ERL_ONLY | 4198 | if ~OP.ERL_ONLY | ||
4315 | switch OP.PHY | 4199 | switch OP.PHY | ||
4316 | case 'C2C' | 4200 | case 'C2C' | ||
4317 | if COM >= param.pass_threshold | 4201 | if COM >= param.pass_threshold | ||
4318 | fprintf('%s <strong> PASS ... COM = %.3f dB</strong>\n', msg, COM); | 4202 | fprintf('%s <strong> PASS ... COM = %.3f dB</strong>\n', msg, COM); | ||
4319 | else | 4203 | else | ||
4320 | fprintf(2,'%s <strong> FAIL ... COM = %.3f dB</strong>\n', msg, COM); | 4204 | fprintf(2,'%s <strong> FAIL ... COM = %.3f dB</strong>\n', msg, COM); | ||
4321 | end | 4205 | end | ||
4322 | % begin yasuo patch 3/18/2019 | 4206 | % begin yasuo patch 3/18/2019 | ||
4323 | fprintf('%s DER = %.3e at COM threshold \n', msg, threshold_DER); | 4207 | fprintf('%s DER = %.3e at COM threshold \n', msg, threshold_DER); | ||
4324 | % end yasuo patch | 4208 | % end yasuo patch | ||
4325 | case 'C2Mcom' | 4209 | case 'C2Mcom' | ||
4326 | if VEC_dB <= param.VEC_pass_threshold | 4210 | if VEC_dB <= param.VEC_pass_threshold | ||
4327 | fprintf('%s <strong> PASS ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | 4211 | fprintf('%s <strong> PASS ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | ||
4328 | else | 4212 | else | ||
4329 | fprintf(2,'%s <strong> FAIL ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | 4213 | fprintf(2,'%s <strong> FAIL ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | ||
4330 | end | 4214 | end | ||
4331 |
| 4215 |
| ||
4332 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | 4216 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | ||
4333 | fprintf('%s <strong> PASS ... EH = %.3f mV</strong>\n', msg, VEO_mV); | 4217 | fprintf('%s <strong> PASS ... EH = %.3f mV</strong>\n', msg, VEO_mV); | ||
4334 | else | 4218 | else | ||
4335 | fprintf(2,'%s <strong> FAIL ... EH = %.3f mV</strong>\n', msg, VEO_mV); | 4219 | fprintf(2,'%s <strong> FAIL ... EH = %.3f mV</strong>\n', msg, VEO_mV); | ||
4336 | end | 4220 | end | ||
4337 | if COM >= param.pass_threshold | 4221 | if COM >= param.pass_threshold | ||
4338 | fprintf('%s <strong> PASS ... COM = %.3f dB</strong>\n', msg, COM); | 4222 | fprintf('%s <strong> PASS ... COM = %.3f dB</strong>\n', msg, COM); | ||
4339 | else | 4223 | else | ||
4340 | fprintf(2,'%s <strong> FAIL ... COM = %.3f dB</strong>\n', msg, COM); | 4224 | fprintf(2,'%s <strong> FAIL ... COM = %.3f dB</strong>\n', msg, COM); | ||
4341 | end | 4225 | end | ||
4342 | % begin yasuo patch 3/18/2019 | 4226 | % begin yasuo patch 3/18/2019 | ||
4343 | fprintf('%s DER = %.3e at COM threshold \n', msg, threshold_DER); | 4227 | fprintf('%s DER = %.3e at COM threshold \n', msg, threshold_DER); | ||
4344 | % end yasuo patch | 4228 | % end yasuo patch | ||
4345 | case 'C2M' | 4229 | case 'C2M' | ||
4346 | if VEC_dB <= param.VEC_pass_threshold | 4230 | if VEC_dB <= param.VEC_pass_threshold | ||
4347 | fprintf('%s <strong> PASS ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | 4231 | fprintf('%s <strong> PASS ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | ||
4348 | else | 4232 | else | ||
4349 | fprintf(2,'%s <strong> FAIL ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | 4233 | fprintf(2,'%s <strong> FAIL ... VEC = %.3f dB</strong>\n', msg, VEC_dB); | ||
4350 | end | 4234 | end | ||
4351 |
| 4235 |
| ||
4352 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | 4236 | if VEO_mV >= param.Min_VEO && VEO_mV <= param.Max_VEO | ||
4353 | fprintf('%s <strong> PASS ... EH = %.3f mV</strong>\n', msg, VEO_mV); | 4237 | fprintf('%s <strong> PASS ... EH = %.3f mV</strong>\n', msg, VEO_mV); | ||
4354 | else | 4238 | else | ||
4355 | fprintf(2,'%s <strong> FAIL ... EH = %.3f mV</strong>\n', msg, VEO_mV); | 4239 | fprintf(2,'%s <strong> FAIL ... EH = %.3f mV</strong>\n', msg, VEO_mV); | ||
4356 | end | 4240 | end | ||
4357 | end | 4241 | end | ||
4358 | end | 4242 | end | ||
4359 | if OP.ERL | 4243 | if OP.ERL | ||
4360 | if ~isempty(ERL) | 4244 | if ~isempty(ERL) | ||
4361 | if min_ERL >= param.ERL_pass_threshold | 4245 | if min_ERL >= param.ERL_pass_threshold | ||
4362 | % msgtext{package_testcase_i+1}=[sprintf(' PASS ... ERL = %.3f dB\n', min_ERL)]; | 4246 | % msgtext{package_testcase_i+1}=[sprintf(' PASS ... ERL = %.3f dB\n', min_ERL)]; | ||
4363 | fprintf('%s: <strong> PASS ... ERL = %.3f dB (%.3f dB, %.3f dB)</strong>\n',msg, min_ERL, ERL ); | 4247 | fprintf('%s: <strong> PASS ... ERL = %.3f dB (%.3f dB, %.3f dB)</strong>\n',msg, min_ERL, ERL ); | ||
4364 | else | 4248 | else | ||
4365 | % msgtext{package_testcase_i+1}=[ sprintf(' FAIL ... ERL = %.3f dB\n', min_ERL) ]; | 4249 | % msgtext{package_testcase_i+1}=[ sprintf(' FAIL ... ERL = %.3f dB\n', min_ERL) ]; | ||
4366 | fprintf(2,'%s: <strong> FAIL ... ERL = %.3f dB (%.3f dB, %.3f dB)</strong>\n',msg, min_ERL, ERL) ; | 4250 | fprintf(2,'%s: <strong> FAIL ... ERL = %.3f dB (%.3f dB, %.3f dB)</strong>\n',msg, min_ERL, ERL) ; | ||
4367 | end | 4251 | end | ||
4368 | end | 4252 | end | ||
4369 | end | 4253 | end | ||
4370 | end | 4254 | end | ||
4371 | 4255 | ||||
4372 | function [Left_EW,Right_EW]=find_eye_width(eye_contour,half_UI,samples_per_UI,vref) | 4256 | function [Left_EW,Right_EW]=find_eye_width(eye_contour,half_UI,samples_per_UI,vref) | ||
4373 | 4257 | ||||
4374 | %Left eye Width (Top Eye) | 4258 | %Left eye Width (Top Eye) | ||
4375 | left_top=eye_contour(half_UI:-1:1,1); | 4259 | left_top=eye_contour(half_UI:-1:1,1); | ||
4376 | %vref_crossing is the first point less than vref (usually first point < 0) | 4260 | %vref_crossing is the first point less than vref (usually first point < 0) | ||
4377 | vref_crossing=find(left_top<vref,1,'first'); | 4261 | vref_crossing=find(left_top<vref,1,'first'); | ||
4378 | if isempty(vref_crossing) | 4262 | if isempty(vref_crossing) | ||
4379 | %this case handles completely open eye | 4263 | %this case handles completely open eye | ||
4380 | L1=half_UI; | 4264 | L1=half_UI; | ||
4381 | elseif vref_crossing==1 | 4265 | elseif vref_crossing==1 | ||
4382 | %this case handles completely closed eye | 4266 | %this case handles completely closed eye | ||
4383 | L1=0; | 4267 | L1=0; | ||
4384 | else | 4268 | else | ||
4385 | %this case handles the normal eye | 4269 | %this case handles the normal eye | ||
4386 | %INT is a linear interpolation between the 2 points on either side of | 4270 | %INT is a linear interpolation between the 2 points on either side of | ||
4387 | %vref to determine where the vref crossing occurred. In systems with | 4271 | %vref to determine where the vref crossing occurred. In systems with | ||
4388 | %a small number of samples_per_UI, interpolation improves accuracy over | 4272 | %a small number of samples_per_UI, interpolation improves accuracy over | ||
4389 | %just using the integer sample point | 4273 | %just using the integer sample point | ||
4390 | INT=vref_intersect(eye_contour(1:half_UI,1),half_UI-vref_crossing+1+1,vref); | 4274 | INT=vref_intersect(eye_contour(1:half_UI,1),half_UI-vref_crossing+1+1,vref); | ||
4391 | L1=half_UI-INT; | 4275 | L1=half_UI-INT; | ||
4392 | end | 4276 | end | ||
4393 | %Left eye Width (Bottom Eye) | 4277 | %Left eye Width (Bottom Eye) | ||
4394 | left_bot=eye_contour(half_UI:-1:1,2); | 4278 | left_bot=eye_contour(half_UI:-1:1,2); | ||
4395 | vref_crossing=find(left_bot>vref,1,'first'); | 4279 | vref_crossing=find(left_bot>vref,1,'first'); | ||
4396 | if isempty(vref_crossing) | 4280 | if isempty(vref_crossing) | ||
4397 | L0=half_UI; | 4281 | L0=half_UI; | ||
4398 | elseif vref_crossing==1 | 4282 | elseif vref_crossing==1 | ||
4399 | L0=0; | 4283 | L0=0; | ||
4400 | else | 4284 | else | ||
4401 | INT=vref_intersect(eye_contour(1:half_UI,2),half_UI-vref_crossing+1+1,vref); | 4285 | INT=vref_intersect(eye_contour(1:half_UI,2),half_UI-vref_crossing+1+1,vref); | ||
4402 | L0=half_UI-INT; | 4286 | L0=half_UI-INT; | ||
4403 | end | 4287 | end | ||
4404 | %Right eye Width (Top Eye) | 4288 | %Right eye Width (Top Eye) | ||
4405 | right_top=eye_contour(half_UI:end,1); | 4289 | right_top=eye_contour(half_UI:end,1); | ||
4406 | vref_crossing=find(right_top<vref,1,'first'); | 4290 | vref_crossing=find(right_top<vref,1,'first'); | ||
4407 | if isempty(vref_crossing) | 4291 | if isempty(vref_crossing) | ||
4408 | R1=samples_per_UI-half_UI; | 4292 | R1=samples_per_UI-half_UI; | ||
4409 | elseif vref_crossing==1 | 4293 | elseif vref_crossing==1 | ||
4410 | R1=0; | 4294 | R1=0; | ||
4411 | else | 4295 | else | ||
4412 | INT=vref_intersect(eye_contour(half_UI:end,1),vref_crossing,vref)+half_UI-1; | 4296 | INT=vref_intersect(eye_contour(half_UI:end,1),vref_crossing,vref)+half_UI-1; | ||
4413 | R1=INT-half_UI; | 4297 | R1=INT-half_UI; | ||
4414 | end | 4298 | end | ||
4415 | %Right eye Width (Bottom Eye) | 4299 | %Right eye Width (Bottom Eye) | ||
4416 | right_bot=eye_contour(half_UI:end,2); | 4300 | right_bot=eye_contour(half_UI:end,2); | ||
4417 | vref_crossing=find(right_bot>vref,1,'first'); | 4301 | vref_crossing=find(right_bot>vref,1,'first'); | ||
4418 | if isempty(vref_crossing) | 4302 | if isempty(vref_crossing) | ||
4419 | R0=samples_per_UI-half_UI; | 4303 | R0=samples_per_UI-half_UI; | ||
4420 | elseif vref_crossing==1 | 4304 | elseif vref_crossing==1 | ||
4421 | R0=0; | 4305 | R0=0; | ||
4422 | else | 4306 | else | ||
4423 | INT=vref_intersect(eye_contour(half_UI:end,2),vref_crossing,vref)+half_UI-1; | 4307 | INT=vref_intersect(eye_contour(half_UI:end,2),vref_crossing,vref)+half_UI-1; | ||
4424 | R0=INT-half_UI; | 4308 | R0=INT-half_UI; | ||
4425 | end | 4309 | end | ||
4426 | 4310 | ||||
4427 | %L1 = top left eye width | 4311 | %L1 = top left eye width | ||
4428 | %L0 = bottom left eye width | 4312 | %L0 = bottom left eye width | ||
4429 | %Left eye width is the minimum | 4313 | %Left eye width is the minimum | ||
4430 | %R1 = top right eye width | 4314 | %R1 = top right eye width | ||
4431 | %R0 = bottom right eye width | 4315 | %R0 = bottom right eye width | ||
4432 | %Right eye width is the minimum | 4316 | %Right eye width is the minimum | ||
4433 | Left_EW=min([L1 L0]); | 4317 | Left_EW=min([L1 L0]); | ||
4434 | Right_EW=min([R1 R0]); | 4318 | Right_EW=min([R1 R0]); | ||
4435 | 4319 | ||||
4436 | function [idx]=findbankloc(hisi,idx_st,idx_en,tap_bk,curval,bmaxg,N_bg) | 4320 | function [idx]=findbankloc(hisi,idx_st,idx_en,tap_bk,curval,bmaxg,N_bg) | ||
4437 | % [idx]=findbankloc(hisi,idx_st,idx_en,tap_bk) | 4321 | % [idx]=findbankloc(hisi,idx_st,idx_en,tap_bk) | ||
4438 | % find the location of the DFE bank | 4322 | % find the location of the DFE bank | ||
4439 | % hisi: waveform with cursor values; | 4323 | % hisi: waveform with cursor values; | ||
4440 | % idx_st: starting index; | 4324 | % idx_st: starting index; | ||
4441 | % idx_en: ending index ; | 4325 | % idx_en: ending index ; | ||
4442 | % tap_bk: number of taps per bank; | 4326 | % tap_bk: number of taps per bank; | ||
4443 | % bmaxg: maximum coefficient; | 4327 | % bmaxg: maximum coefficient; | ||
4444 | 4328 | ||||
4445 | hisi=hisi(:); | 4329 | hisi=hisi(:); | ||
4446 | len=idx_en-idx_st+1; | 4330 | len=idx_en-idx_st+1; | ||
4447 | h0=abs(hisi(idx_st:idx_en)); | 4331 | h0=abs(hisi(idx_st:idx_en)); | ||
4448 | h1=max(0,h0-bmaxg*curval); | 4332 | h1=max(0,h0-bmaxg*curval); | ||
4449 | 4333 | ||||
4450 | %if cursor value is negative, force h1 to all zeros | 4334 | %if cursor value is negative, force h1 to all zeros | ||
4451 | %otherwise h1 will become larger than h0 and the values in ndiff will become inverted | 4335 | %otherwise h1 will become larger than h0 and the values in ndiff will become inverted | ||
4452 | %this makes the weakest isi the most desirable to choose so everything breaks | 4336 | %this makes the weakest isi the most desirable to choose so everything breaks | ||
4453 | if curval<0 | 4337 | if curval<0 | ||
4454 | h1=zeros(size(h0)); | 4338 | h1=zeros(size(h0)); | ||
4455 | end | 4339 | end | ||
4456 | 4340 | ||||
4457 | h0n=zeros(len-tap_bk+1,1); | 4341 | h0n=zeros(len-tap_bk+1,1); | ||
4458 | h1n=h0n; | 4342 | h1n=h0n; | ||
4459 | 4343 | ||||
4460 | for ii=1:tap_bk | 4344 | for ii=1:tap_bk | ||
4461 | h0tmp=h0(ii:ii+len-tap_bk); | 4345 | h0tmp=h0(ii:ii+len-tap_bk); | ||
4462 | h0n=h0n+h0tmp.^2; | 4346 | h0n=h0n+h0tmp.^2; | ||
4463 | h1tmp=h1(ii:ii+len-tap_bk); | 4347 | h1tmp=h1(ii:ii+len-tap_bk); | ||
4464 | h1n=h1n+h1tmp.^2; | 4348 | h1n=h1n+h1tmp.^2; | ||
4465 | end | 4349 | end | ||
4466 | 4350 | ||||
4467 | ndiff=h0n-h1n; | 4351 | ndiff=h0n-h1n; | ||
4468 | 4352 | ||||
4469 | min_energy = -Inf; | 4353 | min_energy = -Inf; | ||
4470 | 4354 | ||||
4471 | idx=zeros(1,tap_bk*N_bg); | 4355 | idx=zeros(1,tap_bk*N_bg); | ||
4472 | ordered_set=(1:(N_bg-1)*tap_bk+1)'; | 4356 | ordered_set=(1:(N_bg-1)*tap_bk+1)'; | ||
4473 | set_next_bank=0; | 4357 | set_next_bank=0; | ||
4474 | %Loop through each group | 4358 | %Loop through each group | ||
4475 | for k=1:N_bg | 4359 | for k=1:N_bg | ||
4476 | %Sort to choose the strongest | 4360 | %Sort to choose the strongest | ||
4477 | [~,val_sort]=sort(ndiff,'descend'); | 4361 | [~,val_sort]=sort(ndiff,'descend'); | ||
4478 | if k==1 | 4362 | if k==1 | ||
4479 | %shortcut: Choose the first 1:N_bg*tap_bk taps if they are the strongest | 4363 | %shortcut: Choose the first 1:N_bg*tap_bk taps if they are the strongest | ||
4480 | if isequal(sort(val_sort(ordered_set)),ordered_set) | 4364 | if isequal(sort(val_sort(ordered_set)),ordered_set) | ||
4481 | idx=1:N_bg*tap_bk; | 4365 | idx=1:N_bg*tap_bk; | ||
4482 | break; | 4366 | break; | ||
4483 | end | 4367 | end | ||
4484 | end | 4368 | end | ||
4485 | if set_next_bank>0 | 4369 | if set_next_bank>0 | ||
4486 | %when a previous bank (goodV) was found, automatically set the bank without going through the search | 4370 | %when a previous bank (goodV) was found, automatically set the bank without going through the search | ||
4487 | new_bank=set_next_bank:set_next_bank+tap_bk-1; | 4371 | new_bank=set_next_bank:set_next_bank+tap_bk-1; | ||
4488 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | 4372 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | ||
4489 | set_next_bank=0; | 4373 | set_next_bank=0; | ||
4490 | ndiff(new_bank)=min_energy; | 4374 | ndiff(new_bank)=min_energy; | ||
4491 | bad_start=new_bank(1)-tap_bk+1; | 4375 | bad_start=new_bank(1)-tap_bk+1; | ||
4492 | bad_end=new_bank(1)-1; | 4376 | bad_end=new_bank(1)-1; | ||
4493 | if bad_end<=0 | 4377 | if bad_end<=0 | ||
4494 | badV=[]; | 4378 | badV=[]; | ||
4495 | elseif bad_start>0 | 4379 | elseif bad_start>0 | ||
4496 | badV=bad_start:bad_end; | 4380 | badV=bad_start:bad_end; | ||
4497 | else | 4381 | else | ||
4498 | badV=1:bad_end; | 4382 | badV=1:bad_end; | ||
4499 | end | 4383 | end | ||
4500 | if ~isempty(badV) | 4384 | if ~isempty(badV) | ||
4501 | ndiff(badV)=min_energy; | 4385 | ndiff(badV)=min_energy; | ||
4502 | end | 4386 | end | ||
4503 | continue; | 4387 | continue; | ||
4504 | end | 4388 | end | ||
4505 | %potential bank = the strongest tap group | 4389 | %potential bank = the strongest tap group | ||
4506 | new_bank=val_sort(1):val_sort(1)+tap_bk-1; | 4390 | new_bank=val_sort(1):val_sort(1)+tap_bk-1; | ||
4507 | if k==N_bg | 4391 | if k==N_bg | ||
4508 | %Last group: just choose the strongest | 4392 | %Last group: just choose the strongest | ||
4509 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | 4393 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | ||
4510 | break; | 4394 | break; | ||
4511 | end | 4395 | end | ||
4512 |
| 4396 |
| ||
4513 | do_it_again=1; | 4397 | do_it_again=1; | ||
4514 | first_time=1; | 4398 | first_time=1; | ||
4515 | num_loops=0; | 4399 | num_loops=0; | ||
4516 | while do_it_again | 4400 | while do_it_again | ||
4517 | do_it_again=0; | 4401 | do_it_again=0; | ||
4518 | if num_loops>length(ndiff) | 4402 | if num_loops>length(ndiff) | ||
4519 | break; | 4403 | break; | ||
4520 | end | 4404 | end | ||
4521 | %note badV: taps smaller and less than 1 group away | 4405 | %note badV: taps smaller and less than 1 group away | ||
4522 | bad_start=new_bank(1)-tap_bk+1; | 4406 | bad_start=new_bank(1)-tap_bk+1; | ||
4523 | bad_end=new_bank(1)-1; | 4407 | bad_end=new_bank(1)-1; | ||
4524 | if bad_end<=0 | 4408 | if bad_end<=0 | ||
4525 | badV=[]; | 4409 | badV=[]; | ||
4526 | elseif bad_start>0 | 4410 | elseif bad_start>0 | ||
4527 | badV=bad_start:bad_end; | 4411 | badV=bad_start:bad_end; | ||
4528 | else | 4412 | else | ||
4529 | badV=1:bad_end; | 4413 | badV=1:bad_end; | ||
4530 | end | 4414 | end | ||
4531 | for j=length(badV):-1:1 | 4415 | for j=length(badV):-1:1 | ||
4532 | if any(badV(j)-idx==0) | 4416 | if any(badV(j)-idx==0) | ||
4533 | badV(j)=[]; | 4417 | badV(j)=[]; | ||
4534 | end | 4418 | end | ||
4535 | end | 4419 | end | ||
4536 | %note goodV: the tap exactly 1 tap_bk smaller | 4420 | %note goodV: the tap exactly 1 tap_bk smaller | ||
4537 | goodV=new_bank(1)-tap_bk; | 4421 | goodV=new_bank(1)-tap_bk; | ||
4538 | if ~isempty(badV) | 4422 | if ~isempty(badV) | ||
4539 | if ~first_time | 4423 | if ~first_time | ||
4540 | [~,val_sort]=sort(ndiff,'descend'); | 4424 | [~,val_sort]=sort(ndiff,'descend'); | ||
4541 | end | 4425 | end | ||
4542 | first_time=0; | 4426 | first_time=0; | ||
4543 | checkV=[badV new_bank]; | 4427 | checkV=[badV new_bank]; | ||
4544 | 4428 | ||||
4545 | badV_pos=zeros(1,length(badV)); | 4429 | badV_pos=zeros(1,length(badV)); | ||
4546 | for j=1:length(badV) | 4430 | for j=1:length(badV) | ||
4547 | badV_pos(j)=find(badV(j)==val_sort); | 4431 | badV_pos(j)=find(badV(j)==val_sort); | ||
4548 | end | 4432 | end | ||
4549 |
| 4433 |
| ||
4550 | %loop through the sorted list to find the first tap outside the group and not a member of badV | 4434 | %loop through the sorted list to find the first tap outside the group and not a member of badV | ||
4551 | found_goodV=0; | 4435 | found_goodV=0; | ||
4552 | for ii=1:length(val_sort) | 4436 | for ii=1:length(val_sort) | ||
4553 | if val_sort(ii)==goodV | 4437 | if val_sort(ii)==goodV | ||
4554 | found_goodV=1; | 4438 | found_goodV=1; | ||
4555 | break; | 4439 | break; | ||
4556 | end | 4440 | end | ||
4557 | if all(val_sort(ii)-checkV~=0) | 4441 | if all(val_sort(ii)-checkV~=0) | ||
4558 | break; | 4442 | break; | ||
4559 | end | 4443 | end | ||
4560 | end | 4444 | end | ||
4561 |
| 4445 |
| ||
4562 | if ~found_goodV && min(badV_pos)<ii | 4446 | if ~found_goodV && min(badV_pos)<ii | ||
4563 | %if goodV wasn't found and bad taps occur before non group members are found | 4447 | %if goodV wasn't found and bad taps occur before non group members are found | ||
4564 | %throw out the strongest tap and take the next strongest | 4448 | %throw out the strongest tap and take the next strongest | ||
4565 | do_it_again=1; | 4449 | do_it_again=1; | ||
4566 | ndiff(new_bank(1))=min_energy; | 4450 | ndiff(new_bank(1))=min_energy; | ||
4567 | %speed up: new max_val is always val_sort(2) | 4451 | %speed up: new max_val is always val_sort(2) | ||
4568 | new_bank=val_sort(2):val_sort(2)+tap_bk-1; | 4452 | new_bank=val_sort(2):val_sort(2)+tap_bk-1; | ||
4569 | end | 4453 | end | ||
4570 | if found_goodV | 4454 | if found_goodV | ||
4571 | %if goodV was found, set the next bank to goodV | 4455 | %if goodV was found, set the next bank to goodV | ||
4572 | set_next_bank=goodV; | 4456 | set_next_bank=goodV; | ||
4573 | end | 4457 | end | ||
4574 | end | 4458 | end | ||
4575 | num_loops=num_loops+1; | 4459 | num_loops=num_loops+1; | ||
4576 | end | 4460 | end | ||
4577 | %at the end, the floating taps are set to idx | 4461 | %at the end, the floating taps are set to idx | ||
4578 | %and ndiff has illegal values set to zero | 4462 | %and ndiff has illegal values set to zero | ||
4579 | ndiff(new_bank)=min_energy; | 4463 | ndiff(new_bank)=min_energy; | ||
4580 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | 4464 | idx(tap_bk*(k-1)+1:tap_bk*k)=new_bank; | ||
4581 | if ~isempty(badV) | 4465 | if ~isempty(badV) | ||
4582 | ndiff(badV)=min_energy; | 4466 | ndiff(badV)=min_energy; | ||
4583 | end | 4467 | end | ||
4584 | end | 4468 | end | ||
4585 | 4469 | ||||
4586 | 4470 | ||||
4587 | idx=idx+idx_st-1; | 4471 | idx=idx+idx_st-1; | ||
4588 | function [tap_loc,tap_coef,hisi,b]=floatingDFE( hisi, N_b, N_bf, N_bg, N_bmax, bmaxg, curval, dfe_delta) | 4472 | function [tap_loc,tap_coef,hisi,b]=floatingDFE( hisi, N_b, N_bf, N_bg, N_bmax, bmaxg, curval, dfe_delta) | ||
4589 | 4473 | ||||
4590 | % hisi = postcursor isi | 4474 | % hisi = postcursor isi | ||
4591 | % N_b = number of fixed dfe taps (before floating taps begin) | 4475 | % N_b = number of fixed dfe taps (before floating taps begin) | ||
4592 | % N_bf = number of floating taps per group | 4476 | % N_bf = number of floating taps per group | ||
4593 | % N_bg = nubmber of groups | 4477 | % N_bg = nubmber of groups | ||
4594 | % N_bmax = max tap number that can be used for floating tap | 4478 | % N_bmax = max tap number that can be used for floating tap | ||
4595 | % bmaxg = max tap strength for floating taps | 4479 | % bmaxg = max tap strength for floating taps | ||
4596 | % curval = value of the cursor | 4480 | % curval = value of the cursor | ||
4597 | 4481 | ||||
4598 | 4482 | ||||
4599 | if nargin<8, dfe_delta=0;end | 4483 | if nargin<8, dfe_delta=0;end | ||
4600 | 4484 | ||||
4601 | 4485 | ||||
4602 | tap_coef=zeros(1,length(hisi)); | 4486 | tap_coef=zeros(1,length(hisi)); | ||
4603 | b=zeros(1,length(hisi)); | 4487 | b=zeros(1,length(hisi)); | ||
4604 | 4488 | ||||
4605 | 4489 | ||||
4606 | [tap_loc]=findbankloc(hisi,N_b+1,N_bmax,N_bf,curval,bmaxg,N_bg); | 4490 | [tap_loc]=findbankloc(hisi,N_b+1,N_bmax,N_bf,curval,bmaxg,N_bg); | ||
4607 | 4491 | ||||
4608 | %Apply DFE to all taps | 4492 | %Apply DFE to all taps | ||
4609 | flt_curval=hisi(tap_loc); | 4493 | flt_curval=hisi(tap_loc); | ||
4610 | if dfe_delta~=0 | 4494 | if dfe_delta~=0 | ||
4611 | flt_curval_q=floor(abs(flt_curval/curval)./dfe_delta) .* ... | 4495 | flt_curval_q=floor(abs(flt_curval/curval)./dfe_delta) .* ... | ||
4612 | dfe_delta.*sign(flt_curval)*curval; | 4496 | dfe_delta.*sign(flt_curval)*curval; | ||
4613 | else | 4497 | else | ||
4614 | flt_curval_q=hisi(tap_loc); | 4498 | flt_curval_q=hisi(tap_loc); | ||
4615 | end | 4499 | end | ||
4616 | applied_coef=min(abs(flt_curval_q/curval),bmaxg).*sign(flt_curval_q); | 4500 | applied_coef=min(abs(flt_curval_q/curval),bmaxg).*sign(flt_curval_q); | ||
4617 | hisi(tap_loc)= hisi(tap_loc) - curval*applied_coef; | 4501 | hisi(tap_loc)= hisi(tap_loc) - curval*applied_coef; | ||
4618 | tap_coef(tap_loc)=applied_coef; | 4502 | tap_coef(tap_loc)=applied_coef; | ||
4619 | 4503 | ||||
4620 | 4504 | ||||
4621 | 4505 | ||||
4622 | tap_loc=sort(tap_loc,'ascend'); | 4506 | tap_loc=sort(tap_loc,'ascend'); | ||
4623 | b(tap_loc)=bmaxg; | 4507 | b(tap_loc)=bmaxg; | ||
4624 | function [ bmax floating_tap_locations] = floating_taps_1sttest( hisi,N_b,N_bf,N_bg,N_bmax, bmaxg, COOP ) | 4508 | function [ bmax floating_tap_locations] = floating_taps_1sttest( hisi,N_b,N_bf,N_bg,N_bmax, bmaxg, COOP ) | ||
4625 | % Richard Mellitz: 04/23/2019 | 4509 | % Richard Mellitz: 04/23/2019 | ||
4626 | % hisi is the isi 1 ui/sample | 4510 | % hisi is the isi 1 ui/sample | ||
4627 | % N_b number of fixed dfe taps | 4511 | % N_b number of fixed dfe taps | ||
4628 | % N_bf number of floating taps per group | 4512 | % N_bf number of floating taps per group | ||
4629 | % N_bg number of floating tap groups. 1 2 or 3 right now | 4513 | % N_bg number of floating tap groups. 1 2 or 3 right now | ||
4630 | % N_bmax number of ui for the max reach of the floating taps | 4514 | % N_bmax number of ui for the max reach of the floating taps | ||
4631 | % bmaxg limit for the floating taps | 4515 | % bmaxg limit for the floating taps | ||
4632 | % COOP = 1 co-optimize banks , -0 sequenatial optmization | 4516 | % COOP = 1 co-optimize banks , -0 sequenatial optmization | ||
4633 | % | 4517 | % | ||
4634 | % | 4518 | % | ||
4635 | % function to remove isi or add noise above bmaxg | 4519 | % function to remove isi or add noise above bmaxg | ||
4636 | if ~exist('COOP','var'), COOP=0;end | 4520 | if ~exist('COOP','var'), COOP=0;end | ||
4637 | if iscolumn(hisi); hisi=hisi.';end | 4521 | if iscolumn(hisi); hisi=hisi.';end | ||
4638 | hsis_in=hisi; | 4522 | hsis_in=hisi; | ||
4639 | % find all the reduction group taken N_bf at a time | 4523 | % find all the reduction group taken N_bf at a time | ||
4640 | % we are looking for the group when when remove yield the miminim isi, h, power | 4524 | % we are looking for the group when when remove yield the miminim isi, h, power | ||
4641 | best_sigma=inf;best_ig1=-1;best_ig2=-1;best_ig3=-1; | 4525 | best_sigma=inf;best_ig1=-1;best_ig2=-1;best_ig3=-1; | ||
4642 | % add on switch and loop for each potential group | 4526 | % add on switch and loop for each potential group | ||
4643 | switch N_bg | 4527 | switch N_bg | ||
4644 | case 0 | 4528 | case 0 | ||
4645 | bmax=0; | 4529 | bmax=0; | ||
4646 | return | 4530 | return | ||
4647 | case 1 | 4531 | case 1 | ||
4648 | end1=N_bmax-N_bf; | 4532 | end1=N_bmax-N_bf; | ||
4649 | end2=N_b+1; | 4533 | end2=N_b+1; | ||
4650 | end3=N_b+1; | 4534 | end3=N_b+1; | ||
4651 | case 2 | 4535 | case 2 | ||
4652 | end1=N_bmax-N_bf; | 4536 | end1=N_bmax-N_bf; | ||
4653 | end2=N_bmax-N_bf; | 4537 | end2=N_bmax-N_bf; | ||
4654 | end3=N_b+1; | 4538 | end3=N_b+1; | ||
4655 | case 3 | 4539 | case 3 | ||
4656 | end1=N_bmax-N_bf; | 4540 | end1=N_bmax-N_bf; | ||
4657 | end2=N_bmax-N_bf; | 4541 | end2=N_bmax-N_bf; | ||
4658 | end3=N_bmax-N_bf; | 4542 | end3=N_bmax-N_bf; | ||
4659 | end | 4543 | end | ||
4660 | if COOP | 4544 | if COOP | ||
4661 | for ig1= N_b+1:end1 % now remove the 2nd group | 4545 | for ig1= N_b+1:end1 % now remove the 2nd group | ||
4662 | hcap= hrem(hisi,ig1,N_bf,bmaxg) ; | 4546 | hcap= hrem(hisi,ig1,N_bf,bmaxg) ; | ||
4663 | % loop for 2rd group | 4547 | % loop for 2rd group | ||
4664 | for ig2= N_b+1: end2 | 4548 | for ig2= N_b+1: end2 | ||
4665 | hcap2= hrem(hcap,ig2,N_bf,bmaxg) ; | 4549 | hcap2= hrem(hcap,ig2,N_bf,bmaxg) ; | ||
4666 | if N_bg < 2; hcap2 =hcap; end | 4550 | if N_bg < 2; hcap2 =hcap; end | ||
4667 | for ig3= N_b+1: end3 | 4551 | for ig3= N_b+1: end3 | ||
4668 | hcap3= hrem(hcap2,ig3,N_bf,bmaxg) ; | 4552 | hcap3= hrem(hcap2,ig3,N_bf,bmaxg) ; | ||
4669 | if N_bg < 3 ; hcap3=hcap2 ; end | 4553 | if N_bg < 3 ; hcap3=hcap2 ; end | ||
4670 | sigma=norm( hcap3 ); | 4554 | sigma=norm( hcap3 ); | ||
4671 | if sigma < best_sigma | 4555 | if sigma < best_sigma | ||
4672 | best_sigma=sigma; | 4556 | best_sigma=sigma; | ||
4673 | best_ig1=ig1; | 4557 | best_ig1=ig1; | ||
4674 | best_ig2=ig2; | 4558 | best_ig2=ig2; | ||
4675 | best_ig3=ig3; | 4559 | best_ig3=ig3; | ||
4676 | best_hcap=hcap3; | 4560 | best_hcap=hcap3; | ||
4677 | end | 4561 | end | ||
4678 | end | 4562 | end | ||
4679 | end | 4563 | end | ||
4680 | end | 4564 | end | ||
4681 | else % sequentail | 4565 | else % sequentail | ||
4682 | for ig1= N_b+1:end1 % now remove the 1st group | 4566 | for ig1= N_b+1:end1 % now remove the 1st group | ||
4683 | hcap= hrem(hisi,ig1,N_bf,bmaxg) ; | 4567 | hcap= hrem(hisi,ig1,N_bf,bmaxg) ; | ||
4684 | sigma=norm( hcap ); | 4568 | sigma=norm( hcap ); | ||
4685 | if sigma < best_sigma | 4569 | if sigma < best_sigma | ||
4686 | best_sigma=sigma; | 4570 | best_sigma=sigma; | ||
4687 | best_ig1=ig1; | 4571 | best_ig1=ig1; | ||
4688 | best_hcap=hcap; | 4572 | best_hcap=hcap; | ||
4689 | end | 4573 | end | ||
4690 | end | 4574 | end | ||
4691 | % loop for 2rd group | 4575 | % loop for 2rd group | ||
4692 | hisi=best_hcap; | 4576 | hisi=best_hcap; | ||
4693 | for ig2= N_b+1: end2 | 4577 | for ig2= N_b+1: end2 | ||
4694 | hcap= hrem(hisi,ig2,N_bf,bmaxg) ; | 4578 | hcap= hrem(hisi,ig2,N_bf,bmaxg) ; | ||
4695 | sigma=norm( hcap ); | 4579 | sigma=norm( hcap ); | ||
4696 | if sigma < best_sigma | 4580 | if sigma < best_sigma | ||
4697 | best_sigma=sigma; | 4581 | best_sigma=sigma; | ||
4698 | best_ig2=ig2; | 4582 | best_ig2=ig2; | ||
4699 | best_hcap=hcap; | 4583 | best_hcap=hcap; | ||
4700 | end | 4584 | end | ||
4701 | end | 4585 | end | ||
4702 | hisi=best_hcap; | 4586 | hisi=best_hcap; | ||
4703 | % loop for 3rd group | 4587 | % loop for 3rd group | ||
4704 | for ig3= N_b+1: end3 | 4588 | for ig3= N_b+1: end3 | ||
4705 | hcap= hrem(hisi, ig3,N_bf,bmaxg) ; | 4589 | hcap= hrem(hisi, ig3,N_bf,bmaxg) ; | ||
4706 | sigma=norm( hcap ); | 4590 | sigma=norm( hcap ); | ||
4707 | if sigma < best_sigma | 4591 | if sigma < best_sigma | ||
4708 | best_sigma=sigma; | 4592 | best_sigma=sigma; | ||
4709 | best_ig3=ig3; | 4593 | best_ig3=ig3; | ||
4710 | best_hcap=hcap; | 4594 | best_hcap=hcap; | ||
4711 | end | 4595 | end | ||
4712 | end | 4596 | end | ||
4713 |
| 4597 |
| ||
4714 | end | 4598 | end | ||
4715 | bmax(N_b+1:N_bmax)=zeros(1,N_bmax-N_b); | 4599 | bmax(N_b+1:N_bmax)=zeros(1,N_bmax-N_b); | ||
4716 | switch N_bg | 4600 | switch N_bg | ||
4717 | case 1 | 4601 | case 1 | ||
4718 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | 4602 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4719 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1]; | 4603 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1]; | ||
4720 | case 2 | 4604 | case 2 | ||
4721 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | 4605 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4722 | bmax(best_ig2:best_ig2+N_bf-1)=ones(1,N_bf)*bmaxg; | 4606 | bmax(best_ig2:best_ig2+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4723 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1 best_ig2:best_ig2+N_bf-1 ]; | 4607 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1 best_ig2:best_ig2+N_bf-1 ]; | ||
4724 | case 3 | 4608 | case 3 | ||
4725 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | 4609 | bmax(best_ig1:best_ig1+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4726 | bmax(best_ig2:best_ig2+N_bf-1)=ones(1,N_bf)*bmaxg; | 4610 | bmax(best_ig2:best_ig2+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4727 | bmax(best_ig3:best_ig3+N_bf-1)=ones(1,N_bf)*bmaxg; | 4611 | bmax(best_ig3:best_ig3+N_bf-1)=ones(1,N_bf)*bmaxg; | ||
4728 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1 best_ig2:best_ig2+N_bf-1 best_ig3:best_ig3+N_bf-1 ]; | 4612 | floating_tap_locations= [best_ig1:best_ig1+N_bf-1 best_ig2:best_ig2+N_bf-1 best_ig3:best_ig3+N_bf-1 ]; | ||
4729 | end | 4613 | end | ||
4730 | floating_tap_locations=sort(floating_tap_locations); | 4614 | floating_tap_locations=sort(floating_tap_locations); | ||
4731 | if 0 % for code debug | 4615 | if 0 % for code debug | ||
4732 | close force all | 4616 | close force all | ||
4733 | stem(best_hcap,'disp','hcap') | 4617 | stem(best_hcap,'disp','hcap') | ||
4734 | hold on | 4618 | hold on | ||
4735 | stem(bmax,'-k','disp','bmax') | 4619 | stem(bmax,'-k','disp','bmax') | ||
4736 | stem(hisi,'disp','hisi') | 4620 | stem(hisi,'disp','hisi') | ||
4737 | hold off | 4621 | hold off | ||
4738 | end | 4622 | end | ||
4739 | 4623 | ||||
4740 | % function [ bmax floating_tap_locations] = floating_taps( hisi, N_b, N_bf, N_bg, N_bmax, bmaxg. COO)) | 4624 | % function [ bmax floating_tap_locations] = floating_taps( hisi, N_b, N_bf, N_bg, N_bmax, bmaxg. COO)) | ||
4741 | function [ Vfiltered, Cmod, idx ]= force( V ,param, OP , ix, C, return_V, chdata, txffe, Noise_XC) | 4625 | function [ Vfiltered, Cmod, idx ]= force( V ,param, OP , ix, C, return_V, chdata, txffe, Noise_XC) | ||
4742 | % Vfilter is vector forced filtered sbr | 4626 | % Vfilter is vector forced filtered sbr | ||
4743 | % Cmod is the ffe tap co-efficient vector | 4627 | % Cmod is the ffe tap co-efficient vector | ||
4744 | % if C is passed, just process V with C else compute C | 4628 | % if C is passed, just process V with C else compute C | ||
4745 | % cmx=param.rx_cmx; number of pre cursor taps | 4629 | % cmx=param.rx_cmx; number of pre cursor taps | ||
4746 | % cpx=param.rx_cps; number of post cursor taps | 4630 | % cpx=param.rx_cps; number of post cursor taps | ||
4747 | % V=sbr; pass pulse response | 4631 | % V=sbr; pass pulse response | ||
4748 | % ix the sample point in the passed pulse response | 4632 | % ix the sample point in the passed pulse response | ||
4749 | % the sample point is recomputed by optimize_fom | 4633 | % the sample point is recomputed by optimize_fom | ||
4750 | % idx - return floating tap location (RIM 9-19-2023) | 4634 | % idx - return floating tap location (RIM 9-19-2023) | ||
4751 | % OP not used for now | 4635 | % OP not used for now | ||
4752 | %return_V is a flag with default value = 1. If 0, Vfiltered is not returned | 4636 | %return_V is a flag with default value = 1. If 0, Vfiltered is not returned | ||
4753 | % this allows significant speed up in optimize_fom since FFE is time consuming | 4637 | % this allows significant speed up in optimize_fom since FFE is time consuming | ||
4754 | % and many combinatiFons of "Cmod" result in illegal combinations that do not need | 4638 | % and many combinatiFons of "Cmod" result in illegal combinations that do not need | ||
4755 | % Vfiltered to be calculated | 4639 | % Vfiltered to be calculated | ||
4756 | % test with load('SBR_FIR_resp.mydata','-mat') | 4640 | % test with load('SBR_FIR_resp.mydata','-mat') | ||
4757 | idx=[]; | 4641 | idx=[]; | ||
4758 | if nargin<4 | 4642 | if nargin<4 | ||
4759 | ix=find(V==max(V),1,'first'); | 4643 | ix=find(V==max(V),1,'first'); | ||
4760 | end | 4644 | end | ||
4761 | if nargin<5 | 4645 | if nargin<5 | ||
4762 | C=[]; | 4646 | C=[]; | ||
4763 | end | 4647 | end | ||
4764 | if nargin<6 | 4648 | if nargin<6 | ||
4765 | return_V=1; | 4649 | return_V=1; | ||
4766 | end | 4650 | end | ||
4767 | cmx=param.RxFFE_cmx; | 4651 | cmx=param.RxFFE_cmx; | ||
4768 | cpx=param.RxFFE_cpx; | 4652 | cpx=param.RxFFE_cpx; | ||
4769 | % do this early on so we can reuse the old code | 4653 | % do this early on so we can reuse the old code | ||
4770 | if param.N_bg ~=0 % must be floating taps | 4654 | if param.N_bg ~=0 % must be floating taps | ||
4771 | cpx=param.N_bmax; % N_f in spreadsheet | 4655 | cpx=param.N_bmax; % N_f in spreadsheet | ||
4772 | end | 4656 | end | ||
4773 | num_taps=cmx+cpx+1; | 4657 | num_taps=cmx+cpx+1; | ||
4774 | cstep=param.RxFFE_stepz; | 4658 | cstep=param.RxFFE_stepz; | ||
4775 | ndfe=param.ndfe; | 4659 | ndfe=param.ndfe; | ||
4776 | spui=param.samples_per_ui; | 4660 | spui=param.samples_per_ui; | ||
4777 | param.current_ffegain=0; | 4661 | param.current_ffegain=0; | ||
4778 | if return_V && ~isempty(C) | 4662 | if return_V && ~isempty(C) | ||
4779 | % RIM 2-3-23 when we just want to EQ not find EQ | 4663 | % RIM 2-3-23 when we just want to EQ not find EQ | ||
4780 | Vfiltered=FFE( C , param.RxFFE_cmx,spui, V ); | 4664 | Vfiltered=FFE( C , param.RxFFE_cmx,spui, V ); | ||
4781 | Cmod=C; | 4665 | Cmod=C; | ||
4782 | return | 4666 | return | ||
4783 | end | 4667 | end | ||
4784 | % Aling V to ix ( the sample point) and then create the sampled vector vsampled_raw | 4668 | % Aling V to ix ( the sample point) and then create the sampled vector vsampled_raw | ||
4785 | if ix < length(V) | 4669 | if ix < length(V) | ||
4786 | if isrow(V) | 4670 | if isrow(V) | ||
4787 | if mod(ix,spui) == 0 | 4671 | if mod(ix,spui) == 0 | ||
4788 | vsampled_raw = [V(spui+mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1)))'; V(ix:spui:end)']; | 4672 | vsampled_raw = [V(spui+mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1)))'; V(ix:spui:end)']; | ||
4789 | else | 4673 | else | ||
4790 | vsampled_raw = [V(mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1)))'; V(ix:spui:end)']; | 4674 | vsampled_raw = [V(mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1)))'; V(ix:spui:end)']; | ||
4791 | end | 4675 | end | ||
4792 | 4676 | ||||
4793 | else | 4677 | else | ||
4794 | if mod(ix,spui) == 0 | 4678 | if mod(ix,spui) == 0 | ||
4795 | vsampled_raw = [V(spui+mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1))); V(ix:spui:end)]; | 4679 | vsampled_raw = [V(spui+mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1))); V(ix:spui:end)]; | ||
4796 | else | 4680 | else | ||
4797 | vsampled_raw = [V(mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1))); V(ix:spui:end)]; | 4681 | vsampled_raw = [V(mod(ix,spui):spui:(mod(ix,spui)+spui*(floor(ix/spui)-1))); V(ix:spui:end)]; | ||
4798 | end | 4682 | end | ||
4799 | end | 4683 | end | ||
4800 | else | 4684 | else | ||
4801 | if isrow(V) | 4685 | if isrow(V) | ||
4802 | if mod(ix,spui) == 0%Yasou Hidaka 11/16/2018 | 4686 | if mod(ix,spui) == 0%Yasou Hidaka 11/16/2018 | ||
4803 | vsampled_raw = V(spui+mod(ix,spui):spui:end)';%Yasou Hidaka 11/16/2018 | 4687 | vsampled_raw = V(spui+mod(ix,spui):spui:end)';%Yasou Hidaka 11/16/2018 | ||
4804 | else | 4688 | else | ||
4805 | vsampled_raw = V(mod(ix,spui):spui:end)';%Yasou Hidaka 11/16/2018 | 4689 | vsampled_raw = V(mod(ix,spui):spui:end)';%Yasou Hidaka 11/16/2018 | ||
4806 | end | 4690 | end | ||
4807 | else | 4691 | else | ||
4808 | if mod(ix,spui) == 0%Yasou Hidaka 11/16/2018 | 4692 | if mod(ix,spui) == 0%Yasou Hidaka 11/16/2018 | ||
4809 | vsampled_raw = V(spui+mod(ix,spui):spui:end) ; | 4693 | vsampled_raw = V(spui+mod(ix,spui):spui:end) ; | ||
4810 | else | 4694 | else | ||
4811 | vsampled_raw = V(mod(ix,spui):spui:end) ;%Yasou Hidaka 11/16/2018 | 4695 | vsampled_raw = V(mod(ix,spui):spui:end) ;%Yasou Hidaka 11/16/2018 | ||
4812 | end | 4696 | end | ||
4813 | end | 4697 | end | ||
4814 | end | 4698 | end | ||
4815 | % zero pad vsampled to account for PR with short delay. RIM 10-02-2023 | 4699 | % zero pad vsampled to account for PR with short delay. RIM 10-02-2023 | ||
4816 | vsampled=[zeros(1,num_taps) vsampled_raw' zeros(1,cpx)];% pad for pre and post cursor prior to shifting | 4700 | vsampled=[zeros(1,num_taps) vsampled_raw' zeros(1,cpx)];% pad for pre and post cursor prior to shifting | ||
4817 | 4701 | ||||
4818 | %% find the index, ivs, for the sample point but in the UI resample vector, vsampled | 4702 | %% find the index, ivs, for the sample point but in the UI resample vector, vsampled | ||
4819 | % ivs=find(vsampled==V(ix),1,'first');% ivs is the sample point for V | 4703 | % ivs=find(vsampled==V(ix),1,'first');% ivs is the sample point for V | ||
4820 | % Upen Kareti suggested fix for indexing 11/04/18 | 4704 | % Upen Kareti suggested fix for indexing 11/04/18 | ||
4821 | if ix < length(V) | 4705 | if ix < length(V) | ||
4822 | ivs=find(vsampled==V(ix),1,'first');% ivs is the sample point for V | 4706 | ivs=find(vsampled==V(ix),1,'first');% ivs is the sample point for V | ||
4823 | else | 4707 | else | ||
4824 | ivs=find(vsampled == max(vsampled),1,'first'); | 4708 | ivs=find(vsampled == max(vsampled),1,'first'); | ||
4825 | end | 4709 | end | ||
4826 | 4710 | ||||
4827 | 4711 | ||||
4828 | %% create VV matrix of shifted UI spaced sample of the pulse response | 4712 | %% create VV matrix of shifted UI spaced sample of the pulse response | ||
4829 | % only consider the VV matrix that correstonds to the FFE taps | 4713 | % only consider the VV matrix that correstonds to the FFE taps | ||
4830 | VV=zeros(num_taps,num_taps); | 4714 | VV=zeros(num_taps,num_taps); | ||
4831 | for i=1:num_taps | 4715 | for i=1:num_taps | ||
4832 | start_idx=ivs+i-1; | 4716 | start_idx=ivs+i-1; | ||
4833 | end_idx=start_idx-num_taps+1; | 4717 | end_idx=start_idx-num_taps+1; | ||
4834 | VV(:,i)=vsampled(start_idx:-1:end_idx); | 4718 | VV(:,i)=vsampled(start_idx:-1:end_idx); | ||
4835 | end | 4719 | end | ||
4836 | % may want to test VV*VV' for rcond here not sure what value to use but 1e-5 is always bad | 4720 | % may want to test VV*VV' for rcond here not sure what value to use but 1e-5 is always bad | ||
4837 | %% Apply RXFFE | 4721 | %% Apply RXFFE | ||
4838 | if isempty(C) | 4722 | if isempty(C) | ||
4839 | switch upper(OP.FFE_OPT_METHOD) | 4723 | switch upper(OP.FFE_OPT_METHOD) | ||
4840 | case 'WIENER-HOPF' | 4724 | case 'WIENER-HOPF' | ||
4841 | C= WIENER_HOPF_MMSE(vsampled ,param, OP , chdata, txffe, Noise_XC,ivs) ; | 4725 | C= WIENER_HOPF_MMSE(vsampled ,param, OP , chdata, txffe, Noise_XC,ivs) ; | ||
4842 | Cmod=C(1:num_taps); | 4726 | Cmod=C(1:num_taps); | ||
4843 | otherwise | 4727 | otherwise | ||
4844 | % cmx+1 is the cursor or sample point | 4728 | % cmx+1 is the cursor or sample point | ||
4845 | %VV=VV(:,ivs-cmx:ivs+cpx); % only consider the VV matrix that correstonds to the FFE taps | 4729 | %VV=VV(:,ivs-cmx:ivs+cpx); % only consider the VV matrix that correstonds to the FFE taps | ||
4846 | FV=zeros(1,num_taps); % zero the forceing vector, FV first | 4730 | FV=zeros(1,num_taps); % zero the forceing vector, FV first | ||
4847 | FV(cmx+1)=vsampled(ivs)*10^(param.current_ffegain/20); % force the voltage at sample point | 4731 | FV(cmx+1)=vsampled(ivs)*10^(param.current_ffegain/20); % force the voltage at sample point | ||
4848 | if param.ndfe~=0 && (cpx > 0) % Yasuo Hidaka suggest fix for no postC 11/11/18 | 4732 | if param.ndfe~=0 && (cpx > 0) % Yasuo Hidaka suggest fix for no postC 11/11/18 | ||
4849 | % FV(cmx+2)=param.bmax(1)*FV(cmx+1); % force the post cursor to bmax if dfe exists | 4733 | % FV(cmx+2)=param.bmax(1)*FV(cmx+1); % force the post cursor to bmax if dfe exists | ||
4850 | FV(cmx+2)=min(param.bmax(1)*FV(cmx+1),abs(vsampled(ivs+1)))*sign(vsampled(ivs+1)); | 4734 | FV(cmx+2)=min(param.bmax(1)*FV(cmx+1),abs(vsampled(ivs+1)))*sign(vsampled(ivs+1)); | ||
4851 | end | 4735 | end | ||
4852 | %C=((VV'*VV)^-1*VV')'*FV'; % sikve for FFE taps, C | 4736 | %C=((VV'*VV)^-1*VV')'*FV'; % sikve for FFE taps, C | ||
4853 | if diff(size(VV))==0 | 4737 | if diff(size(VV))==0 | ||
4854 | %For square matrix, can solve C using simple inv(VV')*FV' | 4738 | %For square matrix, can solve C using simple inv(VV')*FV' | ||
4855 | C=VV'\FV'; | 4739 | C=VV'\FV'; | ||
4856 | else | 4740 | else | ||
4857 | %otherwise use the general solution with psuedo inverse | 4741 | %otherwise use the general solution with psuedo inverse | ||
4858 | %note: this is the same as doing pinv(VV') but pinv is far slower | 4742 | %note: this is the same as doing pinv(VV') but pinv is far slower | ||
4859 | % C=(inv(VV'*VV)*VV')'*FV'; % sikve for FFE taps, C | 4743 | % C=(inv(VV'*VV)*VV')'*FV'; % sikve for FFE taps, C | ||
4860 | C=(inv(VV*VV')*VV)*FV'; % sikve for FFE taps, C | 4744 | C=(inv(VV*VV')*VV)*FV'; % sikve for FFE taps, C | ||
4861 | end | 4745 | end | ||
4862 | 4746 | ||||
4863 | Cmod=C(1:num_taps); | 4747 | Cmod=C(1:num_taps); | ||
4864 | end | 4748 | end | ||
4865 | 4749 | ||||
4866 | 4750 | ||||
4867 | % added for 4.2 find floating taps with either ISI or taps | 4751 | % added for 4.2 find floating taps with either ISI or taps | ||
4868 | switch lower(OP.RXFFE_FLOAT_CTL) | 4752 | switch lower(OP.RXFFE_FLOAT_CTL) | ||
4869 | case 'taps' | 4753 | case 'taps' | ||
4870 | [idx]=findbankloc(Cmod,param.N_tail_start,param.N_bmax,param.N_bf,Cmod(cmx+1),param.bmaxg,param.N_bg); | 4754 | [idx]=findbankloc(Cmod,param.N_tail_start,param.N_bmax,param.N_bf,Cmod(cmx+1),param.bmaxg,param.N_bg); | ||
4871 | otherwise | 4755 | otherwise | ||
4872 | [idx]=findbankloc(VV(cmx+1,:),param.N_tail_start,param.N_bmax,param.N_bf,Cmod(cmx+1),param.bmaxg,param.N_bg); | 4756 | [idx]=findbankloc(VV(cmx+1,:),param.N_tail_start,param.N_bmax,param.N_bf,Cmod(cmx+1),param.bmaxg,param.N_bg); | ||
4873 | end | 4757 | end | ||
4874 | switch lower(OP.RXFFE_TAP_CONSTRAINT) | 4758 | switch lower(OP.RXFFE_TAP_CONSTRAINT) | ||
4875 | case 'unity cursor' | 4759 | case 'unity cursor' | ||
4876 | Cmod=Cmod/Cmod(cmx+1); | 4760 | Cmod=Cmod/Cmod(cmx+1); | ||
4877 | otherwise | 4761 | otherwise | ||
4878 | Cmod=C; | 4762 | Cmod=C; | ||
4879 | end | 4763 | end | ||
4880 | if cstep ~= 0 | 4764 | if cstep ~= 0 | ||
4881 | Cmod=floor(abs(Cmod/cstep)).*sign(Cmod)*cstep;% r250 quantize with floor ad sign(C) | 4765 | Cmod=floor(abs(Cmod/cstep)).*sign(Cmod)*cstep;% r250 quantize with floor ad sign(C) | ||
4882 | end | 4766 | end | ||
4883 | 4767 | ||||
4884 | if ~isempty(idx) | 4768 | if ~isempty(idx) | ||
4885 | idx=sort(idx); | 4769 | idx=sort(idx); | ||
4886 | C1=Cmod; | 4770 | C1=Cmod; | ||
4887 | % C1(param.N_tail_start:end)=0; | 4771 | % C1(param.N_tail_start:end)=0; | ||
4888 | C1(param.RxFFE_cmx+param.RxFFE_cpx+2:end)=0; % zero out flosting taps | 4772 | C1(param.RxFFE_cmx+param.RxFFE_cpx+2:end)=0; % zero out flosting taps | ||
4889 | C1(cmx+1+idx)=Cmod(cmx+1+idx); | 4773 | C1(cmx+1+idx)=Cmod(cmx+1+idx); | ||
4890 | Cmod=C1; | 4774 | Cmod=C1; | ||
4891 | else | 4775 | else | ||
4892 | % Cmod=C; | 4776 | % Cmod=C; | ||
4893 | end | 4777 | end | ||
4894 | 4778 | ||||
4895 | % now when ussing RxFFE floating taps need to tag stems correctly and | 4779 | % now when ussing RxFFE floating taps need to tag stems correctly and | ||
4896 | % make sure DFEfloating tap code does not get exectuted | 4780 | % make sure DFEfloating tap code does not get exectuted | ||
4897 | 4781 | ||||
4898 | % | 4782 | % | ||
4899 | else | 4783 | else | ||
4900 | Cmod=C;%just us the FFE taps, C, passed for filtering | 4784 | Cmod=C;%just us the FFE taps, C, passed for filtering | ||
4901 | end | 4785 | end | ||
4902 | %% | 4786 | %% | ||
4903 | %% filter the pulse response with the solved FFE | 4787 | %% filter the pulse response with the solved FFE | ||
4904 | % (now option to avoid this and just return Cmod for speed up) | 4788 | % (now option to avoid this and just return Cmod for speed up) | ||
4905 | if return_V | 4789 | if return_V | ||
4906 | Vfiltered=FFE( Cmod , param.RxFFE_cmx,spui, V ); | 4790 | Vfiltered=FFE( Cmod , param.RxFFE_cmx,spui, V ); | ||
4907 | else | 4791 | else | ||
4908 | Vfiltered=[]; | 4792 | Vfiltered=[]; | ||
4909 | end | 4793 | end | ||
4910 | function [ILN, efit]= get_ILN(sdd21,faxis_f2) | 4794 | function [ILN, efit]= get_ILN(sdd21,faxis_f2) | ||
4911 | % used for FD IL fitting | 4795 | % used for FD IL fitting | ||
4912 | % sdd21 us a complex insertion loss | 4796 | % sdd21 us a complex insertion loss | ||
4913 | db = @(x) 20*log10(abs(x)); | 4797 | db = @(x) 20*log10(abs(x)); | ||
4914 | sdd21=squeeze(sdd21); | 4798 | sdd21=squeeze(sdd21); | ||
4915 | if iscolumn(sdd21) | 4799 | if iscolumn(sdd21) | ||
4916 | sdd21=sdd21.'; | 4800 | sdd21=sdd21.'; | ||
4917 | end | 4801 | end | ||
4918 | fmbg=[ones(length(faxis_f2),1).*transpose(abs(sdd21)) transpose(sqrt(faxis_f2)).*transpose(abs(sdd21)) transpose(faxis_f2).*transpose(abs(sdd21)) transpose(faxis_f2.^2).*transpose(abs(sdd21)) ]; | 4802 | fmbg=[ones(length(faxis_f2),1).*transpose(abs(sdd21)) transpose(sqrt(faxis_f2)).*transpose(abs(sdd21)) transpose(faxis_f2).*transpose(abs(sdd21)) transpose(faxis_f2.^2).*transpose(abs(sdd21)) ]; | ||
4919 | warning('off','MATLAB:nearlySingularMatrix'); | 4803 | warning('off','MATLAB:nearlySingularMatrix'); | ||
4920 | LGw=transpose(abs(sdd21).*db(sdd21)); | 4804 | LGw=transpose(abs(sdd21).*db(sdd21)); | ||
4921 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | 4805 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | ||
4922 | efit=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | 4806 | efit=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | ||
4923 | ILN = db(sdd21)-efit; | 4807 | ILN = db(sdd21)-efit; | ||
4924 | 4808 | ||||
4925 | 4809 | ||||
4926 | function [ILN, efit, TD_ILN]= get_ILN_cmp_td(sdd21,faxis_f2,OP,param,A_T) | 4810 | function [ILN, efit, TD_ILN]= get_ILN_cmp_td(sdd21,faxis_f2,OP,param,A_T) | ||
4927 | % Complex IL fitting | 4811 | % Complex IL fitting | ||
4928 | % sdd21 us a complex insertion loss | 4812 | % sdd21 us a complex insertion loss | ||
4929 | % efit and ILN are in db | 4813 | % efit and ILN are in db | ||
4930 | % faxix_f2 needs to be at least to fb | 4814 | % faxix_f2 needs to be at least to fb | ||
4931 | % return reflections TD_ILN.FOM based on time domain PR fit from pulse peak | 4815 | % return reflections TD_ILN.FOM based on time domain PR fit from pulse peak | ||
4932 | % still need to settle on voltage scaling. | 4816 | % still need to settle on voltage scaling. | ||
4933 | % maybe db(peak/Rss | 4817 | % maybe db(peak/Rss | ||
4934 | 4818 | ||||
4935 | OP.interp_sparam_mag= 'trend_to_DC'; | 4819 | OP.interp_sparam_mag= 'trend_to_DC'; | ||
4936 | OP.interp_sparam_phase= 'interp_to_DC'; | 4820 | OP.interp_sparam_phase= 'interp_to_DC'; | ||
4937 | % OP.interp_sparam_mag= 'linear_trend_to_DC'; | 4821 | % OP.interp_sparam_mag= 'linear_trend_to_DC'; | ||
4938 | % OP.interp_sparam_phase= 'extrap_cubic_to_dc_linear_to_inf'; | 4822 | % OP.interp_sparam_phase= 'extrap_cubic_to_dc_linear_to_inf'; | ||
4939 | 4823 | ||||
4940 | print_for_codereview=0; | 4824 | print_for_codereview=0; | ||
4941 | if ~exist('A_T','var') | 4825 | if ~exist('A_T','var') | ||
4942 | A_T=1; | 4826 | A_T=1; | ||
4943 | end | 4827 | end | ||
4944 | 4828 | ||||
4945 | db = @(x) 20*log10(abs(x)); | 4829 | db = @(x) 20*log10(abs(x)); | ||
4946 | sdd21=squeeze(sdd21); | 4830 | sdd21=squeeze(sdd21); | ||
4947 | if iscolumn(sdd21) | 4831 | if iscolumn(sdd21) | ||
4948 | sdd21=sdd21.'; | 4832 | sdd21=sdd21.'; | ||
4949 | end | 4833 | end | ||
4950 | fmbg=[ones(length(faxis_f2),1).*transpose(sdd21) transpose(sqrt(faxis_f2)).*transpose(sdd21) transpose(faxis_f2).*transpose(sdd21) transpose(faxis_f2.^2).*transpose(sdd21) ]; | 4834 | fmbg=[ones(length(faxis_f2),1).*transpose(sdd21) transpose(sqrt(faxis_f2)).*transpose(sdd21) transpose(faxis_f2).*transpose(sdd21) transpose(faxis_f2.^2).*transpose(sdd21) ]; | ||
4951 | warning('off','MATLAB:nearlySingularMatrix'); | 4835 | warning('off','MATLAB:nearlySingularMatrix'); | ||
4952 | unwraplog=log(abs(sdd21))+1i*unwrap(angle(sdd21)); | 4836 | unwraplog=log(abs(sdd21))+1i*unwrap(angle(sdd21)); | ||
4953 | LGw=transpose(sdd21.*unwraplog); | 4837 | LGw=transpose(sdd21.*unwraplog); | ||
4954 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | 4838 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | ||
4955 | efit_C=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | 4839 | efit_C=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | ||
4956 | FIT=transpose(exp(transpose(efit_C))); | 4840 | FIT=transpose(exp(transpose(efit_C))); | ||
4957 | efit=db(abs(FIT)); | 4841 | efit=db(abs(FIT)); | ||
4958 | ILN = db(sdd21)-efit; | 4842 | ILN = db(sdd21)-efit; | ||
4959 | % time domain | 4843 | % time domain | ||
4960 | fprintf('computing TD_ILN (dB) ...') | 4844 | fprintf('computing TD_ILN (dB) ...') | ||
4961 | if exist('OP','var') | 4845 | if exist('OP','var') | ||
4962 | % OP.fraction_of_F_range_start_extrap_from=.95; | 4846 | % OP.fraction_of_F_range_start_extrap_from=.95; | ||
4963 | OP.impulse_response_truncation_threshold =1e-7; | 4847 | OP.impulse_response_truncation_threshold =1e-7; | ||
4964 |
| 4848 |
| ||
4965 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | 4849 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | ||
4966 | H_bw=Butterworth_Filter(param,faxis_f2,1); | 4850 | H_bw=Butterworth_Filter(param,faxis_f2,1); | ||
4967 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 4851 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
4968 | H_tw=Tukey_Window(faxis_f2,param); | 4852 | H_tw=Tukey_Window(faxis_f2,param); | ||
4969 | H_tw=ones(1,length(faxis_f2) ); | 4853 | H_tw=ones(1,length(faxis_f2) ); | ||
4970 |
| 4854 |
| ||
4971 | [TD_ILN.REF.FIR, ... | 4855 | [TD_ILN.REF.FIR, ... | ||
4972 | TD_ILN.REF.t, ... | 4856 | TD_ILN.REF.t, ... | ||
4973 | TD_ILN.REF.causality_correction_dB, ... | 4857 | TD_ILN.REF.causality_correction_dB, ... | ||
4974 | TD_ILN.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bt.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 4858 | TD_ILN.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bt.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
4975 | TD_ILN.REF.PR=filter(ones(1, param.samples_per_ui), 1, TD_ILN.REF.FIR); | 4859 | TD_ILN.REF.PR=filter(ones(1, param.samples_per_ui), 1, TD_ILN.REF.FIR); | ||
4976 | 4860 | ||||
4977 | [TD_ILN.FIT.FIR, ... | 4861 | [TD_ILN.FIT.FIR, ... | ||
4978 | TD_ILN.FIT.t, ... | 4862 | TD_ILN.FIT.t, ... | ||
4979 | TD_ILN.FIT.causality_correction_dB, ... | 4863 | TD_ILN.FIT.causality_correction_dB, ... | ||
4980 | TD_ILN.FIT.truncation_dB] = s21_to_impulse_DC(FIT.*H_bt.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 4864 | TD_ILN.FIT.truncation_dB] = s21_to_impulse_DC(FIT.*H_bt.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
4981 | TD_ILN.FIT.PR=filter(ones(1, param.samples_per_ui), 1, TD_ILN.FIT.FIR); | 4865 | TD_ILN.FIT.PR=filter(ones(1, param.samples_per_ui), 1, TD_ILN.FIT.FIR); | ||
4982 | ipeak=find(TD_ILN.REF.PR==max(TD_ILN.REF.PR),1,'first'); | 4866 | ipeak=find(TD_ILN.REF.PR==max(TD_ILN.REF.PR),1,'first'); | ||
4983 | % NrangeUI=1000; | 4867 | % NrangeUI=1000; | ||
4984 | % range_end=min(min(ipeak+param.samples_per_ui*NrangeUI,length(TD_ILN.FIT.PR)-param.samples_per_ui ),length(TD_ILN.REF.PR)-param.samples_per_ui); | 4868 | % range_end=min(min(ipeak+param.samples_per_ui*NrangeUI,length(TD_ILN.FIT.PR)-param.samples_per_ui ),length(TD_ILN.REF.PR)-param.samples_per_ui); | ||
4985 | range_end= min(length(TD_ILN.REF.PR), length(TD_ILN.FIT.PR)); | 4869 | range_end= min(length(TD_ILN.REF.PR), length(TD_ILN.FIT.PR)); | ||
4986 | range=ipeak:range_end; | 4870 | range=ipeak:range_end; | ||
4987 | TD_ILN.ILN=TD_ILN.FIT.PR(range)-TD_ILN.REF.PR(range); | 4871 | TD_ILN.ILN=TD_ILN.FIT.PR(range)-TD_ILN.REF.PR(range); | ||
4988 | TD_ILN.t=TD_ILN.FIT.t(range); | 4872 | TD_ILN.t=TD_ILN.FIT.t(range); | ||
4989 | TD_ILN.FOM=-inf; | 4873 | TD_ILN.FOM=-inf; | ||
4990 | TD_ILN.FOM_PDF=-inf; | 4874 | TD_ILN.FOM_PDF=-inf; | ||
4991 | rms_fom=-inf; | 4875 | rms_fom=-inf; | ||
4992 | for im=1:param.samples_per_ui | 4876 | for im=1:param.samples_per_ui | ||
4993 | TD_ILN.FOM=max(TD_ILN.FOM, norm( TD_ILN.ILN(im:param.samples_per_ui:end))); | 4877 | TD_ILN.FOM=max(TD_ILN.FOM, norm( TD_ILN.ILN(im:param.samples_per_ui:end))); | ||
4994 | [ pdf ] = get_pdf_from_sampled_signal( TD_ILN.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | 4878 | [ pdf ] = get_pdf_from_sampled_signal( TD_ILN.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | ||
4995 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | 4879 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | ||
4996 | cdf=pdf; cdf.y=cumsum(pdf.y); | 4880 | cdf=pdf; cdf.y=cumsum(pdf.y); | ||
4997 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | 4881 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | ||
4998 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | 4882 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | ||
4999 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | 4883 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | ||
5000 | if print_for_codereview % remove once all checked out | 4884 | if print_for_codereview % remove once all checked out | ||
5001 | h=figure(190);set(gcf,'Tag','COM'); | 4885 | h=figure(190);set(gcf,'Tag','COM'); | ||
5002 | semilogy(-cdf.x,cdf.y); | 4886 | semilogy(-cdf.x,cdf.y); | ||
5003 | % xlim ([0,-cdf.x(1)]) | 4887 | % xlim ([0,-cdf.x(1)]) | ||
5004 | ylim([param.specBER 1]);title ('CDF of ILN') | 4888 | ylim([param.specBER 1]);title ('CDF of ILN') | ||
5005 | hold on | 4889 | hold on | ||
5006 | end | 4890 | end | ||
5007 | if rms>rms_fom | 4891 | if rms>rms_fom | ||
5008 | rms_fom=rms; | 4892 | rms_fom=rms; | ||
5009 | TD_ILN.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | 4893 | TD_ILN.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | ||
5010 | TD_ILN.PDF=pdf; | 4894 | TD_ILN.PDF=pdf; | ||
5011 | end | 4895 | end | ||
5012 | end | 4896 | end | ||
5013 | pdf_from_norm=normal_dist(TD_ILN.FOM, 7 , OP.BinSize); | 4897 | pdf_from_norm=normal_dist(TD_ILN.FOM, 7 , OP.BinSize); | ||
5014 | TD_ILN.SNR_ISI_FOM=db(TD_ILN.FIT.PR(ipeak)/TD_ILN.FOM); | 4898 | TD_ILN.SNR_ISI_FOM=db(TD_ILN.FIT.PR(ipeak)/TD_ILN.FOM); | ||
5015 | TD_ILN.SNR_ISI_FOM_PDF=db(TD_ILN.FIT.PR(ipeak)/TD_ILN.FOM_PDF); | 4899 | TD_ILN.SNR_ISI_FOM_PDF=db(TD_ILN.FIT.PR(ipeak)/TD_ILN.FOM_PDF); | ||
5016 | % fprintf('%g dB\n',TD_ILN.SNR_ISI_FOM) | 4900 | % fprintf('%g dB\n',TD_ILN.SNR_ISI_FOM) | ||
5017 | fprintf('%g dB\n',TD_ILN.SNR_ISI_FOM_PDF) | 4901 | fprintf('%g dB\n',TD_ILN.SNR_ISI_FOM_PDF) | ||
5018 | if print_for_codereview % remove once all checked out | 4902 | if print_for_codereview % remove once all checked out | ||
5019 | figure(9000);set(gcf,'Tag','COM'); | 4903 | figure(9000);set(gcf,'Tag','COM'); | ||
5020 | plot(TD_ILN.t,TD_ILN.ILN,'disp','td iln') | 4904 | plot(TD_ILN.t,TD_ILN.ILN,'disp','td iln') | ||
5021 | hold on | 4905 | hold on | ||
5022 | plot(TD_ILN.FIT.t,TD_ILN.FIT.PR,'disp','fit') | 4906 | plot(TD_ILN.FIT.t,TD_ILN.FIT.PR,'disp','fit') | ||
5023 | plot(TD_ILN.REF.t,TD_ILN.REF.PR,'disp','ref') | 4907 | plot(TD_ILN.REF.t,TD_ILN.REF.PR,'disp','ref') | ||
5024 | hold off | 4908 | hold off | ||
5025 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',TD_ILN.SNR_ISI_FOM,TD_ILN.SNR_ISI_FOM_PDF) | 4909 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',TD_ILN.SNR_ISI_FOM,TD_ILN.SNR_ISI_FOM_PDF) | ||
5026 | figure(9002);set(gcf,'Tag','COM'); | 4910 | figure(9002);set(gcf,'Tag','COM'); | ||
5027 | semilogy(TD_ILN.PDF.x,TD_ILN.PDF.y,'disp','actual PDF') | 4911 | semilogy(TD_ILN.PDF.x,TD_ILN.PDF.y,'disp','actual PDF') | ||
5028 | hold on | 4912 | hold on | ||
5029 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | 4913 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | ||
5030 | ylim([param.specBER max([TD_ILN.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | 4914 | ylim([param.specBER max([TD_ILN.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | ||
5031 | grid on | 4915 | grid on | ||
5032 | legend('show') | 4916 | legend('show') | ||
5033 | end | 4917 | end | ||
5034 | end | 4918 | end | ||
5035 | % display('got to end of get_ILN_cmp_td') | 4919 | % display('got to end of get_ILN_cmp_td') | ||
5036 | function result = get_PSDs(result,h,cursor_i, txffe,G_DC,G_DC2,param,chdata,OP) | 4920 | function result = get_PSDs(result,h,cursor_i, txffe,G_DC,G_DC2,param,chdata,OP) | ||
− | 5037 | % OP.COMPUTE_COM is when called after the optimization and returns sigma_Gbest_hk |
| ||
5038 | % as well the Sn with the Rx ffe and Hisi included as sigma ISI inclued | ||||
5039 | if 1 % force indent for doc | 4921 | if 1 % force indent for doc | ||
5040 | num_ui=param.num_ui_RXFF_noise; | 4922 | num_ui=param.num_ui_RXFF_noise; | ||
5041 | M=param.samples_per_ui; | 4923 | M=param.samples_per_ui; | ||
5042 | L=param.levels; | 4924 | L=param.levels; | ||
| + | 4925 | sigma_X2=(L^2-1)/(3*(L-1)^2); | ||
5043 | f_b=param.fb; | 4926 | f_b=param.fb; | ||
− | 5044 | SNR_TX=param.SNR_TX; |
| ||
5045 | dw=param.RxFFE_cmx; | ||||
5046 | bmax=param.bmax; | ||||
5047 | bmin=param.bmin ; | ||||
5048 | Nb=param.ndfe; | ||||
5049 | sigma_X2=(L^2-1)/(3*(L-1)^2); | ||||
5050 | eta_0=param.eta_0; %V^2/GHz | ||||
5051 | T_b=1/f_b; | 4927 | T_b=1/f_b; | ||
5052 | delta_f = f_b/num_ui; % Units are Hz. | 4928 | delta_f = f_b/num_ui; % Units are Hz. | ||
5053 | fvec = (0:num_ui*M/2)*delta_f; % Single-sided frequency axis. | 4929 | fvec = (0:num_ui*M/2)*delta_f; % Single-sided frequency axis. | ||
5054 | result.fvec=fvec; | 4930 | result.fvec=fvec; | ||
− | 5055 | end |
| ||
≠ | 5056 | if OP.COMPUTE_COM | ≠ | 4931 | SNR_TX=param.SNR_TX; |
− | 5057 | %% H_rxffe eq 178A-29 d0.2 |
| ||
5058 | % chdata(xchan).ctle_imp_response is conputed with the RxFFE during the COM compuatation | ||||
5059 | % H_rxffe.^2 is distributed S_jn and S_rn since they do not use use chdata(xchan).ctle_imp_response | ||||
5060 | H_rxffe=0; | ||||
≠ | 5061 | for nn=1:length(result.w) | ≠ | 4932 | eta_0=param.eta_0; %V^2/GHz |
− | 5062 | H_rxffe=result.w(nn)*exp(-1j*2*pi*fvec*T_b*(nn-dw-1))+H_rxffe; |
| ||
5063 | end | ||||
5064 | H_rxffe_2_of_f=abs(H_rxffe).^2; | ||||
5065 | H_rxffe_2=H_rxffe_2_of_f(1:num_ui/2+1); | ||||
5066 | H_rxffe_2= [real( H_rxffe_2(1)), H_rxffe_2(2:end-1), real( H_rxffe_2(end)), conj( H_rxffe_2(end-1:-1:2))]; | ||||
5067 | else | ||||
5068 | H_rxffe_2=1; | ||||
5069 | end | 4933 | end | ||
− | 5070 |
| |||
5071 | if OP.WO_TXFFE % to speed up loop find sn onlu first time ctle is case | 4934 | if OP.WO_TXFFE % to speed up loop find sn onlu first time ctle is case | ||
− | 5072 | % --->this is the point in the code may fork where we add extra rx noise |
| ||
≠ | 5073 | %% compute S_rn ( eq 178A-15 d0.2 ) | ≠ | 4935 | %% compute S_rn healey_3dj_01_2401 slide 5 |
− | 5074 | if ~OP.COMPUTE_COM |
| ||
≠ | 5075 | S_RN_of_f=S_RN(fvec,G_DC,G_DC2,param); | ≠ | 4936 | S_RN_of_f=S_RN(fvec,G_DC,G_DC2,param); |
≠ | 5076 | rxn_psd=[real(S_RN_of_f(1)), S_RN_of_f(2:end-1), real(S_RN_of_f(end)), conj(S_RN_of_f(end-1:-1:2))]; % Convert single-sided frequency response to conjugate-symmetric | ≠ | 4937 | rxn_psd=[real(S_RN_of_f(1)), S_RN_of_f(2:end-1), real(S_RN_of_f(end)), conj(S_RN_of_f(end-1:-1:2))]; % Convert single-sided frequency response to conjugate-symmetric |
≠ | 5077 | rxn_psd=rxn_psd/1e9;% Units are V^2/Hz. | ≠ | 4938 | rxn_psd=rxn_psd/1e9;% Units are V^2/Hz. |
≠ | 5078 | rxn_rms = sqrt(sum(rxn_psd)* delta_f); | ≠ | 4939 | rxn_rms = sqrt(sum(rxn_psd)* delta_f); |
≠ | 5079 | S_rn = sum(reshape(rxn_psd, num_ui, M).'); | ≠ | 4940 | S_rn = sum(reshape(rxn_psd, num_ui, M).'); |
≠ | 5080 | S_rn=S_rn(1:num_ui/2+1); | ≠ | 4941 | S_rn=S_rn(1:num_ui/2+1); |
≠ | 5081 | S_rn= [real( S_rn(1)), S_rn(2:end-1), real( S_rn(end)), conj( S_rn(end-1:-1:2))]; | ≠ | 4942 | S_rn= [real( S_rn(1)), S_rn(2:end-1), real( S_rn(end)), conj( S_rn(end-1:-1:2))]; |
| + | 4943 | %rxn_acf_samp = ifft(S_rn)*f_b; % Autocorrelation function. Note that the first term is rxn_rms^2. | ||
4944 | if 0 % for debug | ||||
4945 | figure | ||||
4946 | set(gcf, 'tag', 'COM');movegui(gcf,'northeast'); | ||||
4947 | plot(fvec(1:num_ui)/f_b,10*log10((S_rn)*1000/100) ... | ||||
4948 | ,'disp','Srn') | ||||
4949 | xlim([0 0.5]) | ||||
4950 | ylim([-200 -140]) | ||||
4951 | set(gcf,'defaulttextinterpreter','none') | ||||
4952 | xlabel('Normalized Frequency') | ||||
4953 | ylabel('PSD dBm/Hz') | ||||
4954 | hold on | ||||
4955 | grid on | ||||
4956 | title('PSD') | ||||
4957 | end | ||||
≠ | 5082 | result.S_rn=S_rn; | ≠ | 4958 | result.S_rn=S_rn; |
≠ | 5083 | result.S_rn_rms = sqrt(sum(result.S_rn)* delta_f); | ≠ | 4959 | result.S_rn_rms=rxn_rms; |
− | 5084 | else |
| ||
5085 | result.S_rn=result.S_rn.*H_rxffe_2; | ||||
5086 | result.S_rn_rms = sqrt(sum(result.S_rn)* delta_f); | ||||
5087 | end | ||||
5088 | 4960 | ||||
5089 | else % find noise for item that set have tx ffe for each loop | 4961 | else % find noise for item that set have tx ffe for each loop | ||
≠ | 5090 | %% S_xn from eq 178A-16 | ≠ | 4962 | %% from healey_3dj_01_2401 slide 6 |
≠ | 5091 | %% Crosstalk power spectral density | ≠ | 4963 | % Crosstalk power spectral density |
− | 5092 | if ~OP.COMPUTE_COM % result.S_xn and result.S_xn_rms were found in optimizes_fom and passed in with the variable result |
| ||
≠ | 5093 | result.S_xn=0; | ≠ | 4964 | result.S_xn=0; |
≠ | 5094 | if length(chdata)~=1 | ≠ | 4965 | if length(chdata)~=1; |
≠ | 5095 | for xchan=2:length(chdata) | ≠ | 4966 | for xchan=2:length(chdata) |
≠ | 5096 | pulse_ctle=filter(ones(1,M),1,chdata(xchan).ctle_imp_response(:).'); | ≠ | 4967 | pulse_ctle=filter(ones(1,M),1,chdata(xchan).ctle_imp_response(:).'); |
≠ | 5097 | pulse_ctle=[ pulse_ctle(1:floor(length(pulse_ctle)/M)*M) ]; | ≠ | 4968 | pulse_ctle=[ pulse_ctle(1:floor(length(pulse_ctle)/M)*M) ]; |
− | 5098 | hk(xchan).k=chdata(xchan).pulse_response_w_CFT_TXFFE_noRxFFE.'; |
| ||
≠ | 5099 | % enable less UI for computation speed improvement | ≠ | 4969 | % enable less UI for computation speed improvement |
≠ | 5100 | %% | ≠ | 4970 | %% |
≠ | 5101 | if num_ui*M > length(pulse_ctle) | ≠ | 4971 | if num_ui*M > length(pulse_ctle) |
≠ | 5102 | hk(xchan).k= [ hk(xchan).k zeros(1,num_ui*M-length(hk(xchan).k)) ];% crosstalk pulse responces | ≠ | 4972 | pulse_ctle= [ pulse_ctle zeros(1,num_ui*M-length(pulse_ctle)) ]; |
| + | 4973 | else | ||
4974 | pulse_ctle=pulse_ctle(1:num_ui*M); | ||||
4975 | end | ||||
4976 | cmx=find(txffe==max(txffe))-1; | ||||
4977 | for i1=1:M | ||||
4978 | if ~strcmp(chdata(xchan).type,'NEXT') | ||||
4979 | hk(xchan).k=FFE( txffe , cmx,M, pulse_ctle )'; % need to speed up here | ||||
5103 | else | 4980 | else | ||
≠ | 5104 | hk(xchan).k=hk(xchan).k(1:num_ui*M); | ≠ | 4981 | hk(xchan).k=pulse_ctle; |
| + | 4982 | end | ||
≠ | 5105 | end | ≠ | 4983 | end |
≠ | 5106 | for i1=1:M | ≠ | 4984 | for i1=1:M |
≠ | 5107 | hxn(i1)=norm(hk(xchan).k(i1:M:length(hk(xchan).k)) ); | ≠ | 4985 | hxn(i1)=norm(hk(xchan).k(i1:M:length(hk(xchan).k)) ); |
≠ | 5108 | end | ≠ | 4986 | end |
≠ | 5109 | iphase(xchan)=find(hxn==max(hxn)); | ≠ | 4987 | iphase(xchan)=find(hxn==max(hxn)); |
≠ | 5110 | hk(xchan).hrn= hk(xchan).k(iphase(xchan):M:length(hk(xchan).k)); | ≠ | 4988 | hk(xchan).hrn= hk(xchan).k(iphase(xchan):M:length(hk(xchan).k)); |
≠ | 5111 | result.hk(xchan).hrn= hk(xchan).hrn; | ≠ | 4989 | result.hk(xchan).hrn= hk(xchan).hrn; |
≠ | 5112 | hk(xchan).S_xn=sigma_X2*(abs(fft(hk(xchan).hrn))).^2/param.fb; | ≠ | 4990 | hk(xchan).S_xn=sigma_X2*(abs(fft(hk(xchan).hrn))).^2/param.fb; |
≠ | 5113 | result.S_xn=hk(xchan).S_xn+result.S_xn; | ≠ | 4991 | result.S_xn=hk(xchan).S_xn+result.S_xn; |
≠ | 5114 | end | ≠ | 4992 | end |
− | 5115 | result.S_xn=result.S_xn; |
| ||
5116 | result.hk=hk; | ||||
5117 | result.iphase=iphase; | ||||
≠ | 5118 | result.S_xn_rms = sqrt(sum(result.S_xn)* delta_f); | ≠ | 4993 | result.xn_rms = sqrt(sum(result.S_xn)* delta_f); |
≠ | 5119 | else % if no crosstalk, perserve structure and return 0 for S_xn | ≠ | 4994 | else |
≠ | 5120 | result.S_xn=0; | ≠ | 4995 | result.xn_rms=0; |
− | 5121 | result.hk=[]; |
| ||
5122 | result.iphase=1; | ||||
≠ | 5123 | result.S_xn_rms = 0; | ≠ | 4996 | iphase=0; |
≠ | 5124 | end | ≠ | 4997 | end |
− | 5125 | else % adjust for H_rxffe when computing COM |
| ||
5126 | result.S_xn=result.S_xn.*H_rxffe_2; | ||||
5127 | result.S_xn_rms = sqrt(sum(result.S_xn)* delta_f); | ||||
5128 | end | ||||
≠ | 5129 | %% S_tn from eq 178A-17 | ≠ | 4998 | %% from healey_3dj_01_2401 slide 7 |
− | 5130 | %% if not in the opimization use value found in optimize_fom times |Hrxffe|^2 |
| ||
≠ | 5131 | %% Transmitter noise power spectral density | ≠ | 4999 | % Transmitter noise power spectral density |
− | 5132 | if ~OP.COMPUTE_COM |
| ||
≠ | 5133 | if ~OP.TDMODE | ≠ | 5000 | if ~OP.TDMODE |
≠ | 5134 | htn=filter(ones(1,M),1,chdata(1).ctle_imp_response); % ctle_imp_response does not have TxFFE included | ≠ | 5001 | htn=filter(ones(1,M),1,chdata(1).ctle_imp_response); % ctle_imp_response does not have TxFFE included |
≠ | 5135 | else % only use when the input was a pulse response not s-parameters | ≠ | 5002 | else % only use when the input was a pulse response not s-parameters |
≠ | 5136 | if isfield(chdata(1),'ctle_pulse_response') | ≠ | 5003 | if isfield(chdata(1),'ctle_pulse_response') |
≠ | 5137 | htn=chdata(1).ctle_pulse_response; | ≠ | 5004 | htn=chdata(1).ctle_pulse_response; |
≠ | 5138 | else | ≠ | 5005 | else |
≠ | 5139 | htn=filter(ones(1,param.samples_per_ui),1, chdata(1).ctle_imp_response); | ≠ | 5006 | htn=filter(ones(1,param.samples_per_ui),1, chdata(1).ctle_imp_response); |
≠ | 5140 | end | ≠ | 5007 | end |
≠ | 5141 | end | ≠ | 5008 | end |
≠ | 5142 | htn=htn(mod(cursor_i,M)+1:end-mod(cursor_i,M)); % align to sample point | ≠ | 5009 | htn=htn(mod(cursor_i,M)+1:end-mod(cursor_i,M)); % align to sample point |
≠ | 5143 | htn=reshape(htn,1,[]); % make row vectors | ≠ | 5010 | htn=reshape(htn,1,[]); % make row vectors |
≠ | 5144 | htn=[ htn(1:floor(length(htn)/M)*M) ]; | ≠ | 5011 | htn=[ htn(1:floor(length(htn)/M)*M) ]; |
≠ | 5145 | htn= [htn zeros(1,num_ui*M-length(htn)) ]; | ≠ | 5012 | htn= [htn zeros(1,num_ui*M-length(htn)) ]; |
≠ | 5146 | htn=htn(1:M:end);% resample | ≠ | 5013 | htn=htn(1:M:end);% resample |
≠ | 5147 | if num_ui>length(htn) | ≠ | 5014 | if num_ui>length(htn) |
≠ | 5148 | hext=[htn zeros(1,num_ui-length(htn))]; | ≠ | 5015 | hext=[htn zeros(1,num_ui-length(htn))]; |
≠ | 5149 | else | ≠ | 5016 | else |
≠ | 5150 | hext=htn(1:num_ui); | ≠ | 5017 | hext=htn(1:num_ui); |
≠ | 5151 | end | ≠ | 5018 | end |
≠ | 5152 | result.S_tn=sigma_X2*10^(-SNR_TX/10)*(abs(fft(hext))).^2/param.fb; % this corresponds to +/- pi | ≠ | 5019 | result.S_tn=sigma_X2*10^(-SNR_TX/10)*(abs(fft(hext))).^2/param.fb; % this corresponds to +/- pi |
≠ | 5153 | result.S_tn_rms = sqrt(sum(result.S_tn)* delta_f); | ≠ | 5020 | result.tn_rms = sqrt(sum(result.S_tn)* delta_f); |
− | 5154 | else |
| ||
5155 | result.S_tn=result.S_tn.*H_rxffe_2; | ||||
5156 | result.S_tn_rms = sqrt(sum(result.S_tn)* delta_f); | ||||
5157 | end | ||||
≠ | 5158 | %% S_jn from eq 178A-17 Srj_jn from eq 178A-31 | ≠ | 5021 | %% from healey_3dj_01_2401 slide 8 |
− | 5159 | %% RxFFE,CTLE, and TxFFE was applied in Apply_EQ when called after optimize_fom |
| ||
≠ | 5160 | %% Power spectral density of noise due to jitter | ≠ | 5022 | % Power spectral density of noise due to jitter |
5161 | %% Eq. 93A-28 %% | 5023 | %% Eq. 93A-28 %% | ||
− | 5162 | if ~OP.COMPUTE_COM |
| ||
≠ | 5163 | sampling_offset = mod(cursor_i, M); | ≠ | 5024 | sampling_offset = mod(cursor_i, M); |
≠ | 5164 | %ensure we can take early sample | ≠ | 5025 | %ensure we can take early sample |
≠ | 5165 | if sampling_offset<=1 | ≠ | 5026 | if sampling_offset<=1 |
≠ | 5166 | sampling_offset=sampling_offset+M; | ≠ | 5027 | sampling_offset=sampling_offset+M; |
≠ | 5167 | end | ≠ | 5028 | end |
≠ | 5168 | if (OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN) | ≠ | 5029 | if (OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN) |
≠ | 5169 | cursors_early_sample = h(cursor_i-1+M*(-1:param.ndfe)); | ≠ | 5030 | cursors_early_sample = h(cursor_i-1+M*(-1:param.ndfe)); |
≠ | 5170 | cursors_late_sample = h(cursor_i+1+M*(-1:param.ndfe)); | ≠ | 5031 | cursors_late_sample = h(cursor_i+1+M*(-1:param.ndfe)); |
≠ | 5171 | else | ≠ | 5032 | else |
≠ | 5172 | cursors_early_sample = h(sampling_offset-1:M:end); | ≠ | 5033 | cursors_early_sample = h(sampling_offset-1:M:end); |
≠ | 5173 | cursors_late_sample = h(sampling_offset+1:M:end); | ≠ | 5034 | cursors_late_sample = h(sampling_offset+1:M:end); |
≠ | 5174 | end | ≠ | 5035 | end |
≠ | 5175 | % ensure lengths are equal | ≠ | 5036 | % ensure lengths are equal |
≠ | 5176 | cursors_early_sample = cursors_early_sample(1:length(cursors_late_sample)); | ≠ | 5037 | cursors_early_sample = cursors_early_sample(1:length(cursors_late_sample)); |
≠ | 5177 | h_J = (cursors_late_sample-cursors_early_sample)/2*M; | ≠ | 5038 | h_J = (cursors_late_sample-cursors_early_sample)/2*M; |
≠ | 5178 | h_J=reshape(h_J,1,[]); % make row vectors | ≠ | 5039 | h_J=reshape(h_J,1,[]); % make row vectors |
≠ | 5179 | if num_ui>length(h_J) | ≠ | 5040 | if num_ui>length(h_J) |
≠ | 5180 | h_J=[h_J zeros(1,num_ui-length(h_J))]; | ≠ | 5041 | h_J=[h_J zeros(1,num_ui-length(h_J))]; |
≠ | 5181 | else | ≠ | 5042 | else |
≠ | 5182 | h_J=h_J(1:num_ui); | ≠ | 5043 | h_J=h_J(1:num_ui); |
≠ | 5183 | end | ≠ | 5044 | end |
| + | 5045 | result.iphase=iphase; | ||
≠ | 5184 | result.S_jn=sigma_X2*(param.A_DD^2+param.sigma_RJ^2)*(abs(fft(h_J))).^2/param.fb; % this corresponds to +/- pi | ≠ | 5046 | result.S_jn=sigma_X2*(param.A_DD^2+param.sigma_RJ^2)*(abs(fft(h_J))).^2/param.fb; % this corresponds to +/- pi |
≠ | 5185 | result.S_jn_rms = sqrt(sum(result.S_jn)* delta_f); | ≠ | 5047 | result.jn_rms = sqrt(sum(result.S_jn)* delta_f); |
− | 5186 | result.S_rj_jn=sigma_X2*(param.sigma_RJ^2)*(abs(fft(h_J))).^2/param.fb; % this corresponds to +/- pi |
| ||
5187 | result.S_rj_rms = sqrt(sum(result.S_rj_jn)* delta_f); | ||||
5188 | else | ||||
5189 | result.S_jn=result.S_jn.*H_rxffe_2; | ||||
5190 | result.S_jn_rms = sqrt(sum(result.S_jn)* delta_f); | ||||
5191 | result.S_rj_jn= result.S_rj_jn.*H_rxffe_2; | ||||
5192 | result.S_rj_rms = sqrt(sum(result.S_rj_jn)* delta_f); | ||||
5193 | end | ||||
5194 | % result.S_jn | ||||
5195 | result.S_n=result.S_rn+ result.S_tn+ result.S_xn+ result.S_jn; | 5048 | result.S_n=result.S_rn+ result.S_tn+ result.S_xn+ result.S_jn; | ||
− | 5196 | result.S_n_rms = sqrt(sum(result.S_n)* delta_f); |
| ||
5197 | |||||
5198 | %% | ||||
5199 | %% Hisi to be included in MLSE rho eq 178a-28 | ||||
5200 | if OP.COMPUTE_COM | ||||
5201 | %% Hisi psd h include CTLE(CFT), TxFFE, and RxFFE but not sigma_X2 | ||||
5202 | sampling_offset = mod(cursor_i-1, M)+1; % Commit request 4p4_6, healey_3dj_COM_01_240416 | ||||
5203 | hisi=h(sampling_offset:M:end); | ||||
5204 | hisi=hisi(:).'; | ||||
5205 | if num_ui>length(hisi) | ||||
5206 | hisi=[hisi zeros(1,num_ui-length(hisi))]; | ||||
5207 | else | ||||
5208 | hisi=hisi(1:num_ui); | ||||
5209 | end | ||||
5210 | cursor_n=floor(cursor_i/M)+1; | ||||
5211 | for ii=1:length(hisi) | ||||
5212 | if ii==cursor_n % cursor | ||||
5213 | cursor=hisi(ii); | ||||
5214 | hisi(ii)= 0; | ||||
5215 | elseif ii >= cursor_n+1 && ii <=cursor_n+Nb | ||||
5216 | ib_indx=ii-cursor_n; | ||||
5217 | if hisi(ii) >= bmax(ib_indx)*cursor | ||||
5218 | hisi(ii) = hisi(ii) - bmax(ib_indx)*cursor; | ||||
5219 | elseif hisi(ii) <= bmin(ib_indx)*cursor | ||||
5220 | hisi(ii) = hisi(ii) - bmin(ib_indx)*cursor; | ||||
5221 | else | ||||
5222 | hisi(ii)=0; | ||||
5223 | end | ||||
5224 | end | ||||
5225 | end | ||||
5226 | result.S_isi=sigma_X2*(abs(fft(hisi))).^2/param.fb; | ||||
5227 | result.S_isi_rms = sqrt(sum(result.S_isi)* delta_f); | ||||
5228 | %% | ||||
5229 | result.S_G=result.S_tn+ result.S_rj_jn + result.S_rn; % eq 178A-30 | ||||
5230 | result.S_G_rms = sqrt(sum(result.S_G)* delta_f); | ||||
5231 | result.Sn_rho=result.S_isi +result.S_n; % need to include xtalk and isi | ||||
5232 | result.Sn_rho_rms = sqrt(sum(result.Sn_rho)* delta_f); | ||||
5233 | end | ||||
5234 | end | 5049 | end | ||
5235 | function result=get_PulseR(ir,param,cb_step,ZT) | 5050 | function result=get_PulseR(ir,param,cb_step,ZT) | ||
5236 | %ir = impulse response | 5051 | %ir = impulse response | ||
5237 | %t_base=time array with equal time steps | 5052 | %t_base=time array with equal time steps | ||
5238 | %samp_UI = number of samples per UI for ir | 5053 | %samp_UI = number of samples per UI for ir | ||
5239 | 5054 | ||||
5240 | % t for debug | 5055 | % t for debug | ||
5241 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | 5056 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | ||
5242 | 5057 | ||||
5243 | if cb_step | 5058 | if cb_step | ||
5244 | Ag=1; | 5059 | Ag=1; | ||
5245 | dt=1/param.fb/param.samples_per_ui; | 5060 | dt=1/param.fb/param.samples_per_ui; | ||
5246 | edge_time=param.TR_TDR*1e-9; | 5061 | edge_time=param.TR_TDR*1e-9; | ||
5247 | fedge=1/edge_time; | 5062 | fedge=1/edge_time; | ||
5248 | tedge=0:dt:edge_time*2; | 5063 | tedge=0:dt:edge_time*2; | ||
5249 | % | 5064 | % | ||
5250 | edge=Ag*(2*cos(2*pi*(tedge)*fedge/16-pi/4).^2-1); | 5065 | edge=Ag*(2*cos(2*pi*(tedge)*fedge/16-pi/4).^2-1); | ||
5251 | drive_pulse=[edge ones(1,param.samples_per_ui)]; | 5066 | drive_pulse=[edge ones(1,param.samples_per_ui)]; | ||
5252 | %pulse=filter(UI_ones,1,ir); | 5067 | %pulse=filter(UI_ones,1,ir); | ||
5253 | % t for debug | 5068 | % t for debug | ||
5254 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | 5069 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | ||
5255 |
| 5070 |
| ||
5256 | pulse=filter(drive_pulse,1,ir); | 5071 | pulse=filter(drive_pulse,1,ir); | ||
5257 | else | 5072 | else | ||
5258 | pulse=filter( ones(1,param.samples_per_ui),1,ir); | 5073 | pulse=filter( ones(1,param.samples_per_ui),1,ir); | ||
5259 | end | 5074 | end | ||
5260 | PDR_response=(1+pulse)./(1-pulse).*ZT*2; | 5075 | PDR_response=(1+pulse)./(1-pulse).*ZT*2; | ||
5261 | result.PDR=PDR_response; | 5076 | result.PDR=PDR_response; | ||
5262 | result.pulse=pulse; | 5077 | result.pulse=pulse; | ||
5263 | 5078 | ||||
5264 | 5079 | ||||
5265 | 5080 | ||||
5266 | function [ FIR t] =get_RAW_FIR(H,f,OP,param) | 5081 | function [ FIR t] =get_RAW_FIR(H,f,OP,param) | ||
5267 | H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(0.75*param.fb)); | 5082 | H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*f./(0.75*param.fb)); | ||
5268 | if ~iscolumn(H), H=H.';end | 5083 | if ~iscolumn(H), H=H.';end | ||
5269 | if ~iscolumn(H_r), H_r=H_r.';end | 5084 | if ~iscolumn(H_r), H_r=H_r.';end | ||
5270 | H=H(:).*H_r; | 5085 | H=H(:).*H_r; | ||
5271 | [FIR, t, ~,~] = s21_to_impulse_DC(H ,f, param.sample_dt, OP) ; | 5086 | [FIR, t, ~,~] = s21_to_impulse_DC(H ,f, param.sample_dt, OP) ; | ||
5272 | % SBR=filter(ones(1, param.samples_per_ui), 1, FIR); | 5087 | % SBR=filter(ones(1, param.samples_per_ui), 1, FIR); | ||
5273 | 5088 | ||||
5274 | function RILN_TD_struct= get_RILN_cmp_td(sdd21,RIL_struct,faxis_f2,OP,param,A_T) | 5089 | function RILN_TD_struct= get_RILN_cmp_td(sdd21,RIL_struct,faxis_f2,OP,param,A_T) | ||
5275 | % Complex reflection and re-reflection noise using the concept of zero'ing | 5090 | % Complex reflection and re-reflection noise using the concept of zero'ing | ||
5276 | % out of reflections | 5091 | % out of reflections | ||
5277 | % sdd21 us a complex insertion loss | 5092 | % sdd21 us a complex insertion loss | ||
5278 | % RIL_struct is the output of capture_RIL_RILN() | 5093 | % RIL_struct is the output of capture_RIL_RILN() | ||
5279 | % faxix_f2 needs to be at least to fb | 5094 | % faxix_f2 needs to be at least to fb | ||
5280 | % return reflections RILN_TD_struct.FOM based on time domain PR fit from pulse peak | 5095 | % return reflections RILN_TD_struct.FOM based on time domain PR fit from pulse peak | ||
5281 | % still need to settle on voltage scaling. | 5096 | % still need to settle on voltage scaling. | ||
5282 | % maybe db(peak/Rss | 5097 | % maybe db(peak/Rss | ||
5283 | db = @(x) 20*log10(abs(x)); | 5098 | db = @(x) 20*log10(abs(x)); | ||
5284 | fprintf('computing TD_RILN (dB) ...'); | 5099 | fprintf('computing TD_RILN (dB) ...'); | ||
5285 | 5100 | ||||
5286 | OP.interp_sparam_mag= 'trend_to_DC'; | 5101 | OP.interp_sparam_mag= 'trend_to_DC'; | ||
5287 | OP.interp_sparam_phase= 'interp_to_DC'; | 5102 | OP.interp_sparam_phase= 'interp_to_DC'; | ||
5288 | % OP.interp_sparam_mag= 'linear_trend_to_DC'; | 5103 | % OP.interp_sparam_mag= 'linear_trend_to_DC'; | ||
5289 | % OP.interp_sparam_phase= 'extrap_cubic_to_dc_linear_to_inf'; | 5104 | % OP.interp_sparam_phase= 'extrap_cubic_to_dc_linear_to_inf'; | ||
5290 | 5105 | ||||
5291 | sdd21=squeeze(sdd21); | 5106 | sdd21=squeeze(sdd21); | ||
5292 | if iscolumn(sdd21) | 5107 | if iscolumn(sdd21) | ||
5293 | sdd21=sdd21.'; | 5108 | sdd21=sdd21.'; | ||
5294 | end | 5109 | end | ||
5295 | RIL=squeeze(RIL_struct.RIL); | 5110 | RIL=squeeze(RIL_struct.RIL); | ||
5296 | if iscolumn(RIL) | 5111 | if iscolumn(RIL) | ||
5297 | RIL=RIL.'; | 5112 | RIL=RIL.'; | ||
5298 | end | 5113 | end | ||
5299 | rho_port1=squeeze(RIL_struct.rho_port1); | 5114 | rho_port1=squeeze(RIL_struct.rho_port1); | ||
5300 | if iscolumn(rho_port1) | 5115 | if iscolumn(rho_port1) | ||
5301 | rho_port1=rho_port1.'; | 5116 | rho_port1=rho_port1.'; | ||
5302 | end | 5117 | end | ||
5303 | rho_port2=squeeze(RIL_struct.rho_port2); | 5118 | rho_port2=squeeze(RIL_struct.rho_port2); | ||
5304 | if iscolumn(rho_port2) | 5119 | if iscolumn(rho_port2) | ||
5305 | rho_port2=rho_port2.'; | 5120 | rho_port2=rho_port2.'; | ||
5306 | end | 5121 | end | ||
5307 | RIL_f=squeeze(RIL_struct.freq); | 5122 | RIL_f=squeeze(RIL_struct.freq); | ||
5308 | if iscolumn(RIL_f) | 5123 | if iscolumn(RIL_f) | ||
5309 | RIL_f=RIL_f.'; | 5124 | RIL_f=RIL_f.'; | ||
5310 | end | 5125 | end | ||
5311 | 5126 | ||||
5312 | %---start. Calculate the reflection and re-reflection noise | 5127 | %---start. Calculate the reflection and re-reflection noise | ||
5313 | number_of_echos= 1e3; | 5128 | number_of_echos= 1e3; | ||
5314 | fmin= 1e9;%<------------- | 5129 | fmin= 1e9;%<------------- | ||
5315 | port2_reflection_rereflection_noise= zeros(1, length(RIL)); | 5130 | port2_reflection_rereflection_noise= zeros(1, length(RIL)); | ||
5316 | port1_reflection_rereflection_noise= zeros(1, length(RIL)); | 5131 | port1_reflection_rereflection_noise= zeros(1, length(RIL)); | ||
5317 | for m= 1:number_of_echos | 5132 | for m= 1:number_of_echos | ||
5318 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise+ abs(RIL).*(RIL.^(2*m)).*(rho_port1.^m).*(rho_port2.^m).*(1+rho_port1).*(1+rho_port2); | 5133 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise+ abs(RIL).*(RIL.^(2*m)).*(rho_port1.^m).*(rho_port2.^m).*(1+rho_port1).*(1+rho_port2); | ||
5319 | port1_reflection_rereflection_noise= port1_reflection_rereflection_noise+ abs(RIL).*(RIL.^(2*m-1)).*(rho_port1.^(m-1)).*(rho_port2.^m).*(1+rho_port1).*(1+rho_port1); | 5134 | port1_reflection_rereflection_noise= port1_reflection_rereflection_noise+ abs(RIL).*(RIL.^(2*m-1)).*(rho_port1.^(m-1)).*(rho_port2.^m).*(1+rho_port1).*(1+rho_port1); | ||
5320 | end | 5135 | end | ||
5321 | 5136 | ||||
5322 | %-----start. In the case of reflections, observed is bad TD conversion and hence removing data before 1GHz | 5137 | %-----start. In the case of reflections, observed is bad TD conversion and hence removing data before 1GHz | ||
5323 | fmin_idx= find(RIL_f>= fmin, 1, 'first'); | 5138 | fmin_idx= find(RIL_f>= fmin, 1, 'first'); | ||
5324 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise(fmin_idx:end); | 5139 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise(fmin_idx:end); | ||
5325 | port1_reflection_rereflection_noise= port1_reflection_rereflection_noise(fmin_idx:end); | 5140 | port1_reflection_rereflection_noise= port1_reflection_rereflection_noise(fmin_idx:end); | ||
5326 | f_reflection_rereflection_noise= RIL_f(fmin_idx:end); | 5141 | f_reflection_rereflection_noise= RIL_f(fmin_idx:end); | ||
5327 | %-----end. In the case of reflections, observed is bad TD conversion and hence removing data before 1GHz | 5142 | %-----end. In the case of reflections, observed is bad TD conversion and hence removing data before 1GHz | ||
5328 | 5143 | ||||
5329 | % clear RIL RIL_f rho_port1 rho_port2 | 5144 | % clear RIL RIL_f rho_port1 rho_port2 | ||
5330 | % clear fmin m | 5145 | % clear fmin m | ||
5331 | %---end. Calculate the reflection and re-reflection noise | 5146 | %---end. Calculate the reflection and re-reflection noise | ||
5332 | 5147 | ||||
5333 | fmbg=[ones(length(faxis_f2),1).*transpose(sdd21) transpose(sqrt(faxis_f2)).*transpose(sdd21) transpose(faxis_f2).*transpose(sdd21) transpose(faxis_f2.^2).*transpose(sdd21) ]; | 5148 | fmbg=[ones(length(faxis_f2),1).*transpose(sdd21) transpose(sqrt(faxis_f2)).*transpose(sdd21) transpose(faxis_f2).*transpose(sdd21) transpose(faxis_f2.^2).*transpose(sdd21) ]; | ||
5334 | warning('off','MATLAB:nearlySingularMatrix'); | 5149 | warning('off','MATLAB:nearlySingularMatrix'); | ||
5335 | unwraplog=log(abs(sdd21))+1i*unwrap(angle(sdd21)); | 5150 | unwraplog=log(abs(sdd21))+1i*unwrap(angle(sdd21)); | ||
5336 | LGw=transpose(sdd21.*unwraplog); | 5151 | LGw=transpose(sdd21.*unwraplog); | ||
5337 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | 5152 | alpha = ((fmbg'*fmbg)^-1)*fmbg'*LGw; | ||
5338 | efit_C=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | 5153 | efit_C=(alpha(1)+alpha(2).*sqrt(faxis_f2)+alpha(3).*faxis_f2 +faxis_f2.^2.*alpha(4) ); | ||
5339 | FIT=transpose(exp(transpose(efit_C))); | 5154 | FIT=transpose(exp(transpose(efit_C))); | ||
5340 | efit=db(abs(FIT)); | 5155 | efit=db(abs(FIT)); | ||
5341 | ILN = db(sdd21)-efit; | 5156 | ILN = db(sdd21)-efit; | ||
5342 | 5157 | ||||
5343 | 5158 | ||||
5344 | OP.impulse_response_truncation_threshold =1e-7; | 5159 | OP.impulse_response_truncation_threshold =1e-7; | ||
5345 | 5160 | ||||
5346 | print_for_codereview=0; | 5161 | print_for_codereview=0; | ||
5347 | if exist('OP','var') | 5162 | if exist('OP','var') | ||
5348 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | 5163 | H_bt=Bessel_Thomson_Filter(param,faxis_f2,1); | ||
5349 | H_bw=Butterworth_Filter(param,faxis_f2,1); | 5164 | H_bw=Butterworth_Filter(param,faxis_f2,1); | ||
5350 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 5165 | H_t = exp(-(pi*faxis_f2/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
5351 | H_tw=Tukey_Window(faxis_f2,param); | 5166 | H_tw=Tukey_Window(faxis_f2,param); | ||
5352 | H_tw=ones(1,length(faxis_f2) ); | 5167 | H_tw=ones(1,length(faxis_f2) ); | ||
5353 | [RILN_TD_struct.REF.FIR, ... | 5168 | [RILN_TD_struct.REF.FIR, ... | ||
5354 | RILN_TD_struct.REF.t, ... | 5169 | RILN_TD_struct.REF.t, ... | ||
5355 | RILN_TD_struct.REF.causality_correction_dB, ... | 5170 | RILN_TD_struct.REF.causality_correction_dB, ... | ||
5356 | RILN_TD_struct.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 5171 | RILN_TD_struct.REF.truncation_dB] = s21_to_impulse_DC(sdd21.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
5357 | RILN_TD_struct.REF.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF.FIR); | 5172 | RILN_TD_struct.REF.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF.FIR); | ||
5358 |
| 5173 |
| ||
5359 |
| 5174 |
| ||
5360 | [RILN_TD_struct.FIT.FIR, ... | 5175 | [RILN_TD_struct.FIT.FIR, ... | ||
5361 | RILN_TD_struct.FIT.t, ... | 5176 | RILN_TD_struct.FIT.t, ... | ||
5362 | RILN_TD_struct.FIT.causality_correction_dB, ... | 5177 | RILN_TD_struct.FIT.causality_correction_dB, ... | ||
5363 | RILN_TD_struct.FIT.truncation_dB] = s21_to_impulse_DC(FIT.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | 5178 | RILN_TD_struct.FIT.truncation_dB] = s21_to_impulse_DC(FIT.*H_bw.*H_t.*H_tw ,faxis_f2, param.sample_dt, OP) ; | ||
5364 | RILN_TD_struct.FIT.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.FIT.FIR); | 5179 | RILN_TD_struct.FIT.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.FIT.FIR); | ||
5365 |
| 5180 |
| ||
5366 |
| 5181 |
| ||
5367 | H_bt=Bessel_Thomson_Filter(param,RIL_f,1); | 5182 | H_bt=Bessel_Thomson_Filter(param,RIL_f,1); | ||
5368 | H_bw=Butterworth_Filter(param,RIL_f,1); | 5183 | H_bw=Butterworth_Filter(param,RIL_f,1); | ||
5369 | H_t = exp(-(pi*RIL_f/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 5184 | H_t = exp(-(pi*RIL_f/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
5370 | H_tw=Tukey_Window(RIL_f,param); | 5185 | H_tw=Tukey_Window(RIL_f,param); | ||
5371 | H_tw=ones(1,length(RIL_f) ); | 5186 | H_tw=ones(1,length(RIL_f) ); | ||
5372 | [RILN_TD_struct.RIL.FIR, ... | 5187 | [RILN_TD_struct.RIL.FIR, ... | ||
5373 | RILN_TD_struct.RIL.t, ... | 5188 | RILN_TD_struct.RIL.t, ... | ||
5374 | RILN_TD_struct.RIL.causality_correction_dB, ... | 5189 | RILN_TD_struct.RIL.causality_correction_dB, ... | ||
5375 | RILN_TD_struct.RIL.truncation_dB] = s21_to_impulse_DC(RIL.*H_bw.*H_t.*H_tw ,RIL_f, param.sample_dt, OP) ; | 5190 | RILN_TD_struct.RIL.truncation_dB] = s21_to_impulse_DC(RIL.*H_bw.*H_t.*H_tw ,RIL_f, param.sample_dt, OP) ; | ||
5376 | RILN_TD_struct.RIL.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.RIL.FIR); | 5191 | RILN_TD_struct.RIL.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.RIL.FIR); | ||
5377 |
| 5192 |
| ||
5378 |
| 5193 |
| ||
5379 | %---start. Calculate the channel delay | 5194 | %---start. Calculate the channel delay | ||
5380 | try | 5195 | try | ||
5381 | [delay_sec, delay_idx]= calculate_delay_CausalityEnforcement(faxis_f2, sdd21, param, OP); | 5196 | [delay_sec, delay_idx]= calculate_delay_CausalityEnforcement(faxis_f2, sdd21, param, OP); | ||
5382 | catch | 5197 | catch | ||
5383 | end | 5198 | end | ||
5384 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise.*exp(-1j*2*pi*f_reflection_rereflection_noise*delay_sec); | 5199 | port2_reflection_rereflection_noise= port2_reflection_rereflection_noise.*exp(-1j*2*pi*f_reflection_rereflection_noise*delay_sec); | ||
5385 | clear delay_sec delay_idx | 5200 | clear delay_sec delay_idx | ||
5386 | %---end. Calculate the channel delay | 5201 | %---end. Calculate the channel delay | ||
5387 | 5202 | ||||
5388 | 5203 | ||||
5389 |
| 5204 |
| ||
5390 | H_bt=Bessel_Thomson_Filter(param,f_reflection_rereflection_noise,1); | 5205 | H_bt=Bessel_Thomson_Filter(param,f_reflection_rereflection_noise,1); | ||
5391 | H_bw=Butterworth_Filter(param,f_reflection_rereflection_noise,1); | 5206 | H_bw=Butterworth_Filter(param,f_reflection_rereflection_noise,1); | ||
5392 | H_t = exp(-(pi*f_reflection_rereflection_noise/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 5207 | H_t = exp(-(pi*f_reflection_rereflection_noise/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
5393 | H_tw=Tukey_Window(f_reflection_rereflection_noise,param); | 5208 | H_tw=Tukey_Window(f_reflection_rereflection_noise,param); | ||
5394 | H_tw=ones(1,length(f_reflection_rereflection_noise) ); | 5209 | H_tw=ones(1,length(f_reflection_rereflection_noise) ); | ||
5395 | [RILN_TD_struct.REF_noise.FIR, ... | 5210 | [RILN_TD_struct.REF_noise.FIR, ... | ||
5396 | RILN_TD_struct.REF_noise.t, ... | 5211 | RILN_TD_struct.REF_noise.t, ... | ||
5397 | RILN_TD_struct.REF_noise.causality_correction_dB, ... | 5212 | RILN_TD_struct.REF_noise.causality_correction_dB, ... | ||
5398 | RILN_TD_struct.REF_noise.truncation_dB] = s21_to_impulse_DC(port2_reflection_rereflection_noise.*H_bw.*H_t.*H_tw ,f_reflection_rereflection_noise, param.sample_dt, OP) ; | 5213 | RILN_TD_struct.REF_noise.truncation_dB] = s21_to_impulse_DC(port2_reflection_rereflection_noise.*H_bw.*H_t.*H_tw ,f_reflection_rereflection_noise, param.sample_dt, OP) ; | ||
5399 | RILN_TD_struct.REF_noise.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF_noise.FIR); | 5214 | RILN_TD_struct.REF_noise.PR=filter(ones(1, param.samples_per_ui), 1, RILN_TD_struct.REF_noise.FIR); | ||
5400 |
| 5215 |
| ||
5401 | ipeak=find(RILN_TD_struct.REF.PR==max(RILN_TD_struct.REF.PR),1,'first'); | 5216 | ipeak=find(RILN_TD_struct.REF.PR==max(RILN_TD_struct.REF.PR),1,'first'); | ||
5402 | % NrangeUI=1000; | 5217 | % NrangeUI=1000; | ||
5403 | % range_end=min(min(ipeak+param.samples_per_ui*NrangeUI,length(RILN_TD_struct.FIT.PR)-param.samples_per_ui ),length(RILN_TD_struct.REF.PR)-param.samples_per_ui); | 5218 | % range_end=min(min(ipeak+param.samples_per_ui*NrangeUI,length(RILN_TD_struct.FIT.PR)-param.samples_per_ui ),length(RILN_TD_struct.REF.PR)-param.samples_per_ui); | ||
5404 | range_end= min(length(RILN_TD_struct.REF.PR), length(RILN_TD_struct.REF_noise.PR)); | 5219 | range_end= min(length(RILN_TD_struct.REF.PR), length(RILN_TD_struct.REF_noise.PR)); | ||
5405 | range=ipeak:range_end; | 5220 | range=ipeak:range_end; | ||
5406 | RILN_TD_struct.ILN=RILN_TD_struct.REF_noise.PR(range); | 5221 | RILN_TD_struct.ILN=RILN_TD_struct.REF_noise.PR(range); | ||
5407 | RILN_TD_struct.t=RILN_TD_struct.REF_noise.t(range); | 5222 | RILN_TD_struct.t=RILN_TD_struct.REF_noise.t(range); | ||
5408 | RILN_TD_struct.FOM=-inf; | 5223 | RILN_TD_struct.FOM=-inf; | ||
5409 | RILN_TD_struct.FOM_PDF=-inf; | 5224 | RILN_TD_struct.FOM_PDF=-inf; | ||
5410 | rms_fom=-inf; | 5225 | rms_fom=-inf; | ||
5411 | for im=1:param.samples_per_ui | 5226 | for im=1:param.samples_per_ui | ||
5412 | RILN_TD_struct.FOM=max(RILN_TD_struct.FOM, norm( RILN_TD_struct.ILN(im:param.samples_per_ui:end))); | 5227 | RILN_TD_struct.FOM=max(RILN_TD_struct.FOM, norm( RILN_TD_struct.ILN(im:param.samples_per_ui:end))); | ||
5413 | [ pdf ] = get_pdf_from_sampled_signal( RILN_TD_struct.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | 5228 | [ pdf ] = get_pdf_from_sampled_signal( RILN_TD_struct.ILN(im:param.samples_per_ui:end), param.levels, OP.BinSize ,0); | ||
5414 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | 5229 | rms=sqrt(pdf.y*pdf.x(:).^2)*sqrt(2); | ||
5415 | cdf=pdf; cdf.y=cumsum(pdf.y); | 5230 | cdf=pdf; cdf.y=cumsum(pdf.y); | ||
5416 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | 5231 | % cursors = d_cpdf(OP.BinSize,param.a_thru*[-1 1], [1 1]/2); | ||
5417 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | 5232 | % signal_and_isi_pdf = conv_fct(cursors, pdf); | ||
5418 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | 5233 | % cdf=signal_and_isi_pdf; cdf.y=cumsum(signal_and_isi_pdf.y); | ||
5419 | if print_for_codereview % remove once all checked out | 5234 | if print_for_codereview % remove once all checked out | ||
5420 | h=figure(190);set(gcf,'Tag','COM'); | 5235 | h=figure(190);set(gcf,'Tag','COM'); | ||
5421 | semilogy(-cdf.x,cdf.y); | 5236 | semilogy(-cdf.x,cdf.y); | ||
5422 | % xlim ([0,-cdf.x(1)]) | 5237 | % xlim ([0,-cdf.x(1)]) | ||
5423 | ylim([param.specBER 1]);title ('CDF of ILN') | 5238 | ylim([param.specBER 1]);title ('CDF of ILN') | ||
5424 | hold on | 5239 | hold on | ||
5425 | end | 5240 | end | ||
5426 | if rms>rms_fom | 5241 | if rms>rms_fom | ||
5427 | rms_fom=rms; | 5242 | rms_fom=rms; | ||
5428 | RILN_TD_struct.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | 5243 | RILN_TD_struct.FOM_PDF= -cdf.x(find(cdf.y >= param.specBER, 1, 'first')); | ||
5429 | RILN_TD_struct.PDF=pdf; | 5244 | RILN_TD_struct.PDF=pdf; | ||
5430 | end | 5245 | end | ||
5431 | end | 5246 | end | ||
5432 | pdf_from_norm=normal_dist(RILN_TD_struct.FOM, 7 , OP.BinSize); | 5247 | pdf_from_norm=normal_dist(RILN_TD_struct.FOM, 7 , OP.BinSize); | ||
5433 | RILN_TD_struct.SNR_ISI_FOM=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM); | 5248 | RILN_TD_struct.SNR_ISI_FOM=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM); | ||
5434 | RILN_TD_struct.SNR_ISI_FOM_PDF=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM_PDF); | 5249 | RILN_TD_struct.SNR_ISI_FOM_PDF=db(RILN_TD_struct.FIT.PR(ipeak)/RILN_TD_struct.FOM_PDF); | ||
5435 | % fprintf('%g dB\n',RILN_TD_struct.SNR_ISI_FOM) | 5250 | % fprintf('%g dB\n',RILN_TD_struct.SNR_ISI_FOM) | ||
5436 | fprintf('%g dB\n',RILN_TD_struct.SNR_ISI_FOM_PDF) | 5251 | fprintf('%g dB\n',RILN_TD_struct.SNR_ISI_FOM_PDF) | ||
5437 | if print_for_codereview % remove once all checked out | 5252 | if print_for_codereview % remove once all checked out | ||
5438 | figure(9000);set(gcf,'Tag','COM'); | 5253 | figure(9000);set(gcf,'Tag','COM'); | ||
5439 | plot(RILN_TD_struct.REF.t,RILN_TD_struct.REF.PR,'disp','ref') | 5254 | plot(RILN_TD_struct.REF.t,RILN_TD_struct.REF.PR,'disp','ref') | ||
5440 | hold on | 5255 | hold on | ||
5441 | plot(RILN_TD_struct.FIT.t,RILN_TD_struct.FIT.PR,'disp','fit') | 5256 | plot(RILN_TD_struct.FIT.t,RILN_TD_struct.FIT.PR,'disp','fit') | ||
5442 | plot(RILN_TD_struct.RIL.t,RILN_TD_struct.RIL.PR,'disp','RILN') | 5257 | plot(RILN_TD_struct.RIL.t,RILN_TD_struct.RIL.PR,'disp','RILN') | ||
5443 | yyaxis right | 5258 | yyaxis right | ||
5444 | plot(RILN_TD_struct.t,RILN_TD_struct.ILN,'disp','td RILN') | 5259 | plot(RILN_TD_struct.t,RILN_TD_struct.ILN,'disp','td RILN') | ||
5445 | hold off | 5260 | hold off | ||
5446 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',RILN_TD_struct.SNR_ISI_FOM,RILN_TD_struct.SNR_ISI_FOM_PDF) | 5261 | fprintf('SNR ISI FOM rms = %g dB; SNR ISI FOM PDF = %g dB\n',RILN_TD_struct.SNR_ISI_FOM,RILN_TD_struct.SNR_ISI_FOM_PDF) | ||
5447 | figure(9002);set(gcf,'Tag','COM'); | 5262 | figure(9002);set(gcf,'Tag','COM'); | ||
5448 | semilogy(RILN_TD_struct.PDF.x,RILN_TD_struct.PDF.y,'disp','actual PDF') | 5263 | semilogy(RILN_TD_struct.PDF.x,RILN_TD_struct.PDF.y,'disp','actual PDF') | ||
5449 | hold on | 5264 | hold on | ||
5450 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | 5265 | semilogy(pdf_from_norm.x,pdf_from_norm.y,'disp','PDF using Gaussian assumed PDF'); | ||
5451 | ylim([param.specBER max([RILN_TD_struct.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | 5266 | ylim([param.specBER max([RILN_TD_struct.PDF.y pdf_from_norm.y])]);title ('Compare actual PDF to Gaussian') | ||
5452 | grid on | 5267 | grid on | ||
5453 | legend('show') | 5268 | legend('show') | ||
5454 | end | 5269 | end | ||
5455 | end | 5270 | end | ||
5456 | function result=get_StepR(ir,param,cb_step,ZT) | 5271 | function result=get_StepR(ir,param,cb_step,ZT) | ||
5457 | %ir = impulse response | 5272 | %ir = impulse response | ||
5458 | %t_base=time array with equal time steps | 5273 | %t_base=time array with equal time steps | ||
5459 | %samp_UI = number of samples per UI for ir | 5274 | %samp_UI = number of samples per UI for ir | ||
5460 | % result.SBR | 5275 | % result.SBR | ||
5461 | % t for debug | 5276 | % t for debug | ||
5462 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | 5277 | t=(1/param.fb)/param.samples_per_ui*(0:length(ir)-1); | ||
5463 | 5278 | ||||
5464 | if cb_step | 5279 | if cb_step | ||
5465 | Ag=1; | 5280 | Ag=1; | ||
5466 | dt=1/param.fb/param.samples_per_ui; | 5281 | dt=1/param.fb/param.samples_per_ui; | ||
5467 | edge_time=param.TR_TDR*1e-9; | 5282 | edge_time=param.TR_TDR*1e-9; | ||
5468 | fedge=1/edge_time; | 5283 | fedge=1/edge_time; | ||
5469 | tedge=0:dt:edge_time*2; | 5284 | tedge=0:dt:edge_time*2; | ||
5470 | % | 5285 | % | ||
5471 | edge=Ag*(2*cos(2*pi*(tedge)*fedge/16-pi/4).^2-1); | 5286 | edge=Ag*(2*cos(2*pi*(tedge)*fedge/16-pi/4).^2-1); | ||
5472 | drive_pulse=[edge ones(1,param.samples_per_ui)]; | 5287 | drive_pulse=[edge ones(1,param.samples_per_ui)]; | ||
5473 | %pulse=filter(UI_ones,1,ir); | 5288 | %pulse=filter(UI_ones,1,ir); | ||
5474 |
| 5289 |
| ||
5475 | pulse=filter(drive_pulse,1,ir); | 5290 | pulse=filter(drive_pulse,1,ir); | ||
5476 | else | 5291 | else | ||
5477 | pulse=cumsum(ir); | 5292 | pulse=cumsum(ir); | ||
5478 | end | 5293 | end | ||
5479 | TDR_response=(1+pulse)./(1-pulse)*ZT*2; | 5294 | TDR_response=(1+pulse)./(1-pulse)*ZT*2; | ||
5480 | result.ZSR=TDR_response; | 5295 | result.ZSR=TDR_response; | ||
5481 | result.pulse=pulse; | 5296 | result.pulse=pulse; | ||
5482 | 5297 | ||||
5483 | 5298 | ||||
5484 | function TDR_results = get_TDR(sdd, OP, param,ZT,np) | 5299 | function TDR_results = get_TDR(sdd, OP, param,ZT,np) | ||
5485 | % sdd is differential s-parameters structure (2 port assumed) | 5300 | % sdd is differential s-parameters structure (2 port assumed) | ||
5486 | % input parameter structure for s parameters sdd--> sdd.Impedance, sdd.Frequencies, sdd.Parameters, sdd.NumPorts | 5301 | % input parameter structure for s parameters sdd--> sdd.Impedance, sdd.Frequencies, sdd.Parameters, sdd.NumPorts | ||
5487 | % TDR_results.delay pre t=0 delay for TDR... help with time domain responce quaility | 5302 | % TDR_results.delay pre t=0 delay for TDR... help with time domain responce quaility | ||
5488 | % TDR_results.tdr the TDR responce (ohms vs TDR_results.t | 5303 | % TDR_results.tdr the TDR responce (ohms vs TDR_results.t | ||
5489 | % TDR_results.t starting at t=0 | 5304 | % TDR_results.t starting at t=0 | ||
5490 | % TDR_results.tx_filter transmitter filter vs TDR_results.f | 5305 | % TDR_results.tx_filter transmitter filter vs TDR_results.f | ||
5491 | % TDR_results.Rx_filter receiver filter vs TDR_results.f | 5306 | % TDR_results.Rx_filter receiver filter vs TDR_results.f | ||
5492 | % TDR_results.f frequency for filter and s parameters | 5307 | % TDR_results.f frequency for filter and s parameters | ||
5493 | % TDR_results.ptdr_RL reflection waveform from the pulse | 5308 | % TDR_results.ptdr_RL reflection waveform from the pulse | ||
5494 | % TDR_results.WC_ptdr_samples_t worst case time sample of the reflection pulse | 5309 | % TDR_results.WC_ptdr_samples_t worst case time sample of the reflection pulse | ||
5495 | % TDR_results.WC_ptdr_samples worst case reflection samples of the reflection pulse | 5310 | % TDR_results.WC_ptdr_samples worst case reflection samples of the reflection pulse | ||
5496 | % TDR_results.ERL reported effective return loss | 5311 | % TDR_results.ERL reported effective return loss | ||
5497 | % | 5312 | % | ||
5498 | db = @(x) 20*log10(abs(x)); | 5313 | db = @(x) 20*log10(abs(x)); | ||
5499 | rms =@(x) norm(x)/sqrt(length(x)); | 5314 | rms =@(x) norm(x)/sqrt(length(x)); | ||
5500 | if isfield(OP,'TDR_duration') | 5315 | if isfield(OP,'TDR_duration') | ||
5501 | TDR_duration=OP.TDR_duration; % approximate transit time multipler | 5316 | TDR_duration=OP.TDR_duration; % approximate transit time multipler | ||
5502 | else | 5317 | else | ||
5503 | TDR_duration=5; | 5318 | TDR_duration=5; | ||
5504 | end | 5319 | end | ||
5505 | if ~isfield(OP,'DISPLAY_WINDOW') | 5320 | if ~isfield(OP,'DISPLAY_WINDOW') | ||
5506 | OP.DISPLAY_WINDOW=1; % approximate transit time multipler | 5321 | OP.DISPLAY_WINDOW=1; % approximate transit time multipler | ||
5507 | end | 5322 | end | ||
5508 | f=sdd.Frequencies; | 5323 | f=sdd.Frequencies; | ||
5509 | TDR_results.f=f; | 5324 | TDR_results.f=f; | ||
5510 | % OP.Zt_adj=2; | 5325 | % OP.Zt_adj=2; | ||
5511 | if param.FLAG.S2P == 0 | 5326 | if param.FLAG.S2P == 0 | ||
5512 |
| 5327 |
| ||
5513 | % re-normalize reference of s-parameterss: this seems correct for a s4p input file | 5328 | % re-normalize reference of s-parameterss: this seems correct for a s4p input file | ||
5514 | TDR_RL =@(Zin,Zout,s11,s12,s21,s22)(Zin.^2.*s11+Zin.^2.*s22+Zout.^2.*s11+Zout.^2.*s22+Zin.^2-Zout.^2+Zin.*Zout.*s11.*2.0-Zin.*Zout.*s22.*2.0+Zin.^2.*s11.*s22-Zin.^2.*s12.*s21-Zout.^2.*s11.*s22+Zout.^2.*s12.*s21)./(Zin.*Zout.*2.0+Zin.^2.*s11+Zin.^2.*s22-Zout.^2.*s11-Zout.^2.*s22+Zin.^2+Zout.^2+Zin.^2.*s11.*s22-Zin.^2.*s12.*s21+Zout.^2.*s11.*s22-Zout.^2.*s12.*s21-Zin.*Zout.*s11.*s22.*2.0+Zin.*Zout.*s12.*s21.*2.0); | 5329 | TDR_RL =@(Zin,Zout,s11,s12,s21,s22)(Zin.^2.*s11+Zin.^2.*s22+Zout.^2.*s11+Zout.^2.*s22+Zin.^2-Zout.^2+Zin.*Zout.*s11.*2.0-Zin.*Zout.*s22.*2.0+Zin.^2.*s11.*s22-Zin.^2.*s12.*s21-Zout.^2.*s11.*s22+Zout.^2.*s12.*s21)./(Zin.*Zout.*2.0+Zin.^2.*s11+Zin.^2.*s22-Zout.^2.*s11-Zout.^2.*s22+Zin.^2+Zout.^2+Zin.^2.*s11.*s22-Zin.^2.*s12.*s21+Zout.^2.*s11.*s22-Zout.^2.*s12.*s21-Zin.*Zout.*s11.*s22.*2.0+Zin.*Zout.*s12.*s21.*2.0); | ||
5515 |
| 5330 |
| ||
5516 | if param.RL_sel==1, other_port=2;end | 5331 | if param.RL_sel==1, other_port=2;end | ||
5517 | if param.RL_sel==2, other_port=1;end | 5332 | if param.RL_sel==2, other_port=1;end | ||
5518 | for i = 1:length(sdd.Frequencies) | 5333 | for i = 1:length(sdd.Frequencies) | ||
5519 | if size(sdd.Parameters,2) ==1 % for s2p files | 5334 | if size(sdd.Parameters,2) ==1 % for s2p files | ||
5520 | RL(i)=TDR_RL(sdd.Impedance,2*ZT,sdd.Parameters(param.RL_sel,param.RL_sel,i) ,1, 1 ,sdd.Parameters(param.RL_sel,param.RL_sel,i) ); | 5335 | RL(i)=TDR_RL(sdd.Impedance,2*ZT,sdd.Parameters(param.RL_sel,param.RL_sel,i) ,1, 1 ,sdd.Parameters(param.RL_sel,param.RL_sel,i) ); | ||
5521 | else | 5336 | else | ||
5522 | RL(i)=TDR_RL(sdd.Impedance,2*ZT,sdd.Parameters(param.RL_sel,param.RL_sel,i) ,sdd.Parameters( 1,2 ,i), sdd.Parameters( 2,1 ,i),sdd.Parameters( other_port,other_port ,i) ); | 5337 | RL(i)=TDR_RL(sdd.Impedance,2*ZT,sdd.Parameters(param.RL_sel,param.RL_sel,i) ,sdd.Parameters( 1,2 ,i), sdd.Parameters( 2,1 ,i),sdd.Parameters( other_port,other_port ,i) ); | ||
5523 | end | 5338 | end | ||
5524 | end | 5339 | end | ||
5525 | % elseif OP.Zt_adj ==2 % only adjust z_t drive impedance | 5340 | % elseif OP.Zt_adj ==2 % only adjust z_t drive impedance | ||
5526 | % RL=squeeze((sdd.Parameters(param.RL_sel,param.RL_sel,:))); | 5341 | % RL=squeeze((sdd.Parameters(param.RL_sel,param.RL_sel,:))); | ||
5527 | % Z_t=ZT; | 5342 | % Z_t=ZT; | ||
5528 | % zref=sdd.Impedance/2; | 5343 | % zref=sdd.Impedance/2; | ||
5529 | % if Z_t > zref | 5344 | % if Z_t > zref | ||
5530 | % radjust= (zref-Z_t); | 5345 | % radjust= (zref-Z_t); | ||
5531 | % S11adjust= radjust./(radjust + 2*zref); | 5346 | % S11adjust= radjust./(radjust + 2*zref); | ||
5532 | % RL=RL +S11adjust; | 5347 | % RL=RL +S11adjust; | ||
5533 | % elseif Z_t < zref | 5348 | % elseif Z_t < zref | ||
5534 | % rpad=-Z_t*zref/(Z_t-zref); | 5349 | % rpad=-Z_t*zref/(Z_t-zref); | ||
5535 | % S11adjust=zref/(rpad*(zref/rpad + 2)); | 5350 | % S11adjust=zref/(rpad*(zref/rpad + 2)); | ||
5536 | % RL=RL + S11adjust; | 5351 | % RL=RL + S11adjust; | ||
5537 | % else | 5352 | % else | ||
5538 | % RL=RL; | 5353 | % RL=RL; | ||
5539 | % end | 5354 | % end | ||
5540 | else | 5355 | else | ||
5541 | for i = 1:length(sdd.Frequencies) | 5356 | for i = 1:length(sdd.Frequencies) | ||
5542 | rho= (2*ZT - sdd.Impedance) / (2*ZT + sdd.Impedance); | 5357 | rho= (2*ZT - sdd.Impedance) / (2*ZT + sdd.Impedance); | ||
5543 | interim = sqrt(1-abs(rho)^2) * (1 - rho) / abs(1-rho); | 5358 | interim = sqrt(1-abs(rho)^2) * (1 - rho) / abs(1-rho); | ||
5544 | RL(i) = interim \ (sdd.Parameters(param.RL_sel,param.RL_sel,i) - rho) / ... | 5359 | RL(i) = interim \ (sdd.Parameters(param.RL_sel,param.RL_sel,i) - rho) / ... | ||
5545 | (1 - rho *sdd.Parameters(param.RL_sel,param.RL_sel,i) ) * interim; | 5360 | (1 - rho *sdd.Parameters(param.RL_sel,param.RL_sel,i) ) * interim; | ||
5546 | end | 5361 | end | ||
5547 | end | 5362 | end | ||
5548 | 5363 | ||||
5549 | % end | 5364 | % end | ||
5550 | RL=squeeze(RL); | 5365 | RL=squeeze(RL); | ||
5551 | f9=f/1e9; | 5366 | f9=f/1e9; | ||
5552 | tr=param.TR_TDR; | 5367 | tr=param.TR_TDR; | ||
5553 | TDR_results.delay=500e-12 ; | 5368 | TDR_results.delay=500e-12 ; | ||
5554 | % determine max time from thue | 5369 | % determine max time from thue | ||
5555 | % if sdd.NumPorts==1 | 5370 | % if sdd.NumPorts==1 | ||
5556 | % try | 5371 | % try | ||
5557 | % maxtime=OP.N*param.ui; | 5372 | % maxtime=OP.N*param.ui; | ||
5558 | % catch | 5373 | % catch | ||
5559 | % maxtime=2e-9; | 5374 | % maxtime=2e-9; | ||
5560 | % end | 5375 | % end | ||
5561 | % pix=1; | 5376 | % pix=1; | ||
5562 | % else | 5377 | % else | ||
5563 | % [ fir4del, tu] =get_RAW_FSIR(squeeze(sdd.Parameters(2,1,:)),f,OP,param); | 5378 | % [ fir4del, tu] =get_RAW_FSIR(squeeze(sdd.Parameters(2,1,:)),f,OP,param); | ||
5564 | % pix=find(fir4del==max(fir4del),1); | 5379 | % pix=find(fir4del==max(fir4del),1); | ||
5565 | % maxtime=tu(pix)*TDR_duration+TDR_results.delay; | 5380 | % maxtime=tu(pix)*TDR_duration+TDR_results.delay; | ||
5566 | % if maxtime > tu(end); maxtime=tu(end);end | 5381 | % if maxtime > tu(end); maxtime=tu(end);end | ||
5567 | % endS | 5382 | % endS | ||
5568 | 5383 | ||||
5569 | try | 5384 | try | ||
5570 | maxtime=OP.N*param.ui; | 5385 | maxtime=OP.N*param.ui; | ||
5571 | catch | 5386 | catch | ||
5572 | maxtime=2e-9; | 5387 | maxtime=2e-9; | ||
5573 | end | 5388 | end | ||
5574 | if OP.N==0 | 5389 | if OP.N==0 | ||
5575 | if sdd.NumPorts==1 | 5390 | if sdd.NumPorts==1 | ||
5576 | fprintf('<strong> Warning for s2p files N must not be zero<\strong> '); | 5391 | fprintf('<strong> Warning for s2p files N must not be zero<\strong> '); | ||
5577 | else | 5392 | else | ||
5578 | [ fir4del, tu] =get_RAW_FIR(squeeze(sdd.Parameters(2,1,:)),f,OP,param); | 5393 | [ fir4del, tu] =get_RAW_FIR(squeeze(sdd.Parameters(2,1,:)),f,OP,param); | ||
5579 | pix=find(fir4del==max(fir4del),1); | 5394 | pix=find(fir4del==max(fir4del),1); | ||
5580 | maxtime=tu(pix)*TDR_duration+TDR_results.delay; | 5395 | maxtime=tu(pix)*TDR_duration+TDR_results.delay; | ||
5581 | if maxtime > tu(end); maxtime=tu(end);end | 5396 | if maxtime > tu(end); maxtime=tu(end);end | ||
5582 | end | 5397 | end | ||
5583 | end | 5398 | end | ||
5584 | 5399 | ||||
5585 | 5400 | ||||
5586 | % add delay 500 ps for TDR and 3 times Gaussnan transtion time | 5401 | % add delay 500 ps for TDR and 3 times Gaussnan transtion time | ||
5587 | % (makes gausian edge somewhat causal) | 5402 | % (makes gausian edge somewhat causal) | ||
5588 | H_t = exp( -2*(pi*f9*(tr)/1.6832).^2 ).*exp(-(1j)*2*pi*f9*TDR_results.delay/1e-9).*exp(-1j*2*pi*f9*tr*3); | 5403 | H_t = exp( -2*(pi*f9*(tr)/1.6832).^2 ).*exp(-(1j)*2*pi*f9*TDR_results.delay/1e-9).*exp(-1j*2*pi*f9*tr*3); | ||
5589 | if ~isfield(OP,'cb_Guassian') | 5404 | if ~isfield(OP,'cb_Guassian') | ||
5590 | Use_gaussian=1; | 5405 | Use_gaussian=1; | ||
5591 | else | 5406 | else | ||
5592 | Use_gaussian=OP.cb_Guassian; | 5407 | Use_gaussian=OP.cb_Guassian; | ||
5593 | end | 5408 | end | ||
5594 | if Use_gaussian | 5409 | if Use_gaussian | ||
5595 | if iscolumn(H_t), H_t=H_t.'; end | 5410 | if iscolumn(H_t), H_t=H_t.'; end | ||
5596 | RLf=RL(:).'.*H_t; | 5411 | RLf=RL(:).'.*H_t; | ||
5597 | else % add extra 3x tr delay for causality | 5412 | else % add extra 3x tr delay for causality | ||
5598 | RLf=RL.*exp(-(1j)*2*pi*f9*TDR_results.delay/1e-9); | 5413 | RLf=RL.*exp(-(1j)*2*pi*f9*TDR_results.delay/1e-9); | ||
5599 | end | 5414 | end | ||
5600 | 5415 | ||||
5601 | %Bessesl-Thomson turned off here (3rd input=0) | 5416 | %Bessesl-Thomson turned off here (3rd input=0) | ||
5602 | H_bt=Bessel_Thomson_Filter(param,f,0); | 5417 | H_bt=Bessel_Thomson_Filter(param,f,0); | ||
5603 | 5418 | ||||
5604 | if isfield(OP,'TDR_Butterworth') | 5419 | if isfield(OP,'TDR_Butterworth') | ||
5605 | H_bw=Butterworth_Filter(param,f,OP.TDR_Butterworth); | 5420 | H_bw=Butterworth_Filter(param,f,OP.TDR_Butterworth); | ||
5606 | else | 5421 | else | ||
5607 | H_bw=ones(1,length(f)); | 5422 | H_bw=ones(1,length(f)); | ||
5608 | end | 5423 | end | ||
5609 | 5424 | ||||
5610 | 5425 | ||||
5611 | if param.Tukey_Window ~= 0 | 5426 | if param.Tukey_Window ~= 0 | ||
5612 | H_tw= Tukey_Window(f,param); | 5427 | H_tw= Tukey_Window(f,param); | ||
5613 | else | 5428 | else | ||
5614 | H_tw=ones(1,length(f)); | 5429 | H_tw=ones(1,length(f)); | ||
5615 | end | 5430 | end | ||
5616 | 5431 | ||||
5617 | 5432 | ||||
5618 | if iscolumn(H_tw), H_tw=H_tw.';end | 5433 | if iscolumn(H_tw), H_tw=H_tw.';end | ||
5619 | if iscolumn(H_bt), H_bt=H_bt.';end | 5434 | if iscolumn(H_bt), H_bt=H_bt.';end | ||
5620 | if iscolumn(H_bw), H_bw=H_bw.';end | 5435 | if iscolumn(H_bw), H_bw=H_bw.';end | ||
5621 | if iscolumn(RLf), RLf=RLf.';end | 5436 | if iscolumn(RLf), RLf=RLf.';end | ||
5622 | 5437 | ||||
5623 | TDR_results.Rx_filter=H_bt.*H_bw.*H_tw; | 5438 | TDR_results.Rx_filter=H_bt.*H_bw.*H_tw; | ||
5624 | RLf=RLf.*TDR_results.Rx_filter; | 5439 | RLf=RLf.*TDR_results.Rx_filter; | ||
5625 | TDR_results.tx_filter=H_t; | 5440 | TDR_results.tx_filter=H_t; | ||
5626 | 5441 | ||||
5627 | 5442 | ||||
5628 | [IR, t, causality_correction_dB, truncation_dB] = ... | 5443 | [IR, t, causality_correction_dB, truncation_dB] = ... | ||
5629 | s21_to_impulse_DC(RLf, sdd.Frequencies(:), param.sample_dt,OP); | 5444 | s21_to_impulse_DC(RLf, sdd.Frequencies(:), param.sample_dt,OP); | ||
5630 | 5445 | ||||
5631 | 5446 | ||||
5632 | % | 5447 | % | ||
5633 | % param.tfx =4.2e-10; % need to put in xls file and comment this out | 5448 | % param.tfx =4.2e-10; % need to put in xls file and comment this out | ||
5634 | tfx=param.tfx(np); % use fixture delay for port (np) | 5449 | tfx=param.tfx(np); % use fixture delay for port (np) | ||
5635 | 5450 | ||||
5636 | % IR(abs(IR)<=OP.impulse_response_truncation_threshold)=0; % noise filter | 5451 | % IR(abs(IR)<=OP.impulse_response_truncation_threshold)=0; % noise filter | ||
5637 | 5452 | ||||
5638 | t = t-TDR_results.delay; | 5453 | t = t-TDR_results.delay; | ||
5639 | tend=find(t>=maxtime+tfx,1); % n starts at tfx | 5454 | tend=find(t>=maxtime+tfx,1); % n starts at tfx | ||
5640 | if isempty(tend), tend=length(t); end | 5455 | if isempty(tend), tend=length(t); end | ||
5641 | IR=IR(1:tend); | 5456 | IR=IR(1:tend); | ||
5642 | t=t(1:tend); | 5457 | t=t(1:tend); | ||
5643 | if isempty(tend), tend=length(t); end | 5458 | if isempty(tend), tend=length(t); end | ||
5644 | tstart=find(t>=tr*1e-9,1); % account for Gaussian precursor | 5459 | tstart=find(t>=tr*1e-9,1); % account for Gaussian precursor | ||
5645 | if isempty(tstart), tstart=1;end | 5460 | if isempty(tstart), tstart=1;end | ||
5646 | if isempty(tend) || tstart >= tend | 5461 | if isempty(tend) || tstart >= tend | ||
5647 | if isempty(tend) || tstart >= tend | 5462 | if isempty(tend) || tstart >= tend | ||
5648 | % warndlg('TDR compuation not valid, try decreasing truncation tolerance, increasing samples, or adding a transmisson line','WrnTDR'); | 5463 | % warndlg('TDR compuation not valid, try decreasing truncation tolerance, increasing samples, or adding a transmisson line','WrnTDR'); | ||
5649 | end | 5464 | end | ||
5650 | tend=length(t); | 5465 | tend=length(t); | ||
5651 | tstart=1; | 5466 | tstart=1; | ||
5652 | end | 5467 | end | ||
5653 | OP.cb_step=0; % step is a basically a cos^2 form -pi/4 to 0. not activated. | 5468 | OP.cb_step=0; % step is a basically a cos^2 form -pi/4 to 0. not activated. | ||
5654 | ch=get_StepR(IR(tstart:tend),param,OP.cb_step,ZT); | 5469 | ch=get_StepR(IR(tstart:tend),param,OP.cb_step,ZT); | ||
5655 | TDR_results.tdr= ch.ZSR; | 5470 | TDR_results.tdr= ch.ZSR; | ||
5656 | TDR_results.t = t(tstart:tend); | 5471 | TDR_results.t = t(tstart:tend); | ||
5657 | 5472 | ||||
5658 | PTDR=get_PulseR(IR(tstart:tend),param,OP.cb_step,ZT); | 5473 | PTDR=get_PulseR(IR(tstart:tend),param,OP.cb_step,ZT); | ||
5659 | if OP.TDR || OP.PTDR % determin average impededance with | 5474 | if OP.TDR || OP.PTDR % determin average impededance with | ||
5660 | try | 5475 | try | ||
5661 | tfstart=find(t>=3*tr*1e-9,1); | 5476 | tfstart=find(t>=3*tr*1e-9,1); | ||
5662 | x=squeeze(TDR_results.t(tfstart:end));TDR_results.x=TDR_results.tdr(:); | 5477 | x=squeeze(TDR_results.t(tfstart:end));TDR_results.x=TDR_results.tdr(:); | ||
5663 | y=squeeze(TDR_results.tdr(tfstart:end));TDR_results.y=TDR_results.t(:); | 5478 | y=squeeze(TDR_results.tdr(tfstart:end));TDR_results.y=TDR_results.t(:); | ||
5664 | w= exp(-(x-x(1))/OP.T_k ) ; % weighting function | 5479 | w= exp(-(x-x(1))/OP.T_k ) ; % weighting function | ||
5665 | TDR_results.avgZport=mean(y.*w.')/mean(w.'); | 5480 | TDR_results.avgZport=mean(y.*w.')/mean(w.'); | ||
5666 | catch | 5481 | catch | ||
5667 | TDR_results.avgZport=0; | 5482 | TDR_results.avgZport=0; | ||
5668 | fit=zeros(1,1); | 5483 | fit=zeros(1,1); | ||
5669 | p=[0 0 0 0 ]; | 5484 | p=[0 0 0 0 ]; | ||
5670 | end | 5485 | end | ||
5671 | TDR_results.RL=RL; | 5486 | TDR_results.RL=RL; | ||
5672 | end | 5487 | end | ||
5673 | if OP.PTDR | 5488 | if OP.PTDR | ||
5674 | % param.N_bx=param.ndfe; | 5489 | % param.N_bx=param.ndfe; | ||
5675 | RL_equiv=-inf; | 5490 | RL_equiv=-inf; | ||
5676 | L=param.levels; | 5491 | L=param.levels; | ||
5677 | BinSize=OP.BinSize; | 5492 | BinSize=OP.BinSize; | ||
5678 | % param.specBER=1e-5; | 5493 | % param.specBER=1e-5; | ||
5679 | if OP.DISPLAY_WINDOW | 5494 | if OP.DISPLAY_WINDOW | ||
5680 | hwaitbar=waitbar(0); | 5495 | hwaitbar=waitbar(0); | ||
5681 | else | 5496 | else | ||
5682 | fprintf('Worst ERL searching'); | 5497 | fprintf('Worst ERL searching'); | ||
5683 | end | 5498 | end | ||
5684 | % adjust PTDR for NDFE | 5499 | % adjust PTDR for NDFE | ||
5685 | % ---------------------- 2.7 code | 5500 | % ---------------------- 2.7 code | ||
5686 | % ntx=find(TDR_results.t >= tfx,1,'first'); | 5501 | % ntx=find(TDR_results.t >= tfx,1,'first'); | ||
5687 | % % gatestartt=TDR_results.t(ntx); | 5502 | % % gatestartt=TDR_results.t(ntx); | ||
5688 | % % gatestartV=PTDR.pulse(ntx); | 5503 | % % gatestartV=PTDR.pulse(ntx); | ||
5689 | % ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx,1,'first'); | 5504 | % ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx,1,'first'); | ||
5690 | % tk=param.ui*1*(param.N_bx+1)+tfx; | 5505 | % tk=param.ui*1*(param.N_bx+1)+tfx; | ||
5691 | % ------------------- | 5506 | % ------------------- | ||
5692 | % [ahealey 09/06/2019] Need to account for the 3*TR_TDR delay included in the rise | 5507 | % [ahealey 09/06/2019] Need to account for the 3*TR_TDR delay included in the rise | ||
5693 | % time filter. | 5508 | % time filter. | ||
5694 | % ntx=find(TDR_results.t >= tfx,1,'first'); | 5509 | % ntx=find(TDR_results.t >= tfx,1,'first'); | ||
5695 | ntx=find(TDR_results.t >= tfx+3*tr*1e-9,1,'first'); | 5510 | ntx=find(TDR_results.t >= tfx+3*tr*1e-9,1,'first'); | ||
5696 | % gatestartt=TDR_results.t(ntx); | 5511 | % gatestartt=TDR_results.t(ntx); | ||
5697 | % gatestartV=PTDR.pulse(ntx); | 5512 | % gatestartV=PTDR.pulse(ntx); | ||
5698 | % ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx,1,'first'); | 5513 | % ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx,1,'first'); | ||
5699 | % tk=param.ui*1*(param.N_bx+1)+tfx; | 5514 | % tk=param.ui*1*(param.N_bx+1)+tfx; | ||
5700 | ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx+3*tr*1e-9,1,'first'); | 5515 | ndfex=find(TDR_results.t > (param.N_bx+1)*param.ui+tfx+3*tr*1e-9,1,'first'); | ||
5701 | tk=param.ui*1*(param.N_bx+1)+tfx+3*tr*1e-9; | 5516 | tk=param.ui*1*(param.N_bx+1)+tfx+3*tr*1e-9; | ||
5702 | % [ahealey] End of modifications. | 5517 | % [ahealey] End of modifications. | ||
5703 | if isempty(ndfex), ndfex=length(TDR_results.t); end | 5518 | if isempty(ndfex), ndfex=length(TDR_results.t); end | ||
5704 | PTDR.pulse_orig=PTDR.pulse; | 5519 | PTDR.pulse_orig=PTDR.pulse; | ||
5705 |
| 5520 |
| ||
5706 | switch param.Grr | 5521 | switch param.Grr | ||
5707 | case 0 % pre .3cd release | 5522 | case 0 % pre .3cd release | ||
5708 | fctrx(1:length(PTDR.pulse_orig))=(1+param.rho_x)*param.rho_x; | 5523 | fctrx(1:length(PTDR.pulse_orig))=(1+param.rho_x)*param.rho_x; | ||
5709 | case 1 % .3cd release | 5524 | case 1 % .3cd release | ||
5710 | fctrx(1:length(PTDR.pulse_orig))=1; | 5525 | fctrx(1:length(PTDR.pulse_orig))=1; | ||
5711 | case 2 % .3ck working | 5526 | case 2 % .3ck working | ||
5712 | fctrx(1:length(PTDR.pulse_orig))=1; | 5527 | fctrx(1:length(PTDR.pulse_orig))=1; | ||
5713 | end | 5528 | end | ||
5714 | Gloss(1:length(TDR_results.t))=1; | 5529 | Gloss(1:length(TDR_results.t))=1; | ||
5715 | Grr(1:length(TDR_results.t))=1; | 5530 | Grr(1:length(TDR_results.t))=1; | ||
5716 | fctrx(1:ntx)=0; % moved out of loop for beta x and n_bx | 5531 | fctrx(1:ntx)=0; % moved out of loop for beta x and n_bx | ||
5717 |
| 5532 |
| ||
5718 | for ii=ntx:ndfex | 5533 | for ii=ntx:ndfex | ||
5719 | % adjust for near end loss | 5534 | % adjust for near end loss | ||
5720 | if param.N_bx>0 && param.beta_x~=0; | 5535 | if param.N_bx>0 && param.beta_x~=0; | ||
5721 | Gloss(ii)= 10.^(param.beta_x*(TDR_results.t(ii)-tk)/20); | 5536 | Gloss(ii)= 10.^(param.beta_x*(TDR_results.t(ii)-tk)/20); | ||
5722 | else | 5537 | else | ||
5723 | Gloss(ii)=1; | 5538 | Gloss(ii)=1; | ||
5724 | end | 5539 | end | ||
5725 | % ---------------------- 2.7 code | 5540 | % ---------------------- 2.7 code | ||
5726 | % x=(TDR_results.t(ii)-tfx)/param.ui; | 5541 | % x=(TDR_results.t(ii)-tfx)/param.ui; | ||
5727 | % ---------------------- | 5542 | % ---------------------- | ||
5728 | % [ahealey9/06/2019] Need to account for the 3*TR_TDR delay included in the | 5543 | % [ahealey9/06/2019] Need to account for the 3*TR_TDR delay included in the | ||
5729 | % rise time filter. | 5544 | % rise time filter. | ||
5730 | % x=(TDR_results.t(ii)-tfx)/param.ui; | 5545 | % x=(TDR_results.t(ii)-tfx)/param.ui; | ||
5731 | x=(TDR_results.t(ii)-tfx-3*tr*1e-9)/param.ui; | 5546 | x=(TDR_results.t(ii)-tfx-3*tr*1e-9)/param.ui; | ||
5732 | % determine how much of the return loss to use base on expected | 5547 | % determine how much of the return loss to use base on expected | ||
5733 | % missing reflections | 5548 | % missing reflections | ||
5734 | switch param.Grr | 5549 | switch param.Grr | ||
5735 | case 0 % pre .3cd release | 5550 | case 0 % pre .3cd release | ||
5736 | Grr(ii)= (1+param.rho_x)*param.rho_x*exp(-(x-1*param.N_bx-1).^2/(1+param.N_bx)^2); | 5551 | Grr(ii)= (1+param.rho_x)*param.rho_x*exp(-(x-1*param.N_bx-1).^2/(1+param.N_bx)^2); | ||
5737 | case 1 % .3cd release | 5552 | case 1 % .3cd release | ||
5738 | Grr(ii)= (1+param.rho_x)*param.rho_x*exp(-(x-1*param.N_bx-1).^2/(1+param.N_bx)^2); | 5553 | Grr(ii)= (1+param.rho_x)*param.rho_x*exp(-(x-1*param.N_bx-1).^2/(1+param.N_bx)^2); | ||
5739 | case 2 % .3ck working | 5554 | case 2 % .3ck working | ||
5740 | Grr(ii)= param.rho_x ; | 5555 | Grr(ii)= param.rho_x ; | ||
5741 | end | 5556 | end | ||
5742 | fctrx(ii)=Gloss(ii).*Grr(ii); | 5557 | fctrx(ii)=Gloss(ii).*Grr(ii); | ||
5743 | end | 5558 | end | ||
5744 |
| 5559 |
| ||
5745 | if isrow(fctrx), fctrx=fctrx(:);end | 5560 | if isrow(fctrx), fctrx=fctrx(:);end | ||
5746 | PTDR.pulse=PTDR.pulse.*fctrx; | 5561 | PTDR.pulse=PTDR.pulse.*fctrx; | ||
5747 | if 0 | 5562 | if 0 | ||
5748 | figure(10101+param.RL_sel);set(gcf,'Tag','COM'); | 5563 | figure(10101+param.RL_sel);set(gcf,'Tag','COM'); | ||
5749 | s1=subplot(2,1,1); | 5564 | s1=subplot(2,1,1); | ||
5750 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,fctrx(ntx:end),'disp','G_l_o_s_s*G_r_r'); | 5565 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,fctrx(ntx:end),'disp','G_l_o_s_s*G_r_r'); | ||
5751 | hold on | 5566 | hold on | ||
5752 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,Gloss(ntx:end),'disp','G_l_o_s_s'); | 5567 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,Gloss(ntx:end),'disp','G_l_o_s_s'); | ||
5753 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,Grr(ntx:end),'disp','G_r_r'); | 5568 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,Grr(ntx:end),'disp','G_r_r'); | ||
5754 | grid on | 5569 | grid on | ||
5755 | ylim([ 0 1.2]) | 5570 | ylim([ 0 1.2]) | ||
5756 | s2=subplot(2,1,2); | 5571 | s2=subplot(2,1,2); | ||
5757 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,PTDR.pulse(ntx:end)./fctrx(ntx:end),'disp','PTDR'); | 5572 | plot((TDR_results.t(ntx:end)- TDR_results.t(ntx))/param.ui,PTDR.pulse(ntx:end)./fctrx(ntx:end),'disp','PTDR'); | ||
5758 | grid on | 5573 | grid on | ||
5759 | linkaxes([s1,s2],'x') | 5574 | linkaxes([s1,s2],'x') | ||
5760 | xlabel 'UI' | 5575 | xlabel 'UI' | ||
5761 | xlim ([ 1 200]) | 5576 | xlim ([ 1 200]) | ||
5762 | end | 5577 | end | ||
5763 |
| 5578 |
| ||
5764 | FAST_NOISE_CONV=0; | 5579 | FAST_NOISE_CONV=0; | ||
5765 | ERLRMS=rms(PTDR.pulse); | 5580 | ERLRMS=rms(PTDR.pulse); | ||
5766 | for ki=1:param.samples_per_ui | 5581 | for ki=1:param.samples_per_ui | ||
5767 | progress = ki/param.samples_per_ui; | 5582 | progress = ki/param.samples_per_ui; | ||
5768 | if OP.DISPLAY_WINDOW | 5583 | if OP.DISPLAY_WINDOW | ||
5769 | waitbar(progress, hwaitbar, 'ERL computing'); figure(hwaitbar); drawnow; | 5584 | waitbar(progress, hwaitbar, 'ERL computing'); figure(hwaitbar); drawnow; | ||
5770 | else | 5585 | else | ||
5771 | if ~mod(progress*100,1), fprintf('%i%% ', progress*100 );end | 5586 | if ~mod(progress*100,1), fprintf('%i%% ', progress*100 );end | ||
5772 | end | 5587 | end | ||
5773 | tps=PTDR.pulse(ki:param.samples_per_ui:end); | 5588 | tps=PTDR.pulse(ki:param.samples_per_ui:end); | ||
5774 | if OP.RL_norm_test | 5589 | if OP.RL_norm_test | ||
5775 | rl_fom=(norm(tps)); | 5590 | rl_fom=(norm(tps)); | ||
5776 | else | 5591 | else | ||
5777 | testpdf=get_pdf_from_sampled_signal( tps,L, BinSize*10, FAST_NOISE_CONV ); | 5592 | testpdf=get_pdf_from_sampled_signal( tps,L, BinSize*10, FAST_NOISE_CONV ); | ||
5778 | cdf_test=cumsum(testpdf.y); | 5593 | cdf_test=cumsum(testpdf.y); | ||
5779 | rl_test=(-testpdf.x(find(cdf_test>=param.specBER,1,'first'))); | 5594 | rl_test=(-testpdf.x(find(cdf_test>=param.specBER,1,'first'))); | ||
5780 | rl_fom=rl_test; | 5595 | rl_fom=rl_test; | ||
5781 | end | 5596 | end | ||
5782 | if rl_fom > RL_equiv | 5597 | if rl_fom > RL_equiv | ||
5783 | RL_equiv=rl_fom; | 5598 | RL_equiv=rl_fom; | ||
5784 | best_ki=ki; | 5599 | best_ki=ki; | ||
5785 | end | 5600 | end | ||
5786 | if ~OP.RL_norm_test | 5601 | if ~OP.RL_norm_test | ||
5787 | best_erl=rl_test; | 5602 | best_erl=rl_test; | ||
5788 | best_pdf=testpdf; | 5603 | best_pdf=testpdf; | ||
5789 | best_cdf=cdf_test; | 5604 | best_cdf=cdf_test; | ||
5790 | end | 5605 | end | ||
5791 |
| 5606 |
| ||
5792 | end | 5607 | end | ||
5793 | if OP.RL_norm_test | 5608 | if OP.RL_norm_test | ||
5794 | tps=PTDR.pulse(best_ki:param.samples_per_ui:end); | 5609 | tps=PTDR.pulse(best_ki:param.samples_per_ui:end); | ||
5795 | testpdf=get_pdf_from_sampled_signal( tps,L, BinSize*10, FAST_NOISE_CONV ); | 5610 | testpdf=get_pdf_from_sampled_signal( tps,L, BinSize*10, FAST_NOISE_CONV ); | ||
5796 | cdf_test=cumsum(testpdf.y); | 5611 | cdf_test=cumsum(testpdf.y); | ||
5797 | best_erl=(-testpdf.x(find(cdf_test>=param.specBER,1,'first'))); | 5612 | best_erl=(-testpdf.x(find(cdf_test>=param.specBER,1,'first'))); | ||
5798 | end | 5613 | end | ||
5799 |
| 5614 |
| ||
5800 | fprintf('\n'); | 5615 | fprintf('\n'); | ||
5801 | try | 5616 | try | ||
5802 | close(hwaitbar) | 5617 | close(hwaitbar) | ||
5803 | catch | 5618 | catch | ||
5804 | end | 5619 | end | ||
5805 | if ~exist('best_ki','var'),best_ki=1;end | 5620 | if ~exist('best_ki','var'),best_ki=1;end | ||
5806 | TDR_results.ptdr_RL=PTDR.pulse; % reflection waveform from the pulse | 5621 | TDR_results.ptdr_RL=PTDR.pulse; % reflection waveform from the pulse | ||
5807 | TDR_results.WC_ptdr_samples_t=TDR_results.t(best_ki:param.samples_per_ui:end); | 5622 | TDR_results.WC_ptdr_samples_t=TDR_results.t(best_ki:param.samples_per_ui:end); | ||
5808 | TDR_results.WC_ptdr_samples=PTDR.pulse(best_ki:param.samples_per_ui:end); | 5623 | TDR_results.WC_ptdr_samples=PTDR.pulse(best_ki:param.samples_per_ui:end); | ||
5809 | TDR_results.ERL=-db(best_erl); | 5624 | TDR_results.ERL=-db(best_erl); | ||
5810 | TDR_results.ERLRMS=-db(ERLRMS); | 5625 | TDR_results.ERLRMS=-db(ERLRMS); | ||
5811 |
| 5626 |
| ||
5812 | end | 5627 | end | ||
5813 | 5628 | ||||
5814 | 5629 | ||||
5815 | % end get TDR | 5630 | % end get TDR | ||
5816 | %% | 5631 | %% | ||
5817 | 5632 | ||||
5818 | 5633 | ||||
5819 | 5634 | ||||
5820 | 5635 | ||||
5821 | function [chdata, param] = get_TD_files(param, OP, num_fext, num_next, file_list) | 5636 | function [chdata, param] = get_TD_files(param, OP, num_fext, num_next, file_list) | ||
5822 | % filename parsing and acquisition | 5637 | % filename parsing and acquisition | ||
5823 | %------------------------------------------------------------------ | 5638 | %------------------------------------------------------------------ | ||
5824 | %----------put files names into chdata structure --------- | 5639 | %----------put files names into chdata structure --------- | ||
5825 | % The thru file has the index of 1 | 5640 | % The thru file has the index of 1 | ||
5826 | % crosstalk file are indexed from 2 | 5641 | % crosstalk file are indexed from 2 | ||
5827 | % nxi is incremented each time a file is read in so that nxi will end | 5642 | % nxi is incremented each time a file is read in so that nxi will end | ||
5828 | filepath=[]; % path name for file | 5643 | filepath=[]; % path name for file | ||
5829 | nxi=0; % file index | 5644 | nxi=0; % file index | ||
5830 | % get the THRU file | 5645 | % get the THRU file | ||
5831 | if size(file_list,2) ~= 0 | 5646 | if size(file_list,2) ~= 0 | ||
5832 | file_list(1)=strrep(file_list(1),'\', filesep); % OS file convention conversion | 5647 | file_list(1)=strrep(file_list(1),'\', filesep); % OS file convention conversion | ||
5833 | [filepath, basename, fileext]=fileparts(file_list{1}); | 5648 | [filepath, basename, fileext]=fileparts(file_list{1}); | ||
5834 |
| 5649 |
| ||
5835 | else | 5650 | else | ||
5836 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 5651 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
5837 | h = msgbox('enter test channel s-parameter file'); set(h,'Color',[1 .85 0]); | 5652 | h = msgbox('enter test channel s-parameter file'); set(h,'Color',[1 .85 0]); | ||
5838 | movegui(h,'northeast') | 5653 | movegui(h,'northeast') | ||
5839 | end | 5654 | end | ||
5840 | dir=fullfile(filepath, '*.csv'); | 5655 | dir=fullfile(filepath, '*.csv'); | ||
5841 | [basename,filepath]=uigetfile(dir,'input thru channel response .cav '); | 5656 | [basename,filepath]=uigetfile(dir,'input thru channel response .cav '); | ||
5842 | if filepath == 0 | 5657 | if filepath == 0 | ||
5843 | error('No Thru file') | 5658 | error('No Thru file') | ||
5844 | end | 5659 | end | ||
5845 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 5660 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
5846 | end | 5661 | end | ||
5847 | nxi=nxi+1; | 5662 | nxi=nxi+1; | ||
5848 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 5663 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
5849 | chdata(nxi).ext = fileext; | 5664 | chdata(nxi).ext = fileext; | ||
5850 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 5665 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
5851 | % chdata(nxi).base=[pth(max(strfind(pth,filesep))+1:end) '--' basename]; % add 1 directory back to basename | 5666 | % chdata(nxi).base=[pth(max(strfind(pth,filesep))+1:end) '--' basename]; % add 1 directory back to basename | ||
5852 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename]; % add 1 directory back to basename | 5667 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename]; % add 1 directory back to basename | ||
5853 | % chdata(nxi).A=param.A_thru; % pam encoding amplitude reduction is do in reporting but is comprehending in crosstalk PDF | 5668 | % chdata(nxi).A=param.A_thru; % pam encoding amplitude reduction is do in reporting but is comprehending in crosstalk PDF | ||
5854 | chdata(nxi).type='THRU'; | 5669 | chdata(nxi).type='THRU'; | ||
5855 | chdata(nxi).ftr=param.fb*param.f_v; | 5670 | chdata(nxi).ftr=param.fb*param.f_v; | ||
5856 | param.base=chdata(nxi).base; %for print out function that don't pass chdata | 5671 | param.base=chdata(nxi).base; %for print out function that don't pass chdata | ||
5857 | 5672 | ||||
5858 | % now get FEXT file names into chdata structure | 5673 | % now get FEXT file names into chdata structure | ||
5859 | kxi=nxi; | 5674 | kxi=nxi; | ||
5860 | for nxi=kxi+1:num_fext+kxi | 5675 | for nxi=kxi+1:num_fext+kxi | ||
5861 | lastfilepath=filepath; | 5676 | lastfilepath=filepath; | ||
5862 | if size(file_list,2) ~= 0 | 5677 | if size(file_list,2) ~= 0 | ||
5863 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | 5678 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | ||
5864 | else | 5679 | else | ||
5865 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 5680 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
5866 | h = msgbox('enter noise channel s-parameter file'); set(h,'Color',[1 .85 0]); | 5681 | h = msgbox('enter noise channel s-parameter file'); set(h,'Color',[1 .85 0]); | ||
5867 | movegui(h,'northeast') | 5682 | movegui(h,'northeast') | ||
5868 | end | 5683 | end | ||
5869 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2; | 5684 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2; | ||
5870 | dir=fullfile(filepath, '*.csv'); | 5685 | dir=fullfile(filepath, '*.csv'); | ||
5871 | [basename,filepath]=uigetfile(dir,'input noise channel response .csv'); | 5686 | [basename,filepath]=uigetfile(dir,'input noise channel response .csv'); | ||
5872 | if filepath==0 | 5687 | if filepath==0 | ||
5873 | error('Not enough NEXT files') | 5688 | error('Not enough NEXT files') | ||
5874 | end | 5689 | end | ||
5875 | else | 5690 | else | ||
5876 | dir=fullfile(filepath, '*.csv'); | 5691 | dir=fullfile(filepath, '*.csv'); | ||
5877 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 5692 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
5878 | [basename,filepath]=uigetfile(dir,'input noise channel response .csv'); | 5693 | [basename,filepath]=uigetfile(dir,'input noise channel response .csv'); | ||
5879 | else | 5694 | else | ||
5880 | [basename,filepath]=uigetfile(dir,['input fext channel response .csv #', num2str(nxi-kxi)]); | 5695 | [basename,filepath]=uigetfile(dir,['input fext channel response .csv #', num2str(nxi-kxi)]); | ||
5881 | end | 5696 | end | ||
5882 | if filepath==0 | 5697 | if filepath==0 | ||
5883 | error('Not enough NEXT files') | 5698 | error('Not enough NEXT files') | ||
5884 | end | 5699 | end | ||
5885 | end | 5700 | end | ||
5886 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 5701 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
5887 | end | 5702 | end | ||
5888 | if isempty( filepath), filepath=lastfilepath; end | 5703 | if isempty( filepath), filepath=lastfilepath; end | ||
5889 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 5704 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
5890 | chdata(nxi).ext = fileext; | 5705 | chdata(nxi).ext = fileext; | ||
5891 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 5706 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
5892 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | 5707 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | ||
5893 | % chdata(nxi).A=param.a_fext; | 5708 | % chdata(nxi).A=param.a_fext; | ||
5894 | chdata(nxi).ftr=param.fb*param.f_f; | 5709 | chdata(nxi).ftr=param.fb*param.f_f; | ||
5895 | chdata(nxi).type='FEXT'; | 5710 | chdata(nxi).type='FEXT'; | ||
5896 | end | 5711 | end | ||
5897 | % now get NEXT file names into chdata structure | 5712 | % now get NEXT file names into chdata structure | ||
5898 | kxi=num_fext+kxi; | 5713 | kxi=num_fext+kxi; | ||
5899 | for nxi=kxi+1:num_next+kxi | 5714 | for nxi=kxi+1:num_next+kxi | ||
5900 | lastfilepath=filepath; | 5715 | lastfilepath=filepath; | ||
5901 | if size(file_list,2) ~= 0 | 5716 | if size(file_list,2) ~= 0 | ||
5902 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | 5717 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | ||
5903 | else | 5718 | else | ||
5904 | dir=fullfile(filepath, '*.csv'); | 5719 | dir=fullfile(filepath, '*.csv'); | ||
5905 | [basename,filepath]=uigetfile(dir,['input next channel response .csv ', num2str(nxi-kxi)]); | 5720 | [basename,filepath]=uigetfile(dir,['input next channel response .csv ', num2str(nxi-kxi)]); | ||
5906 | if filepath==0 | 5721 | if filepath==0 | ||
5907 | error('Not enough NEXT files') | 5722 | error('Not enough NEXT files') | ||
5908 | end | 5723 | end | ||
5909 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 5724 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
5910 | end | 5725 | end | ||
5911 | if isempty( filepath), filepath=lastfilepath; end | 5726 | if isempty( filepath), filepath=lastfilepath; end | ||
5912 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 5727 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
5913 | chdata(nxi).ext = fileext; | 5728 | chdata(nxi).ext = fileext; | ||
5914 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 5729 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
5915 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | 5730 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | ||
5916 | % chdata(nxi).A=param.A_next; | 5731 | % chdata(nxi).A=param.A_next; | ||
5917 | chdata(nxi).ftr=param.fb*param.f_n; | 5732 | chdata(nxi).ftr=param.fb*param.f_n; | ||
5918 | chdata(nxi).type='NEXT'; | 5733 | chdata(nxi).type='NEXT'; | ||
5919 | end | 5734 | end | ||
5920 | function half_UI=get_center_of_UI(samples_per_UI) | 5735 | function half_UI=get_center_of_UI(samples_per_UI) | ||
5921 | 5736 | ||||
5922 | %half_UI reveals which value to use for the center of the UI. For eye | 5737 | %half_UI reveals which value to use for the center of the UI. For eye | ||
5923 | %width calculations, it is necessary to place the cursor in the center of the | 5738 | %width calculations, it is necessary to place the cursor in the center of the | ||
5924 | %UI window to ensure a 0 crossing on both left/right inside the window. | 5739 | %UI window to ensure a 0 crossing on both left/right inside the window. | ||
5925 | %This function was written in order to support even and odd samples_per_UI | 5740 | %This function was written in order to support even and odd samples_per_UI | ||
5926 | %and to prevent the ambiguity of using samples_per_UI/2 vs. samples_per_UI/2+1 | 5741 | %and to prevent the ambiguity of using samples_per_UI/2 vs. samples_per_UI/2+1 | ||
5927 | 5742 | ||||
5928 | %The UI window goes from 0 to 1 with 1/samples_per_UI steps | 5743 | %The UI window goes from 0 to 1 with 1/samples_per_UI steps | ||
5929 | UI_window=0:1/samples_per_UI:1-1/samples_per_UI; | 5744 | UI_window=0:1/samples_per_UI:1-1/samples_per_UI; | ||
5930 | %the center of the UI is sample closest to 0.5 | 5745 | %the center of the UI is sample closest to 0.5 | ||
5931 | [temp_diff,half_UI]=min(abs(UI_window-0.5)); | 5746 | [temp_diff,half_UI]=min(abs(UI_window-0.5)); | ||
5932 | function results= get_cm_noise(M,PR,L,BER,OP) | 5747 | function results= get_cm_noise(M,PR,L,BER,OP) | ||
5933 | 5748 | ||||
5934 | if ~exist('OP') | 5749 | if ~exist('OP') | ||
5935 | OP.DC_norm_test=0; | 5750 | OP.DC_norm_test=0; | ||
5936 | OP.DISPLAY_WINDOW=1; | 5751 | OP.DISPLAY_WINDOW=1; | ||
5937 | end | 5752 | end | ||
5938 | param.BinSize=1e-5; | 5753 | param.BinSize=1e-5; | ||
5939 | PR_test=-inf; | 5754 | PR_test=-inf; | ||
5940 | PR_fom_best=-inf; | 5755 | PR_fom_best=-inf; | ||
5941 | % hwaitbar=waitbar(0); | 5756 | % hwaitbar=waitbar(0); | ||
5942 | for ki=1:M | 5757 | for ki=1:M | ||
5943 | progress = ki/M; | 5758 | progress = ki/M; | ||
5944 | % if OP.DISPLAY_WINDOW | 5759 | % if OP.DISPLAY_WINDOW | ||
5945 | % waitbar(progress, hwaitbar, 'DM to CM computing'); figure(hwaitbar); drawnow; | 5760 | % waitbar(progress, hwaitbar, 'DM to CM computing'); figure(hwaitbar); drawnow; | ||
5946 | % else | 5761 | % else | ||
5947 | % if ~mod(progress*100,1), fprintf('%i%% ', progress*100 );end | 5762 | % if ~mod(progress*100,1), fprintf('%i%% ', progress*100 );end | ||
5948 | % end | 5763 | % end | ||
5949 | tps=PR(ki:M:end); | 5764 | tps=PR(ki:M:end); | ||
5950 | if OP.DC_norm_test | 5765 | if OP.DC_norm_test | ||
5951 | PR_fom=(norm(tps)); | 5766 | PR_fom=(norm(tps)); | ||
5952 | else | 5767 | else | ||
5953 | testpdf=get_pdf_from_sampled_signal( tps,L, param.BinSize*10 ); | 5768 | testpdf=get_pdf_from_sampled_signal( tps,L, param.BinSize*10 ); | ||
5954 | cdf_test=cumsum(testpdf.y); | 5769 | cdf_test=cumsum(testpdf.y); | ||
5955 | PRn_test=(-testpdf.x(find(cdf_test>=BER,1,'first'))); | 5770 | PRn_test=(-testpdf.x(find(cdf_test>=BER,1,'first'))); | ||
5956 | PR_fom=PRn_test; | 5771 | PR_fom=PRn_test; | ||
5957 | end | 5772 | end | ||
5958 | if PR_fom > PR_fom_best | 5773 | if PR_fom > PR_fom_best | ||
5959 | PR_fom_best=PR_fom; | 5774 | PR_fom_best=PR_fom; | ||
5960 | best_ki=ki; | 5775 | best_ki=ki; | ||
5961 | end | 5776 | end | ||
5962 | if ~OP.DC_norm_test | 5777 | if ~OP.DC_norm_test | ||
5963 | results.DCn=PR_fom_best; | 5778 | results.DCn=PR_fom_best; | ||
5964 | results.DCn_pdf=testpdf; | 5779 | results.DCn_pdf=testpdf; | ||
5965 | results.DCn_cdf=cdf_test; | 5780 | results.DCn_cdf=cdf_test; | ||
5966 | else | 5781 | else | ||
5967 | results.DCn=PR_fom_best; | 5782 | results.DCn=PR_fom_best; | ||
5968 | end | 5783 | end | ||
5969 | results.DCn_p2p=max(PR)-min(PR); | 5784 | results.DCn_p2p=max(PR)-min(PR); | ||
5970 | end | 5785 | end | ||
5971 | 5786 | ||||
5972 | 5787 | ||||
5973 | 5788 | ||||
5974 | function pdf=get_pdf(chdata, delta_y, t_s, param, OP,ixphase) | 5789 | function pdf=get_pdf(chdata, delta_y, t_s, param, OP,ixphase) | ||
5975 | SBR=chdata.eq_pulse_response(:)'; % row vector | 5790 | SBR=chdata.eq_pulse_response(:)'; % row vector | ||
5976 | type=chdata.type; | 5791 | type=chdata.type; | ||
5977 | samp_UI=param.samples_per_ui; | 5792 | samp_UI=param.samples_per_ui; | ||
5978 | residual_response = SBR; | 5793 | residual_response = SBR; | ||
5979 | 5794 | ||||
5980 | if isequal(type, 'THRU') | 5795 | if isequal(type, 'THRU') | ||
5981 | % for thru pulse response: | 5796 | % for thru pulse response: | ||
5982 | % remove the cursor and the DFE postcursors (up to their limit), since | 5797 | % remove the cursor and the DFE postcursors (up to their limit), since | ||
5983 | % we only care about the residuals. | 5798 | % we only care about the residuals. | ||
5984 |
| 5799 |
| ||
5985 | if ~param.Floating_DFE | 5800 | if ~param.Floating_DFE | ||
5986 | ideal_cancelled_cursors = SBR(t_s+param.samples_per_ui*(0:param.ndfe)); | 5801 | ideal_cancelled_cursors = SBR(t_s+param.samples_per_ui*(0:param.ndfe)); | ||
5987 | else | 5802 | else | ||
5988 | ideal_cancelled_cursors = SBR(t_s+param.samples_per_ui*(0:param.N_bmax)); | 5803 | ideal_cancelled_cursors = SBR(t_s+param.samples_per_ui*(0:param.N_bmax)); | ||
5989 | end | 5804 | end | ||
5990 | if param.dfe_delta ~= 0 | 5805 | if param.dfe_delta ~= 0 | ||
5991 | ideal_cancelled_cursors_q=floor(abs( ideal_cancelled_cursors/(residual_response(t_s).*param.dfe_delta) )).*residual_response(t_s)*param.dfe_delta.*sign(ideal_cancelled_cursors); | 5806 | ideal_cancelled_cursors_q=floor(abs( ideal_cancelled_cursors/(residual_response(t_s).*param.dfe_delta) )).*residual_response(t_s)*param.dfe_delta.*sign(ideal_cancelled_cursors); | ||
5992 | else | 5807 | else | ||
5993 | ideal_cancelled_cursors_q=ideal_cancelled_cursors; | 5808 | ideal_cancelled_cursors_q=ideal_cancelled_cursors; | ||
5994 | end | 5809 | end | ||
5995 |
| 5810 |
| ||
5996 | %AJG021820 | 5811 | %AJG021820 | ||
5997 | if ~param.Floating_DFE | 5812 | if ~param.Floating_DFE | ||
5998 | bmax_vec=residual_response(t_s)*[1,param.bmax]; | 5813 | bmax_vec=residual_response(t_s)*[1,param.bmax]; | ||
5999 | bmin_vec=residual_response(t_s)*[1,param.bmin]; | 5814 | bmin_vec=residual_response(t_s)*[1,param.bmin]; | ||
6000 | else | 5815 | else | ||
6001 | bmax_vec=residual_response(t_s)*[1,param.use_bmax]; | 5816 | bmax_vec=residual_response(t_s)*[1,param.use_bmax]; | ||
6002 | bmin_vec=residual_response(t_s)*[1,param.use_bmin]; | 5817 | bmin_vec=residual_response(t_s)*[1,param.use_bmin]; | ||
6003 | end | 5818 | end | ||
6004 | effective_cancelled_cursors=dfe_clipper(ideal_cancelled_cursors_q,bmax_vec,bmin_vec); | 5819 | effective_cancelled_cursors=dfe_clipper(ideal_cancelled_cursors_q,bmax_vec,bmin_vec); | ||
6005 |
| 5820 |
| ||
6006 |
| 5821 |
| ||
6007 | effective_cancellation_samples = kron(effective_cancelled_cursors, ones(1, param.samples_per_ui)); | 5822 | effective_cancellation_samples = kron(effective_cancelled_cursors, ones(1, param.samples_per_ui)); | ||
6008 | dfetaps=effective_cancelled_cursors/SBR(t_s); | 5823 | dfetaps=effective_cancelled_cursors/SBR(t_s); | ||
6009 |
| 5824 |
| ||
6010 | % Apply a constant DFE coefficient 1/2 UI before and after each postcursor. Not | 5825 | % Apply a constant DFE coefficient 1/2 UI before and after each postcursor. Not | ||
6011 | % really needed for COM, but helps debugging. May be factored out in future revisions. | 5826 | % really needed for COM, but helps debugging. May be factored out in future revisions. | ||
6012 | start_cancel = t_s-param.samples_per_ui/2; | 5827 | start_cancel = t_s-param.samples_per_ui/2; | ||
6013 | if ~param.Floating_DFE | 5828 | if ~param.Floating_DFE | ||
6014 | end_cancel = t_s+(1/2+param.ndfe)*param.samples_per_ui - 1; | 5829 | end_cancel = t_s+(1/2+param.ndfe)*param.samples_per_ui - 1; | ||
6015 | else | 5830 | else | ||
6016 | end_cancel = t_s+(1/2+param.N_bmax)*param.samples_per_ui - 1; | 5831 | end_cancel = t_s+(1/2+param.N_bmax)*param.samples_per_ui - 1; | ||
6017 | end | 5832 | end | ||
6018 | residual_response(start_cancel:end_cancel) = ... | 5833 | residual_response(start_cancel:end_cancel) = ... | ||
6019 | residual_response(start_cancel:end_cancel) - effective_cancellation_samples; | 5834 | residual_response(start_cancel:end_cancel) - effective_cancellation_samples; | ||
6020 | %else | 5835 | %else | ||
6021 | % for crosstalk pulse responses, nothing is cancelled, and all phases | 5836 | % for crosstalk pulse responses, nothing is cancelled, and all phases | ||
6022 | % are equally important. | 5837 | % are equally important. | ||
6023 | end | 5838 | end | ||
6024 | 5839 | ||||
6025 | nui=round(length(residual_response)/param.samples_per_ui); | 5840 | nui=round(length(residual_response)/param.samples_per_ui); | ||
6026 | 5841 | ||||
6027 | vs=zeros(nui-2, param.samples_per_ui); | 5842 | vs=zeros(nui-2, param.samples_per_ui); | ||
6028 | for i=1:param.samples_per_ui | 5843 | for i=1:param.samples_per_ui | ||
6029 | vs(:,i)=residual_response(param.samples_per_ui*(1:nui-2)+i); | 5844 | vs(:,i)=residual_response(param.samples_per_ui*(1:nui-2)+i); | ||
6030 | end | 5845 | end | ||
6031 | 5846 | ||||
6032 | if OP.DISPLAY_WINDOW, | 5847 | if OP.DISPLAY_WINDOW, | ||
6033 | hwaitbar=waitbar(0); | 5848 | hwaitbar=waitbar(0); | ||
6034 | end | 5849 | end | ||
6035 | 5850 | ||||
6036 | % determine which pdf to use | 5851 | % determine which pdf to use | ||
6037 | if isequal(type, 'THRU') | 5852 | if isequal(type, 'THRU') | ||
6038 | % one phase is interesting for thru | 5853 | % one phase is interesting for thru | ||
6039 | phases = mod(t_s,param.samples_per_ui); | 5854 | phases = mod(t_s,param.samples_per_ui); | ||
6040 | if phases==0, phases = param.samples_per_ui; end | 5855 | if phases==0, phases = param.samples_per_ui; end | ||
6041 | else | 5856 | else | ||
6042 | phases=1:samp_UI; | 5857 | phases=1:samp_UI; | ||
6043 | end | 5858 | end | ||
6044 | 5859 | ||||
6045 | mxV = zeros(size(phases)); | 5860 | mxV = zeros(size(phases)); | ||
6046 | % we already found the phase in the PSD process for MMSE | 5861 | % we already found the phase in the PSD process for MMSE | ||
6047 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | 5862 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | ||
6048 | if isequal(type, 'THRU') | 5863 | if isequal(type, 'THRU') | ||
6049 | pdf=get_pdf_from_sampled_signal(vs(:,phases), param.levels, delta_y); %#ok<AGROW> | 5864 | pdf=get_pdf_from_sampled_signal(vs(:,phases), param.levels, delta_y); %#ok<AGROW> | ||
6050 | else | 5865 | else | ||
6051 | pdf=get_pdf_from_sampled_signal(vs(:,ixphase), param.levels, delta_y); | 5866 | pdf=get_pdf_from_sampled_signal(vs(:,ixphase), param.levels, delta_y); | ||
6052 | end | 5867 | end | ||
6053 | else | 5868 | else | ||
6054 | for k=phases | 5869 | for k=phases | ||
6055 | pdf_samples(k)=get_pdf_from_sampled_signal(vs(:,k), param.levels, delta_y); %#ok<AGROW> | 5870 | pdf_samples(k)=get_pdf_from_sampled_signal(vs(:,k), param.levels, delta_y); %#ok<AGROW> | ||
6056 | mxV(k)=sqrt(sum( pdf_samples(k).x.^2.*pdf_samples(k).y)); % standard deviation of PDF | 5871 | mxV(k)=sqrt(sum( pdf_samples(k).x.^2.*pdf_samples(k).y)); % standard deviation of PDF | ||
6057 | progress = k/length(phases); | 5872 | progress = k/length(phases); | ||
6058 | if OP.DISPLAY_WINDOW, waitbar(progress, hwaitbar, ['processing COM pdf ' chdata.base ] ); figure(hwaitbar); drawnow; end | 5873 | if OP.DISPLAY_WINDOW, waitbar(progress, hwaitbar, ['processing COM pdf ' chdata.base ] ); figure(hwaitbar); drawnow; end | ||
6059 | end | 5874 | end | ||
6060 | [UNUSED_OUTPU, pxi]=max(mxV); %#ok<ASGLU> | 5875 | [UNUSED_OUTPU, pxi]=max(mxV); %#ok<ASGLU> | ||
6061 | pdf=pdf_samples(pxi); | 5876 | pdf=pdf_samples(pxi); | ||
6062 | end | 5877 | end | ||
6063 | 5878 | ||||
6064 | 5879 | ||||
6065 | 5880 | ||||
6066 | if OP.DISPLAY_WINDOW | 5881 | if OP.DISPLAY_WINDOW | ||
6067 | close(hwaitbar); | 5882 | close(hwaitbar); | ||
6068 | end | 5883 | end | ||
6069 | 5884 | ||||
6070 | function [ pdf ] = get_pdf_from_sampled_signal( input_vector, L, BinSize ,FAST_NOISE_CONV) | 5885 | function [ pdf ] = get_pdf_from_sampled_signal( input_vector, L, BinSize ,FAST_NOISE_CONV) | ||
6071 | % Create PDF from interference vector using successive delta-set convolutions. | 5886 | % Create PDF from interference vector using successive delta-set convolutions. | ||
6072 | % input_vector = list of values of samples | 5887 | % input_vector = list of values of samples | ||
6073 | % return | 5888 | % return | ||
6074 | % pdf.x | 5889 | % pdf.x | ||
6075 | % pdf.y | 5890 | % pdf.y | ||
6076 | % pdf.vec | 5891 | % pdf.vec | ||
6077 | % pdf.bin | 5892 | % pdf.bin | ||
6078 | if ~exist('FAST_NOISE_CONV','var') | 5893 | if ~exist('FAST_NOISE_CONV','var') | ||
6079 | FAST_NOISE_CONV=0; | 5894 | FAST_NOISE_CONV=0; | ||
6080 | end | 5895 | end | ||
6081 | if max(input_vector) > BinSize | 5896 | if max(input_vector) > BinSize | ||
6082 | input_vector=input_vector(abs(input_vector)>BinSize); | 5897 | input_vector=input_vector(abs(input_vector)>BinSize); | ||
6083 | end | 5898 | end | ||
6084 | % for i = 1:length(input_vector) | 5899 | % for i = 1:length(input_vector) | ||
6085 | % if abs(input_vector(i)) < BinSize , input_vector(i)=0; end | 5900 | % if abs(input_vector(i)) < BinSize , input_vector(i)=0; end | ||
6086 | %end | 5901 | %end | ||
6087 | 5902 | ||||
6088 | input_vector(abs(input_vector)<BinSize) = 0; | 5903 | input_vector(abs(input_vector)<BinSize) = 0; | ||
6089 | b=sign(input_vector); | 5904 | b=sign(input_vector); | ||
6090 | [input_vector,index]=sort(abs(input_vector),'descend'); | 5905 | [input_vector,index]=sort(abs(input_vector),'descend'); | ||
6091 | input_vector=input_vector.*b(index); | 5906 | input_vector=input_vector.*b(index); | ||
6092 | if FAST_NOISE_CONV | 5907 | if FAST_NOISE_CONV | ||
6093 | sig_res=norm(input_vector(find(abs(input_vector)<.001,1)+1:end)); | 5908 | sig_res=norm(input_vector(find(abs(input_vector)<.001,1)+1:end)); | ||
6094 | res_pdf= normal_dist(sig_res,5,BinSize); | 5909 | res_pdf= normal_dist(sig_res,5,BinSize); | ||
6095 | input_vector=input_vector(1:find(abs(input_vector)<.001,1)); | 5910 | input_vector=input_vector(1:find(abs(input_vector)<.001,1)); | ||
6096 | end | 5911 | end | ||
6097 | %% Equation 93A-39 %% | 5912 | %% Equation 93A-39 %% | ||
6098 | values = 2*(0:L-1)/(L-1)-1; | 5913 | values = 2*(0:L-1)/(L-1)-1; | ||
6099 | prob = ones(1,L)/L; | 5914 | prob = ones(1,L)/L; | ||
6100 | 5915 | ||||
6101 | %% Initialize pdf to delta at 0 | 5916 | %% Initialize pdf to delta at 0 | ||
6102 | pdf=d_cpdf(BinSize, 0, 1); | 5917 | pdf=d_cpdf(BinSize, 0, 1); | ||
6103 | empty_pdf=pdf; | 5918 | empty_pdf=pdf; | ||
6104 | for k = 1:length(input_vector) | 5919 | for k = 1:length(input_vector) | ||
6105 | % pdfn=d_cpdf(BinSize, abs(input_vector(k))*values, prob); | 5920 | % pdfn=d_cpdf(BinSize, abs(input_vector(k))*values, prob); | ||
6106 | pdfn=Init_PDF_Fast(empty_pdf, abs(input_vector(k))*values, prob); | 5921 | pdfn=Init_PDF_Fast(empty_pdf, abs(input_vector(k))*values, prob); | ||
6107 | pdf=conv_fct(pdf, pdfn); | 5922 | pdf=conv_fct(pdf, pdfn); | ||
6108 | end | 5923 | end | ||
6109 | if FAST_NOISE_CONV | 5924 | if FAST_NOISE_CONV | ||
6110 | % pdf=conv_fct(pdf,res_pdf); | 5925 | % pdf=conv_fct(pdf,res_pdf); | ||
6111 | pdf=conv_fct_TEST(pdf,res_pdf); | 5926 | pdf=conv_fct_TEST(pdf,res_pdf); | ||
6112 | end | 5927 | end | ||
6113 | 5928 | ||||
6114 | function [pdf,h_j_full,A_s_vec]=get_pdf_full(chdata, delta_y, t_s, param, OP,pdf_range) | 5929 | function [pdf,h_j_full,A_s_vec]=get_pdf_full(chdata, delta_y, t_s, param, OP,pdf_range) | ||
6115 | t_s_orig=t_s; | 5930 | t_s_orig=t_s; | ||
6116 | %SBR=chdata.eq_pulse_response(:)'; % row vector SBR(1:t_s-14)=0;SBR(t_s+15:end)=0; for debug (AJG edit) | 5931 | %SBR=chdata.eq_pulse_response(:)'; % row vector SBR(1:t_s-14)=0;SBR(t_s+15:end)=0; for debug (AJG edit) | ||
6117 | type=chdata.type; | 5932 | type=chdata.type; | ||
6118 | 5933 | ||||
6119 | pulse_orig=chdata.eq_pulse_response(:)'; | 5934 | pulse_orig=chdata.eq_pulse_response(:)'; | ||
6120 | %build arbitrary time axis with step size = 1/samples per ui | 5935 | %build arbitrary time axis with step size = 1/samples per ui | ||
6121 | old_time=[0:length(pulse_orig)-1]/param.samples_per_ui; | 5936 | old_time=[0:length(pulse_orig)-1]/param.samples_per_ui; | ||
6122 | %force t_s at time =0 (makes the other things below easy) | 5937 | %force t_s at time =0 (makes the other things below easy) | ||
6123 | original_sample_time=old_time(t_s_orig); | 5938 | original_sample_time=old_time(t_s_orig); | ||
6124 | old_time=old_time-original_sample_time; | 5939 | old_time=old_time-original_sample_time; | ||
6125 | %build new time axis that forces time=0 to be in the axis | 5940 | %build new time axis that forces time=0 to be in the axis | ||
6126 | %unless the new/old samples per UI are integer ratios, time 0 will not be | 5941 | %unless the new/old samples per UI are integer ratios, time 0 will not be | ||
6127 | %there by default | 5942 | %there by default | ||
6128 | samp_UI=param.samples_for_C2M; | 5943 | samp_UI=param.samples_for_C2M; | ||
6129 | new_timea=[0:-1/samp_UI:min(old_time)]; | 5944 | new_timea=[0:-1/samp_UI:min(old_time)]; | ||
6130 | new_timeb=[0:1/samp_UI:max(old_time)]; | 5945 | new_timeb=[0:1/samp_UI:max(old_time)]; | ||
6131 | new_time=[fliplr(new_timea) new_timeb(2:end)]; | 5946 | new_time=[fliplr(new_timea) new_timeb(2:end)]; | ||
6132 | SBR=interp1(old_time,pulse_orig,new_time); | 5947 | SBR=interp1(old_time,pulse_orig,new_time); | ||
6133 | %new sample time is simply the point where new_time = 0 | 5948 | %new sample time is simply the point where new_time = 0 | ||
6134 | [tmp,t_s]=min(abs(new_time)); | 5949 | [tmp,t_s]=min(abs(new_time)); | ||
6135 | 5950 | ||||
6136 | residual_response = SBR; | 5951 | residual_response = SBR; | ||
6137 | 5952 | ||||
6138 | half_UI=get_center_of_UI(samp_UI); | 5953 | half_UI=get_center_of_UI(samp_UI); | ||
6139 | 5954 | ||||
6140 | if isequal(type, 'THRU') | 5955 | if isequal(type, 'THRU') | ||
6141 | % for thru pulse response: | 5956 | % for thru pulse response: | ||
6142 | % remove the cursor and the DFE postcursors (up to their limit), since | 5957 | % remove the cursor and the DFE postcursors (up to their limit), since | ||
6143 | % we only care about the residuals. | 5958 | % we only care about the residuals. | ||
6144 |
| 5959 |
| ||
6145 | %AJG021820 | 5960 | %AJG021820 | ||
6146 | if ~param.Floating_DFE | 5961 | if ~param.Floating_DFE | ||
6147 | ideal_cancelled_cursors = SBR(t_s+samp_UI*(1:param.ndfe)); | 5962 | ideal_cancelled_cursors = SBR(t_s+samp_UI*(1:param.ndfe)); | ||
6148 | else | 5963 | else | ||
6149 | ideal_cancelled_cursors = SBR(t_s+samp_UI*(1:param.N_bmax)); | 5964 | ideal_cancelled_cursors = SBR(t_s+samp_UI*(1:param.N_bmax)); | ||
6150 | end | 5965 | end | ||
6151 | if param.dfe_delta ~= 0 | 5966 | if param.dfe_delta ~= 0 | ||
6152 | ideal_cancelled_cursors_q=floor(abs( ideal_cancelled_cursors/(residual_response(t_s).*param.dfe_delta) )).*residual_response(t_s)*param.dfe_delta.*sign(ideal_cancelled_cursors); | 5967 | ideal_cancelled_cursors_q=floor(abs( ideal_cancelled_cursors/(residual_response(t_s).*param.dfe_delta) )).*residual_response(t_s)*param.dfe_delta.*sign(ideal_cancelled_cursors); | ||
6153 | else | 5968 | else | ||
6154 | ideal_cancelled_cursors_q=ideal_cancelled_cursors; | 5969 | ideal_cancelled_cursors_q=ideal_cancelled_cursors; | ||
6155 | end | 5970 | end | ||
6156 |
| 5971 |
| ||
6157 | if ~param.Floating_DFE | 5972 | if ~param.Floating_DFE | ||
6158 | bmax_vec=residual_response(t_s)*[param.bmax]; | 5973 | bmax_vec=residual_response(t_s)*[param.bmax]; | ||
6159 | bmin_vec=residual_response(t_s)*[param.bmin]; | 5974 | bmin_vec=residual_response(t_s)*[param.bmin]; | ||
6160 | else | 5975 | else | ||
6161 | bmax_vec=residual_response(t_s)*[param.use_bmax]; | 5976 | bmax_vec=residual_response(t_s)*[param.use_bmax]; | ||
6162 | bmin_vec=residual_response(t_s)*[param.use_bmin]; | 5977 | bmin_vec=residual_response(t_s)*[param.use_bmin]; | ||
6163 | end | 5978 | end | ||
6164 | effective_cancelled_cursors=dfe_clipper(ideal_cancelled_cursors_q,bmax_vec,bmin_vec); | 5979 | effective_cancelled_cursors=dfe_clipper(ideal_cancelled_cursors_q,bmax_vec,bmin_vec); | ||
6165 |
| 5980 |
| ||
6166 |
| 5981 |
| ||
6167 | effective_cancellation_samples = kron(effective_cancelled_cursors, ones(1, samp_UI)); | 5982 | effective_cancellation_samples = kron(effective_cancelled_cursors, ones(1, samp_UI)); | ||
6168 | dfetaps=effective_cancelled_cursors/SBR(t_s); | 5983 | dfetaps=effective_cancelled_cursors/SBR(t_s); | ||
6169 |
| 5984 |
| ||
6170 | % Apply a constant DFE coefficient 1/2 UI before and after each postcursor. Not | 5985 | % Apply a constant DFE coefficient 1/2 UI before and after each postcursor. Not | ||
6171 | % really needed for COM, but helps debugging. May be factored out in future revisions. | 5986 | % really needed for COM, but helps debugging. May be factored out in future revisions. | ||
6172 |
| 5987 |
| ||
6173 | %avoid dividing samp_UI by 2 in case it is not even | 5988 | %avoid dividing samp_UI by 2 in case it is not even | ||
6174 | start_cancel=t_s-half_UI+1+samp_UI; | 5989 | start_cancel=t_s-half_UI+1+samp_UI; | ||
6175 | %AJG021820 | 5990 | %AJG021820 | ||
6176 | if ~param.Floating_DFE | 5991 | if ~param.Floating_DFE | ||
6177 | end_cancel=start_cancel+param.ndfe*samp_UI-1; | 5992 | end_cancel=start_cancel+param.ndfe*samp_UI-1; | ||
6178 | else | 5993 | else | ||
6179 | end_cancel=start_cancel+param.N_bmax*samp_UI-1; | 5994 | end_cancel=start_cancel+param.N_bmax*samp_UI-1; | ||
6180 | end | 5995 | end | ||
6181 | residual_response(start_cancel:end_cancel) = ... | 5996 | residual_response(start_cancel:end_cancel) = ... | ||
6182 | residual_response(start_cancel:end_cancel) - effective_cancellation_samples; | 5997 | residual_response(start_cancel:end_cancel) - effective_cancellation_samples; | ||
6183 | %else | 5998 | %else | ||
6184 | % for crosstalk pulse responses, nothing is cancelled, and all phases | 5999 | % for crosstalk pulse responses, nothing is cancelled, and all phases | ||
6185 | % are equally important. | 6000 | % are equally important. | ||
6186 |
| 6001 |
| ||
6187 | %remove entire cursor UI | 6002 | %remove entire cursor UI | ||
6188 | uiv_start=start_cancel-samp_UI; | 6003 | uiv_start=start_cancel-samp_UI; | ||
6189 | uiv_end=uiv_start+samp_UI-1; | 6004 | uiv_end=uiv_start+samp_UI-1; | ||
6190 | A_s_vec = param.R_LM*SBR(uiv_start:uiv_end)/(param.levels-1); | 6005 | A_s_vec = param.R_LM*SBR(uiv_start:uiv_end)/(param.levels-1); | ||
6191 | residual_response(uiv_start:uiv_end)=0; | 6006 | residual_response(uiv_start:uiv_end)=0; | ||
6192 | end | 6007 | end | ||
6193 | 6008 | ||||
6194 | nui=round(length(residual_response)/samp_UI); | 6009 | nui=round(length(residual_response)/samp_UI); | ||
6195 | 6010 | ||||
6196 | 6011 | ||||
6197 | vs=transpose(reshape(residual_response(samp_UI+1:samp_UI*(nui-1)),samp_UI,nui-2)); | 6012 | vs=transpose(reshape(residual_response(samp_UI+1:samp_UI*(nui-1)),samp_UI,nui-2)); | ||
6198 | %added vs_raw in order to calculate h_j. vs_raw uses the pulse | 6013 | %added vs_raw in order to calculate h_j. vs_raw uses the pulse | ||
6199 | %response without DFE included. (Can't include DFE for jitter calc) | 6014 | %response without DFE included. (Can't include DFE for jitter calc) | ||
6200 | vs_raw=transpose(reshape(SBR(samp_UI+1:samp_UI*(nui-1)),samp_UI,nui-2)); | 6015 | vs_raw=transpose(reshape(SBR(samp_UI+1:samp_UI*(nui-1)),samp_UI,nui-2)); | ||
6201 | 6016 | ||||
6202 | % if OP.DISPLAY_WINDOW, | 6017 | % if OP.DISPLAY_WINDOW, | ||
6203 | % hwaitbar=waitbar(0); | 6018 | % hwaitbar=waitbar(0); | ||
6204 | % end | 6019 | % end | ||
6205 | 6020 | ||||
6206 | % determine which pdf to use | 6021 | % determine which pdf to use | ||
6207 | if isequal(type, 'THRU') | 6022 | if isequal(type, 'THRU') | ||
6208 | % one phase is interesting for thru | 6023 | % one phase is interesting for thru | ||
6209 | phases = mod(t_s,samp_UI); | 6024 | phases = mod(t_s,samp_UI); | ||
6210 | if phases==0, phases = samp_UI; end | 6025 | if phases==0, phases = samp_UI; end | ||
6211 | else | 6026 | else | ||
6212 | phases=1:samp_UI; | 6027 | phases=1:samp_UI; | ||
6213 | end | 6028 | end | ||
6214 | 6029 | ||||
6215 | mxV = zeros(size(phases)); | 6030 | mxV = zeros(size(phases)); | ||
6216 | 6031 | ||||
6217 | %phases reveals the raw position in the UI window of the cursor. | 6032 | %phases reveals the raw position in the UI window of the cursor. | ||
6218 | %shift_amount is the amount to shift so that it aligns with half_UI | 6033 | %shift_amount is the amount to shift so that it aligns with half_UI | ||
6219 | shift_amount=half_UI-phases; | 6034 | shift_amount=half_UI-phases; | ||
6220 | %vs_shift puts the cursor at the center | 6035 | %vs_shift puts the cursor at the center | ||
6221 | vs_shift=circshift(vs,[0 shift_amount]); | 6036 | vs_shift=circshift(vs,[0 shift_amount]); | ||
6222 | L=size(vs_raw,1); | 6037 | L=size(vs_raw,1); | ||
6223 | %allow partial UI computation through pdf_range | 6038 | %allow partial UI computation through pdf_range | ||
6224 | %if pdf_range is empty, do full UI | 6039 | %if pdf_range is empty, do full UI | ||
6225 | if isempty(pdf_range) | 6040 | if isempty(pdf_range) | ||
6226 | pdf_range=1:samp_UI; | 6041 | pdf_range=1:samp_UI; | ||
6227 | else | 6042 | else | ||
6228 | pdf_range=min(pdf_range):max(pdf_range); | 6043 | pdf_range=min(pdf_range):max(pdf_range); | ||
6229 | end | 6044 | end | ||
6230 | h_j_full=zeros(L,samp_UI); | 6045 | h_j_full=zeros(L,samp_UI); | ||
6231 | for k=pdf_range | 6046 | for k=pdf_range | ||
6232 | pdf(k)=get_pdf_from_sampled_signal(vs_shift(:,k), param.levels, delta_y); %#ok<AGROW> | 6047 | pdf(k)=get_pdf_from_sampled_signal(vs_shift(:,k), param.levels, delta_y); %#ok<AGROW> | ||
6233 | %mxV(k)=sqrt(sum( pdf_samples(k).x.^2.*pdf_samples(k).y)); % standard deviation of PDF | 6048 | %mxV(k)=sqrt(sum( pdf_samples(k).x.^2.*pdf_samples(k).y)); % standard deviation of PDF | ||
6234 | %progress = k/length(phases); | 6049 | %progress = k/length(phases); | ||
6235 | %if OP.DISPLAY_WINDOW, waitbar(progress, hwaitbar, ['processing COM pdf ' chdata.base ] ); figure(hwaitbar); drawnow; end | 6050 | %if OP.DISPLAY_WINDOW, waitbar(progress, hwaitbar, ['processing COM pdf ' chdata.base ] ); figure(hwaitbar); drawnow; end | ||
6236 |
| 6051 |
| ||
6237 | %build the circshift of h_j_full into the loop to support a reduced | 6052 | %build the circshift of h_j_full into the loop to support a reduced | ||
6238 | %range of sampling points. circshift at the end only works if doing the | 6053 | %range of sampling points. circshift at the end only works if doing the | ||
6239 | %full range of sampling points. And shifting before the loop will | 6054 | %full range of sampling points. And shifting before the loop will | ||
6240 | %yield the wrong answer at the edges of the UI | 6055 | %yield the wrong answer at the edges of the UI | ||
6241 | hk=k-shift_amount; | 6056 | hk=k-shift_amount; | ||
6242 | if hk<1 | 6057 | if hk<1 | ||
6243 | hk=hk+samp_UI; | 6058 | hk=hk+samp_UI; | ||
6244 | elseif hk>samp_UI | 6059 | elseif hk>samp_UI | ||
6245 | hk=hk-samp_UI; | 6060 | hk=hk-samp_UI; | ||
6246 | end | 6061 | end | ||
6247 | if hk==1 | 6062 | if hk==1 | ||
6248 | %when hk=1, the early UI is the last column | 6063 | %when hk=1, the early UI is the last column | ||
6249 | h_j_full(1:L-1,k)=(vs_raw(2:end,hk+1)-vs_raw(1:end-1,samp_UI))/2*samp_UI; | 6064 | h_j_full(1:L-1,k)=(vs_raw(2:end,hk+1)-vs_raw(1:end-1,samp_UI))/2*samp_UI; | ||
6250 | elseif hk==samp_UI | 6065 | elseif hk==samp_UI | ||
6251 | %when hk=samp_UI, the late UI is the first column | 6066 | %when hk=samp_UI, the late UI is the first column | ||
6252 | h_j_full(1:L-1,k)=(vs_raw(2:end,1)-vs_raw(1:end-1,hk-1))/2*samp_UI; | 6067 | h_j_full(1:L-1,k)=(vs_raw(2:end,1)-vs_raw(1:end-1,hk-1))/2*samp_UI; | ||
6253 | else | 6068 | else | ||
6254 | %for all other cases, do the normal late=+1, early = -1 | 6069 | %for all other cases, do the normal late=+1, early = -1 | ||
6255 | h_j_full(1:L,k)=(vs_raw(:,hk+1)-vs_raw(:,hk-1))/2*samp_UI; | 6070 | h_j_full(1:L,k)=(vs_raw(:,hk+1)-vs_raw(:,hk-1))/2*samp_UI; | ||
6256 | end | 6071 | end | ||
6257 | end | 6072 | end | ||
6258 | function [chdata, param] = get_s4p_files(param, OP, num_fext, num_next, file_list) | 6073 | function [chdata, param] = get_s4p_files(param, OP, num_fext, num_next, file_list) | ||
6259 | % filename parsing and acquisition | 6074 | % filename parsing and acquisition | ||
6260 | %------------------------------------------------------------------ | 6075 | %------------------------------------------------------------------ | ||
6261 | %----------put files names into chdata structure --------- | 6076 | %----------put files names into chdata structure --------- | ||
6262 | % The thru file has the index of 1 | 6077 | % The thru file has the index of 1 | ||
6263 | % crosstalk file are indexed from 2 | 6078 | % crosstalk file are indexed from 2 | ||
6264 | % nxi is incremented each time a file is read in so that nxi will end | 6079 | % nxi is incremented each time a file is read in so that nxi will end | ||
6265 | filepath=[]; % path name for file | 6080 | filepath=[]; % path name for file | ||
6266 | nxi=0; % file index | 6081 | nxi=0; % file index | ||
6267 | % get the THRU file | 6082 | % get the THRU file | ||
6268 | if size(file_list,2) ~= 0 | 6083 | if size(file_list,2) ~= 0 | ||
6269 | file_list(1)=strrep(file_list(1),'\', filesep); % OS file convention conversion | 6084 | file_list(1)=strrep(file_list(1),'\', filesep); % OS file convention conversion | ||
6270 | [filepath, basename, fileext]=fileparts(file_list{1}); | 6085 | [filepath, basename, fileext]=fileparts(file_list{1}); | ||
6271 |
| 6086 |
| ||
6272 | else | 6087 | else | ||
6273 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 6088 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
6274 | h = msgbox('enter test channel s-parameter file'); set(h,'Color',[1 .85 0]); | 6089 | h = msgbox('enter test channel s-parameter file'); set(h,'Color',[1 .85 0]); | ||
6275 | movegui(h,'northeast') | 6090 | movegui(h,'northeast') | ||
6276 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 6091 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
6277 | end | 6092 | end | ||
6278 | if OP.ERL == 2 | 6093 | if OP.ERL == 2 | ||
6279 | dir=fullfile(filepath, '*.s2p'); | 6094 | dir=fullfile(filepath, '*.s2p'); | ||
6280 | [basename,filepath]=uigetfile(dir,'input RL measurement .s2p '); | 6095 | [basename,filepath]=uigetfile(dir,'input RL measurement .s2p '); | ||
6281 | if filepath == 0 | 6096 | if filepath == 0 | ||
6282 | error('No RL measurement file') | 6097 | error('No RL measurement file') | ||
6283 | end | 6098 | end | ||
6284 | else | 6099 | else | ||
6285 | dir=fullfile(filepath, '*.s4p'); | 6100 | dir=fullfile(filepath, '*.s4p'); | ||
6286 | [basename,filepath]=uigetfile(dir,'input thru channel response .s4p '); | 6101 | [basename,filepath]=uigetfile(dir,'input thru channel response .s4p '); | ||
6287 | if filepath == 0 | 6102 | if filepath == 0 | ||
6288 | error('No Thru file') | 6103 | error('No Thru file') | ||
6289 | end | 6104 | end | ||
6290 | end | 6105 | end | ||
6291 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 6106 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
6292 | end | 6107 | end | ||
6293 | nxi=nxi+1; | 6108 | nxi=nxi+1; | ||
6294 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 6109 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
6295 | chdata(nxi).ext = fileext; | 6110 | chdata(nxi).ext = fileext; | ||
6296 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 6111 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
6297 | % chdata(nxi).base=[pth(max(strfind(pth,filesep))+1:end) '--' basename]; % add 1 directory back to basename | 6112 | % chdata(nxi).base=[pth(max(strfind(pth,filesep))+1:end) '--' basename]; % add 1 directory back to basename | ||
6298 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename]; % add 1 directory back to basename | 6113 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename]; % add 1 directory back to basename | ||
6299 | % chdata(nxi).A=param.A_thru; % pam encoding amplitude reduction is do in reporting but is comprehending in crosstalk PDF | 6114 | % chdata(nxi).A=param.A_thru; % pam encoding amplitude reduction is do in reporting but is comprehending in crosstalk PDF | ||
6300 | chdata(nxi).type='THRU'; | 6115 | chdata(nxi).type='THRU'; | ||
6301 | chdata(nxi).ftr=param.fb*param.f_v; | 6116 | chdata(nxi).ftr=param.fb*param.f_v; | ||
6302 | param.base=chdata(nxi).base; %for print out function that don't pass chdata | 6117 | param.base=chdata(nxi).base; %for print out function that don't pass chdata | ||
6303 | 6118 | ||||
6304 | % now get FEXT file names into chdata structure | 6119 | % now get FEXT file names into chdata structure | ||
6305 | kxi=nxi; | 6120 | kxi=nxi; | ||
6306 | for nxi=kxi+1:num_fext+kxi | 6121 | for nxi=kxi+1:num_fext+kxi | ||
6307 | lastfilepath=filepath; | 6122 | lastfilepath=filepath; | ||
6308 | if size(file_list,2) ~= 0 | 6123 | if size(file_list,2) ~= 0 | ||
6309 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | 6124 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | ||
6310 | else | 6125 | else | ||
6311 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 6126 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
6312 | h = msgbox('enter noise channel s-parameter file'); set(h,'Color',[1 .85 0]); | 6127 | h = msgbox('enter noise channel s-parameter file'); set(h,'Color',[1 .85 0]); | ||
6313 | movegui(h,'northeast') | 6128 | movegui(h,'northeast') | ||
6314 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | 6129 | set(h,'Tag','COM') % RIM 06-13-2022 ... tak msg box for closing later | ||
6315 | end | 6130 | end | ||
6316 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2; | 6131 | if param.tfx(1) == -1 && OP.ERL_ONLY && OP.ERL == 2; | ||
6317 | dir=fullfile(filepath, '*.s4p'); | 6132 | dir=fullfile(filepath, '*.s4p'); | ||
6318 | [basename,filepath]=uigetfile(dir,'input noise channel response .s4p'); | 6133 | [basename,filepath]=uigetfile(dir,'input noise channel response .s4p'); | ||
6319 | if filepath==0 | 6134 | if filepath==0 | ||
6320 | error('Not enough NEXT files') | 6135 | error('Not enough NEXT files') | ||
6321 | end | 6136 | end | ||
6322 | else | 6137 | else | ||
6323 | dir=fullfile(filepath, '*.s4p'); | 6138 | dir=fullfile(filepath, '*.s4p'); | ||
6324 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | 6139 | if OP.RX_CALIBRATION == 1 || OP.FIXTURE_CALIBRATION | ||
6325 | [basename,filepath]=uigetfile(dir,'input noise channel response .s4p'); | 6140 | [basename,filepath]=uigetfile(dir,'input noise channel response .s4p'); | ||
6326 | else | 6141 | else | ||
6327 | [basename,filepath]=uigetfile(dir,['input fext channel response .s4p #', num2str(nxi-kxi)]); | 6142 | [basename,filepath]=uigetfile(dir,['input fext channel response .s4p #', num2str(nxi-kxi)]); | ||
6328 | end | 6143 | end | ||
6329 | if filepath==0 | 6144 | if filepath==0 | ||
6330 | error('Not enough NEXT files') | 6145 | error('Not enough NEXT files') | ||
6331 | end | 6146 | end | ||
6332 | end | 6147 | end | ||
6333 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 6148 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
6334 | end | 6149 | end | ||
6335 | if isempty( filepath), filepath=lastfilepath; end | 6150 | if isempty( filepath), filepath=lastfilepath; end | ||
6336 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 6151 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
6337 | chdata(nxi).ext = fileext; | 6152 | chdata(nxi).ext = fileext; | ||
6338 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 6153 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
6339 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | 6154 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | ||
6340 | % chdata(nxi).A=param.a_fext; | 6155 | % chdata(nxi).A=param.a_fext; | ||
6341 | chdata(nxi).ftr=param.fb*param.f_f; | 6156 | chdata(nxi).ftr=param.fb*param.f_f; | ||
6342 | chdata(nxi).type='FEXT'; | 6157 | chdata(nxi).type='FEXT'; | ||
6343 | end | 6158 | end | ||
6344 | % now get NEXT file names into chdata structure | 6159 | % now get NEXT file names into chdata structure | ||
6345 | kxi=num_fext+kxi; | 6160 | kxi=num_fext+kxi; | ||
6346 | for nxi=kxi+1:num_next+kxi | 6161 | for nxi=kxi+1:num_next+kxi | ||
6347 | lastfilepath=filepath; | 6162 | lastfilepath=filepath; | ||
6348 | if size(file_list,2) ~= 0 | 6163 | if size(file_list,2) ~= 0 | ||
6349 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | 6164 | [filepath, basename, fileext]=fileparts(file_list{nxi}); | ||
6350 | else | 6165 | else | ||
6351 | dir=fullfile(filepath, '*.s4p'); | 6166 | dir=fullfile(filepath, '*.s4p'); | ||
6352 | [basename,filepath]=uigetfile(dir,['input next channel response .s4p ', num2str(nxi-kxi)]); | 6167 | [basename,filepath]=uigetfile(dir,['input next channel response .s4p ', num2str(nxi-kxi)]); | ||
6353 | if filepath==0 | 6168 | if filepath==0 | ||
6354 | error('Not enough NEXT files') | 6169 | error('Not enough NEXT files') | ||
6355 | end | 6170 | end | ||
6356 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | 6171 | [UNUSED_OUTPUT, basename, fileext]=fileparts(basename); %#ok<ASGLU> | ||
6357 | end | 6172 | end | ||
6358 | if isempty( filepath), filepath=lastfilepath; end | 6173 | if isempty( filepath), filepath=lastfilepath; end | ||
6359 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | 6174 | chdata(nxi).filename = fullfile(filepath, [basename fileext]); | ||
6360 | chdata(nxi).ext = fileext; | 6175 | chdata(nxi).ext = fileext; | ||
6361 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | 6176 | [UNUSED_OUTPUT, dirname]=fileparts(filepath); %#ok<ASGLU> | ||
6362 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | 6177 | chdata(nxi).base=[OP.RUNTAG ' ' dirname '--' basename ]; | ||
6363 | % chdata(nxi).A=param.A_next; | 6178 | % chdata(nxi).A=param.A_next; | ||
6364 | chdata(nxi).ftr=param.fb*param.f_n; | 6179 | chdata(nxi).ftr=param.fb*param.f_n; | ||
6365 | chdata(nxi).type='NEXT'; | 6180 | chdata(nxi).type='NEXT'; | ||
6366 | end | 6181 | end | ||
6367 | 6182 | ||||
6368 | function [sigma_N] = get_sigma_eta_ACCM_noise(chdata,param,H_sy,H_r,H_ctf) | 6183 | function [sigma_N] = get_sigma_eta_ACCM_noise(chdata,param,H_sy,H_r,H_ctf) | ||
6369 | % 11-25-2020 correct integratation limits, should be infinity or highest specified frequency | 6184 | % 11-25-2020 correct integratation limits, should be infinity or highest specified frequency | ||
6370 | % H_sy - PSD for Tx power delivery, not normally used and set to a vector 1's | 6185 | % H_sy - PSD for Tx power delivery, not normally used and set to a vector 1's | ||
6371 | % H_r - receiver filter, Butterworth | 6186 | % H_r - receiver filter, Butterworth | ||
6372 | % H_ctf - total gain of CTLE and low freq filtering | 6187 | % H_ctf - total gain of CTLE and low freq filtering | ||
6373 | % H_dc - the common mode channel gain | 6188 | % H_dc - the common mode channel gain | ||
6374 | % param.eta_0 -input referred Rx noise | 6189 | % param.eta_0 -input referred Rx noise | ||
6375 | % param.AC_CM_RMS - AC CM source before Tx series source resistor. | 6190 | % param.AC_CM_RMS - AC CM source before Tx series source resistor. | ||
6376 | % param.ACCM_MAX_Freq - Max frequency for ACCM source intergration | 6191 | % param.ACCM_MAX_Freq - Max frequency for ACCM source intergration | ||
6377 | %% Equation 93A-35 - independent of FFE setting %% | 6192 | %% Equation 93A-35 - independent of FFE setting %% | ||
6378 | sigma_N1 = sqrt(param.eta_0*sum( abs(H_sy(2:end) .* H_r(2:end) .* H_ctf(2:end) ).^2 .* diff(chdata(1).faxis)/1e9));% eta_0 is V^2/Ghz i.e. /1 | 6193 | sigma_N1 = sqrt(param.eta_0*sum( abs(H_sy(2:end) .* H_r(2:end) .* H_ctf(2:end) ).^2 .* diff(chdata(1).faxis)/1e9));% eta_0 is V^2/Ghz i.e. /1 | ||
6379 | if sum(param.AC_CM_RMS) ~= 0 | 6194 | if sum(param.AC_CM_RMS) ~= 0 | ||
6380 | sigma_ACCM=0; | 6195 | sigma_ACCM=0; | ||
6381 | f_int= chdata(1).faxis( chdata(1).faxis<=param.ACCM_MAX_Freq ); | 6196 | f_int= chdata(1).faxis( chdata(1).faxis<=param.ACCM_MAX_Freq ); | ||
6382 | for i=1:length(chdata) | 6197 | for i=1:length(chdata) | ||
6383 | H_dc=abs(squeeze(chdata(i).sdc21)); | 6198 | H_dc=abs(squeeze(chdata(i).sdc21)); | ||
6384 | sigma_ACCM_acc= sqrt( 2*param.AC_CM_RMS_TX^2.*sum( abs(H_sy(2:length(f_int)) .* H_r(2:length(f_int)) .* H_ctf(2:length(f_int)).*H_dc(2:length(f_int)) ).^2 .* diff(f_int))/f_int(end) ); | 6199 | sigma_ACCM_acc= sqrt( 2*param.AC_CM_RMS_TX^2.*sum( abs(H_sy(2:length(f_int)) .* H_r(2:length(f_int)) .* H_ctf(2:length(f_int)).*H_dc(2:length(f_int)) ).^2 .* diff(f_int))/f_int(end) ); | ||
6385 | sigma_ACCM=norm([sigma_ACCM_acc,sigma_ACCM]); | 6200 | sigma_ACCM=norm([sigma_ACCM_acc,sigma_ACCM]); | ||
6386 | end | 6201 | end | ||
6387 | sigma_N=norm([sigma_N1,sigma_ACCM]); | 6202 | sigma_N=norm([sigma_N1,sigma_ACCM]); | ||
6388 | else | 6203 | else | ||
6389 | sigma_N=sigma_N1; | 6204 | sigma_N=sigma_N1; | ||
6390 | end | 6205 | end | ||
6391 | %% | 6206 | %% | ||
6392 | function [ sigma_NE , sigma_HP] = get_sigma_noise( H_ctf, param, chdata, sigma_bn ) | 6207 | function [ sigma_NE , sigma_HP] = get_sigma_noise( H_ctf, param, chdata, sigma_bn ) | ||
6393 | % for Rx calibratrion only | 6208 | % for Rx calibratrion only | ||
6394 | % the FEXT channel for calibration basically a DC connection unlike normal | 6209 | % the FEXT channel for calibration basically a DC connection unlike normal | ||
6395 | % FEXT channels which are nearly open at DC channels | 6210 | % FEXT channels which are nearly open at DC channels | ||
6396 | H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(2).faxis/(param.f_r*param.fb)); | 6211 | H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(2).faxis/(param.f_r*param.fb)); | ||
6397 | idxfbby2=find( chdata(2).faxis(:) >= param.fb/2, 1); | 6212 | idxfbby2=find( chdata(2).faxis(:) >= param.fb/2, 1); | ||
6398 | if size(chdata,2) >= 2 | 6213 | if size(chdata,2) >= 2 | ||
6399 | Hnoise_channel=chdata(2).sdd21;% rx package is already included tx is not | 6214 | Hnoise_channel=chdata(2).sdd21;% rx package is already included tx is not | ||
6400 | else | 6215 | else | ||
6401 | Hnoise_channel=1; | 6216 | Hnoise_channel=1; | ||
6402 | end | 6217 | end | ||
6403 | f=chdata(2).faxis; | 6218 | f=chdata(2).faxis; | ||
6404 | f_hp=param.f_hp; | 6219 | f_hp=param.f_hp; | ||
6405 | if f_hp ~=0 % param.f_hp is a key indicating that Tx bbn is used as in clause 162 | 6220 | if f_hp ~=0 % param.f_hp is a key indicating that Tx bbn is used as in clause 162 | ||
6406 | H_hp=(-1j*f./f_hp)./(1+1j*f./f_hp); | 6221 | H_hp=(-1j*f./f_hp)./(1+1j*f./f_hp); | ||
6407 | else | 6222 | else | ||
6408 | H_hp=ones(1,length(f)); | 6223 | H_hp=ones(1,length(f)); | ||
6409 | end | 6224 | end | ||
6410 | %% Equation 93A-47 or 162-12 | 6225 | %% Equation 93A-47 or 162-12 | ||
6411 | H_np=Hnoise_channel.*H_ctf.*H_r.*H_hp; | 6226 | H_np=Hnoise_channel.*H_ctf.*H_r.*H_hp; | ||
6412 | 6227 | ||||
6413 | %% Equation 93A-48 or 162-14%% | 6228 | %% Equation 93A-48 or 162-14%% | ||
6414 | sigma_NE = sigma_bn*sqrt(mean(abs(H_np(1:idxfbby2).^2))); | 6229 | sigma_NE = sigma_bn*sqrt(mean(abs(H_np(1:idxfbby2).^2))); | ||
6415 | sigma_HP = sigma_bn*(mean(abs(H_hp(1:idxfbby2).^2))); | 6230 | sigma_HP = sigma_bn*(mean(abs(H_hp(1:idxfbby2).^2))); | ||
6416 | function [sigma_XT, sigma_FEXT, sigma_NEXT] = get_xtlk_noise( upsampled_txffe, type, param, chdata, phase_memory,C ) | 6231 | function [sigma_XT, sigma_FEXT, sigma_NEXT] = get_xtlk_noise( upsampled_txffe, type, param, chdata, phase_memory,C ) | ||
6417 | % Modified not to double count crosstalk: John Ewen 13/12/2018 | 6232 | % Modified not to double count crosstalk: John Ewen 13/12/2018 | ||
6418 | % function sigma_XT = get_xtlk_noise( upsampled_txffe, type, param, chdata,ctle_indx,clow_indx, C,cursor_i) | 6233 | % function sigma_XT = get_xtlk_noise( upsampled_txffe, type, param, chdata,ctle_indx,clow_indx, C,cursor_i) | ||
6419 | index_f2=find(chdata(1).faxis(:)>param.fb,1,'first'); | 6234 | index_f2=find(chdata(1).faxis(:)>param.fb,1,'first'); | ||
6420 | if isempty(index_f2), index_f2=length(chdata(1).faxis);end | 6235 | if isempty(index_f2), index_f2=length(chdata(1).faxis);end | ||
6421 | f=chdata(1).faxis; | 6236 | f=chdata(1).faxis; | ||
6422 | temp_angle=(param.samples_per_ui*param.sample_dt)*pi.*chdata(1).faxis; | 6237 | temp_angle=(param.samples_per_ui*param.sample_dt)*pi.*chdata(1).faxis; | ||
6423 | if(f(1)==0) | 6238 | if(f(1)==0) | ||
6424 | temp_angle(1)=1e-20;% we don't want to divide by zero | 6239 | temp_angle(1)=1e-20;% we don't want to divide by zero | ||
6425 | end | 6240 | end | ||
6426 | PWF_tx=ones(1,length(f)); | 6241 | PWF_tx=ones(1,length(f)); | ||
6427 | if max(upsampled_txffe) > 0 | 6242 | if max(upsampled_txffe) > 0 | ||
6428 | PWF_tx=zeros(1,length(f)); | 6243 | PWF_tx=zeros(1,length(f)); | ||
6429 | [mcur,icur] = max(upsampled_txffe); | 6244 | [mcur,icur] = max(upsampled_txffe); | ||
6430 | if exist('phase_memory','var') && ~isempty(phase_memory) | 6245 | if exist('phase_memory','var') && ~isempty(phase_memory) | ||
6431 | pre_calc=1; | 6246 | pre_calc=1; | ||
6432 | else | 6247 | else | ||
6433 | pre_calc=0; | 6248 | pre_calc=0; | ||
6434 | end | 6249 | end | ||
6435 | for ii=1:length(upsampled_txffe) | 6250 | for ii=1:length(upsampled_txffe) | ||
6436 | if upsampled_txffe(ii)==0 | 6251 | if upsampled_txffe(ii)==0 | ||
6437 | %speed up: skip cases when txffe=0 | 6252 | %speed up: skip cases when txffe=0 | ||
6438 | continue; | 6253 | continue; | ||
6439 | end | 6254 | end | ||
6440 | % PWF_tx=upsampled_txffe(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb)+PWF_tx; | 6255 | % PWF_tx=upsampled_txffe(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb)+PWF_tx; | ||
6441 | % Adee Ran 2020-06-03 remove create large 2D matrix when 1D is all | 6256 | % Adee Ran 2020-06-03 remove create large 2D matrix when 1D is all | ||
6442 | % that is needed | 6257 | % that is needed | ||
6443 | if ii==icur | 6258 | if ii==icur | ||
6444 | %speed up: ii-icur=0, so just scalar addition and avoid exp calc | 6259 | %speed up: ii-icur=0, so just scalar addition and avoid exp calc | ||
6445 | PWF_tx = PWF_tx + upsampled_txffe(ii); | 6260 | PWF_tx = PWF_tx + upsampled_txffe(ii); | ||
6446 | else | 6261 | else | ||
6447 | if pre_calc | 6262 | if pre_calc | ||
6448 | %speed up: avoid vector exp calculation by externally pre-calculating it | 6263 | %speed up: avoid vector exp calculation by externally pre-calculating it | ||
6449 | term_ii = upsampled_txffe(ii).*phase_memory(:,ii); | 6264 | term_ii = upsampled_txffe(ii).*phase_memory(:,ii); | ||
6450 | else | 6265 | else | ||
6451 | term_ii = upsampled_txffe(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb); | 6266 | term_ii = upsampled_txffe(ii).*exp(-1j*2*pi*(ii-icur).*f/param.fb); | ||
6452 | end | 6267 | end | ||
6453 | %bug fix: use transpose instead of ' to avoid taking complex conjugate | 6268 | %bug fix: use transpose instead of ' to avoid taking complex conjugate | ||
6454 | PWF_tx = PWF_tx + transpose(term_ii(:)); | 6269 | PWF_tx = PWF_tx + transpose(term_ii(:)); | ||
6455 | end | 6270 | end | ||
6456 | % /Adee | 6271 | % /Adee | ||
6457 | end | 6272 | end | ||
6458 | end | 6273 | end | ||
6459 | PWF_rx=ones(1,length(f)); | 6274 | PWF_rx=ones(1,length(f)); | ||
6460 | if exist('C','var') | 6275 | if exist('C','var') | ||
6461 | PWF_rx=zeros(1,length(f)); | 6276 | PWF_rx=zeros(1,length(f)); | ||
6462 | for ii=-param.RxFFE_cmx:param.RxFFE_cpx | 6277 | for ii=-param.RxFFE_cmx:param.RxFFE_cpx | ||
6463 | if C(ii+param.RxFFE_cmx+1)==0 | 6278 | if C(ii+param.RxFFE_cmx+1)==0 | ||
6464 | %speed up: skip cases when rxffe=0 | 6279 | %speed up: skip cases when rxffe=0 | ||
6465 | continue; | 6280 | continue; | ||
6466 | end | 6281 | end | ||
6467 | if ii+1==0 | 6282 | if ii+1==0 | ||
6468 | %speed up: ii+1=0, so just scalar addition and avoid exp calc | 6283 | %speed up: ii+1=0, so just scalar addition and avoid exp calc | ||
6469 | PWF_rx = PWF_rx + C(ii+param.RxFFE_cmx+1); | 6284 | PWF_rx = PWF_rx + C(ii+param.RxFFE_cmx+1); | ||
6470 | else | 6285 | else | ||
6471 | if pre_calc | 6286 | if pre_calc | ||
6472 | %speed up: avoid vector exp calculation by externally pre-calculating it | 6287 | %speed up: avoid vector exp calculation by externally pre-calculating it | ||
6473 | %The latter columns of phase_memory hold RXFFE shift vectors | 6288 | %The latter columns of phase_memory hold RXFFE shift vectors | ||
6474 | term_ii=C(ii+param.RxFFE_cmx+1).*phase_memory(:,ii+param.RxFFE_cmx+1+length(upsampled_txffe)); | 6289 | term_ii=C(ii+param.RxFFE_cmx+1).*phase_memory(:,ii+param.RxFFE_cmx+1+length(upsampled_txffe)); | ||
6475 | term_ii=transpose(term_ii); | 6290 | term_ii=transpose(term_ii); | ||
6476 | else | 6291 | else | ||
6477 | term_ii=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb); | 6292 | term_ii=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb); | ||
6478 | end | 6293 | end | ||
6479 | PWF_rx=PWF_rx+term_ii; | 6294 | PWF_rx=PWF_rx+term_ii; | ||
6480 | end | 6295 | end | ||
6481 | %PWF_rx=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb)+PWF_rx; | 6296 | %PWF_rx=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb)+PWF_rx; | ||
6482 | end | 6297 | end | ||
6483 | end | 6298 | end | ||
6484 | MDFEXT=0;MDNEXT=0;MDNEXT_ICN=0;MDFEXT_ICN=0; | 6299 | MDFEXT=0;MDNEXT=0;MDNEXT_ICN=0;MDFEXT_ICN=0; | ||
6485 | for ii=2:size(chdata,2) | 6300 | for ii=2:size(chdata,2) | ||
6486 | SINC = sin(temp_angle)./temp_angle; | 6301 | SINC = sin(temp_angle)./temp_angle; | ||
6487 | PWF_data=SINC.^2; | 6302 | PWF_data=SINC.^2; | ||
6488 | PWF=PWF_data.*PWF_rx; % power weight function | 6303 | PWF=PWF_data.*PWF_rx; % power weight function | ||
6489 | PWFnext=abs(PWF); | 6304 | PWFnext=abs(PWF); | ||
6490 | PWF=PWF_data.*PWF_rx.*PWF_tx; % power weight function | 6305 | PWF=PWF_data.*PWF_rx.*PWF_tx; % power weight function | ||
6491 | PWFfext=abs(PWF); | 6306 | PWFfext=abs(PWF); | ||
6492 | if isequal(chdata(ii).type, 'FEXT') | 6307 | if isequal(chdata(ii).type, 'FEXT') | ||
6493 | MDFEXT=sqrt(abs(chdata(ii).sdd21ctf).^2+MDFEXT.^2); % power sum xtk | 6308 | MDFEXT=sqrt(abs(chdata(ii).sdd21ctf).^2+MDFEXT.^2); % power sum xtk | ||
6494 | MDFEXT_ICN=sqrt(2*chdata(ii).delta_f/param.f2*sum( chdata(ii).A^2*PWFfext(1:index_f2).*abs(MDFEXT(1:index_f2)).^2)); %eq 46 | 6309 | MDFEXT_ICN=sqrt(2*chdata(ii).delta_f/param.f2*sum( chdata(ii).A^2*PWFfext(1:index_f2).*abs(MDFEXT(1:index_f2)).^2)); %eq 46 | ||
6495 | elseif isequal(chdata(ii).type, 'NEXT') | 6310 | elseif isequal(chdata(ii).type, 'NEXT') | ||
6496 | MDNEXT=sqrt(abs(chdata(ii).sdd21ctf).^2+MDNEXT.^2); % power sum xtk | 6311 | MDNEXT=sqrt(abs(chdata(ii).sdd21ctf).^2+MDNEXT.^2); % power sum xtk | ||
6497 | MDNEXT_ICN=sqrt(2*chdata(ii).delta_f/param.f2*sum( chdata(ii).A^2*PWFnext(1:index_f2).*abs(MDNEXT(1:index_f2)).^2)); %eq 47 | 6312 | MDNEXT_ICN=sqrt(2*chdata(ii).delta_f/param.f2*sum( chdata(ii).A^2*PWFnext(1:index_f2).*abs(MDNEXT(1:index_f2)).^2)); %eq 47 | ||
6498 | end | 6313 | end | ||
6499 | end | 6314 | end | ||
6500 | if nargout == 1 && isequal(type,'NEXT') | 6315 | if nargout == 1 && isequal(type,'NEXT') | ||
6501 | sigma_XT = MDNEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | 6316 | sigma_XT = MDNEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | ||
6502 | elseif nargout == 1 && isequal(type,'FEXT') | 6317 | elseif nargout == 1 && isequal(type,'FEXT') | ||
6503 | sigma_XT = MDFEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | 6318 | sigma_XT = MDFEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | ||
6504 | elseif nargout == 3 | 6319 | elseif nargout == 3 | ||
6505 | sigma_XT=norm([ MDNEXT_ICN MDFEXT_ICN ])*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | 6320 | sigma_XT=norm([ MDNEXT_ICN MDFEXT_ICN ])*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | ||
6506 | sigma_NEXT = MDNEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | 6321 | sigma_NEXT = MDNEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | ||
6507 | sigma_FEXT = MDFEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | 6322 | sigma_FEXT = MDFEXT_ICN*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); | ||
6508 | end | 6323 | end | ||
6509 | 6324 | ||||
6510 | function out=hrem(h,index,N_bf,bmaxg) | 6325 | function out=hrem(h,index,N_bf,bmaxg) | ||
6511 | 6326 | ||||
6512 | out=[ h(1:index-1) h(index:index+N_bf-1)- sign(h(index:index+N_bf-1)).* (min( bmaxg, abs( h(index:index+N_bf-1) ))) h(index+N_bf:end) ]; | 6327 | out=[ h(1:index-1) h(index:index+N_bf-1)- sign(h(index:index+N_bf-1)).* (min( bmaxg, abs( h(index:index+N_bf-1) ))) h(index+N_bf:end) ]; | ||
6513 | % faster than single line function | 6328 | % faster than single line function | ||
6514 | % hrem =@(h,index,N_bf,bmaxg) ... | 6329 | % hrem =@(h,index,N_bf,bmaxg) ... | ||
6515 | % [ h(1:index-1) ... | 6330 | % [ h(1:index-1) ... | ||
6516 | % h(index:index+N_bf-1)- sign(h(index:index+N_bf-1)).* (min( bmaxg, abs( h(index:index+N_bf-1) ))) ... | 6331 | % h(index:index+N_bf-1)- sign(h(index:index+N_bf-1)).* (min( bmaxg, abs( h(index:index+N_bf-1) ))) ... | ||
6517 | % h(index+N_bf:end) ]... | 6332 | % h(index+N_bf:end) ]... | ||
6518 | % ; | 6333 | % ; | ||
6519 | 6334 | ||||
6520 | %% floating DFE taps | 6335 | %% floating DFE taps | ||
6521 | function [Sout] = interp_Sparam(Sin,fin,fout, ... | 6336 | function [Sout] = interp_Sparam(Sin,fin,fout, ... | ||
6522 | opt_interp_Sparam_mag, opt_interp_Sparam_phase,OP) | 6337 | opt_interp_Sparam_mag, opt_interp_Sparam_phase,OP) | ||
6523 | % Sout = interp_Sparam(Sin,fin,fout) | 6338 | % Sout = interp_Sparam(Sin,fin,fout) | ||
6524 | % | 6339 | % | ||
6525 | % Interpolate S-parameters Sin from frequency grid fin to frequency grid | 6340 | % Interpolate S-parameters Sin from frequency grid fin to frequency grid | ||
6526 | % fout. | 6341 | % fout. | ||
6527 | 6342 | ||||
6528 | if ( fin(end)<fout(end) ) | 6343 | if ( fin(end)<fout(end) ) | ||
6529 | % warning('Channel high frequencies extrapolation might be inaccurate!'); | 6344 | % warning('Channel high frequencies extrapolation might be inaccurate!'); | ||
6530 | end | 6345 | end | ||
6531 | 6346 | ||||
6532 | H_mag = abs(Sin); | 6347 | H_mag = abs(Sin); | ||
6533 | H_mag(H_mag<eps)=eps; % handle ill cases... | 6348 | H_mag(H_mag<eps)=eps; % handle ill cases... | ||
6534 | H_ph = unwrap(angle(Sin)); | 6349 | H_ph = unwrap(angle(Sin)); | ||
6535 | % For long delay channels, the result can turn anti-causal if frequency step is too coarse. Don't let the | 6350 | % For long delay channels, the result can turn anti-causal if frequency step is too coarse. Don't let the | ||
6536 | % user ignore that. | 6351 | % user ignore that. | ||
6537 | if mean(diff(H_ph))>0 | 6352 | if mean(diff(H_ph))>0 | ||
6538 | if OP.DEBUG | 6353 | if OP.DEBUG | ||
6539 | warning('Anti-causal response found. Finer frequency step is required for this channel'); | 6354 | warning('Anti-causal response found. Finer frequency step is required for this channel'); | ||
6540 | else | 6355 | else | ||
6541 | error('Anti-causal response found. Finer frequency step is required for this channel'); | 6356 | error('Anti-causal response found. Finer frequency step is required for this channel'); | ||
6542 | end | 6357 | end | ||
6543 | end | 6358 | end | ||
6544 | 6359 | ||||
6545 | %opt_interp_Sparam_mag='linear_trend_to_DC'; | 6360 | %opt_interp_Sparam_mag='linear_trend_to_DC'; | ||
6546 | switch opt_interp_Sparam_mag | 6361 | switch opt_interp_Sparam_mag | ||
6547 | case {'linear_trend_to_DC','linear_trend_to_DC_log_trend_to_inf'} | 6362 | case {'linear_trend_to_DC','linear_trend_to_DC_log_trend_to_inf'} | ||
6548 | if -iscolumn(H_mag), H_mag=H_mag.';end | 6363 | if -iscolumn(H_mag), H_mag=H_mag.';end | ||
6549 | if -iscolumn(fin), fin=fin.';end | 6364 | if -iscolumn(fin), fin=fin.';end | ||
6550 | fin_x=fin; | 6365 | fin_x=fin; | ||
6551 | H_mag_x=H_mag(:); | 6366 | H_mag_x=H_mag(:); | ||
6552 | if fin(1)>0 | 6367 | if fin(1)>0 | ||
6553 | p=polyfit(fin(1:10), H_mag(1:10), 1); | 6368 | p=polyfit(fin(1:10), H_mag(1:10), 1); | ||
6554 | dc_trend_val=polyval(p, 0); | 6369 | dc_trend_val=polyval(p, 0); | ||
6555 | fin_x=[0, fin_x]; | 6370 | fin_x=[0, fin_x]; | ||
6556 | H_mag_x = [dc_trend_val; H_mag_x]; | 6371 | H_mag_x = [dc_trend_val; H_mag_x]; | ||
6557 | end | 6372 | end | ||
6558 | if fin(end)<fout(end) | 6373 | if fin(end)<fout(end) | ||
6559 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | 6374 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | ||
6560 | mid_freq_ind=round(length(fin)/2); | 6375 | mid_freq_ind=round(length(fin)/2); | ||
6561 | p=polyfit(fin(mid_freq_ind:end), H_mag(mid_freq_ind:end), 1); | 6376 | p=polyfit(fin(mid_freq_ind:end), H_mag(mid_freq_ind:end), 1); | ||
6562 | warning(warn_state); | 6377 | warning(warn_state); | ||
6563 | hf_trend_val=polyval(p, fout(end)); | 6378 | hf_trend_val=polyval(p, fout(end)); | ||
6564 | if hf_trend_val>H_mag(end) | 6379 | if hf_trend_val>H_mag(end) | ||
6565 | hf_trend_val=H_mag(end); | 6380 | hf_trend_val=H_mag(end); | ||
6566 | hf_logtrend_val = H_mag(end); | 6381 | hf_logtrend_val = H_mag(end); | ||
6567 | elseif hf_trend_val<eps | 6382 | elseif hf_trend_val<eps | ||
6568 | hf_trend_val=eps; | 6383 | hf_trend_val=eps; | ||
6569 | hf_logtrend_val = realmin; | 6384 | hf_logtrend_val = realmin; | ||
6570 | end | 6385 | end | ||
6571 | fin_x=[fin_x, fout(end)]; | 6386 | fin_x=[fin_x, fout(end)]; | ||
6572 | H_mag_x = [H_mag_x; hf_trend_val]; | 6387 | H_mag_x = [H_mag_x; hf_trend_val]; | ||
6573 | end | 6388 | end | ||
6574 | H_mag_i = interp1(fin_x, H_mag_x, fout, 'linear', 'extrap'); | 6389 | H_mag_i = interp1(fin_x, H_mag_x, fout, 'linear', 'extrap'); | ||
6575 | if strcmp(opt_interp_Sparam_mag,'linear_trend_to_DC_log_trend_to_inf') | 6390 | if strcmp(opt_interp_Sparam_mag,'linear_trend_to_DC_log_trend_to_inf') | ||
6576 | H_logmag_i = exp(interp1(fin_x, log([H_mag_x(1:end-1);hf_logtrend_val]), fout, 'linear', 'extrap')); | 6391 | H_logmag_i = exp(interp1(fin_x, log([H_mag_x(1:end-1);hf_logtrend_val]), fout, 'linear', 'extrap')); | ||
6577 | indx = find(fout > fin(end),1,'first'); | 6392 | indx = find(fout > fin(end),1,'first'); | ||
6578 | H_mag_i(indx:end) = H_logmag_i(indx:end); | 6393 | H_mag_i(indx:end) = H_logmag_i(indx:end); | ||
6579 | end | 6394 | end | ||
6580 | case 'trend_to_DC' | 6395 | case 'trend_to_DC' | ||
6581 | % extrapolate to trend value at DC. | 6396 | % extrapolate to trend value at DC. | ||
6582 | if -iscolumn(H_mag), H_mag=H_mag.';end | 6397 | if -iscolumn(H_mag), H_mag=H_mag.';end | ||
6583 | if -iscolumn(fin), fin=fin.';end | 6398 | if -iscolumn(fin), fin=fin.';end | ||
6584 | fin_x=fin; | 6399 | fin_x=fin; | ||
6585 | H_mag_x=H_mag; | 6400 | H_mag_x=H_mag; | ||
6586 | if fin(1)>0 | 6401 | if fin(1)>0 | ||
6587 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | 6402 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | ||
6588 | p=polyfit(fin(1:10), log10(H_mag(1:10)), 1); | 6403 | p=polyfit(fin(1:10), log10(H_mag(1:10)), 1); | ||
6589 | dc_trend_val=10^polyval(p, 0); | 6404 | dc_trend_val=10^polyval(p, 0); | ||
6590 | fin_x=[0, fin_x]; | 6405 | fin_x=[0, fin_x]; | ||
6591 | H_mag_x = [dc_trend_val H_mag_x]; | 6406 | H_mag_x = [dc_trend_val H_mag_x]; | ||
6592 | end | 6407 | end | ||
6593 | if fin(end)<fout(end) | 6408 | if fin(end)<fout(end) | ||
6594 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | 6409 | warn_state=warning('off', 'MATLAB:polyfit:RepeatedPointsOrRescale'); | ||
6595 | mid_freq_ind=round(length(fin)/2); | 6410 | mid_freq_ind=round(length(fin)/2); | ||
6596 | p=polyfit(fin(mid_freq_ind:end), log10(H_mag(mid_freq_ind:end)), 1); | 6411 | p=polyfit(fin(mid_freq_ind:end), log10(H_mag(mid_freq_ind:end)), 1); | ||
6597 | warning(warn_state); | 6412 | warning(warn_state); | ||
6598 | hf_trend_val=10^polyval(p, fout(end)); | 6413 | hf_trend_val=10^polyval(p, fout(end)); | ||
6599 | if hf_trend_val>H_mag(end) | 6414 | if hf_trend_val>H_mag(end) | ||
6600 | hf_trend_val=H_mag(end); | 6415 | hf_trend_val=H_mag(end); | ||
6601 | end | 6416 | end | ||
6602 | fin_x=[fin_x, fout(end)]; | 6417 | fin_x=[fin_x, fout(end)]; | ||
6603 | H_mag_x = [H_mag_x hf_trend_val]; | 6418 | H_mag_x = [H_mag_x hf_trend_val]; | ||
6604 | end | 6419 | end | ||
6605 | H_mag_i = 10.^interp1(fin_x,log10(H_mag_x),fout,'linear', 'extrap'); | 6420 | H_mag_i = 10.^interp1(fin_x,log10(H_mag_x),fout,'linear', 'extrap'); | ||
6606 | case 'extrap_to_DC_or_zero' | 6421 | case 'extrap_to_DC_or_zero' | ||
6607 | % same as extrap_to_DC but detect AC-coupled channels and | 6422 | % same as extrap_to_DC but detect AC-coupled channels and | ||
6608 | % extrapolate them to 0. | 6423 | % extrapolate them to 0. | ||
6609 | if fin(1)>0 && 20*log10(H_mag(1))<-20 | 6424 | if fin(1)>0 && 20*log10(H_mag(1))<-20 | ||
6610 | % assume AC coupling, with 0 at DC | 6425 | % assume AC coupling, with 0 at DC | ||
6611 | H_mag_i = 10.^interp1([0, fin],[-100; log10(H_mag)],fout(fout<=fin(end)),'linear', 'extrap'); | 6426 | H_mag_i = 10.^interp1([0, fin],[-100; log10(H_mag)],fout(fout<=fin(end)),'linear', 'extrap'); | ||
6612 | else | 6427 | else | ||
6613 | H_mag_i = 10.^interp1(fin, log10(H_mag), fout(fout<=fin(end)),'linear', 'extrap'); | 6428 | H_mag_i = 10.^interp1(fin, log10(H_mag), fout(fout<=fin(end)),'linear', 'extrap'); | ||
6614 | end | 6429 | end | ||
6615 | H_mag_i(fout>fin(end)) = H_mag(end); | 6430 | H_mag_i(fout>fin(end)) = H_mag(end); | ||
6616 | case 'extrap_to_DC' | 6431 | case 'extrap_to_DC' | ||
6617 | % first extrapolate down to DC, then use highest available frequency | 6432 | % first extrapolate down to DC, then use highest available frequency | ||
6618 | % for higher frequencies | 6433 | % for higher frequencies | ||
6619 | H_mag_i = 10.^interp1(fin,log10(H_mag),fout(fout<=fin(end)),'linear', 'extrap'); | 6434 | H_mag_i = 10.^interp1(fin,log10(H_mag),fout(fout<=fin(end)),'linear', 'extrap'); | ||
6620 | H_mag_i(fout>fin(end)) = H_mag(end); | 6435 | H_mag_i(fout>fin(end)) = H_mag(end); | ||
6621 | case 'old' | 6436 | case 'old' | ||
6622 | H_mag_i = interp1(fin,H_mag,fout,'linear','extrap'); | 6437 | H_mag_i = interp1(fin,H_mag,fout,'linear','extrap'); | ||
6623 | otherwise | 6438 | otherwise | ||
6624 | error('COM:Extrap:InvalidOption', 'opt_interp_Sparam_mag valid values are "old", "extrap_to_DC"'); | 6439 | error('COM:Extrap:InvalidOption', 'opt_interp_Sparam_mag valid values are "old", "extrap_to_DC"'); | ||
6625 | end | 6440 | end | ||
6626 | 6441 | ||||
6627 | H_ph_i = interp1(fin,squeeze(H_ph),fout,'linear', 'extrap'); | 6442 | H_ph_i = interp1(fin,squeeze(H_ph),fout,'linear', 'extrap'); | ||
6628 | 6443 | ||||
6629 | %opt_interp_Sparam_phase='trend_and_shift_to_DC'; | 6444 | %opt_interp_Sparam_phase='trend_and_shift_to_DC'; | ||
6630 | %opt_interp_Sparam_phase='interp_cubic_to_dc_linear_to_inf'; | 6445 | %opt_interp_Sparam_phase='interp_cubic_to_dc_linear_to_inf'; | ||
6631 | switch opt_interp_Sparam_phase | 6446 | switch opt_interp_Sparam_phase | ||
6632 | case 'old' | 6447 | case 'old' | ||
6633 | H_ph_i = H_ph_i-H_ph_i(1); | 6448 | H_ph_i = H_ph_i-H_ph_i(1); | ||
6634 | case 'zero_DC' | 6449 | case 'zero_DC' | ||
6635 | H_ph_i(1) = 0; | 6450 | H_ph_i(1) = 0; | ||
6636 | case 'interp_to_DC' | 6451 | case 'interp_to_DC' | ||
6637 | if fin(1) ~= 0 | 6452 | if fin(1) ~= 0 | ||
6638 | H_ph_i = interp1([0; fin(:)], [0; H_ph(:)], fout, 'linear', 'extrap'); | 6453 | H_ph_i = interp1([0; fin(:)], [0; H_ph(:)], fout, 'linear', 'extrap'); | ||
6639 | end | 6454 | end | ||
6640 | case 'extrap_cubic_to_dc_linear_to_inf' | 6455 | case 'extrap_cubic_to_dc_linear_to_inf' | ||
6641 | if fin(1) ~= 0 | 6456 | if fin(1) ~= 0 | ||
6642 | % estimate low frequency group delay | 6457 | % estimate low frequency group delay | ||
6643 | group_delay = -diff(H_ph(:))./diff(fin(:)); | 6458 | group_delay = -diff(H_ph(:))./diff(fin(:)); | ||
6644 | low_freq_gd = group_delay(1:50); | 6459 | low_freq_gd = group_delay(1:50); | ||
6645 | % calculate trend, throwing away outliers | 6460 | % calculate trend, throwing away outliers | ||
6646 | m = median(low_freq_gd); sigma = std(low_freq_gd); | 6461 | m = median(low_freq_gd); sigma = std(low_freq_gd); | ||
6647 | lf_trend = mean(low_freq_gd(abs(low_freq_gd-m)<sigma)); | 6462 | lf_trend = mean(low_freq_gd(abs(low_freq_gd-m)<sigma)); | ||
6648 | % correct outliers in first 10 phase samples | 6463 | % correct outliers in first 10 phase samples | ||
6649 | for k=10:-1:1 | 6464 | for k=10:-1:1 | ||
6650 | H_ph(k) = H_ph(k+1) + lf_trend*(fin(k+1)-fin(k)); | 6465 | H_ph(k) = H_ph(k+1) + lf_trend*(fin(k+1)-fin(k)); | ||
6651 | end | 6466 | end | ||
6652 | H_ph_cubic = interp1(fin, H_ph, fout, 'pchip', 'extrap'); | 6467 | H_ph_cubic = interp1(fin, H_ph, fout, 'pchip', 'extrap'); | ||
6653 | H_ph_linear = interp1(fin, H_ph, fout, 'linear', 'extrap'); | 6468 | H_ph_linear = interp1(fin, H_ph, fout, 'linear', 'extrap'); | ||
6654 | % modification - trend to inf | 6469 | % modification - trend to inf | ||
6655 | if (1) | 6470 | if (1) | ||
6656 | high_freq_gd = group_delay(end-50:end); | 6471 | high_freq_gd = group_delay(end-50:end); | ||
6657 | % calculate trend, throwing away outliers | 6472 | % calculate trend, throwing away outliers | ||
6658 | m = median(high_freq_gd); sigma = std(high_freq_gd); | 6473 | m = median(high_freq_gd); sigma = std(high_freq_gd); | ||
6659 | hf_trend = -mean(high_freq_gd(abs(high_freq_gd-m)<sigma)); | 6474 | hf_trend = -mean(high_freq_gd(abs(high_freq_gd-m)<sigma)); | ||
6660 | hf_extrap_range = find(fout>fin(end)); | 6475 | hf_extrap_range = find(fout>fin(end)); | ||
6661 | last_data_sample = hf_extrap_range(1)-1; | 6476 | last_data_sample = hf_extrap_range(1)-1; | ||
6662 | H_ph_linear(hf_extrap_range) = H_ph_linear(last_data_sample) + (fout(hf_extrap_range)-fout(last_data_sample))*hf_trend; | 6477 | H_ph_linear(hf_extrap_range) = H_ph_linear(last_data_sample) + (fout(hf_extrap_range)-fout(last_data_sample))*hf_trend; | ||
6663 | % for k=hf_range | 6478 | % for k=hf_range | ||
6664 | % H_ph_linear(k) = H_ph_linear(k-1) + hf_trend*(fout(k)-fout(k-1)); | 6479 | % H_ph_linear(k) = H_ph_linear(k-1) + hf_trend*(fout(k)-fout(k-1)); | ||
6665 | % end | 6480 | % end | ||
6666 | end | 6481 | end | ||
6667 |
| 6482 |
| ||
6668 | [UNUSED_OUTPUT, indx] = min(abs(H_ph_cubic-H_ph_linear)); %#ok<ASGLU> | 6483 | [UNUSED_OUTPUT, indx] = min(abs(H_ph_cubic-H_ph_linear)); %#ok<ASGLU> | ||
6669 | H_ph_i=H_ph_cubic; | 6484 | H_ph_i=H_ph_cubic; | ||
6670 | H_ph_i(indx:end) = H_ph_linear(indx:end); | 6485 | H_ph_i(indx:end) = H_ph_linear(indx:end); | ||
6671 | H_ph_i = H_ph_linear; % John Ewen 12/13/2019 | 6486 | H_ph_i = H_ph_linear; % John Ewen 12/13/2019 | ||
6672 | end | 6487 | end | ||
6673 | case 'interp_and_shift_to_DC' | 6488 | case 'interp_and_shift_to_DC' | ||
6674 | if fin(1) ~= 0 | 6489 | if fin(1) ~= 0 | ||
6675 | dc_phase_trend = H_ph(1)-(H_ph(2)-H_ph(1))/(fin(2)-fin(1))*fin(1); | 6490 | dc_phase_trend = H_ph(1)-(H_ph(2)-H_ph(1))/(fin(2)-fin(1))*fin(1); | ||
6676 | H_ph_i = interp1([0; fin(:)], [0; H_ph(:)-dc_phase_trend], fout, 'linear', 'extrap'); | 6491 | H_ph_i = interp1([0; fin(:)], [0; H_ph(:)-dc_phase_trend], fout, 'linear', 'extrap'); | ||
6677 | end | 6492 | end | ||
6678 | case 'trend_and_shift_to_DC' | 6493 | case 'trend_and_shift_to_DC' | ||
6679 | % estimate low frequency group delay | 6494 | % estimate low frequency group delay | ||
6680 | group_delay = -diff(H_ph(:))./diff(fin(:)); | 6495 | group_delay = -diff(H_ph(:))./diff(fin(:)); | ||
6681 | low_freq_gd = group_delay(1:50); | 6496 | low_freq_gd = group_delay(1:50); | ||
6682 | % calculate trend, throwing away outliers | 6497 | % calculate trend, throwing away outliers | ||
6683 | m = median(low_freq_gd); sigma = std(low_freq_gd); | 6498 | m = median(low_freq_gd); sigma = std(low_freq_gd); | ||
6684 | lf_trend = mean(low_freq_gd(abs(low_freq_gd-m)<sigma)); | 6499 | lf_trend = mean(low_freq_gd(abs(low_freq_gd-m)<sigma)); | ||
6685 | fin_x=fin; | 6500 | fin_x=fin; | ||
6686 | H_ph_x=H_ph(:); | 6501 | H_ph_x=H_ph(:); | ||
6687 | if fin(1) ~= 0 | 6502 | if fin(1) ~= 0 | ||
6688 | % correct outliers in first 10 phase samples | 6503 | % correct outliers in first 10 phase samples | ||
6689 | for k=10:-1:1 | 6504 | for k=10:-1:1 | ||
6690 | H_ph(k) = H_ph(k+1) + lf_trend*(fin(k+1)-fin(k)); | 6505 | H_ph(k) = H_ph(k+1) + lf_trend*(fin(k+1)-fin(k)); | ||
6691 | end | 6506 | end | ||
6692 |
| 6507 |
| ||
6693 | % shift all phase data so that DC extrapolation to 0 follows trend | 6508 | % shift all phase data so that DC extrapolation to 0 follows trend | ||
6694 | dc_phase_trend = H_ph(1)+lf_trend*(fin(1)-0); | 6509 | dc_phase_trend = H_ph(1)+lf_trend*(fin(1)-0); | ||
6695 | fin_x=[0, fin_x]; | 6510 | fin_x=[0, fin_x]; | ||
6696 | H_ph_x=[0; H_ph(:)-dc_phase_trend]; | 6511 | H_ph_x=[0; H_ph(:)-dc_phase_trend]; | ||
6697 | end | 6512 | end | ||
6698 | % Modification: extrapolate using trend. (interp1 with "extrap" extrapolates using just | 6513 | % Modification: extrapolate using trend. (interp1 with "extrap" extrapolates using just | ||
6699 | % the last two samples, so noise can create an inverted slope and | 6514 | % the last two samples, so noise can create an inverted slope and | ||
6700 | % non-causal response). | 6515 | % non-causal response). | ||
6701 | if fout(end)>fin(end) | 6516 | if fout(end)>fin(end) | ||
6702 | group_delay = -diff(H_ph_x(:))./diff(fin_x(:)); | 6517 | group_delay = -diff(H_ph_x(:))./diff(fin_x(:)); | ||
6703 | % p=polyfit(fin_x', H_ph_x, 1); | 6518 | % p=polyfit(fin_x', H_ph_x, 1); | ||
6704 | hf_phase_trend = H_ph_x(end)-median(group_delay)*(max(fout)-max(fin_x)); | 6519 | hf_phase_trend = H_ph_x(end)-median(group_delay)*(max(fout)-max(fin_x)); | ||
6705 | % hf_phase_trend=polyval(p,max(fout)); | 6520 | % hf_phase_trend=polyval(p,max(fout)); | ||
6706 | fin_x=[fin_x, fout(end)]; | 6521 | fin_x=[fin_x, fout(end)]; | ||
6707 | H_ph_x=[H_ph_x; hf_phase_trend]; | 6522 | H_ph_x=[H_ph_x; hf_phase_trend]; | ||
6708 | end | 6523 | end | ||
6709 | H_ph_i = interp1(fin_x, H_ph_x, fout, 'linear', 'extrap'); | 6524 | H_ph_i = interp1(fin_x, H_ph_x, fout, 'linear', 'extrap'); | ||
6710 |
| 6525 |
| ||
6711 | otherwise | 6526 | otherwise | ||
6712 | error('COM:Extrap:InvalidOption', ... | 6527 | error('COM:Extrap:InvalidOption', ... | ||
6713 | 'debug_interp_Sparam valid values are "old", "zero_DC", "interp_to_DC", "interp_and_shift_to_DC", "trend_and_shift_to_DC", "interp_cubic_to_dc_linear_to_inf"'); | 6528 | 'debug_interp_Sparam valid values are "old", "zero_DC", "interp_to_DC", "interp_and_shift_to_DC", "trend_and_shift_to_DC", "interp_cubic_to_dc_linear_to_inf"'); | ||
6714 | end | 6529 | end | ||
6715 | H_i = H_mag_i.*exp(1j*H_ph_i); | 6530 | H_i = H_mag_i.*exp(1j*H_ph_i); | ||
6716 | Sout=H_i; | 6531 | Sout=H_i; | ||
6717 | function [ s11out, s12out, s21out, s22out]=make_full_pkg(type,faxis,param,channel_type,mode,include_die) | 6532 | function [ s11out, s12out, s21out, s22out]=make_full_pkg(type,faxis,param,channel_type,mode,include_die) | ||
6718 | 6533 | ||||
6719 | %This function makes the TX or RX package. The type input must be | 6534 | %This function makes the TX or RX package. The type input must be | ||
6720 | %'TX' or 'RX' | 6535 | %'TX' or 'RX' | ||
6721 | %If the mode argument is omitted, mode='dd' is assumed. Currently | 6536 | %If the mode argument is omitted, mode='dd' is assumed. Currently | ||
6722 | %mode='dc' is only used when making the TX package for AC CM noise | 6537 | %mode='dc' is only used when making the TX package for AC CM noise | ||
6723 | %inclusion. The Rx package for 'dc' mode is still generated using | 6538 | %inclusion. The Rx package for 'dc' mode is still generated using | ||
6724 | %the same parameters as 'dd' mode | 6539 | %the same parameters as 'dd' mode | ||
6725 | %channel_type should be 'THRU' 'FEXT' or 'NEXT' | 6540 | %channel_type should be 'THRU' 'FEXT' or 'NEXT' | ||
6726 | % | 6541 | % | ||
6727 | %One instance of package block looks like this (if no elements are set to 0): | 6542 | %One instance of package block looks like this (if no elements are set to 0): | ||
6728 | %-------------Lcomp----------Tline--------------- | 6543 | %-------------Lcomp----------Tline--------------- | ||
6729 | % | | | | 6544 | % | | | | ||
6730 | % Cpad Cbump Cball | 6545 | % Cpad Cbump Cball | ||
6731 | % | | | | 6546 | % | | | | ||
6732 | %------------------------------------------------ | 6547 | %------------------------------------------------ | ||
6733 | 6548 | ||||
6734 | if nargin<6 | 6549 | if nargin<6 | ||
6735 | %optional input "include_die"=0 allows die parameters to be forced to 0 | 6550 | %optional input "include_die"=0 allows die parameters to be forced to 0 | ||
6736 | %this includes Cpad, Lcomp, and Cbump | 6551 | %this includes Cpad, Lcomp, and Cbump | ||
6737 | include_die=1; | 6552 | include_die=1; | ||
6738 | end | 6553 | end | ||
6739 | if nargin<5 | 6554 | if nargin<5 | ||
6740 | mode='dd'; | 6555 | mode='dd'; | ||
6741 | end | 6556 | end | ||
6742 | 6557 | ||||
6743 | 6558 | ||||
6744 | if ~isempty(param.PKG_NAME) | 6559 | if ~isempty(param.PKG_NAME) | ||
6745 | %The gamma and tau parameters do not currently have a separate Tx and Rx home to live (they were locked for both sides originally) | 6560 | %The gamma and tau parameters do not currently have a separate Tx and Rx home to live (they were locked for both sides originally) | ||
6746 | %so they are swapped in depending on if Tx or Rx is set for type | 6561 | %so they are swapped in depending on if Tx or Rx is set for type | ||
6747 | %Note that param is not returned from this function, so the swap does not persist | 6562 | %Note that param is not returned from this function, so the swap does not persist | ||
6748 | swap_fields = {'pkg_gamma0_a1_a2' 'pkg_tau'}; | 6563 | swap_fields = {'pkg_gamma0_a1_a2' 'pkg_tau'}; | ||
6749 | if strcmpi(type,'tx') | 6564 | if strcmpi(type,'tx') | ||
6750 | pkg_name = param.PKG_NAME{1}; | 6565 | pkg_name = param.PKG_NAME{1}; | ||
6751 | elseif strcmpi(type,'rx') | 6566 | elseif strcmpi(type,'rx') | ||
6752 | pkg_name = param.PKG_NAME{2}; | 6567 | pkg_name = param.PKG_NAME{2}; | ||
6753 | else | 6568 | else | ||
6754 | error('Pkg type must be Tx or Rx'); | 6569 | error('Pkg type must be Tx or Rx'); | ||
6755 | end | 6570 | end | ||
6756 | pkg_parameter_struct = param.PKG.(pkg_name); | 6571 | pkg_parameter_struct = param.PKG.(pkg_name); | ||
6757 | 6572 | ||||
6758 |
| 6573 |
| ||
6759 | for j=1:length(swap_fields) | 6574 | for j=1:length(swap_fields) | ||
6760 | param.(swap_fields{j}) = pkg_parameter_struct.(swap_fields{j}); | 6575 | param.(swap_fields{j}) = pkg_parameter_struct.(swap_fields{j}); | ||
6761 | end | 6576 | end | ||
6762 |
| 6577 |
| ||
6763 | end | 6578 | end | ||
6764 | 6579 | ||||
6765 | C_diepad = param.C_diepad; | 6580 | C_diepad = param.C_diepad; | ||
6766 | C_pkg_board = param.C_pkg_board; | 6581 | C_pkg_board = param.C_pkg_board; | ||
6767 | % [ahealey] Unpack optional compensating L and "bump" C model parameters. | 6582 | % [ahealey] Unpack optional compensating L and "bump" C model parameters. | ||
6768 | L_comp = param.L_comp; | 6583 | L_comp = param.L_comp; | ||
6769 | C_bump = param.C_bump; | 6584 | C_bump = param.C_bump; | ||
6770 | if ~include_die | 6585 | if ~include_die | ||
6771 | %best to multiply by 0. that way vectors maintain original size | 6586 | %best to multiply by 0. that way vectors maintain original size | ||
6772 | C_diepad=C_diepad*0; | 6587 | C_diepad=C_diepad*0; | ||
6773 | L_comp=L_comp*0; | 6588 | L_comp=L_comp*0; | ||
6774 | C_bump=C_bump*0; | 6589 | C_bump=C_bump*0; | ||
6775 | end | 6590 | end | ||
6776 | % [ahealey] End of modifications. | 6591 | % [ahealey] End of modifications. | ||
6777 | % generate TX package according to channel type. | 6592 | % generate TX package according to channel type. | ||
6778 | [ncases, mele]=size(param.z_p_next_cases); | 6593 | [ncases, mele]=size(param.z_p_next_cases); | ||
6779 | 6594 | ||||
6780 | %Syntax update for C_diepad and L_comp | 6595 | %Syntax update for C_diepad and L_comp | ||
6781 | %Allow a chain of values to be entered as a matrix: | 6596 | %Allow a chain of values to be entered as a matrix: | ||
6782 | %[L_Tx1 L_Tx2 L_Tx3 ; L_Rx1 L_Rx2 L_Rx3] | 6597 | %[L_Tx1 L_Tx2 L_Tx3 ; L_Rx1 L_Rx2 L_Rx3] | ||
6783 | if isvector(C_diepad) | 6598 | if isvector(C_diepad) | ||
6784 | Cd_Tx=C_diepad(1); | 6599 | Cd_Tx=C_diepad(1); | ||
6785 | Cd_Rx=C_diepad(2); | 6600 | Cd_Rx=C_diepad(2); | ||
6786 | L_comp_Tx=L_comp(1); | 6601 | L_comp_Tx=L_comp(1); | ||
6787 | L_comp_Rx=L_comp(2); | 6602 | L_comp_Rx=L_comp(2); | ||
6788 | num_blocks=mele; | 6603 | num_blocks=mele; | ||
6789 | else | 6604 | else | ||
6790 | Cd_Tx=C_diepad(1,:); | 6605 | Cd_Tx=C_diepad(1,:); | ||
6791 | Cd_Rx=C_diepad(2,:); | 6606 | Cd_Rx=C_diepad(2,:); | ||
6792 | L_comp_Tx=L_comp(1,:); | 6607 | L_comp_Tx=L_comp(1,:); | ||
6793 | L_comp_Rx=L_comp(2,:); | 6608 | L_comp_Rx=L_comp(2,:); | ||
6794 | num_blocks=mele+length(Cd_Tx)-1; | 6609 | num_blocks=mele+length(Cd_Tx)-1; | ||
6795 | end | 6610 | end | ||
6796 | extra_LC=length(Cd_Tx)-1; | 6611 | extra_LC=length(Cd_Tx)-1; | ||
6797 | %note: "insert_zeros" is empty if length(Cd_Tx) = 1 | 6612 | %note: "insert_zeros" is empty if length(Cd_Tx) = 1 | ||
6798 | insert_zeros=zeros([1 extra_LC]); | 6613 | insert_zeros=zeros([1 extra_LC]); | ||
6799 | 6614 | ||||
6800 | %Updated technique of building Tx/Rx packages | 6615 | %Updated technique of building Tx/Rx packages | ||
6801 | %each index corresponds to the package segment | 6616 | %each index corresponds to the package segment | ||
6802 | switch type | 6617 | switch type | ||
6803 | case 'TX' | 6618 | case 'TX' | ||
6804 | switch mele | 6619 | switch mele | ||
6805 | case 1 | 6620 | case 1 | ||
6806 | Cpad=Cd_Tx; | 6621 | Cpad=Cd_Tx; | ||
6807 | Lcomp=L_comp_Tx; | 6622 | Lcomp=L_comp_Tx; | ||
6808 | Cbump=C_bump(1); | 6623 | Cbump=C_bump(1); | ||
6809 | Cball=C_pkg_board(1); | 6624 | Cball=C_pkg_board(1); | ||
6810 | Zpkg=param.pkg_Z_c(1); | 6625 | Zpkg=param.pkg_Z_c(1); | ||
6811 | case 4 | 6626 | case 4 | ||
6812 | Cpad=[Cd_Tx 0 0 0]; | 6627 | Cpad=[Cd_Tx 0 0 0]; | ||
6813 | Lcomp=[L_comp_Tx 0 0 0]; | 6628 | Lcomp=[L_comp_Tx 0 0 0]; | ||
6814 | Cbump=[C_bump(1) 0 0 0]; | 6629 | Cbump=[C_bump(1) 0 0 0]; | ||
6815 | Cball=[0 0 param.C_v(1) C_pkg_board(1)]; | 6630 | Cball=[0 0 param.C_v(1) C_pkg_board(1)]; | ||
6816 | Zpkg=param.pkg_Z_c(1,:); | 6631 | Zpkg=param.pkg_Z_c(1,:); | ||
6817 | otherwise | 6632 | otherwise | ||
6818 | error('package syntax error') | 6633 | error('package syntax error') | ||
6819 | end | 6634 | end | ||
6820 | switch upper(channel_type) | 6635 | switch upper(channel_type) | ||
6821 | case 'THRU' | 6636 | case 'THRU' | ||
6822 | Len=param.Pkg_len_TX; | 6637 | Len=param.Pkg_len_TX; | ||
6823 | case 'NEXT' | 6638 | case 'NEXT' | ||
6824 | Len=param.Pkg_len_NEXT; | 6639 | Len=param.Pkg_len_NEXT; | ||
6825 | case 'FEXT' | 6640 | case 'FEXT' | ||
6826 | Len=param.Pkg_len_FEXT; | 6641 | Len=param.Pkg_len_FEXT; | ||
6827 | end | 6642 | end | ||
6828 | case 'RX' | 6643 | case 'RX' | ||
6829 | switch mele | 6644 | switch mele | ||
6830 | case 1 | 6645 | case 1 | ||
6831 | Cpad=Cd_Rx; | 6646 | Cpad=Cd_Rx; | ||
6832 | Lcomp=L_comp_Rx; | 6647 | Lcomp=L_comp_Rx; | ||
6833 | Cbump=C_bump(2); | 6648 | Cbump=C_bump(2); | ||
6834 | Cball=C_pkg_board(2); | 6649 | Cball=C_pkg_board(2); | ||
6835 | Zpkg=param.pkg_Z_c(2); | 6650 | Zpkg=param.pkg_Z_c(2); | ||
6836 | case 4 | 6651 | case 4 | ||
6837 | Cpad=[Cd_Rx 0 0 0]; | 6652 | Cpad=[Cd_Rx 0 0 0]; | ||
6838 | Lcomp=[L_comp_Rx 0 0 0]; | 6653 | Lcomp=[L_comp_Rx 0 0 0]; | ||
6839 | Cbump=[C_bump(2) 0 0 0]; | 6654 | Cbump=[C_bump(2) 0 0 0]; | ||
6840 | Cball=[0 0 param.C_v(2) C_pkg_board(2)]; | 6655 | Cball=[0 0 param.C_v(2) C_pkg_board(2)]; | ||
6841 | Zpkg=param.pkg_Z_c(2,:); | 6656 | Zpkg=param.pkg_Z_c(2,:); | ||
6842 | otherwise | 6657 | otherwise | ||
6843 | error('package syntax error') | 6658 | error('package syntax error') | ||
6844 | end | 6659 | end | ||
6845 | switch upper(channel_type) | 6660 | switch upper(channel_type) | ||
6846 | case 'THRU' | 6661 | case 'THRU' | ||
6847 | Len=param.Pkg_len_RX; | 6662 | Len=param.Pkg_len_RX; | ||
6848 | case 'NEXT' | 6663 | case 'NEXT' | ||
6849 | Len=param.Pkg_len_RX; | 6664 | Len=param.Pkg_len_RX; | ||
6850 | case 'FEXT' | 6665 | case 'FEXT' | ||
6851 | Len=param.Pkg_len_RX; | 6666 | Len=param.Pkg_len_RX; | ||
6852 | end | 6667 | end | ||
6853 | end | 6668 | end | ||
6854 | 6669 | ||||
6855 | %Insert the extra 0 at the front end of Cball, Cbump, Len, and Zpkg | 6670 | %Insert the extra 0 at the front end of Cball, Cbump, Len, and Zpkg | ||
6856 | Cball=[insert_zeros Cball]; | 6671 | Cball=[insert_zeros Cball]; | ||
6857 | Cbump=[insert_zeros Cbump]; | 6672 | Cbump=[insert_zeros Cbump]; | ||
6858 | Len=[insert_zeros Len]; | 6673 | Len=[insert_zeros Len]; | ||
6859 | Zpkg=[insert_zeros Zpkg]; | 6674 | Zpkg=[insert_zeros Zpkg]; | ||
6860 | 6675 | ||||
6861 | % debug_string=''; | 6676 | % debug_string=''; | ||
6862 | % for j=1:length(Zpkg) | 6677 | % for j=1:length(Zpkg) | ||
6863 | % if Cpad(j)~=0 | 6678 | % if Cpad(j)~=0 | ||
6864 | % debug_string=[debug_string sprintf(', Cd=%0.4g',Cpad(j))]; | 6679 | % debug_string=[debug_string sprintf(', Cd=%0.4g',Cpad(j))]; | ||
6865 | % end | 6680 | % end | ||
6866 | % if Lcomp(j)~=0 | 6681 | % if Lcomp(j)~=0 | ||
6867 | % debug_string=[debug_string sprintf(', Ls=%0.4g',Lcomp(j))]; | 6682 | % debug_string=[debug_string sprintf(', Ls=%0.4g',Lcomp(j))]; | ||
6868 | % end | 6683 | % end | ||
6869 | % if Cbump(j)~=0 | 6684 | % if Cbump(j)~=0 | ||
6870 | % debug_string=[debug_string sprintf(', Cb=%0.4g',Cbump(j))]; | 6685 | % debug_string=[debug_string sprintf(', Cb=%0.4g',Cbump(j))]; | ||
6871 | % end | 6686 | % end | ||
6872 | % if Len(j)~=0 | 6687 | % if Len(j)~=0 | ||
6873 | % debug_string=[debug_string sprintf(', Len=%0.4g Zc=%0.3g',Len(j),Zpkg(j))]; | 6688 | % debug_string=[debug_string sprintf(', Len=%0.4g Zc=%0.3g',Len(j),Zpkg(j))]; | ||
6874 | % end | 6689 | % end | ||
6875 | % if Cball(j)~=0 | 6690 | % if Cball(j)~=0 | ||
6876 | % debug_string=[debug_string sprintf(', Cp=%0.4g',Cball(j))]; | 6691 | % debug_string=[debug_string sprintf(', Cp=%0.4g',Cball(j))]; | ||
6877 | % end | 6692 | % end | ||
6878 | % end | 6693 | % end | ||
6879 | % if length(debug_string)>2 | 6694 | % if length(debug_string)>2 | ||
6880 | % debug_string=debug_string(3:end); | 6695 | % debug_string=debug_string(3:end); | ||
6881 | % end | 6696 | % end | ||
6882 | 6697 | ||||
6883 | % tx package | 6698 | % tx package | ||
6884 | pkg_param=param; | 6699 | pkg_param=param; | ||
6885 | if strcmpi(mode,'dc') | 6700 | if strcmpi(mode,'dc') | ||
6886 | % change tx package to CC mode | 6701 | % change tx package to CC mode | ||
6887 | pkg_param.Z0=pkg_param.Z0/2; | 6702 | pkg_param.Z0=pkg_param.Z0/2; | ||
6888 | Cpad=Cpad*2; | 6703 | Cpad=Cpad*2; | ||
6889 | Cball=Cball*2; | 6704 | Cball=Cball*2; | ||
6890 | Zpkg=Zpkg*2; | 6705 | Zpkg=Zpkg*2; | ||
6891 | Lcomp=Lcomp/2; | 6706 | Lcomp=Lcomp/2; | ||
6892 | Cbump=Cbump*2; | 6707 | Cbump=Cbump*2; | ||
6893 | end | 6708 | end | ||
6894 | switch num_blocks | 6709 | switch num_blocks | ||
6895 | case 1 | 6710 | case 1 | ||
6896 | [ s11out, s12out, s21out, s22out ]= make_pkg(faxis, Len(1), Cpad(1), Cball(1),Zpkg(1), pkg_param, Lcomp(1), Cbump(1)); | 6711 | [ s11out, s12out, s21out, s22out ]= make_pkg(faxis, Len(1), Cpad(1), Cball(1),Zpkg(1), pkg_param, Lcomp(1), Cbump(1)); | ||
6897 | otherwise | 6712 | otherwise | ||
6898 | for j=1:num_blocks | 6713 | for j=1:num_blocks | ||
6899 | [spkg11,spkg12,spkg21,spkg22]=make_pkg(faxis, Len(j), Cpad(j),Cball(j) ,Zpkg(j), pkg_param, Lcomp(j),Cbump(j)); | 6714 | [spkg11,spkg12,spkg21,spkg22]=make_pkg(faxis, Len(j), Cpad(j),Cball(j) ,Zpkg(j), pkg_param, Lcomp(j),Cbump(j)); | ||
6900 | if j==1 | 6715 | if j==1 | ||
6901 | s11out=spkg11; s12out=spkg12; s21out=spkg21; s22out=spkg22; | 6716 | s11out=spkg11; s12out=spkg12; s21out=spkg21; s22out=spkg22; | ||
6902 | else | 6717 | else | ||
6903 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out, s12out, s21out, s22out, spkg11,spkg12,spkg21,spkg22 ); | 6718 | [ s11out, s12out, s21out, s22out ]=combines4p( s11out, s12out, s21out, s22out, spkg11,spkg12,spkg21,spkg22 ); | ||
6904 | end | 6719 | end | ||
6905 | end | 6720 | end | ||
6906 | end | 6721 | end | ||
6907 | function [ s11out, s12out, s21out, s22out ] = make_pkg(f, pkg_len, cpad, cball, pkg_z, param, varargin) | 6722 | function [ s11out, s12out, s21out, s22out ] = make_pkg(f, pkg_len, cpad, cball, pkg_z, param, varargin) | ||
6908 | f(f<eps)=eps; | 6723 | f(f<eps)=eps; | ||
6909 | tau = param.pkg_tau; gamma0_a1_a2=param.pkg_gamma0_a1_a2; Lenscale=pkg_len; zref=param.Z0; | 6724 | tau = param.pkg_tau; gamma0_a1_a2=param.pkg_gamma0_a1_a2; Lenscale=pkg_len; zref=param.Z0; | ||
6910 | %% Equation 93A-8 | 6725 | %% Equation 93A-8 | ||
6911 | s11pad= -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | 6726 | s11pad= -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | ||
6912 | s21pad= 2./(2+1i*2*pi.*f*cpad*zref); | 6727 | s21pad= 2./(2+1i*2*pi.*f*cpad*zref); | ||
6913 | 6728 | ||||
6914 | % [ahealey] Add compensating L and shunt C (bump) when requested. | 6729 | % [ahealey] Add compensating L and shunt C (bump) when requested. | ||
6915 | s12pad = s21pad; | 6730 | s12pad = s21pad; | ||
6916 | s22pad = s11pad; | 6731 | s22pad = s11pad; | ||
6917 | if nargin > 6 | 6732 | if nargin > 6 | ||
6918 | lcomp = varargin{1}; | 6733 | lcomp = varargin{1}; | ||
6919 | if lcomp>0 | 6734 | if lcomp>0 | ||
6920 | s11comp = (1i*2*pi*f*lcomp/zref)./(2+1i*2*pi*f*lcomp/zref); | 6735 | s11comp = (1i*2*pi*f*lcomp/zref)./(2+1i*2*pi*f*lcomp/zref); | ||
6921 | s21comp = 2./(2+1i*2*pi*f*lcomp/zref); | 6736 | s21comp = 2./(2+1i*2*pi*f*lcomp/zref); | ||
6922 | [s11pad, s12pad, s21pad, s22pad] = combines4p( ... | 6737 | [s11pad, s12pad, s21pad, s22pad] = combines4p( ... | ||
6923 | s11pad, s12pad, s21pad, s22pad, ... | 6738 | s11pad, s12pad, s21pad, s22pad, ... | ||
6924 | s11comp, s21comp, s21comp, s11comp); | 6739 | s11comp, s21comp, s21comp, s11comp); | ||
6925 | end | 6740 | end | ||
6926 | end | 6741 | end | ||
6927 | if nargin > 7 | 6742 | if nargin > 7 | ||
6928 | cbump = varargin{2}; | 6743 | cbump = varargin{2}; | ||
6929 | if cbump>0 | 6744 | if cbump>0 | ||
6930 | s11bump = -1i*2*pi.*f*cbump*zref./(2+1i*2*pi.*f*cbump*zref); | 6745 | s11bump = -1i*2*pi.*f*cbump*zref./(2+1i*2*pi.*f*cbump*zref); | ||
6931 | s21bump = 2./(2+1i*2*pi.*f*cbump*zref); | 6746 | s21bump = 2./(2+1i*2*pi.*f*cbump*zref); | ||
6932 | [s11pad, s12pad, s21pad, s22pad] = combines4p( ... | 6747 | [s11pad, s12pad, s21pad, s22pad] = combines4p( ... | ||
6933 | s11pad, s12pad, s21pad, s22pad, ... | 6748 | s11pad, s12pad, s21pad, s22pad, ... | ||
6934 | s11bump, s21bump, s21bump, s11bump); | 6749 | s11bump, s21bump, s21bump, s11bump); | ||
6935 | end | 6750 | end | ||
6936 | end | 6751 | end | ||
6937 | % [ahealey] End of modifications. | 6752 | % [ahealey] End of modifications. | ||
6938 | 6753 | ||||
6939 | [ S11, S12, S21, S22 ] = synth_tline(f, pkg_z, zref, gamma0_a1_a2, tau, Lenscale); %#ok<NASGU,ASGLU> | 6754 | [ S11, S12, S21, S22 ] = synth_tline(f, pkg_z, zref, gamma0_a1_a2, tau, Lenscale); %#ok<NASGU,ASGLU> | ||
6940 | % [ahealey] Symmetry cannot be assumed with more complex termination models. | 6755 | % [ahealey] Symmetry cannot be assumed with more complex termination models. | ||
6941 | % [ s11out1, s12out1, s21out1, s22out1 ]= ... | 6756 | % [ s11out1, s12out1, s21out1, s22out1 ]= ... | ||
6942 | % combines4p( s11pad, s21pad, s21pad, s11pad, S11, S21, S21, S11 ); % first part of equation 93A-15 | 6757 | % combines4p( s11pad, s21pad, s21pad, s11pad, S11, S21, S21, S11 ); % first part of equation 93A-15 | ||
6943 | [s11out1, s12out1, s21out1, s22out1] = combines4p( ... | 6758 | [s11out1, s12out1, s21out1, s22out1] = combines4p( ... | ||
6944 | s11pad, s12pad, s21pad, s22pad, ... | 6759 | s11pad, s12pad, s21pad, s22pad, ... | ||
6945 | S11, S21, S21, S11); | 6760 | S11, S21, S21, S11); | ||
6946 | % [ahealey] End of modifications. | 6761 | % [ahealey] End of modifications. | ||
6947 | 6762 | ||||
6948 | %% Equation 93A-8 | 6763 | %% Equation 93A-8 | ||
6949 | s11ball= -1i*2*pi.*f*cball*zref./(2+1i*2*pi.*f*cball*zref); | 6764 | s11ball= -1i*2*pi.*f*cball*zref./(2+1i*2*pi.*f*cball*zref); | ||
6950 | s21ball= 2./(2+1i*2*pi.*f*cball*zref); | 6765 | s21ball= 2./(2+1i*2*pi.*f*cball*zref); | ||
6951 | [ s11out, s12out, s21out, s22out ]= ... | 6766 | [ s11out, s12out, s21out, s22out ]= ... | ||
6952 | combines4p( s11out1, s12out1, s21out1, s22out1, s11ball, s21ball, s21ball, s11ball );% second part of equation 93A-15 | 6767 | combines4p( s11out1, s12out1, s21out1, s22out1, s11ball, s21ball, s21ball, s11ball );% second part of equation 93A-15 | ||
6953 | 6768 | ||||
6954 | function missingParameter (parameterName) | 6769 | function missingParameter (parameterName) | ||
6955 | error( 'error:badParameterInformation', ... | 6770 | error( 'error:badParameterInformation', ... | ||
6956 | 'The data for mandatory parameter %s is missing or incorrect' , parameterName); | 6771 | 'The data for mandatory parameter %s is missing or incorrect' , parameterName); | ||
6957 | 6772 | ||||
6958 | function pdf = normal_dist(sigma,nsigma,binsize) | 6773 | function pdf = normal_dist(sigma,nsigma,binsize) | ||
6959 | pdf.BinSize=binsize; | 6774 | pdf.BinSize=binsize; | ||
6960 | pdf.Min=-round(2*nsigma*sigma/binsize); % RIM 03/03/2023 capture more of the tails | 6775 | pdf.Min=-round(2*nsigma*sigma/binsize); % RIM 03/03/2023 capture more of the tails | ||
6961 | pdf.x=(pdf.Min:-pdf.Min)*binsize; | 6776 | pdf.x=(pdf.Min:-pdf.Min)*binsize; | ||
6962 | pdf.y=exp(-pdf.x.^2/(2*sigma^2+eps)); | 6777 | pdf.y=exp(-pdf.x.^2/(2*sigma^2+eps)); | ||
6963 | pdf.y=pdf.y/sum(pdf.y); | 6778 | pdf.y=pdf.y/sum(pdf.y); | ||
6964 | 6779 | ||||
6965 | function result=optimize_fom(OP, param, chdata, sigma_bn,do_C2M) | 6780 | function result=optimize_fom(OP, param, chdata, sigma_bn,do_C2M) | ||
6966 | %% input | 6781 | %% input | ||
6967 | % chdata(1).uneq_imp_response is the impulse response input expected to be normalized to At, peak drive voltage | 6782 | % chdata(1).uneq_imp_response is the impulse response input expected to be normalized to At, peak drive voltage | ||
6968 | % baud_rate - baud rate in seconds | 6783 | % baud_rate - baud rate in seconds | ||
6969 | % param.samples_per_ui = samples per UI of IR | 6784 | % param.samples_per_ui = samples per UI of IR | ||
6970 | % param.max_ctle - maximum ac to dc gain in dB | 6785 | % param.max_ctle - maximum ac to dc gain in dB | ||
6971 | % param.tx_ffe(1) - maximum pre cursor (positive value) | 6786 | % param.tx_ffe(1) - maximum pre cursor (positive value) | ||
6972 | % param.tx_ffe(2) - maximum post cursor (positive value) | 6787 | % param.tx_ffe(2) - maximum post cursor (positive value) | ||
6973 | % param.tx_ffe_step - sweep step size for tx pre and post taps | 6788 | % param.tx_ffe_step - sweep step size for tx pre and post taps | ||
6974 | % param.ndfe - number of reference dfe taps | 6789 | % param.ndfe - number of reference dfe taps | ||
6975 | % do_C2M. set to 0 for standard optimize_fom. set to 1 for optimize_fom_for_C2M | 6790 | % do_C2M. set to 0 for standard optimize_fom. set to 1 for optimize_fom_for_C2M | ||
6976 | % output | 6791 | % output | ||
6977 | % result.eq.txle - [ precusor curosr postcursor]: pre and post are negative | 6792 | % result.eq.txle - [ precusor curosr postcursor]: pre and post are negative | ||
6978 | % result.eq.ctle - index of CTLE parameters in table | 6793 | % result.eq.ctle - index of CTLE parameters in table | ||
6979 | % result.IR - impulse response | 6794 | % result.IR - impulse response | ||
6980 | % result.avail_signal - maximum signal after equalization | 6795 | % result.avail_signal - maximum signal after equalization | ||
6981 | % result.avail_sig_index - index in result.IR of max signal | 6796 | % result.avail_sig_index - index in result.IR of max signal | ||
6982 | % result.best_FOM - best raw ISI | 6797 | % result.best_FOM - best raw ISI | ||
| + | 6798 | |||
6983 | 6799 | ||||
6984 | min_number_of_UI_in_response=40; | 6800 | min_number_of_UI_in_response=40; | ||
6985 | baud_rate=1/param.ui; | 6801 | baud_rate=1/param.ui; | ||
6986 | % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(1).faxis/(param.f_r*param.fb)); | 6802 | % H_r = 1./polyval([1 2.613126 3.414214 2.613126 1], 1i*chdata(1).faxis/(param.f_r*param.fb)); | ||
6987 | f=chdata(1).faxis; | 6803 | f=chdata(1).faxis; | ||
6988 | 6804 | ||||
6989 | %Read user input of ts_sample_adj_range | 6805 | %Read user input of ts_sample_adj_range | ||
6990 | %if one value was entered, go from 0 to that value | 6806 | %if one value was entered, go from 0 to that value | ||
6991 | %if 2 values were entered, go from the 1st value to the 2nd value | 6807 | %if 2 values were entered, go from the 1st value to the 2nd value | ||
6992 | if length(param.ts_sample_adj_range)==1 | 6808 | if length(param.ts_sample_adj_range)==1 | ||
6993 | param.ts_sample_adj_range(2)=param.ts_sample_adj_range(1); | 6809 | param.ts_sample_adj_range(2)=param.ts_sample_adj_range(1); | ||
6994 | param.ts_sample_adj_range(1)=0; | 6810 | param.ts_sample_adj_range(1)=0; | ||
6995 | end | 6811 | end | ||
6996 | full_sample_range=param.ts_sample_adj_range(1):param.ts_sample_adj_range(2); | 6812 | full_sample_range=param.ts_sample_adj_range(1):param.ts_sample_adj_range(2); | ||
6997 | 6813 | ||||
6998 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | 6814 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | ||
6999 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | 6815 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | ||
7000 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine);% experiment with RCos | 6816 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine);% experiment with RCos | ||
7001 | % need to include H_RCos in noise and when computing the system ir for thru | 6817 | % need to include H_RCos in noise and when computing the system ir for thru | ||
7002 | % and crosstalk | 6818 | % and crosstalk | ||
7003 | H_r=H_bw.*H_bt.*H_RCos; | 6819 | H_r=H_bw.*H_bt.*H_RCos; | ||
7004 | %% Bill Kirkland, need to get auto correlation of H_r.*HCTLE | 6820 | %% Bill Kirkland, need to get auto correlation of H_r.*HCTLE | ||
7005 | % Get f vector from 0 to Fs/2-delta_f. | 6821 | % Get f vector from 0 to Fs/2-delta_f. | ||
7006 | N_fft_by2 = 512; | 6822 | N_fft_by2 = 512; | ||
7007 | f_xc = ((1:N_fft_by2)-1)/N_fft_by2*baud_rate*param.samples_per_ui/2; | 6823 | f_xc = ((1:N_fft_by2)-1)/N_fft_by2*baud_rate*param.samples_per_ui/2; | ||
7008 | H_bt_xc=Bessel_Thomson_Filter(param,f_xc,OP.Bessel_Thomson); | 6824 | H_bt_xc=Bessel_Thomson_Filter(param,f_xc,OP.Bessel_Thomson); | ||
7009 | H_bw_xc=Butterworth_Filter(param,f_xc,OP.Butterworth); | 6825 | H_bw_xc=Butterworth_Filter(param,f_xc,OP.Butterworth); | ||
7010 | H_RCos_xc=Raised_Cosine_Filter(param,f_xc,OP.Raised_Cosine); | 6826 | H_RCos_xc=Raised_Cosine_Filter(param,f_xc,OP.Raised_Cosine); | ||
7011 | H_r_xc=H_bw_xc.*H_bt_xc.*H_RCos_xc; | 6827 | H_r_xc=H_bw_xc.*H_bt_xc.*H_RCos_xc; | ||
7012 | %% | 6828 | %% | ||
7013 | 6829 | ||||
7014 | % system noise H_sy PSD | 6830 | % system noise H_sy PSD | ||
7015 | if OP.USE_ETA0_PSD | 6831 | if OP.USE_ETA0_PSD | ||
7016 | fspike=1e9; | 6832 | fspike=1e9; | ||
7017 | % requires communication tool box if used | 6833 | % requires communication tool box if used | ||
7018 | H_sy=sinc(sqrt(2)*(chdata(1).faxis-fspike)/(fspike)).^2; | 6834 | H_sy=sinc(sqrt(2)*(chdata(1).faxis-fspike)/(fspike)).^2; | ||
7019 | else | 6835 | else | ||
7020 | H_sy=ones(1,length(chdata(1).faxis)); | 6836 | H_sy=ones(1,length(chdata(1).faxis)); | ||
7021 | end | 6837 | end | ||
7022 | 6838 | ||||
7023 | %Build txffe values dynamically | 6839 | %Build txffe values dynamically | ||
7024 | %any param field that is "tx_ffe_cm<X>_values" is a precursor | 6840 | %any param field that is "tx_ffe_cm<X>_values" is a precursor | ||
7025 | %any param field that is "tx_ffe_cp<X>_values" is a postcursor | 6841 | %any param field that is "tx_ffe_cp<X>_values" is a postcursor | ||
7026 | %where <X> is any integer | 6842 | %where <X> is any integer | ||
7027 | param_fields=fieldnames(param); | 6843 | param_fields=fieldnames(param); | ||
7028 | num_pre=length(find(~cellfun('isempty',regexp(param_fields,'tx_ffe_cm\d+_values')))); | 6844 | num_pre=length(find(~cellfun('isempty',regexp(param_fields,'tx_ffe_cm\d+_values')))); | ||
7029 | num_post=length(find(~cellfun('isempty',regexp(param_fields,'tx_ffe_cp\d+_values')))); | 6845 | num_post=length(find(~cellfun('isempty',regexp(param_fields,'tx_ffe_cp\d+_values')))); | ||
7030 | num_taps=num_pre+num_post; | 6846 | num_taps=num_pre+num_post; | ||
7031 | cur=num_pre+1; | 6847 | cur=num_pre+1; | ||
7032 | %txffe_cell combines all the txffe values into a single cell array | 6848 | %txffe_cell combines all the txffe values into a single cell array | ||
7033 | %It is ordered: [precursorN precursorN-1 ... precursor1 postcursor1 ... postcursorN-1 postcursorN] | 6849 | %It is ordered: [precursorN precursorN-1 ... precursor1 postcursor1 ... postcursorN-1 postcursorN] | ||
7034 | txffe_cell=cell(1,num_taps); | 6850 | txffe_cell=cell(1,num_taps); | ||
7035 | for k=num_pre:-1:1 | 6851 | for k=num_pre:-1:1 | ||
7036 | idx=num_pre-k+1; | 6852 | idx=num_pre-k+1; | ||
7037 | this_tx_field=sprintf('tx_ffe_cm%d_values',k); | 6853 | this_tx_field=sprintf('tx_ffe_cm%d_values',k); | ||
7038 | txffe_cell{idx}=param.(this_tx_field); | 6854 | txffe_cell{idx}=param.(this_tx_field); | ||
7039 | end | 6855 | end | ||
7040 | for k=1:num_post | 6856 | for k=1:num_post | ||
7041 | idx=k+num_pre; | 6857 | idx=k+num_pre; | ||
7042 | this_tx_field=sprintf('tx_ffe_cp%d_values',k); | 6858 | this_tx_field=sprintf('tx_ffe_cp%d_values',k); | ||
7043 | txffe_cell{idx}=param.(this_tx_field); | 6859 | txffe_cell{idx}=param.(this_tx_field); | ||
7044 | end | 6860 | end | ||
7045 | %total number of txffe runs is the product of the lengths of each tap | 6861 | %total number of txffe runs is the product of the lengths of each tap | ||
7046 | txffe_lengths=cellfun('length',txffe_cell); | 6862 | txffe_lengths=cellfun('length',txffe_cell); | ||
7047 | if isempty(txffe_cell) | 6863 | if isempty(txffe_cell) | ||
7048 | num_txffe_runs=1; | 6864 | num_txffe_runs=1; | ||
7049 | else | 6865 | else | ||
7050 | num_txffe_runs=prod(txffe_lengths); | 6866 | num_txffe_runs=prod(txffe_lengths); | ||
7051 | end | 6867 | end | ||
7052 | %txffe_sweep_indices are used in the LOCAL_SEARCH block | 6868 | %txffe_sweep_indices are used in the LOCAL_SEARCH block | ||
7053 | %any tap with length=1 can be ignored | 6869 | %any tap with length=1 can be ignored | ||
7054 | %Also is statistically likely that taps with greater number of values | 6870 | %Also is statistically likely that taps with greater number of values | ||
7055 | %will exceed the LOCAL SEARCH criteria, so searching those first is faster | 6871 | %will exceed the LOCAL SEARCH criteria, so searching those first is faster | ||
7056 | txffe_sweep_indices=find(txffe_lengths>1); | 6872 | txffe_sweep_indices=find(txffe_lengths>1); | ||
7057 | [~,length_sort]=sort(txffe_lengths(txffe_sweep_indices),'descend'); | 6873 | [~,length_sort]=sort(txffe_lengths(txffe_sweep_indices),'descend'); | ||
7058 | txffe_sweep_indices=txffe_sweep_indices(length_sort); | 6874 | txffe_sweep_indices=txffe_sweep_indices(length_sort); | ||
7059 | num_txffe_sweep_indices=length(txffe_sweep_indices); | 6875 | num_txffe_sweep_indices=length(txffe_sweep_indices); | ||
7060 | 6876 | ||||
7061 | gdc_values = param.ctle_gdc_values; | 6877 | gdc_values = param.ctle_gdc_values; | ||
7062 | Gffe_values = param.cursor_gain; | 6878 | Gffe_values = param.cursor_gain; | ||
7063 | switch param.CTLE_type | 6879 | switch param.CTLE_type | ||
7064 | case 'CL93' | 6880 | case 'CL93' | ||
7065 | case 'CL120d' | 6881 | case 'CL120d' | ||
7066 | g_DC_HP_values =param.g_DC_HP_values; | 6882 | g_DC_HP_values =param.g_DC_HP_values; | ||
7067 | case 'CL120e' | 6883 | case 'CL120e' | ||
7068 | f_HP_Z=param.f_HP_Z; | 6884 | f_HP_Z=param.f_HP_Z; | ||
7069 | f_HP_P=param.f_HP_P; | 6885 | f_HP_P=param.f_HP_P; | ||
7070 |
| 6886 |
| ||
7071 | end | 6887 | end | ||
7072 | best_ctle = []; | 6888 | best_ctle = []; | ||
7073 | best_FOM = -inf; | 6889 | best_FOM = -inf; | ||
7074 | best_txffe = []; | 6890 | best_txffe = []; | ||
7075 | delta_sbr = []; | 6891 | delta_sbr = []; | ||
7076 | PSD_results=[]; | 6892 | PSD_results=[]; | ||
7077 | MMSE_results=[]; | 6893 | MMSE_results=[]; | ||
7078 | best_bmax=param.bmax; | 6894 | best_bmax=param.bmax; | ||
7079 | %AJG021820 | 6895 | %AJG021820 | ||
7080 | best_bmin=param.bmin; | 6896 | best_bmin=param.bmin; | ||
7081 | h_J=[]; | 6897 | h_J=[]; | ||
7082 | pxi=0; | 6898 | pxi=0; | ||
7083 | if OP.DISPLAY_WINDOW | 6899 | if OP.DISPLAY_WINDOW | ||
7084 | hwaitbar=waitbar(0); | 6900 | hwaitbar=waitbar(0); | ||
7085 | else | 6901 | else | ||
7086 | fprintf('FOM search '); | 6902 | fprintf('FOM search '); | ||
7087 | end | 6903 | end | ||
7088 | FOM=0; | 6904 | FOM=0; | ||
7089 | if ~OP.RxFFE | 6905 | if ~OP.RxFFE | ||
7090 | Gffe_values=0; | 6906 | Gffe_values=0; | ||
7091 | end | 6907 | end | ||
7092 | param.ndfe_passed=param.ndfe; | 6908 | param.ndfe_passed=param.ndfe; | ||
7093 | old_loops=0; | 6909 | old_loops=0; | ||
7094 | new_loops=0; | 6910 | new_loops=0; | ||
7095 | 6911 | ||||
7096 | %GDC Qual construction | 6912 | %GDC Qual construction | ||
7097 | gqual= param.gqual; | 6913 | gqual= param.gqual; | ||
7098 | g2qual=param.g2qual; | 6914 | g2qual=param.g2qual; | ||
7099 | if ~strcmp(param.CTLE_type,'CL120d') | 6915 | if ~strcmp(param.CTLE_type,'CL120d') | ||
7100 | qual=ones(1,length(gdc_values)); | 6916 | qual=ones(1,length(gdc_values)); | ||
7101 | else | 6917 | else | ||
7102 | if isempty(gqual) && isempty(g2qual) | 6918 | if isempty(gqual) && isempty(g2qual) | ||
7103 | qual=ones(length(g_DC_HP_values),length(gdc_values)); | 6919 | qual=ones(length(g_DC_HP_values),length(gdc_values)); | ||
7104 | else | 6920 | else | ||
7105 | qual=zeros(length(g_DC_HP_values),length(gdc_values)); | 6921 | qual=zeros(length(g_DC_HP_values),length(gdc_values)); | ||
7106 |
| 6922 |
| ||
7107 | %prepare gqual and g2qual | 6923 | %prepare gqual and g2qual | ||
7108 | [g2qual,si]=sort(g2qual,'descend'); | 6924 | [g2qual,si]=sort(g2qual,'descend'); | ||
7109 | gqual=gqual(si,:); | 6925 | gqual=gqual(si,:); | ||
7110 | tmp=g2qual; | 6926 | tmp=g2qual; | ||
7111 | g2qual=zeros(length(tmp),2); | 6927 | g2qual=zeros(length(tmp),2); | ||
7112 | for kk=1:length(tmp) | 6928 | for kk=1:length(tmp) | ||
7113 | if kk==1 | 6929 | if kk==1 | ||
7114 | g2qual(kk,:)=[tmp(kk)+eps tmp(kk)]; | 6930 | g2qual(kk,:)=[tmp(kk)+eps tmp(kk)]; | ||
7115 | else | 6931 | else | ||
7116 | g2qual(kk,:)=[tmp(kk-1) tmp(kk)]; | 6932 | g2qual(kk,:)=[tmp(kk-1) tmp(kk)]; | ||
7117 | end | 6933 | end | ||
7118 | gqual(kk,:)=sort(gqual(kk,:),'descend'); | 6934 | gqual(kk,:)=sort(gqual(kk,:),'descend'); | ||
7119 | end | 6935 | end | ||
7120 |
| 6936 |
| ||
7121 | %Qual Construction | 6937 | %Qual Construction | ||
7122 | for jj=1:length(g_DC_HP_values) | 6938 | for jj=1:length(g_DC_HP_values) | ||
7123 | for ii=1:length(gdc_values) | 6939 | for ii=1:length(gdc_values) | ||
7124 | for kk=1:size(gqual,1) | 6940 | for kk=1:size(gqual,1) | ||
7125 | if g_DC_HP_values(jj) >= g2qual(kk,2) && g_DC_HP_values(jj) < g2qual(kk,1) | 6941 | if g_DC_HP_values(jj) >= g2qual(kk,2) && g_DC_HP_values(jj) < g2qual(kk,1) | ||
7126 | if gdc_values(ii) >= gqual(kk,2) && gdc_values(ii) < gqual(kk,1) | 6942 | if gdc_values(ii) >= gqual(kk,2) && gdc_values(ii) < gqual(kk,1) | ||
7127 | qual(jj,ii)=1; | 6943 | qual(jj,ii)=1; | ||
7128 | break; | 6944 | break; | ||
7129 | end | 6945 | end | ||
7130 | end | 6946 | end | ||
7131 | end | 6947 | end | ||
7132 | end | 6948 | end | ||
7133 | end | 6949 | end | ||
7134 | end | 6950 | end | ||
7135 | end | 6951 | end | ||
7136 | 6952 | ||||
7137 | progress_interval=0.025; | 6953 | progress_interval=0.025; | ||
7138 | if do_C2M | 6954 | if do_C2M | ||
7139 | loop_count=[1 2]; | 6955 | loop_count=[1 2]; | ||
7140 | T_O=floor((param.T_O/1000)*param.samples_per_ui); | 6956 | T_O=floor((param.T_O/1000)*param.samples_per_ui); | ||
7141 | T_O=max(0,T_O); | 6957 | T_O=max(0,T_O); | ||
7142 | else | 6958 | else | ||
7143 | loop_count=1; | 6959 | loop_count=1; | ||
7144 | T_O=0; | 6960 | T_O=0; | ||
7145 | end | 6961 | end | ||
7146 | switch param.CTLE_type | 6962 | switch param.CTLE_type | ||
7147 | case 'CL93' | 6963 | case 'CL93' | ||
7148 | lf_indx=1; | 6964 | lf_indx=1; | ||
7149 | case 'CL120d' | 6965 | case 'CL120d' | ||
7150 | lf_indx=length(g_DC_HP_values); | 6966 | lf_indx=length(g_DC_HP_values); | ||
7151 | case 'CL120e' | 6967 | case 'CL120e' | ||
7152 | lf_indx=1; | 6968 | lf_indx=1; | ||
7153 | end | 6969 | end | ||
7154 | runs=length(gdc_values)*lf_indx*length(Gffe_values)*num_txffe_runs; | 6970 | runs=length(gdc_values)*lf_indx*length(Gffe_values)*num_txffe_runs; | ||
7155 | if OP.Optimize_loop_speed_up == 1 | 6971 | if OP.Optimize_loop_speed_up == 1 | ||
7156 | OP.BinSize = 1e-4; | 6972 | OP.BinSize = 1e-4; | ||
7157 | OP.impulse_response_truncation_threshold = 1e-3; | 6973 | OP.impulse_response_truncation_threshold = 1e-3; | ||
7158 | end | 6974 | end | ||
7159 | 6975 | ||||
7160 | %Used to speed up FFE by only performing circshift when necessary | 6976 | %Used to speed up FFE by only performing circshift when necessary | ||
≠ | 7161 | pulse_struc(1).pulse_ctle_circshift=[]; | ≠ | 6977 | pulse_ctle_circshift=[]; |
7162 | ctle_response_updated=1; | 6978 | ctle_response_updated=1; | ||
7163 | 6979 | ||||
7164 | %Used to speed up get_xtlk_noise by pre-calculating all the phase shift exponentials | 6980 | %Used to speed up get_xtlk_noise by pre-calculating all the phase shift exponentials | ||
7165 | calc_exp_phase=0; | 6981 | calc_exp_phase=0; | ||
7166 | 6982 | ||||
7167 | %calculate cur index and pre/post indices outside of the loop | 6983 | %calculate cur index and pre/post indices outside of the loop | ||
7168 | cur_start=cur; | 6984 | cur_start=cur; | ||
7169 | precursor_indices=[]; | 6985 | precursor_indices=[]; | ||
7170 | postcursor_indices=[]; | 6986 | postcursor_indices=[]; | ||
7171 | auto_count_trigger=0; | 6987 | auto_count_trigger=0; | ||
7172 | for kv=1:num_taps | 6988 | for kv=1:num_taps | ||
7173 | if ~auto_count_trigger && length(txffe_cell{kv})==1 && txffe_cell{kv}==0 | 6989 | if ~auto_count_trigger && length(txffe_cell{kv})==1 && txffe_cell{kv}==0 | ||
7174 | %precursor values fill the beginning of the vector. Any empty precursor means | 6990 | %precursor values fill the beginning of the vector. Any empty precursor means | ||
7175 | %cursor position must be subtracted by 1 | 6991 | %cursor position must be subtracted by 1 | ||
7176 | if kv<cur_start | 6992 | if kv<cur_start | ||
7177 | cur=cur-1; | 6993 | cur=cur-1; | ||
7178 | end | 6994 | end | ||
7179 | else | 6995 | else | ||
7180 | %non empty value: add to precursor or postcursor indices depending on position | 6996 | %non empty value: add to precursor or postcursor indices depending on position | ||
7181 | %in the vector | 6997 | %in the vector | ||
7182 | if kv<cur_start | 6998 | if kv<cur_start | ||
7183 | auto_count_trigger=1; | 6999 | auto_count_trigger=1; | ||
7184 | precursor_indices=[precursor_indices kv]; | 7000 | precursor_indices=[precursor_indices kv]; | ||
7185 | else | 7001 | else | ||
7186 | auto_count_trigger=0; | 7002 | auto_count_trigger=0; | ||
7187 | postcursor_indices=[postcursor_indices kv]; | 7003 | postcursor_indices=[postcursor_indices kv]; | ||
7188 | end | 7004 | end | ||
7189 | end | 7005 | end | ||
7190 | end | 7006 | end | ||
7191 | if ~isempty(postcursor_indices) | 7007 | if ~isempty(postcursor_indices) | ||
7192 | postcursor_indices=postcursor_indices(1):postcursor_indices(end); | 7008 | postcursor_indices=postcursor_indices(1):postcursor_indices(end); | ||
7193 | end | 7009 | end | ||
7194 | 7010 | ||||
7195 | %Calculate the full grid matrix of all txffe combinations | 7011 | %Calculate the full grid matrix of all txffe combinations | ||
7196 | if isempty(txffe_cell) | 7012 | if isempty(txffe_cell) | ||
7197 | TXFFE_grid=0; | 7013 | TXFFE_grid=0; | ||
7198 | FULL_tx_index_vector=1; | 7014 | FULL_tx_index_vector=1; | ||
7199 | else | 7015 | else | ||
7200 | TXFFE_grid=Full_Grid_Matrix(txffe_cell); | 7016 | TXFFE_grid=Full_Grid_Matrix(txffe_cell); | ||
7201 | %Also calculate the full grid matrix for the index used in each txffe combination | 7017 | %Also calculate the full grid matrix for the index used in each txffe combination | ||
7202 | %(the index is used in the LOCAL SEARCH block) | 7018 | %(the index is used in the LOCAL SEARCH block) | ||
7203 | for k=1:num_taps | 7019 | for k=1:num_taps | ||
7204 | txffe_index_cell{k}=1:txffe_lengths(k); | 7020 | txffe_index_cell{k}=1:txffe_lengths(k); | ||
7205 | end | 7021 | end | ||
7206 | FULL_tx_index_vector=Full_Grid_Matrix(txffe_index_cell); | 7022 | FULL_tx_index_vector=Full_Grid_Matrix(txffe_index_cell); | ||
7207 | end | 7023 | end | ||
7208 | 7024 | ||||
7209 | %pre-calculate cursor to save time | 7025 | %pre-calculate cursor to save time | ||
7210 | txffe_cursor_vector=1-sum(abs(TXFFE_grid),2); | 7026 | txffe_cursor_vector=1-sum(abs(TXFFE_grid),2); | ||
7211 | 7027 | ||||
7212 | %pre-calculate full txffe for each iteration to save time | 7028 | %pre-calculate full txffe for each iteration to save time | ||
7213 | precursor_matrix=TXFFE_grid(:,precursor_indices); | 7029 | precursor_matrix=TXFFE_grid(:,precursor_indices); | ||
7214 | postcursor_matrix=TXFFE_grid(:,postcursor_indices); | 7030 | postcursor_matrix=TXFFE_grid(:,postcursor_indices); | ||
7215 | txffe_matrix = [precursor_matrix txffe_cursor_vector postcursor_matrix]; | 7031 | txffe_matrix = [precursor_matrix txffe_cursor_vector postcursor_matrix]; | ||
7216 | 7032 | ||||
7217 | if OP.TDMODE | 7033 | if OP.TDMODE | ||
7218 | uneq_field='uneq_pulse_response'; | 7034 | uneq_field='uneq_pulse_response'; | ||
7219 | ctle_field='ctle_pulse_response'; | 7035 | ctle_field='ctle_pulse_response'; | ||
7220 | else | 7036 | else | ||
7221 | uneq_field='uneq_imp_response'; | 7037 | uneq_field='uneq_imp_response'; | ||
7222 | ctle_field='ctle_imp_response'; | 7038 | ctle_field='ctle_imp_response'; | ||
7223 | end | 7039 | end | ||
7224 | 7040 | ||||
7225 | %Speed up search for max(sbr) | 7041 | %Speed up search for max(sbr) | ||
7226 | if OP.TDMODE | 7042 | if OP.TDMODE | ||
7227 | [~,init_max]=max(chdata(1).uneq_pulse_response); | 7043 | [~,init_max]=max(chdata(1).uneq_pulse_response); | ||
7228 | else | 7044 | else | ||
7229 | [~,init_max]=max(filter(ones(1,param.samples_per_ui),1,chdata(1).uneq_imp_response)); | 7045 | [~,init_max]=max(filter(ones(1,param.samples_per_ui),1,chdata(1).uneq_imp_response)); | ||
7230 | end | 7046 | end | ||
7231 | UI_max_window=20; | 7047 | UI_max_window=20; | ||
7232 | start_max_idx=init_max-UI_max_window*param.samples_per_ui; | 7048 | start_max_idx=init_max-UI_max_window*param.samples_per_ui; | ||
7233 | if start_max_idx<1 | 7049 | if start_max_idx<1 | ||
7234 | start_max_idx=1; | 7050 | start_max_idx=1; | ||
7235 | end | 7051 | end | ||
7236 | end_max_idx=init_max+UI_max_window*param.samples_per_ui; | 7052 | end_max_idx=init_max+UI_max_window*param.samples_per_ui; | ||
7237 | if end_max_idx>length(chdata(1).(uneq_field)) | 7053 | if end_max_idx>length(chdata(1).(uneq_field)) | ||
7238 | end_max_idx=length(chdata(1).(uneq_field)); | 7054 | end_max_idx=length(chdata(1).(uneq_field)); | ||
7239 | end | 7055 | end | ||
7240 | 7056 | ||||
7241 | itick_skips=0; | 7057 | itick_skips=0; | ||
7242 | itick_cases=0; | 7058 | itick_cases=0; | ||
7243 | FOM_TRACKER(1:length(Gffe_values),1:length(gdc_values),1:lf_indx,1:size(TXFFE_grid,1),1:length(full_sample_range))=0; | 7059 | FOM_TRACKER(1:length(Gffe_values),1:length(gdc_values),1:lf_indx,1:size(TXFFE_grid,1),1:length(full_sample_range))=0; | ||
7244 | for i=loop_count | 7060 | for i=loop_count | ||
7245 |
| 7061 |
| ||
7246 | for Gffe_index=1:length(Gffe_values) | 7062 | for Gffe_index=1:length(Gffe_values) | ||
7247 | param.current_ffegain=Gffe_values(Gffe_index); | 7063 | param.current_ffegain=Gffe_values(Gffe_index); | ||
7248 | for ctle_index=1:length(gdc_values) | 7064 | for ctle_index=1:length(gdc_values) | ||
7249 | g_dc = gdc_values(ctle_index); | 7065 | g_dc = gdc_values(ctle_index); | ||
7250 | kacdc = 10^(g_dc/20); | 7066 | kacdc = 10^(g_dc/20); | ||
7251 | CTLE_fp1 = param.CTLE_fp1(ctle_index); | 7067 | CTLE_fp1 = param.CTLE_fp1(ctle_index); | ||
7252 | CTLE_fp2 = param.CTLE_fp2(ctle_index); | 7068 | CTLE_fp2 = param.CTLE_fp2(ctle_index); | ||
7253 | CTLE_fz = param.CTLE_fz(ctle_index); | 7069 | CTLE_fz = param.CTLE_fz(ctle_index); | ||
7254 | switch param.CTLE_type | 7070 | switch param.CTLE_type | ||
7255 | case 'CL93' | 7071 | case 'CL93' | ||
7256 | % | 7072 | % | ||
7257 | case 'CL120d' | 7073 | case 'CL120d' | ||
7258 | % | 7074 | % | ||
7259 | case 'CL120e' | 7075 | case 'CL120e' | ||
7260 | HP_Z = param.f_HP_Z(ctle_index); | 7076 | HP_Z = param.f_HP_Z(ctle_index); | ||
7261 | HP_P = param.f_HP_P(ctle_index); | 7077 | HP_P = param.f_HP_P(ctle_index); | ||
7262 | end | 7078 | end | ||
7263 | %% HF Boost | 7079 | %% HF Boost | ||
7264 | ctle_gain = (kacdc + 1i*chdata(1).faxis/CTLE_fz) ./ ... | 7080 | ctle_gain = (kacdc + 1i*chdata(1).faxis/CTLE_fz) ./ ... | ||
7265 | ((1+1i*chdata(1).faxis/CTLE_fp1).*(1+1i*chdata(1).faxis/CTLE_fp2)); | 7081 | ((1+1i*chdata(1).faxis/CTLE_fp1).*(1+1i*chdata(1).faxis/CTLE_fp2)); | ||
7266 | %% Mid Frequency Boost | 7082 | %% Mid Frequency Boost | ||
7267 | ctle_gain_xc = (kacdc + 1i*f_xc/CTLE_fz) ./ ... | 7083 | ctle_gain_xc = (kacdc + 1i*f_xc/CTLE_fz) ./ ... | ||
7268 | ((1+1i*f_xc/CTLE_fp1).*(1+1i*f_xc/CTLE_fp2)); % Bill Kirkland | 7084 | ((1+1i*f_xc/CTLE_fp1).*(1+1i*f_xc/CTLE_fp2)); % Bill Kirkland | ||
7269 | for g_LP_index=1:lf_indx | 7085 | for g_LP_index=1:lf_indx | ||
7270 |
| 7086 |
| ||
7271 | %GDC Qual Check | 7087 | %GDC Qual Check | ||
7272 | if qual(g_LP_index,ctle_index)==0 | 7088 | if qual(g_LP_index,ctle_index)==0 | ||
7273 | pxi=pxi+num_txffe_runs; | 7089 | pxi=pxi+num_txffe_runs; | ||
7274 | continue; | 7090 | continue; | ||
7275 | end | 7091 | end | ||
7276 |
| 7092 |
| ||
7277 | switch param.CTLE_type | 7093 | switch param.CTLE_type | ||
7278 | case 'CL93' | 7094 | case 'CL93' | ||
7279 | H_low=1; | 7095 | H_low=1; | ||
7280 | kacde_DC_low=1; | 7096 | kacde_DC_low=1; | ||
7281 | case 'CL120d' | 7097 | case 'CL120d' | ||
7282 | g_DC_low = g_DC_HP_values(g_LP_index); | 7098 | g_DC_low = g_DC_HP_values(g_LP_index); | ||
7283 | f_HP=param.f_HP(g_LP_index); | 7099 | f_HP=param.f_HP(g_LP_index); | ||
7284 | kacde_DC_low = 10^(g_DC_low/20); | 7100 | kacde_DC_low = 10^(g_DC_low/20); | ||
7285 | H_low=(kacde_DC_low + 1i*chdata(1).faxis/f_HP)./(1 + 1i*chdata(1).faxis/f_HP); | 7101 | H_low=(kacde_DC_low + 1i*chdata(1).faxis/f_HP)./(1 + 1i*chdata(1).faxis/f_HP); | ||
7286 | H_low_xc = (kacde_DC_low + 1i*f_xc/f_HP)./(1 + 1i*f_xc/f_HP);% Bill Kirkland | 7102 | H_low_xc = (kacde_DC_low + 1i*f_xc/f_HP)./(1 + 1i*f_xc/f_HP);% Bill Kirkland | ||
7287 | case 'CL120e' % z1 has been adusted on read in | 7103 | case 'CL120e' % z1 has been adusted on read in | ||
7288 | H_low=(1 + 1i*chdata(1).faxis/HP_Z)./(1 + 1i*chdata(1).faxis/HP_P); | 7104 | H_low=(1 + 1i*chdata(1).faxis/HP_Z)./(1 + 1i*chdata(1).faxis/HP_P); | ||
7289 | H_low_xc=(1 + 1i*f_xc/HP_Z)./(1 + 1i*f_xc/HP_P); % Bill Kirkland | 7105 | H_low_xc=(1 + 1i*f_xc/HP_Z)./(1 + 1i*f_xc/HP_P); % Bill Kirkland | ||
7290 | end | 7106 | end | ||
7291 | H_ctf=H_low.*ctle_gain; | 7107 | H_ctf=H_low.*ctle_gain; | ||
7292 | switch upper(OP.FFE_OPT_METHOD) | 7108 | switch upper(OP.FFE_OPT_METHOD) | ||
7293 | case 'WIENER-HOPF' | 7109 | case 'WIENER-HOPF' | ||
7294 | %% Bill Kirkland | 7110 | %% Bill Kirkland | ||
7295 | H_ctf_xc = H_low_xc.*ctle_gain_xc; | 7111 | H_ctf_xc = H_low_xc.*ctle_gain_xc; | ||
7296 | H_rx_ctle_xc = H_r_xc.*H_ctf_xc; | 7112 | H_rx_ctle_xc = H_r_xc.*H_ctf_xc; | ||
7297 | % use Fourier Transform pair for correlation as we have to | 7113 | % use Fourier Transform pair for correlation as we have to | ||
7298 | % take ifft of H_r anyways. | 7114 | % take ifft of H_r anyways. | ||
7299 | % onesided and two sided responses - tricky, tricky, tricky | 7115 | % onesided and two sided responses - tricky, tricky, tricky | ||
7300 | Var_eta0 = param.eta_0*f_xc(end)/1e9; | 7116 | Var_eta0 = param.eta_0*f_xc(end)/1e9; | ||
7301 | XC_rx_ctle = ifft (H_rx_ctle_xc.*conj(H_rx_ctle_xc),2*length(H_rx_ctle_xc),'symmetric'); | 7117 | XC_rx_ctle = ifft (H_rx_ctle_xc.*conj(H_rx_ctle_xc),2*length(H_rx_ctle_xc),'symmetric'); | ||
7302 | Noise_XC = Var_eta0.*XC_rx_ctle(1:param.samples_per_ui:N_fft_by2); | 7118 | Noise_XC = Var_eta0.*XC_rx_ctle(1:param.samples_per_ui:N_fft_by2); | ||
7303 | 7119 | ||||
7304 | if OP.Do_White_Noise | 7120 | if OP.Do_White_Noise | ||
7305 | Noise_XC = Noise_XC(1); | 7121 | Noise_XC = Noise_XC(1); | ||
7306 | end | 7122 | end | ||
7307 | otherwise | 7123 | otherwise | ||
7308 | Noise_XC=[]; | 7124 | Noise_XC=[]; | ||
7309 | end | 7125 | end | ||
7310 | 7126 | ||||
7311 | 7127 | ||||
7312 |
| 7128 |
| ||
7313 | if OP.INCLUDE_CTLE==1 | 7129 | if OP.INCLUDE_CTLE==1 | ||
7314 | for k=1:param.num_s4p_files | 7130 | for k=1:param.num_s4p_files | ||
7315 | ir_peak = max(abs(chdata(k).(uneq_field))); | 7131 | ir_peak = max(abs(chdata(k).(uneq_field))); | ||
7316 | ir_last = find(abs(chdata(k).(uneq_field))>ir_peak*OP.impulse_response_truncation_threshold, 1, 'last'); | 7132 | ir_last = find(abs(chdata(k).(uneq_field))>ir_peak*OP.impulse_response_truncation_threshold, 1, 'last'); | ||
7317 | chdata(k).(uneq_field) = chdata(k).(uneq_field)(1:ir_last); | 7133 | chdata(k).(uneq_field) = chdata(k).(uneq_field)(1:ir_last); | ||
7318 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(uneq_field), baud_rate ... | 7134 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(uneq_field), baud_rate ... | ||
7319 | , CTLE_fz, CTLE_fp1, CTLE_fp2, g_dc, param.samples_per_ui); | 7135 | , CTLE_fz, CTLE_fp1, CTLE_fp2, g_dc, param.samples_per_ui); | ||
7320 | switch param.CTLE_type | 7136 | switch param.CTLE_type | ||
7321 | case 'CL93' | 7137 | case 'CL93' | ||
7322 | case 'CL120d' | 7138 | case 'CL120d' | ||
7323 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(ctle_field), baud_rate, f_HP, f_HP,100e100 , g_DC_low , param.samples_per_ui); | 7139 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(ctle_field), baud_rate, f_HP, f_HP,100e100 , g_DC_low , param.samples_per_ui); | ||
7324 | case 'CL120e' % z1 has been adusted on read in | 7140 | case 'CL120e' % z1 has been adusted on read in | ||
7325 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(ctle_field), baud_rate, HP_Z,HP_P,100e100 , 0 , param.samples_per_ui); | 7141 | chdata(k).(ctle_field) = TD_CTLE(chdata(k).(ctle_field), baud_rate, HP_Z,HP_P,100e100 , 0 , param.samples_per_ui); | ||
7326 | end | 7142 | end | ||
7327 | end | 7143 | end | ||
7328 | %set the flag to show ctle response was updated | 7144 | %set the flag to show ctle response was updated | ||
7329 | ctle_response_updated=1; | 7145 | ctle_response_updated=1; | ||
7330 | else | 7146 | else | ||
7331 | for k=1:param.num_s4p_files | 7147 | for k=1:param.num_s4p_files | ||
7332 | chdata(k).(ctle_field) = chdata(k).(uneq_field); | 7148 | chdata(k).(ctle_field) = chdata(k).(uneq_field); | ||
7333 | end | 7149 | end | ||
7334 | end | 7150 | end | ||
7335 | for k=1:param.num_s4p_files | 7151 | for k=1:param.num_s4p_files | ||
7336 | chdata(k).sdd21ctf=chdata(k).sdd21.*H_ctf; % sdd21 is a VTF, includes H_t, H_f, and package | 7152 | chdata(k).sdd21ctf=chdata(k).sdd21.*H_ctf; % sdd21 is a VTF, includes H_t, H_f, and package | ||
7337 | end | 7153 | end | ||
7338 | %% Equation 93A-22 %% | 7154 | %% Equation 93A-22 %% | ||
7339 | % figure(1000) | 7155 | % figure(1000) | ||
7340 | % semilogx(chdata(1).faxis/1e9,db(H_ctf)) | 7156 | % semilogx(chdata(1).faxis/1e9,db(H_ctf)) | ||
7341 | % hold on | 7157 | % hold on | ||
7342 | if OP.RX_CALIBRATION | 7158 | if OP.RX_CALIBRATION | ||
7343 | ctle_gain2 = (kacdc + 1i*chdata(2).faxis/CTLE_fz) ./ ... | 7159 | ctle_gain2 = (kacdc + 1i*chdata(2).faxis/CTLE_fz) ./ ... | ||
7344 | ((1+1i*chdata(2).faxis/CTLE_fp1).*(1+1i*chdata(2).faxis/CTLE_fp2)); | 7160 | ((1+1i*chdata(2).faxis/CTLE_fp1).*(1+1i*chdata(2).faxis/CTLE_fp2)); | ||
7345 | switch param.CTLE_type | 7161 | switch param.CTLE_type | ||
7346 | case 'CL93' | 7162 | case 'CL93' | ||
7347 | H_low2=1; | 7163 | H_low2=1; | ||
7348 | case 'CL120d' | 7164 | case 'CL120d' | ||
7349 | g_DC_low = g_DC_HP_values(g_LP_index); | 7165 | g_DC_low = g_DC_HP_values(g_LP_index); | ||
7350 | f_HP=param.f_HP(g_LP_index); | 7166 | f_HP=param.f_HP(g_LP_index); | ||
7351 | kacde_DC_low = 10^(g_DC_low/20); | 7167 | kacde_DC_low = 10^(g_DC_low/20); | ||
7352 | H_low2=(kacde_DC_low + 1i*chdata(1).faxis/f_HP)./(1 + 1i*chdata(1).faxis/f_HP); | 7168 | H_low2=(kacde_DC_low + 1i*chdata(1).faxis/f_HP)./(1 + 1i*chdata(1).faxis/f_HP); | ||
7353 | case 'CL120e' % z1 has been adusted on read in | 7169 | case 'CL120e' % z1 has been adusted on read in | ||
7354 | H_low2=(1 + 1i*chdata(1).faxis/HP_Z)./(1 + 1i*chdata(1).faxis/HP_P); | 7170 | H_low2=(1 + 1i*chdata(1).faxis/HP_Z)./(1 + 1i*chdata(1).faxis/HP_P); | ||
7355 | end | 7171 | end | ||
7356 | H_ctf2=H_low2.*ctle_gain2; | 7172 | H_ctf2=H_low2.*ctle_gain2; | ||
7357 | end | 7173 | end | ||
7358 | % RIM 11-30-2020 moved to a subfunction | 7174 | % RIM 11-30-2020 moved to a subfunction | ||
7359 | [sigma_N] = get_sigma_eta_ACCM_noise(chdata,param,H_sy,H_r,H_ctf); | 7175 | [sigma_N] = get_sigma_eta_ACCM_noise(chdata,param,H_sy,H_r,H_ctf); | ||
7360 | if OP.RX_CALIBRATION | 7176 | if OP.RX_CALIBRATION | ||
7361 | sigma_ne = get_sigma_noise( H_ctf2, param, chdata, sigma_bn); %% Equation 93A-48 %% | 7177 | sigma_ne = get_sigma_noise( H_ctf2, param, chdata, sigma_bn); %% Equation 93A-48 %% | ||
7362 | sigma_NEXT=sqrt(param.eta_0*sum( abs(H_sy(2:end).^2 .* H_r(2:end).*2 .* H_ctf(2:end).^2 ) .* diff(chdata(1).faxis)/1e9));% changed from /chdata(1).faxis(end) B. Kirkland S. Elnagar 11/6/2021 | 7178 | sigma_NEXT=sqrt(param.eta_0*sum( abs(H_sy(2:end).^2 .* H_r(2:end).*2 .* H_ctf(2:end).^2 ) .* diff(chdata(1).faxis)/1e9));% changed from /chdata(1).faxis(end) B. Kirkland S. Elnagar 11/6/2021 | ||
7363 | else | 7179 | else | ||
7364 | %% Equations 93A-33 and 93A-34 for NEXT - independent of TXFFE setting %% | 7180 | %% Equations 93A-33 and 93A-34 for NEXT - independent of TXFFE setting %% | ||
− | 7365 | % sigma_NEXT not used sigma_ne is one used in Rx calibration RIM 03-28-2024 |
| ||
≠ | 7366 | % sigma_NEXT = get_xtlk_noise( [0 1 0], 'NEXT', param, chdata ); | ≠ | 7181 | sigma_NEXT = get_xtlk_noise( [0 1 0], 'NEXT', param, chdata ); |
7367 | sigma_ne=0; | 7182 | sigma_ne=0; | ||
7368 | end | 7183 | end | ||
7369 |
| 7184 |
| ||
7370 | if param.GDC_MIN ~= 0 && gdc_values(ctle_index) + g_DC_HP_values(g_LP_index) > param.GDC_MIN | 7185 | if param.GDC_MIN ~= 0 && gdc_values(ctle_index) + g_DC_HP_values(g_LP_index) > param.GDC_MIN | ||
7371 | pxi=pxi+num_txffe_runs; | 7186 | pxi=pxi+num_txffe_runs; | ||
7372 | continue; % change per 0.3k draft 2.3 | 7187 | continue; % change per 0.3k draft 2.3 | ||
7373 | end | 7188 | end | ||
7374 | %% | 7189 | %% | ||
7375 | PSD_results=[]; | 7190 | PSD_results=[]; | ||
7376 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | 7191 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE | ||
7377 | OP.WO_TXFFE=1; | 7192 | OP.WO_TXFFE=1; | ||
7378 | PSD_results=get_PSDs(PSD_results,[],[],[],gdc_values(ctle_index),g_DC_low,param,chdata,OP); | 7193 | PSD_results=get_PSDs(PSD_results,[],[],[],gdc_values(ctle_index),g_DC_low,param,chdata,OP); | ||
7379 | end | 7194 | end | ||
7380 | %TXFFE Loop | 7195 | %TXFFE Loop | ||
7381 | %Originally this was a separate for loop for each tap, but it is now all contained in the TXFFE_grid matrix to use a single modular loop | 7196 | %Originally this was a separate for loop for each tap, but it is now all contained in the TXFFE_grid matrix to use a single modular loop | ||
7382 | for TK=1:size(TXFFE_grid,1) | 7197 | for TK=1:size(TXFFE_grid,1) | ||
7383 | 7198 | ||||
7384 | pxi=pxi+1; | 7199 | pxi=pxi+1; | ||
7385 | progress = pxi/runs; | 7200 | progress = pxi/runs; | ||
7386 | if OP.DISPLAY_WINDOW | 7201 | if OP.DISPLAY_WINDOW | ||
7387 | if ~mod(pxi,floor(runs*progress_interval)) | 7202 | if ~mod(pxi,floor(runs*progress_interval)) | ||
7388 | waitbar(progress, hwaitbar, 'Linear equalization tuning'); figure(hwaitbar); drawnow; | 7203 | waitbar(progress, hwaitbar, 'Linear equalization tuning'); figure(hwaitbar); drawnow; | ||
7389 | end | 7204 | end | ||
7390 | else | 7205 | else | ||
7391 | if ~mod(pxi,floor(runs*progress_interval)), fprintf('%i%% ', round(progress*100) );end | 7206 | if ~mod(pxi,floor(runs*progress_interval)), fprintf('%i%% ', round(progress*100) );end | ||
7392 | end | 7207 | end | ||
7393 |
| 7208 |
| ||
7394 | %get the cursor for this iteration | 7209 | %get the cursor for this iteration | ||
7395 | txffe_cur=txffe_cursor_vector(TK); | 7210 | txffe_cur=txffe_cursor_vector(TK); | ||
7396 |
| 7211 |
| ||
7397 | % Skip combinations with small values of c(0), not guaranteed to be supported by all transmitters. | 7212 | % Skip combinations with small values of c(0), not guaranteed to be supported by all transmitters. | ||
7398 | if txffe_cur<param.tx_ffe_c0_min | 7213 | if txffe_cur<param.tx_ffe_c0_min | ||
7399 | continue; | 7214 | continue; | ||
7400 | end | 7215 | end | ||
7401 | old_loops=old_loops+1; | 7216 | old_loops=old_loops+1; | ||
7402 |
| 7217 |
| ||
7403 | %get the index used for each tap on this iteration | 7218 | %get the index used for each tap on this iteration | ||
7404 | %this is needed for the LOCAL SEARCH block | 7219 | %this is needed for the LOCAL SEARCH block | ||
7405 | tx_index_vector=FULL_tx_index_vector(TK,:); | 7220 | tx_index_vector=FULL_tx_index_vector(TK,:); | ||
7406 |
| 7221 |
| ||
7407 | %Original LOCAL SEARCH Block: | 7222 | %Original LOCAL SEARCH Block: | ||
7408 | %Keeping this one as commented code because it is a bit more readable than the Modular Block below | 7223 | %Keeping this one as commented code because it is a bit more readable than the Modular Block below | ||
7409 | %But unlike the Modular Block, this one does not work if additional TXFFE taps are added | 7224 | %But unlike the Modular Block, this one does not work if additional TXFFE taps are added | ||
7410 | % % speedup "local search" heuristic - Adee Ran 03-17-2020 | 7225 | % % speedup "local search" heuristic - Adee Ran 03-17-2020 | ||
7411 | % % skip configurations more than | 7226 | % % skip configurations more than | ||
7412 | % % 2 steps away from current "best" point on any grid direction | 7227 | % % 2 steps away from current "best" point on any grid direction | ||
7413 | % % Matt Brown 11/19/2021 for cp2 and cp3 | 7228 | % % Matt Brown 11/19/2021 for cp2 and cp3 | ||
7414 | % if param.LOCAL_SEARCH>0 && ~isinf(best_FOM) && ... | 7229 | % if param.LOCAL_SEARCH>0 && ~isinf(best_FOM) && ... | ||
7415 | % ((k_cp2>1 && length(cp3_values)>1 && abs(k_cp3-find(cp3_values==best_txffe(cur+3)))>param.LOCAL_SEARCH) ... | 7230 | % ((k_cp2>1 && length(cp3_values)>1 && abs(k_cp3-find(cp3_values==best_txffe(cur+3)))>param.LOCAL_SEARCH) ... | ||
7416 | % || (k_cp1>1 && length(cp2_values)>1 && abs(k_cp2-find(cp2_values==best_txffe(cur+2)))>param.LOCAL_SEARCH) ... | 7231 | % || (k_cp1>1 && length(cp2_values)>1 && abs(k_cp2-find(cp2_values==best_txffe(cur+2)))>param.LOCAL_SEARCH) ... | ||
7417 | % || (k_cm1>1 && length(cp1_values)>1 && abs(k_cp1-find(cp1_values==best_txffe(cur+1)))>param.LOCAL_SEARCH) ... | 7232 | % || (k_cm1>1 && length(cp1_values)>1 && abs(k_cp1-find(cp1_values==best_txffe(cur+1)))>param.LOCAL_SEARCH) ... | ||
7418 | % || (k_cm2>1 && length(cm1_values)>1 && abs(k_cm1-find(cm1_values==best_txffe(cur-1)))>param.LOCAL_SEARCH) ... | 7233 | % || (k_cm2>1 && length(cm1_values)>1 && abs(k_cm1-find(cm1_values==best_txffe(cur-1)))>param.LOCAL_SEARCH) ... | ||
7419 | % || (k_cm3>1 && length(cm2_values)>1 && abs(k_cm2-find(cm2_values==best_txffe(cur-2)))>param.LOCAL_SEARCH) ... | 7234 | % || (k_cm3>1 && length(cm2_values)>1 && abs(k_cm2-find(cm2_values==best_txffe(cur-2)))>param.LOCAL_SEARCH) ... | ||
7420 | % || (k_cm4>1 && length(cm3_values)>1 && abs(k_cm3-find(cm3_values==best_txffe(cur-3)))>param.LOCAL_SEARCH) ... | 7235 | % || (k_cm4>1 && length(cm3_values)>1 && abs(k_cm3-find(cm3_values==best_txffe(cur-3)))>param.LOCAL_SEARCH) ... | ||
7421 | % || (g_LP_index>1 && length(cm4_values)>1 && abs(k_cm4-find(cm4_values==best_txffe(cur-4)))>param.LOCAL_SEARCH) ... | 7236 | % || (g_LP_index>1 && length(cm4_values)>1 && abs(k_cm4-find(cm4_values==best_txffe(cur-4)))>param.LOCAL_SEARCH) ... | ||
7422 | % || (ctle_index>1 && abs(g_LP_index-best_G_high_pass)>param.LOCAL_SEARCH)) | 7237 | % || (ctle_index>1 && abs(g_LP_index-best_G_high_pass)>param.LOCAL_SEARCH)) | ||
7423 | % | 7238 | % | ||
7424 | % continue; | 7239 | % continue; | ||
7425 | % end | 7240 | % end | ||
7426 | 7241 | ||||
7427 | %Modular LOCAL_SEARCH block: | 7242 | %Modular LOCAL_SEARCH block: | ||
7428 | % speedup "local search" heuristic - Adee Ran 03-17-2020 | 7243 | % speedup "local search" heuristic - Adee Ran 03-17-2020 | ||
7429 | % skip configurations more than 2 steps away from current "best" point on any grid direction | 7244 | % skip configurations more than 2 steps away from current "best" point on any grid direction | ||
7430 | skip_it=0; | 7245 | skip_it=0; | ||
7431 | if param.LOCAL_SEARCH>0 && ~isinf(best_FOM) | 7246 | if param.LOCAL_SEARCH>0 && ~isinf(best_FOM) | ||
7432 | %instead of looping across all taps, only loop across | 7247 | %instead of looping across all taps, only loop across | ||
7433 | %those with length>1 (txffe_sweep_indices). | 7248 | %those with length>1 (txffe_sweep_indices). | ||
7434 | %It saves time since this block is encountered so often | 7249 | %It saves time since this block is encountered so often | ||
7435 | for kj=1:num_txffe_sweep_indices | 7250 | for kj=1:num_txffe_sweep_indices | ||
7436 | kv=txffe_sweep_indices(kj); | 7251 | kv=txffe_sweep_indices(kj); | ||
7437 | if kv==1 | 7252 | if kv==1 | ||
7438 | previous_loop_val=g_LP_index; | 7253 | previous_loop_val=g_LP_index; | ||
7439 | else | 7254 | else | ||
7440 | previous_loop_val=tx_index_vector(kv-1); | 7255 | previous_loop_val=tx_index_vector(kv-1); | ||
7441 | end | 7256 | end | ||
7442 | if previous_loop_val>1 | 7257 | if previous_loop_val>1 | ||
7443 | best_index_this_tap=best_txffe_index(kv); | 7258 | best_index_this_tap=best_txffe_index(kv); | ||
7444 | if abs(tx_index_vector(kv)-best_index_this_tap)>param.LOCAL_SEARCH | 7259 | if abs(tx_index_vector(kv)-best_index_this_tap)>param.LOCAL_SEARCH | ||
7445 | skip_it=1; | 7260 | skip_it=1; | ||
7446 | break; | 7261 | break; | ||
7447 | end | 7262 | end | ||
7448 | end | 7263 | end | ||
7449 | end | 7264 | end | ||
7450 |
| 7265 |
| ||
7451 | if ~skip_it && ctle_index>1 && abs(g_LP_index-best_G_high_pass)>param.LOCAL_SEARCH | 7266 | if ~skip_it && ctle_index>1 && abs(g_LP_index-best_G_high_pass)>param.LOCAL_SEARCH | ||
7452 | skip_it=1; | 7267 | skip_it=1; | ||
7453 | end | 7268 | end | ||
7454 | end | 7269 | end | ||
7455 | if skip_it | 7270 | if skip_it | ||
7456 | continue; | 7271 | continue; | ||
7457 | end | 7272 | end | ||
7458 | %End Modular LOCAL SEARCH block | 7273 | %End Modular LOCAL SEARCH block | ||
7459 |
| 7274 |
| ||
7460 | new_loops=new_loops+1; | 7275 | new_loops=new_loops+1; | ||
7461 |
| 7276 |
| ||
7462 | %fetch txffe for this iteration | 7277 | %fetch txffe for this iteration | ||
7463 | txffe=txffe_matrix(TK,:); | 7278 | txffe=txffe_matrix(TK,:); | ||
7464 |
| 7279 |
| ||
7465 | %The phase shift exponentials used in get_xtlk_noise are independent of | 7280 | %The phase shift exponentials used in get_xtlk_noise are independent of | ||
7466 | %everything except number of taps and cursor position | 7281 | %everything except number of taps and cursor position | ||
7467 | %So it can be calculated 1 time here to avoid thousands of re-calcs | 7282 | %So it can be calculated 1 time here to avoid thousands of re-calcs | ||
7468 | if ~calc_exp_phase | 7283 | if ~calc_exp_phase | ||
7469 | calc_exp_phase=1; | 7284 | calc_exp_phase=1; | ||
7470 | for k=1:length(txffe) | 7285 | for k=1:length(txffe) | ||
7471 | phase_memory(:,k)=exp(-1j*2*pi*(k-cur).*f/param.fb); | 7286 | phase_memory(:,k)=exp(-1j*2*pi*(k-cur).*f/param.fb); | ||
7472 | end | 7287 | end | ||
7473 | if OP.RxFFE | 7288 | if OP.RxFFE | ||
7474 | for k=-1*param.RxFFE_cmx:param.RxFFE_cpx | 7289 | for k=-1*param.RxFFE_cmx:param.RxFFE_cpx | ||
7475 | phase_memoryRXFFE(:,k+param.RxFFE_cmx+1)=exp(-1j*2*pi*(k+1).*f/param.fb); | 7290 | phase_memoryRXFFE(:,k+param.RxFFE_cmx+1)=exp(-1j*2*pi*(k+1).*f/param.fb); | ||
7476 | end | 7291 | end | ||
7477 | phase_memory=[phase_memory phase_memoryRXFFE]; | 7292 | phase_memory=[phase_memory phase_memoryRXFFE]; | ||
7478 | end | 7293 | end | ||
7479 | end | 7294 | end | ||
7480 |
| 7295 |
| ||
7481 | %% Unequalized Pulse Reponse & circshift for FFE | 7296 | %% Unequalized Pulse Reponse & circshift for FFE | ||
7482 | %Perform circshift for FFE only when CTLE is updated. The FFE_Fast function takes | 7297 | %Perform circshift for FFE only when CTLE is updated. The FFE_Fast function takes | ||
≠ | 7483 | %in the pre-shifted matrix. FFE fast is scaled sum of rows of pulse_struc(ii).pulse_ctle_circshift | ≠ | 7298 | %in the pre-shifted matrix |
7484 | if ctle_response_updated | 7299 | if ctle_response_updated | ||
7485 | ctle_response_updated=0; | 7300 | ctle_response_updated=0; | ||
7486 | num_pre=cur-1; | 7301 | num_pre=cur-1; | ||
7487 | %Another speed up: the unequalized pulse is also only unique for each CTLE update | 7302 | %Another speed up: the unequalized pulse is also only unique for each CTLE update | ||
7488 | %Calculating here reduces number of convolutions by thousands | 7303 | %Calculating here reduces number of convolutions by thousands | ||
− | 7489 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) |
| ||
7490 | ich=1; | ||||
7491 | else | ||||
7492 | ich=param.num_s4p_files; | ||||
7493 | end | ||||
7494 | for ii=1:ich | ||||
≠ | 7495 | if OP.TDMODE | ≠ | 7304 | if OP.TDMODE |
≠ | 7496 | pulse_struc(ii).pulse_ctle=chdata(ii).(ctle_field)(:); | ≠ | 7305 | pulse_ctle=chdata(1).(ctle_field)(:); |
≠ | 7497 | else | ≠ | 7306 | else |
≠ | 7498 | %uneq_pulse=filter(ones(param.samples_per_ui, 1), 1, chdata(1).(ctle_field)(:)); | ≠ | 7307 | %uneq_pulse=filter(ones(param.samples_per_ui, 1), 1, chdata(1).(ctle_field)(:)); |
≠ | 7499 | %"conv2" is faster than filter. Just need to chop off extra points at the end | ≠ | 7308 | %"conv2" is faster than filter. Just need to chop off extra points at the end |
≠ | 7500 | pulse_struc(ii).pulse_ctle=conv2(chdata(ii).(ctle_field)(:),ones(param.samples_per_ui, 1)); | ≠ | 7309 | pulse_ctle=conv2(chdata(1).(ctle_field)(:),ones(param.samples_per_ui, 1)); |
≠ | 7501 | pulse_struc(ii).pulse_ctle=pulse_struc(ii).pulse_ctle(1:end-param.samples_per_ui+1); | ≠ | 7310 | pulse_ctle=pulse_ctle(1:end-param.samples_per_ui+1); |
≠ | 7502 | end | ≠ | 7311 | end |
≠ | 7503 | for k=1:length(txffe) | ≠ | 7312 | for k=1:length(txffe) |
≠ | 7504 | pulse_struc(ii).pulse_ctle_circshift(:,k)=circshift(pulse_struc(ii).pulse_ctle,[(k-1-num_pre)*param.samples_per_ui 0]); | ≠ | 7313 | pulse_ctle_circshift(:,k)=circshift(pulse_ctle,[(k-1-num_pre)*param.samples_per_ui 0]); |
− | 7505 | end |
| ||
7506 | end | 7314 | end | ||
7507 | end | 7315 | end | ||
7508 |
| 7316 |
| ||
7509 | %% Apply TXFFE to pre-shifted pulse response | 7317 | %% Apply TXFFE to pre-shifted pulse response | ||
7510 | %[sbr] = FFE( txffe, cur-1, param.samples_per_ui, uneq_pulse); | 7318 | %[sbr] = FFE( txffe, cur-1, param.samples_per_ui, uneq_pulse); | ||
≠ | 7511 | sbr=FFE_Fast(txffe,pulse_struc(1).pulse_ctle_circshift); | ≠ | 7319 | sbr=FFE_Fast(txffe,pulse_ctle_circshift); |
7512 | sbr_from_txffe=sbr; | 7320 | sbr_from_txffe=sbr; | ||
− | 7513 | for ii=1:ich |
| ||
≠ | 7514 | % this is sbr when ii=1; to be used in get_PSDs | ≠ | 7321 | sbr1=sbr; |
− | 7515 | if isequal(chdata(ii).type, 'FEXT') || isequal(chdata(ii).type, 'THRU') |
| ||
7516 | chdata(ii).pulse_response_w_CFT_TXFFE_noRxFFE=FFE_Fast(txffe,pulse_struc(ii).pulse_ctle_circshift); | ||||
7517 | else | ||||
7518 | chdata(ii).pulse_response_w_CFT_TXFFE_noRxFFE=pulse_struc(ii).pulse_ctle; % don't apply TxFFE for NEXT | ||||
7519 | end | ||||
7520 | end | ||||
| + | 7322 |
| ||
7521 |
| 7323 |
| ||
7522 | %% Find Sample Location | 7324 | %% Find Sample Location | ||
7523 | % If RXFFE is included, the sample location will be found again below | 7325 | % If RXFFE is included, the sample location will be found again below | ||
7524 | [cursor_i,no_zero_crossing,sbr_peak_i,zxi]=cursor_sample_index(sbr,param,OP,start_max_idx:end_max_idx); | 7326 | [cursor_i,no_zero_crossing,sbr_peak_i,zxi]=cursor_sample_index(sbr,param,OP,start_max_idx:end_max_idx); | ||
7525 | if param.ts_anchor==0 | 7327 | if param.ts_anchor==0 | ||
7526 | %keep MM | 7328 | %keep MM | ||
7527 | elseif param.ts_anchor==1 | 7329 | elseif param.ts_anchor==1 | ||
7528 | %peak sample | 7330 | %peak sample | ||
7529 | cursor_i=sbr_peak_i; | 7331 | cursor_i=sbr_peak_i; | ||
7530 | no_zero_crossing=0; | 7332 | no_zero_crossing=0; | ||
7531 | elseif param.ts_anchor==2 | 7333 | elseif param.ts_anchor==2 | ||
7532 | %max DV | 7334 | %max DV | ||
7533 | possible_cursor=sbr(sbr_peak_i-param.samples_per_ui:sbr_peak_i+param.samples_per_ui); | 7335 | possible_cursor=sbr(sbr_peak_i-param.samples_per_ui:sbr_peak_i+param.samples_per_ui); | ||
7534 | possible_precursor=sbr(sbr_peak_i-2*param.samples_per_ui:sbr_peak_i); | 7336 | possible_precursor=sbr(sbr_peak_i-2*param.samples_per_ui:sbr_peak_i); | ||
7535 | [max_diff,d_idx]=max(possible_cursor-possible_precursor); | 7337 | [max_diff,d_idx]=max(possible_cursor-possible_precursor); | ||
7536 | cursor_i=sbr_peak_i-param.samples_per_ui+d_idx-1; | 7338 | cursor_i=sbr_peak_i-param.samples_per_ui+d_idx-1; | ||
7537 | no_zero_crossing=0; | 7339 | no_zero_crossing=0; | ||
7538 | else | 7340 | else | ||
7539 | error('ts_anchor parameter must be 0, 1, or 2'); | 7341 | error('ts_anchor parameter must be 0, 1, or 2'); | ||
7540 | end | 7342 | end | ||
7541 | if no_zero_crossing | 7343 | if no_zero_crossing | ||
7542 | continue; | 7344 | continue; | ||
7543 | end | 7345 | end | ||
7544 | raw_cursor_i=cursor_i; | 7346 | raw_cursor_i=cursor_i; | ||
7545 |
| 7347 |
| ||
7546 | %%%%%%%%%% | 7348 | %%%%%%%%%% | ||
7547 | %%%%%%%%%% | 7349 | %%%%%%%%%% | ||
7548 | %%%%%%%%%% | 7350 | %%%%%%%%%% | ||
7549 | %NEW ITICK LOOP (not indenting everything yet) | 7351 | %NEW ITICK LOOP (not indenting everything yet) | ||
7550 | [~,si]=sort(abs(full_sample_range)); | 7352 | [~,si]=sort(abs(full_sample_range)); | ||
7551 | best_positive_itick_FOM=-inf; | 7353 | best_positive_itick_FOM=-inf; | ||
7552 | best_negative_itick_FOM=-inf; | 7354 | best_negative_itick_FOM=-inf; | ||
7553 | best_positive_itick_in_loop=[]; | 7355 | best_positive_itick_in_loop=[]; | ||
7554 | best_negative_itick_in_loop=[]; | 7356 | best_negative_itick_in_loop=[]; | ||
7555 | best_itick_FOM=-inf; | 7357 | best_itick_FOM=-inf; | ||
7556 | best_itick_in_cluster=[]; | 7358 | best_itick_in_cluster=[]; | ||
7557 | best_cluster=[]; | 7359 | best_cluster=[]; | ||
7558 |
| 7360 |
| ||
7559 | %box_search: take the middle of 5 point windows, then use the best of those to search the rest of that window | 7361 | %box_search: take the middle of 5 point windows, then use the best of those to search the rest of that window | ||
7560 | %middle_search: start from itick=0 and work outwards in negative and positive direction. stop searching when FOM starts to go down (using LOCAL SEARCH) | 7362 | %middle_search: start from itick=0 and work outwards in negative and positive direction. stop searching when FOM starts to go down (using LOCAL SEARCH) | ||
− | 7561 | % Commit request4p4_7 healey_3dj_COM_01_240416 |
| ||
7562 | %box_search=0; | ||||
7563 | %middle_search=1;% should set 0 so all Ts sample points are used | ||||
7564 | switch lower(OP.TS_SRCH_MODE) % Commit request4p4_7 healey_3dj_COM_01_240416 | ||||
7565 | case 'full-sweep' | ||||
7566 | box_search=0; | ||||
7567 | middle_search=0; | ||||
7568 | case 'middle' | ||||
≠ | 7569 | box_search=0; | ≠ | 7363 | box_search=0; |
≠ | 7570 | middle_search=1; | ≠ | 7364 | middle_search=1; |
≠ | 7571 | otherwise | ≠ | 7365 |
|
− | 7572 | error('unsuported TS_SRCH_MODE (%s)!',OP.TS_SRCH_MODE); |
| ||
7573 | end | ||||
7574 | if box_search | 7366 | if box_search | ||
7575 | box_size=5; | 7367 | box_size=5; | ||
7576 | box_mid=floor(box_size/2); | 7368 | box_mid=floor(box_size/2); | ||
7577 | cluster=full_sample_range(1)+box_mid:box_size:full_sample_range(end); | 7369 | cluster=full_sample_range(1)+box_mid:box_size:full_sample_range(end); | ||
7578 | CL=length(cluster); | 7370 | CL=length(cluster); | ||
7579 | loop_range=1:CL+box_mid*2; | 7371 | loop_range=1:CL+box_mid*2; | ||
7580 | elseif middle_search | 7372 | elseif middle_search | ||
7581 | loop_range=si; | 7373 | loop_range=si; | ||
7582 | else | 7374 | else | ||
7583 | loop_range=1:length(full_sample_range); | 7375 | loop_range=1:length(full_sample_range); | ||
7584 | end | 7376 | end | ||
7585 |
| 7377 |
| ||
7586 | for itickn=loop_range | 7378 | for itickn=loop_range | ||
7587 | if box_search | 7379 | if box_search | ||
7588 | if itickn<=CL | 7380 | if itickn<=CL | ||
7589 | itick=cluster(itickn); | 7381 | itick=cluster(itickn); | ||
7590 | else | 7382 | else | ||
7591 | if itickn==CL+1 | 7383 | if itickn==CL+1 | ||
7592 | best_cluster=setdiff([best_itick_in_cluster-box_mid:best_itick_in_cluster+box_mid],best_itick_in_cluster); | 7384 | best_cluster=setdiff([best_itick_in_cluster-box_mid:best_itick_in_cluster+box_mid],best_itick_in_cluster); | ||
7593 | end | 7385 | end | ||
7594 | if isempty(best_cluster) | 7386 | if isempty(best_cluster) | ||
7595 | continue; | 7387 | continue; | ||
7596 | end | 7388 | end | ||
7597 | itick=best_cluster(itickn-CL); | 7389 | itick=best_cluster(itickn-CL); | ||
7598 | end | 7390 | end | ||
7599 | else | 7391 | else | ||
7600 | itick=full_sample_range(itickn); | 7392 | itick=full_sample_range(itickn); | ||
7601 | end | 7393 | end | ||
7602 |
| 7394 |
| ||
7603 | itick_cases=itick_cases+1; | 7395 | itick_cases=itick_cases+1; | ||
7604 |
| 7396 |
| ||
7605 | sbr=sbr_from_txffe; | 7397 | sbr=sbr_from_txffe; | ||
7606 | cursor_i = raw_cursor_i+itick; | 7398 | cursor_i = raw_cursor_i+itick; | ||
7607 |
| 7399 |
| ||
7608 | %Local Search for +/- itick sweep | 7400 | %Local Search for +/- itick sweep | ||
7609 | if middle_search && param.LOCAL_SEARCH>0 | 7401 | if middle_search && param.LOCAL_SEARCH>0 | ||
7610 | if itick>=0 && ~isinf(best_positive_itick_FOM) && abs(best_positive_itick_in_loop-itick)>=param.LOCAL_SEARCH | 7402 | if itick>=0 && ~isinf(best_positive_itick_FOM) && abs(best_positive_itick_in_loop-itick)>=param.LOCAL_SEARCH | ||
7611 | itick_skips=itick_skips+1; | 7403 | itick_skips=itick_skips+1; | ||
7612 | continue; | 7404 | continue; | ||
7613 | end | 7405 | end | ||
7614 | if itick<=0 && ~isinf(best_negative_itick_FOM) && abs(best_negative_itick_in_loop-itick)>=param.LOCAL_SEARCH | 7406 | if itick<=0 && ~isinf(best_negative_itick_FOM) && abs(best_negative_itick_in_loop-itick)>=param.LOCAL_SEARCH | ||
7615 | itick_skips=itick_skips+1; | 7407 | itick_skips=itick_skips+1; | ||
7616 | continue; | 7408 | continue; | ||
7617 | end | 7409 | end | ||
7618 | end | 7410 | end | ||
7619 |
| 7411 |
| ||
7620 | triple_transit_time = round(sbr_peak_i*2/param.samples_per_ui)+20; | 7412 | triple_transit_time = round(sbr_peak_i*2/param.samples_per_ui)+20; | ||
7621 | if min_number_of_UI_in_response < triple_transit_time | 7413 | if min_number_of_UI_in_response < triple_transit_time | ||
7622 | min_number_of_UI_in_response = triple_transit_time; | 7414 | min_number_of_UI_in_response = triple_transit_time; | ||
7623 | end | 7415 | end | ||
7624 |
| 7416 |
| ||
7625 | cursor = sbr(cursor_i); | 7417 | cursor = sbr(cursor_i); | ||
7626 |
| 7418 |
| ||
7627 | %% RXFFE | 7419 | %% RXFFE | ||
7628 | if OP.RxFFE | 7420 | if OP.RxFFE | ||
7629 | % [ sbr, C]=force(sbr,param,OP,cursor_i); | 7421 | % [ sbr, C]=force(sbr,param,OP,cursor_i); | ||
7630 | %[ sbr, C]=force(sbr,param,OP,zxi+param.samples_per_ui); | 7422 | %[ sbr, C]=force(sbr,param,OP,zxi+param.samples_per_ui); | ||
7631 | %if isrow(sbr), sbr=sbr';end | 7423 | %if isrow(sbr), sbr=sbr';end | ||
7632 |
| 7424 |
| ||
7633 | %AJG: do not return sbr here (run time improvement) | 7425 | %AJG: do not return sbr here (run time improvement) | ||
7634 | %UPDATE: use cursor_i in RXFFE instead of zero crossing + 1 UI | 7426 | %UPDATE: use cursor_i in RXFFE instead of zero crossing + 1 UI | ||
7635 | %[ ~, C]=force(sbr,param,OP,zxi+param.samples_per_ui,[],0); | 7427 | %[ ~, C]=force(sbr,param,OP,zxi+param.samples_per_ui,[],0); | ||
7636 | % [ ~, C, floating_tap_locations]=force(sbr,param,OP,cursor_i,[],0); | 7428 | % [ ~, C, floating_tap_locations]=force(sbr,param,OP,cursor_i,[],0); | ||
7637 | % sbr at this point include the current setting | 7429 | % sbr at this point include the current setting | ||
7638 | % under consideration of txffe h21 ctf and fr | 7430 | % under consideration of txffe h21 ctf and fr | ||
7639 | switch upper(OP.FFE_OPT_METHOD) | 7431 | switch upper(OP.FFE_OPT_METHOD) | ||
7640 | case 'MMSE' | 7432 | case 'MMSE' | ||
7641 | OP.WO_TXFFE=0; | 7433 | OP.WO_TXFFE=0; | ||
7642 | PSD_results=get_PSDs(PSD_results,sbr,cursor_i,txffe,gdc_values(ctle_index),g_DC_low,param,chdata,OP); | 7434 | PSD_results=get_PSDs(PSD_results,sbr,cursor_i,txffe,gdc_values(ctle_index),g_DC_low,param,chdata,OP); | ||
7643 | S_n=PSD_results.S_rn+PSD_results.S_tn+PSD_results.S_xn+PSD_results.S_jn; | 7435 | S_n=PSD_results.S_rn+PSD_results.S_tn+PSD_results.S_xn+PSD_results.S_jn; | ||
7644 | if 0 % for debug | 7436 | if 0 % for debug | ||
7645 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_rn*1000/100) ,'disp','Srn') | 7437 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_rn*1000/100) ,'disp','Srn') | ||
7646 | hold on | 7438 | hold on | ||
7647 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_xn*1000/100) ,'disp','Sxn') | 7439 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_xn*1000/100) ,'disp','Sxn') | ||
7648 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_tn*1000/100) ,'disp','Stn') | 7440 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_tn*1000/100) ,'disp','Stn') | ||
7649 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_jn*1000/100) ,'disp','Sjn') | 7441 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_jn*1000/100) ,'disp','Sjn') | ||
7650 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_n*1000/100) ,'disp','Sn') | 7442 | plot(PSD_results.fvec(1:param.num_ui_RXFF_noise)/param.fb,10*log10(PSD_results.S_n*1000/100) ,'disp','Sn') | ||
7651 | xlim([0 0.5]) | 7443 | xlim([0 0.5]) | ||
7652 | % ylim([-190 -160]) | 7444 | % ylim([-190 -160]) | ||
7653 | set(gcf,'defaulttextinterpreter','none') | 7445 | set(gcf,'defaulttextinterpreter','none') | ||
7654 | xlabel('Normalized Frequency') | 7446 | xlabel('Normalized Frequency') | ||
7655 | ylabel('PSD dBm/Hz') | 7447 | ylabel('PSD dBm/Hz') | ||
7656 | hold on | 7448 | hold on | ||
7657 | grid on | 7449 | grid on | ||
7658 | legend show | 7450 | legend show | ||
7659 | title('PSD') | 7451 | title('PSD') | ||
7660 | end | 7452 | end | ||
7661 | MMSE_results = MMSE(PSD_results,sbr,cursor_i, param, OP ) ; | 7453 | MMSE_results = MMSE(PSD_results,sbr,cursor_i, param, OP ) ; | ||
7662 | % floating_tap_locations=MMSE_results.MLSE_results; | 7454 | % floating_tap_locations=MMSE_results.MLSE_results; | ||
7663 | C=MMSE_results.C; | 7455 | C=MMSE_results.C; | ||
7664 | FOM=MMSE_results.FOM; | 7456 | FOM=MMSE_results.FOM; | ||
7665 | floating_tap_locations=MMSE_results.floating_tap_locations; | 7457 | floating_tap_locations=MMSE_results.floating_tap_locations; | ||
7666 | otherwise | 7458 | otherwise | ||
7667 | [ ~, C, floating_tap_locations]=force(sbr,param,OP,cursor_i,[],0, chdata, txffe, Noise_XC); | 7459 | [ ~, C, floating_tap_locations]=force(sbr,param,OP,cursor_i,[],0, chdata, txffe, Noise_XC); | ||
7668 | end | 7460 | end | ||
7669 | %Now there is a stand alone function for determining if RXFFE taps are illegal | 7461 | %Now there is a stand alone function for determining if RXFFE taps are illegal | ||
7670 | %This is because the "force" function will also do a legality check when "backoff" is enabled | 7462 | %This is because the "force" function will also do a legality check when "backoff" is enabled | ||
7671 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 7463 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
7672 | if RXFFE_Illegal(C,param) | 7464 | if RXFFE_Illegal(C,param) | ||
7673 | continue; | 7465 | continue; | ||
7674 | end | 7466 | end | ||
7675 | end | 7467 | end | ||
7676 | %AJG: speed up: calculate sbr after checks for illegal taps (many tap combinations are illegal and "FFE" is time consuming) | 7468 | %AJG: speed up: calculate sbr after checks for illegal taps (many tap combinations are illegal and "FFE" is time consuming) | ||
7677 | sbr=FFE(C,param.RxFFE_cmx,param.samples_per_ui,sbr); | 7469 | sbr=FFE(C,param.RxFFE_cmx,param.samples_per_ui,sbr); | ||
7678 | if isrow(sbr), sbr=sbr';end | 7470 | if isrow(sbr), sbr=sbr';end | ||
7679 |
| 7471 |
| ||
7680 | %% second guess at cursor location (t_s) - based on approximate zero crossing | 7472 | %% second guess at cursor location (t_s) - based on approximate zero crossing | ||
7681 | %This entire block is now inside the "if OP.RxFFE" to avoid unnecessary re-calculation | 7473 | %This entire block is now inside the "if OP.RxFFE" to avoid unnecessary re-calculation | ||
7682 | %UPDATE: NOT RESAMPLING AFTER RXFFE | 7474 | %UPDATE: NOT RESAMPLING AFTER RXFFE | ||
7683 | % [cursor_i,no_zero_crossing,sbr_peak_i]=cursor_sample_index(sbr,param,OP,start_max_idx:end_max_idx); | 7475 | % [cursor_i,no_zero_crossing,sbr_peak_i]=cursor_sample_index(sbr,param,OP,start_max_idx:end_max_idx); | ||
7684 | % if no_zero_crossing | 7476 | % if no_zero_crossing | ||
7685 | % continue; | 7477 | % continue; | ||
7686 | % end | 7478 | % end | ||
7687 |
| 7479 |
| ||
7688 | cursor = sbr(cursor_i); | 7480 | cursor = sbr(cursor_i); | ||
7689 | end | 7481 | end | ||
7690 | A_p=sbr(sbr_peak_i); | 7482 | A_p=sbr(sbr_peak_i); | ||
7691 | %% 93A.1.6 step c defines A_s %% | 7483 | %% 93A.1.6 step c defines A_s %% | ||
7692 | A_s = param.R_LM*cursor/(param.levels-1); | 7484 | A_s = param.R_LM*cursor/(param.levels-1); | ||
7693 | if isempty(delta_sbr) | 7485 | if isempty(delta_sbr) | ||
7694 | delta_sbr = sbr; | 7486 | delta_sbr = sbr; | ||
7695 | end | 7487 | end | ||
7696 | sbr=sbr(:); | 7488 | sbr=sbr(:); | ||
7697 | %% Equation 93A-27 "otherwise" case %% param.N_bmax is param.ndfe if groups are not used | 7489 | %% Equation 93A-27 "otherwise" case %% param.N_bmax is param.ndfe if groups are not used | ||
7698 |
| 7490 |
| ||
7699 | if(param.Floating_DFE), param.ndfe=param.N_bmax; end | 7491 | if(param.Floating_DFE), param.ndfe=param.N_bmax; end | ||
7700 | far_cursors = sbr(cursor_i-T_O+param.samples_per_ui*(param.ndfe+1):param.samples_per_ui:end); | 7492 | far_cursors = sbr(cursor_i-T_O+param.samples_per_ui*(param.ndfe+1):param.samples_per_ui:end); | ||
7701 | t=((cursor_i+param.samples_per_ui*(param.ndfe+1):param.samples_per_ui:length(sbr))-(cursor_i+param.samples_per_ui*(param.ndfe+1)))*... | 7493 | t=((cursor_i+param.samples_per_ui*(param.ndfe+1):param.samples_per_ui:length(sbr))-(cursor_i+param.samples_per_ui*(param.ndfe+1)))*... | ||
7702 | param.ui/param.samples_per_ui; | 7494 | param.ui/param.samples_per_ui; | ||
7703 | precursors = sbr(cursor_i-param.samples_per_ui:-param.samples_per_ui:1); | 7495 | precursors = sbr(cursor_i-param.samples_per_ui:-param.samples_per_ui:1); | ||
7704 | precursors = precursors(end:-1:1); | 7496 | precursors = precursors(end:-1:1); | ||
7705 |
| 7497 |
| ||
7706 | % % Error message if the sbr is not long enough for the specified range of Nb | 7498 | % % Error message if the sbr is not long enough for the specified range of Nb | ||
7707 | % if length(sbr) < cursor_i+param.samples_per_ui*(param.ndfe+1) | 7499 | % if length(sbr) < cursor_i+param.samples_per_ui*(param.ndfe+1) | ||
7708 | % close(hwaitbar); | 7500 | % close(hwaitbar); | ||
7709 | % error('Pulse Response contains %d samples after the cursor. Specified Nb requires %d samples after the cursor.' ... | 7501 | % error('Pulse Response contains %d samples after the cursor. Specified Nb requires %d samples after the cursor.' ... | ||
7710 | % , length(sbr)-cursor_i, param.samples_per_ui*(param.ndfe+1)); | 7502 | % , length(sbr)-cursor_i, param.samples_per_ui*(param.ndfe+1)); | ||
7711 | % end | 7503 | % end | ||
7712 |
| 7504 |
| ||
7713 |
| 7505 |
| ||
7714 |
| 7506 |
| ||
7715 | %% skip this case if FOM has no chance of beating old FOM | 7507 | %% skip this case if FOM has no chance of beating old FOM | ||
7716 | %this is also done below but with excess_dfe_cursors included. | 7508 | %this is also done below but with excess_dfe_cursors included. | ||
7717 | %excess_dfe_cursors requires the floating DFE computation which is | 7509 | %excess_dfe_cursors requires the floating DFE computation which is | ||
7718 | %time consuming, so checking here can have significant run time improvements | 7510 | %time consuming, so checking here can have significant run time improvements | ||
7719 | sigma_ISI_ignoreDFE = param.sigma_X*norm([precursors; far_cursors]); | 7511 | sigma_ISI_ignoreDFE = param.sigma_X*norm([precursors; far_cursors]); | ||
7720 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 7512 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
7721 | if (20*log10(A_s/sigma_ISI_ignoreDFE) < best_FOM) | 7513 | if (20*log10(A_s/sigma_ISI_ignoreDFE) < best_FOM) | ||
7722 | continue | 7514 | continue | ||
7723 | end | 7515 | end | ||
7724 | end | 7516 | end | ||
7725 |
| 7517 |
| ||
7726 | %% Equation 93A-27, when 1<=n<=N_b | 7518 | %% Equation 93A-27, when 1<=n<=N_b | ||
7727 | %required length = cursor + all DFE UI + 1 additional UI | 7519 | %required length = cursor + all DFE UI + 1 additional UI | ||
7728 | sbr_required_length=cursor_i+param.samples_per_ui*(param.ndfe+1); | 7520 | sbr_required_length=cursor_i+param.samples_per_ui*(param.ndfe+1); | ||
7729 | if length(sbr)<sbr_required_length | 7521 | if length(sbr)<sbr_required_length | ||
7730 | sbr(end+1:sbr_required_length)=0; | 7522 | sbr(end+1:sbr_required_length)=0; | ||
7731 | end | 7523 | end | ||
7732 | dfecursors=sbr(cursor_i+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe)); | 7524 | dfecursors=sbr(cursor_i+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe)); | ||
7733 | if param.dfe_delta ~= 0 | 7525 | if param.dfe_delta ~= 0 | ||
7734 | dfecursors_q=floor(abs(dfecursors/sbr(cursor_i))./param.dfe_delta).*param.dfe_delta.*sign(dfecursors)*sbr(cursor_i); | 7526 | dfecursors_q=floor(abs(dfecursors/sbr(cursor_i))./param.dfe_delta).*param.dfe_delta.*sign(dfecursors)*sbr(cursor_i); | ||
7735 |
| 7527 |
| ||
7736 | else | 7528 | else | ||
7737 | dfecursors_q=dfecursors; | 7529 | dfecursors_q=dfecursors; | ||
7738 | end | 7530 | end | ||
7739 | if param.Floating_DFE | 7531 | if param.Floating_DFE | ||
7740 | %% floating taps | 7532 | %% floating taps | ||
7741 | postcurors= sbr(cursor_i+param.samples_per_ui:param.samples_per_ui:end); | 7533 | postcurors= sbr(cursor_i+param.samples_per_ui:param.samples_per_ui:end); | ||
7742 |
| 7534 |
| ||
7743 | [floating_tap_locations, floating_tap_coef, hisi, bmax]= floatingDFE( postcurors ,param.ndfe_passed,param.N_bf,param.N_bg,param.N_bmax, param.bmaxg, sbr(cursor_i), param.dfe_delta ); | 7535 | [floating_tap_locations, floating_tap_coef, hisi, bmax]= floatingDFE( postcurors ,param.ndfe_passed,param.N_bf,param.N_bg,param.N_bmax, param.bmaxg, sbr(cursor_i), param.dfe_delta ); | ||
7744 |
| 7536 |
| ||
7745 | newbmax= [ param.bmax bmax(param.ndfe_passed+1:param.N_bmax)].'; | 7537 | newbmax= [ param.bmax bmax(param.ndfe_passed+1:param.N_bmax)].'; | ||
7746 | param.use_bmax=newbmax; | 7538 | param.use_bmax=newbmax; | ||
7747 | %AJG021820 | 7539 | %AJG021820 | ||
7748 | param.use_bmin=[param.bmin bmax(param.ndfe_passed+1:param.N_bmax)*-1].'; | 7540 | param.use_bmin=[param.bmin bmax(param.ndfe_passed+1:param.N_bmax)*-1].'; | ||
7749 | else | 7541 | else | ||
7750 | param.use_bmax=param.bmax; | 7542 | param.use_bmax=param.bmax; | ||
7751 | %AJG021820 | 7543 | %AJG021820 | ||
7752 | param.use_bmin=param.bmin; | 7544 | param.use_bmin=param.bmin; | ||
7753 | end | 7545 | end | ||
7754 |
| 7546 |
| ||
7755 | %AJG021820 | 7547 | %AJG021820 | ||
7756 | actual_dfecursors=dfe_clipper(dfecursors_q,sbr(cursor_i)*param.use_bmax(:),sbr(cursor_i)*param.use_bmin(:)); | 7548 | actual_dfecursors=dfe_clipper(dfecursors_q,sbr(cursor_i)*param.use_bmax(:),sbr(cursor_i)*param.use_bmin(:)); | ||
7757 | if do_C2M | 7549 | if do_C2M | ||
7758 | dfecursors_windowed=sbr(cursor_i-T_O+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe)-T_O); | 7550 | dfecursors_windowed=sbr(cursor_i-T_O+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe)-T_O); | ||
7759 | % readjust SBR | 7551 | % readjust SBR | ||
7760 | if 0 | 7552 | if 0 | ||
7761 | %PR_DFE_center not currently used, so this is in "if 0" statement | 7553 | %PR_DFE_center not currently used, so this is in "if 0" statement | ||
7762 | PR_DFE_center=sbr; | 7554 | PR_DFE_center=sbr; | ||
7763 | for n=1:param.ndfe | 7555 | for n=1:param.ndfe | ||
7764 | % for ix=-param.samples_per_ui/2: param.samples_per_ui/2 | 7556 | % for ix=-param.samples_per_ui/2: param.samples_per_ui/2 | ||
7765 | % i_sample=ix+n*param.samples_per_ui+cursor_i; | 7557 | % i_sample=ix+n*param.samples_per_ui+cursor_i; | ||
7766 | % dper=sbr(i_sample)- actual_dfecursors(n); | 7558 | % dper=sbr(i_sample)- actual_dfecursors(n); | ||
7767 | % PR_DFE_center(i_sample)=dper; | 7559 | % PR_DFE_center(i_sample)=dper; | ||
7768 | % end | 7560 | % end | ||
7769 | i_sample=(-param.samples_per_ui/2: param.samples_per_ui/2)+n*param.samples_per_ui+cursor_i; | 7561 | i_sample=(-param.samples_per_ui/2: param.samples_per_ui/2)+n*param.samples_per_ui+cursor_i; | ||
7770 | PR_DFE_center(i_sample)=sbr(i_sample)-actual_dfecursors(n); | 7562 | PR_DFE_center(i_sample)=sbr(i_sample)-actual_dfecursors(n); | ||
7771 | end | 7563 | end | ||
7772 | end | 7564 | end | ||
7773 | excess_dfe_cursors=dfecursors_windowed-actual_dfecursors; | 7565 | excess_dfe_cursors=dfecursors_windowed-actual_dfecursors; | ||
7774 | else | 7566 | else | ||
7775 | excess_dfe_cursors=dfecursors-actual_dfecursors; | 7567 | excess_dfe_cursors=dfecursors-actual_dfecursors; | ||
7776 | end | 7568 | end | ||
7777 | dfetaps=actual_dfecursors/sbr(cursor_i); | 7569 | dfetaps=actual_dfecursors/sbr(cursor_i); | ||
7778 |
| 7570 |
| ||
7779 | if length(dfetaps) >= param.N_tail_start && param.N_tail_start ~=0 | 7571 | if length(dfetaps) >= param.N_tail_start && param.N_tail_start ~=0 | ||
7780 | tail_RSS=norm(dfetaps(param.N_tail_start:end)); | 7572 | tail_RSS=norm(dfetaps(param.N_tail_start:end)); | ||
7781 | if tail_RSS ~= 0 | 7573 | if tail_RSS ~= 0 | ||
7782 | if tail_RSS >= param.B_float_RSS_MAX | 7574 | if tail_RSS >= param.B_float_RSS_MAX | ||
7783 | param.use_bmax(param.N_tail_start:end)= ... | 7575 | param.use_bmax(param.N_tail_start:end)= ... | ||
7784 | min(tail_RSS, param.B_float_RSS_MAX) * sign(dfetaps(param.N_tail_start:end)).*dfetaps(param.N_tail_start:end) /tail_RSS; | 7576 | min(tail_RSS, param.B_float_RSS_MAX) * sign(dfetaps(param.N_tail_start:end)).*dfetaps(param.N_tail_start:end) /tail_RSS; | ||
7785 | %AJG021820 | 7577 | %AJG021820 | ||
7786 | param.use_bmin(param.N_tail_start:end)= ... | 7578 | param.use_bmin(param.N_tail_start:end)= ... | ||
7787 | min(tail_RSS, param.B_float_RSS_MAX) * -1 * sign(dfetaps(param.N_tail_start:end)).*dfetaps(param.N_tail_start:end) /tail_RSS; | 7579 | min(tail_RSS, param.B_float_RSS_MAX) * -1 * sign(dfetaps(param.N_tail_start:end)).*dfetaps(param.N_tail_start:end) /tail_RSS; | ||
7788 | end | 7580 | end | ||
7789 | end | 7581 | end | ||
7790 |
| 7582 |
| ||
7791 | %AJG021820 | 7583 | %AJG021820 | ||
7792 | actual_dfecursors=dfe_clipper(dfecursors_q,sbr(cursor_i)*param.use_bmax(:),sbr(cursor_i)*param.use_bmin(:)); | 7584 | actual_dfecursors=dfe_clipper(dfecursors_q,sbr(cursor_i)*param.use_bmax(:),sbr(cursor_i)*param.use_bmin(:)); | ||
7793 | if do_C2M | 7585 | if do_C2M | ||
7794 | excess_dfe_cursors=dfecursors_windowed-actual_dfecursors; | 7586 | excess_dfe_cursors=dfecursors_windowed-actual_dfecursors; | ||
7795 | else | 7587 | else | ||
7796 | excess_dfe_cursors=dfecursors-actual_dfecursors; | 7588 | excess_dfe_cursors=dfecursors-actual_dfecursors; | ||
7797 | end | 7589 | end | ||
7798 | dfetaps=actual_dfecursors/sbr(cursor_i); | 7590 | dfetaps=actual_dfecursors/sbr(cursor_i); | ||
7799 |
| 7591 |
| ||
7800 | else | 7592 | else | ||
7801 | tail_RSS=0; | 7593 | tail_RSS=0; | ||
7802 | end | 7594 | end | ||
7803 | %% Eq. 93A-28 %% | 7595 | %% Eq. 93A-28 %% | ||
7804 | sampling_offset = mod(cursor_i, param.samples_per_ui); | 7596 | sampling_offset = mod(cursor_i, param.samples_per_ui); | ||
7805 | %ensure we can take early sample | 7597 | %ensure we can take early sample | ||
7806 | if sampling_offset<=1 | 7598 | if sampling_offset<=1 | ||
7807 | sampling_offset=sampling_offset+param.samples_per_ui; | 7599 | sampling_offset=sampling_offset+param.samples_per_ui; | ||
7808 | end | 7600 | end | ||
7809 | if (OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN) | 7601 | if (OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN) | ||
7810 | cursors_early_sample = sbr(cursor_i-1+param.samples_per_ui*(-1:param.ndfe)); | 7602 | cursors_early_sample = sbr(cursor_i-1+param.samples_per_ui*(-1:param.ndfe)); | ||
7811 | cursors_late_sample = sbr(cursor_i+1+param.samples_per_ui*(-1:param.ndfe)); | 7603 | cursors_late_sample = sbr(cursor_i+1+param.samples_per_ui*(-1:param.ndfe)); | ||
7812 | else | 7604 | else | ||
7813 | cursors_early_sample = sbr(sampling_offset-1:param.samples_per_ui:end); | 7605 | cursors_early_sample = sbr(sampling_offset-1:param.samples_per_ui:end); | ||
7814 | cursors_late_sample = sbr(sampling_offset+1:param.samples_per_ui:end); | 7606 | cursors_late_sample = sbr(sampling_offset+1:param.samples_per_ui:end); | ||
7815 | end | 7607 | end | ||
7816 | % ensure lengths are equal | 7608 | % ensure lengths are equal | ||
7817 | cursors_early_sample = cursors_early_sample(1:length(cursors_late_sample)); | 7609 | cursors_early_sample = cursors_early_sample(1:length(cursors_late_sample)); | ||
7818 | h_J = (cursors_late_sample-cursors_early_sample)/2*param.samples_per_ui; | 7610 | h_J = (cursors_late_sample-cursors_early_sample)/2*param.samples_per_ui; | ||
7819 | if ~OP.SNR_TXwC0 | 7611 | if ~OP.SNR_TXwC0 | ||
7820 | %% Equation 93A-30 %% | 7612 | %% Equation 93A-30 %% | ||
7821 | % since A_s = param.R_LM*cursor/(param.levels-1), cursor=(param.levels-1)*A_s/param.R_LM | 7613 | % since A_s = param.R_LM*cursor/(param.levels-1), cursor=(param.levels-1)*A_s/param.R_LM | ||
7822 | sigma_TX = (param.levels-1)*A_s/param.R_LM*10^(-param.SNR_TX/20); | 7614 | sigma_TX = (param.levels-1)*A_s/param.R_LM*10^(-param.SNR_TX/20); | ||
7823 | else | 7615 | else | ||
7824 | sigma_TX = (param.levels-1)*A_s/txffe(cur)/param.R_LM*10^(-param.SNR_TX/20);% SNER_TX mod from Adee | 7616 | sigma_TX = (param.levels-1)*A_s/txffe(cur)/param.R_LM*10^(-param.SNR_TX/20);% SNER_TX mod from Adee | ||
7825 | end | 7617 | end | ||
7826 | %% Equation 93A-31 %% | 7618 | %% Equation 93A-31 %% | ||
7827 | sigma_ISI = param.sigma_X*norm([precursors; excess_dfe_cursors; far_cursors]); | 7619 | sigma_ISI = param.sigma_X*norm([precursors; excess_dfe_cursors; far_cursors]); | ||
7828 | ISI_N=param.sigma_X*norm( far_cursors); | 7620 | ISI_N=param.sigma_X*norm( far_cursors); | ||
7829 | %% break if FOM has no chance of beating old e | 7621 | %% break if FOM has no chance of beating old e | ||
≠ | 7830 | OP.exe_mode=1; | ≠ | 7622 | OP.EXE_MODE=1; |
7831 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 7623 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
7832 | switch OP.EXE_MODE | 7624 | switch OP.EXE_MODE | ||
7833 | case 0 | 7625 | case 0 | ||
7834 | case 1 | 7626 | case 1 | ||
7835 | if (20*log10(A_s/sigma_ISI) < best_FOM) | 7627 | if (20*log10(A_s/sigma_ISI) < best_FOM) | ||
7836 | continue | 7628 | continue | ||
7837 | end | 7629 | end | ||
7838 | case 2 | 7630 | case 2 | ||
7839 | if (20*log10(A_s/sigma_ISI) < best_FOM) | 7631 | if (20*log10(A_s/sigma_ISI) < best_FOM) | ||
7840 | break | 7632 | break | ||
7841 | end | 7633 | end | ||
7842 | end | 7634 | end | ||
7843 | end | 7635 | end | ||
7844 | %% Equation 93A-32 %% | 7636 | %% Equation 93A-32 %% | ||
7845 | sigma_J = norm([param.A_DD param.sigma_RJ])*param.sigma_X*norm(h_J); | 7637 | sigma_J = norm([param.A_DD param.sigma_RJ])*param.sigma_X*norm(h_J); | ||
7846 |
| 7638 |
| ||
7847 | %% Equations 93A-33 and 93A-34 for FEXT (depends on TXFFE setting) %% | 7639 | %% Equations 93A-33 and 93A-34 for FEXT (depends on TXFFE setting) %% | ||
7848 | if OP.RX_CALIBRATION | 7640 | if OP.RX_CALIBRATION | ||
7849 | sigma_XT=0; | 7641 | sigma_XT=0; | ||
7850 | else | 7642 | else | ||
7851 | if ~OP.RxFFE | 7643 | if ~OP.RxFFE | ||
| + | 7644 | % sigma_FEXT = get_xtlk_noise( 0, 'FEXT', param ,chdata); | ||
7645 | % sigma_XT = norm([sigma_NEXT sigma_FEXT]); | ||||
7852 | [sigma_XT,~,~] = get_xtlk_noise( txffe, 'FEXT', param ,chdata,phase_memory); %with three outputs, the sigma_XT includes both FEXT and NEXT zhilei huang 01/11/2019 | 7646 | [sigma_XT,~,~] = get_xtlk_noise( txffe, 'FEXT', param ,chdata,phase_memory); %with three outputs, the sigma_XT includes both FEXT and NEXT zhilei huang 01/11/2019 | ||
7853 | %% Equation 93A-36 denominator (actually its sqrt) | 7647 | %% Equation 93A-36 denominator (actually its sqrt) | ||
7854 | else % John Ewen: 13/12/20018 | 7648 | else % John Ewen: 13/12/20018 | ||
− | 7855 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE')) |
| ||
≠ | 7856 | [sigma_XT,~,~] = get_xtlk_noise( txffe, 'FEXT', param ,chdata, phase_memory,C); %with three outputs, the sigma_XT includes both FEXT and NEXT zhilei huang 01/11/2019 | ≠ | 7649 | [sigma_XT,~,~] = get_xtlk_noise( txffe, 'FEXT', param ,chdata, phase_memory,C); %with three outputs, the sigma_XT includes both FEXT and NEXT zhilei huang 01/11/2019 |
| + | 7650 | % sigma_FEXT_ffe= get_xtlk_noise( 0, 'FEXT', param, chdata, C ); | ||
7651 | % if ~OP.RxFFE | ||||
7652 | % sigma_NEXT_ffe = get_xtlk_noise(0, 'NEXT', param, chdata); | ||||
7653 | % else | ||||
≠ | 7857 | else % use results from get_PSDs RIM 3/28/2024 | ≠ | 7654 | % sigma_NEXT_ffe = get_xtlk_noise(0, 'NEXT', param, chdata , C); |
| + | 7655 | % end | ||
≠ | 7858 | sigma_XT=PSD_results.S_xn_rms; | ≠ | 7656 | % sigma_XT = norm([sigma_NEXT_ffe sigma_FEXT_ffe])*sqrt((param.levels^2-1)/(3*(param.levels-1)^2)); |
− | 7859 | end |
| ||
7860 | end | 7657 | end | ||
7861 | end | 7658 | end | ||
7862 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | 7659 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) | ||
7863 | if OP.RxFFE % modify sigma_N with rx noise from the rx ffe | 7660 | if OP.RxFFE % modify sigma_N with rx noise from the rx ffe | ||
7864 | index_f2=find(chdata(1).faxis(:)>param.fb,1,'first'); | 7661 | index_f2=find(chdata(1).faxis(:)>param.fb,1,'first'); | ||
7865 | if isempty(index_f2), index_f2=length(chdata(1).faxis);end | 7662 | if isempty(index_f2), index_f2=length(chdata(1).faxis);end | ||
7866 | f=chdata(1).faxis; | 7663 | f=chdata(1).faxis; | ||
7867 | H_Rx_FFE=zeros(1,length(f)); | 7664 | H_Rx_FFE=zeros(1,length(f)); | ||
7868 | for ii=-param.RxFFE_cmx:param.RxFFE_cpx | 7665 | for ii=-param.RxFFE_cmx:param.RxFFE_cpx | ||
7869 | %H_Rx_FFE=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb)+H_Rx_FFE; | 7666 | %H_Rx_FFE=C(ii+param.RxFFE_cmx+1).*exp(-1j*2*pi*(ii+1).*f/param.fb)+H_Rx_FFE; | ||
7870 | if C(ii+param.RxFFE_cmx+1)==0 | 7667 | if C(ii+param.RxFFE_cmx+1)==0 | ||
7871 | %speed up: skip cases when rxffe=0 | 7668 | %speed up: skip cases when rxffe=0 | ||
7872 | continue; | 7669 | continue; | ||
7873 | end | 7670 | end | ||
7874 | if ii+1==0 | 7671 | if ii+1==0 | ||
7875 | %speed up: ii+1=0, so just scalar addition and avoid exp calc | 7672 | %speed up: ii+1=0, so just scalar addition and avoid exp calc | ||
7876 | H_Rx_FFE = H_Rx_FFE + C(ii+param.RxFFE_cmx+1); | 7673 | H_Rx_FFE = H_Rx_FFE + C(ii+param.RxFFE_cmx+1); | ||
7877 | else | 7674 | else | ||
7878 | H_Rx_FFE=C(ii+param.RxFFE_cmx+1).*transpose(phase_memory(:,ii+param.RxFFE_cmx+1+length(txffe)))+H_Rx_FFE; | 7675 | H_Rx_FFE=C(ii+param.RxFFE_cmx+1).*transpose(phase_memory(:,ii+param.RxFFE_cmx+1+length(txffe)))+H_Rx_FFE; | ||
7879 | end | 7676 | end | ||
7880 | end | 7677 | end | ||
7881 | sigma_N =sqrt(param.eta_0*sum(H_sy(2:end) .* abs(H_r(2:end) .* H_ctf(2:end) .*H_Rx_FFE(2:end)).^2 .* diff(chdata(1).faxis)/1e9)); % changed from /chdata(1).faxis(end) B. Kirkland S. Elnagar 11/6/2021 | 7678 | sigma_N =sqrt(param.eta_0*sum(H_sy(2:end) .* abs(H_r(2:end) .* H_ctf(2:end) .*H_Rx_FFE(2:end)).^2 .* diff(chdata(1).faxis)/1e9)); % changed from /chdata(1).faxis(end) B. Kirkland S. Elnagar 11/6/2021 | ||
7882 | end | 7679 | end | ||
7883 | end | 7680 | end | ||
7884 | %% Equation 93A-36 (note log argument is voltage rather than power ratio) | 7681 | %% Equation 93A-36 (note log argument is voltage rather than power ratio) | ||
− | 7885 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) |
| ||
≠ | 7886 | total_noise_rms = norm([sigma_ISI sigma_J sigma_XT sigma_N sigma_TX sigma_ne]); | ≠ | 7682 | total_noise_rms = norm([sigma_ISI sigma_J sigma_XT sigma_N sigma_TX sigma_ne]); |
− | 7887 | else |
| ||
7888 | total_noise_rms = norm([sigma_ISI PSD_results.S_n_rms sigma_ne]); | ||||
7889 | end | ||||
7890 | if do_C2M | 7683 | if do_C2M | ||
7891 | if param.Noise_Crest_Factor == 0 | 7684 | if param.Noise_Crest_Factor == 0 | ||
7892 | ber_q = sqrt(2)*erfcinv(2*param.specBER); | 7685 | ber_q = sqrt(2)*erfcinv(2*param.specBER); | ||
7893 | else | 7686 | else | ||
7894 | ber_q=param.Noise_Crest_Factor; | 7687 | ber_q=param.Noise_Crest_Factor; | ||
7895 | end | 7688 | end | ||
7896 | if OP.force_pdf_bin_size | 7689 | if OP.force_pdf_bin_size | ||
7897 | delta_y = OP.BinSize; | 7690 | delta_y = OP.BinSize; | ||
7898 | else | 7691 | else | ||
7899 | delta_y = min(A_s/1000, OP.BinSize); | 7692 | delta_y = min(A_s/1000, OP.BinSize); | ||
7900 | end | 7693 | end | ||
7901 | ne_noise_pdf = normal_dist(0, ber_q, delta_y); | 7694 | ne_noise_pdf = normal_dist(0, ber_q, delta_y); | ||
7902 | cci_pdf = normal_dist(0, ber_q, delta_y); | 7695 | cci_pdf = normal_dist(0, ber_q, delta_y); | ||
7903 | chdata(1).eq_pulse_response=sbr; | 7696 | chdata(1).eq_pulse_response=sbr; | ||
7904 | tmp_result.t_s= cursor_i; | 7697 | tmp_result.t_s= cursor_i; | ||
7905 | tmp_result.A_s=A_s; | 7698 | tmp_result.A_s=A_s; | ||
7906 | EH_1st= 2*(A_s-erfcinv(param.specBER*2)*2/sqrt(2)*total_noise_rms); | 7699 | EH_1st= 2*(A_s-erfcinv(param.specBER*2)*2/sqrt(2)*total_noise_rms); | ||
7907 | if EH_1st <= param.Min_VEO_Test/1000 -.001 | 7700 | if EH_1st <= param.Min_VEO_Test/1000 -.001 | ||
7908 | % sprintf( '%g.1 As .. %g.1 EH\n',A_s*1000,EH_1st*1000) | 7701 | % sprintf( '%g.1 As .. %g.1 EH\n',A_s*1000,EH_1st*1000) | ||
7909 | continue | 7702 | continue | ||
7910 | else | 7703 | else | ||
7911 | % sprintf( ' OK before %g As .. %g EH\n',A_s*1000,EH_1st*1000) | 7704 | % sprintf( ' OK before %g As .. %g EH\n',A_s*1000,EH_1st*1000) | ||
7912 | end | 7705 | end | ||
7913 | Struct_Noise.sigma_N=sigma_N; | 7706 | Struct_Noise.sigma_N=sigma_N; | ||
7914 | Struct_Noise.sigma_TX=sigma_TX; | 7707 | Struct_Noise.sigma_TX=sigma_TX; | ||
7915 | Struct_Noise.cci_pdf=cci_pdf; | 7708 | Struct_Noise.cci_pdf=cci_pdf; | ||
7916 | Struct_Noise.ber_q=ber_q; | 7709 | Struct_Noise.ber_q=ber_q; | ||
7917 | Struct_Noise.ne_noise_pdf=ne_noise_pdf; | 7710 | Struct_Noise.ne_noise_pdf=ne_noise_pdf; | ||
7918 | [Left_EW,Right_EW,eye_contour,EH_T_C2M,EH_B_C2M]=COM_eye_width(chdata,delta_y,tmp_result,param,OP,Struct_Noise,1); | 7711 | [Left_EW,Right_EW,eye_contour,EH_T_C2M,EH_B_C2M]=COM_eye_width(chdata,delta_y,tmp_result,param,OP,Struct_Noise,1); | ||
7919 | EH=EH_T_C2M-EH_B_C2M; | 7712 | EH=EH_T_C2M-EH_B_C2M; | ||
7920 | N_i=(A_s*2-EH)/2; | 7713 | N_i=(A_s*2-EH)/2; | ||
7921 | if EH <= param.Min_VEO_Test/1000 | 7714 | if EH <= param.Min_VEO_Test/1000 | ||
7922 | % sprintf( 'After As=%.1f .. EH=%.1f EH_1st=%.1f \n',A_s*1000,EH*1000, EH_1st*1000) | 7715 | % sprintf( 'After As=%.1f .. EH=%.1f EH_1st=%.1f \n',A_s*1000,EH*1000, EH_1st*1000) | ||
7923 | continue | 7716 | continue | ||
7924 | else | 7717 | else | ||
7925 | % sprintf( '<strong> After As=%.1f .. EH=%.1f EH_1st=%.1f </strong> \n',A_s*1000,EH*1000, EH_1st*1000) | 7718 | % sprintf( '<strong> After As=%.1f .. EH=%.1f EH_1st=%.1f </strong> \n',A_s*1000,EH*1000, EH_1st*1000) | ||
7926 | end | 7719 | end | ||
7927 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) % MMSE defines its own FOM | 7720 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) % MMSE defines its own FOM | ||
7928 | FOM =20*log10(A_s/N_i); | 7721 | FOM =20*log10(A_s/N_i); | ||
7929 | end | 7722 | end | ||
7930 | else | 7723 | else | ||
7931 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) % MMSE defines its own FOM | 7724 | if ~(strcmp(OP.FFE_OPT_METHOD,'MMSE') && OP.RxFFE) % MMSE defines its own FOM | ||
7932 | FOM = 20*log10(A_s/total_noise_rms); | 7725 | FOM = 20*log10(A_s/total_noise_rms); | ||
7933 | end | 7726 | end | ||
7934 | % if strfind(param.CTLE_type,'CL120e') | 7727 | % if strfind(param.CTLE_type,'CL120e') | ||
7935 | % FOM = A_s*C(param.RxFFE_cmx+1)-total_noise_rms_ffe; | 7728 | % FOM = A_s*C(param.RxFFE_cmx+1)-total_noise_rms_ffe; | ||
7936 | end | 7729 | end | ||
7937 | if 0 % for loop analysis | 7730 | if 0 % for loop analysis | ||
7938 | result.FOM_array(new_loops)=FOM; | 7731 | result.FOM_array(new_loops)=FOM; | ||
7939 | end | 7732 | end | ||
7940 |
| 7733 |
| ||
7941 | if FOM>best_itick_FOM | 7734 | if FOM>best_itick_FOM | ||
7942 | best_itick_FOM=FOM; | 7735 | best_itick_FOM=FOM; | ||
7943 | best_itick_in_cluster=itick; | 7736 | best_itick_in_cluster=itick; | ||
7944 | end | 7737 | end | ||
7945 |
| 7738 |
| ||
7946 | if itick>=0 && FOM>best_positive_itick_FOM | 7739 | if itick>=0 && FOM>best_positive_itick_FOM | ||
7947 | best_positive_itick_FOM=FOM; | 7740 | best_positive_itick_FOM=FOM; | ||
7948 | best_positive_itick_in_loop=itick; | 7741 | best_positive_itick_in_loop=itick; | ||
7949 | end | 7742 | end | ||
7950 | if itick<=0 && FOM>best_negative_itick_FOM | 7743 | if itick<=0 && FOM>best_negative_itick_FOM | ||
7951 | best_negative_itick_FOM=FOM; | 7744 | best_negative_itick_FOM=FOM; | ||
7952 | best_negative_itick_in_loop=itick; | 7745 | best_negative_itick_in_loop=itick; | ||
7953 | end | 7746 | end | ||
7954 |
| 7747 |
| ||
7955 | itick_index=find(itick==full_sample_range); | 7748 | itick_index=find(itick==full_sample_range); | ||
7956 | FOM_TRACKER(Gffe_index,ctle_index,g_LP_index,TK,itick_index)=FOM; | 7749 | FOM_TRACKER(Gffe_index,ctle_index,g_LP_index,TK,itick_index)=FOM; | ||
7957 |
| 7750 |
| ||
7958 | if (FOM > best_FOM) | 7751 | if (FOM > best_FOM) | ||
7959 | best_current_ffegain=param.current_ffegain; | 7752 | best_current_ffegain=param.current_ffegain; | ||
7960 | best_txffe = txffe; | 7753 | best_txffe = txffe; | ||
7961 | %along with best_txffe, save the indices of the best_txffe | 7754 | %along with best_txffe, save the indices of the best_txffe | ||
7962 | %(saves time in LOCAL SEARCH block) | 7755 | %(saves time in LOCAL SEARCH block) | ||
7963 | best_txffe_index=tx_index_vector; | 7756 | best_txffe_index=tx_index_vector; | ||
7964 | best_sbr = sbr; | 7757 | best_sbr = sbr; | ||
7965 | best_ctle = ctle_index; | 7758 | best_ctle = ctle_index; | ||
7966 | best_G_high_pass =g_LP_index; | 7759 | best_G_high_pass =g_LP_index; | ||
7967 | best_FOM = FOM; | 7760 | best_FOM = FOM; | ||
7968 | best_cursor_i = cursor_i; | 7761 | best_cursor_i = cursor_i; | ||
7969 | best_itick = itick; | 7762 | best_itick = itick; | ||
7970 | if ~OP.TDMODE | 7763 | if ~OP.TDMODE | ||
7971 | [ effective_channel ] = FFE( txffe , cur-1, param.samples_per_ui, chdata(1).ctle_imp_response ); | 7764 | [ effective_channel ] = FFE( txffe , cur-1, param.samples_per_ui, chdata(1).ctle_imp_response ); | ||
7972 | best_IR=effective_channel; | 7765 | best_IR=effective_channel; | ||
7973 | end | 7766 | end | ||
7974 | best_sigma_N = sigma_N; | 7767 | best_sigma_N = sigma_N; | ||
7975 | best_h_J = h_J; | 7768 | best_h_J = h_J; | ||
7976 | best_A_s=A_s; | 7769 | best_A_s=A_s; | ||
7977 | best_A_p=A_p; | 7770 | best_A_p=A_p; | ||
7978 | best_ISI=ISI_N; | 7771 | best_ISI=ISI_N; | ||
7979 | best_bmax=param.use_bmax; | 7772 | best_bmax=param.use_bmax; | ||
7980 | %AJG021820 | 7773 | %AJG021820 | ||
7981 | best_bmin=param.use_bmin; | 7774 | best_bmin=param.use_bmin; | ||
7982 | best_tail_RSS=tail_RSS; | 7775 | best_tail_RSS=tail_RSS; | ||
7983 | best_dfetaps=dfetaps; | 7776 | best_dfetaps=dfetaps; | ||
7984 | if param.Floating_DFE | 7777 | if param.Floating_DFE | ||
7985 | best_floating_tap_locations=floating_tap_locations; | 7778 | best_floating_tap_locations=floating_tap_locations; | ||
7986 | best_floating_tap_coef=floating_tap_coef; | 7779 | best_floating_tap_coef=floating_tap_coef; | ||
7987 | end | 7780 | end | ||
7988 | if param.Floating_RXFFE | 7781 | if param.Floating_RXFFE | ||
7989 | best_floating_tap_locations=floating_tap_locations; | 7782 | best_floating_tap_locations=floating_tap_locations; | ||
7990 | % best_floating_tap_coef=floating_tap_coef; | 7783 | % best_floating_tap_coef=floating_tap_coef; | ||
7991 | end | 7784 | end | ||
7992 | if OP.RxFFE | 7785 | if OP.RxFFE | ||
7993 | best_RxFFE=C; | 7786 | best_RxFFE=C; | ||
7994 | best_PSD_results=PSD_results; | 7787 | best_PSD_results=PSD_results; | ||
7995 | best_MMSE_results=MMSE_results; | 7788 | best_MMSE_results=MMSE_results; | ||
7996 | end | 7789 | end | ||
7997 | end | 7790 | end | ||
7998 | end | 7791 | end | ||
7999 | end | 7792 | end | ||
8000 |
| 7793 |
| ||
8001 | end | 7794 | end | ||
8002 | end | 7795 | end | ||
8003 | end | 7796 | end | ||
8004 | if do_C2M | 7797 | if do_C2M | ||
8005 | if best_FOM == -inf | 7798 | if best_FOM == -inf | ||
8006 | param.Min_VEO_Test=0; | 7799 | param.Min_VEO_Test=0; | ||
8007 | else | 7800 | else | ||
8008 | break | 7801 | break | ||
8009 | end | 7802 | end | ||
8010 | end | 7803 | end | ||
8011 | end | 7804 | end | ||
8012 | if 0 | 7805 | if 0 | ||
8013 | fprintf('old loops = %d\n',old_loops); | 7806 | fprintf('old loops = %d\n',old_loops); | ||
8014 | fprintf('new loops = %d\n',new_loops); | 7807 | fprintf('new loops = %d\n',new_loops); | ||
8015 | display(sprintf('\n :loops = %g',pxi)) | 7808 | display(sprintf('\n :loops = %g',pxi)) | ||
8016 | end | 7809 | end | ||
8017 | 7810 | ||||
8018 | %turn this on to review if FOM changes sign more than once in an itick loop | 7811 | %turn this on to review if FOM changes sign more than once in an itick loop | ||
8019 | if 0 | 7812 | if 0 | ||
8020 | DIR_CHANGE={}; | 7813 | DIR_CHANGE={}; | ||
8021 | for m=1:length(Gffe_values) | 7814 | for m=1:length(Gffe_values) | ||
8022 | for n=1:length(gdc_values) | 7815 | for n=1:length(gdc_values) | ||
8023 | for k=1:lf_indx | 7816 | for k=1:lf_indx | ||
8024 | FOM_this_mat=squeeze(FOM_TRACKER(m,n,k,:,:)); | 7817 | FOM_this_mat=squeeze(FOM_TRACKER(m,n,k,:,:)); | ||
8025 | %x reveals if FOM on a particular row (locked txffe, moving itick) goes up or down | 7818 | %x reveals if FOM on a particular row (locked txffe, moving itick) goes up or down | ||
8026 | %1 = goes up, -1=goes down | 7819 | %1 = goes up, -1=goes down | ||
8027 | x=sign(diff(FOM_this_mat')'); | 7820 | x=sign(diff(FOM_this_mat')'); | ||
8028 | %y = change in sign on x. the location of a "2" is where FOM changes direction | 7821 | %y = change in sign on x. the location of a "2" is where FOM changes direction | ||
8029 | y=abs(diff(x'))'; | 7822 | y=abs(diff(x'))'; | ||
8030 | %the goal is the FOM only changes direction once. so count the occurences of the 2 | 7823 | %the goal is the FOM only changes direction once. so count the occurences of the 2 | ||
8031 | for j=1:size(FOM_this_mat,1) | 7824 | for j=1:size(FOM_this_mat,1) | ||
8032 | z{j}=find(y(j,:)==2); | 7825 | z{j}=find(y(j,:)==2); | ||
8033 | end | 7826 | end | ||
8034 | zL=cellfun('length',z); | 7827 | zL=cellfun('length',z); | ||
8035 | %return any row where FOM changed direction more than once | 7828 | %return any row where FOM changed direction more than once | ||
8036 | DIR_CHANGE{j,k}=find(zL>1); | 7829 | DIR_CHANGE{j,k}=find(zL>1); | ||
8037 | end | 7830 | end | ||
8038 | end | 7831 | end | ||
8039 | end | 7832 | end | ||
8040 | multi_direction_change=find(~cellfun('isempty',DIR_CHANGE)) | 7833 | multi_direction_change=find(~cellfun('isempty',DIR_CHANGE)) | ||
8041 | end | 7834 | end | ||
8042 | 7835 | ||||
8043 | if ~exist('best_cursor_i', 'var')% take last setting | 7836 | if ~exist('best_cursor_i', 'var')% take last setting | ||
8044 | result.eq_failed=true; | 7837 | result.eq_failed=true; | ||
8045 | display('equalization failed') | 7838 | display('equalization failed') | ||
8046 | best_bmax=param.bmax; | 7839 | best_bmax=param.bmax; | ||
8047 | %AJG021820 | 7840 | %AJG021820 | ||
8048 | best_bmin=param.bmin; | 7841 | best_bmin=param.bmin; | ||
8049 | best_tail_RSS=0; | 7842 | best_tail_RSS=0; | ||
8050 | best_current_ffegain=0; | 7843 | best_current_ffegain=0; | ||
8051 | best_txffe = txffe; | 7844 | best_txffe = txffe; | ||
8052 | best_sbr = sbr; | 7845 | best_sbr = sbr; | ||
8053 | best_ctle = ctle_index; | 7846 | best_ctle = ctle_index; | ||
8054 | if OP.RxFFE | 7847 | if OP.RxFFE | ||
8055 | best_PSD_results=PSD_results; | 7848 | best_PSD_results=PSD_results; | ||
8056 | best_MMSE_results=MMSE_results; | 7849 | best_MMSE_results=MMSE_results; | ||
8057 | best_RxFFE=C; | 7850 | best_RxFFE=C; | ||
8058 | end | 7851 | end | ||
8059 | best_G_high_pass =g_LP_index; | 7852 | best_G_high_pass =g_LP_index; | ||
8060 | best_FOM = FOM; | 7853 | best_FOM = FOM; | ||
8061 | %if this block is reached, the last encountered EQ parameters are used | 7854 | %if this block is reached, the last encountered EQ parameters are used | ||
8062 | %if it so happened that there was no zero crossing in the last encountered EQ set, then cursor_i will be empty | 7855 | %if it so happened that there was no zero crossing in the last encountered EQ set, then cursor_i will be empty | ||
8063 | %EQ search has failed, so it is not important to give an exact sample location, so just use the peak of the pulse | 7856 | %EQ search has failed, so it is not important to give an exact sample location, so just use the peak of the pulse | ||
8064 | if isempty(cursor_i) | 7857 | if isempty(cursor_i) | ||
8065 | [~,cursor_i]=max(sbr); | 7858 | [~,cursor_i]=max(sbr); | ||
8066 | end | 7859 | end | ||
8067 | best_cursor_i = cursor_i; | 7860 | best_cursor_i = cursor_i; | ||
8068 | best_itick = itick; | 7861 | best_itick = itick; | ||
8069 | if ~OP.TDMODE | 7862 | if ~OP.TDMODE | ||
8070 | [ effective_channel ] = FFE( txffe , cur-1, param.samples_per_ui, chdata(1).ctle_imp_response ); | 7863 | [ effective_channel ] = FFE( txffe , cur-1, param.samples_per_ui, chdata(1).ctle_imp_response ); | ||
8071 | best_IR=effective_channel; | 7864 | best_IR=effective_channel; | ||
8072 | end | 7865 | end | ||
8073 | best_sigma_N = sigma_N; | 7866 | best_sigma_N = sigma_N; | ||
8074 | best_h_J = h_J; | 7867 | best_h_J = h_J; | ||
8075 | best_A_p=max(sbr); | 7868 | best_A_p=max(sbr); | ||
8076 | best_ISI=1; | 7869 | best_ISI=1; | ||
8077 | best_dfetaps= sbr( cursor_i+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe))/sbr(cursor_i) ; | 7870 | best_dfetaps= sbr( cursor_i+param.samples_per_ui*(1):param.samples_per_ui:cursor_i+param.samples_per_ui*(param.ndfe))/sbr(cursor_i) ; | ||
8078 | best_A_s= sbr( cursor_i); | 7871 | best_A_s= sbr( cursor_i); | ||
8079 | if param.Floating_DFE | 7872 | if param.Floating_DFE | ||
8080 | best_floating_tap_locations=[]; | 7873 | best_floating_tap_locations=[]; | ||
8081 | best_floating_tap_coef=[]; | 7874 | best_floating_tap_coef=[]; | ||
8082 | end | 7875 | end | ||
8083 | if do_C2M | 7876 | if do_C2M | ||
8084 | return | 7877 | return | ||
8085 | end | 7878 | end | ||
8086 | % return | 7879 | % return | ||
8087 | else | 7880 | else | ||
8088 | result.eq_failed=false; % RIM 12/30/2023 | 7881 | result.eq_failed=false; % RIM 12/30/2023 | ||
8089 | end | 7882 | end | ||
8090 | 7883 | ||||
8091 | best_cursor = best_sbr(best_cursor_i); | 7884 | best_cursor = best_sbr(best_cursor_i); | ||
8092 | % report during debug | 7885 | % report during debug | ||
8093 | PRin=filter(ones(param.samples_per_ui, 1),1, chdata(1).uneq_imp_response); | 7886 | PRin=filter(ones(param.samples_per_ui, 1),1, chdata(1).uneq_imp_response); | ||
8094 | %If sbr was zero padded, then PRin needs to do so as well) | 7887 | %If sbr was zero padded, then PRin needs to do so as well) | ||
8095 | if length(PRin)<length(best_sbr) | 7888 | if length(PRin)<length(best_sbr) | ||
8096 | PRin(end+1:length(best_sbr))=0; | 7889 | PRin(end+1:length(best_sbr))=0; | ||
8097 | end | 7890 | end | ||
8098 | f=1e8:1e8:100e9; | 7891 | f=1e8:1e8:100e9; | ||
8099 | 7892 | ||||
8100 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | 7893 | H_bt=Bessel_Thomson_Filter(param,f,OP.Bessel_Thomson); | ||
8101 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | 7894 | H_bw=Butterworth_Filter(param,f,OP.Butterworth); | ||
8102 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine);% experiment with RCos | 7895 | H_RCos=Raised_Cosine_Filter(param,f,OP.Raised_Cosine);% experiment with RCos | ||
8103 | % need to include H_RCos in noise and when computing the system ir for thru | 7896 | % need to include H_RCos in noise and when computing the system ir for thru | ||
8104 | % and crosstalk | 7897 | % and crosstalk | ||
8105 | H_r=H_bw.*H_bt.*H_RCos; | 7898 | H_r=H_bw.*H_bt.*H_RCos; | ||
8106 | 7899 | ||||
8107 | ctle_gain1 = (10^(gdc_values(best_ctle)/20) + 1i*f/param.CTLE_fz(best_ctle)) ./ ... | 7900 | ctle_gain1 = (10^(gdc_values(best_ctle)/20) + 1i*f/param.CTLE_fz(best_ctle)) ./ ... | ||
8108 | ((1+1i*f/param.CTLE_fp1(best_ctle)).*(1+1i*f/param.CTLE_fp2(best_ctle))); | 7901 | ((1+1i*f/param.CTLE_fp1(best_ctle)).*(1+1i*f/param.CTLE_fp2(best_ctle))); | ||
8109 | 7902 | ||||
8110 | switch param.CTLE_type | 7903 | switch param.CTLE_type | ||
8111 | case 'CL93' | 7904 | case 'CL93' | ||
8112 | H_low=1; | 7905 | H_low=1; | ||
8113 | case 'CL120d' | 7906 | case 'CL120d' | ||
8114 | H_low=(10^(param.g_DC_HP_values(best_G_high_pass)/20) + 1i*f/param.f_HP(best_G_high_pass))./(1 + 1i*f/param.f_HP(best_G_high_pass)); | 7907 | H_low=(10^(param.g_DC_HP_values(best_G_high_pass)/20) + 1i*f/param.f_HP(best_G_high_pass))./(1 + 1i*f/param.f_HP(best_G_high_pass)); | ||
8115 | case 'CL120e' | 7908 | case 'CL120e' | ||
8116 | H_low=(1 + 1i*f/param.f_HP_Z(best_ctle))./ (1 + 1i*f/param.f_HP_P(best_ctle)); | 7909 | H_low=(1 + 1i*f/param.f_HP_Z(best_ctle))./ (1 + 1i*f/param.f_HP_P(best_ctle)); | ||
8117 | end | 7910 | end | ||
8118 | ctle_gain=H_low.*ctle_gain1.*H_r; | 7911 | ctle_gain=H_low.*ctle_gain1.*H_r; | ||
8119 | 7912 | ||||
8120 | 7913 | ||||
8121 | 7914 | ||||
8122 | %lsbr=length(sbr); | 7915 | %lsbr=length(sbr); | ||
8123 | %use length of best_sbr in case zero padding was performed | 7916 | %use length of best_sbr in case zero padding was performed | ||
8124 | %check "sbr_required_length" variable | 7917 | %check "sbr_required_length" variable | ||
8125 | lsbr=length(best_sbr); | 7918 | lsbr=length(best_sbr); | ||
8126 | t=0:param.ui/param.samples_per_ui:(lsbr-1)*param.ui/param.samples_per_ui; | 7919 | t=0:param.ui/param.samples_per_ui:(lsbr-1)*param.ui/param.samples_per_ui; | ||
8127 | 7920 | ||||
8128 | sampled_best_sbr_precursors_t = (best_cursor_i/param.samples_per_ui:-1:1/param.samples_per_ui)*param.ui; | 7921 | sampled_best_sbr_precursors_t = (best_cursor_i/param.samples_per_ui:-1:1/param.samples_per_ui)*param.ui; | ||
8129 | sampled_best_sbr_precursors_t = sampled_best_sbr_precursors_t(end:-1:2); % exclude cursor | 7922 | sampled_best_sbr_precursors_t = sampled_best_sbr_precursors_t(end:-1:2); % exclude cursor | ||
8130 | sampled_best_sbr_precursors = best_sbr(round(sampled_best_sbr_precursors_t/param.ui*param.samples_per_ui)); | 7923 | sampled_best_sbr_precursors = best_sbr(round(sampled_best_sbr_precursors_t/param.ui*param.samples_per_ui)); | ||
8131 | sampled_best_sbr_postcursors_t = (best_cursor_i:param.samples_per_ui:lsbr)/param.samples_per_ui*param.ui; | 7924 | sampled_best_sbr_postcursors_t = (best_cursor_i:param.samples_per_ui:lsbr)/param.samples_per_ui*param.ui; | ||
8132 | sampled_best_sbr_postcursors_t = sampled_best_sbr_postcursors_t(2:end); % exclude cursor | 7925 | sampled_best_sbr_postcursors_t = sampled_best_sbr_postcursors_t(2:end); % exclude cursor | ||
8133 | sampled_best_sbr_postcursors = best_sbr(round(sampled_best_sbr_postcursors_t/param.ui*param.samples_per_ui)); | 7926 | sampled_best_sbr_postcursors = best_sbr(round(sampled_best_sbr_postcursors_t/param.ui*param.samples_per_ui)); | ||
8134 | sampled_best_sbr_dfecursors_t = (best_cursor_i/param.samples_per_ui+(1:param.ndfe_passed))*param.ui; | 7927 | sampled_best_sbr_dfecursors_t = (best_cursor_i/param.samples_per_ui+(1:param.ndfe_passed))*param.ui; | ||
8135 | if param.Floating_DFE | 7928 | if param.Floating_DFE | ||
8136 | sampled_best_sbr_fdfecursors_t = (best_cursor_i/param.samples_per_ui+(best_floating_tap_locations))*param.ui; | 7929 | sampled_best_sbr_fdfecursors_t = (best_cursor_i/param.samples_per_ui+(best_floating_tap_locations))*param.ui; | ||
8137 | end | 7930 | end | ||
8138 | % apply max tap value constraint | 7931 | % apply max tap value constraint | ||
8139 | dfe_cursors = sampled_best_sbr_postcursors(1:param.ndfe); | 7932 | dfe_cursors = sampled_best_sbr_postcursors(1:param.ndfe); | ||
8140 | dfe_SBRcursors = sampled_best_sbr_postcursors(1:param.ndfe); | 7933 | dfe_SBRcursors = sampled_best_sbr_postcursors(1:param.ndfe); | ||
8141 | if isrow(best_bmax) == 1, best_bmax=best_bmax.';end | 7934 | if isrow(best_bmax) == 1, best_bmax=best_bmax.';end | ||
8142 | 7935 | ||||
8143 | %AJG021820 | 7936 | %AJG021820 | ||
8144 | if isrow(best_bmin) == 1, best_bmin=best_bmin.';end | 7937 | if isrow(best_bmin) == 1, best_bmin=best_bmin.';end | ||
8145 | DFE_taps_mV=dfe_clipper(dfe_cursors,best_cursor*best_bmax(1:param.ndfe),best_cursor*best_bmin(1:param.ndfe)); | 7938 | DFE_taps_mV=dfe_clipper(dfe_cursors,best_cursor*best_bmax(1:param.ndfe),best_cursor*best_bmin(1:param.ndfe)); | ||
8146 | if param.Floating_DFE | 7939 | if param.Floating_DFE | ||
8147 | FDFE_taps_mV=DFE_taps_mV(best_floating_tap_locations); | 7940 | FDFE_taps_mV=DFE_taps_mV(best_floating_tap_locations); | ||
8148 | end | 7941 | end | ||
8149 | 7942 | ||||
8150 | sampled_best_sbr_postcursors(1:param.ndfe) = dfe_SBRcursors-DFE_taps_mV; | 7943 | sampled_best_sbr_postcursors(1:param.ndfe) = dfe_SBRcursors-DFE_taps_mV; | ||
8151 | Symbol_Adj = (param.levels-1);% 3A.1.6 | 7944 | Symbol_Adj = (param.levels-1);% 3A.1.6 | ||
8152 | if OP.DEBUG ~=0 | 7945 | if OP.DEBUG ~=0 | ||
8153 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | 7946 | if OP.DISPLAY_WINDOW && ~OP.RX_CALIBRATION | ||
8154 | % display pulse responses in one axis per test case. | 7947 | % display pulse responses in one axis per test case. | ||
8155 | switch upper(OP.TIME_AXIS) | 7948 | switch upper(OP.TIME_AXIS) | ||
8156 | case 'S' % RIM 11-13-2023 added user selectable xaxis | 7949 | case 'S' % RIM 11-13-2023 added user selectable xaxis | ||
8157 | xnorm=1; | 7950 | xnorm=1; | ||
8158 | xaxis_label='seconds'; | 7951 | xaxis_label='seconds'; | ||
8159 | offset=0; | 7952 | offset=0; | ||
8160 | case 'UI' | 7953 | case 'UI' | ||
8161 | xnorm=param.ui; | 7954 | xnorm=param.ui; | ||
8162 | xaxis_label='UI'; | 7955 | xaxis_label='UI'; | ||
8163 | offset=t(best_cursor_i)/xnorm; | 7956 | offset=t(best_cursor_i)/xnorm; | ||
8164 | otherwise | 7957 | otherwise | ||
8165 | xnorm=1; | 7958 | xnorm=1; | ||
8166 | xaxis_label='seconds'; | 7959 | xaxis_label='seconds'; | ||
8167 | offset=0; | 7960 | offset=0; | ||
8168 | end | 7961 | end | ||
8169 | figure_name = sprintf('PKG %d: Equalization effect: %s : ', OP.pkg_len_select( param.package_testcase_i), param.base); | 7962 | figure_name = sprintf('PKG %d: Equalization effect: %s : ', OP.pkg_len_select( param.package_testcase_i), param.base); | ||
8170 | fig=findobj('Name', figure_name); | 7963 | fig=findobj('Name', figure_name); | ||
8171 | if isempty(fig), fig=figure('Name', figure_name); end | 7964 | if isempty(fig), fig=figure('Name', figure_name); end | ||
8172 | figure(fig);set(gcf,'Tag','COM'); | 7965 | figure(fig);set(gcf,'Tag','COM'); | ||
8173 | movegui(fig,'north') | 7966 | movegui(fig,'north') | ||
8174 | %figure(fig.Number); | 7967 | %figure(fig.Number); | ||
8175 | % hax = subplot(length(OP.pkg_len_select), 1, param.package_testcase_i); | 7968 | % hax = subplot(length(OP.pkg_len_select), 1, param.package_testcase_i); | ||
8176 | if OP.RxFFE | 7969 | if OP.RxFFE | ||
8177 | ax1=subplot(2,1,1); | 7970 | ax1=subplot(2,1,1); | ||
8178 | end | 7971 | end | ||
8179 | plot(t/xnorm-offset,best_sbr/Symbol_Adj,'disp', '1/2 Symbol 0-3 Equalized PR'); | 7972 | plot(t/xnorm-offset,best_sbr/Symbol_Adj,'disp', '1/2 Symbol 0-3 Equalized PR'); | ||
8180 | hold on | 7973 | hold on | ||
8181 |
| 7974 |
| ||
8182 | PRplt(1:param.samples_per_ui+5)=PRin(1); % line up with the ffe introduced delay | 7975 | PRplt(1:param.samples_per_ui+5)=PRin(1); % line up with the ffe introduced delay | ||
8183 | PRplt(param.samples_per_ui+6:length(t))=PRin(1:length(t)-param.samples_per_ui-5); | 7976 | PRplt(param.samples_per_ui+6:length(t))=PRin(1:length(t)-param.samples_per_ui-5); | ||
8184 | plot((t-param.ui-t(6))/xnorm-offset,PRplt/Symbol_Adj,'r','disp', '1/2 Symbol 0-3 Unequalized (tp5d) PR'); | 7977 | plot((t-param.ui-t(6))/xnorm-offset,PRplt/Symbol_Adj,'r','disp', '1/2 Symbol 0-3 Unequalized (tp5d) PR'); | ||
8185 | stem(t(best_cursor_i)/xnorm-offset,best_sbr(best_cursor_i)/Symbol_Adj,'g','disp','Cursor (sample point)'); | 7978 | stem(t(best_cursor_i)/xnorm-offset,best_sbr(best_cursor_i)/Symbol_Adj,'g','disp','Cursor (sample point)'); | ||
8186 | title(sprintf('PKG Case %d', OP.pkg_len_select( param.package_testcase_i))); | 7979 | title(sprintf('PKG Case %d', OP.pkg_len_select( param.package_testcase_i))); | ||
8187 | ylabel('volts') | 7980 | ylabel('volts') | ||
8188 | xlabel(xaxis_label) | 7981 | xlabel(xaxis_label) | ||
8189 | grid on | 7982 | grid on | ||
8190 | legend show | 7983 | legend show | ||
8191 | legend( 'Location', 'best') | 7984 | legend( 'Location', 'best') | ||
8192 | plot((sampled_best_sbr_precursors_t-param.ui/param.samples_per_ui)/xnorm-offset, sampled_best_sbr_precursors'/Symbol_Adj, 'kx', 'disp','Pre cursors'); | 7985 | plot((sampled_best_sbr_precursors_t-param.ui/param.samples_per_ui)/xnorm-offset, sampled_best_sbr_precursors'/Symbol_Adj, 'kx', 'disp','Pre cursors'); | ||
8193 | plot((sampled_best_sbr_postcursors_t-param.ui/param.samples_per_ui)/xnorm-offset, sampled_best_sbr_postcursors'/Symbol_Adj, 'ko', 'disp','Post cursors'); | 7986 | plot((sampled_best_sbr_postcursors_t-param.ui/param.samples_per_ui)/xnorm-offset, sampled_best_sbr_postcursors'/Symbol_Adj, 'ko', 'disp','Post cursors'); | ||
8194 | if param.ndfe_passed ~=0 | 7987 | if param.ndfe_passed ~=0 | ||
8195 | stem((sampled_best_sbr_dfecursors_t-param.ui/param.samples_per_ui)/xnorm-offset,DFE_taps_mV(1:param.ndfe_passed)/Symbol_Adj','m', 'LineWidth',2,'disp','DFE-canceled cursors'); | 7988 | stem((sampled_best_sbr_dfecursors_t-param.ui/param.samples_per_ui)/xnorm-offset,DFE_taps_mV(1:param.ndfe_passed)/Symbol_Adj','m', 'LineWidth',2,'disp','DFE-canceled cursors'); | ||
8196 | end | 7989 | end | ||
8197 | if param.Floating_DFE | 7990 | if param.Floating_DFE | ||
8198 | stem((sampled_best_sbr_fdfecursors_t-param.ui/param.samples_per_ui)/xnorm-offset,FDFE_taps_mV/Symbol_Adj, 'MarkerFaceColor','red','MarkerEdgeColor','m','LineWidth',1,'disp','FDFE-canceled cursors'); | 7991 | stem((sampled_best_sbr_fdfecursors_t-param.ui/param.samples_per_ui)/xnorm-offset,FDFE_taps_mV/Symbol_Adj, 'MarkerFaceColor','red','MarkerEdgeColor','m','LineWidth',1,'disp','FDFE-canceled cursors'); | ||
8199 | end | 7992 | end | ||
8200 | if OP.RxFFE | 7993 | if OP.RxFFE | ||
8201 | ax2=subplot(2,1,2); | 7994 | ax2=subplot(2,1,2); | ||
8202 | if param.Floating_RXFFE | 7995 | if param.Floating_RXFFE | ||
8203 | stem((t(best_cursor_i+(best_floating_tap_locations)*param.samples_per_ui))/xnorm-offset,best_RxFFE(best_floating_tap_locations)... | 7996 | stem((t(best_cursor_i+(best_floating_tap_locations)*param.samples_per_ui))/xnorm-offset,best_RxFFE(best_floating_tap_locations)... | ||
8204 | ,'filled','disp','RxFFE floating FFE taps') | 7997 | ,'filled','disp','RxFFE floating FFE taps') | ||
8205 | hold on | 7998 | hold on | ||
8206 | end | 7999 | end | ||
8207 | stem((t(best_cursor_i+param.samples_per_ui*(-param.RxFFE_cmx:param.RxFFE_cpx)))/xnorm-offset,best_RxFFE(1:param.RxFFE_cmx+param.RxFFE_cpx+1)... | 8000 | stem((t(best_cursor_i+param.samples_per_ui*(-param.RxFFE_cmx:param.RxFFE_cpx)))/xnorm-offset,best_RxFFE(1:param.RxFFE_cmx+param.RxFFE_cpx+1)... | ||
8208 | ,'filled','disp','RxFFE fixted FFE taps') | 8001 | ,'filled','disp','RxFFE fixted FFE taps') | ||
8209 | legend show | 8002 | legend show | ||
8210 | zoom xon | 8003 | zoom xon | ||
8211 | linkaxes([ax1 ax2],'x') | 8004 | linkaxes([ax1 ax2],'x') | ||
8212 | end | 8005 | end | ||
8213 | 8006 | ||||
8214 | 8007 | ||||
8215 | grid on | 8008 | grid on | ||
8216 | legend show | 8009 | legend show | ||
8217 | legend( 'Location', 'best') | 8010 | legend( 'Location', 'best') | ||
8218 | zoom xon | 8011 | zoom xon | ||
8219 | % set(hax, 'tag', 'EQE'); | 8012 | % set(hax, 'tag', 'EQE'); | ||
8220 | % | 8013 | % | ||
8221 | figure(110);set(gcf,'Tag','COM'); | 8014 | figure(110);set(gcf,'Tag','COM'); | ||
8222 | set(gcf, 'Name', 'CTLE selection'); | 8015 | set(gcf, 'Name', 'CTLE selection'); | ||
8223 | movegui(gcf, 'southeast'); | 8016 | movegui(gcf, 'southeast'); | ||
8224 | semilogx(f,20*log10(abs(ctle_gain)), 'disp', sprintf('Case %d', param.package_testcase_i)); | 8017 | semilogx(f,20*log10(abs(ctle_gain)), 'disp', sprintf('Case %d', param.package_testcase_i)); | ||
8225 | hold on | 8018 | hold on | ||
8226 | semilogx(f,20*log10(abs(H_r)), 'disp', sprintf('Rx filter Case %d', param.package_testcase_i)); | 8019 | semilogx(f,20*log10(abs(H_r)), 'disp', sprintf('Rx filter Case %d', param.package_testcase_i)); | ||
8227 | semilogx(f,20*log10(abs(H_low.*ctle_gain1)), 'disp', sprintf('CTF Case %d', param.package_testcase_i)); | 8020 | semilogx(f,20*log10(abs(H_low.*ctle_gain1)), 'disp', sprintf('CTF Case %d', param.package_testcase_i)); | ||
8228 | fbaud_tick=find(f >= baud_rate, 1); | 8021 | fbaud_tick=find(f >= baud_rate, 1); | ||
8229 | fnq_tick=find(f >= baud_rate/2, 1); | 8022 | fnq_tick=find(f >= baud_rate/2, 1); | ||
8230 | stem(f(fnq_tick),20*log10(abs(ctle_gain(fnq_tick))),'g', 'handlevisibility', 'off'); | 8023 | stem(f(fnq_tick),20*log10(abs(ctle_gain(fnq_tick))),'g', 'handlevisibility', 'off'); | ||
8231 | stem(f(fbaud_tick),20*log10(abs(ctle_gain(fbaud_tick))),'g', 'handlevisibility', 'off'); | 8024 | stem(f(fbaud_tick),20*log10(abs(ctle_gain(fbaud_tick))),'g', 'handlevisibility', 'off'); | ||
8232 | recolor_plots(gca); | 8025 | recolor_plots(gca); | ||
8233 | title('CTF/w Rx Filter Response') | 8026 | title('CTF/w Rx Filter Response') | ||
8234 | ylabel('dB') | 8027 | ylabel('dB') | ||
8235 | xlabel('Hz') | 8028 | xlabel('Hz') | ||
8236 | legend show | 8029 | legend show | ||
8237 | end | 8030 | end | ||
8238 | display(['FOM: ' ,num2str(best_FOM, 2),' dB']); | 8031 | display(['FOM: ' ,num2str(best_FOM, 2),' dB']); | ||
8239 | display(['TXFFE coefficients: ' ,mat2str(best_txffe) ] ); | 8032 | display(['TXFFE coefficients: ' ,mat2str(best_txffe) ] ); | ||
8240 | display(['SNR ISI: ' ,num2str(20*log10(best_A_p/best_ISI), 2),' dB']); | 8033 | display(['SNR ISI: ' ,num2str(20*log10(best_A_p/best_ISI), 2),' dB']); | ||
8241 | display(['CTLE DC gain: ' ,num2str(gdc_values(best_ctle)), ' dB']); | 8034 | display(['CTLE DC gain: ' ,num2str(gdc_values(best_ctle)), ' dB']); | ||
8242 | display(['CTF peaking gain: ' ,num2str(20*log10(max(abs(ctle_gain))), 2), ' dB']); | 8035 | display(['CTF peaking gain: ' ,num2str(20*log10(max(abs(ctle_gain))), 2), ' dB']); | ||
8243 | display(['Symbol Available signal: ' ,num2str(best_cursor/Symbol_Adj)]); | 8036 | display(['Symbol Available signal: ' ,num2str(best_cursor/Symbol_Adj)]); | ||
8244 | end | 8037 | end | ||
8245 | if OP.DEBUG && OP.DISPLAY_WINDOW && OP.RX_CALIBRATION==0 | 8038 | if OP.DEBUG && OP.DISPLAY_WINDOW && OP.RX_CALIBRATION==0 | ||
8246 | eqe_axes = findobj('tag', 'EQE'); | 8039 | eqe_axes = findobj('tag', 'EQE'); | ||
8247 | if ~isempty(eqe_axes), linkaxes(eqe_axes, 'xy'); end | 8040 | if ~isempty(eqe_axes), linkaxes(eqe_axes, 'xy'); end | ||
8248 | end | 8041 | end | ||
8249 | if OP.DISPLAY_WINDOW | 8042 | if OP.DISPLAY_WINDOW | ||
8250 | close(hwaitbar); | 8043 | close(hwaitbar); | ||
8251 | else | 8044 | else | ||
8252 | fprintf('\n'); | 8045 | fprintf('\n'); | ||
8253 | end | 8046 | end | ||
8254 | 8047 | ||||
8255 | % % eq_data | 8048 | % % eq_data | ||
8256 | result.cur=cur; | 8049 | result.cur=cur; | ||
8257 | result.txffe = best_txffe; | 8050 | result.txffe = best_txffe; | ||
8258 | result.ctle = best_ctle; | 8051 | result.ctle = best_ctle; | ||
8259 | result.best_G_high_pass=best_G_high_pass; | 8052 | result.best_G_high_pass=best_G_high_pass; | ||
8260 | result.DFE_taps = best_dfetaps; %relative | 8053 | result.DFE_taps = best_dfetaps; %relative | ||
8261 | result.DFE_taps_i = best_cursor_i+(1:param.ndfe)*param.samples_per_ui; | 8054 | result.DFE_taps_i = best_cursor_i+(1:param.ndfe)*param.samples_per_ui; | ||
8262 | if param.Floating_DFE | 8055 | if param.Floating_DFE | ||
8263 | result.floating_tap_locations=best_floating_tap_locations; | 8056 | result.floating_tap_locations=best_floating_tap_locations; | ||
8264 | result.floating_tap_coef=best_floating_tap_coef; | 8057 | result.floating_tap_coef=best_floating_tap_coef; | ||
8265 | end | 8058 | end | ||
8266 | if param.Floating_RXFFE | 8059 | if param.Floating_RXFFE | ||
8267 | result.floating_tap_locations=best_floating_tap_locations; | 8060 | result.floating_tap_locations=best_floating_tap_locations; | ||
8268 | end | 8061 | end | ||
8269 | result.A_s = best_A_s; | 8062 | result.A_s = best_A_s; | ||
8270 | result.t_s = best_cursor_i; | 8063 | result.t_s = best_cursor_i; | ||
8271 | result.itick = best_itick; | 8064 | result.itick = best_itick; | ||
8272 | result.sigma_N = best_sigma_N; | 8065 | result.sigma_N = best_sigma_N; | ||
8273 | result.h_J = best_h_J; | 8066 | result.h_J = best_h_J; | ||
8274 | result.FOM = best_FOM; | 8067 | result.FOM = best_FOM; | ||
8275 | if ~OP.TDMODE | 8068 | if ~OP.TDMODE | ||
8276 | %If sbr was zero padded, then best_IR needs to do so as well) | 8069 | %If sbr was zero padded, then best_IR needs to do so as well) | ||
8277 | if length(best_IR)<length(best_sbr) | 8070 | if length(best_IR)<length(best_sbr) | ||
8278 | best_IR(end+1:length(best_sbr))=0; | 8071 | best_IR(end+1:length(best_sbr))=0; | ||
8279 | end | 8072 | end | ||
8280 | result.IR = best_IR; | 8073 | result.IR = best_IR; | ||
8281 | end | 8074 | end | ||
8282 | result.t=t; | 8075 | result.t=t; | ||
8283 | result.sbr=best_sbr; | 8076 | result.sbr=best_sbr; | ||
8284 | if OP.RxFFE | 8077 | if OP.RxFFE | ||
8285 | result.RxFFE=best_RxFFE; | 8078 | result.RxFFE=best_RxFFE; | ||
− | 8286 | if strcmp(OP.FFE_OPT_METHOD,'MMSE') |
| ||
≠ | 8287 | result.PSD_results=best_PSD_results; | ≠ | 8079 | result.PSD_results=best_PSD_results; |
≠ | 8288 | result.MMSE_results=best_MMSE_results; | ≠ | 8080 | result.MMSE_results=best_MMSE_results; |
− | 8289 | end |
| ||
8290 | end | 8081 | end | ||
8291 | 8082 | ||||
8292 | 8083 | ||||
8293 | 8084 | ||||
8294 | % changed RIM 4/17/2019 use sum(IR) for Vf of originl IR at N_b UI | 8085 | % changed RIM 4/17/2019 use sum(IR) for Vf of originl IR at N_b UI | ||
8295 | % updated RIM 12/17/2021 | 8086 | % updated RIM 12/17/2021 | ||
8296 | result.A_p = max(chdata(1).uneq_pulse_response); | 8087 | result.A_p = max(chdata(1).uneq_pulse_response); | ||
8297 | its=find(chdata(1).uneq_pulse_response>=max(chdata(1).uneq_pulse_response),1,'first'); | 8088 | its=find(chdata(1).uneq_pulse_response>=max(chdata(1).uneq_pulse_response),1,'first'); | ||
8298 | PR=chdata(1).uneq_pulse_response; | 8089 | PR=chdata(1).uneq_pulse_response; | ||
8299 | iend = its+param.N_v*param.samples_per_ui-param.samples_per_ui/2; % from eq: 163A-3 | 8090 | iend = its+param.N_v*param.samples_per_ui-param.samples_per_ui/2; % from eq: 163A-3 | ||
8300 | ibeg= its-param.D_p*param.samples_per_ui-param.samples_per_ui/2;% from eq: 163A-3 | 8091 | ibeg= its-param.D_p*param.samples_per_ui-param.samples_per_ui/2;% from eq: 163A-3 | ||
8301 | if iend >= length(PR) | 8092 | if iend >= length(PR) | ||
8302 | iend = length (PR); | 8093 | iend = length (PR); | ||
8303 | end | 8094 | end | ||
8304 | if ibeg < 1 | 8095 | if ibeg < 1 | ||
8305 | ibeg = 1; | 8096 | ibeg = 1; | ||
8306 | end | 8097 | end | ||
8307 | PR=PR(ibeg:iend); | 8098 | PR=PR(ibeg:iend); | ||
8308 | result.A_f = sum(PR/param.samples_per_ui); %% eq 163A-3 | 8099 | result.A_f = sum(PR/param.samples_per_ui); %% eq 163A-3 | ||
8309 | SRn=PR; | 8100 | SRn=PR; | ||
8310 | for ik=1:floor(length(PR)/param.samples_per_ui) | 8101 | for ik=1:floor(length(PR)/param.samples_per_ui) | ||
8311 | SPR=circshift(PR,param.samples_per_ui*ik); | 8102 | SPR=circshift(PR,param.samples_per_ui*ik); | ||
8312 | SPR(1:ik*param.samples_per_ui)=0; | 8103 | SPR(1:ik*param.samples_per_ui)=0; | ||
8313 | SRn=SRn+ SPR; | 8104 | SRn=SRn+ SPR; | ||
8314 | end | 8105 | end | ||
8315 | codedebug=0; | 8106 | codedebug=0; | ||
8316 | if codedebug | 8107 | if codedebug | ||
8317 | fig=figure('Name', 'step and pulse response for code debug'); | 8108 | fig=figure('Name', 'step and pulse response for code debug'); | ||
8318 | figure(fig);set(gcf,'Tag','COM'); | 8109 | figure(fig);set(gcf,'Tag','COM'); | ||
8319 | UI=(1:length(SRn))/param.samples_per_ui-param.D_p; | 8110 | UI=(1:length(SRn))/param.samples_per_ui-param.D_p; | ||
8320 | plot(UI,SRn) | 8111 | plot(UI,SRn) | ||
8321 | hold on | 8112 | hold on | ||
8322 | plot(UI,PR) | 8113 | plot(UI,PR) | ||
8323 | xlim([-param.D_p param.N_v]) | 8114 | xlim([-param.D_p param.N_v]) | ||
8324 | grid on;hold off; | 8115 | grid on;hold off; | ||
8325 | result.step=SRn; | 8116 | result.step=SRn; | ||
8326 | end | 8117 | end | ||
8327 | i20=find(SRn>=0.20*result.A_f,1,'first'); | 8118 | i20=find(SRn>=0.20*result.A_f,1,'first'); | ||
8328 | i80=find(SRn>=0.80*result.A_f,1,'first'); | 8119 | i80=find(SRn>=0.80*result.A_f,1,'first'); | ||
8329 | result.Tr_measured_from_step=(i80-i20)/(param.fb*param.samples_per_ui); | 8120 | result.Tr_measured_from_step=(i80-i20)/(param.fb*param.samples_per_ui); | ||
8330 | result.Pmax_by_Vf=result.A_p/result.A_f; | 8121 | result.Pmax_by_Vf=result.A_p/result.A_f; | ||
8331 | result.ISI =best_ISI; | 8122 | result.ISI =best_ISI; | ||
8332 | result.SNR_ISI=20*log10(best_A_p/best_ISI); | 8123 | result.SNR_ISI=20*log10(best_A_p/best_ISI); | ||
8333 | result.best_current_ffegain=best_current_ffegain; | 8124 | result.best_current_ffegain=best_current_ffegain; | ||
8334 | result.best_bmax=best_bmax; | 8125 | result.best_bmax=best_bmax; | ||
8335 | %AJG021820 | 8126 | %AJG021820 | ||
8336 | result.best_bmin=best_bmin; | 8127 | result.best_bmin=best_bmin; | ||
8337 | result.tail_RSS=best_tail_RSS; | 8128 | result.tail_RSS=best_tail_RSS; | ||
8338 | function param=parameter_size_adjustment(param,OP) | 8129 | function param=parameter_size_adjustment(param,OP) | ||
8339 | 8130 | ||||
8340 | make_length2={'C_pkg_board' 'C_diepad' 'L_comp' 'C_bump' 'tfx' 'C_v' 'C_0' 'C_1' 'pkg_Z_c' 'brd_Z_c' 'R_diepad'}; | 8131 | make_length2={'C_pkg_board' 'C_diepad' 'L_comp' 'C_bump' 'tfx' 'C_v' 'C_0' 'C_1' 'pkg_Z_c' 'brd_Z_c' 'R_diepad'}; | ||
8341 | make_length_WCPORTZ={'a_thru' 'a_fext' 'a_next' 'SNDR'}; | 8132 | make_length_WCPORTZ={'a_thru' 'a_fext' 'a_next' 'SNDR'}; | ||
8342 | make_length_GDC={'CTLE_fp1' 'CTLE_fp2' 'CTLE_fz' 'f_HP_Z' 'f_HP_P'}; | 8133 | make_length_GDC={'CTLE_fp1' 'CTLE_fp2' 'CTLE_fz' 'f_HP_Z' 'f_HP_P'}; | ||
8343 | make_length_DCHP={'f_HP'}; | 8134 | make_length_DCHP={'f_HP'}; | ||
8344 | make_length_ncases={'AC_CM_RMS'}; | 8135 | make_length_ncases={'AC_CM_RMS'}; | ||
8345 | 8136 | ||||
8346 | %ncases used by make_length_ncases fields | 8137 | %ncases used by make_length_ncases fields | ||
8347 | [ncases, mele]=size(param.z_p_tx_cases); % need find the number of test cases RIM 01-08-20 | 8138 | [ncases, mele]=size(param.z_p_tx_cases); % need find the number of test cases RIM 01-08-20 | ||
8348 | 8139 | ||||
8349 | %PORTZ_mult used by make_length_WCPORTZ fields | 8140 | %PORTZ_mult used by make_length_WCPORTZ fields | ||
8350 | pkg_sel_vec=ones(1,max(OP.pkg_len_select)); | 8141 | pkg_sel_vec=ones(1,max(OP.pkg_len_select)); | ||
8351 | if OP.WC_PORTZ | 8142 | if OP.WC_PORTZ | ||
8352 | PORTZ_mult=[1 1]; | 8143 | PORTZ_mult=[1 1]; | ||
8353 | else | 8144 | else | ||
8354 | PORTZ_mult=pkg_sel_vec; | 8145 | PORTZ_mult=pkg_sel_vec; | ||
8355 | end | 8146 | end | ||
8356 | 8147 | ||||
8357 | %Parameters that have length = 2 | 8148 | %Parameters that have length = 2 | ||
8358 | for j=1:length(make_length2) | 8149 | for j=1:length(make_length2) | ||
8359 | if numel(param.(make_length2{j}))==1 | 8150 | if numel(param.(make_length2{j}))==1 | ||
8360 | param.(make_length2{j}) = param.(make_length2{j})*[1 1]; | 8151 | param.(make_length2{j}) = param.(make_length2{j})*[1 1]; | ||
8361 | end | 8152 | end | ||
8362 | end | 8153 | end | ||
8363 | 8154 | ||||
8364 | %Parameters that have length = ncases | 8155 | %Parameters that have length = ncases | ||
8365 | for j=1:length(make_length_ncases) | 8156 | for j=1:length(make_length_ncases) | ||
8366 | if numel(param.(make_length_ncases{j}))==1 | 8157 | if numel(param.(make_length_ncases{j}))==1 | ||
8367 | param.(make_length_ncases{j}) = param.(make_length_ncases{j})*ones(1,ncases); | 8158 | param.(make_length_ncases{j}) = param.(make_length_ncases{j})*ones(1,ncases); | ||
8368 | end | 8159 | end | ||
8369 | end | 8160 | end | ||
8370 | 8161 | ||||
8371 | %Parameters that have length = length(ctle_gdc_values) | 8162 | %Parameters that have length = length(ctle_gdc_values) | ||
8372 | for j=1:length(make_length_GDC) | 8163 | for j=1:length(make_length_GDC) | ||
8373 | if numel(param.(make_length_GDC{j}))==1 | 8164 | if numel(param.(make_length_GDC{j}))==1 | ||
8374 | param.(make_length_GDC{j}) = param.(make_length_GDC{j})*ones(size(param.ctle_gdc_values)); | 8165 | param.(make_length_GDC{j}) = param.(make_length_GDC{j})*ones(size(param.ctle_gdc_values)); | ||
8375 | end | 8166 | end | ||
8376 | end | 8167 | end | ||
8377 | 8168 | ||||
8378 | %Parameters that have length = length(g_DC_HP_values) | 8169 | %Parameters that have length = length(g_DC_HP_values) | ||
8379 | for j=1:length(make_length_DCHP) | 8170 | for j=1:length(make_length_DCHP) | ||
8380 | if numel(param.(make_length_DCHP{j}))==1 | 8171 | if numel(param.(make_length_DCHP{j}))==1 | ||
8381 | param.(make_length_DCHP{j}) = param.(make_length_DCHP{j})*ones(size(param.g_DC_HP_values)); | 8172 | param.(make_length_DCHP{j}) = param.(make_length_DCHP{j})*ones(size(param.g_DC_HP_values)); | ||
8382 | end | 8173 | end | ||
8383 | end | 8174 | end | ||
8384 | 8175 | ||||
8385 | %Parameters that have length associated with PORTZ_mult | 8176 | %Parameters that have length associated with PORTZ_mult | ||
8386 | for j=1:length(make_length_WCPORTZ) | 8177 | for j=1:length(make_length_WCPORTZ) | ||
8387 | if numel(param.(make_length_WCPORTZ{j}))==1 | 8178 | if numel(param.(make_length_WCPORTZ{j}))==1 | ||
8388 | param.(make_length_WCPORTZ{j}) = param.(make_length_WCPORTZ{j})*PORTZ_mult; | 8179 | param.(make_length_WCPORTZ{j}) = param.(make_length_WCPORTZ{j})*PORTZ_mult; | ||
8389 | end | 8180 | end | ||
8390 | end | 8181 | end | ||
8391 | function sgm = pdf2sgm(pdf) | 8182 | function sgm = pdf2sgm(pdf) | ||
8392 | avg = sum(pdf.x .* pdf.y); | 8183 | avg = sum(pdf.x .* pdf.y); | ||
8393 | sgm = sqrt(sum((pdf.x - avg).^2 .* pdf.y)); | 8184 | sgm = sqrt(sum((pdf.x - avg).^2 .* pdf.y)); | ||
8394 | % end yasuo patch | 8185 | % end yasuo patch | ||
8395 | 8186 | ||||
8396 | 8187 | ||||
8397 | %% adding tx packgage | 8188 | %% adding tx packgage | ||
8398 | function cdf=pdf_to_cdf(pdf) | 8189 | function cdf=pdf_to_cdf(pdf) | ||
8399 | 8190 | ||||
8400 | %Transform PDF to CDF | 8191 | %Transform PDF to CDF | ||
8401 | %The CDF is natively calculated from negative-to-positive voltage. | 8192 | %The CDF is natively calculated from negative-to-positive voltage. | ||
8402 | %This only gives BER calculation for bottom eye. Need to also | 8193 | %This only gives BER calculation for bottom eye. Need to also | ||
8403 | %calculate a CDF of reversed PDF to get top eye. The final CDF is the | 8194 | %calculate a CDF of reversed PDF to get top eye. The final CDF is the | ||
8404 | %min of top and bottom CDF values. | 8195 | %min of top and bottom CDF values. | ||
8405 | %If only interested in one side, a simple cumsum on y is all that is needed. | 8196 | %If only interested in one side, a simple cumsum on y is all that is needed. | ||
8406 | 8197 | ||||
8407 | cdf.yB=cumsum(pdf.y); | 8198 | cdf.yB=cumsum(pdf.y); | ||
8408 | cdf.yT=fliplr(cumsum(fliplr(pdf.y))); | 8199 | cdf.yT=fliplr(cumsum(fliplr(pdf.y))); | ||
8409 | cdf.y=min([cdf.yB(:) cdf.yT(:)],[],2); | 8200 | cdf.y=min([cdf.yB(:) cdf.yT(:)],[],2); | ||
8410 | cdf.x=pdf.x; | 8201 | cdf.x=pdf.x; | ||
8411 | function plot_bathtub_curves(hax, max_signal, sci_pdf, cci_pdf, isi_and_xtalk_pdf, noise_pdf,jitt_pdf, combined_interference_and_noise_pdf, bin_size) | 8202 | function plot_bathtub_curves(hax, max_signal, sci_pdf, cci_pdf, isi_and_xtalk_pdf, noise_pdf,jitt_pdf, combined_interference_and_noise_pdf, bin_size) | ||
8412 | cursors = d_cpdf(bin_size,max_signal*[-1 1], [1 1]/2); | 8203 | cursors = d_cpdf(bin_size,max_signal*[-1 1], [1 1]/2); | ||
8413 | signal_and_isi_pdf = conv_fct(cursors, sci_pdf); | 8204 | signal_and_isi_pdf = conv_fct(cursors, sci_pdf); | ||
8414 | signal_and_xtalk_pdf = conv_fct(cursors, cci_pdf); | 8205 | signal_and_xtalk_pdf = conv_fct(cursors, cci_pdf); | ||
8415 | signal_and_channel_noise_pdf = conv_fct(cursors, isi_and_xtalk_pdf); | 8206 | signal_and_channel_noise_pdf = conv_fct(cursors, isi_and_xtalk_pdf); | ||
8416 | signal_and_system_noise_pdf = conv_fct(cursors, noise_pdf); | 8207 | signal_and_system_noise_pdf = conv_fct(cursors, noise_pdf); | ||
8417 | signal_and_system_jitt_pdf = conv_fct(cursors, jitt_pdf); | 8208 | signal_and_system_jitt_pdf = conv_fct(cursors, jitt_pdf); | ||
8418 | signal_and_total_noise_pdf = conv_fct(cursors, combined_interference_and_noise_pdf); | 8209 | signal_and_total_noise_pdf = conv_fct(cursors, combined_interference_and_noise_pdf); | ||
8419 | %% Added by Bill Kirkland, June 14, 2017 | 8210 | %% Added by Bill Kirkland, June 14, 2017 | ||
8420 | cursors_l = cursors; cursors_l.y(cursors_l.x>0) = 0; | 8211 | cursors_l = cursors; cursors_l.y(cursors_l.x>0) = 0; | ||
8421 | cursors_r = cursors; cursors_r.y(cursors_r.x<0) = 0; | 8212 | cursors_r = cursors; cursors_r.y(cursors_r.x<0) = 0; | ||
8422 | signal_and_total_noise_pdf_l = conv_fct(cursors_l, combined_interference_and_noise_pdf); | 8213 | signal_and_total_noise_pdf_l = conv_fct(cursors_l, combined_interference_and_noise_pdf); | ||
8423 | signal_and_total_noise_pdf_r = conv_fct(cursors_r, combined_interference_and_noise_pdf); | 8214 | signal_and_total_noise_pdf_r = conv_fct(cursors_r, combined_interference_and_noise_pdf); | ||
8424 | 8215 | ||||
8425 | semilogy(signal_and_isi_pdf.x, abs(cumsum(signal_and_isi_pdf.y)-0.5) ,'r','Disp','ISI', 'parent', hax) | 8216 | semilogy(signal_and_isi_pdf.x, abs(cumsum(signal_and_isi_pdf.y)-0.5) ,'r','Disp','ISI', 'parent', hax) | ||
8426 | hold on | 8217 | hold on | ||
8427 | semilogy(signal_and_xtalk_pdf.x, abs(cumsum(signal_and_xtalk_pdf.y)-0.5) ,'b','Disp','Xtalk', 'parent', hax) | 8218 | semilogy(signal_and_xtalk_pdf.x, abs(cumsum(signal_and_xtalk_pdf.y)-0.5) ,'b','Disp','Xtalk', 'parent', hax) | ||
8428 | semilogy(signal_and_channel_noise_pdf.x, abs(cumsum(signal_and_channel_noise_pdf.y)-0.5) ,'c','Disp','ISI+Xtalk', 'parent', hax) | 8219 | semilogy(signal_and_channel_noise_pdf.x, abs(cumsum(signal_and_channel_noise_pdf.y)-0.5) ,'c','Disp','ISI+Xtalk', 'parent', hax) | ||
8429 | semilogy(signal_and_system_noise_pdf.x, abs(cumsum(signal_and_system_noise_pdf.y)-0.5) ,'m','Disp','Jitter, SNR_TX,RL_M, eta_0 noise', 'parent', hax) | 8220 | semilogy(signal_and_system_noise_pdf.x, abs(cumsum(signal_and_system_noise_pdf.y)-0.5) ,'m','Disp','Jitter, SNR_TX,RL_M, eta_0 noise', 'parent', hax) | ||
8430 | semilogy(signal_and_system_jitt_pdf.x, abs(cumsum(signal_and_system_jitt_pdf.y)-0.5) ,'g','Disp','Jitter noise', 'parent', hax) | 8221 | semilogy(signal_and_system_jitt_pdf.x, abs(cumsum(signal_and_system_jitt_pdf.y)-0.5) ,'g','Disp','Jitter noise', 'parent', hax) | ||
8431 | 8222 | ||||
8432 | %% Added by Bill Kirkland, June 14, 2017 | 8223 | %% Added by Bill Kirkland, June 14, 2017 | ||
8433 | % modification allows bathtub curves to cross over and hence one can | 8224 | % modification allows bathtub curves to cross over and hence one can | ||
8434 | % directly read the noise component. | 8225 | % directly read the noise component. | ||
8435 | %semilogy(signal_and_total_noise_pdf.x, abs(cumsum(signal_and_total_noise_pdf.y)-0.5) ,'k','Disp','total noise PDF', 'parent', hax) | 8226 | %semilogy(signal_and_total_noise_pdf.x, abs(cumsum(signal_and_total_noise_pdf.y)-0.5) ,'k','Disp','total noise PDF', 'parent', hax) | ||
8436 | vbt_l = abs(0.5-cumsum(signal_and_total_noise_pdf_l.y)); | 8227 | vbt_l = abs(0.5-cumsum(signal_and_total_noise_pdf_l.y)); | ||
8437 | vbt_r = fliplr(0.5-(cumsum(fliplr(signal_and_total_noise_pdf_r.y)))); | 8228 | vbt_r = fliplr(0.5-(cumsum(fliplr(signal_and_total_noise_pdf_r.y)))); | ||
8438 | semilogy(signal_and_total_noise_pdf_l.x, vbt_l ,'k','Disp','total noise PDF left', 'parent', hax) | 8229 | semilogy(signal_and_total_noise_pdf_l.x, vbt_l ,'k','Disp','total noise PDF left', 'parent', hax) | ||
8439 | semilogy(signal_and_total_noise_pdf_r.x, vbt_r ,'k','Disp','total noise PDF right', 'parent', hax) | 8230 | semilogy(signal_and_total_noise_pdf_r.x, vbt_r ,'k','Disp','total noise PDF right', 'parent', hax) | ||
8440 | 8231 | ||||
8441 | hc=semilogy(max_signal*[-1 -1 1 1], [0.5 1e-20 1e-20 0.5], '--ok'); | 8232 | hc=semilogy(max_signal*[-1 -1 1 1], [0.5 1e-20 1e-20 0.5], '--ok'); | ||
8442 | set(get(get(hc,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | 8233 | set(get(get(hc,'Annotation'),'LegendInformation'), 'IconDisplayStyle','off'); | ||
8443 | 8234 | ||||
8444 | ylabel(hax, 'Probability') | 8235 | ylabel(hax, 'Probability') | ||
8445 | xlabel(hax, 'volts') | 8236 | xlabel(hax, 'volts') | ||
8446 | legend(hax, 'show') | 8237 | legend(hax, 'show') | ||
8447 | % testing code | 8238 | % testing code | ||
8448 | if 0 | 8239 | if 0 | ||
8449 | figure_name = 'COM curves'; | 8240 | figure_name = 'COM curves'; | ||
8450 | fig=findobj('Name', figure_name); | 8241 | fig=findobj('Name', figure_name); | ||
8451 | if isempty(fig), fig=figure('Name', figure_name); end | 8242 | if isempty(fig), fig=figure('Name', figure_name); end | ||
8452 | figure(fig);set(gcf,'Tag','COM'); | 8243 | figure(fig);set(gcf,'Tag','COM'); | ||
8453 | grid on | 8244 | grid on | ||
8454 | semilogy(db(max_signal./(signal_and_total_noise_pdf_r.x)), 2*vbt_r ,'Disp','SNR CDF') | 8245 | semilogy(db(max_signal./(signal_and_total_noise_pdf_r.x)), 2*vbt_r ,'Disp','SNR CDF') | ||
8455 | hold on | 8246 | hold on | ||
8456 | semilogy(db(max_signal./(max_signal-signal_and_total_noise_pdf_r.x)), 2*vbt_r ,'Disp','COM CDF') | 8247 | semilogy(db(max_signal./(max_signal-signal_and_total_noise_pdf_r.x)), 2*vbt_r ,'Disp','COM CDF') | ||
8457 | ylim([ 1e-6 0.25]) | 8248 | ylim([ 1e-6 0.25]) | ||
8458 | xlim([0 30]) | 8249 | xlim([0 30]) | ||
8459 | grid on | 8250 | grid on | ||
8460 | end | 8251 | end | ||
8461 | function plot_pie_com(hax, max_signal, sci_pdf, cci_pdf, isi_and_xtalk_pdf, noise_pdf, combined_interference_and_noise_pdf, bin_size,param) | 8252 | function plot_pie_com(hax, max_signal, sci_pdf, cci_pdf, isi_and_xtalk_pdf, noise_pdf, combined_interference_and_noise_pdf, bin_size,param) | ||
8462 | BER=param.specBER; | 8253 | BER=param.specBER; | ||
8463 | delta_dB=param.delta_IL; | 8254 | delta_dB=param.delta_IL; | ||
8464 | 8255 | ||||
8465 | iex.combined_interference_and_noise_pdf=find(abs(cumsum(combined_interference_and_noise_pdf.y))>= BER, 1, 'first'); | 8256 | iex.combined_interference_and_noise_pdf=find(abs(cumsum(combined_interference_and_noise_pdf.y))>= BER, 1, 'first'); | ||
8466 | iex.noise_pdf=find(abs(cumsum(noise_pdf.y))>= BER, 1, 'first'); | 8257 | iex.noise_pdf=find(abs(cumsum(noise_pdf.y))>= BER, 1, 'first'); | ||
8467 | iex.cci_pdf=find(abs(cumsum(cci_pdf.y))>= BER, 1, 'first'); | 8258 | iex.cci_pdf=find(abs(cumsum(cci_pdf.y))>= BER, 1, 'first'); | ||
8468 | iex.sci_pdf=find(abs(cumsum(sci_pdf.y))>= BER, 1, 'first'); | 8259 | iex.sci_pdf=find(abs(cumsum(sci_pdf.y))>= BER, 1, 'first'); | ||
8469 | 8260 | ||||
8470 | 8261 | ||||
8471 | maxn(1)=abs(sci_pdf.x(iex.sci_pdf)); | 8262 | maxn(1)=abs(sci_pdf.x(iex.sci_pdf)); | ||
8472 | maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | 8263 | maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | ||
8473 | maxn(3)=abs(cci_pdf.x(iex.cci_pdf)); | 8264 | maxn(3)=abs(cci_pdf.x(iex.cci_pdf)); | ||
8474 | maxn_tot=abs(combined_interference_and_noise_pdf.x(iex.combined_interference_and_noise_pdf)); | 8265 | maxn_tot=abs(combined_interference_and_noise_pdf.x(iex.combined_interference_and_noise_pdf)); | ||
8475 | 8266 | ||||
8476 | COM=20*log10(max_signal/maxn_tot); | 8267 | COM=20*log10(max_signal/maxn_tot); | ||
8477 | COM_per_noise(1:3)=COM*(maxn(1:3).^2/sum(maxn.^2)); | 8268 | COM_per_noise(1:3)=COM*(maxn(1:3).^2/sum(maxn.^2)); | ||
8478 | COM_ISI=sprintf( '%.2g%%',100*COM_per_noise(1)/sum(COM_per_noise)); | 8269 | COM_ISI=sprintf( '%.2g%%',100*COM_per_noise(1)/sum(COM_per_noise)); | ||
8479 | COM_SYS=sprintf( '%.2g%%',100*COM_per_noise(2)/sum(COM_per_noise)); | 8270 | COM_SYS=sprintf( '%.2g%%',100*COM_per_noise(2)/sum(COM_per_noise)); | ||
8480 | COM_xtalk=sprintf('%.2g%%',100*COM_per_noise(3)/sum(COM_per_noise)); | 8271 | COM_xtalk=sprintf('%.2g%%',100*COM_per_noise(3)/sum(COM_per_noise)); | ||
8481 | 8272 | ||||
8482 | pfctr=exp(-0.09054*delta_dB);% less loss | 8273 | pfctr=exp(-0.09054*delta_dB);% less loss | ||
8483 | mfctr=exp(0.09054*delta_dB); % more loss | 8274 | mfctr=exp(0.09054*delta_dB); % more loss | ||
8484 | 8275 | ||||
8485 | %less loss | 8276 | %less loss | ||
8486 | plus_maxn(1)=abs(sci_pdf.x(iex.sci_pdf))*pfctr; | 8277 | plus_maxn(1)=abs(sci_pdf.x(iex.sci_pdf))*pfctr; | ||
8487 | plus_maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | 8278 | plus_maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | ||
8488 | plus_maxn(3)=abs(cci_pdf.x(iex.cci_pdf))*pfctr; | 8279 | plus_maxn(3)=abs(cci_pdf.x(iex.cci_pdf))*pfctr; | ||
8489 | % plus_maxn_tot=(maxn(1)*pfctr+maxn(2)+maxn(3)*pfctr)*maxn_tot/sum(plus_maxn); | 8280 | % plus_maxn_tot=(maxn(1)*pfctr+maxn(2)+maxn(3)*pfctr)*maxn_tot/sum(plus_maxn); | ||
8490 | plus_maxn_tot=norm(plus_maxn); | 8281 | plus_maxn_tot=norm(plus_maxn); | ||
8491 | 8282 | ||||
8492 | minus_maxn(1)=abs(sci_pdf.x(iex.sci_pdf))*mfctr; | 8283 | minus_maxn(1)=abs(sci_pdf.x(iex.sci_pdf))*mfctr; | ||
8493 | minus_maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | 8284 | minus_maxn(2)=abs(noise_pdf.x(iex.noise_pdf)); | ||
8494 | minus_maxn(3)=abs(cci_pdf.x(iex.cci_pdf))*mfctr; | 8285 | minus_maxn(3)=abs(cci_pdf.x(iex.cci_pdf))*mfctr; | ||
8495 | % minus_maxn_tot=(maxn(1)*mfctr+maxn(2)+maxn(3)*mfctr)*maxn_tot/sum(minus_maxn); | 8286 | % minus_maxn_tot=(maxn(1)*mfctr+maxn(2)+maxn(3)*mfctr)*maxn_tot/sum(minus_maxn); | ||
8496 | minus_maxn_tot=norm(minus_maxn); | 8287 | minus_maxn_tot=norm(minus_maxn); | ||
8497 | 8288 | ||||
8498 | % more loss | 8289 | % more loss | ||
8499 | COMp=20*log10(max_signal*pfctr/maxn_tot); | 8290 | COMp=20*log10(max_signal*pfctr/maxn_tot); | ||
8500 | COMp_per_noise(1:3)=COMp*(plus_maxn(1:3).^2/plus_maxn_tot^2); | 8291 | COMp_per_noise(1:3)=COMp*(plus_maxn(1:3).^2/plus_maxn_tot^2); | ||
8501 | COMp_ISI=sprintf( '%.2gdB',COMp_per_noise(1)); | 8292 | COMp_ISI=sprintf( '%.2gdB',COMp_per_noise(1)); | ||
8502 | COMp_SYS=sprintf( '%.2gdB',COMp_per_noise(2)); | 8293 | COMp_SYS=sprintf( '%.2gdB',COMp_per_noise(2)); | ||
8503 | COMp_xtalk=sprintf('%.2gdB',COMp_per_noise(3)); | 8294 | COMp_xtalk=sprintf('%.2gdB',COMp_per_noise(3)); | ||
8504 | % less loss | 8295 | % less loss | ||
8505 | COMm=20*log10(max_signal*mfctr/maxn_tot); | 8296 | COMm=20*log10(max_signal*mfctr/maxn_tot); | ||
8506 | COMm_per_noise(1:3)=COMm*(minus_maxn(1:3).^2/minus_maxn_tot^2); | 8297 | COMm_per_noise(1:3)=COMm*(minus_maxn(1:3).^2/minus_maxn_tot^2); | ||
8507 | COMm_ISI=sprintf( '%.2gdB',COMm_per_noise(1)); | 8298 | COMm_ISI=sprintf( '%.2gdB',COMm_per_noise(1)); | ||
8508 | COMm_SYS=sprintf( '%.2gdB',COMm_per_noise(2)); | 8299 | COMm_SYS=sprintf( '%.2gdB',COMm_per_noise(2)); | ||
8509 | COMm_xtalk=sprintf('%.2gdB',COMm_per_noise(3)); | 8300 | COMm_xtalk=sprintf('%.2gdB',COMm_per_noise(3)); | ||
8510 | 8301 | ||||
8511 | xax=[[delta_dB delta_dB delta_dB];[ 0 0 0 ]; [ -delta_dB -delta_dB -delta_dB]]; | 8302 | xax=[[delta_dB delta_dB delta_dB];[ 0 0 0 ]; [ -delta_dB -delta_dB -delta_dB]]; | ||
8512 | 8303 | ||||
8513 | 8304 | ||||
8514 | if(COM<0) | 8305 | if(COM<0) | ||
8515 | return | 8306 | return | ||
8516 | end | 8307 | end | ||
8517 | 8308 | ||||
8518 | labels= { ['ISI ' COM_ISI] ['System noise/jitter ' COM_SYS] [' Crosstalk ' COM_xtalk]}; | 8309 | labels= { ['ISI ' COM_ISI] ['System noise/jitter ' COM_SYS] [' Crosstalk ' COM_xtalk]}; | ||
8519 | 8310 | ||||
8520 | % pie(COM_per_noise,labels) | 8311 | % pie(COM_per_noise,labels) | ||
8521 | % legend(labels,{'ISI COM','System noise/jitter COM','Crosstalk COM'}); | 8312 | % legend(labels,{'ISI COM','System noise/jitter COM','Crosstalk COM'}); | ||
8522 | % legend('show','Location','bestoutside') | 8313 | % legend('show','Location','bestoutside') | ||
8523 | nullbar= [ 0 0 0 ]; | 8314 | nullbar= [ 0 0 0 ]; | ||
8524 | bar(xax,[nullbar ;COM_per_noise; nullbar],'stacked') | 8315 | bar(xax,[nullbar ;COM_per_noise; nullbar],'stacked') | ||
8525 | % bar(xax,[COMp_per_noise;COM_per_noise;COMm_per_noise],'stacked') | 8316 | % bar(xax,[COMp_per_noise;COM_per_noise;COMm_per_noise],'stacked') | ||
8526 | hold on | 8317 | hold on | ||
8527 | bar(xax,[[COMp 0 0 ];nullbar;nullbar],'stacked','w','barwidth',.5) | 8318 | bar(xax,[[COMp 0 0 ];nullbar;nullbar],'stacked','w','barwidth',.5) | ||
8528 | bar(xax,[nullbar ;nullbar; [0 0 COMm]],'stacked','w','barwidth',.5) | 8319 | bar(xax,[nullbar ;nullbar; [0 0 COMm]],'stacked','w','barwidth',.5) | ||
8529 | 8320 | ||||
8530 | plot([-delta_dB,0, delta_dB], [param.pass_threshold ,param.pass_threshold ,param.pass_threshold ],'r') | 8321 | plot([-delta_dB,0, delta_dB], [param.pass_threshold ,param.pass_threshold ,param.pass_threshold ],'r') | ||
8531 | % ax=gca; | 8322 | % ax=gca; | ||
8532 | % ax.XTickLabels = {'decreasing loss','-','increasing loss'}; | 8323 | % ax.XTickLabels = {'decreasing loss','-','increasing loss'}; | ||
8533 | set(gca,'XTickLabel', {'decreasing loss','-','increasing loss'}) | 8324 | set(gca,'XTickLabel', {'decreasing loss','-','increasing loss'}) | ||
8534 | grid on | 8325 | grid on | ||
8535 | legend(labels,'Location','north') | 8326 | legend(labels,'Location','north') | ||
8536 | xlabel(['if loss is changed by ' sprintf('%.2gdB',delta_dB) ]) | 8327 | xlabel(['if loss is changed by ' sprintf('%.2gdB',delta_dB) ]) | ||
8537 | ylabel('COM (dB)') | 8328 | ylabel('COM (dB)') | ||
8538 | hold off | 8329 | hold off | ||
8539 | 8330 | ||||
8540 | 8331 | ||||
8541 | 8332 | ||||
8542 | 8333 | ||||
8543 | function [chdata, param] = process_sxp(param, OP, chdata, SDDch) | 8334 | function [chdata, param] = process_sxp(param, OP, chdata, SDDch) | ||
8544 | num_files=length(chdata); | 8335 | num_files=length(chdata); | ||
8545 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | 8336 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | ||
8546 | for i=1:num_files | 8337 | for i=1:num_files | ||
8547 | if param.package_testcase_i==1 && i==1 | 8338 | if param.package_testcase_i==1 && i==1 | ||
8548 | if OP.TDR && i==1 | 8339 | if OP.TDR && i==1 | ||
8549 | S.Frequencies=chdata(i).faxis; | 8340 | S.Frequencies=chdata(i).faxis; | ||
8550 | S.Impedance=100; | 8341 | S.Impedance=100; | ||
8551 | if ~OP.SHOW_BRD | 8342 | if ~OP.SHOW_BRD | ||
8552 | Sfield='_orig'; | 8343 | Sfield='_orig'; | ||
8553 | else | 8344 | else | ||
8554 | Sfield='_raw'; | 8345 | Sfield='_raw'; | ||
8555 | end | 8346 | end | ||
8556 | S.Parameters(1,1,:)=chdata(i).(['sdd11' Sfield]) ; | 8347 | S.Parameters(1,1,:)=chdata(i).(['sdd11' Sfield]) ; | ||
8557 | if ~param.FLAG.S2P | 8348 | if ~param.FLAG.S2P | ||
8558 | S.Parameters(1,2,:)=chdata(i).(['sdd12' Sfield]) ; | 8349 | S.Parameters(1,2,:)=chdata(i).(['sdd12' Sfield]) ; | ||
8559 | S.Parameters(2,1,:)=chdata(i).(['sdd21' Sfield]) ; | 8350 | S.Parameters(2,1,:)=chdata(i).(['sdd21' Sfield]) ; | ||
8560 | S.Parameters(2,2,:)=chdata(i).(['sdd22' Sfield]) ; | 8351 | S.Parameters(2,2,:)=chdata(i).(['sdd22' Sfield]) ; | ||
8561 | S.NumPorts=2; % rim 2/26/2019 correct from S.NumPorts=4; | 8352 | S.NumPorts=2; % rim 2/26/2019 correct from S.NumPorts=4; | ||
8562 | else | 8353 | else | ||
8563 | S.NumPorts=1; | 8354 | S.NumPorts=1; | ||
8564 | end | 8355 | end | ||
8565 | if OP.TDR_W_TXPKG | 8356 | if OP.TDR_W_TXPKG | ||
8566 | if OP.ERL == 2 | 8357 | if OP.ERL == 2 | ||
8567 | error('Cannot add pacakge to s2p files. ERL==2 not supportted if TDR_W_TXPKG = 1') | 8358 | error('Cannot add pacakge to s2p files. ERL==2 not supportted if TDR_W_TXPKG = 1') | ||
8568 | end | 8359 | end | ||
8569 | R_diepad = param.R_diepad; | 8360 | R_diepad = param.R_diepad; | ||
8570 | % RX package length is assumed to be the same for all | 8361 | % RX package length is assumed to be the same for all | ||
8571 | % channel types. swap Cp and Cd for Tx. TDR_W_TXPKG only | 8362 | % channel types. swap Cp and Cd for Tx. TDR_W_TXPKG only | ||
8572 | % for Rx pkg | 8363 | % for Rx pkg | ||
8573 | [ s11in, s12in, s21in, s22in]=make_full_pkg('TX',S.Frequencies,param,'THRU'); | 8364 | [ s11in, s12in, s21in, s22in]=make_full_pkg('TX',S.Frequencies,param,'THRU'); | ||
8574 | [ S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:)] = ... | 8365 | [ S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:)] = ... | ||
8575 | combines4p( s11in, s12in, s21in, s22in, ... | 8366 | combines4p( s11in, s12in, s21in, s22in, ... | ||
8576 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ); | 8367 | S.Parameters(1,1,:), S.Parameters(1,2,:), S.Parameters(2,1,:), S.Parameters(2,2,:) ); | ||
8577 | % S=sparameters(S.Parameters,S.Frequencies,100); | 8368 | % S=sparameters(S.Parameters,S.Frequencies,100); | ||
8578 | S=SL(S,S.Frequencies,R_diepad(1)*2); | 8369 | S=SL(S,S.Frequencies,R_diepad(1)*2); | ||
8579 | chdata(i).TX_RL=S.Parameters(2,2,:); | 8370 | chdata(i).TX_RL=S.Parameters(2,2,:); | ||
8580 | S.Parameters(1,1,:)=chdata(i).sdd11_orig; % when looking at Tx don't include package | 8371 | S.Parameters(1,1,:)=chdata(i).sdd11_orig; % when looking at Tx don't include package | ||
8581 | end | 8372 | end | ||
8582 |
| 8373 |
| ||
8583 | % need to combine S wiht is page and channel | 8374 | % need to combine S wiht is page and channel | ||
8584 | if param.FLAG.S2P | 8375 | if param.FLAG.S2P | ||
8585 | port_sel=1; | 8376 | port_sel=1; | ||
8586 | else | 8377 | else | ||
8587 | port_sel=[1 2]; | 8378 | port_sel=[1 2]; | ||
8588 | if OP.AUTO_TFX | 8379 | if OP.AUTO_TFX | ||
8589 | [ fir4del, tu] =get_RAW_FIR(squeeze(chdata(i).sdd12_orig),S.Frequencies,OP,param); | 8380 | [ fir4del, tu] =get_RAW_FIR(squeeze(chdata(i).sdd12_orig),S.Frequencies,OP,param); | ||
8590 | pix=find(fir4del==max(fir4del),1); | 8381 | pix=find(fir4del==max(fir4del),1); | ||
8591 | param.tfx(2)=2*tu(pix); | 8382 | param.tfx(2)=2*tu(pix); | ||
8592 | end | 8383 | end | ||
8593 | end | 8384 | end | ||
8594 | OP.impulse_response_truncation_threshold=1e-5; %Only for TDR not returned out of "process_sxp" function | 8385 | OP.impulse_response_truncation_threshold=1e-5; %Only for TDR not returned out of "process_sxp" function | ||
8595 | for ipsl=1:length(port_sel) % do for both port if s4p | 8386 | for ipsl=1:length(port_sel) % do for both port if s4p | ||
8596 | for izt=1:length(param.Z_t) % do for all tdr impedances | 8387 | for izt=1:length(param.Z_t) % do for all tdr impedances | ||
8597 | param.RL_sel=port_sel(ipsl); % this used in get_TDR | 8388 | param.RL_sel=port_sel(ipsl); % this used in get_TDR | ||
8598 | % OP.interp_sparam_phase='interp_to_DC'; % better for return loss | 8389 | % OP.interp_sparam_phase='interp_to_DC'; % better for return loss | ||
8599 | % OP.interp_sparam_mag='trend_to_DC'; | 8390 | % OP.interp_sparam_mag='trend_to_DC'; | ||
8600 | OP.interp_sparam_mag='linear_trend_to_DC'; | 8391 | OP.interp_sparam_mag='linear_trend_to_DC'; | ||
8601 | % OP.interp_sparam_mag='extrap_to_DC_or_zero'; | 8392 | % OP.interp_sparam_mag='extrap_to_DC_or_zero'; | ||
8602 | OP.interp_sparam_phase='extrap_cubic_to_dc_linear_to_inf'; | 8393 | OP.interp_sparam_phase='extrap_cubic_to_dc_linear_to_inf'; | ||
8603 | TDR_results(izt,ipsl) = get_TDR(S, OP, param,param.Z_t(izt),ipsl); | 8394 | TDR_results(izt,ipsl) = get_TDR(S, OP, param,param.Z_t(izt),ipsl); | ||
8604 | if ipsl ==1 | 8395 | if ipsl ==1 | ||
8605 | chdata(i).TDR11(izt).ZSR=[TDR_results(izt,1).tdr]; | 8396 | chdata(i).TDR11(izt).ZSR=[TDR_results(izt,1).tdr]; | ||
8606 | chdata(i).TDR11(izt).t=TDR_results(izt,1).t; | 8397 | chdata(i).TDR11(izt).t=TDR_results(izt,1).t; | ||
8607 | chdata(i).TDR11(izt).avgZport=[TDR_results(izt,1).avgZport]; | 8398 | chdata(i).TDR11(izt).avgZport=[TDR_results(izt,1).avgZport]; | ||
8608 | if OP.PTDR, chdata(i).PDTR11(izt).ptdr=TDR_results(izt,1).ptdr_RL;end | 8399 | if OP.PTDR, chdata(i).PDTR11(izt).ptdr=TDR_results(izt,1).ptdr_RL;end | ||
8609 | else | 8400 | else | ||
8610 | chdata(i).TDR22(izt).ZSR=[TDR_results(izt,2).tdr]; | 8401 | chdata(i).TDR22(izt).ZSR=[TDR_results(izt,2).tdr]; | ||
8611 | chdata(i).TDR22(izt).t=TDR_results(izt,2).t; | 8402 | chdata(i).TDR22(izt).t=TDR_results(izt,2).t; | ||
8612 | chdata(i).TDR22(izt).avgZport=[TDR_results(izt,2).avgZport]; | 8403 | chdata(i).TDR22(izt).avgZport=[TDR_results(izt,2).avgZport]; | ||
8613 | if OP.PTDR, chdata(i).PDTR22(izt).ptdr=TDR_results(izt,2).ptdr_RL;end | 8404 | if OP.PTDR, chdata(i).PDTR22(izt).ptdr=TDR_results(izt,2).ptdr_RL;end | ||
8614 | end | 8405 | end | ||
8615 | if OP.PTDR && i==1 | 8406 | if OP.PTDR && i==1 | ||
8616 | if ipsl ==1 | 8407 | if ipsl ==1 | ||
8617 | chdata(i).TDR11(izt).ERL=[TDR_results(izt,1).ERL]; | 8408 | chdata(i).TDR11(izt).ERL=[TDR_results(izt,1).ERL]; | ||
8618 | chdata(i).TDR11(izt).ERLRMS=[TDR_results(izt,1).ERLRMS]; | 8409 | chdata(i).TDR11(izt).ERLRMS=[TDR_results(izt,1).ERLRMS]; | ||
8619 | else | 8410 | else | ||
8620 | if ~param.FLAG.S2P | 8411 | if ~param.FLAG.S2P | ||
8621 | chdata(i).TDR22(izt).ERL=[TDR_results(izt,2).ERL]; | 8412 | chdata(i).TDR22(izt).ERL=[TDR_results(izt,2).ERL]; | ||
8622 | chdata(i).TDR22(izt).ERLRMS=[TDR_results(izt,2).ERLRMS]; | 8413 | chdata(i).TDR22(izt).ERLRMS=[TDR_results(izt,2).ERLRMS]; | ||
8623 | else | 8414 | else | ||
8624 | chdata(i).TDR22(izt).ERL=[]; | 8415 | chdata(i).TDR22(izt).ERL=[]; | ||
8625 | chdata(i).TDR22(izt).ERLRMS=[]; | 8416 | chdata(i).TDR22(izt).ERLRMS=[]; | ||
8626 | end | 8417 | end | ||
8627 | end | 8418 | end | ||
8628 | else | 8419 | else | ||
8629 | chdata(i).TDR11(izt).ERL=[]; | 8420 | chdata(i).TDR11(izt).ERL=[]; | ||
8630 | chdata(i).TDR22(izt).ERL=[]; | 8421 | chdata(i).TDR22(izt).ERL=[]; | ||
8631 | chdata(i).TDR11(izt).ERLRMS=[]; | 8422 | chdata(i).TDR11(izt).ERLRMS=[]; | ||
8632 | chdata(i).TDR22(izt).ERLRMS=[]; | 8423 | chdata(i).TDR22(izt).ERLRMS=[]; | ||
8633 | end | 8424 | end | ||
8634 | end | 8425 | end | ||
8635 | end | 8426 | end | ||
8636 | end | 8427 | end | ||
8637 |
| 8428 |
| ||
8638 | end | 8429 | end | ||
8639 | if OP.DISPLAY_WINDOW && OP.DEBUG && OP.TDR | 8430 | if OP.DISPLAY_WINDOW && OP.DEBUG && OP.TDR | ||
8640 | h=figure(180);set(gcf,'Tag','COM'); | 8431 | h=figure(180);set(gcf,'Tag','COM'); | ||
8641 | if param.package_testcase_i==1 && i == 1 | 8432 | if param.package_testcase_i==1 && i == 1 | ||
8642 | if i==1 | 8433 | if i==1 | ||
8643 | htabgroup = uitabgroup(h); | 8434 | htabgroup = uitabgroup(h); | ||
8644 | htab1 = uitab(htabgroup, 'Title', 'TDR TX'); | 8435 | htab1 = uitab(htabgroup, 'Title', 'TDR TX'); | ||
8645 | htab3 = uitab(htabgroup, 'Title', 'PTDR TX'); | 8436 | htab3 = uitab(htabgroup, 'Title', 'PTDR TX'); | ||
8646 | hax1 = axes('Parent', htab1); | 8437 | hax1 = axes('Parent', htab1); | ||
8647 | hax3 = axes('Parent', htab3); | 8438 | hax3 = axes('Parent', htab3); | ||
8648 | if ~param.FLAG.S2P | 8439 | if ~param.FLAG.S2P | ||
8649 | htab2 = uitab(htabgroup, 'Title', 'TDR RX'); | 8440 | htab2 = uitab(htabgroup, 'Title', 'TDR RX'); | ||
8650 | htab4 = uitab(htabgroup, 'Title', 'PTDR RX'); | 8441 | htab4 = uitab(htabgroup, 'Title', 'PTDR RX'); | ||
8651 | hax2 = axes('Parent', htab2); | 8442 | hax2 = axes('Parent', htab2); | ||
8652 | hax4 = axes('Parent', htab4); | 8443 | hax4 = axes('Parent', htab4); | ||
8653 | end | 8444 | end | ||
8654 | end | 8445 | end | ||
8655 | set(h,'CurrentAxes',hax1) | 8446 | set(h,'CurrentAxes',hax1) | ||
8656 | hold on | 8447 | hold on | ||
8657 | plot(chdata(i).TDR11(izt).t(:),chdata(i).TDR11(izt).ZSR,'disp',[ chdata(i).base ' Tx port']); | 8448 | plot(chdata(i).TDR11(izt).t(:),chdata(i).TDR11(izt).ZSR,'disp',[ chdata(i).base ' Tx port']); | ||
8658 | hold off | 8449 | hold off | ||
8659 | legend (hax1, 'off');grid on;zoom xon; | 8450 | legend (hax1, 'off');grid on;zoom xon; | ||
8660 | set(legend (hax1, 'show'), 'interp', 'none'); | 8451 | set(legend (hax1, 'show'), 'interp', 'none'); | ||
8661 |
| 8452 |
| ||
8662 | if ~param.FLAG.S2P | 8453 | if ~param.FLAG.S2P | ||
8663 | set(h,'CurrentAxes',hax2) | 8454 | set(h,'CurrentAxes',hax2) | ||
8664 | hold on | 8455 | hold on | ||
8665 | plot(chdata(i).TDR22(izt).t(:),chdata(i).TDR22(izt).ZSR,'disp',[ chdata(i).base ' Rx port']); | 8456 | plot(chdata(i).TDR22(izt).t(:),chdata(i).TDR22(izt).ZSR,'disp',[ chdata(i).base ' Rx port']); | ||
8666 | hold off | 8457 | hold off | ||
8667 | legend (hax2, 'off');grid on;zoom xon; | 8458 | legend (hax2, 'off');grid on;zoom xon; | ||
8668 | set(legend (hax2, 'show'), 'interp', 'none'); | 8459 | set(legend (hax2, 'show'), 'interp', 'none'); | ||
8669 | end | 8460 | end | ||
8670 |
| 8461 |
| ||
8671 | set(h,'CurrentAxes',hax3) | 8462 | set(h,'CurrentAxes',hax3) | ||
8672 | hold on | 8463 | hold on | ||
8673 | if OP.PTDR | 8464 | if OP.PTDR | ||
8674 | for izt=1:length(param.Z_t) | 8465 | for izt=1:length(param.Z_t) | ||
8675 | msg=[ chdata(i).base ' Tx port Zt=' num2str(param.Z_t(izt),3) ' ERL=', num2str(chdata(i).TDR11(izt).ERL, 3) 'db']; | 8466 | msg=[ chdata(i).base ' Tx port Zt=' num2str(param.Z_t(izt),3) ' ERL=', num2str(chdata(i).TDR11(izt).ERL, 3) 'db']; | ||
8676 | plot(chdata(i).TDR11(izt).t/param.ui,chdata(i).PDTR11(izt).ptdr,'disp',msg); | 8467 | plot(chdata(i).TDR11(izt).t/param.ui,chdata(i).PDTR11(izt).ptdr,'disp',msg); | ||
8677 | msg=['PTDR Zt=' num2str(param.Z_t(izt)/param.ui,3) ' worst sampled noise cursors ' 'Tx port Zt=' num2str(param.Z_t(izt),3) ]; | 8468 | msg=['PTDR Zt=' num2str(param.Z_t(izt)/param.ui,3) ' worst sampled noise cursors ' 'Tx port Zt=' num2str(param.Z_t(izt),3) ]; | ||
8678 | stem(TDR_results(izt,1).WC_ptdr_samples_t/param.ui,TDR_results(izt,1).WC_ptdr_samples,'disp',msg); | 8469 | stem(TDR_results(izt,1).WC_ptdr_samples_t/param.ui,TDR_results(izt,1).WC_ptdr_samples,'disp',msg); | ||
8679 | end | 8470 | end | ||
8680 | end | 8471 | end | ||
8681 | hold off | 8472 | hold off | ||
8682 | legend (hax3, 'off');grid on;zoom xon; | 8473 | legend (hax3, 'off');grid on;zoom xon; | ||
8683 | set(legend (hax3, 'show'), 'interp', 'none'); | 8474 | set(legend (hax3, 'show'), 'interp', 'none'); | ||
8684 | if ~param.FLAG.S2P | 8475 | if ~param.FLAG.S2P | ||
8685 | set(h,'CurrentAxes',hax4) | 8476 | set(h,'CurrentAxes',hax4) | ||
8686 | hold on | 8477 | hold on | ||
8687 | if OP.PTDR | 8478 | if OP.PTDR | ||
8688 | for izt=1:length(param.Z_t) | 8479 | for izt=1:length(param.Z_t) | ||
8689 | msg=[ chdata(i).base ' Tx port Zt=' num2str(param.Z_t(izt),3) ' ERL=', num2str(chdata(i).TDR22(izt).ERL, 3) 'db']; | 8480 | msg=[ chdata(i).base ' Tx port Zt=' num2str(param.Z_t(izt),3) ' ERL=', num2str(chdata(i).TDR22(izt).ERL, 3) 'db']; | ||
8690 | plot(chdata(i).TDR22(izt).t/param.ui,chdata(i).PDTR22(izt).ptdr,'disp',msg); | 8481 | plot(chdata(i).TDR22(izt).t/param.ui,chdata(i).PDTR22(izt).ptdr,'disp',msg); | ||
8691 | msg=['PTDR Zt=' num2str(param.Z_t(izt),3)/param.ui ' worst sampled noise cursors ' 'Rx port Zt=' num2str(param.Z_t(izt),3) ]; | 8482 | msg=['PTDR Zt=' num2str(param.Z_t(izt),3)/param.ui ' worst sampled noise cursors ' 'Rx port Zt=' num2str(param.Z_t(izt),3) ]; | ||
8692 | stem(TDR_results(izt,2).WC_ptdr_samples_t/param.ui,TDR_results(izt,2).WC_ptdr_samples,'disp',msg); | 8483 | stem(TDR_results(izt,2).WC_ptdr_samples_t/param.ui,TDR_results(izt,2).WC_ptdr_samples,'disp',msg); | ||
8693 | end | 8484 | end | ||
8694 | end | 8485 | end | ||
8695 | hold off | 8486 | hold off | ||
8696 | legend (hax4, 'off');grid on;zoom xon; | 8487 | legend (hax4, 'off');grid on;zoom xon; | ||
8697 | set(legend (hax4, 'show'), 'interp', 'none'); | 8488 | set(legend (hax4, 'show'), 'interp', 'none'); | ||
8698 | end | 8489 | end | ||
8699 | end | 8490 | end | ||
8700 | end | 8491 | end | ||
8701 | if param.FLAG.S2P, return; end | 8492 | if param.FLAG.S2P, return; end | ||
8702 | end | 8493 | end | ||
8703 | function S =r_parrelell2(zref,f,rpad) | 8494 | function S =r_parrelell2(zref,f,rpad) | ||
8704 | S.Parameters(1,1,:) = -zref/(rpad*(zref/rpad + 2)).*ones(1,length(f)); | 8495 | S.Parameters(1,1,:) = -zref/(rpad*(zref/rpad + 2)).*ones(1,length(f)); | ||
8705 | S.Parameters(2,2,:) = -zref/(rpad*(zref/rpad + 2)).*ones(1,length(f)); | 8496 | S.Parameters(2,2,:) = -zref/(rpad*(zref/rpad + 2)).*ones(1,length(f)); | ||
8706 | S.Parameters(2,1,:) = 2/(zref/rpad + 2).*ones(1,length(f)); | 8497 | S.Parameters(2,1,:) = 2/(zref/rpad + 2).*ones(1,length(f)); | ||
8707 | S.Parameters(1,2,:) = 2/(zref/rpad + 2).*ones(1,length(f)); | 8498 | S.Parameters(1,2,:) = 2/(zref/rpad + 2).*ones(1,length(f)); | ||
8708 | % Sm=sparameters(S.Parameters,f,zref); | 8499 | % Sm=sparameters(S.Parameters,f,zref); | ||
8709 | 8500 | ||||
8710 | 8501 | ||||
8711 | 8502 | ||||
8712 | 8503 | ||||
8713 | 8504 | ||||
8714 | function [sch,schFreqAxis]=read_Nport_touchstone(touchstone_file,port_order) | 8505 | function [sch,schFreqAxis]=read_Nport_touchstone(touchstone_file,port_order) | ||
8715 | 8506 | ||||
8716 | %touchstone_file: .sNp touchstone file to read | 8507 | %touchstone_file: .sNp touchstone file to read | ||
8717 | %port_order: port reorder vector | 8508 | %port_order: port reorder vector | ||
8718 | % | 8509 | % | ||
8719 | %sch: sparameter matrix | 8510 | %sch: sparameter matrix | ||
8720 | %schFreqAxis: frequency axis | 8511 | %schFreqAxis: frequency axis | ||
8721 | 8512 | ||||
8722 | [file_path,root_name,extension]=fileparts(touchstone_file); | 8513 | [file_path,root_name,extension]=fileparts(touchstone_file); | ||
8723 | fid=fopen(touchstone_file); | 8514 | fid=fopen(touchstone_file); | ||
8724 | 8515 | ||||
8725 | %fetch number of ports from extension | 8516 | %fetch number of ports from extension | ||
8726 | num_ports=str2num(char(regexp(extension,'\d*','match'))); | 8517 | num_ports=str2num(char(regexp(extension,'\d*','match'))); | ||
8727 | 8518 | ||||
8728 | %Get option line | 8519 | %Get option line | ||
8729 | [optstr,opt_pos] = textscan(fid,'%s',1,'Delimiter','','CommentStyle','!'); | 8520 | [optstr,opt_pos] = textscan(fid,'%s',1,'Delimiter','','CommentStyle','!'); | ||
8730 | optcell=textscan(optstr{1}{1},'%s'); | 8521 | optcell=textscan(optstr{1}{1},'%s'); | ||
8731 | optcell=optcell{1}; | 8522 | optcell=optcell{1}; | ||
8732 | while isempty(optcell) || isempty(strfind(optcell{1},'#')) | 8523 | while isempty(optcell) || isempty(strfind(optcell{1},'#')) | ||
8733 | %Some touchstone files need this. can't remember why now. maybe lines | 8524 | %Some touchstone files need this. can't remember why now. maybe lines | ||
8734 | %with whitespace but not empty but not commented | 8525 | %with whitespace but not empty but not commented | ||
8735 | [optstr,opt_pos] = textscan(fid,'%s',1,'Delimiter','','CommentStyle','!'); | 8526 | [optstr,opt_pos] = textscan(fid,'%s',1,'Delimiter','','CommentStyle','!'); | ||
8736 | optcell=textscan(optstr{1}{1},'%s'); | 8527 | optcell=textscan(optstr{1}{1},'%s'); | ||
8737 | optcell=optcell{1}; | 8528 | optcell=optcell{1}; | ||
8738 | end | 8529 | end | ||
8739 | 8530 | ||||
8740 | %read the entire file | 8531 | %read the entire file | ||
8741 | raw_read_data = textscan(fid,'%f %f %f %f %f %f %f %f %f','CollectOutput',true,'CommentStyle','!'); | 8532 | raw_read_data = textscan(fid,'%f %f %f %f %f %f %f %f %f','CollectOutput',true,'CommentStyle','!'); | ||
8742 | raw_column_data=raw_read_data{1}; | 8533 | raw_column_data=raw_read_data{1}; | ||
8743 | fclose(fid); | 8534 | fclose(fid); | ||
8744 | 8535 | ||||
8745 | %number of columns for 2D matrix | 8536 | %number of columns for 2D matrix | ||
8746 | columns=num_ports*num_ports*2+1; | 8537 | columns=num_ports*num_ports*2+1; | ||
8747 | 8538 | ||||
8748 | %find the frequency lines by searching for the right number of NaN | 8539 | %find the frequency lines by searching for the right number of NaN | ||
8749 | a=sum(isnan(raw_column_data),2); | 8540 | a=sum(isnan(raw_column_data),2); | ||
8750 | if num_ports==3 | 8541 | if num_ports==3 | ||
8751 | b=find(a==2); | 8542 | b=find(a==2); | ||
8752 | elseif num_ports==1 | 8543 | elseif num_ports==1 | ||
8753 | b=find(a==6); | 8544 | b=find(a==6); | ||
8754 | else | 8545 | else | ||
8755 | b=find(a==0); | 8546 | b=find(a==0); | ||
8756 | end | 8547 | end | ||
8757 | 8548 | ||||
8758 | num_freq=length(b); | 8549 | num_freq=length(b); | ||
8759 | 8550 | ||||
8760 | %toss out the NaN and reshape into a 2D matrix | 8551 | %toss out the NaN and reshape into a 2D matrix | ||
8761 | raw_input = raw_column_data.'; | 8552 | raw_input = raw_column_data.'; | ||
8762 | raw_input = raw_input(~isnan(raw_input)); | 8553 | raw_input = raw_input(~isnan(raw_input)); | ||
8763 | raw_input = reshape(raw_input,columns,num_freq).'; | 8554 | raw_input = reshape(raw_input,columns,num_freq).'; | ||
8764 | 8555 | ||||
8765 | %get the frequency mult | 8556 | %get the frequency mult | ||
8766 | frequency_mult_text=optcell{2}; | 8557 | frequency_mult_text=optcell{2}; | ||
8767 | if(strcmpi(frequency_mult_text,'hz')) | 8558 | if(strcmpi(frequency_mult_text,'hz')) | ||
8768 | frequency_mult=1; | 8559 | frequency_mult=1; | ||
8769 | elseif(strcmpi(frequency_mult_text,'khz')) | 8560 | elseif(strcmpi(frequency_mult_text,'khz')) | ||
8770 | frequency_mult=1e3; | 8561 | frequency_mult=1e3; | ||
8771 | elseif(strcmpi(frequency_mult_text,'mhz')) | 8562 | elseif(strcmpi(frequency_mult_text,'mhz')) | ||
8772 | frequency_mult=1e6; | 8563 | frequency_mult=1e6; | ||
8773 | elseif(strcmpi(frequency_mult_text,'ghz')) | 8564 | elseif(strcmpi(frequency_mult_text,'ghz')) | ||
8774 | frequency_mult=1e9; | 8565 | frequency_mult=1e9; | ||
8775 | else | 8566 | else | ||
8776 | error('Unsupported format for frequency multiplier %s',frequency_mult_text); | 8567 | error('Unsupported format for frequency multiplier %s',frequency_mult_text); | ||
8777 | end | 8568 | end | ||
8778 | 8569 | ||||
8779 | %get the RI/MA/DB format | 8570 | %get the RI/MA/DB format | ||
8780 | format=optcell{4}; | 8571 | format=optcell{4}; | ||
8781 | %get Z0 | 8572 | %get Z0 | ||
8782 | port_impedance=str2double(optcell(6:end))'; | 8573 | port_impedance=str2double(optcell(6:end))'; | ||
8783 | 8574 | ||||
8784 | 8575 | ||||
8785 | %grab frequency | 8576 | %grab frequency | ||
8786 | raw_input(:,1)=raw_input(:,1)*frequency_mult; | 8577 | raw_input(:,1)=raw_input(:,1)*frequency_mult; | ||
8787 | Spar.F=raw_input(:,1); | 8578 | Spar.F=raw_input(:,1); | ||
8788 | Spar.F=transpose(Spar.F(:)); | 8579 | Spar.F=transpose(Spar.F(:)); | ||
8789 | 8580 | ||||
8790 | 8581 | ||||
8791 | %transform data to real imaginary | 8582 | %transform data to real imaginary | ||
8792 | %for 2.0 support, keep it in 2D form instead of 3D because we may need to process upper/lower sparse matrix definitions | 8583 | %for 2.0 support, keep it in 2D form instead of 3D because we may need to process upper/lower sparse matrix definitions | ||
8793 | if(strcmpi(format,'ri')) | 8584 | if(strcmpi(format,'ri')) | ||
8794 | ri_data_2D=raw_input(:,2:2:end)+raw_input(:,3:2:end)*1i; | 8585 | ri_data_2D=raw_input(:,2:2:end)+raw_input(:,3:2:end)*1i; | ||
8795 | elseif(strcmpi(format,'ma')) | 8586 | elseif(strcmpi(format,'ma')) | ||
8796 | mag_data=raw_input(:,2:2:end); | 8587 | mag_data=raw_input(:,2:2:end); | ||
8797 | rad_data=raw_input(:,3:2:end)*pi/180; | 8588 | rad_data=raw_input(:,3:2:end)*pi/180; | ||
8798 | ri_data_2D=mag_data.*cos(rad_data)+mag_data.*sin(rad_data)*1i; | 8589 | ri_data_2D=mag_data.*cos(rad_data)+mag_data.*sin(rad_data)*1i; | ||
8799 | elseif(strcmpi(format,'db')) | 8590 | elseif(strcmpi(format,'db')) | ||
8800 | mag_data=10.^(raw_input(:,2:2:end)/20); | 8591 | mag_data=10.^(raw_input(:,2:2:end)/20); | ||
8801 | rad_data=raw_input(:,3:2:end)*pi/180; | 8592 | rad_data=raw_input(:,3:2:end)*pi/180; | ||
8802 | ri_data_2D=mag_data.*cos(rad_data)+mag_data.*sin(rad_data)*1i; | 8593 | ri_data_2D=mag_data.*cos(rad_data)+mag_data.*sin(rad_data)*1i; | ||
8803 | else | 8594 | else | ||
8804 | error('Format %s is not supported. Use RI MA or DB',format); | 8595 | error('Format %s is not supported. Use RI MA or DB',format); | ||
8805 | end | 8596 | end | ||
8806 | 8597 | ||||
8807 | 8598 | ||||
8808 | 8599 | ||||
8809 | %transform to 3D | 8600 | %transform to 3D | ||
8810 | %allow for upper/lower matrix specification for touchstone 2.0 support | 8601 | %allow for upper/lower matrix specification for touchstone 2.0 support | ||
8811 | matrix_format=0; | 8602 | matrix_format=0; | ||
8812 | if(matrix_format==0) | 8603 | if(matrix_format==0) | ||
8813 | %full | 8604 | %full | ||
8814 | for j=1:num_ports | 8605 | for j=1:num_ports | ||
8815 | pre_out.sp(j,1:num_ports,:)=transpose(ri_data_2D( :,(j-1)*num_ports+1:j*num_ports)); | 8606 | pre_out.sp(j,1:num_ports,:)=transpose(ri_data_2D( :,(j-1)*num_ports+1:j*num_ports)); | ||
8816 | end | 8607 | end | ||
8817 | elseif(matrix_format==1) | 8608 | elseif(matrix_format==1) | ||
8818 | %upper | 8609 | %upper | ||
8819 | used_ports=0; | 8610 | used_ports=0; | ||
8820 | for j=1:num_ports | 8611 | for j=1:num_ports | ||
8821 | stated_ports=num_ports-j+1; | 8612 | stated_ports=num_ports-j+1; | ||
8822 | pre_out.sp(j,j:num_ports,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | 8613 | pre_out.sp(j,j:num_ports,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | ||
8823 | pre_out.sp(j:num_ports,j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | 8614 | pre_out.sp(j:num_ports,j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | ||
8824 | used_ports=used_ports+stated_ports; | 8615 | used_ports=used_ports+stated_ports; | ||
8825 | end | 8616 | end | ||
8826 | elseif(matrix_format==2) | 8617 | elseif(matrix_format==2) | ||
8827 | %lower | 8618 | %lower | ||
8828 | used_ports=0; | 8619 | used_ports=0; | ||
8829 | for j=1:num_ports | 8620 | for j=1:num_ports | ||
8830 | stated_ports=j; | 8621 | stated_ports=j; | ||
8831 | pre_out.sp(j,1:j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | 8622 | pre_out.sp(j,1:j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | ||
8832 | pre_out.sp(1:j,j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | 8623 | pre_out.sp(1:j,j,:)=transpose(ri_data_2D( :,used_ports+1:used_ports+stated_ports)); | ||
8833 | used_ports=used_ports+stated_ports; | 8624 | used_ports=used_ports+stated_ports; | ||
8834 | end | 8625 | end | ||
8835 | else | 8626 | else | ||
8836 | error('Matrix format is not supported. Use Full, Lower, or Upper'); | 8627 | error('Matrix format is not supported. Use Full, Lower, or Upper'); | ||
8837 | end | 8628 | end | ||
8838 | 8629 | ||||
8839 | 8630 | ||||
8840 | %check for swapping the 2 port matrix (required on 1.x spec) | 8631 | %check for swapping the 2 port matrix (required on 1.x spec) | ||
8841 | two_port_swap=1; | 8632 | two_port_swap=1; | ||
8842 | if(num_ports==2 && two_port_swap==1) | 8633 | if(num_ports==2 && two_port_swap==1) | ||
8843 | temp=pre_out.sp(1,2,:); | 8634 | temp=pre_out.sp(1,2,:); | ||
8844 | pre_out.sp(1,2,:)=pre_out.sp(2,1,:); | 8635 | pre_out.sp(1,2,:)=pre_out.sp(2,1,:); | ||
8845 | pre_out.sp(2,1,:)=temp; | 8636 | pre_out.sp(2,1,:)=temp; | ||
8846 | end | 8637 | end | ||
8847 | 8638 | ||||
8848 | Spar.S=pre_out.sp; | 8639 | Spar.S=pre_out.sp; | ||
8849 | Spar.Z0=transpose(port_impedance(:)); | 8640 | Spar.Z0=transpose(port_impedance(:)); | ||
8850 | 8641 | ||||
8851 | if length(Spar.Z0)>1 | 8642 | if length(Spar.Z0)>1 | ||
8852 | error('Each port must have the same reference impedance'); | 8643 | error('Each port must have the same reference impedance'); | ||
8853 | end | 8644 | end | ||
8854 | if ~isequal(Spar.Z0,50) | 8645 | if ~isequal(Spar.Z0,50) | ||
8855 | warning('Reference impedance of %0.6g ohms renormalized to 50 ohms',Spar.Z0); | 8646 | warning('Reference impedance of %0.6g ohms renormalized to 50 ohms',Spar.Z0); | ||
8856 | %Renormalize to 50 ohms | 8647 | %Renormalize to 50 ohms | ||
8857 | rho=(50-Spar.Z0)/(50+Spar.Z0); | 8648 | rho=(50-Spar.Z0)/(50+Spar.Z0); | ||
8858 | p=num_ports; | 8649 | p=num_ports; | ||
8859 | s_old=Spar.S; | 8650 | s_old=Spar.S; | ||
8860 | for k=1:num_freq | 8651 | for k=1:num_freq | ||
8861 | Spar.S(:,:,k)=inv(eye(p,p)-rho*s_old(:,:,k))*(s_old(:,:,k)-rho*eye(p,p)); | 8652 | Spar.S(:,:,k)=inv(eye(p,p)-rho*s_old(:,:,k))*(s_old(:,:,k)-rho*eye(p,p)); | ||
8862 | end | 8653 | end | ||
8863 | end | 8654 | end | ||
8864 | 8655 | ||||
8865 | %These operations sync up with COM style Spar matrix | 8656 | %These operations sync up with COM style Spar matrix | ||
8866 | %1: put frequency as first dimension | 8657 | %1: put frequency as first dimension | ||
8867 | sch=shiftdim(Spar.S,2); | 8658 | sch=shiftdim(Spar.S,2); | ||
8868 | %2: reorder ports according to "ports" input | 8659 | %2: reorder ports according to "ports" input | ||
8869 | sch=sch(:,port_order,port_order); | 8660 | sch=sch(:,port_order,port_order); | ||
8870 | schFreqAxis=Spar.F; | 8661 | schFreqAxis=Spar.F; | ||
8871 | function [chdata, param] = read_PR_files(param, OP, chdata) | 8662 | function [chdata, param] = read_PR_files(param, OP, chdata) | ||
8872 | %% Read in pulse response | 8663 | %% Read in pulse response | ||
8873 | % extract s-parameter data from files and apply tx and rx filters as well as package filters | 8664 | % extract s-parameter data from files and apply tx and rx filters as well as package filters | ||
8874 | num_files=length(chdata); | 8665 | num_files=length(chdata); | ||
8875 | M=param.samples_per_ui; | 8666 | M=param.samples_per_ui; | ||
8876 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | 8667 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | ||
8877 | for i=1:num_files | 8668 | for i=1:num_files | ||
8878 | if OP.DISPLAY_WINDOW; hwaitbar=waitbar(0);end | 8669 | if OP.DISPLAY_WINDOW; hwaitbar=waitbar(0);end | ||
8879 | progress = i/num_files; | 8670 | progress = i/num_files; | ||
8880 | if OP.DISPLAY_WINDOW | 8671 | if OP.DISPLAY_WINDOW | ||
8881 | [~,a]=fileparts(chdata(i).filename); | 8672 | [~,a]=fileparts(chdata(i).filename); | ||
8882 | waitbar(progress, hwaitbar, ['Processing ' a]); figure(hwaitbar); drawnow; | 8673 | waitbar(progress, hwaitbar, ['Processing ' a]); figure(hwaitbar); drawnow; | ||
8883 | else | 8674 | else | ||
8884 | fprintf('%i ',i); | 8675 | fprintf('%i ',i); | ||
8885 | end | 8676 | end | ||
8886 | switch chdata(i).ext | 8677 | switch chdata(i).ext | ||
8887 | case '.csv' | 8678 | case '.csv' | ||
8888 | vt=load(chdata(i).filename); | 8679 | vt=load(chdata(i).filename); | ||
8889 | % many PR's need to have precursors added: we'll a 2 here RIM 5-24-2021 | 8680 | % many PR's need to have precursors added: we'll a 2 here RIM 5-24-2021 | ||
8890 | chdata(i).uneq_pulse_response=[ zeros(3*param.samples_per_ui, 1) ; vt(:,2) ]; | 8681 | chdata(i).uneq_pulse_response=[ zeros(3*param.samples_per_ui, 1) ; vt(:,2) ]; | ||
8891 | dt=vt(2,1)-vt(1,1); | 8682 | dt=vt(2,1)-vt(1,1); | ||
8892 | chdata(i).t= [ (0:3*param.samples_per_ui-1).'*dt ; vt(:,1)+3*param.samples_per_ui*dt]; | 8683 | chdata(i).t= [ (0:3*param.samples_per_ui-1).'*dt ; vt(:,1)+3*param.samples_per_ui*dt]; | ||
8893 |
| 8684 |
| ||
8894 |
| 8685 |
| ||
8895 | step_shifting_vector=kron(ones(1,floor(length( chdata(i).uneq_pulse_response)/M)) ,[ 1 zeros(1,M-1) ]) ; | 8686 | step_shifting_vector=kron(ones(1,floor(length( chdata(i).uneq_pulse_response)/M)) ,[ 1 zeros(1,M-1) ]) ; | ||
8896 | step_response=filter(step_shifting_vector,1,chdata(i).uneq_pulse_response); | 8687 | step_response=filter(step_shifting_vector,1,chdata(i).uneq_pulse_response); | ||
8897 | Vf=step_response(end); | 8688 | Vf=step_response(end); | ||
8898 | chdata(i).uneq_imp_response=step_response-circshift(step_response,1); % too noisey to be usefull | 8689 | chdata(i).uneq_imp_response=step_response-circshift(step_response,1); % too noisey to be usefull | ||
8899 | chdata(i).uneq_imp_response(1)=chdata(i).uneq_imp_response(2); | 8690 | chdata(i).uneq_imp_response(1)=chdata(i).uneq_imp_response(2); | ||
8900 |
| 8691 |
| ||
8901 | end | 8692 | end | ||
8902 | end | 8693 | end | ||
8903 | function [param,OP]= read_ParamConfigFile(paramFile,OP) | 8694 | function [param,OP]= read_ParamConfigFile(paramFile,OP) | ||
8904 | %warning('off','MATLAB:xlsread:Mode'); % suppress warning messages for reading the settings file from XLS | 8695 | %warning('off','MATLAB:xlsread:Mode'); % suppress warning messages for reading the settings file from XLS | ||
8905 | [filepath,name,ext] = fileparts(paramFile); | 8696 | [filepath,name,ext] = fileparts(paramFile); | ||
8906 | if ~isempty(filepath) | 8697 | if ~isempty(filepath) | ||
8907 | filepath=[filepath '\']; | 8698 | filepath=[filepath '\']; | ||
8908 | end | 8699 | end | ||
8909 | matcongfile=[filepath name '.mat']; | 8700 | matcongfile=[filepath name '.mat']; | ||
8910 | try | 8701 | try | ||
8911 | switch upper(ext) | 8702 | switch upper(ext) | ||
8912 | case upper('.mat') | 8703 | case upper('.mat') | ||
8913 | load(matcongfile) | 8704 | load(matcongfile) | ||
8914 | case upper('.csv') | 8705 | case upper('.csv') | ||
8915 | [na1, na2, parameter] = xlsread(paramFile); | 8706 | [na1, na2, parameter] = xlsread(paramFile); | ||
8916 | otherwise | 8707 | otherwise | ||
8917 | [na1, na2, parameter] = xlsread(paramFile,'COM_Settings','',''); %#ok<ASGLU> % Import data from the settings file (imports the entire sheet) | 8708 | [na1, na2, parameter] = xlsread(paramFile,'COM_Settings','',''); %#ok<ASGLU> % Import data from the settings file (imports the entire sheet) | ||
8918 | end | 8709 | end | ||
8919 |
| 8710 |
| ||
8920 | catch ME %#ok<NASGU> | 8711 | catch ME %#ok<NASGU> | ||
8921 | warning('off','MATLAB:xlsread:Mode'); % suppress warning messages for reading the settings file from XLS | 8712 | warning('off','MATLAB:xlsread:Mode'); % suppress warning messages for reading the settings file from XLS | ||
8922 | switch upper(ext) | 8713 | switch upper(ext) | ||
8923 | case upper('.mat') | 8714 | case upper('.mat') | ||
8924 | load(matcongfile) | 8715 | load(matcongfile) | ||
8925 | case upper('.csv') | 8716 | case upper('.csv') | ||
8926 | [na1, na2, parameter] = xlsread(paramFile); | 8717 | [na1, na2, parameter] = xlsread(paramFile); | ||
8927 | otherwise | 8718 | otherwise | ||
8928 | [na1, na2, parameter] = xlsread(paramFile,'COM_Settings','','basic'); %#ok<ASGLU> % Import data from the settings file (imports the entire sheet) | 8719 | [na1, na2, parameter] = xlsread(paramFile,'COM_Settings','','basic'); %#ok<ASGLU> % Import data from the settings file (imports the entire sheet) | ||
8929 | end | 8720 | end | ||
8930 | end | 8721 | end | ||
8931 | 8722 | ||||
8932 | %% New section to parse .START package data | 8723 | %% New section to parse .START package data | ||
8933 | first_column_data = parameter(:,1); | 8724 | first_column_data = parameter(:,1); | ||
8934 | start_data_rows = find(strcmp(first_column_data,'.START')); | 8725 | start_data_rows = find(strcmp(first_column_data,'.START')); | ||
8935 | if ~isempty(start_data_rows) | 8726 | if ~isempty(start_data_rows) | ||
8936 | end_data_rows = find(strcmp(first_column_data,'.END')); | 8727 | end_data_rows = find(strcmp(first_column_data,'.END')); | ||
8937 | if length(start_data_rows) ~= length(end_data_rows) | 8728 | if length(start_data_rows) ~= length(end_data_rows) | ||
8938 | error('Number of .START and .END must be the same'); | 8729 | error('Number of .START and .END must be the same'); | ||
8939 | end | 8730 | end | ||
8940 | first_start_row = start_data_rows(1); | 8731 | first_start_row = start_data_rows(1); | ||
8941 | special_parameter = parameter; | 8732 | special_parameter = parameter; | ||
8942 | parameter = parameter(1:first_start_row-1,:); | 8733 | parameter = parameter(1:first_start_row-1,:); | ||
8943 | for j=1:length(start_data_rows) | 8734 | for j=1:length(start_data_rows) | ||
8944 | this_block = special_parameter(start_data_rows(j)+1:end_data_rows(j)-1,:); | 8735 | this_block = special_parameter(start_data_rows(j)+1:end_data_rows(j)-1,:); | ||
8945 | pkg_name = special_parameter{start_data_rows(j),2}; | 8736 | pkg_name = special_parameter{start_data_rows(j),2}; | ||
8946 |
| 8737 |
| ||
8947 | %Read all the parameters that make up a package | 8738 | %Read all the parameters that make up a package | ||
8948 | PKG_param = read_package_parameters(this_block); | 8739 | PKG_param = read_package_parameters(this_block); | ||
8949 |
| 8740 |
| ||
8950 | %save the data in a field revealed by pkg_name | 8741 | %save the data in a field revealed by pkg_name | ||
8951 | param.PKG.(pkg_name) = PKG_param; | 8742 | param.PKG.(pkg_name) = PKG_param; | ||
8952 |
| 8743 |
| ||
8953 |
| 8744 |
| ||
8954 | end | 8745 | end | ||
8955 | end | 8746 | end | ||
8956 | %Allow specification of TX and RX package section through PKG_NAME keyword | 8747 | %Allow specification of TX and RX package section through PKG_NAME keyword | ||
8957 | %the values must match package blocks specified in .START sections | 8748 | %the values must match package blocks specified in .START sections | ||
8958 | param.PKG_NAME= xls_parameter(parameter, 'PKG_NAME', false,''); | 8749 | param.PKG_NAME= xls_parameter(parameter, 'PKG_NAME', false,''); | ||
8959 | if isnan(param.PKG_NAME) | 8750 | if isnan(param.PKG_NAME) | ||
8960 | param.PKG_NAME = ''; | 8751 | param.PKG_NAME = ''; | ||
8961 | end | 8752 | end | ||
8962 | if isempty(param.PKG_NAME) | 8753 | if isempty(param.PKG_NAME) | ||
8963 | param.PKG_NAME = {}; | 8754 | param.PKG_NAME = {}; | ||
8964 | else | 8755 | else | ||
8965 | param.PKG_NAME = strsplit(param.PKG_NAME); | 8756 | param.PKG_NAME = strsplit(param.PKG_NAME); | ||
8966 | end | 8757 | end | ||
8967 | if ~isempty(param.PKG_NAME) && ~isfield(param,'PKG') | 8758 | if ~isempty(param.PKG_NAME) && ~isfield(param,'PKG') | ||
8968 | error('PKG_NAME can only be used if .START blocks for package parameters are used'); | 8759 | error('PKG_NAME can only be used if .START blocks for package parameters are used'); | ||
8969 | end | 8760 | end | ||
8970 | for j=1:length(param.PKG_NAME) | 8761 | for j=1:length(param.PKG_NAME) | ||
8971 | if ~isfield(param.PKG,param.PKG_NAME{j}) | 8762 | if ~isfield(param.PKG,param.PKG_NAME{j}) | ||
8972 | error('Package Block "%s" not found',param.PKG_NAME{j}); | 8763 | error('Package Block "%s" not found',param.PKG_NAME{j}); | ||
8973 | end | 8764 | end | ||
8974 | end | 8765 | end | ||
8975 | 8766 | ||||
8976 | %% | 8767 | %% | ||
8977 | % just need to define so we can pass | 8768 | % just need to define so we can pass | ||
8978 | param.c=[.4e-12 .4e-12]; | 8769 | param.c=[.4e-12 .4e-12]; | ||
8979 | param.alen=[ 20 30 550 ]; | 8770 | param.alen=[ 20 30 550 ]; | ||
8980 | param.az=[100 120 100]; | 8771 | param.az=[100 120 100]; | ||
8981 | 8772 | ||||
8982 | % make control for package/channel reflection control | 8773 | % make control for package/channel reflection control | ||
8983 | param.kappa1= xls_parameter(parameter, 'kappa1', true,1); % if set 0 reflection at tp0 are omitted from COM | 8774 | param.kappa1= xls_parameter(parameter, 'kappa1', true,1); % if set 0 reflection at tp0 are omitted from COM | ||
8984 | param.kappa2= xls_parameter(parameter, 'kappa2', true,1); % if set 0 reflection at tp5 are omitted from COM | 8775 | param.kappa2= xls_parameter(parameter, 'kappa2', true,1); % if set 0 reflection at tp5 are omitted from COM | ||
8985 | 8776 | ||||
8986 | 8777 | ||||
8987 | % make compatible with presentation of kappa | 8778 | % make compatible with presentation of kappa | ||
8988 | 8779 | ||||
8989 | % Default values are given for parameters when they are common to all clauses in 802.3bj and 803.2bm. | 8780 | % Default values are given for parameters when they are common to all clauses in 802.3bj and 803.2bm. | ||
8990 | 8781 | ||||
8991 | OP.dynamic_txffe = xls_parameter(parameter, 'Dynamic TXFFE', false,1); % Temporary switch for testing new optimize_fom with dynamic txffe | 8782 | OP.dynamic_txffe = xls_parameter(parameter, 'Dynamic TXFFE', false,1); % Temporary switch for testing new optimize_fom with dynamic txffe | ||
8992 | OP.FloatingDFE_Development = xls_parameter(parameter, 'FloatingDFE_Development', false,1); % Temporary switch for testing new floating dfe routine | 8783 | OP.FloatingDFE_Development = xls_parameter(parameter, 'FloatingDFE_Development', false,1); % Temporary switch for testing new floating dfe routine | ||
8993 | 8784 | ||||
8994 | param.fb = xls_parameter(parameter, 'f_b')*1e9; % Baud (Signaling) rate in Gbaud | 8785 | param.fb = xls_parameter(parameter, 'f_b')*1e9; % Baud (Signaling) rate in Gbaud | ||
8995 | param.f2 = xls_parameter(parameter, 'f_2', true, param.fb/1e9 )*1e9; % frequency in GHz for intergration compuation of ICN or FOM_Ild in GHz | 8786 | param.f2 = xls_parameter(parameter, 'f_2', true, param.fb/1e9 )*1e9; % frequency in GHz for intergration compuation of ICN or FOM_Ild in GHz | ||
8996 | param.max_start_freq = xls_parameter(parameter, 'f_min')*1e9; % minimum required frequency start for s parameters | 8787 | param.max_start_freq = xls_parameter(parameter, 'f_min')*1e9; % minimum required frequency start for s parameters | ||
8997 | param.f1 = xls_parameter(parameter, 'f_1', true, param.max_start_freq/1e9)*1e9; % start frequency for ICN and ILD calculations in GHz | 8788 | param.f1 = xls_parameter(parameter, 'f_1', true, param.max_start_freq/1e9)*1e9; % start frequency for ICN and ILD calculations in GHz | ||
8998 | param.max_freq_step = xls_parameter(parameter, 'Delta_f')*1e9; % freqency step | 8789 | param.max_freq_step = xls_parameter(parameter, 'Delta_f')*1e9; % freqency step | ||
8999 | param.tx_ffe_c0_min = xls_parameter(parameter, 'c(0)', false); % TX equalizer cursor minimum value (actual value is calculated as 1-sum(abs(tap)), Grid seat ingored for when C(0) is below this value | 8790 | param.tx_ffe_c0_min = xls_parameter(parameter, 'c(0)', false); % TX equalizer cursor minimum value (actual value is calculated as 1-sum(abs(tap)), Grid seat ingored for when C(0) is below this value | ||
9000 | 8791 | ||||
9001 | if OP.dynamic_txffe | 8792 | if OP.dynamic_txffe | ||
9002 | found_pre=1; | 8793 | found_pre=1; | ||
9003 | pre_count=1; | 8794 | pre_count=1; | ||
9004 | while found_pre | 8795 | while found_pre | ||
9005 | [p,found_pre]=xls_parameter_txffe(parameter,sprintf('c(-%d)',pre_count)); | 8796 | [p,found_pre]=xls_parameter_txffe(parameter,sprintf('c(-%d)',pre_count)); | ||
9006 | if found_pre | 8797 | if found_pre | ||
9007 | field_name=sprintf('tx_ffe_cm%d_values',pre_count); | 8798 | field_name=sprintf('tx_ffe_cm%d_values',pre_count); | ||
9008 | param.(field_name)=p; | 8799 | param.(field_name)=p; | ||
9009 | pre_count=pre_count+1; | 8800 | pre_count=pre_count+1; | ||
9010 | end | 8801 | end | ||
9011 | end | 8802 | end | ||
9012 | found_post=1; | 8803 | found_post=1; | ||
9013 | post_count=1; | 8804 | post_count=1; | ||
9014 | while found_post | 8805 | while found_post | ||
9015 | [p,found_post]=xls_parameter_txffe(parameter,sprintf('c(%d)',post_count)); | 8806 | [p,found_post]=xls_parameter_txffe(parameter,sprintf('c(%d)',post_count)); | ||
9016 | if found_post | 8807 | if found_post | ||
9017 | field_name=sprintf('tx_ffe_cp%d_values',post_count); | 8808 | field_name=sprintf('tx_ffe_cp%d_values',post_count); | ||
9018 | param.(field_name)=p; | 8809 | param.(field_name)=p; | ||
9019 | post_count=post_count+1; | 8810 | post_count=post_count+1; | ||
9020 | end | 8811 | end | ||
9021 | end | 8812 | end | ||
9022 | else | 8813 | else | ||
9023 | param.tx_ffe_cm4_values = xls_parameter(parameter, 'c(-4)', true,0); % TX equalizer pre cursor tap -4 individual settings or range. If not present ignored | 8814 | param.tx_ffe_cm4_values = xls_parameter(parameter, 'c(-4)', true,0); % TX equalizer pre cursor tap -4 individual settings or range. If not present ignored | ||
9024 | param.tx_ffe_cm3_values = xls_parameter(parameter, 'c(-3)', true,0); % TX equalizer pre cursor tap -3 individual settings or range. If not present ignored | 8815 | param.tx_ffe_cm3_values = xls_parameter(parameter, 'c(-3)', true,0); % TX equalizer pre cursor tap -3 individual settings or range. If not present ignored | ||
9025 | param.tx_ffe_cm2_values = xls_parameter(parameter, 'c(-2)', true,0); % TX equalizer pre cursor tap -2 individual settings or range. If not present ignored | 8816 | param.tx_ffe_cm2_values = xls_parameter(parameter, 'c(-2)', true,0); % TX equalizer pre cursor tap -2 individual settings or range. If not present ignored | ||
9026 | param.tx_ffe_cm1_values = xls_parameter(parameter, 'c(-1)', true,0); % TX equalizer pre cursor tap -1 individual settings or range. If not present ignored | 8817 | param.tx_ffe_cm1_values = xls_parameter(parameter, 'c(-1)', true,0); % TX equalizer pre cursor tap -1 individual settings or range. If not present ignored | ||
9027 | param.tx_ffe_cp1_values = xls_parameter(parameter, 'c(1)', true,0); % TX equalizer post cursor tap 1 individual settings or range. If not present ignored | 8818 | param.tx_ffe_cp1_values = xls_parameter(parameter, 'c(1)', true,0); % TX equalizer post cursor tap 1 individual settings or range. If not present ignored | ||
9028 | param.tx_ffe_cp2_values = xls_parameter(parameter, 'c(2)', true,0); % TX equalizer post cursor tap 2 individual settings or range. If not present ignored | 8819 | param.tx_ffe_cp2_values = xls_parameter(parameter, 'c(2)', true,0); % TX equalizer post cursor tap 2 individual settings or range. If not present ignored | ||
9029 | param.tx_ffe_cp3_values = xls_parameter(parameter, 'c(3)', true,0); % TX equalizer post cursor tap 3 individual settings or range. If not present ignored | 8820 | param.tx_ffe_cp3_values = xls_parameter(parameter, 'c(3)', true,0); % TX equalizer post cursor tap 3 individual settings or range. If not present ignored | ||
9030 | end | 8821 | end | ||
9031 | param.ndfe = xls_parameter(parameter, 'N_b'); % Decision feedback fixed equalizer (DFE) length | 8822 | param.ndfe = xls_parameter(parameter, 'N_b'); % Decision feedback fixed equalizer (DFE) length | ||
9032 | param.N_v = xls_parameter(parameter, 'N_v',true,param.ndfe); % number of UI used to compute Vf | 8823 | param.N_v = xls_parameter(parameter, 'N_v',true,param.ndfe); % number of UI used to compute Vf | ||
9033 | param.D_p = xls_parameter(parameter, 'D_p',true, 4 ); % number of precursor UI's used to compute Vf Default to 10 | 8824 | param.D_p = xls_parameter(parameter, 'D_p',true, 4 ); % number of precursor UI's used to compute Vf Default to 10 | ||
9034 | param.N_bx = xls_parameter(parameter, 'N_bx', true, param.ndfe ); % Used for ERL to Compensate for a number of Ui assoicated with the DFE | 8825 | param.N_bx = xls_parameter(parameter, 'N_bx', true, param.ndfe ); % Used for ERL to Compensate for a number of Ui assoicated with the DFE | ||
9035 | % support for floating taps | 8826 | % support for floating taps | ||
9036 | param.N_bg=xls_parameter(parameter, 'N_bg', true,0); % number of group of floating tap. Used as a switch, 0 means no float | 8827 | param.N_bg=xls_parameter(parameter, 'N_bg', true,0); % number of group of floating tap. Used as a switch, 0 means no float | ||
9037 | param.N_bf=xls_parameter(parameter, 'N_bf', true,6); % number of taps in group | 8828 | param.N_bf=xls_parameter(parameter, 'N_bf', true,6); % number of taps in group | ||
9038 | param.N_bmax=xls_parameter(parameter, 'N_bmax', true, param.ndfe); % UI span for floating taps | 8829 | param.N_bmax=xls_parameter(parameter, 'N_bmax', true, param.ndfe); % UI span for floating taps | ||
9039 | param.N_bmax=xls_parameter(parameter, 'N_f', true, param.ndfe); % UI span for floating taps. replaced by N_bmax | 8830 | param.N_bmax=xls_parameter(parameter, 'N_f', true, param.ndfe); % UI span for floating taps. replaced by N_bmax | ||
9040 | param.N_f=xls_parameter(parameter, 'N_f', true, param.ndfe); % UI span for floating taps for rX FFE | 8831 | param.N_f=xls_parameter(parameter, 'N_f', true, param.ndfe); % UI span for floating taps for rX FFE | ||
9041 | if param.N_bg == 0, param.N_bmax=param.ndfe; end | 8832 | if param.N_bg == 0, param.N_bmax=param.ndfe; end | ||
9042 | param.bmaxg=xls_parameter(parameter, 'bmaxg', true,0.2); % max DFE value for floating taps | 8833 | param.bmaxg=xls_parameter(parameter, 'bmaxg', true,0.2); % max DFE value for floating taps | ||
9043 | 8834 | ||||
9044 | % support for tail tap power limitations | 8835 | % support for tail tap power limitations | ||
9045 | param.B_float_RSS_MAX=xls_parameter(parameter, 'B_float_RSS_MAX', true,0); % floating DFE tap start for RSS floating tap limit | 8836 | param.B_float_RSS_MAX=xls_parameter(parameter, 'B_float_RSS_MAX', true,0); % floating DFE tap start for RSS floating tap limit | ||
9046 | param.N_tail_start=xls_parameter(parameter, 'N_tail_start', true,0); % start range for max RSS limit for DFE taps | 8837 | param.N_tail_start=xls_parameter(parameter, 'N_tail_start', true,0); % start range for max RSS limit for DFE taps | ||
9047 | % | 8838 | % | ||
9048 | param.dfe_delta = xls_parameter(parameter, 'N_b_step', true,0); % discreatiztion of DFE, 0 disables and is not normally used | 8839 | param.dfe_delta = xls_parameter(parameter, 'N_b_step', true,0); % discreatiztion of DFE, 0 disables and is not normally used | ||
9049 | param.ffe_pre_tap_len=xls_parameter(parameter, 'ffe_pre_tap_len', true,0); % RX ffe pre cursor tap length | 8840 | param.ffe_pre_tap_len=xls_parameter(parameter, 'ffe_pre_tap_len', true,0); % RX ffe pre cursor tap length | ||
9050 | param.RxFFE_cmx=param.ffe_pre_tap_len; | 8841 | param.RxFFE_cmx=param.ffe_pre_tap_len; | ||
9051 | param.ffe_post_tap_len=xls_parameter(parameter, 'ffe_post_tap_len', true,0); % Rx FFE post cursor tap length | 8842 | param.ffe_post_tap_len=xls_parameter(parameter, 'ffe_post_tap_len', true,0); % Rx FFE post cursor tap length | ||
9052 | param.RxFFE_cpx=param.ffe_post_tap_len; | 8843 | param.RxFFE_cpx=param.ffe_post_tap_len; | ||
9053 | param.ffe_tap_step_size=xls_parameter(parameter, 'ffe_tap_step_size', true,0); % Rx FFE tap step size | 8844 | param.ffe_tap_step_size=xls_parameter(parameter, 'ffe_tap_step_size', true,0); % Rx FFE tap step size | ||
9054 | param.RxFFE_stepz=param.ffe_tap_step_size; | 8845 | param.RxFFE_stepz=param.ffe_tap_step_size; | ||
9055 | param.ffe_main_cursor_min=xls_parameter(parameter, 'ffe_main_cursor_min', true,1); % Rx FFE main cursor miminum | 8846 | param.ffe_main_cursor_min=xls_parameter(parameter, 'ffe_main_cursor_min', true,1); % Rx FFE main cursor miminum | ||
9056 | param.ffe_pre_tap1_max=xls_parameter(parameter, 'ffe_pre_tap1_max', true,.7); % Rx FFE precursor tap1 limit | 8847 | param.ffe_pre_tap1_max=xls_parameter(parameter, 'ffe_pre_tap1_max', true,.7); % Rx FFE precursor tap1 limit | ||
9057 | param.ffe_post_tap1_max=xls_parameter(parameter, 'ffe_post_tap1_max', true,.7); % Rx FFE post cursor tap1 limit | 8848 | param.ffe_post_tap1_max=xls_parameter(parameter, 'ffe_post_tap1_max', true,.7); % Rx FFE post cursor tap1 limit | ||
9058 | param.ffe_tapn_max=xls_parameter(parameter, 'ffe_tapn_max', true,.7); % Rx FFE precursor tapn limit | 8849 | param.ffe_tapn_max=xls_parameter(parameter, 'ffe_tapn_max', true,.7); % Rx FFE precursor tapn limit | ||
9059 | param.ffe_backoff=xls_parameter(parameter, 'ffe_backoff', true,0); % see if better zero foreced solution is better by backing off the number specified FFE taps one at at time | 8850 | param.ffe_backoff=xls_parameter(parameter, 'ffe_backoff', true,0); % see if better zero foreced solution is better by backing off the number specified FFE taps one at at time | ||
9060 | if param.RxFFE_cmx ~= 0 || param.RxFFE_cpx ~=0 | 8851 | if param.RxFFE_cmx ~= 0 || param.RxFFE_cpx ~=0 | ||
9061 | OP.RxFFE= true; | 8852 | OP.RxFFE= true; | ||
9062 | else | 8853 | else | ||
9063 | OP.RxFFE=false; | 8854 | OP.RxFFE=false; | ||
9064 | end | 8855 | end | ||
9065 | param.num_ui_RXFF_noise=xls_parameter(parameter, 'num_ui_RXFF_noise', true,2048); % Rx FFE precursor tapn limit | 8856 | param.num_ui_RXFF_noise=xls_parameter(parameter, 'num_ui_RXFF_noise', true,2048); % Rx FFE precursor tapn limit | ||
9066 | 8857 | ||||
9067 | param.g_DC_HP_values = xls_parameter(parameter, 'g_DC_HP', true,[]); % CTF AC-DC gain list (GDC2) | 8858 | param.g_DC_HP_values = xls_parameter(parameter, 'g_DC_HP', true,[]); % CTF AC-DC gain list (GDC2) | ||
9068 | param.f_HP = 1e9*xls_parameter(parameter, 'f_HP_PZ', true, []); % CFT pole pole zero pair in GHz for low frequency CTF | 8859 | param.f_HP = 1e9*xls_parameter(parameter, 'f_HP_PZ', true, []); % CFT pole pole zero pair in GHz for low frequency CTF | ||
9069 | param.f_HP_Z = 1e9*xls_parameter(parameter, 'f_HP_Z', true, []); % CFT zero fz1 is in GHz. Normally a list for 120e. Not normally use elsewise | 8860 | param.f_HP_Z = 1e9*xls_parameter(parameter, 'f_HP_Z', true, []); % CFT zero fz1 is in GHz. Normally a list for 120e. Not normally use elsewise | ||
9070 | param.f_HP_P = 1e9*xls_parameter(parameter, 'f_HP_P', true, []); % CFT pole fp2 is in GHz. Normally a list for 120e. Not normally use elsewise | 8861 | param.f_HP_P = 1e9*xls_parameter(parameter, 'f_HP_P', true, []); % CFT pole fp2 is in GHz. Normally a list for 120e. Not normally use elsewise | ||
9071 | 8862 | ||||
9072 | 8863 | ||||
9073 | param.Min_VEO= xls_parameter(parameter, 'EH_min', true,0); % used when PMD_type is C2M | 8864 | param.Min_VEO= xls_parameter(parameter, 'EH_min', true,0); % used when PMD_type is C2M | ||
9074 | param.Max_VEO= xls_parameter(parameter, 'EH_max', true,inf); % used when PMD_type is C2M and is not really computed per spec | 8865 | param.Max_VEO= xls_parameter(parameter, 'EH_max', true,inf); % used when PMD_type is C2M and is not really computed per spec | ||
9075 | param.Min_VEO_Test= xls_parameter(parameter, 'EH_min_test', true,0); % Older syntax. Used when PMD_type is C2M. This allow EH to go below EH_min. If set to zero it is ignored (same as Min_VEO_test) | 8866 | param.Min_VEO_Test= xls_parameter(parameter, 'EH_min_test', true,0); % Older syntax. Used when PMD_type is C2M. This allow EH to go below EH_min. If set to zero it is ignored (same as Min_VEO_test) | ||
9076 | param.Min_VEO_Test= xls_parameter(parameter, 'Min_VEO_Test', true,param.Min_VEO_Test); % used when PMD_type is C2M. This allow EH to go blow EH_min. If set to Zero it is ignored | 8867 | param.Min_VEO_Test= xls_parameter(parameter, 'Min_VEO_Test', true,param.Min_VEO_Test); % used when PMD_type is C2M. This allow EH to go blow EH_min. If set to Zero it is ignored | ||
9077 | 8868 | ||||
9078 | param.CTLE_type= xls_parameter(parameter, 'CTLE_type', false,'CL93'); % Sets the CTLE type default is poles and zeros (i.e. not a list of poles as in 120e) | 8869 | param.CTLE_type= xls_parameter(parameter, 'CTLE_type', false,'CL93'); % Sets the CTLE type default is poles and zeros (i.e. not a list of poles as in 120e) | ||
9079 | if ~isempty(param.g_DC_HP_values) ; param.CTLE_type='CL120d';end % overrides CL93 if g_DC_HP_values are a spreadsheet entry. Mostly used when baud rare is >= 50Gbps | 8870 | if ~isempty(param.g_DC_HP_values) ; param.CTLE_type='CL120d';end % overrides CL93 if g_DC_HP_values are a spreadsheet entry. Mostly used when baud rare is >= 50Gbps | ||
9080 | if ~isempty(param.f_HP_Z) ; param.CTLE_type='CL120e';end % overrides CL93 and CL120d if f_HP_Z is a spreadsheet entry | 8871 | if ~isempty(param.f_HP_Z) ; param.CTLE_type='CL120e';end % overrides CL93 and CL120d if f_HP_Z is a spreadsheet entry | ||
9081 | % always read in main ctle values. They would be interpreted different baseed | 8872 | % always read in main ctle values. They would be interpreted different baseed | ||
9082 | % on the clause they apply because of different CTF equations | 8873 | % on the clause they apply because of different CTF equations | ||
9083 | param.ctle_gdc_values = xls_parameter(parameter, 'g_DC', true); % AC-DC gain list | 8874 | param.ctle_gdc_values = xls_parameter(parameter, 'g_DC', true); % AC-DC gain list | ||
9084 | param.CTLE_fp1 = 1e9*xls_parameter(parameter, 'f_p1', true, param.fb/4); % fp1 is in GHz | 8875 | param.CTLE_fp1 = 1e9*xls_parameter(parameter, 'f_p1', true, param.fb/4); % fp1 is in GHz | ||
9085 | param.CTLE_fp2 = 1e9*xls_parameter(parameter, 'f_p2', true, param.fb); % fp2 is in GHz | 8876 | param.CTLE_fp2 = 1e9*xls_parameter(parameter, 'f_p2', true, param.fb); % fp2 is in GHz | ||
9086 | param.CTLE_fz = 1e9*xls_parameter(parameter, 'f_z', true, param.fb/4); % fz is in GHz | 8877 | param.CTLE_fz = 1e9*xls_parameter(parameter, 'f_z', true, param.fb/4); % fz is in GHz | ||
9087 | % the contex of the poles an zeros are determined by the clause | 8878 | % the contex of the poles an zeros are determined by the clause | ||
9088 | switch param.CTLE_type | 8879 | switch param.CTLE_type | ||
9089 | case 'CL93' | 8880 | case 'CL93' | ||
9090 | param.ctle_gdc_values = xls_parameter(parameter, 'g_DC', true); % Continuous time filter DC gain settings (G_DC) or range as specified in Annex 93A | 8881 | param.ctle_gdc_values = xls_parameter(parameter, 'g_DC', true); % Continuous time filter DC gain settings (G_DC) or range as specified in Annex 93A | ||
9091 | param.CTLE_fp1 = 1e9*xls_parameter(parameter, 'f_p1', true, param.fb/4); % fp1 is in GHz | 8882 | param.CTLE_fp1 = 1e9*xls_parameter(parameter, 'f_p1', true, param.fb/4); % fp1 is in GHz | ||
9092 | param.CTLE_fp2 = 1e9*xls_parameter(parameter, 'f_p2', true, param.fb); % fp2 is in GHz | 8883 | param.CTLE_fp2 = 1e9*xls_parameter(parameter, 'f_p2', true, param.fb); % fp2 is in GHz | ||
9093 | param.CTLE_fz = 1e9*xls_parameter(parameter, 'f_z', true, param.fb/4); % fz is in GHz | 8884 | param.CTLE_fz = 1e9*xls_parameter(parameter, 'f_z', true, param.fb/4); % fz is in GHz | ||
9094 | case 'CL120d' | 8885 | case 'CL120d' | ||
9095 | param.g_DC_HP_values = xls_parameter(parameter, 'g_DC_HP', true,[]); % Continuous time filter DC gain settings (G_DC2) | 8886 | param.g_DC_HP_values = xls_parameter(parameter, 'g_DC_HP', true,[]); % Continuous time filter DC gain settings (G_DC2) | ||
9096 | param.f_HP = 1e9*xls_parameter(parameter, 'f_HP_PZ', true, []); % fLF is in GHz | 8887 | param.f_HP = 1e9*xls_parameter(parameter, 'f_HP_PZ', true, []); % fLF is in GHz | ||
9097 | case 'CL120e' | 8888 | case 'CL120e' | ||
9098 | % re adjust to get TD_CTLE to work with C:120e equation without | 8889 | % re adjust to get TD_CTLE to work with C:120e equation without | ||
9099 | % changing TD_CTLE code | 8890 | % changing TD_CTLE code | ||
9100 | param.CTLE_fz =param.CTLE_fz ./ 10.^(param.ctle_gdc_values/20); | 8891 | param.CTLE_fz =param.CTLE_fz ./ 10.^(param.ctle_gdc_values/20); | ||
9101 | end | 8892 | end | ||
9102 | param.GDC_MIN = xls_parameter(parameter, 'GDC_MIN',true, 0); % max ACDC gain, if 0 ignore | 8893 | param.GDC_MIN = xls_parameter(parameter, 'GDC_MIN',true, 0); % max ACDC gain, if 0 ignore | ||
9103 | param.cursor_gain=xls_parameter(parameter, 'crusor_gain', true,0); % only FFE and not supported | 8894 | param.cursor_gain=xls_parameter(parameter, 'crusor_gain', true,0); % only FFE and not supported | ||
9104 | param.a_thru = xls_parameter(parameter, 'A_v', true); % Victim differential peak source output voltage (half of peak to peak) | 8895 | param.a_thru = xls_parameter(parameter, 'A_v', true); % Victim differential peak source output voltage (half of peak to peak) | ||
9105 | param.a_fext = xls_parameter(parameter, 'A_fe', true); % FEXT aggressor differential peak source output voltage (half of peak to peak) | 8896 | param.a_fext = xls_parameter(parameter, 'A_fe', true); % FEXT aggressor differential peak source output voltage (half of peak to peak) | ||
9106 | param.a_next = xls_parameter(parameter, 'A_ne', true); % NEXT aggressor differential peak source output voltage (half of peak to peak) | 8897 | param.a_next = xls_parameter(parameter, 'A_ne', true); % NEXT aggressor differential peak source output voltage (half of peak to peak) | ||
9107 | param.a_icn_fext = xls_parameter(parameter, 'A_ft', true, param.a_fext); % FEXT aggressor amplitude for ICN. Defaults to A_fe if not specified | 8898 | param.a_icn_fext = xls_parameter(parameter, 'A_ft', true, param.a_fext); % FEXT aggressor amplitude for ICN. Defaults to A_fe if not specified | ||
9108 | param.a_icn_next = xls_parameter(parameter, 'A_nt', true, param.a_next );% NEXT aggressor amplitude for ICN. Defaults to A_ne if not specified | 8899 | param.a_icn_next = xls_parameter(parameter, 'A_nt', true, param.a_next );% NEXT aggressor amplitude for ICN. Defaults to A_ne if not specified | ||
9109 | param.levels = xls_parameter(parameter, 'L'); % number of symbols levels (PAM-4 is 4, NRZ is 2) | 8900 | param.levels = xls_parameter(parameter, 'L'); % number of symbols levels (PAM-4 is 4, NRZ is 2) | ||
9110 | param.specBER = xls_parameter(parameter, 'DER_0'); % Target detector error ratio | 8901 | param.specBER = xls_parameter(parameter, 'DER_0'); % Target detector error ratio | ||
9111 | param.pass_threshold = xls_parameter(parameter, 'COM Pass threshold',false,0); % the pass fail threshold for COM in dB | 8902 | param.pass_threshold = xls_parameter(parameter, 'COM Pass threshold',false,0); % the pass fail threshold for COM in dB | ||
9112 | param.ERL_pass_threshold = xls_parameter(parameter, 'ERL Pass threshold',false,0); % the pass fail threshold for ERL in dB | 8903 | param.ERL_pass_threshold = xls_parameter(parameter, 'ERL Pass threshold',false,0); % the pass fail threshold for ERL in dB | ||
9113 | param.VEC_pass_threshold = xls_parameter(parameter, 'VEC Pass threshold',false,0);% the pass fail threshold for VEC in dB only used when PMD_type is C2M | 8904 | param.VEC_pass_threshold = xls_parameter(parameter, 'VEC Pass threshold',false,0);% the pass fail threshold for VEC in dB only used when PMD_type is C2M | ||
9114 | 8905 | ||||
9115 | param.sigma_RJ = xls_parameter(parameter, 'sigma_RJ'); % rms of of random jitter | 8906 | param.sigma_RJ = xls_parameter(parameter, 'sigma_RJ'); % rms of of random jitter | ||
9116 | param.A_DD = xls_parameter(parameter, 'A_DD'); % Normalized peak dual-Dirac noise, this is half of the total bound uncorrelated jitter (BUJ) in UI | 8907 | param.A_DD = xls_parameter(parameter, 'A_DD'); % Normalized peak dual-Dirac noise, this is half of the total bound uncorrelated jitter (BUJ) in UI | ||
9117 | param.eta_0 = xls_parameter(parameter, 'eta_0'); % One-sided noise spectral density (V^2/GHz).Input refered noise at TP5. Input referred noise at TP5 | 8908 | param.eta_0 = xls_parameter(parameter, 'eta_0'); % One-sided noise spectral density (V^2/GHz).Input refered noise at TP5. Input referred noise at TP5 | ||
9118 | param.SNDR = xls_parameter(parameter, 'SNR_TX', true); % Transmitter SNDR noise in dB | 8909 | param.SNDR = xls_parameter(parameter, 'SNR_TX', true); % Transmitter SNDR noise in dB | ||
9119 | param.R_LM = xls_parameter(parameter, 'R_LM'); % Ratio of level separation mismatch. Relevant when not PAM-2 (NRZ). | 8910 | param.R_LM = xls_parameter(parameter, 'R_LM'); % Ratio of level separation mismatch. Relevant when not PAM-2 (NRZ). | ||
9120 | param.samples_per_ui = xls_parameter(parameter, 'M', 32); % Samples per UI | 8911 | param.samples_per_ui = xls_parameter(parameter, 'M', 32); % Samples per UI | ||
9121 | param.ts_sample_adj_range = xls_parameter(parameter, 'sample_adjustment', true, [0 0]); %sample point adjustment range | 8912 | param.ts_sample_adj_range = xls_parameter(parameter, 'sample_adjustment', true, [0 0]); %sample point adjustment range | ||
9122 | param.ts_anchor = xls_parameter(parameter, 'ts_anchor', true, 0); %choice of sampling routine. 0=MM, 1=Peak, 2=max DV (max cursor minus precursor) | 8913 | param.ts_anchor = xls_parameter(parameter, 'ts_anchor', true, 0); %choice of sampling routine. 0=MM, 1=Peak, 2=max DV (max cursor minus precursor) | ||
9123 | % This will keep bmax length 0 if Nb=0 | 8914 | % This will keep bmax length 0 if Nb=0 | ||
9124 | 8915 | ||||
9125 | %AJG021820 | 8916 | %AJG021820 | ||
9126 | param.bmax(1:param.ndfe) = xls_parameter(parameter, 'b_max(1)'); % DFE magnitude limit, first coefficient(ignored if Nb=0) | 8917 | param.bmax(1:param.ndfe) = xls_parameter(parameter, 'b_max(1)'); % DFE magnitude limit, first coefficient(ignored if Nb=0) | ||
9127 | if isempty(param.bmax) | 8918 | if isempty(param.bmax) | ||
9128 | param.bmin=param.bmax; | 8919 | param.bmin=param.bmax; | ||
9129 | else | 8920 | else | ||
9130 | param.bmin(1:param.ndfe) =xls_parameter(parameter, 'b_min(1)', true,-param.bmax(1) ); % DFE negative magnitude limit. If not specified it defaults to -bmax. | 8921 | param.bmin(1:param.ndfe) =xls_parameter(parameter, 'b_min(1)', true,-param.bmax(1) ); % DFE negative magnitude limit. If not specified it defaults to -bmax. | ||
9131 | 8922 | ||||
9132 | end | 8923 | end | ||
9133 | if param.ndfe >= 2 | 8924 | if param.ndfe >= 2 | ||
9134 | param.bmax(2:param.ndfe) = xls_parameter(parameter, 'b_max(2..N_b)', true, .2); % DFE magnitude limit, second coefficient and on (ignored if Nb<2). Can be a regualar expression | 8925 | param.bmax(2:param.ndfe) = xls_parameter(parameter, 'b_max(2..N_b)', true, .2); % DFE magnitude limit, second coefficient and on (ignored if Nb<2). Can be a regualar expression | ||
9135 | param.bmin(2:param.ndfe) = xls_parameter(parameter, 'b_min(2..N_b)', true, -1*param.bmax(2:param.ndfe) ); % DFE negative magnitude limit, if not specified it defaults to -b_max(2..N_b) | 8926 | param.bmin(2:param.ndfe) = xls_parameter(parameter, 'b_min(2..N_b)', true, -1*param.bmax(2:param.ndfe) ); % DFE negative magnitude limit, if not specified it defaults to -b_max(2..N_b) | ||
9136 | end | 8927 | end | ||
9137 | 8928 | ||||
9138 | param.gqual=xls_parameter(parameter, 'G_Qual', true,[]);% G_Qual are the dB ranges of g_DC g DC )which correspond tog_DC_HP (g DC2) | 8929 | param.gqual=xls_parameter(parameter, 'G_Qual', true,[]);% G_Qual are the dB ranges of g_DC g DC )which correspond tog_DC_HP (g DC2) | ||
9139 | param.g2qual=xls_parameter(parameter, 'G2_Qual', true,[]); % G2_Qual limit values of g_DC_HP (g DC2 ) which corresponds to ranges of g_DC g DC specified with G_QUAL | 8930 | param.g2qual=xls_parameter(parameter, 'G2_Qual', true,[]); % G2_Qual limit values of g_DC_HP (g DC2 ) which corresponds to ranges of g_DC g DC specified with G_QUAL | ||
9140 | %verify gqual and gqual2 input | 8931 | %verify gqual and gqual2 input | ||
9141 | if ~isempty(param.gqual) || ~isempty(param.g2qual) | 8932 | if ~isempty(param.gqual) || ~isempty(param.g2qual) | ||
9142 | if size(param.gqual,1)~=length(param.g2qual) | 8933 | if size(param.gqual,1)~=length(param.g2qual) | ||
9143 | error('gqual and g2qual size mismatch'); | 8934 | error('gqual and g2qual size mismatch'); | ||
9144 | end | 8935 | end | ||
9145 | if size(param.gqual,2)~=2 | 8936 | if size(param.gqual,2)~=2 | ||
9146 | error('gqual must be Nx2 matrix'); | 8937 | error('gqual must be Nx2 matrix'); | ||
9147 | end | 8938 | end | ||
9148 | end | 8939 | end | ||
9149 | 8940 | ||||
9150 | 8941 | ||||
9151 | % eval if string for all three - can use different for TX and RX | 8942 | % eval if string for all three - can use different for TX and RX | ||
9152 | param.C_pkg_board = xls_parameter(parameter, 'C_p', true)*1e-9; % C_p in nF (single sided) | 8943 | param.C_pkg_board = xls_parameter(parameter, 'C_p', true)*1e-9; % C_p in nF (single sided) | ||
9153 | param.C_diepad = xls_parameter(parameter, 'C_d', true)*1e-9; % C_d in nF (single sided) | 8944 | param.C_diepad = xls_parameter(parameter, 'C_d', true)*1e-9; % C_d in nF (single sided) | ||
9154 | % [ahealey] Read values for optional compensating L and "bump" C | 8945 | % [ahealey] Read values for optional compensating L and "bump" C | ||
9155 | param.L_comp = xls_parameter(parameter, 'L_s', true, 0)*1e-9; % L_s in nH (single sided) | 8946 | param.L_comp = xls_parameter(parameter, 'L_s', true, 0)*1e-9; % L_s in nH (single sided) | ||
9156 | param.C_bump = xls_parameter(parameter, 'C_b', true, 0)*1e-9; % C_b in nF (single sided) | 8947 | param.C_bump = xls_parameter(parameter, 'C_b', true, 0)*1e-9; % C_b in nF (single sided) | ||
9157 | % [ahealey] End of modifications. | 8948 | % [ahealey] End of modifications. | ||
9158 | param.C_v = xls_parameter(parameter, 'C_v', true,0)*1e-9; % C_v in nF (via cap) (single sided) | 8949 | param.C_v = xls_parameter(parameter, 'C_v', true,0)*1e-9; % C_v in nF (via cap) (single sided) | ||
9159 | param.R_diepad = xls_parameter(parameter, 'R_d', true); % Die source termination resistance (single sided) | 8950 | param.R_diepad = xls_parameter(parameter, 'R_d', true); % Die source termination resistance (single sided) | ||
9160 | param.Z_t = xls_parameter(parameter, 'Z_t', true,50); % single sided source termination reference resistance for TDR and ERL | 8951 | param.Z_t = xls_parameter(parameter, 'Z_t', true,50); % single sided source termination reference resistance for TDR and ERL | ||
9161 | param.TR_TDR = xls_parameter(parameter, 'TR_TDR', true , 8e-3); % Gaussian shaped transition time for TDR source in ns | 8952 | param.TR_TDR = xls_parameter(parameter, 'TR_TDR', true , 8e-3); % Gaussian shaped transition time for TDR source in ns | ||
9162 | 8953 | ||||
9163 | 8954 | ||||
9164 | param.Z0 = xls_parameter(parameter, 'R_0', 50); % | 8955 | param.Z0 = xls_parameter(parameter, 'R_0', 50); % | ||
9165 | param.z_p_tx_cases = xls_parameter(parameter, 'z_p (TX)', true).'; % List of victim transmitter package trace lengths in mm, one per case | 8956 | param.z_p_tx_cases = xls_parameter(parameter, 'z_p (TX)', true).'; % List of victim transmitter package trace lengths in mm, one per case | ||
9166 | [ncases, mele]=size(param.z_p_tx_cases); | 8957 | [ncases, mele]=size(param.z_p_tx_cases); | ||
9167 | if mele ==2 | 8958 | if mele ==2 | ||
9168 | param.flex=2; | 8959 | param.flex=2; | ||
9169 | elseif mele==4 | 8960 | elseif mele==4 | ||
9170 | param.flex=4; | 8961 | param.flex=4; | ||
9171 | elseif mele==1 | 8962 | elseif mele==1 | ||
9172 | param.flex=1; | 8963 | param.flex=1; | ||
9173 | else | 8964 | else | ||
9174 | error(sprintf('config file syntax error')) | 8965 | error(sprintf('config file syntax error')) | ||
9175 | end | 8966 | end | ||
9176 | 8967 | ||||
9177 | % board parameters | 8968 | % board parameters | ||
9178 | param.C_0 = xls_parameter(parameter, 'C_0', true,0)*1e-9; % If Include PCB is set to 1, near device single ended capacitance C0 in nF is added | 8969 | param.C_0 = xls_parameter(parameter, 'C_0', true,0)*1e-9; % If Include PCB is set to 1, near device single ended capacitance C0 in nF is added | ||
9179 | param.C_1 = xls_parameter(parameter, 'C_1', true,0)*1e-9; % if Include PCB is set to 1, connector side single ended capacitance C1 in nF is added | 8970 | param.C_1 = xls_parameter(parameter, 'C_1', true,0)*1e-9; % if Include PCB is set to 1, connector side single ended capacitance C1 in nF is added | ||
9180 | % | 8971 | % | ||
9181 | param.z_p_next_cases = xls_parameter(parameter, 'z_p (NEXT)', true).'; % List of NEXT transmitter package trace lengths in mm, one per case | 8972 | param.z_p_next_cases = xls_parameter(parameter, 'z_p (NEXT)', true).'; % List of NEXT transmitter package trace lengths in mm, one per case | ||
9182 | [ncases1, mele1]=size(param.z_p_next_cases); | 8973 | [ncases1, mele1]=size(param.z_p_next_cases); | ||
9183 | if ncases ~= ncases1 || mele ~= mele1 | 8974 | if ncases ~= ncases1 || mele ~= mele1 | ||
9184 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 8975 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9185 | else | 8976 | else | ||
9186 | end | 8977 | end | ||
9187 | param.z_p_fext_cases = xls_parameter(parameter, 'z_p (FEXT)', true).'; % List of FEXT transmitter package trace lengths in mm, one per case | 8978 | param.z_p_fext_cases = xls_parameter(parameter, 'z_p (FEXT)', true).'; % List of FEXT transmitter package trace lengths in mm, one per case | ||
9188 | [ncases1, mele1]=size(param.z_p_fext_cases); | 8979 | [ncases1, mele1]=size(param.z_p_fext_cases); | ||
9189 | if ncases ~= ncases1 || mele ~= mele1 | 8980 | if ncases ~= ncases1 || mele ~= mele1 | ||
9190 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 8981 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9191 | else | 8982 | else | ||
9192 | end | 8983 | end | ||
9193 | param.z_p_rx_cases = xls_parameter(parameter, 'z_p (RX)', true).'; % List of FEXT receiver package trace lengths in mm, one per case | 8984 | param.z_p_rx_cases = xls_parameter(parameter, 'z_p (RX)', true).'; % List of FEXT receiver package trace lengths in mm, one per case | ||
9194 | [ncases1, mele1]=size(param.z_p_rx_cases); | 8985 | [ncases1, mele1]=size(param.z_p_rx_cases); | ||
9195 | if ncases ~= ncases1 || mele ~= mele1 | 8986 | if ncases ~= ncases1 || mele ~= mele1 | ||
9196 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 8987 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9197 | else | 8988 | else | ||
9198 | end | 8989 | end | ||
9199 | % Table 93A-3 parameters | 8990 | % Table 93A-3 parameters | ||
9200 | param.pkg_gamma0_a1_a2 = xls_parameter(parameter, 'package_tl_gamma0_a1_a2', true, [0 1.734e-3 1.455e-4]); %Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | 8991 | param.pkg_gamma0_a1_a2 = xls_parameter(parameter, 'package_tl_gamma0_a1_a2', true, [0 1.734e-3 1.455e-4]); %Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | ||
9201 | param.pkg_tau = xls_parameter(parameter, 'package_tl_tau', true, 6.141e-3); % Package model transmission line delay ns/mm | 8992 | param.pkg_tau = xls_parameter(parameter, 'package_tl_tau', true, 6.141e-3); % Package model transmission line delay ns/mm | ||
9202 | param.pkg_Z_c = xls_parameter(parameter, 'package_Z_c', true, 78.2).';% Package model transmission line characteristic impedance [ Tx , Rx ] | 8993 | param.pkg_Z_c = xls_parameter(parameter, 'package_Z_c', true, 78.2).';% Package model transmission line characteristic impedance [ Tx , Rx ] | ||
9203 | [ ncases1, mele1]=size(param.pkg_Z_c);% | 8994 | [ ncases1, mele1]=size(param.pkg_Z_c);% | ||
9204 | if mele ~= mele1 | 8995 | if mele ~= mele1 | ||
9205 | error('tx rx pairs must have thesame number element entries as TX, NEXT, FEXT, Rx'); | 8996 | error('tx rx pairs must have thesame number element entries as TX, NEXT, FEXT, Rx'); | ||
9206 | else | 8997 | else | ||
9207 | end | 8998 | end | ||
9208 | if mele1==2 % fuill in a array if only a 2 element flex package is specified | 8999 | if mele1==2 % fuill in a array if only a 2 element flex package is specified | ||
9209 | for ii=1:ncases | 9000 | for ii=1:ncases | ||
9210 | param.z_p_fext_casesx(ii,:)= [param.z_p_fext_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9001 | param.z_p_fext_casesx(ii,:)= [param.z_p_fext_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9211 | param.z_p_next_casesx(ii,:)= [param.z_p_next_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9002 | param.z_p_next_casesx(ii,:)= [param.z_p_next_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9212 | param.z_p_tx_casesx(ii,:)= [param.z_p_tx_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9003 | param.z_p_tx_casesx(ii,:)= [param.z_p_tx_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9213 | param.z_p_rx_casesx(ii,:)= [param.z_p_rx_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9004 | param.z_p_rx_casesx(ii,:)= [param.z_p_rx_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9214 | end | 9005 | end | ||
9215 | param.z_p_fext_cases = param.z_p_fext_casesx; | 9006 | param.z_p_fext_cases = param.z_p_fext_casesx; | ||
9216 | param.z_p_next_cases= param.z_p_next_casesx; | 9007 | param.z_p_next_cases= param.z_p_next_casesx; | ||
9217 | param.z_p_tx_cases= param.z_p_tx_casesx; | 9008 | param.z_p_tx_cases= param.z_p_tx_casesx; | ||
9218 | param.z_p_rx_cases= param.z_p_rx_casesx; | 9009 | param.z_p_rx_cases= param.z_p_rx_casesx; | ||
9219 | param.pkg_Z_c=[param.pkg_Z_c' ;[ 100 100 ; 100 100 ]]'; | 9010 | param.pkg_Z_c=[param.pkg_Z_c' ;[ 100 100 ; 100 100 ]]'; | ||
9220 | end | 9011 | end | ||
9221 | param.PKG_Tx_FFE_preset =xls_parameter(parameter, 'PKG_Tx_FFE_preset', true, 0); % RIM 08-18-2022 for Tx preset capability | 9012 | param.PKG_Tx_FFE_preset =xls_parameter(parameter, 'PKG_Tx_FFE_preset', true, 0); % RIM 08-18-2022 for Tx preset capability | ||
9222 | 9013 | ||||
9223 | % Table 92-12 parameters | 9014 | % Table 92-12 parameters | ||
9224 | param.brd_gamma0_a1_a2 = xls_parameter(parameter, 'board_tl_gamma0_a1_a2', true, [0 4.114e-4 2.547e-4]); % Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | 9015 | param.brd_gamma0_a1_a2 = xls_parameter(parameter, 'board_tl_gamma0_a1_a2', true, [0 4.114e-4 2.547e-4]); % Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | ||
9225 | param.brd_tau = xls_parameter(parameter, 'board_tl_tau', true, 6.191e-3);% Board model transmission line delay ns/mm | 9016 | param.brd_tau = xls_parameter(parameter, 'board_tl_tau', true, 6.191e-3);% Board model transmission line delay ns/mm | ||
9226 | param.brd_Z_c = xls_parameter(parameter, 'board_Z_c', true, 109.8); % Board model transmission line characteristic impedance [ Tx , Rx ] | 9017 | param.brd_Z_c = xls_parameter(parameter, 'board_Z_c', true, 109.8); % Board model transmission line characteristic impedance [ Tx , Rx ] | ||
9227 | param.z_bp_tx = xls_parameter(parameter, 'z_bp (TX)', true, 151); % Victim transmitter board trace lengths in mm | 9018 | param.z_bp_tx = xls_parameter(parameter, 'z_bp (TX)', true, 151); % Victim transmitter board trace lengths in mm | ||
9228 | param.z_bp_next = xls_parameter(parameter, 'z_bp (NEXT)', true, 72);% Next Assessor transmitter board trace lengths in mm | 9019 | param.z_bp_next = xls_parameter(parameter, 'z_bp (NEXT)', true, 72);% Next Assessor transmitter board trace lengths in mm | ||
9229 | param.z_bp_fext = xls_parameter(parameter, 'z_bp (FEXT)', true, 72);% Rext Assessor transmitter board trace lengths in mm | 9020 | param.z_bp_fext = xls_parameter(parameter, 'z_bp (FEXT)', true, 72);% Rext Assessor transmitter board trace lengths in mm | ||
9230 | param.z_bp_rx = xls_parameter(parameter, 'z_bp (RX)', true, 151);% Victim receiver board trace lengths in mm | 9021 | param.z_bp_rx = xls_parameter(parameter, 'z_bp (RX)', true, 151);% Victim receiver board trace lengths in mm | ||
9231 | 9022 | ||||
9232 | % Unofficial parameters | 9023 | % Unofficial parameters | ||
9233 | param.snpPortsOrder = xls_parameter(parameter, 'Port Order', true, [1 3 2 4]); % s parameter port order [ tx+ tx- rx+ rx-] | 9024 | param.snpPortsOrder = xls_parameter(parameter, 'Port Order', true, [1 3 2 4]); % s parameter port order [ tx+ tx- rx+ rx-] | ||
9234 | param.delta_IL=xls_parameter(parameter, 'delta_IL', false, 1); % experiemnal | 9025 | param.delta_IL=xls_parameter(parameter, 'delta_IL', false, 1); % experiemnal | ||
9235 | % Deprecated parameters - affect only frequency domain analysis. | 9026 | % Deprecated parameters - affect only frequency domain analysis. | ||
9236 | param.f_v = xls_parameter(parameter, 'f_v', true, 4); % For FOM_ILD: Transiton rate cut off frequency for ICN/ILD calc in terms of fb | 9027 | param.f_v = xls_parameter(parameter, 'f_v', true, 4); % For FOM_ILD: Transiton rate cut off frequency for ICN/ILD calc in terms of fb | ||
9237 | param.f_f = xls_parameter(parameter, 'f_f', true, 4); % For ICN: Fext transiton rate cut off frequency for ICN calc in terms of fb | 9028 | param.f_f = xls_parameter(parameter, 'f_f', true, 4); % For ICN: Fext transiton rate cut off frequency for ICN calc in terms of fb | ||
9238 | param.f_n = xls_parameter(parameter, 'f_n', true, 4); % For ICN: Next transiton rate cut off frequency for ICN calc in terms of fb | 9029 | param.f_n = xls_parameter(parameter, 'f_n', true, 4); % For ICN: Next transiton rate cut off frequency for ICN calc in terms of fb | ||
9239 | param.f_r = xls_parameter(parameter, 'f_r', true, 4); % reference receive filter in COM and in ICN/FOM_ILD calcs in terms of fb | 9030 | param.f_r = xls_parameter(parameter, 'f_r', true, 4); % reference receive filter in COM and in ICN/FOM_ILD calcs in terms of fb | ||
9240 | param.fb_BT_cutoff= xls_parameter(parameter, 'TDR_f_BT_3db', true, 0.4730); % Bessel-Thomson 3 dB cut off freqeuncy in terms of fb | 9031 | param.fb_BT_cutoff= xls_parameter(parameter, 'TDR_f_BT_3db', true, 0.4730); % Bessel-Thomson 3 dB cut off freqeuncy in terms of fb | ||
9241 | param.BTorder = xls_parameter(parameter, 'BTorder', false, 4); % Bessel function order | 9032 | param.BTorder = xls_parameter(parameter, 'BTorder', false, 4); % Bessel function order | ||
9242 | param.RC_Start = xls_parameter(parameter, 'RC_Start', false, param.fb/2); % start frequency for raised cosine filter | 9033 | param.RC_Start = xls_parameter(parameter, 'RC_Start', false, param.fb/2); % start frequency for raised cosine filter | ||
9243 | param.RC_end = xls_parameter(parameter, 'RC_end', false, param.fb*param.f_r ); % end frequency for raised cosine filter | 9034 | param.RC_end = xls_parameter(parameter, 'RC_end', false, param.fb*param.f_r ); % end frequency for raised cosine filter | ||
9244 | param.beta_x= xls_parameter(parameter, 'beta_x', false, 0);% (for ERL) use default | 9035 | param.beta_x= xls_parameter(parameter, 'beta_x', false, 0);% (for ERL) use default | ||
9245 | param.rho_x= xls_parameter(parameter, 'rho_x', false, .618); % (for ERL) use default | 9036 | param.rho_x= xls_parameter(parameter, 'rho_x', false, .618); % (for ERL) use default | ||
9246 | param.tfx= xls_parameter(parameter, 'fixture delay time', true, -1);% fixture delay time (for ERL) | 9037 | param.tfx= xls_parameter(parameter, 'fixture delay time', true, -1);% fixture delay time (for ERL) | ||
9247 | param.Grr_limit=xls_parameter(parameter, 'Grr_limit', false, 1); % either do no use or set to 1 (for ERL) | 9038 | param.Grr_limit=xls_parameter(parameter, 'Grr_limit', false, 1); % either do no use or set to 1 (for ERL) | ||
9248 | param.Grr=xls_parameter(parameter, 'Grr', false, param.Grr_limit);% either do no use or set to 1 (for ERL) | 9039 | param.Grr=xls_parameter(parameter, 'Grr', false, param.Grr_limit);% either do no use or set to 1 (for ERL) | ||
9249 | param.Gx=xls_parameter(parameter, 'Gx', false, 0); % ERL parameter param.Grr, This is used is the COM code | 9040 | param.Gx=xls_parameter(parameter, 'Gx', false, 0); % ERL parameter param.Grr, This is used is the COM code | ||
9250 | switch param.Gx | 9041 | switch param.Gx | ||
9251 | case 0 | 9042 | case 0 | ||
9252 | param.Grr=param.Grr; % just use older Grr ir gx not specified | 9043 | param.Grr=param.Grr; % just use older Grr ir gx not specified | ||
9253 | case 1 | 9044 | case 1 | ||
9254 | param.Grr=2; % use newer Grr | 9045 | param.Grr=2; % use newer Grr | ||
9255 | end | 9046 | end | ||
9256 | 9047 | ||||
9257 | param.LOCAL_SEARCH=xls_parameter(parameter,'Local Search',true,0); % Decreases COM compute time. Aetting to 2 seems ok ,if 0 search is full grid | 9048 | param.LOCAL_SEARCH=xls_parameter(parameter,'Local Search',true,0); % Decreases COM compute time. Aetting to 2 seems ok ,if 0 search is full grid | ||
9258 | % Operational control variables | 9049 | % Operational control variables | ||
9259 | %OP.include_pcb = xls_parameter(parameter, 'Include PCB (table 92-13)', false, 0); | 9050 | %OP.include_pcb = xls_parameter(parameter, 'Include PCB (table 92-13)', false, 0); | ||
9260 | param.Tukey_Window=xls_parameter(parameter,'Tukey_Window',true,0); % required for ERL. Set to 1. Default is 0. | 9051 | param.Tukey_Window=xls_parameter(parameter,'Tukey_Window',true,0); % required for ERL. Set to 1. Default is 0. | ||
9261 | param.Noise_Crest_Factor= xls_parameter(parameter, 'Noise_Crest_Factor', true, 0); % Normally not used. If set this is q factor used for quantized Gaussian PDFs | 9052 | param.Noise_Crest_Factor= xls_parameter(parameter, 'Noise_Crest_Factor', true, 0); % Normally not used. If set this is q factor used for quantized Gaussian PDFs | ||
9262 | param.AC_CM_RMS = xls_parameter(parameter, 'AC_CM_RMS', true, 0); % AC_CM_RMS is the CM BBN AWGN RMS at COM source point. Default is 0. Adds common mode noise source to the COM signal path for the through channel | 9053 | param.AC_CM_RMS = xls_parameter(parameter, 'AC_CM_RMS', true, 0); % AC_CM_RMS is the CM BBN AWGN RMS at COM source point. Default is 0. Adds common mode noise source to the COM signal path for the through channel | ||
9263 | param.ACCM_MAX_Freq=xls_parameter(parameter, 'ACCM_MAX_Freq', true, param.fb); % F max for integrating ACCM voltage in Hz. Default is fb | 9054 | param.ACCM_MAX_Freq=xls_parameter(parameter, 'ACCM_MAX_Freq', true, param.fb); % F max for integrating ACCM voltage in Hz. Default is fb | ||
9264 | param.T_O = xls_parameter(parameter, 'T_O', true, 0 ); % Units are mUI. Histogram for VEC and VEO are computed over T_s +/- T_O. | 9055 | param.T_O = xls_parameter(parameter, 'T_O', true, 0 ); % Units are mUI. Histogram for VEC and VEO are computed over T_s +/- T_O. | ||
9265 | param.T_O = xls_parameter(parameter, 'T_h', true, param.T_O ); % superceded with T_O but is the internal values that is used. Do not use. | 9056 | param.T_O = xls_parameter(parameter, 'T_h', true, param.T_O ); % superceded with T_O but is the internal values that is used. Do not use. | ||
9266 | 9057 | ||||
9267 | param.samples_for_C2M =xls_parameter(parameter, 'samples_for_C2M', true, 100 ); % Finer sampling in terms of samples per UI for c2m histgram analysis. | 9058 | param.samples_for_C2M =xls_parameter(parameter, 'samples_for_C2M', true, 100 ); % Finer sampling in terms of samples per UI for c2m histgram analysis. | ||
9268 | 9059 | ||||
9269 | OP.Histogram_Window_Weight=xls_parameter(parameter, 'Histogram_Window_Weight', false, 'rectangle' ); %Weighting for VEC and VEO are histogram processing. Type are Gaussian,Dual Rayleigh,Triangle, and Rectangle (default) | 9060 | OP.Histogram_Window_Weight=xls_parameter(parameter, 'Histogram_Window_Weight', false, 'rectangle' ); %Weighting for VEC and VEO are histogram processing. Type are Gaussian,Dual Rayleigh,Triangle, and Rectangle (default) | ||
9270 | param.sigma_r=xls_parameter(parameter, 'sigma_r', true, .020 ); % sigma_r for 0.3ck Gaussian histogram window. Unit are UI. Preferred usage. | 9061 | param.sigma_r=xls_parameter(parameter, 'sigma_r', true, .020 ); % sigma_r for 0.3ck Gaussian histogram window. Unit are UI. Preferred usage. | ||
9271 | param.Qr=xls_parameter(parameter, 'Qr', true, param.sigma_r ); % sigma_r replaces Qr gasussian histogram window. Unit are UI | 9062 | param.Qr=xls_parameter(parameter, 'Qr', true, param.sigma_r ); % sigma_r replaces Qr gasussian histogram window. Unit are UI | ||
9272 | param.QL=xls_parameter(parameter, 'QL', true, param.T_O/param.Qr/1000 ); % superceded with sigma_r but is the internal values that is used | 9063 | param.QL=xls_parameter(parameter, 'QL', true, param.T_O/param.Qr/1000 ); % superceded with sigma_r but is the internal values that is used | ||
9273 | 9064 | ||||
9274 | %% | 9065 | %% | ||
9275 | 9066 | ||||
9276 | param.skew_ps=xls_parameter(parameter, 'skew_ps', true, 0 );% experiment p/n skew. Not used. | 9067 | param.skew_ps=xls_parameter(parameter, 'skew_ps', true, 0 );% experiment p/n skew. Not used. | ||
9277 | param.imb_Z_fctr=xls_parameter(parameter, 'imb_Z_fctr', true, 1 ); % exprimental p/n impedance missmatch. Not used. | 9068 | param.imb_Z_fctr=xls_parameter(parameter, 'imb_Z_fctr', true, 1 ); % exprimental p/n impedance missmatch. Not used. | ||
9278 | param.imb_C_fctr=xls_parameter(parameter, 'imb_C_fctr', true, 1 ); % exprimental p/n capacitance missmatch. Not used. | 9069 | param.imb_C_fctr=xls_parameter(parameter, 'imb_C_fctr', true, 1 ); % exprimental p/n capacitance missmatch. Not used. | ||
9279 | param.awgn_mv=param.AC_CM_RMS; | 9070 | param.awgn_mv=param.AC_CM_RMS; | ||
9280 | param.flip=xls_parameter(parameter, 'flip', true, 0 ); % exprimental p/n missmatch flip. Not used. | 9071 | param.flip=xls_parameter(parameter, 'flip', true, 0 ); % exprimental p/n missmatch flip. Not used. | ||
9281 | param.f_hp=xls_parameter(parameter, 'f_hp', true, 0 ); % for rx testing for eq 162-12 if 0 (default) then rx test using rx bbn | 9072 | param.f_hp=xls_parameter(parameter, 'f_hp', true, 0 ); % for rx testing for eq 162-12 if 0 (default) then rx test using rx bbn | ||
9282 | 9073 | ||||
9283 | 9074 | ||||
9284 | %% Adding new parameters to reveal whether Floating DFE or Floating RXFFE is used | 9075 | %% Adding new parameters to reveal whether Floating DFE or Floating RXFFE is used | ||
9285 | % This removes the dependency on checking param.N_bg (that is no longer valid to reveal if floating DFE is used) | 9076 | % This removes the dependency on checking param.N_bg (that is no longer valid to reveal if floating DFE is used) | ||
9286 | param.Floating_RXFFE=false; | 9077 | param.Floating_RXFFE=false; | ||
9287 | param.Floating_DFE=false; | 9078 | param.Floating_DFE=false; | ||
9288 | if param.N_bg > 0 | 9079 | if param.N_bg > 0 | ||
9289 | param.Floating_DFE=true; | 9080 | param.Floating_DFE=true; | ||
9290 | end | 9081 | end | ||
9291 | if OP.RxFFE | 9082 | if OP.RxFFE | ||
9292 | param.Floating_DFE=false; | 9083 | param.Floating_DFE=false; | ||
9293 | if param.N_bg > 0 | 9084 | if param.N_bg > 0 | ||
9294 | param.Floating_RXFFE=true; | 9085 | param.Floating_RXFFE=true; | ||
9295 | end | 9086 | end | ||
9296 | end | 9087 | end | ||
9297 | %% for introducing Tx or Rx skew on p leg or n leg | 9088 | %% for introducing Tx or Rx skew on p leg or n leg | ||
9298 | param.Txpskew=xls_parameter(parameter, 'Txpskew', true, 0 ); % Tx p skew in ps | 9089 | param.Txpskew=xls_parameter(parameter, 'Txpskew', true, 0 ); % Tx p skew in ps | ||
9299 | param.Txnskew=xls_parameter(parameter, 'Txnskew', true, 0 ); % Tx n skew in ps | 9090 | param.Txnskew=xls_parameter(parameter, 'Txnskew', true, 0 ); % Tx n skew in ps | ||
9300 | param.Rxpskew=xls_parameter(parameter, 'Rxpskew', true, 0 ); % Rx p skew in ps | 9091 | param.Rxpskew=xls_parameter(parameter, 'Rxpskew', true, 0 ); % Rx p skew in ps | ||
9301 | param.Rxnskew=xls_parameter(parameter, 'Rxnskew', true, 0 ); % Rx n skew in ps | 9092 | param.Rxnskew=xls_parameter(parameter, 'Rxnskew', true, 0 ); % Rx n skew in ps | ||
9302 | 9093 | ||||
9303 | %% | 9094 | %% | ||
9304 | OP.include_pcb = xls_parameter(parameter, 'Include PCB', false); % Used to add a PCB one each side of the passed s-parameters. | 9095 | OP.include_pcb = xls_parameter(parameter, 'Include PCB', false); % Used to add a PCB one each side of the passed s-parameters. | ||
9305 | OP.exit_if_deployed = xls_parameter(parameter, 'exit if deployed', false,0); % may need set when COM is an exe | 9096 | OP.exit_if_deployed = xls_parameter(parameter, 'exit if deployed', false,0); % may need set when COM is an exe | ||
9306 | OP.INCLUDE_CTLE = xls_parameter(parameter, 'INCLUDE_CTLE', false, 1); % do not use | 9097 | OP.INCLUDE_CTLE = xls_parameter(parameter, 'INCLUDE_CTLE', false, 1); % do not use | ||
9307 | OP.EXE_MODE= xls_parameter(parameter, 'EXE_MODE', false, 1);% 12/21 0:legacy 1:fast 2:superfast default is 1. | 9098 | OP.EXE_MODE= xls_parameter(parameter, 'EXE_MODE', false, 1);% 12/21 0:legacy 1:fast 2:superfast default is 1. | ||
9308 | OP.INCLUDE_FILTER = xls_parameter(parameter, 'INCLUDE_TX_RX_FILTER', false, 1); % do not use | 9099 | OP.INCLUDE_FILTER = xls_parameter(parameter, 'INCLUDE_TX_RX_FILTER', false, 1); % do not use | ||
9309 | OP.force_pdf_bin_size = xls_parameter(parameter, 'Force PDF bin size', false, 0); % do not use | 9100 | OP.force_pdf_bin_size = xls_parameter(parameter, 'Force PDF bin size', false, 0); % do not use | ||
9310 | OP.BinSize = xls_parameter(parameter, 'PDF bin size', false, 1e-5); % set lower for faster computation time but less accuracy. | 9101 | OP.BinSize = xls_parameter(parameter, 'PDF bin size', false, 1e-5); % set lower for faster computation time but less accuracy. | ||
9311 | OP.DEBUG = xls_parameter(parameter, 'DIAGNOSTICS', false, false); % supresss some interim compuation value printouts | 9102 | OP.DEBUG = xls_parameter(parameter, 'DIAGNOSTICS', false, false); % supresss some interim compuation value printouts | ||
9312 | OP.DISPLAY_WINDOW = xls_parameter(parameter, 'DISPLAY_WINDOW', false, true); % controls if graph plots are displayed. Typically goes along with DIAGNOSTICS | 9103 | OP.DISPLAY_WINDOW = xls_parameter(parameter, 'DISPLAY_WINDOW', false, true); % controls if graph plots are displayed. Typically goes along with DIAGNOSTICS | ||
9313 | OP.CSV_REPORT = xls_parameter(parameter, 'CSV_REPORT', false, true); % saves all the output parameters to a CSV file in the results directory, If DIAGNOSTICS is set then a mat file is also created | 9104 | OP.CSV_REPORT = xls_parameter(parameter, 'CSV_REPORT', false, true); % saves all the output parameters to a CSV file in the results directory, If DIAGNOSTICS is set then a mat file is also created | ||
9314 | OP.SAVE_TD=xls_parameter(parameter, 'SAVE_TD', false, false); % Save the time domian waveforms. FIR, PR etc. in an output structure | 9105 | OP.SAVE_TD=xls_parameter(parameter, 'SAVE_TD', false, false); % Save the time domian waveforms. FIR, PR etc. in an output structure | ||
9315 | OP.SAVE_FIGURES=xls_parameter(parameter, 'SAVE_FIGURES', false, false); % save displayed figures in the results directory | 9106 | OP.SAVE_FIGURES=xls_parameter(parameter, 'SAVE_FIGURES', false, false); % save displayed figures in the results directory | ||
9316 | OP.SAVE_FIGURE_to_CSV=xls_parameter(parameter, 'SAVE_FIGURE_to_CSV', false, false); % does not work. do not use. | 9107 | OP.SAVE_FIGURE_to_CSV=xls_parameter(parameter, 'SAVE_FIGURE_to_CSV', false, false); % does not work. do not use. | ||
9317 | OP.GET_FD = xls_parameter(parameter, 'Display frequency domain', false, OP.GET_FD); % Not normally set in the config file. It is normally just set to true to get FD plots | 9108 | OP.GET_FD = xls_parameter(parameter, 'Display frequency domain', false, OP.GET_FD); % Not normally set in the config file. It is normally just set to true to get FD plots | ||
9318 | OP.INC_PACKAGE = xls_parameter(parameter, 'INC_PACKAGE', false, true); % warning: INC_PACKAGE=0 not fully supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 | 9109 | OP.INC_PACKAGE = xls_parameter(parameter, 'INC_PACKAGE', false, true); % warning: INC_PACKAGE=0 not fully supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 | ||
9319 | if ~OP.INC_PACKAGE | 9110 | if ~OP.INC_PACKAGE | ||
9320 | fprintf('<strong> Warning!!! INC_PACKAGE=0 not fully supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | 9111 | fprintf('<strong> Warning!!! INC_PACKAGE=0 not fully supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | ||
9321 | end | 9112 | end | ||
9322 | 9113 | ||||
9323 | OP.EW = xls_parameter(parameter, 'EW', false, false); % RIM 3-18-2021 change defaults | 9114 | OP.EW = xls_parameter(parameter, 'EW', false, false); % RIM 3-18-2021 change defaults | ||
9324 | OP.IDEAL_TX_TERM = xls_parameter(parameter, 'IDEAL_TX_TERM', false, false); | 9115 | OP.IDEAL_TX_TERM = xls_parameter(parameter, 'IDEAL_TX_TERM', false, false); | ||
9325 | if OP.IDEAL_TX_TERM | 9116 | if OP.IDEAL_TX_TERM | ||
9326 | fprintf('<strong> Warning!!! IDEAL_TX_TERM not supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | 9117 | fprintf('<strong> Warning!!! IDEAL_TX_TERM not supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | ||
9327 | end | 9118 | end | ||
9328 | OP.IDEAL_RX_TERM = xls_parameter(parameter, 'IDEAL_RX_TERM', false, false); | 9119 | OP.IDEAL_RX_TERM = xls_parameter(parameter, 'IDEAL_RX_TERM', false, false); | ||
9329 | if OP.IDEAL_RX_TERM | 9120 | if OP.IDEAL_RX_TERM | ||
9330 | fprintf('<strong> Warning!!! IDEAL_RX_TERM not supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | 9121 | fprintf('<strong> Warning!!! IDEAL_RX_TERM not supported, instead, set Zp,Cd, and Cp parameters to zero and Zp select to 1 </strong>\n'); | ||
9331 | end | 9122 | end | ||
9332 | 9123 | ||||
9333 | OP.TDMODE = xls_parameter(parameter, 'TDMODE',false, OP.TDMODE); % Enables the the use of pulse response instead of s-parameters. Assumes no packages or the packages are included in the PR. Default is 0. | 9124 | OP.TDMODE = xls_parameter(parameter, 'TDMODE',false, OP.TDMODE); % Enables the the use of pulse response instead of s-parameters. Assumes no packages or the packages are included in the PR. Default is 0. | ||
9334 | 9125 | ||||
9335 | OP.FT_COOP = xls_parameter(parameter, 'FT_COOP',false, false); % obsolete do not use. | 9126 | OP.FT_COOP = xls_parameter(parameter, 'FT_COOP',false, false); % obsolete do not use. | ||
9336 | OP.RESULT_DIR = regexprep(xls_parameter(parameter, 'RESULT_DIR'), '\\', filesep); % directory where results like csv, mat, and/or figure files will be written | 9127 | OP.RESULT_DIR = regexprep(xls_parameter(parameter, 'RESULT_DIR'), '\\', filesep); % directory where results like csv, mat, and/or figure files will be written | ||
9337 | OP.RESULT_DIR=strrep(OP.RESULT_DIR,'{date}',date); | 9128 | OP.RESULT_DIR=strrep(OP.RESULT_DIR,'{date}',date); | ||
9338 | OP.BREAD_CRUMBS = xls_parameter(parameter, 'BREAD_CRUMBS',false, false); % if DIAGNOSTICS is set then param, OP, and chdata are include in the output for each run | 9129 | OP.BREAD_CRUMBS = xls_parameter(parameter, 'BREAD_CRUMBS',false, false); % if DIAGNOSTICS is set then param, OP, and chdata are include in the output for each run | ||
9339 | OP.BREAD_CRUMBS_FIELDS = xls_parameter(parameter, 'BREAD_CRUMBS_FIELDS',false, ''); % if BREAD_CRUMBs is enabled, this file controls what chdata fields are included | 9130 | OP.BREAD_CRUMBS_FIELDS = xls_parameter(parameter, 'BREAD_CRUMBS_FIELDS',false, ''); % if BREAD_CRUMBs is enabled, this file controls what chdata fields are included | ||
9340 | OP.COM_CONTRIBUTION_CURVES = xls_parameter(parameter, 'COM_CONTRIBUTION',false,0); % Default is 0. If set to 1 then a bar graph of COM contributors is produce instead of bathtub curves | 9131 | OP.COM_CONTRIBUTION_CURVES = xls_parameter(parameter, 'COM_CONTRIBUTION',false,0); % Default is 0. If set to 1 then a bar graph of COM contributors is produce instead of bathtub curves | ||
9341 | OP.ENFORCE_CAUSALITY = xls_parameter(parameter, 'Enforce Causality', false, 0);% default is 0. Not recommended | 9132 | OP.ENFORCE_CAUSALITY = xls_parameter(parameter, 'Enforce Causality', false, 0);% default is 0. Not recommended | ||
9342 | OP.EC_REL_TOL = xls_parameter(parameter, 'Enforce Causality REL_TOL', false, 1e-2); % Relative Tolerance parameter for causality, Hard enforcement, 1e-3, Soft enforcement, 1e-2 | 9133 | OP.EC_REL_TOL = xls_parameter(parameter, 'Enforce Causality REL_TOL', false, 1e-2); % Relative Tolerance parameter for causality, Hard enforcement, 1e-3, Soft enforcement, 1e-2 | ||
9343 | OP.EC_DIFF_TOL = xls_parameter(parameter, 'Enforce Causality DIFF_TOL', false, 1e-3); % Difference Tolerance parameter for causality, Hard enforcement, 1e-4,Soft enforcement, 1e-3 | 9134 | OP.EC_DIFF_TOL = xls_parameter(parameter, 'Enforce Causality DIFF_TOL', false, 1e-3); % Difference Tolerance parameter for causality, Hard enforcement, 1e-4,Soft enforcement, 1e-3 | ||
9344 | OP.EC_PULSE_TOL = xls_parameter(parameter, 'Enforce Causality pulse start tolerance', false, 0.01); % Tolerance parameter for causality, Hard enforcement, 0.05, Soft enforcement, .01 | 9135 | OP.EC_PULSE_TOL = xls_parameter(parameter, 'Enforce Causality pulse start tolerance', false, 0.01); % Tolerance parameter for causality, Hard enforcement, 0.05, Soft enforcement, .01 | ||
9345 | OP.pkg_len_select = xls_parameter(parameter, 'z_p select', true, 1); % List of package length indexes used to run COM | 9136 | OP.pkg_len_select = xls_parameter(parameter, 'z_p select', true, 1); % List of package length indexes used to run COM | ||
9346 | OP.RX_CALIBRATION = xls_parameter(parameter, 'RX_CALIBRATION', false, false); % Turn on RX_Calibration loop | 9137 | OP.RX_CALIBRATION = xls_parameter(parameter, 'RX_CALIBRATION', false, false); % Turn on RX_Calibration loop | ||
9347 | OP.sigma_bn_STEP = xls_parameter(parameter, 'Sigma BBN step', false, 5e-3); % BBN step for Rx Calibration in volts. Defaults is 0.5e-3 | 9138 | OP.sigma_bn_STEP = xls_parameter(parameter, 'Sigma BBN step', false, 5e-3); % BBN step for Rx Calibration in volts. Defaults is 0.5e-3 | ||
9348 | OP.BBN_Q_factor = xls_parameter(parameter, 'BBN Q factor', false, 5); % Overrides NEXT/FEXT noise Qfactor for 'Force BBN Q factor' used for reporting. does not affect COM. | 9139 | OP.BBN_Q_factor = xls_parameter(parameter, 'BBN Q factor', false, 5); % Overrides NEXT/FEXT noise Qfactor for 'Force BBN Q factor' used for reporting. does not affect COM. | ||
9349 | OP.force_BBN_Q_factor = xls_parameter(parameter, 'Force BBN Q factor', false, false); % Used for reporting and bathtub curves. does not affect COM. | 9140 | OP.force_BBN_Q_factor = xls_parameter(parameter, 'Force BBN Q factor', false, false); % Used for reporting and bathtub curves. does not affect COM. | ||
9350 | OP.transmitter_transition_time = xls_parameter(parameter, 'T_r', true , 8e-3); % 20% to 80% transition time used for the Gaussian shaped source | 9141 | OP.transmitter_transition_time = xls_parameter(parameter, 'T_r', true , 8e-3); % 20% to 80% transition time used for the Gaussian shaped source | ||
9351 | OP.RL_norm_test=xls_parameter(parameter, 'ERL_FOM', false, 1); % Defaults to 1 indicating variance is used for FOM determination. Do not change. | 9142 | OP.RL_norm_test=xls_parameter(parameter, 'ERL_FOM', false, 1); % Defaults to 1 indicating variance is used for FOM determination. Do not change. | ||
9352 | 9143 | ||||
9353 | OP.T_r_meas_point = xls_parameter(parameter, 'T_r_meas_point', false, 0); % included for earlier version support. Not recommended to use. | 9144 | OP.T_r_meas_point = xls_parameter(parameter, 'T_r_meas_point', false, 0); % included for earlier version support. Not recommended to use. | ||
9354 | OP.T_r_filter_type= xls_parameter(parameter, 'T_r_filter_type', false, 0);% included for earlier version support. Not recommended to use. | 9145 | OP.T_r_filter_type= xls_parameter(parameter, 'T_r_filter_type', false, 0);% included for earlier version support. Not recommended to use. | ||
9355 | OP.FORCE_TR = xls_parameter(parameter, 'FORCE_TR', false, false);% Included for earlier version support but should be set to 1 in most later config sheets. | 9146 | OP.FORCE_TR = xls_parameter(parameter, 'FORCE_TR', false, false);% Included for earlier version support but should be set to 1 in most later config sheets. | ||
9356 | % Control with OP.T_r_filter_type and OP.T_r_meas_point for backward | 9147 | % Control with OP.T_r_filter_type and OP.T_r_meas_point for backward | ||
9357 | % compatibility | 9148 | % compatibility | ||
9358 | if OP.FORCE_TR | 9149 | if OP.FORCE_TR | ||
9359 | OP.T_r_meas_point=0; | 9150 | OP.T_r_meas_point=0; | ||
9360 | OP.T_r_filter_type=1; | 9151 | OP.T_r_filter_type=1; | ||
9361 | end | 9152 | end | ||
9362 | OP.TDR = xls_parameter(parameter, 'TDR', false, false); % Set to 1 to produce TDR results | 9153 | OP.TDR = xls_parameter(parameter, 'TDR', false, false); % Set to 1 to produce TDR results | ||
9363 | OP.TDR_duration= xls_parameter(parameter, 'TDR_duration', false, 5); % only used if N*UI is longer than the TDR duration time. Default is 5 times the raw s-parameter transit time. | 9154 | OP.TDR_duration= xls_parameter(parameter, 'TDR_duration', false, 5); % only used if N*UI is longer than the TDR duration time. Default is 5 times the raw s-parameter transit time. | ||
9364 | OP.N = xls_parameter(parameter, 'N', false, 0); % duration time in UI which is used for ERL (PTDR) | 9155 | OP.N = xls_parameter(parameter, 'N', false, 0); % duration time in UI which is used for ERL (PTDR) | ||
9365 | OP.WC_PORTZ = xls_parameter(parameter, 'WC_PORTZ', false, false); % Do not use: Obsolete. | 9156 | OP.WC_PORTZ = xls_parameter(parameter, 'WC_PORTZ', false, false); % Do not use: Obsolete. | ||
9366 | OP.T_k= xls_parameter(parameter, 'T_k', false, .6)*1e-9; % Time span (ns) for which the impedance of port is determined using TDR. | 9157 | OP.T_k= xls_parameter(parameter, 'T_k', false, .6)*1e-9; % Time span (ns) for which the impedance of port is determined using TDR. | ||
9367 | OP.ERL_ONLY = xls_parameter(parameter, 'ERL_ONLY', false,0); % Compute ERL only | 9158 | OP.ERL_ONLY = xls_parameter(parameter, 'ERL_ONLY', false,0); % Compute ERL only | ||
9368 | OP.ERL=xls_parameter(parameter, 'ERL', false, false); % Enables ERL. Needs TDR to be set as well. | 9159 | OP.ERL=xls_parameter(parameter, 'ERL', false, false); % Enables ERL. Needs TDR to be set as well. | ||
9369 | if OP.ERL | 9160 | if OP.ERL | ||
9370 | OP.PTDR=1; | 9161 | OP.PTDR=1; | ||
9371 | else | 9162 | else | ||
9372 | OP.PTDR=0; | 9163 | OP.PTDR=0; | ||
9373 | end % ERL needs to do a TDR | 9164 | end % ERL needs to do a TDR | ||
9374 | OP.SHOW_BRD= xls_parameter(parameter, 'SHOW_BRD', false,0);% indclude added board (PCB) in TDR and ERL. Default is 0. | 9165 | OP.SHOW_BRD= xls_parameter(parameter, 'SHOW_BRD', false,0);% indclude added board (PCB) in TDR and ERL. Default is 0. | ||
9375 | if OP.WC_PORTZ , OP.TDR=1;end % Obsolete: WC_PORTZ needs to do a TDR | 9166 | if OP.WC_PORTZ , OP.TDR=1;end % Obsolete: WC_PORTZ needs to do a TDR | ||
9376 | OP.TDR_W_TXPKG = xls_parameter(parameter, 'TDR_W_TXPKG', false,0);% adds tx package for TDR, PTDR, and ERL. Default is 0. | 9167 | OP.TDR_W_TXPKG = xls_parameter(parameter, 'TDR_W_TXPKG', false,0);% adds tx package for TDR, PTDR, and ERL. Default is 0. | ||
9377 | OP.Bessel_Thomson=xls_parameter(parameter, 'Bessel_Thomson', false, false); % enable Bessel Thomsen filter for COM | 9168 | OP.Bessel_Thomson=xls_parameter(parameter, 'Bessel_Thomson', false, false); % enable Bessel Thomsen filter for COM | ||
9378 | OP.TDR_Butterworth=xls_parameter(parameter, 'TDR_Butterworth', false, true); % enable Butterworth filter for TDR, PTDR, and ERL | 9169 | OP.TDR_Butterworth=xls_parameter(parameter, 'TDR_Butterworth', false, true); % enable Butterworth filter for TDR, PTDR, and ERL | ||
9379 | OP.Butterworth=xls_parameter(parameter, 'Butterworth', false, 1); % Enable Butterworth Rx filter for COM compuatetopm | 9170 | OP.Butterworth=xls_parameter(parameter, 'Butterworth', false, 1); % Enable Butterworth Rx filter for COM compuatetopm | ||
9380 | OP.Raised_Cosine=xls_parameter(parameter, 'Raised_Cosine', false,0); % Not used if 0. Default is zero. Should set BT and BW to false | 9171 | OP.Raised_Cosine=xls_parameter(parameter, 'Raised_Cosine', false,0); % Not used if 0. Default is zero. Should set BT and BW to false | ||
9381 | OP.inc_reflect_board=xls_parameter(parameter, 'inc_reflect_board', false,0); % Not used if 0. Default is zero. | 9172 | OP.inc_reflect_board=xls_parameter(parameter, 'inc_reflect_board', false,0); % Not used if 0. Default is zero. | ||
9382 | OP.AUTO_TFX=xls_parameter(parameter, 'AUTO_TFX', false,0); % Mostly used for device ERL. If sent to 1 the fixture tfx will be estimated. | 9173 | OP.AUTO_TFX=xls_parameter(parameter, 'AUTO_TFX', false,0); % Mostly used for device ERL. If sent to 1 the fixture tfx will be estimated. | ||
9383 | OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN = xls_parameter(parameter, 'LIMIT_JITTER_CONTRIB_TO_DFE_SPAN', false, false); % Experimental. Default is 0. | 9174 | OP.LIMIT_JITTER_CONTRIB_TO_DFE_SPAN = xls_parameter(parameter, 'LIMIT_JITTER_CONTRIB_TO_DFE_SPAN', false, false); % Experimental. Default is 0. | ||
9384 | %OP.impulse_response_truncation_threshold = xls_parameter(parameter, 'Impulse response truncatio threshold', false, 1e-3); | 9175 | %OP.impulse_response_truncation_threshold = xls_parameter(parameter, 'Impulse response truncatio threshold', false, 1e-3); | ||
9385 | OP.impulse_response_truncation_threshold = xls_parameter(parameter, 'Impulse response truncation threshold', false, 1e-3); % zero padding threshold in fraction of IR peak for the impulse response. Effectively controls the length of time for the PR. Larger values decrease run time and accuracy. Default is 1e-3. | 9176 | OP.impulse_response_truncation_threshold = xls_parameter(parameter, 'Impulse response truncation threshold', false, 1e-3); % zero padding threshold in fraction of IR peak for the impulse response. Effectively controls the length of time for the PR. Larger values decrease run time and accuracy. Default is 1e-3. | ||
9386 | OP.interp_sparam_mag = xls_parameter(parameter, 'S-parameter magnitude extrapolation policy', false, 'linear_trend_to_DC'); % magnitued extrapolation method | 9177 | OP.interp_sparam_mag = xls_parameter(parameter, 'S-parameter magnitude extrapolation policy', false, 'linear_trend_to_DC'); % magnitued extrapolation method | ||
9387 | OP.interp_sparam_phase = xls_parameter(parameter, 'S-parameter phase extrapolation policy', false, 'extrap_cubic_to_dc_linear_to_inf'); % phase extrapolation method | 9178 | OP.interp_sparam_phase = xls_parameter(parameter, 'S-parameter phase extrapolation policy', false, 'extrap_cubic_to_dc_linear_to_inf'); % phase extrapolation method | ||
9388 | OP.PMD_type= xls_parameter(parameter, 'PMD_type', false,'C2C'); % Either C2C or C2M. C2M is for computing VEC and VEO | 9179 | OP.PMD_type= xls_parameter(parameter, 'PMD_type', false,'C2C'); % Either C2C or C2M. C2M is for computing VEC and VEO | ||
9389 | OP.PHY= xls_parameter(parameter, 'PHY', false, OP.PMD_type); % The keyword OP.PMD_type is now used | 9180 | OP.PHY= xls_parameter(parameter, 'PHY', false, OP.PMD_type); % The keyword OP.PMD_type is now used | ||
9390 | if strcmpi(OP.PHY,'C2M') | 9181 | if strcmpi(OP.PHY,'C2M') | ||
9391 | OP.EW=true; | 9182 | OP.EW=true; | ||
9392 | else | 9183 | else | ||
9393 | param.T_O=0; % make sure when c2c that sample is at Ts | 9184 | param.T_O=0; % make sure when c2c that sample is at Ts | ||
9394 | end | 9185 | end | ||
9395 | if param.Min_VEO ~=0 && strcmpi(OP.PHY,'C2C') | 9186 | if param.Min_VEO ~=0 && strcmpi(OP.PHY,'C2C') | ||
9396 | OP.PHY='C2Mcom'; | 9187 | OP.PHY='C2Mcom'; | ||
9397 | end | 9188 | end | ||
9398 | OP.TDECQ=xls_parameter(parameter, 'TDECQ', false, 0); % Experimental, for only option is none (0) or vma. Default is 0. | 9189 | OP.TDECQ=xls_parameter(parameter, 'TDECQ', false, 0); % Experimental, for only option is none (0) or vma. Default is 0. | ||
9399 | switch lower(OP.TDECQ) | 9190 | switch lower(OP.TDECQ) | ||
9400 | case {false 'none' 'vma'} | 9191 | case {false 'none' 'vma'} | ||
9401 | otherwise | 9192 | otherwise | ||
9402 | error('%s unrecognized TDECQ keyword',OP.TDECQ) | 9193 | error('%s unrecognized TDECQ keyword',OP.TDECQ) | ||
9403 | end | 9194 | end | ||
9404 | OP.RUNTAG = xls_parameter(parameter, 'RUNTAG', false, ''); % This string is appended to the begining of results files | 9195 | OP.RUNTAG = xls_parameter(parameter, 'RUNTAG', false, ''); % This string is appended to the begining of results files | ||
9405 | if isnan(OP.RUNTAG), OP.RUNTAG='';end | 9196 | if isnan(OP.RUNTAG), OP.RUNTAG='';end | ||
9406 | if isnumeric(OP.RUNTAG), OP.RUNTAG=num2str(OP.RUNTAG);end | 9197 | if isnumeric(OP.RUNTAG), OP.RUNTAG=num2str(OP.RUNTAG);end | ||
9407 | OP.CDR=xls_parameter(parameter, 'CDR', false, 'MM');% 12/21 from Yuchun Lu to accomdate 'Mod-MM', Defautt is 'MM' | 9198 | OP.CDR=xls_parameter(parameter, 'CDR', false, 'MM');% 12/21 from Yuchun Lu to accomdate 'Mod-MM', Defautt is 'MM' | ||
9408 | OP.Optimize_loop_speed_up =xls_parameter(parameter, 'Optimize_loop_speed_up', true , 0);% If set to 0 (or default) normal looping, If set to 1 loop speedup by slightly reducing PD Fbin and FIR_threshold for optimize looping only | 9199 | OP.Optimize_loop_speed_up =xls_parameter(parameter, 'Optimize_loop_speed_up', true , 0);% If set to 0 (or default) normal looping, If set to 1 loop speedup by slightly reducing PD Fbin and FIR_threshold for optimize looping only | ||
9409 | % Parameters for error burst probability calculation. Not officially used | 9200 | % Parameters for error burst probability calculation. Not officially used | ||
9410 | OP.use_simple_EP_model = xls_parameter(parameter, 'Use simple error propagation model', false, false);% Use to calculate burst error rate (not normally used | 9201 | OP.use_simple_EP_model = xls_parameter(parameter, 'Use simple error propagation model', false, false);% Use to calculate burst error rate (not normally used | ||
9411 | OP.nburst = xls_parameter(parameter, 'Max burst length calculated', false, 0); % Use to calculate burst error rate (not normally used) | 9202 | OP.nburst = xls_parameter(parameter, 'Max burst length calculated', false, 0); % Use to calculate burst error rate (not normally used) | ||
9412 | OP.COM_EP_margin = xls_parameter(parameter, 'Error propagation COM margin', false, 0); % Use to calculate error propogation (not normally used) | 9203 | OP.COM_EP_margin = xls_parameter(parameter, 'Error propagation COM margin', false, 0); % Use to calculate error propogation (not normally used) | ||
9413 | OP.USE_ETA0_PSD = xls_parameter(parameter, 'USE_ETA0_PSD', false, 0); % Used eta_0 PSD equaiton for sigma_n. Default is 0. Do not use. | 9204 | OP.USE_ETA0_PSD = xls_parameter(parameter, 'USE_ETA0_PSD', false, 0); % Used eta_0 PSD equaiton for sigma_n. Default is 0. Do not use. | ||
9414 | OP.SAVE_CONFIG2MAT = xls_parameter(parameter, 'SAVE_CONFIG2MAT', false, 0); % If set to 1 (default) saves parameters in mat file. Requires DIAGNOSTICS to be set. | 9205 | OP.SAVE_CONFIG2MAT = xls_parameter(parameter, 'SAVE_CONFIG2MAT', false, 0); % If set to 1 (default) saves parameters in mat file. Requires DIAGNOSTICS to be set. | ||
9415 | OP.PLOT_CM = xls_parameter(parameter, 'PLOT_CM', false, 0); % Display CM plots if set to 1. Default is 0. | 9206 | OP.PLOT_CM = xls_parameter(parameter, 'PLOT_CM', false, 0); % Display CM plots if set to 1. Default is 0. | ||
9416 | OP.fraction_of_F_range_start_extrap_from= xls_parameter(parameter, 'fraction_of_F_range_start_extrap_from', true, 0.75); % Frequency (fb) where high frequency extropolation begins for computing IR. Helps control Gibbs phenomena. defualt is 0.75. | 9207 | OP.fraction_of_F_range_start_extrap_from= xls_parameter(parameter, 'fraction_of_F_range_start_extrap_from', true, 0.75); % Frequency (fb) where high frequency extropolation begins for computing IR. Helps control Gibbs phenomena. defualt is 0.75. | ||
9417 | OP.COMPUTE_RILN = xls_parameter(parameter, 'COMPUTE_RILN', false, 0); % Computes RILN default is 0. FOM_RILN reported | 9208 | OP.COMPUTE_RILN = xls_parameter(parameter, 'COMPUTE_RILN', false, 0); % Computes RILN default is 0. FOM_RILN reported | ||
9418 | OP.COMPUTE_TDILN = xls_parameter(parameter, 'COMPUTE_TDILN', false, OP.COMPUTE_RILN); % computes TD ILN from complex freq IL fit. FOM_TDILN reported. | 9209 | OP.COMPUTE_TDILN = xls_parameter(parameter, 'COMPUTE_TDILN', false, OP.COMPUTE_RILN); % computes TD ILN from complex freq IL fit. FOM_TDILN reported. | ||
9419 | OP.SAVE_KEYWORD_FILE = xls_parameter(parameter, 'SAVE_KEYWORD_FILE', false, 0); % Save csv file of COM parameter (OP) and keywords. Not implemented. | 9210 | OP.SAVE_KEYWORD_FILE = xls_parameter(parameter, 'SAVE_KEYWORD_FILE', false, 0); % Save csv file of COM parameter (OP) and keywords. Not implemented. | ||
9420 | OP.SNR_TXwC0 = xls_parameter(parameter, 'SNR_TXwC0', false, 0); % Adjust SNR_TX with C0 | 9211 | OP.SNR_TXwC0 = xls_parameter(parameter, 'SNR_TXwC0', false, 0); % Adjust SNR_TX with C0 | ||
9421 | OP.MLSE = xls_parameter(parameter, 'MLSE', false, 0); % MLSE 0,1,2, 3 (no MLSE, U1 MLSE, experimetal MLSE, U3 MLSE) | 9212 | OP.MLSE = xls_parameter(parameter, 'MLSE', false, 0); % MLSE 0,1,2, 3 (no MLSE, U1 MLSE, experimetal MLSE, U3 MLSE) | ||
9422 | OP.RXFFE_FLOAT_CTL = xls_parameter(parameter, 'RXFFE FLOAT CTL', false, 'FOM'); % select taps (taps), pulse response (ISI), or FOM for floating taps determination | 9213 | OP.RXFFE_FLOAT_CTL = xls_parameter(parameter, 'RXFFE FLOAT CTL', false, 'FOM'); % select taps (taps), pulse response (ISI), or FOM for floating taps determination | ||
9423 | OP.RXFFE_TAP_CONSTRAINT =xls_parameter(parameter, 'RXFFE TAP CONSTRAINT', false, 'Unity Cursor'); % "Unity sum taps", "Unity Cursor", of unbounded | 9214 | OP.RXFFE_TAP_CONSTRAINT =xls_parameter(parameter, 'RXFFE TAP CONSTRAINT', false, 'Unity Cursor'); % "Unity sum taps", "Unity Cursor", of unbounded | ||
9424 | if OP.MLSE && param.ndfe==0 | 9215 | if OP.MLSE && param.ndfe==0 | ||
9425 | error('At least DFE 1 must be set to use MLSE'); | 9216 | error('At least DFE 1 must be set to use MLSE'); | ||
9426 | end | 9217 | end | ||
9427 | OP.TIME_AXIS = xls_parameter(parameter, 'TIME_AXIS', false, 'UI'); % if0 OP.display set pulse response xaxis to seconds or UI | 9218 | OP.TIME_AXIS = xls_parameter(parameter, 'TIME_AXIS', false, 'UI'); % if0 OP.display set pulse response xaxis to seconds or UI | ||
9428 | % MNSE parameters | 9219 | % MNSE parameters | ||
9429 | OP.Do_XT_Noise= xls_parameter(parameter, 'Do_XT_Noise', false, 1); | 9220 | OP.Do_XT_Noise= xls_parameter(parameter, 'Do_XT_Noise', false, 1); | ||
9430 | OP.FFE_SNR= xls_parameter(parameter, 'FFE_SNR', false, 1); | 9221 | OP.FFE_SNR= xls_parameter(parameter, 'FFE_SNR', false, 1); | ||
9431 | OP.Do_Colored_Noise= xls_parameter(parameter, 'Do_Colored_Noise', false, 1); | 9222 | OP.Do_Colored_Noise= xls_parameter(parameter, 'Do_Colored_Noise', false, 1); | ||
9432 | OP.Do_White_Noise=xls_parameter(parameter, 'Do_White_Noise', false, 0); | 9223 | OP.Do_White_Noise=xls_parameter(parameter, 'Do_White_Noise', false, 0); | ||
≠ | 9433 | OP.FFE_OPT_METHOD=xls_parameter(parameter,'FFE_OPT_METHOD',false,'MMSE'); % 'MMSE','FV-LMS' | ≠ | 9224 | OP.FFE_OPT_METHOD=xls_parameter(parameter,'FFE_OPT_METHOD',false,'MMSE'); % 'MMSE','FV-LMS', 'WIENER-HOPF', |
− | 9434 | % Commit request 4p4_7, healey_3dj_COM_01_240416 |
| ||
9435 | OP.TS_SRCH_MODE=xls_parameter(parameter,'TS_SRCH_MODE',false,'full-sweep'); % full-sweep, middle | ||||
| + | 9225 | |||
9436 | % need to make sure TD mode does not invoke FD operations | 9226 | % need to make sure TD mode does not invoke FD operations | ||
9437 | if OP.TDMODE % need to set GET_FD false of TDMODE | 9227 | if OP.TDMODE % need to set GET_FD false of TDMODE | ||
9438 | OP.GET_FD=false; | 9228 | OP.GET_FD=false; | ||
9439 | OP.ERL_ONLY=0; | 9229 | OP.ERL_ONLY=0; | ||
9440 | OP.ERL=0; | 9230 | OP.ERL=0; | ||
9441 | OP.PTDR=0; | 9231 | OP.PTDR=0; | ||
9442 | OP.TDR=0; | 9232 | OP.TDR=0; | ||
9443 | OP.RX_CALIBRATION=0; | 9233 | OP.RX_CALIBRATION=0; | ||
9444 | end | 9234 | end | ||
9445 | if OP.SAVE_CONFIG2MAT || OP.CONFIG2MAT_ONLY | 9235 | if OP.SAVE_CONFIG2MAT || OP.CONFIG2MAT_ONLY | ||
9446 | save(matcongfile ,'parameter'); | 9236 | save(matcongfile ,'parameter'); | ||
9447 | end | 9237 | end | ||
9448 | 9238 | ||||
9449 | 9239 | ||||
9450 | %% At the very end of Parameter reading, swap in the proper Tx and Rx values for package parameters based on pkg name | 9240 | %% At the very end of Parameter reading, swap in the proper Tx and Rx values for package parameters based on pkg name | ||
9451 | if ~isempty(param.PKG_NAME) | 9241 | if ~isempty(param.PKG_NAME) | ||
9452 | if length(param.PKG_NAME) == 1 | 9242 | if length(param.PKG_NAME) == 1 | ||
9453 | param.PKG_NAME = [param.PKG_NAME param.PKG_NAME]; | 9243 | param.PKG_NAME = [param.PKG_NAME param.PKG_NAME]; | ||
9454 | end | 9244 | end | ||
9455 | tx_rx_fields = {'C_pkg_board' 'R_diepad'}; | 9245 | tx_rx_fields = {'C_pkg_board' 'R_diepad'}; | ||
9456 | tx_rx_fields_matrix = {'pkg_Z_c'}; | 9246 | tx_rx_fields_matrix = {'pkg_Z_c'}; | ||
9457 | tx_fields = {'z_p_tx_cases' 'z_p_next_cases' 'z_p_fext_cases' 'pkg_gamma0_a1_a2' 'pkg_tau' 'a_thru' 'a_fext'}; | 9247 | tx_fields = {'z_p_tx_cases' 'z_p_next_cases' 'z_p_fext_cases' 'pkg_gamma0_a1_a2' 'pkg_tau' 'a_thru' 'a_fext'}; | ||
9458 | rx_fields = {'z_p_rx_cases' 'a_next'}; | 9248 | rx_fields = {'z_p_rx_cases' 'a_next'}; | ||
9459 | tx_pkg_name=param.PKG_NAME{1}; | 9249 | tx_pkg_name=param.PKG_NAME{1}; | ||
9460 | rx_pkg_name=param.PKG_NAME{2}; | 9250 | rx_pkg_name=param.PKG_NAME{2}; | ||
9461 | tx_pkg_struct=param.PKG.(tx_pkg_name); | 9251 | tx_pkg_struct=param.PKG.(tx_pkg_name); | ||
9462 | rx_pkg_struct=param.PKG.(rx_pkg_name); | 9252 | rx_pkg_struct=param.PKG.(rx_pkg_name); | ||
9463 |
| 9253 |
| ||
9464 | %tx_rx_fields: put the value from the tx package in the Tx position and the value from the rx package in the RX position | 9254 | %tx_rx_fields: put the value from the tx package in the Tx position and the value from the rx package in the RX position | ||
9465 | for j=1:length(tx_rx_fields) | 9255 | for j=1:length(tx_rx_fields) | ||
9466 | tx_val = tx_pkg_struct.(tx_rx_fields{j}); | 9256 | tx_val = tx_pkg_struct.(tx_rx_fields{j}); | ||
9467 | rx_val = rx_pkg_struct.(tx_rx_fields{j}); | 9257 | rx_val = rx_pkg_struct.(tx_rx_fields{j}); | ||
9468 | param.(tx_rx_fields{j}) = [tx_val(1) rx_val(2)]; | 9258 | param.(tx_rx_fields{j}) = [tx_val(1) rx_val(2)]; | ||
9469 | end | 9259 | end | ||
9470 |
| 9260 |
| ||
9471 | %tx_rx_fields_matrix: same as tx_rx_fields but in matrix form | 9261 | %tx_rx_fields_matrix: same as tx_rx_fields but in matrix form | ||
9472 | for j=1:length(tx_rx_fields_matrix) | 9262 | for j=1:length(tx_rx_fields_matrix) | ||
9473 | tx_val = tx_pkg_struct.(tx_rx_fields_matrix{j})(1,:); | 9263 | tx_val = tx_pkg_struct.(tx_rx_fields_matrix{j})(1,:); | ||
9474 | rx_val = rx_pkg_struct.(tx_rx_fields_matrix{j})(2,:); | 9264 | rx_val = rx_pkg_struct.(tx_rx_fields_matrix{j})(2,:); | ||
9475 | param.(tx_rx_fields_matrix{j}) = [tx_val; rx_val]; | 9265 | param.(tx_rx_fields_matrix{j}) = [tx_val; rx_val]; | ||
9476 | end | 9266 | end | ||
9477 |
| 9267 |
| ||
9478 | %tx_fields: use only the tx package values | 9268 | %tx_fields: use only the tx package values | ||
9479 | for j=1:length(tx_fields) | 9269 | for j=1:length(tx_fields) | ||
9480 | param.(tx_fields{j}) = tx_pkg_struct.(tx_fields{j}); | 9270 | param.(tx_fields{j}) = tx_pkg_struct.(tx_fields{j}); | ||
9481 | end | 9271 | end | ||
9482 |
| 9272 |
| ||
9483 | %rx_fields: use only the rx package values | 9273 | %rx_fields: use only the rx package values | ||
9484 | for j=1:length(rx_fields) | 9274 | for j=1:length(rx_fields) | ||
9485 | param.(rx_fields{j}) = rx_pkg_struct.(rx_fields{j}); | 9275 | param.(rx_fields{j}) = rx_pkg_struct.(rx_fields{j}); | ||
9486 | end | 9276 | end | ||
9487 | 9277 | ||||
9488 | end | 9278 | end | ||
9489 | 9279 | ||||
9490 | 9280 | ||||
9491 | %% | 9281 | %% | ||
9492 | function [data, SDD, SDC] = read_p2_s2params(infile, plot_ini_s_params, plot_dif_s_params, ports,OP) | 9282 | function [data, SDD, SDC] = read_p2_s2params(infile, plot_ini_s_params, plot_dif_s_params, ports,OP) | ||
9493 | %% FUNCTION :: read_sp4_sparams | 9283 | %% FUNCTION :: read_sp4_sparams | ||
9494 | % | 9284 | % | ||
9495 | % Description | 9285 | % Description | ||
9496 | % Read the fid of single-ended 4-port complex S-parameters | 9286 | % Read the fid of single-ended 4-port complex S-parameters | ||
9497 | % in Touchstone format 'file' and convert to the internal | 9287 | % in Touchstone format 'file' and convert to the internal | ||
9498 | % format using the port transform 'ports' | 9288 | % format using the port transform 'ports' | ||
9499 | % | 9289 | % | ||
9500 | % Created by Mike Y. He | 9290 | % Created by Mike Y. He | ||
9501 | % April 22, 2005 | 9291 | % April 22, 2005 | ||
9502 | % | 9292 | % | ||
9503 | % Reused some code from | 9293 | % Reused some code from | ||
9504 | % Anthony Sanders, Alex Deas, Bob Davidov (24 January 2005) | 9294 | % Anthony Sanders, Alex Deas, Bob Davidov (24 January 2005) | ||
9505 | % for touchstone 4-port S-matrix import. | 9295 | % for touchstone 4-port S-matrix import. | ||
9506 | % | 9296 | % | ||
9507 | % Modified (2012-July-27) by Ken Young to match current indexing scheme and | 9297 | % Modified (2012-July-27) by Ken Young to match current indexing scheme and | ||
9508 | % optimized for quicker parameter matching and parsing. also, separated out | 9298 | % optimized for quicker parameter matching and parsing. also, separated out | ||
9509 | % the plotting algorithms into their own sub-function routines | 9299 | % the plotting algorithms into their own sub-function routines | ||
9510 | % | 9300 | % | ||
9511 | % Modified December 2021 to use read_Nport_touchstone | 9301 | % Modified December 2021 to use read_Nport_touchstone | ||
9512 | % This is faster reader that is capable of reading touchstone with any number of ports | 9302 | % This is faster reader that is capable of reading touchstone with any number of ports | ||
9513 | % | 9303 | % | ||
9514 | % Input Variables (required) | 9304 | % Input Variables (required) | ||
9515 | % infile -- The s4p file to be read and converted | 9305 | % infile -- The s4p file to be read and converted | ||
9516 | % plot_ini_sparams -- Plot the initial s-parameter information. For debugging purposes | 9306 | % plot_ini_sparams -- Plot the initial s-parameter information. For debugging purposes | ||
9517 | % plot_dif_s_params -- Plot the differential s-parameter information. For debugging purposes | 9307 | % plot_dif_s_params -- Plot the differential s-parameter information. For debugging purposes | ||
9518 | % ports -- Re-order the port layout | 9308 | % ports -- Re-order the port layout | ||
9519 | % | 9309 | % | ||
9520 | % Output/Return Variables | 9310 | % Output/Return Variables | ||
9521 | % data -- structure containing network parameter data points and frequency axis | 9311 | % data -- structure containing network parameter data points and frequency axis | ||
9522 | % sdc -- the differential in/common-mode out s-parameter data matrix | 9312 | % sdc -- the differential in/common-mode out s-parameter data matrix | ||
9523 | % sdd -- the differential in/differential out s-parameter data matrix | 9313 | % sdd -- the differential in/differential out s-parameter data matrix | ||
9524 | % | 9314 | % | ||
9525 | 9315 | ||||
9526 | 9316 | ||||
9527 | % backwards compatibility settings. can be removed in updated code. | 9317 | % backwards compatibility settings. can be removed in updated code. | ||
9528 | if ~exist('OP', 'var'); OP.DISPLAY_WINDOW = true; end | 9318 | if ~exist('OP', 'var'); OP.DISPLAY_WINDOW = true; end | ||
9529 | if isempty(ports); ports = [1 2]; end % default order normally used. | 9319 | if isempty(ports); ports = [1 2]; end % default order normally used. | ||
9530 | ports = [1 2]; | 9320 | ports = [1 2]; | ||
9531 | 9321 | ||||
9532 | 9322 | ||||
9533 | if OP.DISPLAY_WINDOW | 9323 | if OP.DISPLAY_WINDOW | ||
9534 | set(0,'defaulttextinterpreter','none') % prevents subscripting character in displayed messages | 9324 | set(0,'defaulttextinterpreter','none') % prevents subscripting character in displayed messages | ||
9535 | hMsgBox = msgbox(infile, 'Reading S-Parameter File'); % display a progress bar for reading the s-parameter file(s) | 9325 | hMsgBox = msgbox(infile, 'Reading S-Parameter File'); % display a progress bar for reading the s-parameter file(s) | ||
9536 | end | 9326 | end | ||
9537 | 9327 | ||||
9538 | %AJG: fast touchstone read for any number of ports | 9328 | %AJG: fast touchstone read for any number of ports | ||
9539 | [sch,schFreqAxis]=read_Nport_touchstone(infile,ports); | 9329 | [sch,schFreqAxis]=read_Nport_touchstone(infile,ports); | ||
9540 | 9330 | ||||
9541 | 9331 | ||||
9542 | 9332 | ||||
9543 | D=NaN(size(sch)); | 9333 | D=NaN(size(sch)); | ||
9544 | % calculate differential s parameter matrix from single ended | 9334 | % calculate differential s parameter matrix from single ended | ||
9545 | for i=1:size(sch,1) | 9335 | for i=1:size(sch,1) | ||
9546 | S(:,:) = sch(i,:,:); | 9336 | S(:,:) = sch(i,:,:); | ||
9547 | T = [1 1 ; 1 -1 ]; | 9337 | T = [1 1 ; 1 -1 ]; | ||
9548 | W = T * (S / T); | 9338 | W = T * (S / T); | ||
9549 | D(i,:,:) = W(:,:); | 9339 | D(i,:,:) = W(:,:); | ||
9550 | end | 9340 | end | ||
9551 | 9341 | ||||
9552 | % D matrix should be | 9342 | % D matrix should be | ||
9553 | % Scc11 Scd11 Scc12 Scd21 | 9343 | % Scc11 Scd11 Scc12 Scd21 | ||
9554 | % Sdc11 Sdd11 Sdc12 Sdd12 | 9344 | % Sdc11 Sdd11 Sdc12 Sdd12 | ||
9555 | % Scc21 Scd21 Scc22 Scd22 | 9345 | % Scc21 Scd21 Scc22 Scd22 | ||
9556 | % Sdc21 Sdd21 Sdc22 Sdd22 | 9346 | % Sdc21 Sdd21 Sdc22 Sdd22 | ||
9557 | 9347 | ||||
9558 | % proper values | 9348 | % proper values | ||
9559 | %AJG: matrix can be properly referenced after fixing mapping | 9349 | %AJG: matrix can be properly referenced after fixing mapping | ||
9560 | SDD(:,1,1) = D(:,2,2); | 9350 | SDD(:,1,1) = D(:,2,2); | ||
9561 | SDC(:,1,1)= D(:,2,1); | 9351 | SDC(:,1,1)= D(:,2,1); | ||
9562 | SCC(:,1,1)= D(:,1,1); | 9352 | SCC(:,1,1)= D(:,1,1); | ||
9563 | SCD(:,1,1)= D(:,1,2); | 9353 | SCD(:,1,1)= D(:,1,2); | ||
9564 | 9354 | ||||
9565 | 9355 | ||||
9566 | 9356 | ||||
9567 | % backwards compatibility output variables | 9357 | % backwards compatibility output variables | ||
9568 | data.m = sch; | 9358 | data.m = sch; | ||
9569 | %schFreqAxis=schFreqAxis(1:freqCounter); % truncating preallocated array to number of freq points. | 9359 | %schFreqAxis=schFreqAxis(1:freqCounter); % truncating preallocated array to number of freq points. | ||
9570 | data.freq = schFreqAxis; | 9360 | data.freq = schFreqAxis; | ||
9571 | colors = 'rgbk'; | 9361 | colors = 'rgbk'; | ||
9572 | 9362 | ||||
9573 | if (plot_ini_s_params == 1) | 9363 | if (plot_ini_s_params == 1) | ||
9574 | figure('name', 'Single-ended s-parameters');set(gcf,'Tag','COM'); | 9364 | figure('name', 'Single-ended s-parameters');set(gcf,'Tag','COM'); | ||
9575 | for mj=1:4 | 9365 | for mj=1:4 | ||
9576 | % subplot(2,2,mj); | 9366 | % subplot(2,2,mj); | ||
9577 | for mi=1:4 | 9367 | for mi=1:4 | ||
9578 | plot(data.freq, 20*log10(abs(data.m(:,mj,mi)+1.0e-15)), ... | 9368 | plot(data.freq, 20*log10(abs(data.m(:,mj,mi)+1.0e-15)), ... | ||
9579 | colors(mi), 'linewidth', 2, 'disp', sprintf('S%d%d', mj, mi)); | 9369 | colors(mi), 'linewidth', 2, 'disp', sprintf('S%d%d', mj, mi)); | ||
9580 | hold on | 9370 | hold on | ||
9581 | end | 9371 | end | ||
9582 | xlabel('Frequency (Hz)'); | 9372 | xlabel('Frequency (Hz)'); | ||
9583 | ylabel('Magnitude (dB)'); | 9373 | ylabel('Magnitude (dB)'); | ||
9584 | legend show | 9374 | legend show | ||
9585 | grid on | 9375 | grid on | ||
9586 | title(sprintf('Output port %d', mj)); | 9376 | title(sprintf('Output port %d', mj)); | ||
9587 | end | 9377 | end | ||
9588 | end | 9378 | end | ||
9589 | plot_dif_s_params =0; | 9379 | plot_dif_s_params =0; | ||
9590 | if (plot_dif_s_params == 1) | 9380 | if (plot_dif_s_params == 1) | ||
9591 | figure('name', 'Mixed-mode s-parameters');set(gcf,'Tag','COM'); | 9381 | figure('name', 'Mixed-mode s-parameters');set(gcf,'Tag','COM'); | ||
9592 | % subplot(2,1,1); | 9382 | % subplot(2,1,1); | ||
9593 | for mj=1:1 | 9383 | for mj=1:1 | ||
9594 | for mi=1:1 | 9384 | for mi=1:1 | ||
9595 | plot(data.freq, 20*log10(abs(squeeze(SDD(:,mj,mi)))), ... | 9385 | plot(data.freq, 20*log10(abs(squeeze(SDD(:,mj,mi)))), ... | ||
9596 | colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDD%d%d', mj, mi)); | 9386 | colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDD%d%d', mj, mi)); | ||
9597 | hold on | 9387 | hold on | ||
9598 | end | 9388 | end | ||
9599 | end | 9389 | end | ||
9600 | xlabel('Frequency (Hz)'); | 9390 | xlabel('Frequency (Hz)'); | ||
9601 | ylabel('Magnitude (dB)'); | 9391 | ylabel('Magnitude (dB)'); | ||
9602 | legend show | 9392 | legend show | ||
9603 | grid on | 9393 | grid on | ||
9604 | title(infile); | 9394 | title(infile); | ||
9605 |
| 9395 |
| ||
9606 | % subplot(2,1,2); | 9396 | % subplot(2,1,2); | ||
9607 | % for mj=1:2 | 9397 | % for mj=1:2 | ||
9608 | % for mi=1:2 | 9398 | % for mi=1:2 | ||
9609 | % plot(data.freq, 20*log10(abs(SDC(:,mj,mi))+1.0e-15), ... | 9399 | % plot(data.freq, 20*log10(abs(SDC(:,mj,mi))+1.0e-15), ... | ||
9610 | % colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDC%d%d', mj, mi)); | 9400 | % colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDC%d%d', mj, mi)); | ||
9611 | % hold on | 9401 | % hold on | ||
9612 | % end | 9402 | % end | ||
9613 | % end | 9403 | % end | ||
9614 | % xlabel('Frequency (Hz)'); | 9404 | % xlabel('Frequency (Hz)'); | ||
9615 | % ylabel('Magnitude (dB)'); | 9405 | % ylabel('Magnitude (dB)'); | ||
9616 | % legend show | 9406 | % legend show | ||
9617 | % grid on | 9407 | % grid on | ||
9618 | end | 9408 | end | ||
9619 | 9409 | ||||
9620 | if OP.DISPLAY_WINDOW, close(hMsgBox); end | 9410 | if OP.DISPLAY_WINDOW, close(hMsgBox); end | ||
9621 | % end read_sp2_sparam | 9411 | % end read_sp2_sparam | ||
9622 | 9412 | ||||
9623 | function [data, SDD, SDC, SCC ] = read_p4_s4params(infile, plot_ini_s_params, plot_dif_s_params, ports,OP,param) | 9413 | function [data, SDD, SDC, SCC ] = read_p4_s4params(infile, plot_ini_s_params, plot_dif_s_params, ports,OP,param) | ||
9624 | %% FUNCTION :: read_sp4_sparams | 9414 | %% FUNCTION :: read_sp4_sparams | ||
9625 | % | 9415 | % | ||
9626 | % Description | 9416 | % Description | ||
9627 | % Read the fid of single-ended 4-port complex S-parameters | 9417 | % Read the fid of single-ended 4-port complex S-parameters | ||
9628 | % in Touchstone format 'file' and convert to the internal | 9418 | % in Touchstone format 'file' and convert to the internal | ||
9629 | % format using the port transform 'ports' | 9419 | % format using the port transform 'ports' | ||
9630 | % | 9420 | % | ||
9631 | % Created by Mike Y. He | 9421 | % Created by Mike Y. He | ||
9632 | % April 22, 2005 | 9422 | % April 22, 2005 | ||
9633 | % | 9423 | % | ||
9634 | % Reused some code from | 9424 | % Reused some code from | ||
9635 | % Anthony Sanders, Alex Deas, Bob Davidov (24 January 2005) | 9425 | % Anthony Sanders, Alex Deas, Bob Davidov (24 January 2005) | ||
9636 | % for touchstone 4-port S-matrix import. | 9426 | % for touchstone 4-port S-matrix import. | ||
9637 | % | 9427 | % | ||
9638 | % Modified (2012-July-27) by Ken Young to match current indexing scheme and | 9428 | % Modified (2012-July-27) by Ken Young to match current indexing scheme and | ||
9639 | % optimized for quicker parameter matching and parsing. also, separated out | 9429 | % optimized for quicker parameter matching and parsing. also, separated out | ||
9640 | % the plotting algorithms into their own sub-function routines | 9430 | % the plotting algorithms into their own sub-function routines | ||
9641 | % | 9431 | % | ||
9642 | % Modified December 2021 to use read_Nport_touchstone | 9432 | % Modified December 2021 to use read_Nport_touchstone | ||
9643 | % This is faster reader that is capable of reading touchstone with any number of ports | 9433 | % This is faster reader that is capable of reading touchstone with any number of ports | ||
9644 | % | 9434 | % | ||
9645 | % Input Variables (required) | 9435 | % Input Variables (required) | ||
9646 | % infile -- The s4p file to be read and converted | 9436 | % infile -- The s4p file to be read and converted | ||
9647 | % plot_ini_sparams -- Plot the initial s-parameter information. For debugging purposes | 9437 | % plot_ini_sparams -- Plot the initial s-parameter information. For debugging purposes | ||
9648 | % plot_dif_s_params -- Plot the differential s-parameter information. For debugging purposes | 9438 | % plot_dif_s_params -- Plot the differential s-parameter information. For debugging purposes | ||
9649 | % ports -- Re-order the port layout | 9439 | % ports -- Re-order the port layout | ||
9650 | % OP | 9440 | % OP | ||
9651 | % param | 9441 | % param | ||
9652 | % Output/Return Variables | 9442 | % Output/Return Variables | ||
9653 | % data -- structure containing network parameter data points and frequency axis | 9443 | % data -- structure containing network parameter data points and frequency axis | ||
9654 | % sdd -- the differential in/differential out s-parameter data matrix | 9444 | % sdd -- the differential in/differential out s-parameter data matrix | ||
9655 | % sdc -- the differential in/common-mode out s-parameter data matrix | 9445 | % sdc -- the differential in/common-mode out s-parameter data matrix | ||
9656 | % scc -- the common mode in/common-mode out s-parameter data matrix | 9446 | % scc -- the common mode in/common-mode out s-parameter data matrix | ||
9657 | % | 9447 | % | ||
9658 | % | 9448 | % | ||
9659 | 9449 | ||||
9660 | 9450 | ||||
9661 | % backwards compatibility settings. can be removed in updated code. | 9451 | % backwards compatibility settings. can be removed in updated code. | ||
9662 | if ~exist('OP', 'var'); OP.DISPLAY_WINDOW = true; end | 9452 | if ~exist('OP', 'var'); OP.DISPLAY_WINDOW = true; end | ||
9663 | if isempty(ports); ports = [1 3 2 4]; end % default order normally used. | 9453 | if isempty(ports); ports = [1 3 2 4]; end % default order normally used. | ||
9664 | 9454 | ||||
9665 | % adjust ports to maintain the meaning [in1, in2 , out1, out2] when one | 9455 | % adjust ports to maintain the meaning [in1, in2 , out1, out2] when one | ||
9666 | % pair is reversed. | 9456 | % pair is reversed. | ||
9667 | %ports_adj=ports; for k=1:4, ports_adj(k)=find(ports==k); end; ports=ports_adj; | 9457 | %ports_adj=ports; for k=1:4, ports_adj(k)=find(ports==k); end; ports=ports_adj; | ||
9668 | 9458 | ||||
9669 | if OP.DISPLAY_WINDOW | 9459 | if OP.DISPLAY_WINDOW | ||
9670 | hMsgBox = msgbox(infile, 'Reading S-Parameter File'); % display a progress bar for reading the s-parameter file(s) | 9460 | hMsgBox = msgbox(infile, 'Reading S-Parameter File'); % display a progress bar for reading the s-parameter file(s) | ||
9671 | end | 9461 | end | ||
9672 | 9462 | ||||
9673 | %AJG: fast touchstone read for any number of ports | 9463 | %AJG: fast touchstone read for any number of ports | ||
9674 | [sch,schFreqAxis]=read_Nport_touchstone(infile,ports); | 9464 | [sch,schFreqAxis]=read_Nport_touchstone(infile,ports); | ||
9675 | % matrix to introduce p or n skew on Tx or Rx RIM 12/29/2023 | 9465 | % matrix to introduce p or n skew on Tx or Rx RIM 12/29/2023 | ||
9676 | % Sigma's will be form exp(2i*pi*f*skew*1e-12). i.e. if skew = 0 sigma = 1 | 9466 | % Sigma's will be form exp(2i*pi*f*skew*1e-12). i.e. if skew = 0 sigma = 1 | ||
9677 | % need to swap sigma for 1 and 3 and 2 and 4 not RIM 12/29/2023 | 9467 | % need to swap sigma for 1 and 3 and 2 and 4 not RIM 12/29/2023 | ||
9678 | Sigfct = ... | 9468 | Sigfct = ... | ||
9679 | @(sigma2,sigma1,sigma4,sigma3)reshape([sigma1.^2,sigma1.*sigma2,sigma1.*sigma3,sigma1.*sigma4,sigma1.*sigma2,sigma2.^2,sigma2.*sigma3,sigma2.*sigma4,sigma1.*sigma3,sigma2.*sigma3,sigma3.^2,sigma3.*sigma4,sigma1.*sigma4,sigma2.*sigma4,sigma3.*sigma4,sigma4.^2],[4,4]); | 9469 | @(sigma2,sigma1,sigma4,sigma3)reshape([sigma1.^2,sigma1.*sigma2,sigma1.*sigma3,sigma1.*sigma4,sigma1.*sigma2,sigma2.^2,sigma2.*sigma3,sigma2.*sigma4,sigma1.*sigma3,sigma2.*sigma3,sigma3.^2,sigma3.*sigma4,sigma1.*sigma4,sigma2.*sigma4,sigma3.*sigma4,sigma4.^2],[4,4]); | ||
9680 | D=NaN(size(sch)); | 9470 | D=NaN(size(sch)); | ||
9681 | % calculate differential s parameter matrix from single ended | 9471 | % calculate differential s parameter matrix from single ended | ||
9682 | % skew added RIM 12/29/2023 | 9472 | % skew added RIM 12/29/2023 | ||
9683 | for i=1:size(sch,1) | 9473 | for i=1:size(sch,1) | ||
9684 | f=schFreqAxis(i); | 9474 | f=schFreqAxis(i); | ||
9685 | sigma_matrix=Sigfct(exp(2i*pi*f*param.Txpskew*1e-12),exp(2i*pi*f*param.Txnskew*1e-12),exp(2i*pi*f*param.Rxpskew*1e-12),exp(2i*pi*f*param.Rxnskew*1e-12) ); | 9475 | sigma_matrix=Sigfct(exp(2i*pi*f*param.Txpskew*1e-12),exp(2i*pi*f*param.Txnskew*1e-12),exp(2i*pi*f*param.Rxpskew*1e-12),exp(2i*pi*f*param.Rxnskew*1e-12) ); | ||
9686 | S(:,:) = sch(i,:,:); | 9476 | S(:,:) = sch(i,:,:); | ||
9687 | Snew=sigma_matrix.*S; | 9477 | Snew=sigma_matrix.*S; | ||
9688 | T = [1 1 0 0 ; 1 -1 0 0 ; 0 0 1 1 ; 0 0 1 -1]; | 9478 | T = [1 1 0 0 ; 1 -1 0 0 ; 0 0 1 1 ; 0 0 1 -1]; | ||
9689 | W = T * (Snew / T); | 9479 | W = T * (Snew / T); | ||
9690 | D(i,:,:) = W(:,:); | 9480 | D(i,:,:) = W(:,:); | ||
9691 | end | 9481 | end | ||
9692 | 9482 | ||||
9693 | % D matrix should be | 9483 | % D matrix should be | ||
9694 | % Scc11 Scd11 Scc12 Scd21 | 9484 | % Scc11 Scd11 Scc12 Scd21 | ||
9695 | % Sdc11 Sdd11 Sdc12 Sdd12 | 9485 | % Sdc11 Sdd11 Sdc12 Sdd12 | ||
9696 | % Scc21 Scd21 Scc22 Scd22 | 9486 | % Scc21 Scd21 Scc22 Scd22 | ||
9697 | % Sdc21 Sdd21 Sdc22 Sdd22 | 9487 | % Sdc21 Sdd21 Sdc22 Sdd22 | ||
9698 | 9488 | ||||
9699 | % proper values | 9489 | % proper values | ||
9700 | SDD(:,1,1) = D(:,2,2); | 9490 | SDD(:,1,1) = D(:,2,2); | ||
9701 | SDD(:,2,2) = D(:,4,4); | 9491 | SDD(:,2,2) = D(:,4,4); | ||
9702 | SDD(:,1,2) = D(:,2,4); | 9492 | SDD(:,1,2) = D(:,2,4); | ||
9703 | SDD(:,2,1) = D(:,4,2); | 9493 | SDD(:,2,1) = D(:,4,2); | ||
9704 | 9494 | ||||
9705 | SDC(:,1,1) = D(:,2,1); | 9495 | SDC(:,1,1) = D(:,2,1); | ||
9706 | SDC(:,2,2) = D(:,4,3); | 9496 | SDC(:,2,2) = D(:,4,3); | ||
9707 | SDC(:,1,2) = D(:,2,3); | 9497 | SDC(:,1,2) = D(:,2,3); | ||
9708 | SDC(:,2,1) = D(:,4,1); | 9498 | SDC(:,2,1) = D(:,4,1); | ||
9709 | 9499 | ||||
9710 | SCC(:,1,1) = D(:,1,1); | 9500 | SCC(:,1,1) = D(:,1,1); | ||
9711 | SCC(:,2,2) = D(:,3,3); | 9501 | SCC(:,2,2) = D(:,3,3); | ||
9712 | SCC(:,1,2) = D(:,1,3); | 9502 | SCC(:,1,2) = D(:,1,3); | ||
9713 | SCC(:,2,1) = D(:,3,1); | 9503 | SCC(:,2,1) = D(:,3,1); | ||
9714 | 9504 | ||||
9715 | % backwards compatibility output variables | 9505 | % backwards compatibility output variables | ||
9716 | data.m = sch; | 9506 | data.m = sch; | ||
9717 | %schFreqAxis=schFreqAxis(1:freqCounter); % truncating preallocated array to number of freq points. | 9507 | %schFreqAxis=schFreqAxis(1:freqCounter); % truncating preallocated array to number of freq points. | ||
9718 | data.freq = schFreqAxis; | 9508 | data.freq = schFreqAxis; | ||
9719 | colors = 'rgbk'; | 9509 | colors = 'rgbk'; | ||
9720 | 9510 | ||||
9721 | if (plot_ini_s_params == 1) | 9511 | if (plot_ini_s_params == 1) | ||
9722 | figure('name', 'Single-ended s-parameters');set(gcf,'Tag','COM'); | 9512 | figure('name', 'Single-ended s-parameters');set(gcf,'Tag','COM'); | ||
9723 | for mj=1:4 | 9513 | for mj=1:4 | ||
9724 | subplot(2,2,mj); | 9514 | subplot(2,2,mj); | ||
9725 | for mi=1:4 | 9515 | for mi=1:4 | ||
9726 | plot(data.freq, 20*log10(abs(data.m(:,mj,mi)+1.0e-15)), ... | 9516 | plot(data.freq, 20*log10(abs(data.m(:,mj,mi)+1.0e-15)), ... | ||
9727 | colors(mi), 'linewidth', 2, 'disp', sprintf('S%d%d', mj, mi)); | 9517 | colors(mi), 'linewidth', 2, 'disp', sprintf('S%d%d', mj, mi)); | ||
9728 | hold on | 9518 | hold on | ||
9729 | end | 9519 | end | ||
9730 | xlabel('Frequency (Hz)'); | 9520 | xlabel('Frequency (Hz)'); | ||
9731 | ylabel('Magnitude (dB)'); | 9521 | ylabel('Magnitude (dB)'); | ||
9732 | legend show | 9522 | legend show | ||
9733 | grid on | 9523 | grid on | ||
9734 | title(sprintf('Output port %d', mj)); | 9524 | title(sprintf('Output port %d', mj)); | ||
9735 | end | 9525 | end | ||
9736 | end | 9526 | end | ||
9737 | plot_dif_s_params =0; | 9527 | plot_dif_s_params =0; | ||
9738 | if (plot_dif_s_params == 1) | 9528 | if (plot_dif_s_params == 1) | ||
9739 | figure('name', 'Mixed-mode s-parameters');set(gcf,'Tag','COM'); | 9529 | figure('name', 'Mixed-mode s-parameters');set(gcf,'Tag','COM'); | ||
9740 | % subplot(2,1,1); | 9530 | % subplot(2,1,1); | ||
9741 | for mj=1:2 | 9531 | for mj=1:2 | ||
9742 | for mi=1:2 | 9532 | for mi=1:2 | ||
9743 | plot(data.freq, 20*log10(abs(SDD(:,mj,mi))), ... | 9533 | plot(data.freq, 20*log10(abs(SDD(:,mj,mi))), ... | ||
9744 | colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDD%d%d', mj, mi)); | 9534 | colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDD%d%d', mj, mi)); | ||
9745 | hold on | 9535 | hold on | ||
9746 | end | 9536 | end | ||
9747 | end | 9537 | end | ||
9748 | xlabel('Frequency (Hz)'); | 9538 | xlabel('Frequency (Hz)'); | ||
9749 | ylabel('Magnitude (dB)'); | 9539 | ylabel('Magnitude (dB)'); | ||
9750 | legend show | 9540 | legend show | ||
9751 | grid on | 9541 | grid on | ||
9752 | title(infile); | 9542 | title(infile); | ||
9753 | % | 9543 | % | ||
9754 | % subplot(2,1,2); | 9544 | % subplot(2,1,2); | ||
9755 | % for mj=1:2 | 9545 | % for mj=1:2 | ||
9756 | % for mi=1:2 | 9546 | % for mi=1:2 | ||
9757 | % plot(data.freq, 20*log10(abs(SDC(:,mj,mi))+1.0e-15), ... | 9547 | % plot(data.freq, 20*log10(abs(SDC(:,mj,mi))+1.0e-15), ... | ||
9758 | % colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDC%d%d', mj, mi)); | 9548 | % colors((mj-1)*2+mi), 'linewidth',2, 'disp', sprintf('SDC%d%d', mj, mi)); | ||
9759 | % hold on | 9549 | % hold on | ||
9760 | % end | 9550 | % end | ||
9761 | % end | 9551 | % end | ||
9762 | % xlabel('Frequency (Hz)'); | 9552 | % xlabel('Frequency (Hz)'); | ||
9763 | % ylabel('Magnitude (dB)'); | 9553 | % ylabel('Magnitude (dB)'); | ||
9764 | % legend show | 9554 | % legend show | ||
9765 | % grid on | 9555 | % grid on | ||
9766 | end | 9556 | end | ||
9767 | 9557 | ||||
9768 | if OP.DISPLAY_WINDOW, close(hMsgBox); end | 9558 | if OP.DISPLAY_WINDOW, close(hMsgBox); end | ||
9769 | % end read_sp4_sparam | 9559 | % end read_sp4_sparam | ||
9770 | function param_struct = read_package_parameters(parameter,param_struct) | 9560 | function param_struct = read_package_parameters(parameter,param_struct) | ||
9771 | 9561 | ||||
9772 | %With the introduction of Package sections in COM spreadsheet, it makes sense to have a single function that grabs all package parameters from a parameter block | 9562 | %With the introduction of Package sections in COM spreadsheet, it makes sense to have a single function that grabs all package parameters from a parameter block | ||
9773 | %This block should eventually replace what is in read_ParamConfigFile | 9563 | %This block should eventually replace what is in read_ParamConfigFile | ||
9774 | %It can be called as: param = read_package_parameters(parameter, param) | 9564 | %It can be called as: param = read_package_parameters(parameter, param) | ||
9775 | 9565 | ||||
9776 | if nargin<2 | 9566 | if nargin<2 | ||
9777 | %param_struct doesn't need to be passed when building a new package structure | 9567 | %param_struct doesn't need to be passed when building a new package structure | ||
9778 | %it is only needed when appending to regular param structure | 9568 | %it is only needed when appending to regular param structure | ||
9779 | param_struct=struct; | 9569 | param_struct=struct; | ||
9780 | end | 9570 | end | ||
9781 | 9571 | ||||
9782 | param_struct.C_pkg_board = xls_parameter(parameter, 'C_p', true)*1e-9; % C_p in nF (single sided) | 9572 | param_struct.C_pkg_board = xls_parameter(parameter, 'C_p', true)*1e-9; % C_p in nF (single sided) | ||
9783 | param_struct.R_diepad = xls_parameter(parameter, 'R_d', true); % Die source termination resistance (single sided) | 9573 | param_struct.R_diepad = xls_parameter(parameter, 'R_d', true); % Die source termination resistance (single sided) | ||
9784 | 9574 | ||||
9785 | param_struct.a_thru = xls_parameter(parameter, 'A_v', true); % Victim differential peak source output voltage (half of peak to peak) | 9575 | param_struct.a_thru = xls_parameter(parameter, 'A_v', true); % Victim differential peak source output voltage (half of peak to peak) | ||
9786 | param_struct.a_fext = xls_parameter(parameter, 'A_fe', true); % FEXT aggressor differential peak source output voltage (half of peak to peak) | 9576 | param_struct.a_fext = xls_parameter(parameter, 'A_fe', true); % FEXT aggressor differential peak source output voltage (half of peak to peak) | ||
9787 | param_struct.a_next = xls_parameter(parameter, 'A_ne', true); % NEXT aggressor differential peak source output voltage (half of peak to peak) | 9577 | param_struct.a_next = xls_parameter(parameter, 'A_ne', true); % NEXT aggressor differential peak source output voltage (half of peak to peak) | ||
9788 | 9578 | ||||
9789 | param_struct.z_p_tx_cases = xls_parameter(parameter, 'z_p (TX)', true).'; % List of victim transmitter package trace lengths in mm, one per case | 9579 | param_struct.z_p_tx_cases = xls_parameter(parameter, 'z_p (TX)', true).'; % List of victim transmitter package trace lengths in mm, one per case | ||
9790 | [ncases, mele]=size(param_struct.z_p_tx_cases); | 9580 | [ncases, mele]=size(param_struct.z_p_tx_cases); | ||
9791 | if mele ==2 | 9581 | if mele ==2 | ||
9792 | param_struct.flex=2; | 9582 | param_struct.flex=2; | ||
9793 | elseif mele==4 | 9583 | elseif mele==4 | ||
9794 | param_struct.flex=4; | 9584 | param_struct.flex=4; | ||
9795 | elseif mele==1 | 9585 | elseif mele==1 | ||
9796 | param_struct.flex=1; | 9586 | param_struct.flex=1; | ||
9797 | else | 9587 | else | ||
9798 | error('config file syntax error') | 9588 | error('config file syntax error') | ||
9799 | end | 9589 | end | ||
9800 | param_struct.z_p_next_cases = xls_parameter(parameter, 'z_p (NEXT)', true).'; % List of NEXT transmitter package trace lengths in mm, one per case | 9590 | param_struct.z_p_next_cases = xls_parameter(parameter, 'z_p (NEXT)', true).'; % List of NEXT transmitter package trace lengths in mm, one per case | ||
9801 | [ncases1, mele1]=size(param_struct.z_p_next_cases); | 9591 | [ncases1, mele1]=size(param_struct.z_p_next_cases); | ||
9802 | if ncases ~= ncases1 || mele ~= mele1 | 9592 | if ncases ~= ncases1 || mele ~= mele1 | ||
9803 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 9593 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9804 | else | 9594 | else | ||
9805 | end | 9595 | end | ||
9806 | param_struct.z_p_fext_cases = xls_parameter(parameter, 'z_p (FEXT)', true).'; % List of FEXT transmitter package trace lengths in mm, one per case | 9596 | param_struct.z_p_fext_cases = xls_parameter(parameter, 'z_p (FEXT)', true).'; % List of FEXT transmitter package trace lengths in mm, one per case | ||
9807 | [ncases1, mele1]=size(param_struct.z_p_fext_cases); | 9597 | [ncases1, mele1]=size(param_struct.z_p_fext_cases); | ||
9808 | if ncases ~= ncases1 || mele ~= mele1 | 9598 | if ncases ~= ncases1 || mele ~= mele1 | ||
9809 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 9599 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9810 | else | 9600 | else | ||
9811 | end | 9601 | end | ||
9812 | param_struct.z_p_rx_cases = xls_parameter(parameter, 'z_p (RX)', true).'; % List of FEXT receiver package trace lengths in mm, one per case | 9602 | param_struct.z_p_rx_cases = xls_parameter(parameter, 'z_p (RX)', true).'; % List of FEXT receiver package trace lengths in mm, one per case | ||
9813 | [ncases1, mele1]=size(param_struct.z_p_rx_cases); | 9603 | [ncases1, mele1]=size(param_struct.z_p_rx_cases); | ||
9814 | if ncases ~= ncases1 || mele ~= mele1 | 9604 | if ncases ~= ncases1 || mele ~= mele1 | ||
9815 | error('All TX, NEXT, FEXT, Rx cases must agree'); | 9605 | error('All TX, NEXT, FEXT, Rx cases must agree'); | ||
9816 | else | 9606 | else | ||
9817 | end | 9607 | end | ||
9818 | % Table 93A-3 parameters | 9608 | % Table 93A-3 parameters | ||
9819 | param_struct.pkg_gamma0_a1_a2 = xls_parameter(parameter, 'package_tl_gamma0_a1_a2', true, [0 1.734e-3 1.455e-4]); %Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | 9609 | param_struct.pkg_gamma0_a1_a2 = xls_parameter(parameter, 'package_tl_gamma0_a1_a2', true, [0 1.734e-3 1.455e-4]); %Fitting parameters for package model per unit length. First element is in 1/mm and affects DC loss of package model . Second element is in ns1/2/mm and affects loss proportional to sqrt(f). Third element is in ns/mm and affects loss proportional to f. | ||
9820 | param_struct.pkg_tau = xls_parameter(parameter, 'package_tl_tau', true, 6.141e-3); % Package model transmission line delay ns/mm | 9610 | param_struct.pkg_tau = xls_parameter(parameter, 'package_tl_tau', true, 6.141e-3); % Package model transmission line delay ns/mm | ||
9821 | param_struct.pkg_Z_c = xls_parameter(parameter, 'package_Z_c', true, 78.2).';% Package model transmission line characteristic impedance [ Tx , Rx ] | 9611 | param_struct.pkg_Z_c = xls_parameter(parameter, 'package_Z_c', true, 78.2).';% Package model transmission line characteristic impedance [ Tx , Rx ] | ||
9822 | [ ncases1, mele1]=size(param_struct.pkg_Z_c);% | 9612 | [ ncases1, mele1]=size(param_struct.pkg_Z_c);% | ||
9823 | if mele ~= mele1 | 9613 | if mele ~= mele1 | ||
9824 | error('tx rx pairs must have thesame number element entries as TX, NEXT, FEXT, Rx'); | 9614 | error('tx rx pairs must have thesame number element entries as TX, NEXT, FEXT, Rx'); | ||
9825 | else | 9615 | else | ||
9826 | end | 9616 | end | ||
9827 | if mele1==2 % fuill in a array if only a 2 element flex package is specified | 9617 | if mele1==2 % fuill in a array if only a 2 element flex package is specified | ||
9828 | for ii=1:ncases | 9618 | for ii=1:ncases | ||
9829 | param_struct.z_p_fext_casesx(ii,:)= [param_struct.z_p_fext_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9619 | param_struct.z_p_fext_casesx(ii,:)= [param_struct.z_p_fext_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9830 | param_struct.z_p_next_casesx(ii,:)= [param_struct.z_p_next_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9620 | param_struct.z_p_next_casesx(ii,:)= [param_struct.z_p_next_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9831 | param_struct.z_p_tx_casesx(ii,:)= [param_struct.z_p_tx_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9621 | param_struct.z_p_tx_casesx(ii,:)= [param_struct.z_p_tx_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9832 | param_struct.z_p_rx_casesx(ii,:)= [param_struct.z_p_rx_cases(ii,:)' ;[ 0 ; 0 ]]'; | 9622 | param_struct.z_p_rx_casesx(ii,:)= [param_struct.z_p_rx_cases(ii,:)' ;[ 0 ; 0 ]]'; | ||
9833 | end | 9623 | end | ||
9834 | param_struct.z_p_fext_cases = param_struct.z_p_fext_casesx; | 9624 | param_struct.z_p_fext_cases = param_struct.z_p_fext_casesx; | ||
9835 | param_struct.z_p_next_cases= param_struct.z_p_next_casesx; | 9625 | param_struct.z_p_next_cases= param_struct.z_p_next_casesx; | ||
9836 | param_struct.z_p_tx_cases= param_struct.z_p_tx_casesx; | 9626 | param_struct.z_p_tx_cases= param_struct.z_p_tx_casesx; | ||
9837 | param_struct.z_p_rx_cases= param_struct.z_p_rx_casesx; | 9627 | param_struct.z_p_rx_cases= param_struct.z_p_rx_casesx; | ||
9838 | param_struct.pkg_Z_c=[param_struct.pkg_Z_c' ;[ 100 100 ; 100 100 ]]'; | 9628 | param_struct.pkg_Z_c=[param_struct.pkg_Z_c' ;[ 100 100 ; 100 100 ]]'; | ||
9839 | end | 9629 | end | ||
9840 | function [chdata,SDDch,SDDp2p] = read_s4p_files(param, OP, chdata) | 9630 | function [chdata,SDDch,SDDp2p] = read_s4p_files(param, OP, chdata) | ||
9841 | %% extract s-parameter and convert to differential mode | 9631 | %% extract s-parameter and convert to differential mode | ||
9842 | % extract s-parameter data from files and apply tx and rx filters as well as package filters | 9632 | % extract s-parameter data from files and apply tx and rx filters as well as package filters | ||
9843 | num_files=length(chdata); | 9633 | num_files=length(chdata); | ||
9844 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | 9634 | if ~OP.DISPLAY_WINDOW, fprintf('reading file '); end | ||
9845 | for i=1:num_files | 9635 | for i=1:num_files | ||
9846 | if OP.DISPLAY_WINDOW; hwaitbar=waitbar(0);end | 9636 | if OP.DISPLAY_WINDOW; hwaitbar=waitbar(0);end | ||
9847 | progress = i/num_files; | 9637 | progress = i/num_files; | ||
9848 | if OP.DISPLAY_WINDOW | 9638 | if OP.DISPLAY_WINDOW | ||
9849 | [~,a]=fileparts(chdata(i).filename); | 9639 | [~,a]=fileparts(chdata(i).filename); | ||
9850 | waitbar(progress, hwaitbar, ['Processing ' a]); figure(hwaitbar); drawnow; | 9640 | waitbar(progress, hwaitbar, ['Processing ' a]); figure(hwaitbar); drawnow; | ||
9851 | else | 9641 | else | ||
9852 | fprintf('%i ',i); | 9642 | fprintf('%i ',i); | ||
9853 | end | 9643 | end | ||
9854 |
| 9644 |
| ||
9855 | % Skip reading file if it was already read (multiple test cases) | 9645 | % Skip reading file if it was already read (multiple test cases) | ||
9856 | if (~isfield(chdata(i), 'faxis')) || isempty(chdata(i).faxis) | 9646 | if (~isfield(chdata(i), 'faxis')) || isempty(chdata(i).faxis) | ||
9857 | switch lower(chdata(i).ext) | 9647 | switch lower(chdata(i).ext) | ||
9858 | case '.s2p' % for differential return loss | 9648 | case '.s2p' % for differential return loss | ||
9859 | [Sch,SDDch] = read_p2_s2params(chdata(i).filename, 0, 0, param.snpPortsOrder, OP); | 9649 | [Sch,SDDch] = read_p2_s2params(chdata(i).filename, 0, 0, param.snpPortsOrder, OP); | ||
9860 | chdata(i).fmaxi = length(Sch.freq); | 9650 | chdata(i).fmaxi = length(Sch.freq); | ||
9861 | chdata(i).faxis = Sch.freq; | 9651 | chdata(i).faxis = Sch.freq; | ||
9862 | chdata(i).sdd11_raw = transpose(SDDch(1:chdata(i).fmaxi,1,1)); | 9652 | chdata(i).sdd11_raw = transpose(SDDch(1:chdata(i).fmaxi,1,1)); | ||
9863 | SDDp2p(i)=NaN; | 9653 | SDDp2p(i)=NaN; | ||
9864 | chdata(i).sdd11_orig=chdata(i).sdd11_raw; | 9654 | chdata(i).sdd11_orig=chdata(i).sdd11_raw; | ||
9865 | chdata(i).sdd11=chdata(i).sdd11_raw; | 9655 | chdata(i).sdd11=chdata(i).sdd11_raw; | ||
9866 | case '.s4p' | 9656 | case '.s4p' | ||
9867 | if length(param.snpPortsOrder) ~= 4 | 9657 | if length(param.snpPortsOrder) ~= 4 | ||
9868 | error( 'warning:sNpFilePortMismatch', ... | 9658 | error( 'warning:sNpFilePortMismatch', ... | ||
9869 | '\n\t The number of ports defined (%G) does not match the sNp file type (%s)', ... | 9659 | '\n\t The number of ports defined (%G) does not match the sNp file type (%s)', ... | ||
9870 | length(param.snpPortsOrder), ... | 9660 | length(param.snpPortsOrder), ... | ||
9871 | chdata(i).ext ... | 9661 | chdata(i).ext ... | ||
9872 | ); | 9662 | ); | ||
9873 | end | 9663 | end | ||
9874 | % read function returns differnetial mode parameters | 9664 | % read function returns differnetial mode parameters | ||
9875 | if param.package_testcase_i==1 % added to speed up cases e.g. don't read file in twice | 9665 | if param.package_testcase_i==1 % added to speed up cases e.g. don't read file in twice | ||
9876 | [Sch, SDDch, SDCch] = read_p4_s4params(chdata(i).filename, 0, 0, param.snpPortsOrder, OP,param); | 9666 | [Sch, SDDch, SDCch] = read_p4_s4params(chdata(i).filename, 0, 0, param.snpPortsOrder, OP,param); | ||
9877 | % param.holdsdata(i).Sch= Sch; | 9667 | % param.holdsdata(i).Sch= Sch; | ||
9878 | % param.holdsdata(i).SDDch= SDDch; | 9668 | % param.holdsdata(i).SDDch= SDDch; | ||
9879 | % param.holdsdata(i).SDCch= SDCch; | 9669 | % param.holdsdata(i).SDCch= SDCch; | ||
9880 | else | 9670 | else | ||
9881 | error('If this line is reached, there is a logic error'); | 9671 | error('If this line is reached, there is a logic error'); | ||
9882 | % Sch=param.holdsdata(i).Sch; | 9672 | % Sch=param.holdsdata(i).Sch; | ||
9883 | % SDDch=param.holdsdata(i).SDDch; | 9673 | % SDDch=param.holdsdata(i).SDDch; | ||
9884 | % SDCch=param.holdsdata(i).SDCch; | 9674 | % SDCch=param.holdsdata(i).SDCch; | ||
9885 | end | 9675 | end | ||
9886 | chdata(i).fmaxi = length(Sch.freq); | 9676 | chdata(i).fmaxi = length(Sch.freq); | ||
9887 |
| 9677 |
| ||
9888 | 9678 | ||||
9889 | if Sch.freq(chdata(i).fmaxi) < param.fb | 9679 | if Sch.freq(chdata(i).fmaxi) < param.fb | ||
9890 | warning('COM:read_s4p:MaxFreqTooLow', ... | 9680 | warning('COM:read_s4p:MaxFreqTooLow', ... | ||
9891 | 'In %s: the maximum frequency provided, %g, is less than the signaling rate: %g', ... | 9681 | 'In %s: the maximum frequency provided, %g, is less than the signaling rate: %g', ... | ||
9892 | chdata(i).filename, Sch.freq(end), param.fb); | 9682 | chdata(i).filename, Sch.freq(end), param.fb); | ||
9893 | end | 9683 | end | ||
9894 | if Sch.freq(1) > param.max_start_freq | 9684 | if Sch.freq(1) > param.max_start_freq | ||
9895 | warning('COM:read_s4p:StartFreqTooHigh', ... | 9685 | warning('COM:read_s4p:StartFreqTooHigh', ... | ||
9896 | 'In %s: minimum frequency, %.2g GHz, is larger than the recommended %.2g GHz', ... | 9686 | 'In %s: minimum frequency, %.2g GHz, is larger than the recommended %.2g GHz', ... | ||
9897 | chdata(i).filename, Sch.freq(1)/1e9, param.max_start_freq/1e9); | 9687 | chdata(i).filename, Sch.freq(1)/1e9, param.max_start_freq/1e9); | ||
9898 | end | 9688 | end | ||
9899 | freqstep=diff(Sch.freq); | 9689 | freqstep=diff(Sch.freq); | ||
9900 | % ignore frequency differences up to 1 Hz - possible numerical artifacts | 9690 | % ignore frequency differences up to 1 Hz - possible numerical artifacts | ||
9901 | if max(freqstep)-min(freqstep) > 1 | 9691 | if max(freqstep)-min(freqstep) > 1 | ||
9902 | warning('COM:read_s4p:NonUniformFreqSpacing', 'In %s: non-uniform frequency steps: min=%.3g GHz, max=%.3g GHz', ... | 9692 | warning('COM:read_s4p:NonUniformFreqSpacing', 'In %s: non-uniform frequency steps: min=%.3g GHz, max=%.3g GHz', ... | ||
9903 | chdata(i).filename, min(freqstep)/1e9, max(freqstep)/1e9); | 9693 | chdata(i).filename, min(freqstep)/1e9, max(freqstep)/1e9); | ||
9904 | end | 9694 | end | ||
9905 | if max(freqstep) - param.max_freq_step > 1 | 9695 | if max(freqstep) - param.max_freq_step > 1 | ||
9906 | warning('COM:read_s4p:FreqStepTooHigh', 'In %s: frequency step, %.2g GHz, is larger than the recommended %.2g GHz', ... | 9696 | warning('COM:read_s4p:FreqStepTooHigh', 'In %s: frequency step, %.2g GHz, is larger than the recommended %.2g GHz', ... | ||
9907 | chdata(i).filename, max(freqstep)/1e9, param.max_freq_step/1e9); | 9697 | chdata(i).filename, max(freqstep)/1e9, param.max_freq_step/1e9); | ||
9908 | end | 9698 | end | ||
9909 |
| 9699 |
| ||
9910 | chdata(i).faxis = Sch.freq; | 9700 | chdata(i).faxis = Sch.freq; | ||
9911 | chdata(i).sdd12_raw = transpose(SDDch(1:chdata(i).fmaxi,1,2)); | 9701 | chdata(i).sdd12_raw = transpose(SDDch(1:chdata(i).fmaxi,1,2)); | ||
9912 | chdata(i).sdd21_raw = transpose(SDDch(1:chdata(i).fmaxi,2,1)); | 9702 | chdata(i).sdd21_raw = transpose(SDDch(1:chdata(i).fmaxi,2,1)); | ||
9913 | chdata(i).sdd22_raw = transpose(SDDch(1:chdata(i).fmaxi,2,2)); | 9703 | chdata(i).sdd22_raw = transpose(SDDch(1:chdata(i).fmaxi,2,2)); | ||
9914 | chdata(i).sdd11_raw = transpose(SDDch(1:chdata(i).fmaxi,1,1)); | 9704 | chdata(i).sdd11_raw = transpose(SDDch(1:chdata(i).fmaxi,1,1)); | ||
9915 | % mode conversion | 9705 | % mode conversion | ||
9916 | chdata(i).sdc12_raw = transpose(SDCch(1:chdata(i).fmaxi,1,2)); | 9706 | chdata(i).sdc12_raw = transpose(SDCch(1:chdata(i).fmaxi,1,2)); | ||
9917 | chdata(i).sdc21_raw = transpose(SDCch(1:chdata(i).fmaxi,2,1)); | 9707 | chdata(i).sdc21_raw = transpose(SDCch(1:chdata(i).fmaxi,2,1)); | ||
9918 | chdata(i).sdc22_raw = transpose(SDCch(1:chdata(i).fmaxi,2,2)); | 9708 | chdata(i).sdc22_raw = transpose(SDCch(1:chdata(i).fmaxi,2,2)); | ||
9919 | chdata(i).sdc11_raw = transpose(SDCch(1:chdata(i).fmaxi,1,1)); | 9709 | chdata(i).sdc11_raw = transpose(SDCch(1:chdata(i).fmaxi,1,1)); | ||
9920 | %save original and add board (if required) | 9710 | %save original and add board (if required) | ||
9921 | chdata(i).sdd11_orig=chdata(i).sdd11_raw; | 9711 | chdata(i).sdd11_orig=chdata(i).sdd11_raw; | ||
9922 | chdata(i).sdd22_orig=chdata(i).sdd22_raw; | 9712 | chdata(i).sdd22_orig=chdata(i).sdd22_raw; | ||
9923 | chdata(i).sdd12_orig=chdata(i).sdd12_raw; | 9713 | chdata(i).sdd12_orig=chdata(i).sdd12_raw; | ||
9924 | chdata(i).sdd21_orig=chdata(i).sdd21_raw; | 9714 | chdata(i).sdd21_orig=chdata(i).sdd21_raw; | ||
9925 | if OP.include_pcb | 9715 | if OP.include_pcb | ||
9926 | % add boards to sdd | 9716 | % add boards to sdd | ||
9927 | [chdata(i).sdd11_raw, chdata(i).sdd12_raw, chdata(i).sdd21_raw, chdata(i).sdd22_raw] = add_brd(chdata(i), param, OP); | 9717 | [chdata(i).sdd11_raw, chdata(i).sdd12_raw, chdata(i).sdd21_raw, chdata(i).sdd22_raw] = add_brd(chdata(i), param, OP); | ||
9928 |
| 9718 |
| ||
9929 | end | 9719 | end | ||
9930 | %save final return loss (after the boards were included) | 9720 | %save final return loss (after the boards were included) | ||
9931 | chdata(i).sdd11=chdata(i).sdd11_raw; | 9721 | chdata(i).sdd11=chdata(i).sdd11_raw; | ||
9932 | chdata(i).sdd22=chdata(i).sdd22_raw; | 9722 | chdata(i).sdd22=chdata(i).sdd22_raw; | ||
9933 | otherwise | 9723 | otherwise | ||
9934 | error('Extension "%s" in file "%s" is not supported',chdata(i).ext,chdata(i).filename); | 9724 | error('Extension "%s" in file "%s" is not supported',chdata(i).ext,chdata(i).filename); | ||
9935 | end | 9725 | end | ||
9936 |
| 9726 |
| ||
9937 | %Crosstalk frequency axis must be the same as Thru | 9727 | %Crosstalk frequency axis must be the same as Thru | ||
9938 | if i>1 | 9728 | if i>1 | ||
9939 | %error on length difference | 9729 | %error on length difference | ||
9940 | if length(chdata(i).faxis)~=length(chdata(1).faxis) | 9730 | if length(chdata(i).faxis)~=length(chdata(1).faxis) | ||
9941 | error('Crosstalk file "%s" has different number of frequency points',chdata(i).filename); | 9731 | error('Crosstalk file "%s" has different number of frequency points',chdata(i).filename); | ||
9942 | end | 9732 | end | ||
9943 | %error if any value > 1Hz (don't want to check for exact | 9733 | %error if any value > 1Hz (don't want to check for exact | ||
9944 | %equality in case of floating point error) | 9734 | %equality in case of floating point error) | ||
9945 | Fdiff=abs(chdata(i).faxis-chdata(1).faxis); | 9735 | Fdiff=abs(chdata(i).faxis-chdata(1).faxis); | ||
9946 | if max(Fdiff)>1 | 9736 | if max(Fdiff)>1 | ||
9947 | error('Crosstalk file "%s" has a different frequency axis',chdata(i).filename); | 9737 | error('Crosstalk file "%s" has a different frequency axis',chdata(i).filename); | ||
9948 | end | 9738 | end | ||
9949 | end | 9739 | end | ||
9950 | else | 9740 | else | ||
9951 | SDDch(:,1,2)=chdata(i).sdd12_raw; | 9741 | SDDch(:,1,2)=chdata(i).sdd12_raw; | ||
9952 | SDDch(:,2,1)=chdata(i).sdd21_raw; | 9742 | SDDch(:,2,1)=chdata(i).sdd21_raw; | ||
9953 | SDDch(:,1,1)=chdata(i).sdd11_raw; | 9743 | SDDch(:,1,1)=chdata(i).sdd11_raw; | ||
9954 | SDDch(:,2,2)=chdata(i).sdd22_raw; | 9744 | SDDch(:,2,2)=chdata(i).sdd22_raw; | ||
9955 | end | 9745 | end | ||
9956 | chdata(i).sigma_ACCM_at_tp0=0; | 9746 | chdata(i).sigma_ACCM_at_tp0=0; | ||
9957 | if ~param.FLAG.S2P | 9747 | if ~param.FLAG.S2P | ||
9958 | if OP.INC_PACKAGE ~= 0 || (OP.RX_CALIBRATION == 1 && i==1) | 9748 | if OP.INC_PACKAGE ~= 0 || (OP.RX_CALIBRATION == 1 && i==1) | ||
9959 | if (OP.RX_CALIBRATION == 1 && i==2) | 9749 | if (OP.RX_CALIBRATION == 1 && i==2) | ||
9960 | chdata(i).sdd21=chdata(i).sdd21_raw; | 9750 | chdata(i).sdd21=chdata(i).sdd21_raw; | ||
9961 | else | 9751 | else | ||
9962 | %updated package construction with single function for both DD and DC | 9752 | %updated package construction with single function for both DD and DC | ||
9963 | [chdata(i).sdd21p,SDDp2p(i)]= s21_pkg(chdata(i), param, OP, i); | 9753 | [chdata(i).sdd21p,SDDp2p(i)]= s21_pkg(chdata(i), param, OP, i); | ||
9964 | [chdata(i).sdd21p_nodie]= s21_pkg(chdata(i), param, OP, i, 'dd', 0); | 9754 | [chdata(i).sdd21p_nodie]= s21_pkg(chdata(i), param, OP, i, 'dd', 0); | ||
9965 | chdata(i).sdd21=chdata(i).sdd21p; | 9755 | chdata(i).sdd21=chdata(i).sdd21p; | ||
9966 | if 1 % for AC CM noise inclusion | 9756 | if 1 % for AC CM noise inclusion | ||
9967 | [chdata(i).sdc21p,SDCp2p(i),chdata(i).sigma_ACCM_at_tp0]= s21_pkg(chdata(i), param, OP, i,'dc'); | 9757 | [chdata(i).sdc21p,SDCp2p(i),chdata(i).sigma_ACCM_at_tp0]= s21_pkg(chdata(i), param, OP, i,'dc'); | ||
9968 | chdata(i).sdc21=chdata(i).sdc21p; | 9758 | chdata(i).sdc21=chdata(i).sdc21p; | ||
9969 | end | 9759 | end | ||
9970 | end | 9760 | end | ||
9971 | else | 9761 | else | ||
9972 | chdata(i).sdd21=chdata(i).sdd21_raw; | 9762 | chdata(i).sdd21=chdata(i).sdd21_raw; | ||
9973 | end | 9763 | end | ||
9974 | chdata(i).sdd21f=chdata(i).sdd21_orig; % used for FD analysis i.e. not filtered (RIM 9/24/2021 without boards or packages) | 9764 | chdata(i).sdd21f=chdata(i).sdd21_orig; % used for FD analysis i.e. not filtered (RIM 9/24/2021 without boards or packages) | ||
9975 | end | 9765 | end | ||
9976 | end | 9766 | end | ||
9977 | if ~OP.DISPLAY_WINDOW, fprintf('\n'); end | 9767 | if ~OP.DISPLAY_WINDOW, fprintf('\n'); end | ||
9978 | 9768 | ||||
9979 | function result = readdataSnPx(filename, nport) | 9769 | function result = readdataSnPx(filename, nport) | ||
9980 | %function [freq, cs] = readdataSnPx(filename, nport) | 9770 | %function [freq, cs] = readdataSnPx(filename, nport) | ||
9981 | % [freq, cs] = readdataSnP(filename, nport, format, nheader) | 9771 | % [freq, cs] = readdataSnP(filename, nport, format, nheader) | ||
9982 | % | 9772 | % | ||
9983 | % Read Touchstone file with frequencies in units of Hertz | 9773 | % Read Touchstone file with frequencies in units of Hertz | ||
9984 | % | 9774 | % | ||
9985 | % Input: | 9775 | % Input: | ||
9986 | % ====== | 9776 | % ====== | ||
9987 | % filename: Name of the Touchstone/SnP file | 9777 | % filename: Name of the Touchstone/SnP file | ||
9988 | % nport: Number of ports | 9778 | % nport: Number of ports | ||
9989 | % format: 'RI' for real/imag, 'MA' for mag/angle (check option line in the | 9779 | % format: 'RI' for real/imag, 'MA' for mag/angle (check option line in the | ||
9990 | % Touchstone file) | 9780 | % Touchstone file) | ||
9991 | % nheader: Number of header lines (comment lines plus option line in the | 9781 | % nheader: Number of header lines (comment lines plus option line in the | ||
9992 | % Touchstone file) | 9782 | % Touchstone file) | ||
9993 | % | 9783 | % | ||
9994 | % Output: | 9784 | % Output: | ||
9995 | % ======= | 9785 | % ======= | ||
9996 | % freq: Vector of frequencies [Hz] | 9786 | % freq: Vector of frequencies [Hz] | ||
9997 | % cs: 3-D array of complex-valued S parameters where cs(i,j,k) is S(i,j) | 9787 | % cs: 3-D array of complex-valued S parameters where cs(i,j,k) is S(i,j) | ||
9998 | % at frequency freq(k) | 9788 | % at frequency freq(k) | ||
9999 | % | 9789 | % | ||
10000 | % Note: If frequency unit is not Hertz (but GHz, MHz etc.) simply scale | 9790 | % Note: If frequency unit is not Hertz (but GHz, MHz etc.) simply scale | ||
10001 | % frequencies appropriately after reading the data. | 9791 | % frequencies appropriately after reading the data. | ||
10002 | % | 9792 | % | ||
10003 | % Ref.: Touchstone(R) File Format Specification, Rev.1.1, | 9793 | % Ref.: Touchstone(R) File Format Specification, Rev.1.1, | ||
10004 | % EIA/IBIS Open Forum, 2002. | 9794 | % EIA/IBIS Open Forum, 2002. | ||
10005 | % | 9795 | % | ||
10006 | % Written by Henning Braunisch, September 2004. | 9796 | % Written by Henning Braunisch, September 2004. | ||
10007 | % Updated by Steven Krooswyk, April 2006. | 9797 | % Updated by Steven Krooswyk, April 2006. | ||
10008 | 9798 | ||||
10009 | 9799 | ||||
10010 | fid = fopen(filename, 'r'); | 9800 | fid = fopen(filename, 'r'); | ||
10011 | 9801 | ||||
10012 | 9802 | ||||
10013 | % Skip header lines | 9803 | % Skip header lines | ||
10014 | str = ' '; | 9804 | str = ' '; | ||
10015 | n = 0; | 9805 | n = 0; | ||
10016 | while ~strcmp(str(1),'#') | 9806 | while ~strcmp(str(1),'#') | ||
10017 | str = fgetl(fid); | 9807 | str = fgetl(fid); | ||
10018 | if isempty(str) | 9808 | if isempty(str) | ||
10019 | str=' ' ; | 9809 | str=' ' ; | ||
10020 | if n > 1000 | 9810 | if n > 1000 | ||
10021 | display('error: could not find config line (#)') | 9811 | display('error: could not find config line (#)') | ||
10022 | break | 9812 | break | ||
10023 | end | 9813 | end | ||
10024 | end | 9814 | end | ||
10025 | n = n + 1; | 9815 | n = n + 1; | ||
10026 | end | 9816 | end | ||
10027 | 9817 | ||||
10028 | % parse configuration line | 9818 | % parse configuration line | ||
10029 | A=sscanf(str,'%1s %2s %1s %2s %1s %2s',[1,inf]); | 9819 | A=sscanf(str,'%1s %2s %1s %2s %1s %2s',[1,inf]); | ||
10030 | p = find(A=='S'); %position of 'S' | 9820 | p = find(A=='S'); %position of 'S' | ||
10031 | units = lower(A(2:p-1)); %units before 'S' | 9821 | units = lower(A(2:p-1)); %units before 'S' | ||
10032 | format = A(p+1:p+2); %format after 'S' | 9822 | format = A(p+1:p+2); %format after 'S' | ||
10033 | 9823 | ||||
10034 | % skip any more header lines | 9824 | % skip any more header lines | ||
10035 | %while ~str | 9825 | %while ~str | ||
10036 | 9826 | ||||
10037 | nk = 0; % frequency counter | 9827 | nk = 0; % frequency counter | ||
10038 | while 1 | 9828 | while 1 | ||
10039 |
| 9829 |
| ||
10040 | [temp, count] = fscanf(fid, '%f', 1); | 9830 | [temp, count] = fscanf(fid, '%f', 1); | ||
10041 | if count == 0 | 9831 | if count == 0 | ||
10042 | temp2 = fscanf(fid, '%s', 1); | 9832 | temp2 = fscanf(fid, '%s', 1); | ||
10043 | if ~isempty(temp2), fgetl(fid); continue, end; | 9833 | if ~isempty(temp2), fgetl(fid); continue, end; | ||
10044 | break | 9834 | break | ||
10045 | end | 9835 | end | ||
10046 | nk = nk+1; freq(1,nk) = temp; %#ok<AGROW> | 9836 | nk = nk+1; freq(1,nk) = temp; %#ok<AGROW> | ||
10047 | for ni = 1:nport | 9837 | for ni = 1:nport | ||
10048 | for nj = 1:nport | 9838 | for nj = 1:nport | ||
10049 | switch lower(format) | 9839 | switch lower(format) | ||
10050 | case 'ma' | 9840 | case 'ma' | ||
10051 | mag = fscanf(fid, '%f', 1); ang = fscanf(fid, '%f', 1); | 9841 | mag = fscanf(fid, '%f', 1); ang = fscanf(fid, '%f', 1); | ||
10052 | cs(ni,nj,nk) = mag * exp(1i*ang*pi/180); %#ok<AGROW> | 9842 | cs(ni,nj,nk) = mag * exp(1i*ang*pi/180); %#ok<AGROW> | ||
10053 | case 'ri' | 9843 | case 'ri' | ||
10054 | re = fscanf(fid, '%f', 1); im = fscanf(fid, '%f', 1); | 9844 | re = fscanf(fid, '%f', 1); im = fscanf(fid, '%f', 1); | ||
10055 | cs(ni,nj,nk) = complex(re, im); %#ok<AGROW> | 9845 | cs(ni,nj,nk) = complex(re, im); %#ok<AGROW> | ||
10056 | case 'db' | 9846 | case 'db' | ||
10057 | db = fscanf(fid, '%f', 1); ang = fscanf(fid, '%f', 1); | 9847 | db = fscanf(fid, '%f', 1); ang = fscanf(fid, '%f', 1); | ||
10058 | M = 10^(db/20); | 9848 | M = 10^(db/20); | ||
10059 | %re = M*cos(ang); | 9849 | %re = M*cos(ang); | ||
10060 | %im = M*sin(ang); | 9850 | %im = M*sin(ang); | ||
10061 | re = M*cos(ang * pi / 180); | 9851 | re = M*cos(ang * pi / 180); | ||
10062 | im = M*sin(ang * pi / 180); | 9852 | im = M*sin(ang * pi / 180); | ||
10063 | cs(ni,nj,nk) = complex(re, im); %#ok<AGROW> | 9853 | cs(ni,nj,nk) = complex(re, im); %#ok<AGROW> | ||
10064 | otherwise | 9854 | otherwise | ||
10065 | error('readdataSnP: Unknown data format'); | 9855 | error('readdataSnP: Unknown data format'); | ||
10066 | end | 9856 | end | ||
10067 | end | 9857 | end | ||
10068 | end | 9858 | end | ||
10069 | end | 9859 | end | ||
10070 | 9860 | ||||
10071 | fclose(fid); | 9861 | fclose(fid); | ||
10072 | 9862 | ||||
10073 | % If 2-port then swap S_12 and S_21 per Touchstone spec | 9863 | % If 2-port then swap S_12 and S_21 per Touchstone spec | ||
10074 | if nport == 2 | 9864 | if nport == 2 | ||
10075 | temp = cs(2,1,:); | 9865 | temp = cs(2,1,:); | ||
10076 | cs(2,1,:) = cs(1,2,:); | 9866 | cs(2,1,:) = cs(1,2,:); | ||
10077 | cs(1,2,:) = temp; | 9867 | cs(1,2,:) = temp; | ||
10078 | end | 9868 | end | ||
10079 | 9869 | ||||
10080 | % Update freq units to Hz | 9870 | % Update freq units to Hz | ||
10081 | switch lower(units) | 9871 | switch lower(units) | ||
10082 | case 'hz' | 9872 | case 'hz' | ||
10083 |
| 9873 |
| ||
10084 | case 'khz' | 9874 | case 'khz' | ||
10085 | freq=freq.*1e3; | 9875 | freq=freq.*1e3; | ||
10086 | case 'mhz' | 9876 | case 'mhz' | ||
10087 | freq=freq.*1e6; | 9877 | freq=freq.*1e6; | ||
10088 | case 'ghz' | 9878 | case 'ghz' | ||
10089 | freq=freq.*1e9; | 9879 | freq=freq.*1e9; | ||
10090 | end | 9880 | end | ||
10091 | 9881 | ||||
10092 | % passivity check | 9882 | % passivity check | ||
10093 | result.freq = freq; | 9883 | result.freq = freq; | ||
10094 | result.cs = cs; | 9884 | result.cs = cs; | ||
10095 | 9885 | ||||
10096 | function recolor_plots(ax) | 9886 | function recolor_plots(ax) | ||
10097 | 9887 | ||||
10098 | if ~verLessThan('matlab', '8.4.0') | 9888 | if ~verLessThan('matlab', '8.4.0') | ||
10099 | return | 9889 | return | ||
10100 | end | 9890 | end | ||
10101 | colors='brgcmk'; | 9891 | colors='brgcmk'; | ||
10102 | ch=flipud(get(ax, 'children')); | 9892 | ch=flipud(get(ax, 'children')); | ||
10103 | 9893 | ||||
10104 | for k=1:length(ch) | 9894 | for k=1:length(ch) | ||
10105 | set(ch(k), 'Color', colors(mod(k-1, length(colors))+1)); | 9895 | set(ch(k), 'Color', colors(mod(k-1, length(colors))+1)); | ||
10106 | set(ch(k), 'LineWidth', 2*floor((k-1)/length(colors))+1); | 9896 | set(ch(k), 'LineWidth', 2*floor((k-1)/length(colors))+1); | ||
10107 | end | 9897 | end | ||
10108 | legend (ax, 'off'); | 9898 | legend (ax, 'off'); | ||
10109 | warning('off', 'MATLAB:legend:PlotEmpty'); | 9899 | warning('off', 'MATLAB:legend:PlotEmpty'); | ||
10110 | set(legend (ax, 'show'), 'interp', 'none'); | 9900 | set(legend (ax, 'show'), 'interp', 'none'); | ||
10111 | 9901 | ||||
10112 | function result = reduce(var1) | 9902 | function result = reduce(var1) | ||
10113 | % --- Reduce 1x1xn array to 1xn (aka squeeze) | 9903 | % --- Reduce 1x1xn array to 1xn (aka squeeze) | ||
10114 | out = zeros(1,length(var1)); | 9904 | out = zeros(1,length(var1)); | ||
10115 | out(1,:) = var1(1,1,:); | 9905 | out(1,:) = var1(1,1,:); | ||
10116 | result=out; | 9906 | result=out; | ||
10117 | 9907 | ||||
10118 | function [s21p,SCH,sigma_ACCM_at_tp0] = s21_pkg(chdata, param, OP, channel_number,mode,include_die) | 9908 | function [s21p,SCH,sigma_ACCM_at_tp0] = s21_pkg(chdata, param, OP, channel_number,mode,include_die) | ||
10119 | % concatenates package reflections with s21,s11,and s22 with spec return loss (gammas) | 9909 | % concatenates package reflections with s21,s11,and s22 with spec return loss (gammas) | ||
10120 | % faxis is the frequency array | 9910 | % faxis is the frequency array | ||
10121 | % s21, s11, s22 are the corresponding array of differential parameters | 9911 | % s21, s11, s22 are the corresponding array of differential parameters | ||
10122 | % s21p includes the VFT and Tx filter if include_die=1 | 9912 | % s21p includes the VFT and Tx filter if include_die=1 | ||
10123 | if nargin<6 | 9913 | if nargin<6 | ||
10124 | include_die=1; | 9914 | include_die=1; | ||
10125 | end | 9915 | end | ||
10126 | if nargin<5 | 9916 | if nargin<5 | ||
10127 | mode='dd'; | 9917 | mode='dd'; | ||
10128 | end | 9918 | end | ||
10129 | 9919 | ||||
10130 | s21=chdata.(['s' mode '21_raw']); | 9920 | s21=chdata.(['s' mode '21_raw']); | ||
10131 | s12=chdata.(['s' mode '12_raw']); | 9921 | s12=chdata.(['s' mode '12_raw']); | ||
10132 | s11=chdata.(['s' mode '11_raw']); | 9922 | s11=chdata.(['s' mode '11_raw']); | ||
10133 | s22=chdata.(['s' mode '22_raw']); | 9923 | s22=chdata.(['s' mode '22_raw']); | ||
10134 | faxis=chdata.faxis; | 9924 | faxis=chdata.faxis; | ||
10135 | channel_type=chdata.type; | 9925 | channel_type=chdata.type; | ||
10136 | 9926 | ||||
10137 | if strcmpi(mode,'dd') | 9927 | if strcmpi(mode,'dd') | ||
10138 | s11=s11*param.kappa1; | 9928 | s11=s11*param.kappa1; | ||
10139 | s22=s22*param.kappa2; | 9929 | s22=s22*param.kappa2; | ||
10140 | end | 9930 | end | ||
10141 | 9931 | ||||
10142 | 9932 | ||||
10143 | Z0=param.Z0; | 9933 | Z0=param.Z0; | ||
10144 | %sigma_ACCM_at_tp0 is only used when mode=DC | 9934 | %sigma_ACCM_at_tp0 is only used when mode=DC | ||
10145 | sigma_ACCM_at_tp0=0; | 9935 | sigma_ACCM_at_tp0=0; | ||
10146 | 9936 | ||||
10147 | % The following three parameters have possibly different valuesF for TX and | 9937 | % The following three parameters have possibly different valuesF for TX and | ||
10148 | % RX (so can be 2-element vectors). | 9938 | % RX (so can be 2-element vectors). | ||
10149 | R_diepad = param.R_diepad; | 9939 | R_diepad = param.R_diepad; | ||
10150 | 9940 | ||||
10151 | %Make TX Package | 9941 | %Make TX Package | ||
10152 | [ s11out, s12out, s21out, s22out]=make_full_pkg('TX',faxis,param,channel_type,mode,include_die); | 9942 | [ s11out, s12out, s21out, s22out]=make_full_pkg('TX',faxis,param,channel_type,mode,include_die); | ||
10153 | 9943 | ||||
10154 | %Make RX Package | 9944 | %Make RX Package | ||
10155 | %Important: RX pkg doesn't change based on mode being dd or dc. So 'dd' is always passed | 9945 | %Important: RX pkg doesn't change based on mode being dd or dc. So 'dd' is always passed | ||
10156 | [ s11in, s12in, s21in, s22in]=make_full_pkg('RX',faxis,param,channel_type,'dd',include_die); | 9946 | [ s11in, s12in, s21in, s22in]=make_full_pkg('RX',faxis,param,channel_type,'dd',include_die); | ||
10157 | 9947 | ||||
10158 | 9948 | ||||
10159 | % p(1 ,1, :)=s11in; | 9949 | % p(1 ,1, :)=s11in; | ||
10160 | % p(2 ,2, :)=s22in; | 9950 | % p(2 ,2, :)=s22in; | ||
10161 | % p(1 ,2, :)=s12in; | 9951 | % p(1 ,2, :)=s12in; | ||
10162 | % p(2 ,1, :)=s21in; | 9952 | % p(2 ,1, :)=s21in; | ||
10163 | % | 9953 | % | ||
10164 | % S=sparameters(p,faxis); | 9954 | % S=sparameters(p,faxis); | ||
10165 | % rfwrite(S,'temp.s4p'); | 9955 | % rfwrite(S,'temp.s4p'); | ||
10166 | 9956 | ||||
10167 | if strcmpi(mode,'dc') | 9957 | if strcmpi(mode,'dc') | ||
10168 | RTX=R_diepad(param.Tx_rd_sel)/2; | 9958 | RTX=R_diepad(param.Tx_rd_sel)/2; | ||
10169 | RRX=R_diepad(param.Rx_rd_sel)/2; | 9959 | RRX=R_diepad(param.Rx_rd_sel)/2; | ||
10170 | Z0gamma=Z0/2; | 9960 | Z0gamma=Z0/2; | ||
10171 | else | 9961 | else | ||
10172 | RTX=R_diepad(param.Tx_rd_sel); | 9962 | RTX=R_diepad(param.Tx_rd_sel); | ||
10173 | RRX=R_diepad(param.Rx_rd_sel); | 9963 | RRX=R_diepad(param.Rx_rd_sel); | ||
10174 | Z0gamma=Z0; | 9964 | Z0gamma=Z0; | ||
10175 | end | 9965 | end | ||
10176 | if OP.IDEAL_TX_TERM || (OP.RX_CALIBRATION == 1 && channel_number == 2) || OP.include_pcb == 2 | 9966 | if OP.IDEAL_TX_TERM || (OP.RX_CALIBRATION == 1 && channel_number == 2) || OP.include_pcb == 2 | ||
10177 | gamma_tx=0; | 9967 | gamma_tx=0; | ||
10178 | else | 9968 | else | ||
10179 | gamma_tx=(RTX-Z0gamma)/(RTX+Z0gamma);% equation 93A-17 | 9969 | gamma_tx=(RTX-Z0gamma)/(RTX+Z0gamma);% equation 93A-17 | ||
10180 | end | 9970 | end | ||
10181 | if OP.IDEAL_RX_TERM | 9971 | if OP.IDEAL_RX_TERM | ||
10182 | gamma_rx=0; | 9972 | gamma_rx=0; | ||
10183 | else | 9973 | else | ||
10184 | gamma_rx=(RRX-Z0gamma)/(RRX+Z0gamma);% equation 93A-17 | 9974 | gamma_rx=(RRX-Z0gamma)/(RRX+Z0gamma);% equation 93A-17 | ||
10185 | end | 9975 | end | ||
10186 | 9976 | ||||
10187 | if OP.INC_PACKAGE==0 | 9977 | if OP.INC_PACKAGE==0 | ||
10188 | s21p= s21; | 9978 | s21p= s21; | ||
10189 | warning('do not use INC_PACKAGE = 0. Instead use package parameters)'); | 9979 | warning('do not use INC_PACKAGE = 0. Instead use package parameters)'); | ||
10190 | else | 9980 | else | ||
10191 | if OP.RX_CALIBRATION == 1 && channel_number == 2 | 9981 | if OP.RX_CALIBRATION == 1 && channel_number == 2 | ||
10192 | % for calibration do not include the transmitter package | 9982 | % for calibration do not include the transmitter package | ||
10193 | [s11out_rx, s12out_rx, s21out_rx, s22out_rx ] = combines4p( s11, s12, s21, s22, s22out, s12out, s21out, s11out ); %#ok<ASGLU> % s22 is ball side of package | 9983 | [s11out_rx, s12out_rx, s21out_rx, s22out_rx ] = combines4p( s11, s12, s21, s22, s22out, s12out, s21out, s11out ); %#ok<ASGLU> % s22 is ball side of package | ||
10194 | SCH.Frequencies=faxis; | 9984 | SCH.Frequencies=faxis; | ||
10195 | SCH.Parameters(1,1,:)=s11out_rx; | 9985 | SCH.Parameters(1,1,:)=s11out_rx; | ||
10196 | SCH.Parameters(2,2,:)=s22out_rx; | 9986 | SCH.Parameters(2,2,:)=s22out_rx; | ||
10197 | SCH.Parameters(1,2,:)=s12out_rx; | 9987 | SCH.Parameters(1,2,:)=s12out_rx; | ||
10198 | SCH.Parameters(2,1,:)=s21out_rx; | 9988 | SCH.Parameters(2,1,:)=s21out_rx; | ||
10199 | SCH.NumPorts=2; | 9989 | SCH.NumPorts=2; | ||
10200 | SCH.Impedance=100; | 9990 | SCH.Impedance=100; | ||
10201 | %% Equation 93A-18 | 9991 | %% Equation 93A-18 | ||
10202 | if include_die | 9992 | if include_die | ||
10203 | s21p= s21out_rx.*(1-gamma_tx).*(1+gamma_rx)./(1.- s11out_rx.*gamma_tx - s22out_rx.*gamma_rx -s21out_rx.^2.*gamma_tx.*gamma_rx +s11out_rx.*s22out_rx.*gamma_tx.*gamma_rx); | 9993 | s21p= s21out_rx.*(1-gamma_tx).*(1+gamma_rx)./(1.- s11out_rx.*gamma_tx - s22out_rx.*gamma_rx -s21out_rx.^2.*gamma_tx.*gamma_rx +s11out_rx.*s22out_rx.*gamma_tx.*gamma_rx); | ||
10204 | else | 9994 | else | ||
10205 | s21p=s21out_rx; % if no die we do not want a VTF | 9995 | s21p=s21out_rx; % if no die we do not want a VTF | ||
10206 | end | 9996 | end | ||
10207 | else | 9997 | else | ||
10208 | %% Equations 93A-4 to 93A-7 | 9998 | %% Equations 93A-4 to 93A-7 | ||
10209 | if ~OP.IDEAL_TX_TERM | 9999 | if ~OP.IDEAL_TX_TERM | ||
10210 | [s11, s12, s21, s22] = combines4p( s11out, s12out, s21out, s22out, s11, s12, s21, s22 ); %#ok<ASGLU> | 10000 | [s11, s12, s21, s22] = combines4p( s11out, s12out, s21out, s22out, s11, s12, s21, s22 ); %#ok<ASGLU> | ||
10211 | end | 10001 | end | ||
10212 | H_t=ones(1,length(faxis)); % .3bj compatibility | 10002 | H_t=ones(1,length(faxis)); % .3bj compatibility | ||
10213 | if OP.IDEAL_TX_TERM || OP.T_r_filter_type == 1 | 10003 | if OP.IDEAL_TX_TERM || OP.T_r_filter_type == 1 | ||
10214 | % for RITT testing with good termination as in some instruments | 10004 | % for RITT testing with good termination as in some instruments | ||
10215 | % and tx filter when required | 10005 | % and tx filter when required | ||
10216 | if OP.T_r_filter_type==0 | 10006 | if OP.T_r_filter_type==0 | ||
10217 | H_t = exp(-(pi*faxis/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | 10007 | H_t = exp(-(pi*faxis/1e9*OP.transmitter_transition_time/1.6832).^2); %% Equation 93A-46 %% | ||
10218 | else | 10008 | else | ||
10219 | tr=OP.transmitter_transition_time; | 10009 | tr=OP.transmitter_transition_time; | ||
10220 | f9=faxis/1e9; | 10010 | f9=faxis/1e9; | ||
10221 | if OP.T_r_meas_point == 1 | 10011 | if OP.T_r_meas_point == 1 | ||
10222 | k=1.9466+7.12*sqrt(1-6.51e-3/tr); | 10012 | k=1.9466+7.12*sqrt(1-6.51e-3/tr); | ||
10223 | H_t=105./(f9.^4*(k*tr)^4 - f9.^3*(k*tr)^3*10i - 45*f9.^2*(k*tr)^2 + f9*(k*tr)*105i + 105); | 10013 | H_t=105./(f9.^4*(k*tr)^4 - f9.^3*(k*tr)^3*10i - 45*f9.^2*(k*tr)^2 + f9*(k*tr)*105i + 105); | ||
10224 | else | 10014 | else | ||
10225 | H_t = exp( -2*(pi*f9*tr/1.6832).^2 ).*exp(-1j*2*pi*f9*tr*3); | 10015 | H_t = exp( -2*(pi*f9*tr/1.6832).^2 ).*exp(-1j*2*pi*f9*tr*3); | ||
10226 | end | 10016 | end | ||
10227 |
| 10017 |
| ||
10228 | end | 10018 | end | ||
10229 | end | 10019 | end | ||
10230 | if strcmpi(mode,'dc') | 10020 | if strcmpi(mode,'dc') | ||
10231 | % H_t=ones(1,length(faxis)); % not sure if we need a H_t or not. Is the CM noise correlated to the edge rate? | 10021 | % H_t=ones(1,length(faxis)); % not sure if we need a H_t or not. Is the CM noise correlated to the edge rate? | ||
10232 | end | 10022 | end | ||
10233 | if ~OP.IDEAL_RX_TERM | 10023 | if ~OP.IDEAL_RX_TERM | ||
10234 | [s11, s12, s21, s22] = combines4p( s11, s12, s21, s22, s22in, s21in, s12in, s11in ); %#ok<ASGLU> % s22 is ball side of package | 10024 | [s11, s12, s21, s22] = combines4p( s11, s12, s21, s22, s22in, s21in, s12in, s11in ); %#ok<ASGLU> % s22 is ball side of package | ||
10235 | else | 10025 | else | ||
10236 | warning('do not use IDEAL_RX_TERM. Instead hard code package and TR parameters') | 10026 | warning('do not use IDEAL_RX_TERM. Instead hard code package and TR parameters') | ||
10237 | end | 10027 | end | ||
10238 | %% Equation 93A-18 and part of 93A-1: Ht fix in V290 identified by Bill Kirkland and Ed Frlan ( s21^2 changed to s12*s21 ) | 10028 | %% Equation 93A-18 and part of 93A-1: Ht fix in V290 identified by Bill Kirkland and Ed Frlan ( s21^2 changed to s12*s21 ) | ||
10239 | if include_die | 10029 | if include_die | ||
10240 | s21p= H_t.*s21.*(1-gamma_tx).*(1+gamma_rx)./(1.- s11.*gamma_tx - s22.*gamma_rx -s21.*s12.*gamma_tx.*gamma_rx +s11.*s22.*gamma_tx.*gamma_rx); | 10030 | s21p= H_t.*s21.*(1-gamma_tx).*(1+gamma_rx)./(1.- s11.*gamma_tx - s22.*gamma_rx -s21.*s12.*gamma_tx.*gamma_rx +s11.*s22.*gamma_tx.*gamma_rx); | ||
10241 | else | 10031 | else | ||
10242 | s21p=s21; % if no die we do not want a VTF | 10032 | s21p=s21; % if no die we do not want a VTF | ||
10243 | end | 10033 | end | ||
10244 | end | 10034 | end | ||
10245 |
| 10035 |
| ||
10246 | if strcmpi(mode,'dc') | 10036 | if strcmpi(mode,'dc') | ||
10247 | % compute AC_CM_RMS at tp0 | 10037 | % compute AC_CM_RMS at tp0 | ||
10248 | OP.TX_BesselThomson=1; %AC CM is measured in scopes with at BT filter | 10038 | OP.TX_BesselThomson=1; %AC CM is measured in scopes with at BT filter | ||
10249 | H_bt=Bessel_Thomson_Filter(param,faxis,OP.TX_BesselThomson); | 10039 | H_bt=Bessel_Thomson_Filter(param,faxis,OP.TX_BesselThomson); | ||
10250 | if channel_number == 1 | 10040 | if channel_number == 1 | ||
10251 | f_int= faxis( faxis<=param.ACCM_MAX_Freq ); | 10041 | f_int= faxis( faxis<=param.ACCM_MAX_Freq ); | ||
10252 | H_cc= s21out.*(1-gamma_tx)./(1.- s11out.*gamma_tx ).*H_bt; | 10042 | H_cc= s21out.*(1-gamma_tx)./(1.- s11out.*gamma_tx ).*H_bt; | ||
10253 | sigma_ACCM_at_tp0= sqrt(2*param.AC_CM_RMS_TX^2*sum( abs( H_cc(2:length(f_int)) ).^2 .* diff(f_int))/f_int(end)) ; | 10043 | sigma_ACCM_at_tp0= sqrt(2*param.AC_CM_RMS_TX^2*sum( abs( H_cc(2:length(f_int)) ).^2 .* diff(f_int))/f_int(end)) ; | ||
10254 | % S=sparameters(p,faxis); | 10044 | % S=sparameters(p,faxis); | ||
10255 | % rfwrite(S,'temp.s4p'); | 10045 | % rfwrite(S,'temp.s4p'); | ||
10256 | end | 10046 | end | ||
10257 | end | 10047 | end | ||
10258 |
| 10048 |
| ||
10259 | SCH.Frequencies=faxis; | 10049 | SCH.Frequencies=faxis; | ||
10260 | SCH.Parameters(1,1,:)=s11; | 10050 | SCH.Parameters(1,1,:)=s11; | ||
10261 | SCH.Parameters(2,2,:)=s22; | 10051 | SCH.Parameters(2,2,:)=s22; | ||
10262 | SCH.Parameters(1,2,:)=s12; | 10052 | SCH.Parameters(1,2,:)=s12; | ||
10263 | SCH.Parameters(2,1,:)=s21; | 10053 | SCH.Parameters(2,1,:)=s21; | ||
10264 | SCH.NumPorts=2; | 10054 | SCH.NumPorts=2; | ||
10265 | if strcmpi(mode,'dc') | 10055 | if strcmpi(mode,'dc') | ||
10266 | SCH.Impedance=25; | 10056 | SCH.Impedance=25; | ||
10267 | else | 10057 | else | ||
10268 | SCH.Impedance=100; | 10058 | SCH.Impedance=100; | ||
10269 | end | 10059 | end | ||
10270 |
| 10060 |
| ||
10271 | end | 10061 | end | ||
10272 | function [voltage, t_base, causality_correction_dB, truncation_dB] = ... | 10062 | function [voltage, t_base, causality_correction_dB, truncation_dB] = ... | ||
10273 | s21_to_impulse_DC(IL, freq_array, time_step, OP) | 10063 | s21_to_impulse_DC(IL, freq_array, time_step, OP) | ||
10274 | % Creates a time-domain impulse response from frequency-domain IL data. | 10064 | % Creates a time-domain impulse response from frequency-domain IL data. | ||
10275 | % IL does not need to have DC but a corresponding frequency array | 10065 | % IL does not need to have DC but a corresponding frequency array | ||
10276 | % (freq_array) is required. | 10066 | % (freq_array) is required. | ||
10277 | % | 10067 | % | ||
10278 | % Causality is imposed using the Alternating Projections Method. See also: | 10068 | % Causality is imposed using the Alternating Projections Method. See also: | ||
10279 | % Quatieri and Oppenheim, "Iterative Techniques for Minimum Phase Signal | 10069 | % Quatieri and Oppenheim, "Iterative Techniques for Minimum Phase Signal | ||
10280 | % Reconstruction from Phase or Magnitude", IEEE Trans. ASSP-29, December | 10070 | % Reconstruction from Phase or Magnitude", IEEE Trans. ASSP-29, December | ||
10281 | % 1981 (http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1163714) | 10071 | % 1981 (http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=1163714) | ||
10282 | 10072 | ||||
10283 | ILin=IL; | 10073 | ILin=IL; | ||
10284 | fmax=1/time_step/2; | 10074 | fmax=1/time_step/2; | ||
10285 | freq_step=(freq_array(3)-freq_array(2))/1; | 10075 | freq_step=(freq_array(3)-freq_array(2))/1; | ||
10286 | fout=0:1/round(fmax/freq_step)*fmax:fmax; | 10076 | fout=0:1/round(fmax/freq_step)*fmax:fmax; | ||
10287 | if all(IL==0) | 10077 | if all(IL==0) | ||
10288 | %response with all zeros is problematic. set to all eps and avoid interp function | 10078 | %response with all zeros is problematic. set to all eps and avoid interp function | ||
10289 | IL=ones(1,length(fout))*eps; | 10079 | IL=ones(1,length(fout))*eps; | ||
10290 | else | 10080 | else | ||
10291 | IL=interp_Sparam(ILin,freq_array,fout, OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | 10081 | IL=interp_Sparam(ILin,freq_array,fout, OP.interp_sparam_mag, OP.interp_sparam_phase,OP); | ||
10292 | IL_nan = find(isnan(IL)); | 10082 | IL_nan = find(isnan(IL)); | ||
10293 | for in=IL_nan | 10083 | for in=IL_nan | ||
10294 | IL(in)=IL(in-1); | 10084 | IL(in)=IL(in-1); | ||
10295 | end | 10085 | end | ||
10296 | end | 10086 | end | ||
10297 | IL = IL(:); | 10087 | IL = IL(:); | ||
10298 | % add padding for time steps | 10088 | % add padding for time steps | ||
10299 | % IL_symmetric = [IL(1:end-1);0; flipud(conj(IL(2:end-1)))]; | 10089 | % IL_symmetric = [IL(1:end-1);0; flipud(conj(IL(2:end-1)))]; | ||
10300 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | 10090 | IL_symmetric = [real(IL(1)); IL(2:end-1); real(IL(end)); flipud(conj(IL(2:end-1)))]; | ||
10301 | impulse_response = real(ifft(IL_symmetric)); | 10091 | impulse_response = real(ifft(IL_symmetric)); | ||
10302 | L = length(impulse_response); | 10092 | L = length(impulse_response); | ||
10303 | t_base = (0:L-1)/(freq_step*L); | 10093 | t_base = (0:L-1)/(freq_step*L); | ||
10304 | 10094 | ||||
10305 | original_impulse_response=impulse_response; | 10095 | original_impulse_response=impulse_response; | ||
10306 | % Correct non-causal effects frequently caused by extrapolation of IL | 10096 | % Correct non-causal effects frequently caused by extrapolation of IL | ||
10307 | % Assumption: peak of impulse_response is in the first half, i.e. not anti-causal | 10097 | % Assumption: peak of impulse_response is in the first half, i.e. not anti-causal | ||
10308 | abs_ir=abs(impulse_response); | 10098 | abs_ir=abs(impulse_response); | ||
10309 | a = find(abs_ir(1:L/2) > max(abs_ir(1:L/2))*OP.EC_PULSE_TOL); | 10099 | a = find(abs_ir(1:L/2) > max(abs_ir(1:L/2))*OP.EC_PULSE_TOL); | ||
10310 | start_ind = a(1); | 10100 | start_ind = a(1); | ||
10311 | 10101 | ||||
10312 | err=inf; | 10102 | err=inf; | ||
10313 | while ~all(impulse_response==0) | 10103 | while ~all(impulse_response==0) | ||
10314 | impulse_response(1:start_ind)=0; | 10104 | impulse_response(1:start_ind)=0; | ||
10315 | impulse_response(floor(L/2):end)=0; | 10105 | impulse_response(floor(L/2):end)=0; | ||
10316 | IL_modified=abs(IL_symmetric).*exp(1j*angle(fft(impulse_response))); | 10106 | IL_modified=abs(IL_symmetric).*exp(1j*angle(fft(impulse_response))); | ||
10317 | ir_modified = real(ifft(IL_modified)); | 10107 | ir_modified = real(ifft(IL_modified)); | ||
10318 | delta = abs(impulse_response-ir_modified); | 10108 | delta = abs(impulse_response-ir_modified); | ||
10319 |
| 10109 |
| ||
10320 | err_prev = err; | 10110 | err_prev = err; | ||
10321 | err=max(delta)/max(impulse_response); | 10111 | err=max(delta)/max(impulse_response); | ||
10322 | if err<OP.EC_REL_TOL || abs(err_prev-err)<OP.EC_DIFF_TOL | 10112 | if err<OP.EC_REL_TOL || abs(err_prev-err)<OP.EC_DIFF_TOL | ||
10323 | break; | 10113 | break; | ||
10324 | end | 10114 | end | ||
10325 |
| 10115 |
| ||
10326 | impulse_response=ir_modified; | 10116 | impulse_response=ir_modified; | ||
10327 | end | 10117 | end | ||
10328 | 10118 | ||||
10329 | causality_correction_dB=20*log10(norm(impulse_response-original_impulse_response)/norm(impulse_response)); | 10119 | causality_correction_dB=20*log10(norm(impulse_response-original_impulse_response)/norm(impulse_response)); | ||
10330 | 10120 | ||||
10331 | if ~OP.ENFORCE_CAUSALITY | 10121 | if ~OP.ENFORCE_CAUSALITY | ||
10332 | impulse_response = original_impulse_response; | 10122 | impulse_response = original_impulse_response; | ||
10333 | end | 10123 | end | ||
10334 | % truncate final samples smaller than 1e-3 of the peak | 10124 | % truncate final samples smaller than 1e-3 of the peak | ||
10335 | ir_peak = max(abs(impulse_response)); | 10125 | ir_peak = max(abs(impulse_response)); | ||
10336 | ir_last = find(abs(impulse_response)>ir_peak*OP.impulse_response_truncation_threshold, 1, 'last'); | 10126 | ir_last = find(abs(impulse_response)>ir_peak*OP.impulse_response_truncation_threshold, 1, 'last'); | ||
10337 | 10127 | ||||
10338 | voltage = impulse_response(1:ir_last); | 10128 | voltage = impulse_response(1:ir_last); | ||
10339 | t_base = t_base(1:ir_last); | 10129 | t_base = t_base(1:ir_last); | ||
10340 | 10130 | ||||
10341 | truncation_dB=20*log10(norm(impulse_response(ir_last+1:end))/norm(voltage)); | 10131 | truncation_dB=20*log10(norm(impulse_response(ir_last+1:end))/norm(voltage)); | ||
10342 | 10132 | ||||
10343 | function S =s_for_c2(zref,f,cpad) | 10133 | function S =s_for_c2(zref,f,cpad) | ||
10344 | % S is 2 port s parameters out | 10134 | % S is 2 port s parameters out | ||
10345 | S_Parameters(1,1,:) = -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | 10135 | S_Parameters(1,1,:) = -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | ||
10346 | S_Parameters(2,2,:) = -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | 10136 | S_Parameters(2,2,:) = -1i*2*pi.*f*cpad*zref./(2+1i*2*pi.*f*cpad*zref); | ||
10347 | S_Parameters(2,1,:) = 2./(2+1i*2*pi.*f*cpad*zref); | 10137 | S_Parameters(2,1,:) = 2./(2+1i*2*pi.*f*cpad*zref); | ||
10348 | S_Parameters(1,2,:) = 2./(2+1i*2*pi.*f*cpad*zref); | 10138 | S_Parameters(1,2,:) = 2./(2+1i*2*pi.*f*cpad*zref); | ||
10349 | S=sparameters(S_Parameters,f,zref); | 10139 | S=sparameters(S_Parameters,f,zref); | ||
10350 | 10140 | ||||
10351 | function S =s_for_c4(zref,f,cpad) | 10141 | function S =s_for_c4(zref,f,cpad) | ||
10352 | 10142 | ||||
10353 | S2 = s_for_c2(zref,f,cpad); | 10143 | S2 = s_for_c2(zref,f,cpad); | ||
10354 | S4P=s2_to_s4(S2.Parameters); | 10144 | S4P=s2_to_s4(S2.Parameters); | ||
10355 | S=sparameters(S4P,f,zref); | 10145 | S=sparameters(S4P,f,zref); | ||
10356 | S.Parameters=snp2smp(S.Parameters,zref,[ 1 3 2 4]); | 10146 | S.Parameters=snp2smp(S.Parameters,zref,[ 1 3 2 4]); | ||
10357 | 10147 | ||||
10358 | 10148 | ||||
10359 | 10149 | ||||
10360 | 10150 | ||||
10361 | %% | 10151 | %% | ||
10362 | function [ cmd_str ] = save_cmd_line( config_file, chdata, num_fext,num_next, cli_name ) | 10152 | function [ cmd_str ] = save_cmd_line( config_file, chdata, num_fext,num_next, cli_name ) | ||
10363 | % save commmend string | 10153 | % save commmend string | ||
10364 | % for saving from interactive queries | 10154 | % for saving from interactive queries | ||
10365 | 10155 | ||||
10366 | 10156 | ||||
10367 | cmd_str=[ cli_name '(' '''' config_file '''' ',' num2str(num_fext) ', ' num2str(num_next) ',' '''' chdata(1).filename '''']; | 10157 | cmd_str=[ cli_name '(' '''' config_file '''' ',' num2str(num_fext) ', ' num2str(num_next) ',' '''' chdata(1).filename '''']; | ||
10368 | for i=1:num_next+num_fext | 10158 | for i=1:num_next+num_fext | ||
10369 | cmd_str= [cmd_str ',' '''' chdata(i+1).filename '''']; | 10159 | cmd_str= [cmd_str ',' '''' chdata(i+1).filename '''']; | ||
10370 | end | 10160 | end | ||
10371 | cmd_str= [ cmd_str ')']; | 10161 | cmd_str= [ cmd_str ')']; | ||
10372 | 10162 | ||||
10373 | 10163 | ||||
10374 | %%%%% require the RF tool box | 10164 | %%%%% require the RF tool box | ||
10375 | %% | 10165 | %% | ||
10376 | function [ h ] = savefigs( param, OP ) | 10166 | function [ h ] = savefigs( param, OP ) | ||
10377 | 10167 | ||||
10378 | %% find the figures | 10168 | %% find the figures | ||
10379 | hw = waitbar(0,'Saving figures...'); | 10169 | hw = waitbar(0,'Saving figures...'); | ||
10380 | h = findobj(0, 'Type', 'figure'); | 10170 | h = findobj(0, 'Type', 'figure'); | ||
10381 | for ii=1:length(h) | 10171 | for ii=1:length(h) | ||
10382 |
| 10172 |
| ||
10383 | figname= get(h(ii), 'Name'); % use the figure name as file name | 10173 | figname= get(h(ii), 'Name'); % use the figure name as file name | ||
10384 | if isempty(strfind(figname,param.base)) | 10174 | if isempty(strfind(figname,param.base)) | ||
10385 | figname = [figname ' ' OP.RUNTAG ' ' param.base ]; %#ok<AGROW> | 10175 | figname = [figname ' ' OP.RUNTAG ' ' param.base ]; %#ok<AGROW> | ||
10386 | end | 10176 | end | ||
10387 | if verLessThan('matlab', '8.4.0') | 10177 | if verLessThan('matlab', '8.4.0') | ||
10388 | figname = ['f_' num2str(h(ii)) '_' figname]; %#ok<AGROW> | 10178 | figname = ['f_' num2str(h(ii)) '_' figname]; %#ok<AGROW> | ||
10389 | else | 10179 | else | ||
10390 | figname = ['f_' num2str(h(ii).Number) '_' figname]; %#ok<AGROW> | 10180 | figname = ['f_' num2str(h(ii).Number) '_' figname]; %#ok<AGROW> | ||
10391 | end | 10181 | end | ||
10392 | figname = strrep(figname,':','-'); | 10182 | figname = strrep(figname,':','-'); | ||
10393 | figname = strrep(figname,' ','_'); | 10183 | figname = strrep(figname,' ','_'); | ||
10394 | if OP.SAVE_FIGURES==1 | 10184 | if OP.SAVE_FIGURES==1 | ||
10395 | saveas(h(ii), fullfile(OP.RESULT_DIR, [figname '.fig'])); | 10185 | saveas(h(ii), fullfile(OP.RESULT_DIR, [figname '.fig'])); | ||
10396 | end | 10186 | end | ||
10397 | %% get x y data | 10187 | %% get x y data | ||
10398 | if OP.SAVE_FIGURE_to_CSV==1 | 10188 | if OP.SAVE_FIGURE_to_CSV==1 | ||
10399 | h_L = findobj(h(ii),'Type','line'); % find handles to all the lines | 10189 | h_L = findobj(h(ii),'Type','line'); % find handles to all the lines | ||
10400 | M=[]; %ncol=1; | 10190 | M=[]; %ncol=1; | ||
10401 | for nk=1:length(h_L) | 10191 | for nk=1:length(h_L) | ||
10402 | % get x and data for a line. | 10192 | % get x and data for a line. | ||
10403 | x_data=get(h_L(nk),'xdata')'; | 10193 | x_data=get(h_L(nk),'xdata')'; | ||
10404 | y_data=get(h_L(nk),'ydata')'; | 10194 | y_data=get(h_L(nk),'ydata')'; | ||
10405 | % .........>> need to get data in the line structure (legend or label) for headers | 10195 | % .........>> need to get data in the line structure (legend or label) for headers | ||
10406 | M=[M; x_data; y_data]; %#ok<AGROW> | 10196 | M=[M; x_data; y_data]; %#ok<AGROW> | ||
10407 | end | 10197 | end | ||
10408 | csvwrite([OP.RESULT_DIR figname '.csv'],M); | 10198 | csvwrite([OP.RESULT_DIR figname '.csv'],M); | ||
10409 | % clear M y x header h_L | 10199 | % clear M y x header h_L | ||
10410 | end | 10200 | end | ||
10411 | waitbar(ii/length(h),hw) | 10201 | waitbar(ii/length(h),hw) | ||
10412 |
| 10202 |
| ||
10413 | end | 10203 | end | ||
10414 | 10204 | ||||
10415 | close(hw) | 10205 | close(hw) | ||
10416 | 10206 | ||||
10417 | %% | 10207 | %% | ||
10418 | function [ h ] = savefigs_png( param, OP ) | 10208 | function [ h ] = savefigs_png( param, OP ) | ||
10419 | 10209 | ||||
10420 | %% find the figures | 10210 | %% find the figures | ||
10421 | hw = waitbar(0,'Saving figures...'); | 10211 | hw = waitbar(0,'Saving figures...'); | ||
10422 | h = findobj(0, 'Type', 'figure'); | 10212 | h = findobj(0, 'Type', 'figure'); | ||
10423 | for ii=1:length(h) | 10213 | for ii=1:length(h) | ||
10424 |
| 10214 |
| ||
10425 | figname= get(h(ii), 'Name'); % use the figure name as file name | 10215 | figname= get(h(ii), 'Name'); % use the figure name as file name | ||
10426 | if isempty(strfind(figname,param.base)) | 10216 | if isempty(strfind(figname,param.base)) | ||
10427 | figname = [figname ' ' OP.RUNTAG ' ' param.base ]; %#ok<AGROW> | 10217 | figname = [figname ' ' OP.RUNTAG ' ' param.base ]; %#ok<AGROW> | ||
10428 | end | 10218 | end | ||
10429 | if verLessThan('matlab', '8.4.0') | 10219 | if verLessThan('matlab', '8.4.0') | ||
10430 | figname = ['f_' num2str(h(ii)) '_' figname]; %#ok<AGROW> | 10220 | figname = ['f_' num2str(h(ii)) '_' figname]; %#ok<AGROW> | ||
10431 | else | 10221 | else | ||
10432 | figname = ['f_' num2str(h(ii).Number) '_' figname]; %#ok<AGROW> | 10222 | figname = ['f_' num2str(h(ii).Number) '_' figname]; %#ok<AGROW> | ||
10433 | end | 10223 | end | ||
10434 | figname = strrep(figname,':','-'); | 10224 | figname = strrep(figname,':','-'); | ||
10435 | figname = strrep(figname,' ','_'); | 10225 | figname = strrep(figname,' ','_'); | ||
10436 | if OP.SAVE_FIGURES==1 | 10226 | if OP.SAVE_FIGURES==1 | ||
10437 | saveas(h(ii), fullfile(OP.RESULT_DIR, [figname '.png'])); | 10227 | saveas(h(ii), fullfile(OP.RESULT_DIR, [figname '.png'])); | ||
10438 | end | 10228 | end | ||
10439 | %% get x y data | 10229 | %% get x y data | ||
10440 | if OP.SAVE_FIGURE_to_CSV==1 | 10230 | if OP.SAVE_FIGURE_to_CSV==1 | ||
10441 | h_L = findobj(h(ii),'Type','line'); % find handles to all the lines | 10231 | h_L = findobj(h(ii),'Type','line'); % find handles to all the lines | ||
10442 | M=[]; %ncol=1; | 10232 | M=[]; %ncol=1; | ||
10443 | for nk=1:length(h_L) | 10233 | for nk=1:length(h_L) | ||
10444 | % get x and data for a line. | 10234 | % get x and data for a line. | ||
10445 | x_data=get(h_L(nk),'xdata')'; | 10235 | x_data=get(h_L(nk),'xdata')'; | ||
10446 | y_data=get(h_L(nk),'ydata')'; | 10236 | y_data=get(h_L(nk),'ydata')'; | ||
10447 | % .........>> need to get data in the line structure (legend or label) for headers | 10237 | % .........>> need to get data in the line structure (legend or label) for headers | ||
10448 | M=[M; x_data; y_data]; %#ok<AGROW> | 10238 | M=[M; x_data; y_data]; %#ok<AGROW> | ||
10449 | end | 10239 | end | ||
10450 | csvwrite([OP.RESULT_DIR figname '.csv'],M); | 10240 | csvwrite([OP.RESULT_DIR figname '.csv'],M); | ||
10451 | % clear M y x header h_L | 10241 | % clear M y x header h_L | ||
10452 | end | 10242 | end | ||
10453 | waitbar(ii/length(h),hw) | 10243 | waitbar(ii/length(h),hw) | ||
10454 |
| 10244 |
| ||
10455 | end | 10245 | end | ||
10456 | 10246 | ||||
10457 | close(hw) | 10247 | close(hw) | ||
10458 | 10248 | ||||
10459 | %% | 10249 | %% | ||
10460 | function pdf_out = scalePDF(pdf,scale_factor) | 10250 | function pdf_out = scalePDF(pdf,scale_factor) | ||
10461 | pdf_out=pdf; | 10251 | pdf_out=pdf; | ||
10462 | pdf_out.Min=floor(pdf.Min*scale_factor); | 10252 | pdf_out.Min=floor(pdf.Min*scale_factor); | ||
10463 | pdf_out.x=(pdf_out.Min:-pdf_out.Min)*pdf_out.BinSize; | 10253 | pdf_out.x=(pdf_out.Min:-pdf_out.Min)*pdf_out.BinSize; | ||
10464 | pdf_out.y=interp1(pdf.x*scale_factor,pdf.y,pdf_out.x); | 10254 | pdf_out.y=interp1(pdf.x*scale_factor,pdf.y,pdf_out.x); | ||
10465 | pdf_out.y(1)= pdf_out.y(2); % NAN interp work around | 10255 | pdf_out.y(1)= pdf_out.y(2); % NAN interp work around | ||
10466 | pdf_out.y(end)= pdf_out.y(end-1); % NAN interp work around | 10256 | pdf_out.y(end)= pdf_out.y(end-1); % NAN interp work around | ||
10467 | pdf_out.y=pdf_out.y/sum(pdf_out.y); | 10257 | pdf_out.y=pdf_out.y/sum(pdf_out.y); | ||
10468 | function t_params = stot(s_params) | 10258 | function t_params = stot(s_params) | ||
10469 | % p 67 R. Mavaddat. (1996). Network scattering parameter. Singapore: World Scientific. | 10259 | % p 67 R. Mavaddat. (1996). Network scattering parameter. Singapore: World Scientific. | ||
10470 | % ISBN 978-981-02-2305-2. http://books.google.com/?id=287g2NkRYxUC&lpg=PA65&dq=T-parameters+&pg=PA67. | 10260 | % ISBN 978-981-02-2305-2. http://books.google.com/?id=287g2NkRYxUC&lpg=PA65&dq=T-parameters+&pg=PA67. | ||
10471 | [s11, s12, s21, s22] = deal(s_params(1,1,:), s_params(1,2,:), s_params(2,1,:), s_params(2,2,:)); | 10261 | [s11, s12, s21, s22] = deal(s_params(1,1,:), s_params(1,2,:), s_params(2,1,:), s_params(2,2,:)); | ||
10472 | delta = (s11.*s22-s12.*s21); | 10262 | delta = (s11.*s22-s12.*s21); | ||
10473 | s21(s21==0)=eps; | 10263 | s21(s21==0)=eps; | ||
10474 | t_params = [1./s21, -s22./s21; s11./s21, -delta./s21]; | 10264 | t_params = [1./s21, -s22./s21; s11./s21, -delta./s21]; | ||
10475 | 10265 | ||||
10476 | function csv_string = str2csv(c) | 10266 | function csv_string = str2csv(c) | ||
10477 | % convert a cell array of strings to a csv string | 10267 | % convert a cell array of strings to a csv string | ||
10478 | cell_tmp = cell(2, length(c)); | 10268 | cell_tmp = cell(2, length(c)); | ||
10479 | cell_tmp(1,:)=c; | 10269 | cell_tmp(1,:)=c; | ||
10480 | cell_tmp(2,:) = {','}; | 10270 | cell_tmp(2,:) = {','}; | ||
10481 | cell_tmp{2,end} = ''; | 10271 | cell_tmp{2,end} = ''; | ||
10482 | csv_string=strcat(cell_tmp{:}); | 10272 | csv_string=strcat(cell_tmp{:}); | ||
10483 | 10273 | ||||
10484 | function [s11, s12, s21, s22] = synth_tline(f, Z_c, Z_0, gamma_coeff, tau, d) | 10274 | function [s11, s12, s21, s22] = synth_tline(f, Z_c, Z_0, gamma_coeff, tau, d) | ||
10485 | f_GHz=f/1e9; | 10275 | f_GHz=f/1e9; | ||
10486 | %% Equation 93A-10 %% | 10276 | %% Equation 93A-10 %% | ||
10487 | gamma_1 = gamma_coeff(2)*(1+1i); | 10277 | gamma_1 = gamma_coeff(2)*(1+1i); | ||
10488 | %% Equation 93A-11 %% | 10278 | %% Equation 93A-11 %% | ||
10489 | gamma_2 = gamma_coeff(3)*(1-2i/pi*log(f_GHz)) + 2i*pi*tau; | 10279 | gamma_2 = gamma_coeff(3)*(1-2i/pi*log(f_GHz)) + 2i*pi*tau; | ||
10490 | %% Equation 93A-9 %% | 10280 | %% Equation 93A-9 %% | ||
10491 | gamma = gamma_coeff(1)+gamma_1.*sqrt(f_GHz)+gamma_2.*f_GHz; | 10281 | gamma = gamma_coeff(1)+gamma_1.*sqrt(f_GHz)+gamma_2.*f_GHz; | ||
10492 | gamma(f_GHz==0) = gamma_coeff(1); | 10282 | gamma(f_GHz==0) = gamma_coeff(1); | ||
10493 | 10283 | ||||
10494 | %% Equation 93A-12 %% | 10284 | %% Equation 93A-12 %% | ||
10495 | if d==0 | 10285 | if d==0 | ||
10496 | %force matched impedance if length is 0 | 10286 | %force matched impedance if length is 0 | ||
10497 | %otherwise divide by zero can occur if Z_c=0 | 10287 | %otherwise divide by zero can occur if Z_c=0 | ||
10498 | rho_rl=0; | 10288 | rho_rl=0; | ||
10499 | else | 10289 | else | ||
10500 | rho_rl=(Z_c-2*Z_0)/(Z_c+2*Z_0); | 10290 | rho_rl=(Z_c-2*Z_0)/(Z_c+2*Z_0); | ||
10501 | end | 10291 | end | ||
10502 | 10292 | ||||
10503 | exp_gamma_d = exp(-d*gamma); | 10293 | exp_gamma_d = exp(-d*gamma); | ||
10504 | %% Equations 93A-13 and 93A-14 %% | 10294 | %% Equations 93A-13 and 93A-14 %% | ||
10505 | s11 = rho_rl*(1-exp_gamma_d.^2)./(1-rho_rl^2*exp_gamma_d.^2); | 10295 | s11 = rho_rl*(1-exp_gamma_d.^2)./(1-rho_rl^2*exp_gamma_d.^2); | ||
10506 | s21 = (1-rho_rl^2)*exp_gamma_d./(1-rho_rl^2*exp_gamma_d.^2); | 10296 | s21 = (1-rho_rl^2)*exp_gamma_d./(1-rho_rl^2*exp_gamma_d.^2); | ||
10507 | s12 = s21; | 10297 | s12 = s21; | ||
10508 | s22 = s11; | 10298 | s22 = s11; | ||
10509 | 10299 | ||||
10510 | function s_params = ttos(t_params) | 10300 | function s_params = ttos(t_params) | ||
10511 | % p 67 R. Mavaddat. (1996). Network scattering parameter. Singapore: World Scientific. | 10301 | % p 67 R. Mavaddat. (1996). Network scattering parameter. Singapore: World Scientific. | ||
10512 | % ISBN 978-981-02-2305-2. http://books.google.com/?id=287g2NkRYxUC&lpg=PA65&dq=T-parameters+&pg=PA67. | 10302 | % ISBN 978-981-02-2305-2. http://books.google.com/?id=287g2NkRYxUC&lpg=PA65&dq=T-parameters+&pg=PA67. | ||
10513 | [t11, t12, t21, t22] = deal(t_params(1,1,:), t_params(1,2,:), t_params(2,1,:), t_params(2,2,:)); | 10303 | [t11, t12, t21, t22] = deal(t_params(1,1,:), t_params(1,2,:), t_params(2,1,:), t_params(2,2,:)); | ||
10514 | delta = t11.*t22-t21.*t12; | 10304 | delta = t11.*t22-t21.*t12; | ||
10515 | t11(t11==0)=eps; | 10305 | t11(t11==0)=eps; | ||
10516 | s_params = [t21./t11, delta./t11; 1./t11, -t12./t11]; | 10306 | s_params = [t21./t11, delta./t11; 1./t11, -t12./t11]; | ||
10517 | 10307 | ||||
10518 | function [out_var,varg_out]=varargin_extractor(varargin) | 10308 | function [out_var,varg_out]=varargin_extractor(varargin) | ||
10519 | 10309 | ||||
10520 | if isempty(varargin) | 10310 | if isempty(varargin) | ||
10521 | out_var=[]; | 10311 | out_var=[]; | ||
10522 | varg_out={}; | 10312 | varg_out={}; | ||
10523 | else | 10313 | else | ||
10524 | out_var=varargin{1}; | 10314 | out_var=varargin{1}; | ||
10525 | varg_out=varargin; | 10315 | varg_out=varargin; | ||
10526 | varg_out(1)=[]; | 10316 | varg_out(1)=[]; | ||
10527 | end | 10317 | end | ||
10528 |
| 10318 |
| ||
10529 |
| 10319 |
| ||
10530 | function results= vma(PR, M) | 10320 | function results= vma(PR, M) | ||
10531 | % PR=sbr.Data; | 10321 | % PR=sbr.Data; | ||
10532 | % M=32; | 10322 | % M=32; | ||
10533 | % PR is the pulse response | 10323 | % PR is the pulse response | ||
10534 | % M is samples per UI | 10324 | % M is samples per UI | ||
10535 | [ seq, syms, syms_nrz ] = PRBS13Q( ); | 10325 | [ seq, syms, syms_nrz ] = PRBS13Q( ); | ||
10536 | % seq uses [ -1 -1/3 1/3 1] & syms uses [ 0 1 2 3 ] | 10326 | % seq uses [ -1 -1/3 1/3 1] & syms uses [ 0 1 2 3 ] | ||
10537 | symbols=seq; | 10327 | symbols=seq; | ||
10538 | imaxPR=find(PR==max(PR),1,'first'); % find index for peak | 10328 | imaxPR=find(PR==max(PR),1,'first'); % find index for peak | ||
10539 | % start end symbols index for 7 3's and 6 0's | 10329 | % start end symbols index for 7 3's and 6 0's | ||
10540 | indx_S3x7_start=M*(strfind(syms,ones(1,7)*3)-1)+imaxPR; | 10330 | indx_S3x7_start=M*(strfind(syms,ones(1,7)*3)-1)+imaxPR; | ||
10541 | indx_S3x7_end=M*(strfind(syms,ones(1,7)*3)+5)+imaxPR; | 10331 | indx_S3x7_end=M*(strfind(syms,ones(1,7)*3)+5)+imaxPR; | ||
10542 | indx_S0x6_start=M*(strfind(syms,ones(1,6)*0))-1+imaxPR; | 10332 | indx_S0x6_start=M*(strfind(syms,ones(1,6)*0))-1+imaxPR; | ||
10543 | indx_S0x6_end=M*(strfind(syms,ones(1,6)*0)+4)+imaxPR; | 10333 | indx_S0x6_end=M*(strfind(syms,ones(1,6)*0)+4)+imaxPR; | ||
10544 | % superposition code | 10334 | % superposition code | ||
10545 | shifting_vector=kron(symbols,[ 1 zeros(1,M-1) ]) ; | 10335 | shifting_vector=kron(symbols,[ 1 zeros(1,M-1) ]) ; | ||
10546 | Bit_stream_response=filter(PR,1, shifting_vector); | 10336 | Bit_stream_response=filter(PR,1, shifting_vector); | ||
10547 | % find center of 3's and 0's | 10337 | % find center of 3's and 0's | ||
10548 | icent3=floor((indx_S3x7_end-indx_S3x7_start)/2 + indx_S3x7_start); | 10338 | icent3=floor((indx_S3x7_end-indx_S3x7_start)/2 + indx_S3x7_start); | ||
10549 | icent0=floor((indx_S0x6_end-indx_S0x6_start)/2 + indx_S0x6_start); | 10339 | icent0=floor((indx_S0x6_end-indx_S0x6_start)/2 + indx_S0x6_start); | ||
10550 | % plot(Bit_stream_response(indx_S3x7_start:indx_S3x7_end)) | 10340 | % plot(Bit_stream_response(indx_S3x7_start:indx_S3x7_end)) | ||
10551 | % hold on | 10341 | % hold on | ||
10552 | % plot(Bit_stream_response(indx_S0x6_start:indx_S0x6_end)) | 10342 | % plot(Bit_stream_response(indx_S0x6_start:indx_S0x6_end)) | ||
10553 | P_3 = mean( Bit_stream_response((icent3-M):(icent3+M) ) ); | 10343 | P_3 = mean( Bit_stream_response((icent3-M):(icent3+M) ) ); | ||
10554 | P_0 = mean( Bit_stream_response((icent0-M):(icent0+M) ) ); | 10344 | P_0 = mean( Bit_stream_response((icent0-M):(icent0+M) ) ); | ||
10555 | VMA= P_3 - P_0; | 10345 | VMA= P_3 - P_0; | ||
10556 | results.P_3=P_3; | 10346 | results.P_3=P_3; | ||
10557 | results.P_0=P_0; | 10347 | results.P_0=P_0; | ||
10558 | results.VMA=VMA; | 10348 | results.VMA=VMA; | ||
10559 | function line_intersection=vref_intersect(eye_contour,x_in,vref) | 10349 | function line_intersection=vref_intersect(eye_contour,x_in,vref) | ||
10560 | 10350 | ||||
10561 | %slope of the 2 sample points around vref crossing | 10351 | %slope of the 2 sample points around vref crossing | ||
10562 | m1=(eye_contour(x_in,1)-eye_contour(x_in-1,1)); | 10352 | m1=(eye_contour(x_in,1)-eye_contour(x_in-1,1)); | ||
10563 | %x-intercept for the line | 10353 | %x-intercept for the line | ||
10564 | b1=eye_contour(x_in,1)-m1*x_in; | 10354 | b1=eye_contour(x_in,1)-m1*x_in; | ||
10565 | % drawing a horizontal line through vref so slope = 0 | 10355 | % drawing a horizontal line through vref so slope = 0 | ||
10566 | m2=0; | 10356 | m2=0; | ||
10567 | %special case for horizontal line, b=y | 10357 | %special case for horizontal line, b=y | ||
10568 | b2=vref; | 10358 | b2=vref; | ||
10569 | %the x-value of line intersection = (b2-b1)/(m1-m2) | 10359 | %the x-value of line intersection = (b2-b1)/(m1-m2) | ||
10570 | %sinc m2 is always 0 and b2 is always vref, this could be stated as (vref-b1)/m1 | 10360 | %sinc m2 is always 0 and b2 is always vref, this could be stated as (vref-b1)/m1 | ||
10571 | %And usually vref is 0, so it further reduces to -b1/m1 | 10361 | %And usually vref is 0, so it further reduces to -b1/m1 | ||
10572 | line_intersection=(b2-b1)/(m1-m2); | 10362 | line_intersection=(b2-b1)/(m1-m2); | ||
10573 | 10363 | ||||
10574 | 10364 | ||||
10575 | 10365 | ||||
10576 | 10366 | ||||
10577 | 10367 | ||||
10578 | function p=xls_parameter(param_sheet, param_name, eval_if_string, default_value) | 10368 | function p=xls_parameter(param_sheet, param_name, eval_if_string, default_value) | ||
10579 | % helper function to read parameter values from XLS file. Uses names to find values. | 10369 | % helper function to read parameter values from XLS file. Uses names to find values. | ||
10580 | if nargin<3, eval_if_string=0; end | 10370 | if nargin<3, eval_if_string=0; end | ||
10581 | [row, col]=find(strcmpi(param_sheet, param_name)); % RIM 08-26-2020 make case insensitive | 10371 | [row, col]=find(strcmpi(param_sheet, param_name)); % RIM 08-26-2020 make case insensitive | ||
10582 | if numel(row)*numel(col)==0 | 10372 | if numel(row)*numel(col)==0 | ||
10583 | if nargin<4 | 10373 | if nargin<4 | ||
10584 | missingParameter(param_name); | 10374 | missingParameter(param_name); | ||
10585 | else | 10375 | else | ||
10586 | p = default_value; | 10376 | p = default_value; | ||
10587 | end | 10377 | end | ||
10588 | elseif numel(row)*numel(col)>1 | 10378 | elseif numel(row)*numel(col)>1 | ||
10589 | % if there are several occurrences, use the first, but warn | 10379 | % if there are several occurrences, use the first, but warn | ||
10590 | % warning('COM:XLS_parameter:MultipleOccurrence', ... | 10380 | % warning('COM:XLS_parameter:MultipleOccurrence', ... | ||
10591 | % '%d occurrences of "%s" found. Using the first', numel(row), param_name); | 10381 | % '%d occurrences of "%s" found. Using the first', numel(row), param_name); | ||
10592 | error('COM:XLS_parameter:MultipleOccurrence', ... | 10382 | error('COM:XLS_parameter:MultipleOccurrence', ... | ||
10593 | '%d occurrences of "%s" found. Please recheck spreadsheet', numel(row), param_name);% RIM 01-0 8-20 | 10383 | '%d occurrences of "%s" found. Please recheck spreadsheet', numel(row), param_name);% RIM 01-0 8-20 | ||
10594 | p=param_sheet{row(1), col(1)+1}; | 10384 | p=param_sheet{row(1), col(1)+1}; | ||
10595 | else | 10385 | else | ||
10596 | p=param_sheet{row, col+1}; | 10386 | p=param_sheet{row, col+1}; | ||
10597 | end | 10387 | end | ||
10598 | if ischar(p) && eval_if_string | 10388 | if ischar(p) && eval_if_string | ||
10599 | p=eval(p); | 10389 | p=eval(p); | ||
10600 | end | 10390 | end | ||
10601 | OP.SAVE_KEYWORD_FILE=0; % OP not passed ... maybe later set to 1 manually to get keyword file. | 10391 | OP.SAVE_KEYWORD_FILE=0; % OP not passed ... maybe later set to 1 manually to get keyword file. | ||
10602 | if OP.SAVE_KEYWORD_FILE | 10392 | if OP.SAVE_KEYWORD_FILE | ||
10603 | 10393 | ||||
10604 | if nargin<3 || ~exist('default_value','var') | 10394 | if nargin<3 || ~exist('default_value','var') | ||
10605 | default_value=p; | 10395 | default_value=p; | ||
10606 | end | 10396 | end | ||
10607 | if isempty(default_value) | 10397 | if isempty(default_value) | ||
10608 | default_value='-'; | 10398 | default_value='-'; | ||
10609 | end | 10399 | end | ||
10610 | %% | 10400 | %% | ||
10611 | % Get call-stack info: | 10401 | % Get call-stack info: | ||
10612 | stDebug = dbstack; | 10402 | stDebug = dbstack; | ||
10613 | callerFileName = stDebug(2).file; | 10403 | callerFileName = stDebug(2).file; | ||
10614 | callerLineNumber = stDebug(2).line; | 10404 | callerLineNumber = stDebug(2).line; | ||
10615 | % Open caller file: | 10405 | % Open caller file: | ||
10616 | fCaller = fopen(callerFileName); | 10406 | fCaller = fopen(callerFileName); | ||
10617 | % Iterate through lines to get to desired line number: | 10407 | % Iterate through lines to get to desired line number: | ||
10618 | for iLine = 1 : callerLineNumber | 10408 | for iLine = 1 : callerLineNumber | ||
10619 | % Read current line of text: | 10409 | % Read current line of text: | ||
10620 | currLine = fgetl(fCaller); | 10410 | currLine = fgetl(fCaller); | ||
10621 | end | 10411 | end | ||
10622 | % (currLine) now reflects calling desired code: display this code: | 10412 | % (currLine) now reflects calling desired code: display this code: | ||
10623 | % fprintf('Complete text of calling code is : ''%s''\n',currLine); | 10413 | % fprintf('Complete text of calling code is : ''%s''\n',currLine); | ||
10624 | % Close caller file: | 10414 | % Close caller file: | ||
10625 | left_side=currLine(1:strfind(currLine,'=')-1); | 10415 | left_side=currLine(1:strfind(currLine,'=')-1); | ||
10626 | cmt_side=currLine(strfind(currLine,'%')+1:end); | 10416 | cmt_side=currLine(strfind(currLine,'%')+1:end); | ||
10627 | if isempty(cmt_side), cmt_side=' ';end | 10417 | if isempty(cmt_side), cmt_side=' ';end | ||
10628 | fclose(fCaller); | 10418 | fclose(fCaller); | ||
10629 |
| 10419 |
| ||
10630 | if ~ischar(default_value) | 10420 | if ~ischar(default_value) | ||
10631 | default_str=sprintf('%g ',default_value); | 10421 | default_str=sprintf('%g ',default_value); | ||
10632 | else | 10422 | else | ||
10633 | default_str=default_value; | 10423 | default_str=default_value; | ||
10634 | end | 10424 | end | ||
10635 | if ~isfile('keyworklog.mat') | 10425 | if ~isfile('keyworklog.mat') | ||
10636 | save_p=param_name; | 10426 | save_p=param_name; | ||
10637 | save_d=default_str; | 10427 | save_d=default_str; | ||
10638 | save_r=left_side; | 10428 | save_r=left_side; | ||
10639 | save_c=cmt_side; | 10429 | save_c=cmt_side; | ||
10640 | param_name = {'keyword'}; | 10430 | param_name = {'keyword'}; | ||
10641 | default_str = {'default'}; | 10431 | default_str = {'default'}; | ||
10642 | left_side={'matlab variable'}; | 10432 | left_side={'matlab variable'}; | ||
10643 | cmt_side={'info'}; | 10433 | cmt_side={'info'}; | ||
10644 | save('keyworklog.mat','left_side', 'param_name','default_str','cmt_side'); | 10434 | save('keyworklog.mat','left_side', 'param_name','default_str','cmt_side'); | ||
10645 | param_name=save_p; | 10435 | param_name=save_p; | ||
10646 | default_str=save_d; | 10436 | default_str=save_d; | ||
10647 | left_side=save_r; | 10437 | left_side=save_r; | ||
10648 | cmt_side=save_c; | 10438 | cmt_side=save_c; | ||
10649 | data=load('keyworklog.mat'); | 10439 | data=load('keyworklog.mat'); | ||
10650 | else | 10440 | else | ||
10651 | load('keyworklog.mat'); | 10441 | load('keyworklog.mat'); | ||
10652 | end | 10442 | end | ||
10653 | data.left_side = [ data.left_side; left_side]; | 10443 | data.left_side = [ data.left_side; left_side]; | ||
10654 | data.param_name = [data.param_name; param_name]; | 10444 | data.param_name = [data.param_name; param_name]; | ||
10655 | data.default_str = [data.default_str; default_str ]; | 10445 | data.default_str = [data.default_str; default_str ]; | ||
10656 | data.cmt_side = [ data.cmt_side; cmt_side]; | 10446 | data.cmt_side = [ data.cmt_side; cmt_side]; | ||
10657 | if length(data.default_str)~=length(data.default_str) | 10447 | if length(data.default_str)~=length(data.default_str) | ||
10658 | a=1; | 10448 | a=1; | ||
10659 | end | 10449 | end | ||
10660 | T=table(data.left_side, data.param_name, data.default_str, data.cmt_side); | 10450 | T=table(data.left_side, data.param_name, data.default_str, data.cmt_side); | ||
10661 | save('keyworklog.mat','data'); | 10451 | save('keyworklog.mat','data'); | ||
10662 | writetable(T,[ 'keywords_' date '.csv' ]); | 10452 | writetable(T,[ 'keywords_' date '.csv' ]); | ||
10663 | end | 10453 | end | ||
10664 | function [p,found]=xls_parameter_txffe(param_sheet, param_name) | 10454 | function [p,found]=xls_parameter_txffe(param_sheet, param_name) | ||
10665 | % pretty much the same as "xls_parameter" but this is only used to dynamically find txffe | 10455 | % pretty much the same as "xls_parameter" but this is only used to dynamically find txffe | ||
10666 | % to make the search dynamic, the "found" output is returned to let the calling function know to stop searching | 10456 | % to make the search dynamic, the "found" output is returned to let the calling function know to stop searching | ||
10667 | 10457 | ||||
10668 | found=1; | 10458 | found=1; | ||
10669 | [row, col]=find(strcmpi(param_sheet, param_name)); % RIM 08-26-2020 make case insensitive | 10459 | [row, col]=find(strcmpi(param_sheet, param_name)); % RIM 08-26-2020 make case insensitive | ||
10670 | if numel(row)*numel(col)==0 | 10460 | if numel(row)*numel(col)==0 | ||
10671 | p = 0; | 10461 | p = 0; | ||
10672 | found=0; | 10462 | found=0; | ||
10673 | elseif numel(row)*numel(col)>1 | 10463 | elseif numel(row)*numel(col)>1 | ||
10674 | % if there are several occurrences, use the first, but warn | 10464 | % if there are several occurrences, use the first, but warn | ||
10675 | % warning('COM:XLS_parameter:MultipleOccurrence', ... | 10465 | % warning('COM:XLS_parameter:MultipleOccurrence', ... | ||
10676 | % '%d occurrences of "%s" found. Using the first', numel(row), param_name); | 10466 | % '%d occurrences of "%s" found. Using the first', numel(row), param_name); | ||
10677 | error('COM:XLS_parameter:MultipleOccurrence', ... | 10467 | error('COM:XLS_parameter:MultipleOccurrence', ... | ||
10678 | '%d occurrences of "%s" found. Please recheck spreadsheet', numel(row), param_name);% RIM 01-0 8-20 | 10468 | '%d occurrences of "%s" found. Please recheck spreadsheet', numel(row), param_name);% RIM 01-0 8-20 | ||
10679 | p=param_sheet{row(1), col(1)+1}; | 10469 | p=param_sheet{row(1), col(1)+1}; | ||
10680 | else | 10470 | else | ||
10681 | p=param_sheet{row, col+1}; | 10471 | p=param_sheet{row, col+1}; | ||
10682 | end | 10472 | end | ||
10683 | if ischar(p) | 10473 | if ischar(p) | ||
10684 | p=eval(p); | 10474 | p=eval(p); | ||
10685 | end | 10475 | end | ||
10686 | function zzz_list_of_changes | 10476 | function zzz_list_of_changes | ||
10687 | % structures: | 10477 | % structures: | ||
10688 | % chdata(i) | 10478 | % chdata(i) | ||
10689 | % i= 1 --> THRU index | 10479 | % i= 1 --> THRU index | ||
10690 | % i= 2, num_fext+1 --> FEXT channel index | 10480 | % i= 2, num_fext+1 --> FEXT channel index | ||
10691 | % i= num_fext+2, num_next+num_fext+1 | 10481 | % i= num_fext+2, num_next+num_fext+1 | ||
10692 | % base: name of THRU file | 10482 | % base: name of THRU file | ||
10693 | % A: amplitude | 10483 | % A: amplitude | ||
10694 | % type: 'THRU', 'NEXT', or 'FEXT' | 10484 | % type: 'THRU', 'NEXT', or 'FEXT' | ||
10695 | % ftr: Rise time frequency | 10485 | % ftr: Rise time frequency | ||
10696 | % fmaxi: max number of frequency points | 10486 | % fmaxi: max number of frequency points | ||
10697 | % faxis: frequency array [Hz] | 10487 | % faxis: frequency array [Hz] | ||
10698 | % sdd21: (Htot) rewritten as product of ,vtf based on pkg RL ,tx filter, Rx filter | 10488 | % sdd21: (Htot) rewritten as product of ,vtf based on pkg RL ,tx filter, Rx filter | ||
10699 | % sdd22: differential RL | 10489 | % sdd22: differential RL | ||
10700 | % sdd11: differential RL | 10490 | % sdd11: differential RL | ||
10701 | % sdd21p: vtf based on pkg RL , this an interim parameter and set to sdd21 | 10491 | % sdd21p: vtf based on pkg RL , this an interim parameter and set to sdd21 | ||
10702 | % sdd21f: raw differential IL not filtered use for FD plots | 10492 | % sdd21f: raw differential IL not filtered use for FD plots | ||
10703 | % added output_args.peak_uneq_pulse_mV | 10493 | % added output_args.peak_uneq_pulse_mV | ||
10704 | % added output_args.cable_loss when "Include PCB" is not 0 in the config file | 10494 | % added output_args.cable_loss when "Include PCB" is not 0 in the config file | ||
10705 | % added: tap c(-2) c(2) and c(3) | 10495 | % added: tap c(-2) c(2) and c(3) | ||
10706 | % added: g_DC_HP and f_HP_PZ | 10496 | % added: g_DC_HP and f_HP_PZ | ||
10707 | % added: new value for "Include PCB" = 2 for cable Rx compliance test only Rx host added | 10497 | % added: new value for "Include PCB" = 2 for cable Rx compliance test only Rx host added | ||
10708 | % added: BREAD_CRUMBS is 1 then a mat file with the structures params and OP is created in the results directory | 10498 | % added: BREAD_CRUMBS is 1 then a mat file with the structures params and OP is created in the results directory | ||
10709 | % added: T_r_filter_type for RITT testing when IDEAL_TX_TERM is 1: | 10499 | % added: T_r_filter_type for RITT testing when IDEAL_TX_TERM is 1: | ||
10710 | % added T_r_meas_point for RITT, if 0, measurement was at tp0, if 1 measurement was tp0a | 10500 | % added T_r_meas_point for RITT, if 0, measurement was at tp0, if 1 measurement was tp0a | ||
10711 | % 0 is for is for Gaussian filter and 1 is for a 4th order Bessel-Thomson filter | 10501 | % 0 is for is for Gaussian filter and 1 is for a 4th order Bessel-Thomson filter | ||
10712 | % fixed INCLUDE_CTLE=0 to really remove from computation | 10502 | % fixed INCLUDE_CTLE=0 to really remove from computation | ||
10713 | % r161a fixed matlab version issue when for OP.INCLUDE_CTLE=0 | 10503 | % r161a fixed matlab version issue when for OP.INCLUDE_CTLE=0 | ||
10714 | % r162 adjusting RITT rise time to Mike Dudek's recommendations also always enable risetime filter if T_r_filter_type=1 | 10504 | % r162 adjusting RITT rise time to Mike Dudek's recommendations also always enable risetime filter if T_r_filter_type=1 | ||
10715 | % r162 tx and rx package impedance {Zc) | 10505 | % r162 tx and rx package impedance {Zc) | ||
10716 | % r162a Gaussian equation corrected | 10506 | % r162a Gaussian equation corrected | ||
10717 | % r163 cast snr_tx with package test case | 10507 | % r163 cast snr_tx with package test case | ||
10718 | % r164 fix pdf for very low noise and lo pass filter enhancements | 10508 | % r164 fix pdf for very low noise and lo pass filter enhancements | ||
10719 | % r164 add zero gain at nqyist CTLE as in CL12e | 10509 | % r164 add zero gain at nqyist CTLE as in CL12e | ||
10720 | % r165 add simpler congfig command called FORCE_TR (force risetime) | 10510 | % r165 add simpler congfig command called FORCE_TR (force risetime) | ||
10721 | % r200 cm3 and cm4 added cp3 removed | 10511 | % r200 cm3 and cm4 added cp3 removed | ||
10722 | % r200 fixed problem in s21_to_impulse_DC when s parameter have a DC entry | 10512 | % r200 fixed problem in s21_to_impulse_DC when s parameter have a DC entry | ||
10723 | % r200 ILD_FOM updated to EQ93A-55 ERL adde | 10513 | % r200 ILD_FOM updated to EQ93A-55 ERL adde | ||
10724 | % r200 improved phase interpolation for return loss time conversion | 10514 | % r200 improved phase interpolation for return loss time conversion | ||
10725 | % r200a db = @(x) 20*log10(abs(x)) added so sig processing toolbox won't be required | 10515 | % r200a db = @(x) 20*log10(abs(x)) added so sig processing toolbox won't be required | ||
10726 | % r200b Fixed error in bifurcation of Tx/Rx Rd% | 10516 | % r200b Fixed error in bifurcation of Tx/Rx Rd% | ||
10727 | % r200c missed on fix for interpolation | 10517 | % r200c missed on fix for interpolation | ||
10728 | % r210 new ERL with time gating function | 10518 | % r210 new ERL with time gating function | ||
10729 | % r224 update ERL with from D3.1 | 10519 | % r224 update ERL with from D3.1 | ||
10730 | % r226 fix s2p reading problem | 10520 | % r226 fix s2p reading problem | ||
10731 | % change SNR_ISI_XTK_normalized_1_sigma to SNR_ISI (with nulled noise) | 10521 | % change SNR_ISI_XTK_normalized_1_sigma to SNR_ISI (with nulled noise) | ||
10732 | % Fix Rx calibration issue | 10522 | % Fix Rx calibration issue | ||
10733 | % added ERL limit and Nd | 10523 | % added ERL limit and Nd | ||
10734 | % r227 adding Pmax/Vf and peak of eq pulse, fixed issue with rx testing | 10524 | % r227 adding Pmax/Vf and peak of eq pulse, fixed issue with rx testing | ||
10735 | % INC_PACKAGE=0 not fully supported message | 10525 | % INC_PACKAGE=0 not fully supported message | ||
10736 | % if N=0 use TDR_duration | 10526 | % if N=0 use TDR_duration | ||
10737 | % red display text for fail ERL and COM | 10527 | % red display text for fail ERL and COM | ||
10738 | % r228 fixed ERL pass fail report, default Grr_limit to 1 | 10528 | % r228 fixed ERL pass fail report, default Grr_limit to 1 | ||
10739 | % r230 add rx ffe | 10529 | % r230 add rx ffe | ||
10740 | % r231 change crosstalk noise to icn like to speed things up | 10530 | % r231 change crosstalk noise to icn like to speed things up | ||
10741 | % r231 change default OP.impulse_response_truncation_threshold to 1e-3 from | 10531 | % r231 change default OP.impulse_response_truncation_threshold to 1e-3 from | ||
10742 | % 1e-5mof- | 10532 | % 1e-5mof- | ||
10743 | % r232 fix default for Rx eq so old spead sheets work | 10533 | % r232 fix default for Rx eq so old spead sheets work | ||
10744 | % r234 fix inadvertent typo for clause 120e ctle and problem with TXffe loop time reduction | 10534 | % r234 fix inadvertent typo for clause 120e ctle and problem with TXffe loop time reduction | ||
10745 | % r235 adding dfe quantization changed to normalized DFE taps reported | 10535 | % r235 adding dfe quantization changed to normalized DFE taps reported | ||
10746 | % r236 adding ffe gain loop and resample after RxFFE | 10536 | % r236 adding ffe gain loop and resample after RxFFE | ||
10747 | % r240 added output for C2M and setting defaults for some FFE eq | 10537 | % r240 added output for C2M and setting defaults for some FFE eq | ||
10748 | % r241 force FFE main cursor to 1 and remove sum of taps = 1 | 10538 | % r241 force FFE main cursor to 1 and remove sum of taps = 1 | ||
10749 | % r250 adding more complex package | 10539 | % r250 adding more complex package | ||
10750 | % r251 post cursor fix for DFE in force() and ffe backoff | 10540 | % r251 post cursor fix for DFE in force() and ffe backoff | ||
10751 | % r251 remove TDR threshold noise filter | 10541 | % r251 remove TDR threshold noise filter | ||
10752 | % r252 add rx FFE filter to receiver noise filter | 10542 | % r252 add rx FFE filter to receiver noise filter | ||
10753 | % r252 change ICN in the xtk noise calculation to end at fb rather than fb/2 | 10543 | % r252 change ICN in the xtk noise calculation to end at fb rather than fb/2 | ||
10754 | % r253 a few bug fixes in force from i indexing and for no ffe postcursors | 10544 | % r253 a few bug fixes in force from i indexing and for no ffe postcursors | ||
10755 | % r254 precursor check fix in optimize_fom % mod fix in force | 10545 | % r254 precursor check fix in optimize_fom % mod fix in force | ||
10756 | % r254 help to align columns in csv file | 10546 | % r254 help to align columns in csv file | ||
10757 | % r254 accept syntax for 2 tline flex package model | 10547 | % r254 accept syntax for 2 tline flex package model | ||
10758 | % r256 speed up optimize FOM | 10548 | % r256 speed up optimize FOM | ||
10759 | % r256 fix problem reading in config file from q/a | 10549 | % r256 fix problem reading in config file from q/a | ||
10760 | % r256 added code from Yasou Hidaka for reading in parameter an and printing out noise | 10550 | % r256 added code from Yasou Hidaka for reading in parameter an and printing out noise | ||
10761 | % r257 fixed extrapolation of channel with lower bandwidths in s21_to_impulse_DC | 10551 | % r257 fixed extrapolation of channel with lower bandwidths in s21_to_impulse_DC | ||
10762 | % r257 in get_xtlk_noise in optimize_FOM: reomove crosstalk double counting and apply TXFFE is FEXT | 10552 | % r257 in get_xtlk_noise in optimize_FOM: reomove crosstalk double counting and apply TXFFE is FEXT | ||
10763 | % r258 EXE_MODE switch 12/21 0:legacy 1:fast 2:superfast | 10553 | % r258 EXE_MODE switch 12/21 0:legacy 1:fast 2:superfast | ||
10764 | % r258 CDR switch 'MM' or 'mod-MM' | 10554 | % r258 CDR switch 'MM' or 'mod-MM' | ||
10765 | % r258 correction for asymentirc tx/Rx packages | 10555 | % r258 correction for asymentirc tx/Rx packages | ||
10766 | % r258 revamped display results display window | 10556 | % r258 revamped display results display window | ||
10767 | % r259 fix problem if Min_VEO is set in spreadsheet. | 10557 | % r259 fix problem if Min_VEO is set in spreadsheet. | ||
10768 | % r259 fix problem in optimize_FOM. get_xtlk_noise need to have 3 output | 10558 | % r259 fix problem in optimize_FOM. get_xtlk_noise need to have 3 output | ||
10769 | % parameter else only FEXT is considered for FOM.zhilei huang 01/11/2019 | 10559 | % parameter else only FEXT is considered for FOM.zhilei huang 01/11/2019 | ||
10770 | % r259 putting COM_db and IL last in output to terminal | 10560 | % r259 putting COM_db and IL last in output to terminal | ||
10771 | % r259 msgtext change to msg for C2C case other cases not vetted but not presently used | 10561 | % r259 msgtext change to msg for C2C case other cases not vetted but not presently used | ||
10772 | % r259 use N_bx for ERL rather than Nb (ndfe)) | 10562 | % r259 use N_bx for ERL rather than Nb (ndfe)) | ||
10773 | % r259 added TDR_W_TXPKG which performs TDR and ERL with the Tx package added | 10563 | % r259 added TDR_W_TXPKG which performs TDR and ERL with the Tx package added | ||
10774 | % r260 r259 used rd for the reciever to terminate the package. It was changed to the rd of the transmitter | 10564 | % r260 r259 used rd for the reciever to terminate the package. It was changed to the rd of the transmitter | ||
10775 | % r260 used eta_0 PSD equation for sigma_n | 10565 | % r260 used eta_0 PSD equation for sigma_n | ||
10776 | % r260 fix IL graph legend to w/pkg and Tr | 10566 | % r260 fix IL graph legend to w/pkg and Tr | ||
10777 | % r260 define tfx for each port | 10567 | % r260 define tfx for each port | ||
10778 | % r262 fx parameter passing parsing for mod_string revert to 2.57 no COM computational impact | 10568 | % r262 fx parameter passing parsing for mod_string revert to 2.57 no COM computational impact | ||
10779 | % r262 Report estimate for DER for channel (Yasuo 2/30/19) | 10569 | % r262 Report estimate for DER for channel (Yasuo 2/30/19) | ||
10780 | % r262 reset on exit default text interpreter to tex | 10570 | % r262 reset on exit default text interpreter to tex | ||
10781 | % r262 localize run timer (John Buck 1/17/19) | 10571 | % r262 localize run timer (John Buck 1/17/19) | ||
10782 | % r262 set db as internal function in force to avoid tool box | 10572 | % r262 set db as internal function in force to avoid tool box | ||
10783 | % r262 changed loop for Grr and Gloss in get_tdr so that nbx and tfx works when beta x = 0 | 10573 | % r262 changed loop for Grr and Gloss in get_tdr so that nbx and tfx works when beta x = 0 | ||
10784 | % r263 added to output_args RL structure and report "struct" in csv file | 10574 | % r263 added to output_args RL structure and report "struct" in csv file | ||
10785 | % r264 added EW estimate | 10575 | % r264 added EW estimate | ||
10786 | % r266 using unequalized IR for Vf and Vf to compute ratio of Vp/Vf | 10576 | % r266 using unequalized IR for Vf and Vf to compute ratio of Vp/Vf | ||
10787 | % r267 added floating taps with param.N_bf, param.N_bg, param.N_bmax, param.bmaxg. groups not used for ERL | 10577 | % r267 added floating taps with param.N_bf, param.N_bg, param.N_bmax, param.bmaxg. groups not used for ERL | ||
10788 | % r268 added sequential/co-optimization switch for floating tap banks OP.FT_COOP default 0 i.e. sequential | 10578 | % r268 added sequential/co-optimization switch for floating tap banks OP.FT_COOP default 0 i.e. sequential | ||
10789 | % r269 changed param.N_bmax to param.N_f | 10579 | % r269 changed param.N_bmax to param.N_f | ||
10790 | % r270 implement JingBo Li's and Howard Heck's floating tap method | 10580 | % r270 implement JingBo Li's and Howard Heck's floating tap method | ||
10791 | % r270 modification by Adam Healey for Ls and Cb termination (aka t-coil emulation) | 10581 | % r270 modification by Adam Healey for Ls and Cb termination (aka t-coil emulation) | ||
10792 | % r270 added c_0 and c_1 for CA in add_brd | 10582 | % r270 added c_0 and c_1 for CA in add_brd | ||
10793 | % r272 fixed version syntax problem in output_args RL report | 10583 | % r272 fixed version syntax problem in output_args RL report | ||
10794 | % r272 fixed eye width computation problem crosstalk was missed in pervious versions | 10584 | % r272 fixed eye width computation problem crosstalk was missed in pervious versions | ||
10795 | % r272 removed eye width report if doing a Rx calibration | 10585 | % r272 removed eye width report if doing a Rx calibration | ||
10796 | % r273 better alignment and control for ICN reporting | 10586 | % r273 better alignment and control for ICN reporting | ||
10797 | % r273 fixed PSXTK graph | 10587 | % r273 fixed PSXTK graph | ||
10798 | % r275 fixed delay adjustment for ERL/TDR in get_TDR (Adam Healey 09/06/2019) | 10588 | % r275 fixed delay adjustment for ERL/TDR in get_TDR (Adam Healey 09/06/2019) | ||
10799 | % r276 go back to reporting channel IL results (output_args.IL_dB_channel_only_at_Fnq) with board added read_s4p_files (as in r270) | 10589 | % r276 go back to reporting channel IL results (output_args.IL_dB_channel_only_at_Fnq) with board added read_s4p_files (as in r270) | ||
10800 | % r276 chdata(i).Aicn=param.a_icn_fext should have been chdata(i).Aicn=param.a_icn_next for the next selection. Since in most spec's they are the same there is little no impact in results | 10590 | % r276 chdata(i).Aicn=param.a_icn_fext should have been chdata(i).Aicn=param.a_icn_next for the next selection. Since in most spec's they are the same there is little no impact in results | ||
10801 | % r276 test for output_args for isfield(chdata(1),'sdd22_raw') | 10591 | % r276 test for output_args for isfield(chdata(1),'sdd22_raw') | ||
10802 | % r276 change divisor for ICN and FOM_ILD to param.f2 from param.fb, may raise ICN and ILD value reported in r275 | 10592 | % r276 change divisor for ICN and FOM_ILD to param.f2 from param.fb, may raise ICN and ILD value reported in r275 | ||
10803 | % r276 C_1 was instantiated as C_0. This was fixed | 10593 | % r276 C_1 was instantiated as C_0. This was fixed | ||
10804 | % r276 fixed rounding problem in reporting of loss at f_nq | 10594 | % r276 fixed rounding problem in reporting of loss at f_nq | ||
10805 | % r276 power limit (RSS) for tail DFE taps (B_float_RSS_MAX, N_tail_start) | 10595 | % r276 power limit (RSS) for tail DFE taps (B_float_RSS_MAX, N_tail_start) | ||
10806 | % r277 added nv for deterining steady state voltage for fitting compatibility | 10596 | % r277 added nv for deterining steady state voltage for fitting compatibility | ||
10807 | % r278 added b_min to support asymmetric bmax | 10597 | % r278 added b_min to support asymmetric bmax | ||
10808 | % r278 added kappa1 and kappa2 to scale package to channel reflection for ERL experiments | 10598 | % r278 added kappa1 and kappa2 to scale package to channel reflection for ERL experiments | ||
10809 | % r278 added keyword OP.SHOW_BRD which includes added board in TDR and ERL | 10599 | % r278 added keyword OP.SHOW_BRD which includes added board in TDR and ERL | ||
10810 | % r292 speed up for FOM search (Adee Ran) implemented by Adam Gregory. | 10600 | % r292 speed up for FOM search (Adee Ran) implemented by Adam Gregory. | ||
10811 | % r292 param.LOCAL_SEARCH set to is the heuristic step distance keyword is 'Local Search' | 10601 | % r292 param.LOCAL_SEARCH set to is the heuristic step distance keyword is 'Local Search' | ||
10812 | % r292 fixing TDR for different impedance references in get_TDR and s2p file compatibility | 10602 | % r292 fixing TDR for different impedance references in get_TDR and s2p file compatibility | ||
10813 | % r292 eq. 93A-19 and 93-20 code implementation bug when include .3by change% to fix edge rate equation 93A-46 (h_T). no effect if Rd=50 or IL > 5 dB | 10603 | % r292 eq. 93A-19 and 93-20 code implementation bug when include .3by change% to fix edge rate equation 93A-46 (h_T). no effect if Rd=50 or IL > 5 dB | ||
10814 | % r292 H_t implemented in s21_pkg | 10604 | % r292 H_t implemented in s21_pkg | ||
10815 | % r292 plot and report for die to die IL remove the Tr effect "IL with pkgs & Tr filter" goes to "IL with pkgs" | 10605 | % r292 plot and report for die to die IL remove the Tr effect "IL with pkgs & Tr filter" goes to "IL with pkgs" | ||
10816 | % r292 add GDC_MIN to optimize_FOM | 10606 | % r292 add GDC_MIN to optimize_FOM | ||
10817 | % r293 fix if ndfe-0 and ERL only and s2p issue | 10607 | % r293 fix if ndfe-0 and ERL only and s2p issue | ||
10818 | % r293a investigate the Tukey filtering | 10608 | % r293a investigate the Tukey filtering | ||
10819 | % r293a if fix if bmin is missing | 10609 | % r293a if fix if bmin is missing | ||
10820 | % r294 fix problems reading s2p files for ERL computation | 10610 | % r294 fix problems reading s2p files for ERL computation | ||
10821 | % r294 align Tukey_Window with .3ck definition for ERL and TDR computations | 10611 | % r294 align Tukey_Window with .3ck definition for ERL and TDR computations | ||
10822 | % r294 add parameter param.Noise_Crest_Factor. Default is not to use | 10612 | % r294 add parameter param.Noise_Crest_Factor. Default is not to use | ||
10823 | % r294 add gdc and gdc2 range limitations | 10613 | % r294 add gdc and gdc2 range limitations | ||
10824 | % r295 add VEC Pass threshold | 10614 | % r295 add VEC Pass threshold | ||
10825 | % r295 removed close force all. Tagged all figures with "COM" | 10615 | % r295 removed close force all. Tagged all figures with "COM" | ||
10826 | % r295 consolidated print in new function "end_display_control" | 10616 | % r295 consolidated print in new function "end_display_control" | ||
10827 | % r295 report pre/pmax for Txffe | 10617 | % r295 report pre/pmax for Txffe | ||
10828 | % r295 speed up test cases by not re-reading in s4p files | 10618 | % r295 speed up test cases by not re-reading in s4p files | ||
10829 | % r297 add provisions for AC_CM_RMS for through CM (experimental) | 10619 | % r297 add provisions for AC_CM_RMS for through CM (experimental) | ||
10830 | % r299 add keyword T_O (param.T_O) and samples_for_C2M (parsm.samples_for_C2M) for new C2M VEC and EH computations | 10620 | % r299 add keyword T_O (param.T_O) and samples_for_C2M (parsm.samples_for_C2M) for new C2M VEC and EH computations | ||
10831 | % r310 refine VEC and EH for C2M from Adam Gregory in | 10621 | % r310 refine VEC and EH for C2M from Adam Gregory in | ||
10832 | % r315 added keyword for Bessel_Thomson and Butterworth(default) filter. | 10622 | % r315 added keyword for Bessel_Thomson and Butterworth(default) filter. | ||
10833 | % cdf_to_ber_contour,COM_eye_width,combine_pdf_same_voltage_axis, | 10623 | % cdf_to_ber_contour,COM_eye_width,combine_pdf_same_voltage_axis, | ||
10834 | % optimize_fom_for_C2M. pdf_to_cdf, conv_fct_MeanNotZero, and get_pdf_full | 10624 | % optimize_fom_for_C2M. pdf_to_cdf, conv_fct_MeanNotZero, and get_pdf_full | ||
10835 | % r311 added RILN | 10625 | % r311 added RILN | ||
10836 | % r314 when T_O is not zero 3 eyes are used to compute VEC and VEO | 10626 | % r314 when T_O is not zero 3 eyes are used to compute VEC and VEO | ||
10837 | % r315 Bessel_Thomson keyword is added mostly for measuring Pmax, Vf, and SNDR | 10627 | % r315 Bessel_Thomson keyword is added mostly for measuring Pmax, Vf, and SNDR | ||
10838 | % r316 remove DC computation for RX Calibration loops | 10628 | % r316 remove DC computation for RX Calibration loops | ||
10839 | % r317 for SAVE_TD to include EQ and unEQ FIR | 10629 | % r317 for SAVE_TD to include EQ and unEQ FIR | ||
10840 | % r317 clean up bessel thomson and butterworth filter logic for ERL and normal COM | 10630 | % r317 clean up bessel thomson and butterworth filter logic for ERL and normal COM | ||
10841 | % r318 if min_VEO_test fails to find a solution the loop is restarted with min_VEO_test to near zero. Makes sure COM returns results | 10631 | % r318 if min_VEO_test fails to find a solution the loop is restarted with min_VEO_test to near zero. Makes sure COM returns results | ||
10842 | % r320 fixed RX_CALIBRATION which was broken in r310 | 10632 | % r320 fixed RX_CALIBRATION which was broken in r310 | ||
10843 | % r320 speed up for C2M by moving managing optimize loop distribution of computations | 10633 | % r320 speed up for C2M by moving managing optimize loop distribution of computations | ||
10844 | % r320 for C2M added Gaussian window keyword, Gaussian_histogram_window, for T_O and keyword, QL which is at Q limit at +/-T_O | 10634 | % r320 for C2M added Gaussian window keyword, Gaussian_histogram_window, for T_O and keyword, QL which is at Q limit at +/-T_O | ||
10845 | % r320 removed external feature and replace with TDMODE | 10635 | % r320 removed external feature and replace with TDMODE | ||
10846 | % r320 added TDMODE which allows for the use of pulse resonance files (CSV) instead of s4p files | 10636 | % r320 added TDMODE which allows for the use of pulse resonance files (CSV) instead of s4p files | ||
10847 | % r330 changed FOM ILN to use a complex fit and compute FOM_ILN in the time domain330 added tfx to N for ERL | 10637 | % r330 changed FOM ILN to use a complex fit and compute FOM_ILN in the time domain330 added tfx to N for ERL | ||
10848 | % r335 fixed typo in when processing the bessel thompson filter option | 10638 | % r335 fixed typo in when processing the bessel thompson filter option | ||
10849 | % r335 process in CD mode instead of DC mode to get CM noise at Rx | 10639 | % r335 process in CD mode instead of DC mode to get CM noise at Rx | ||
10850 | % r335 compute and report CD_CM_RMS | 10640 | % r335 compute and report CD_CM_RMS | ||
10851 | % r335 fixed where output_arg is save i.e. move to end | 10641 | % r335 fixed where output_arg is save i.e. move to end | ||
10852 | % r335 refine interp_Sparam to do zero fill instead of extrapolation | 10642 | % r335 refine interp_Sparam to do zero fill instead of extrapolation | ||
10853 | % r335 change raw IL plot to not include boards | 10643 | % r335 change raw IL plot to not include boards | ||
10854 | % r335 set T_0 to zero if not C2M | 10644 | % r335 set T_0 to zero if not C2M | ||
10855 | % r335 change for s parameter interp: check fit sigma, if not OK zero fill | 10645 | % r335 change for s parameter interp: check fit sigma, if not OK zero fill | ||
10856 | % r335 added actual sdd12 (instead fo mirroring sdd21) to s21_pkg and 21dc_pkg and read_s4p_files | 10646 | % r335 added actual sdd12 (instead fo mirroring sdd21) to s21_pkg and 21dc_pkg and read_s4p_files | ||
10857 | % r335 TD_RILN changes from Hansel Dsilva | 10647 | % r335 TD_RILN changes from Hansel Dsilva | ||
10858 | % r335 Fixed sigma_N for RxFFE | 10648 | % r335 Fixed sigma_N for RxFFE | ||
10859 | % r335 added more to self documenting keyword capability from read_ParamConfigFile and xls_parameter routines | 10649 | % r335 added more to self documenting keyword capability from read_ParamConfigFile and xls_parameter routines | ||
10860 | % r335 added c(2) and C(3) back to read_ParamConfigFile | 10650 | % r335 added c(2) and C(3) back to read_ParamConfigFile | ||
10861 | % r335 Optimize_loop_speed_up keyword option added. Mostly speeds up c2m(vsr) | 10651 | % r335 Optimize_loop_speed_up keyword option added. Mostly speeds up c2m(vsr) | ||
10862 | % r335 corrected GDC_MIN per 0.3ck D2.3 | 10652 | % r335 corrected GDC_MIN per 0.3ck D2.3 | ||
10863 | % r335 sigma_r replaces Qr which replaced QL for Gaussian histogram window | 10653 | % r335 sigma_r replaces Qr which replaced QL for Gaussian histogram window | ||
10864 | % r340 fix for when post cursor taps 2 and 3 are used (from Matt Brown) | 10654 | % r340 fix for when post cursor taps 2 and 3 are used (from Matt Brown) | ||
10865 | % r370 speed up | 10655 | % r370 speed up | ||
10866 | % r370 fix for floating tap missing locations | 10656 | % r370 fix for floating tap missing locations | ||
10867 | % r370 variable Tx FFE taps | 10657 | % r370 variable Tx FFE taps | ||
10868 | % r370 package die load with ladder circuit | 10658 | % r370 package die load with ladder circuit | ||
10869 | % r370 mods for SNDR_tx exporation using keyword SNR_TXwC0 | 10659 | % r370 mods for SNDR_tx exporation using keyword SNR_TXwC0 | ||
10870 | % r380 fix for Rx Calibaration (error introduced going from 3.4 to 3.7) | 10660 | % r380 fix for Rx Calibaration (error introduced going from 3.4 to 3.7) | ||
10871 | % r380 added capabablity to enable a raised cosine Rx filter0 | 10661 | % r380 added capabablity to enable a raised cosine Rx filter0 | ||
10872 | % r380 keyword added: RC_Start, RC_end, Raised_Cosine | 10662 | % r380 keyword added: RC_Start, RC_end, Raised_Cosine | ||
10873 | % r380 added plot for VTF | 10663 | % r380 added plot for VTF | ||
10874 | % r385 added capability for additional Tx FFE per package | 10664 | % r385 added capability for additional Tx FFE per package | ||
10875 | % r385 keyword added: PKG_Tx_FFE_preset default is 0 i.e. noop | 10665 | % r385 keyword added: PKG_Tx_FFE_preset default is 0 i.e. noop | ||
10876 | % r385 SAVE_CONFIG2MAT set to 0 as default i.e. don't create a conifig mat file( | 10666 | % r385 SAVE_CONFIG2MAT set to 0 as default i.e. don't create a conifig mat file( | ||
10877 | % r388 Adjusted Rx caliberation for CL 162 i.e. adding Tx noise (sigma hn) instead of Rx noise line | 10667 | % r388 Adjusted Rx caliberation for CL 162 i.e. adding Tx noise (sigma hn) instead of Rx noise line | ||
10878 | % r389 Improvement by A. Ran for reporting loss at Nq | 10668 | % r389 Improvement by A. Ran for reporting loss at Nq | ||
10879 | % r389 Fixed typo: changed VIM to VMP | 10669 | % r389 Fixed typo: changed VIM to VMP | ||
10880 | % r400 fixed PR with zero pad extension | 10670 | % r400 fixed PR with zero pad extension | ||
10881 | % r400 keyword MLSE and SNRADJ_EQUA for future work | 10671 | % r400 keyword MLSE and SNRADJ_EQUA for future work | ||
10882 | % r400 replaced function db with instances of 20*log10(abs(...)) | 10672 | % r400 replaced function db with instances of 20*log10(abs(...)) | ||
10883 | % r410 widen voltage distriution for normal_dist doubled max Q | 10673 | % r410 widen voltage distriution for normal_dist doubled max Q | ||
10884 | % r410 improve reading in of config files | 10674 | % r410 improve reading in of config files | ||
10885 | % r410 renormalize s-parameter if not 50 ohm ref | 10675 | % r410 renormalize s-parameter if not 50 ohm ref | ||
10886 | % r410 reference for RXFFE changed to MM from UI+zero first precursor | 10676 | % r410 reference for RXFFE changed to MM from UI+zero first precursor | ||
10887 | % r410 remove RL from output_args bc not need and too much storage allocation | 10677 | % r410 remove RL from output_args bc not need and too much storage allocation | ||
10888 | % r410 s21^2 changed to s12*s21 in s21_pkg. Corrected VTF needed for non-passive sparameters | 10678 | % r410 s21^2 changed to s12*s21 in s21_pkg. Corrected VTF needed for non-passive sparameters | ||
10889 | % r420 updated equalization figures. if Rxffe is use a subplot of Rx FFE taps is graphed | 10679 | % r420 updated equalization figures. if Rxffe is use a subplot of Rx FFE taps is graphed | ||
10890 | % r420 updated equalization figures. Now separate per pkg case in optimize_fom | 10680 | % r420 updated equalization figures. Now separate per pkg case in optimize_fom | ||
10891 | % r420 updade force to account for pulse responces with short delays in force | 10681 | % r420 updade force to account for pulse responces with short delays in force | ||
10892 | % r420 added Tx/Rx p/n skew with keywords Txpskew, Txnskew, Rxpskew, Pxnskew | 10682 | % r420 added Tx/Rx p/n skew with keywords Txpskew, Txnskew, Rxpskew, Pxnskew | ||
10893 | % r420 add common mode outputs: VMC_H_mV and SCMR_dB from CDF of CD PR and DD PR | 10683 | % r420 add common mode outputs: VMC_H_mV and SCMR_dB from CDF of CD PR and DD PR | ||
10894 | % r420 fixed and added control for RXFFE_TAP_CONSTRAINT and RXFFE_FLOAT_CTL | 10684 | % r420 fixed and added control for RXFFE_TAP_CONSTRAINT and RXFFE_FLOAT_CTL | ||
10895 | % r420 Wiener-Kofp MMSE optimization for RxFFE | 10685 | % r420 Wiener-Kofp MMSE optimization for RxFFE | ||
10896 | % r430 first pass at healey_3dj_01_2401 | 10686 | % r430 first pass at healey_3dj_01_2401 | ||
10897 | % r430 RxFFE fixed taps | 10687 | % r430 RxFFE fixed taps | ||
10898 | % r440 RxffE fixed tap index corrections and floating taps | 10688 | % r440 RxffE fixed tap index corrections and floating taps | ||
10899 | % r440 first pass implemenation of MLSE U3 | 10689 | % r440 first pass implemenation of MLSE U3 | ||
10900 | 10690 |