libsidplayfp  2.4.0
Integrator8580.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2022 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 INTEGRATOR8580_H
24 #define INTEGRATOR8580_H
25 
26 #include "FilterModelConfig8580.h"
27 
28 #include <stdint.h>
29 #include <cassert>
30 
31 #include "siddefs-fp.h"
32 
33 namespace reSIDfp
34 {
35 
55 {
56 private:
57  mutable int vx;
58  mutable int vc;
59 
60  unsigned short nVgt;
61  unsigned short n_dac;
62 
63  const FilterModelConfig8580* fmc;
64 
65 public:
67  vx(0),
68  vc(0),
69  fmc(fmc)
70  {
71  setV(1.5);
72  }
73 
77  void setFc(double wl)
78  {
79  // Normalized current factor, 1 cycle at 1MHz.
80  // Fit in 5 bits.
81  n_dac = fmc->getNormalizedCurrentFactor(wl);
82  }
83 
87  void setV(double v)
88  {
89  // Gate voltage is controlled by the switched capacitor voltage divider
90  // Ua = Ue * v = 4.76v 1<v<2
91  assert(v > 1.0 && v < 2.0);
92  const double Vg = fmc->getVoiceDCVoltage() * v;
93  const double Vgt = Vg - fmc->getVth();
94 
95  // Vg - Vth, normalized so that translated values can be subtracted:
96  // Vgt - x = (Vgt - t) - (x - t)
97  nVgt = fmc->getNormalizedValue(Vgt);
98  }
99 
100  int solve(int vi) const;
101 };
102 
103 } // namespace reSIDfp
104 
105 #if RESID_INLINING || defined(INTEGRATOR8580_CPP)
106 
107 namespace reSIDfp
108 {
109 
110 RESID_INLINE
111 int Integrator8580::solve(int vi) const
112 {
113  // Make sure we're not in subthreshold mode
114  assert(vx < nVgt);
115 
116  // DAC voltages
117  const unsigned int Vgst = nVgt - vx;
118  const unsigned int Vgdt = (vi < nVgt) ? nVgt - vi : 0; // triode/saturation mode
119 
120  const unsigned int Vgst_2 = Vgst * Vgst;
121  const unsigned int Vgdt_2 = Vgdt * Vgdt;
122 
123  // DAC current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
124  const int n_I_dac = n_dac * (static_cast<int>(Vgst_2 - Vgdt_2) >> 15);
125 
126  // Change in capacitor charge.
127  vc += n_I_dac;
128 
129  // vx = g(vc)
130  const int tmp = (vc >> 15) + (1 << 15);
131  assert(tmp < (1 << 16));
132  vx = fmc->getOpampRev(tmp);
133 
134  // Return vo.
135  return vx - (vc >> 14);
136 }
137 
138 } // namespace reSIDfp
139 
140 #endif
141 
142 #endif
Definition: FilterModelConfig8580.h:41
Definition: Integrator8580.h:55
void setFc(double wl)
Definition: Integrator8580.h:77
void setV(double v)
Definition: Integrator8580.h:87