libsidplayfp  1.3.0
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 
28 #include "siddefs-fp.h"
29 
30 namespace reSIDfp
31 {
32 
152 {
153 private:
154  unsigned int Vddt_Vw_2;
155  int kVddt, n_snake, vx;
156  int vc;
157  const unsigned short* vcr_kVg;
158  const unsigned short* vcr_n_Ids_term;
159  const int* opamp_rev;
160 
161 public:
162  Integrator(const unsigned short* vcr_kVg, const unsigned short* vcr_n_Ids_term,
163  const int* opamp_rev, int kVddt, int n_snake) :
164  Vddt_Vw_2(0),
165  kVddt(kVddt),
166  n_snake(n_snake),
167  vx(0),
168  vc(0),
169  vcr_kVg(vcr_kVg),
170  vcr_n_Ids_term(vcr_n_Ids_term),
171  opamp_rev(opamp_rev) {}
172 
173  void setVw(unsigned int Vw) { Vddt_Vw_2 = (kVddt - Vw) * (kVddt - Vw) >> 1; }
174 
175  int solve(int vi);
176 };
177 
178 } // namespace reSIDfp
179 
180 #if RESID_INLINING || defined(INTEGRATOR_CPP)
181 
182 namespace reSIDfp
183 {
184 
185 RESID_INLINE
186 int Integrator::solve(int vi)
187 {
188  // "Snake" voltages for triode mode calculation.
189  const int Vgst = kVddt - vx;
190  const int Vgdt = kVddt - vi;
191 
192  const int64_t Vgst_2 = (int64_t)Vgst * (int64_t)Vgst;
193  const int64_t Vgdt_2 = (int64_t)Vgdt * (int64_t)Vgdt;
194 
195  // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
196  const int n_I_snake = n_snake * ((Vgst_2 - Vgdt_2) >> 15);
197 
198  // VCR gate voltage. // Scaled by m*2^16
199  // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
200  const int kVg = (int)vcr_kVg[(Vddt_Vw_2 + (Vgdt_2 >> 1)) >> 16];
201 
202  // VCR voltages for EKV model table lookup.
203  int Vgs = kVg - vx;
204  if (Vgs < 0) Vgs = 0;
205  int Vgd = kVg - vi;
206  if (Vgd < 0) Vgd = 0;
207 
208  // VCR current, scaled by m*2^15*2^15 = m*2^30
209  const int n_I_vcr = (int)(vcr_n_Ids_term[Vgs & 0xffff] - vcr_n_Ids_term[Vgd & 0xffff]) << 15;
210 
211  // Change in capacitor charge.
212  vc += n_I_snake + n_I_vcr;
213 
214  // vx = g(vc)
215  vx = opamp_rev[((vc >> 15) + (1 << 15)) & 0xffff];
216 
217  // Return vo.
218  return vx - (vc >> 14);
219 }
220 
221 } // namespace reSIDfp
222 
223 #endif
224 
225 #endif
Definition: Integrator.h:151