-
Notifications
You must be signed in to change notification settings - Fork 11
/
read_touchstone.m
150 lines (139 loc) · 4.74 KB
/
read_touchstone.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
function [type,freq,data,ref,comment]=read_touchstone( filename )
% [type,freq,data,ref]=read_touchstone( filename ) - read touchstone-file
% type (lowercase) 'z' for Z-Parameter touchstone-file
% freq vector of frequencies (in Hz)
% data (numports x numports x numfreq) matrix
% filename filename of the file to read
% ref reference impedance
% comment cell array of comment lines
%
% Version 16. Jun 2010
% 18. Aug 2010: comment lines
% 1. Sep 2010: BUGFIX: two-port files had S12 and S21 swapped!!!!!
% ATTENTION: higher than two-ports must be validated again!!!!!!!!!1
[fid, message] = fopen( filename, 'rt' );
if fid == -1
error( message );
end
comment = {};
% constants
DB = 0;
MA = 1;
RI = 2;
% number of ports (extract extension)
temp = lower(filename);
k = strfind(temp,'.');
if isempty(k)
error( 'filename has no extension' );
end
last_dot = k(length(k));
if length(temp) <= k
error( 'filename ends with "."' );
end
extension = temp(last_dot+1:length(temp));
if (lower(extension(1)) ~= 's') && (lower(extension(length(extension))) ~= 'p')
error( 'filename must have an extension like .s2p' );
end
num_ports = str2double(extension(2:length(extension)-1));
parameters_found = 0;
freq_nr = 1;
tline = fgetl(fid);
while ischar(tline)
tline = strtrim(tline);
if isempty(tline) || (tline(1) == '!')
% comment
if ~isempty(tline)
comment{end+1} = tline;
end
tline = fgetl(fid);
continue
end
if tline(1) == '#'
% found parameters
if parameters_found == 1
warning( 'additional parameter line found; expect garbage!' );
end
parameters_found = 1;
% parse parameters
[~,remain] = strtok(tline); % token is now '#'
[token,remain] = strtok(remain); % token is now the unit
unit = lower(token);
if strcmp(unit,'hz')
freq_mul = 1;
elseif strcmp(unit,'khz')
freq_mul = 1e3;
elseif strcmp(unit,'mhz')
freq_mul = 1e6;
elseif strcmp(unit,'ghz')
freq_mul = 1e9;
else
error( ['wrong unit: "' token '"'] );
end
[token,remain] = strtok(remain); % token is now the parameter type
type = lower(token);
[token,remain] = strtok(remain); % token is now the complex format
format = lower(token);
if strcmp(format,'ri')
format = RI;
elseif strcmp(format,'ma')
format = MA;
elseif strcmp(format,'db')
format = DB;
else
error( ['wrong complex format: "' format '"'] );
end
[token,remain] = strtok(remain); % token must be 'R'
if lower(token) ~= 'r'
error( 'incorrect file format' );
end
token = strtok(remain); % token is reference impedance
ref = str2double(token);
tline = fgetl(fid);
continue
end
% read data
clear 'cell_array';
cell_array = split( tline );
while length(cell_array) < 2*num_ports^2 + 1
temp_tline = fgetl(fid); %FIXME comments? empty lines?
cell_array = [cell_array,split( temp_tline )];
end
% now we have (at least) num_values values in cell_array
temp_freq = str2double(cell_array(1)) * freq_mul;
temp_data = zeros(num_ports);
for source = 1:num_ports
for dest = 1:num_ports
if num_ports ~= 2
pos = ((source-1)*num_ports + dest)*2;
else
% special file format for two-ports
pos = ((source-1)*2 + dest)*2;
end
if format == RI
temp_data(dest,source) = str2double(cell_array(pos)) + 1i*str2double(cell_array(pos+1));
elseif format == MA
temp_data(dest,source) = str2double(cell_array(pos)) * exp(1i*str2double(cell_array(pos+1))/180*pi);
%disp( [tline ' ### freq: ' num2str(temp_freq/1e9) ' S' num2str(source) num2str(dest) ' ' num2str(temp_data(dest,source))] );
%disp( ['pos: ' num2str(pos) ' cell_array: ' char(cell_array(pos))] );
elseif format == DB
temp_data(dest,source) = 10^(str2double(cell_array(pos))/20) * exp(1i*str2double(cell_array(pos+1))/180*pi);
end
end
end
% values are parsed, insert them into the freq and data arrays
freq(freq_nr) = temp_freq;
data(:,:,freq_nr) = temp_data;
freq_nr = freq_nr + 1;
% disp( ['frequency f=' num2str(temp_freq/1e9)] );
tline = fgetl(fid);
end
fclose( fid );
end %read_touchstone()
function cell_array=split( str )
cell_array = cell(0);
[token,remain] = strtok(str);
while ~isempty(token)
cell_array = [cell_array token];
[token,remain] = strtok(remain);
end
end