libsidplayfp  1.1.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 
43 {
44 private:
45  unsigned int Vddt_Vw_2;
46  int Vddt, n_snake, x;
47  int vc;
48  const unsigned short* vcr_Vg;
49  const unsigned short* vcr_n_Ids_term;
50  const int* opamp_rev;
51 
52 public:
53  Integrator(const unsigned short* vcr_Vg, const unsigned short* vcr_n_Ids_term,
54  const int* opamp_rev, int Vddt, int n_snake) :
55  Vddt_Vw_2(0),
56  Vddt(Vddt),
57  n_snake(n_snake),
58  x(0),
59  vc(0),
60  vcr_Vg(vcr_Vg),
61  vcr_n_Ids_term(vcr_n_Ids_term),
62  opamp_rev(opamp_rev) {}
63 
64  void setVw(const int Vw) { Vddt_Vw_2 = (Vddt - Vw) * (Vddt - Vw) >> 1; }
65 
66  int solve(const int vi);
67 };
68 
69 } // namespace reSIDfp
70 
71 #if RESID_INLINING || defined(INTEGRATOR_CPP)
72 
73 namespace reSIDfp
74 {
75 
76 RESID_INLINE
77 int Integrator::solve(int vi)
78 {
79  // "Snake" voltages for triode mode calculation.
80  const int Vgst = Vddt - x;
81  const int Vgdt = Vddt - vi;
82 
83  const uint64_t Vgst_2 = (int64_t)Vgst * (int64_t)Vgst;
84  const uint64_t Vgdt_2 = (int64_t)Vgdt * (int64_t)Vgdt;
85 
86  // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
87  const int n_I_snake = n_snake * ((Vgst_2 >> 15) - (Vgdt_2 >> 15));
88 
89  // VCR gate voltage. // Scaled by m*2^16
90  // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
91  const int Vg = (int)vcr_Vg[(Vddt_Vw_2 >> 16) + (Vgdt_2 >> 17)];
92 
93  // VCR voltages for EKV model table lookup.
94  const int Vgs = Vg > x ? Vg - x : 0;
95  const int Vgd = Vg > vi ? Vg - vi : 0;
96 
97  // VCR current, scaled by m*2^15*2^15 = m*2^30
98  const int n_I_vcr = (int)(vcr_n_Ids_term[Vgs & 0xffff] - vcr_n_Ids_term[Vgd & 0xffff]) << 15;
99 
100  // Change in capacitor charge.
101  vc += n_I_snake + n_I_vcr;
102 
103  // vx = g(vc)
104  x = opamp_rev[((vc >> 15) + (1 << 15)) & 0xffff];
105 
106  // Return vo.
107  return x - (vc >> 14);
108 }
109 
110 } // namespace reSIDfp
111 
112 #endif
113 
114 #endif