libsidplayfp
1.0.3
|
00001 /* 00002 * This file is part of libsidplayfp, a SID player engine. 00003 * 00004 * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net> 00005 * Copyright 2007-2010 Antti Lankila 00006 * Copyright 2004, 2010 Dag Lem <resid@nimrod.no> 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef INTEGRATOR_H 00024 #define INTEGRATOR_H 00025 00026 #include <stdint.h> 00027 00028 #include "siddefs-fp.h" 00029 00030 namespace reSIDfp 00031 { 00032 00042 class Integrator 00043 { 00044 private: 00045 unsigned int Vddt_Vw_2; 00046 int Vddt, n_snake, x; 00047 int vc; 00048 const unsigned short* vcr_Vg; 00049 const unsigned short* vcr_n_Ids_term; 00050 const int* opamp_rev; 00051 00052 public: 00053 Integrator(const unsigned short* vcr_Vg, const unsigned short* vcr_n_Ids_term, 00054 const int* opamp_rev, int Vddt, int n_snake) : 00055 Vddt_Vw_2(0), 00056 Vddt(Vddt), 00057 n_snake(n_snake), 00058 x(0), 00059 vc(0), 00060 vcr_Vg(vcr_Vg), 00061 vcr_n_Ids_term(vcr_n_Ids_term), 00062 opamp_rev(opamp_rev) {} 00063 00064 void setVw(const int Vw) { Vddt_Vw_2 = (Vddt - Vw) * (Vddt - Vw) >> 1; } 00065 00066 int solve(const int vi); 00067 }; 00068 00069 } // namespace reSIDfp 00070 00071 #if RESID_INLINING || defined(INTEGRATOR_CPP) 00072 00073 namespace reSIDfp 00074 { 00075 00076 RESID_INLINE 00077 int Integrator::solve(int vi) 00078 { 00079 // "Snake" voltages for triode mode calculation. 00080 const int Vgst = Vddt - x; 00081 const int Vgdt = Vddt - vi; 00082 00083 const uint64_t Vgst_2 = (int64_t)Vgst * (int64_t)Vgst; 00084 const uint64_t Vgdt_2 = (int64_t)Vgdt * (int64_t)Vgdt; 00085 00086 // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30 00087 const int n_I_snake = n_snake * ((Vgst_2 >> 15) - (Vgdt_2 >> 15)); 00088 00089 // VCR gate voltage. // Scaled by m*2^16 00090 // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2) 00091 const int Vg = (int)vcr_Vg[(Vddt_Vw_2 >> 16) + (Vgdt_2 >> 17)]; 00092 00093 // VCR voltages for EKV model table lookup. 00094 const int Vgs = Vg > x ? Vg - x : 0; 00095 const int Vgd = Vg > vi ? Vg - vi : 0; 00096 00097 // VCR current, scaled by m*2^15*2^15 = m*2^30 00098 const int n_I_vcr = (int)(vcr_n_Ids_term[Vgs & 0xffff] - vcr_n_Ids_term[Vgd & 0xffff]) << 15; 00099 00100 // Change in capacitor charge. 00101 vc += n_I_snake + n_I_vcr; 00102 00103 // vx = g(vc) 00104 x = opamp_rev[((vc >> 15) + (1 << 15)) & 0xffff]; 00105 00106 // Return vo. 00107 return x - (vc >> 14); 00108 } 00109 00110 } // namespace reSIDfp 00111 00112 #endif 00113 00114 #endif