libsidplayfp  0.3.5
Integrator.h
1 #ifndef INTEGRATOR_H
2 #define INTEGRATOR_H
3 
4 #include "siddefs-fp.h"
5 
6 namespace reSIDfp
7 {
8 
18 class Integrator {
19 
20 private:
21  unsigned int Vddt_Vw_2;
22  int Vddt, n_snake, x;
23  int vc;
24  const unsigned short* vcr_Vg;
25  const unsigned short* vcr_n_Ids_term;
26  const int* opamp_rev;
27 
28 public:
29  Integrator(const unsigned short* vcr_Vg, const unsigned short* vcr_n_Ids_term,
30  const int* opamp_rev, const int Vddt, const int n_snake) :
31  Vddt_Vw_2(0),
32  Vddt(Vddt),
33  n_snake(n_snake),
34  x(0),
35  vc(0),
36  vcr_Vg(vcr_Vg),
37  vcr_n_Ids_term(vcr_n_Ids_term),
38  opamp_rev(opamp_rev) {}
39 
40  void setVw(const int Vw);
41 
42  int solve(const int vi);
43 };
44 
45 } // namespace reSIDfp
46 
47 #if RESID_INLINING || defined(INTEGRATOR_CPP)
48 
49 namespace reSIDfp
50 {
51 
52 RESID_INLINE
53 int Integrator::solve(const int vi) {
54  // "Snake" voltages for triode mode calculation.
55  const int Vgst = Vddt - x;
56  const int Vgdt = Vddt - vi;
57  const unsigned int Vgst_2 = Vgst*Vgst;
58  const unsigned int Vgdt_2 = Vgdt*Vgdt;
59 
60  // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
61  const int n_I_snake = n_snake*((Vgst_2 >> 15) - (Vgdt_2 >> 15));
62 
63  // VCR gate voltage. // Scaled by m*2^16
64  // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
65  const int Vg = (int)vcr_Vg[(Vddt_Vw_2 >> 16) + (Vgdt_2 >> 17)];
66 
67  // VCR voltages for EKV model table lookup.
68  const int Vgs = Vg > x ? Vg - x : 0;
69  const int Vgd = Vg > vi ? Vg - vi : 0;
70 
71  // VCR current, scaled by m*2^15*2^15 = m*2^30
72  const int n_I_vcr = (int)(vcr_n_Ids_term[Vgs & 0xffff] - vcr_n_Ids_term[Vgd & 0xffff]) << 15;
73 
74  // Change in capacitor charge.
75  vc += n_I_snake + n_I_vcr;
76 
77  // vx = g(vc)
78  x = opamp_rev[((vc >> 15) + (1 << 15)) & 0xffff];
79 
80  // Return vo.
81  return x - (vc >> 14);
82 }
83 
84 } // namespace reSIDfp
85 
86 #endif
87 
88 #endif