libsidplayfp  1.5.3
Integrator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2004, 2010 Dag Lem <resid@nimrod.no>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INTEGRATOR_H
24 #define INTEGRATOR_H
25 
26 #include <stdint.h>
27 #include <cassert>
28 
29 #include "siddefs-fp.h"
30 
31 namespace reSIDfp
32 {
33 
153 {
154 private:
155  unsigned int Vddt_Vw_2;
156  const unsigned short kVddt, n_snake;
157  int vx, vc;
158  const unsigned short* vcr_kVg;
159  const unsigned short* vcr_n_Ids_term;
160  const unsigned short* opamp_rev;
161 
162 public:
163  Integrator(const unsigned short* vcr_kVg, const unsigned short* vcr_n_Ids_term,
164  const unsigned short* opamp_rev, unsigned short kVddt, unsigned short n_snake) :
165  Vddt_Vw_2(0),
166  kVddt(kVddt),
167  n_snake(n_snake),
168  vx(0),
169  vc(0),
170  vcr_kVg(vcr_kVg),
171  vcr_n_Ids_term(vcr_n_Ids_term),
172  opamp_rev(opamp_rev) {}
173 
174  void setVw(unsigned short Vw) { Vddt_Vw_2 = (kVddt - Vw) * (kVddt - Vw) >> 1; }
175 
176  int solve(int vi);
177 };
178 
179 } // namespace reSIDfp
180 
181 #if RESID_INLINING || defined(INTEGRATOR_CPP)
182 
183 namespace reSIDfp
184 {
185 
186 RESID_INLINE
187 int Integrator::solve(int vi)
188 {
189  // "Snake" voltages for triode mode calculation.
190  const unsigned int Vgst = kVddt - vx;
191  const unsigned int Vgdt = kVddt - vi;
192 
193  const unsigned int Vgst_2 = Vgst * Vgst;
194  const unsigned int Vgdt_2 = Vgdt * Vgdt;
195 
196  // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
197  const int n_I_snake = n_snake * (int(Vgst_2 - Vgdt_2) >> 15);
198 
199  // VCR gate voltage. // Scaled by m*2^16
200  // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
201  const int kVg = (int)vcr_kVg[(Vddt_Vw_2 + (Vgdt_2 >> 1)) >> 16];
202 
203  // VCR voltages for EKV model table lookup.
204  int Vgs = kVg - vx;
205  if (Vgs < 0) Vgs = 0;
206  assert(Vgs < (1 << 16));
207  int Vgd = kVg - vi;
208  if (Vgd < 0) Vgd = 0;
209  assert(Vgd < (1 << 16));
210 
211  // VCR current, scaled by m*2^15*2^15 = m*2^30
212  const int n_I_vcr = (int)(vcr_n_Ids_term[Vgs] - vcr_n_Ids_term[Vgd]) << 15;
213 
214  // Change in capacitor charge.
215  vc += n_I_snake + n_I_vcr;
216 
217  // vx = g(vc)
218  const int tmp = (vc >> 15) + (1 << 15);
219  assert(tmp < (1 << 16));
220  vx = opamp_rev[tmp];
221 
222  // Return vo.
223  return vx - (vc >> 14);
224 }
225 
226 } // namespace reSIDfp
227 
228 #endif
229 
230 #endif
Definition: Integrator.h:152