forked from ggventurini/python-deltasigma
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLCparam2tf.m
executable file
·163 lines (157 loc) · 5.14 KB
/
LCparam2tf.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
151
152
153
154
155
156
157
158
159
160
161
162
163
function [H,L0,ABCD,k]=LCparam2tf(param,k)
%[H,L0,ABCD,k]=LCparam2tf(param,k=1)
%Compute the transfer functions (and the Q. gain, k) of an LC modulator.
%
%Arguments
% param A struct containing the following fields (all normalized):
% l The inductances in each tank.
% c The capacitances in each tank.
% gu The transconductance from the u input to each of the tanks.
% The final term is the voltage gain to the comparator input.
% Default = [1 0 .. ]. (1 by n+1)
% gv The transconductance from the v output to each of the tanks.
% (1 by n+1).
% gw The inter-stage transconductances.
% Default = [1 1 .. ]. (1 by n-1)
% gx The gains from the top of each tank resistor to the comparator.
% Default = [0 0 .. 1]. (1 by n)
% rx The resistances inserted between the output of each interstage
% transconductance and the top of each tank.
% Default = [0 ..]. (1 by n) Note that rx(1) is not used.
% t A two-element vector containing the start and end times of the feedback
% waveform.
% Default = [0 1].
% rl The series resistance of each inductor.
% Default = [0 ..]. (1 by n)
% gc The parallel conductances of each tank.
% Default = [0 ..]. (1 by n)
%
% k The value to assume for the quantizer gain. If k is omitted or if
% k is defaulted, k is taken to be 1.
% If k is 0, a value is computed by the formula
% k = mean(abs(y))/mean(y.^2), where y is the quantizer input
% sequence when the modulator is fed with a small input at f0.
%
%Output
% H The closed-loop noise transfer function (in z).
% L0 The open-loop tf (in s) from u to v. G may be evaluated
% using evalContSTF(L0,H,f).
% k The value of the quantizer gain used to compute the above tfs.
% ABCD The state-space description of the discrete-time system
%
%For the conversion from continuous to discrete time, corrections to the
%standard MATLAB formulae need to be applied in order for the sampled-data
%value to be taken at the END of the time interval.
%This effectively makes t1>0 and requires corrections if t2>=1 and gv(n+1)~=0.
%More complex formulae are needed for t2>=1, so for the moment this code
%requires t2<1.
l = param.l;
c = param.c;
f0 = mean(1 ./ sqrt(l.*c)) / (2*pi);
n = length(l);
%Handle the input arguments and their defaults
% !! isempty() must be first because when k=[] isnan returns [] and this
% !! makes the whole expression []
if nargin<2 | isempty(k) | isnan(k)
k = 1;
end
if any(strcmp(fieldnames(param),'gu')) & ~isempty(param.gu) & ~isnan(param.gu)
gu = param.gu;
else
gu = [1 zeros(1,n)];
end
gu = padr(gu,n+1,0); % Pad out with zeros, if needed.
gv = padr(param.gv,n+1,0); % Pad out with zeros, if needed.
if any(strcmp(fieldnames(param),'gw')) & ~isempty(param.gw) & ~isnan(param.gw)
gw = param.gw;
else
gw = ones(1,n-1);
end
if any(strcmp(fieldnames(param),'gx')) & ~isempty(param.gx) & ~isnan(param.gx)
gx = param.gx;
else
gx = [zeros(1,n-1) 1];
end
if any(strcmp(fieldnames(param),'rx')) & ~isempty(param.rx) & ~isnan(param.rx)
rx = param.rx;
if length(rx)==1;
rx = rx(ones(1,n));
end
else
rx = [zeros(1,n)];
end
if any(strcmp(fieldnames(param),'t')) & ~isempty(param.t) & ~isnan(param.t)
t = param.t;
else
t = [0 1];
end
if any(strcmp(fieldnames(param),'rl')) & ~isempty(param.rl) & ~isnan(param.rl)
rl = param.rl;
if length(rl)==1;
rl = rl(ones(1,n));
end
else
rl = [zeros(1,n)];
end
if any(strcmp(fieldnames(param),'gc')) & ~isempty(param.gc) & ~isnan(param.gc)
gc = param.gc;
if length(gc)==1;
gc = gc(ones(1,n));
end
else
gc = [zeros(1,n)];
end
% Form the state-space description of the modulator
% The states are ordered v1, i1, v2, i2 ...
n2 = 2*n;
ABc = zeros(n2,n2+2); CDc = zeros(1,n2+2);
for i = 1:n
i2 = 2*i-1;
% y represents the voltage at the top of the resistor stacked on the tank.
if i == 1
y = [ 1 zeros(1,n2+1) ];
else
ABc(i2,:) = gw(i-1)*y;
y = rx(i)*gw(i-1)*y; y(i2) = 1;
end
ABc(i2,n2+1:n2+2) = [gu(i) -gv(i)];
ABc(i2:i2+1,i2:i2+1) = [-gc(i) -1; 1 -rl(i)];
ABc(i2,:) = ABc(i2,:)/c(i);
ABc(i2+1,:) = ABc(i2+1,:)/l(i);
CDc = CDc + gx(i)*y;
end
CDc = CDc + [zeros(1,n2) gu(n+1) -gv(n+1)];
% THIS IS THE NEW CODE !!
[Ac,Bc,Cc,Dc] = partitionABCD([ABc;CDc], 2);
sys_c = ss( Ac, Bc(:,2), Cc, Dc(2) );
sys = mapCtoD(sys_c,t,f0);
% Augment the input matrix.
A=sys.a;
B=[padb(Bc(:,1),size(sys.b,1)) sys.b];
C=sys.c;
D=[Dc(1) sys.d];
% Compute L0; use the LC parameters to compute the poles and thereby
% ensure exact agreement with the zeros in H.
%!! THIS IS GOING TO NEED FIXING
s_poles = zeros(1,2*n);
for i=1:n
s_poles(2*i-1:2*i) = roots([ l(i)*c(i) ( rl(i)*c(i) + gc(i)*l(i) ) 1+rl(i)*gc(i) ]);
end
LF0 = ss(Ac,Bc(:,1),Cc,Dc(1));
L0 = zpk( LF0 );
L0.p = s_poles;
% Compute H. Use the poles in L0 to compute the zeros in H.
ABCD =[A B; C D];
if k==0 % Estimate k by simulatiing the modulator with a small input
w0 = mean(1./sqrt(l.*c));
H = calculateTF(ABCD);
H.z = exp(s_poles);
stf0 = abs(evalTFP(L0,H,w0/(2*pi)));
u = 0.1/stf0*sin(w0*[0:10000]);
[tmp1,tmp2,tmp3,y] = simulateDSM(u,[A B; C D]);
k = mean(abs(y))/mean(y.^2);
end
H = calculateTF(ABCD,k);
H.z = exp(s_poles);
% Correct L0k to include the quantizer gain
L0.k = L0.k*k;