108 lines
2.8 KiB
Plaintext
108 lines
2.8 KiB
Plaintext
/*
|
|
* This file is part of libsidplayfp, a SID player engine.
|
|
*
|
|
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
|
|
* Copyright 2007-2010 Antti Lankila
|
|
* Copyright 2004,2010 Dag Lem
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef OPAMP_H
|
|
#define OPAMP_H
|
|
|
|
#include <memory>
|
|
#include "Spline.h"
|
|
|
|
namespace reSIDfp
|
|
{
|
|
|
|
/**
|
|
* Find output voltage in inverting gain and inverting summer SID op-amp
|
|
* circuits, using a combination of Newton-Raphson and bisection.
|
|
*
|
|
* ---R2--
|
|
* | |
|
|
* vi ---R1-----[A>----- vo
|
|
* vx
|
|
*
|
|
* From Kirchoff's current law it follows that
|
|
*
|
|
* IR1f + IR2r = 0
|
|
*
|
|
* Substituting the triode mode transistor model K*W/L*(Vgst^2 - Vgdt^2)
|
|
* for the currents, we get:
|
|
*
|
|
* n*((Vddt - vx)^2 - (Vddt - vi)^2) + (Vddt - vx)^2 - (Vddt - vo)^2 = 0
|
|
*
|
|
* Our root function f can thus be written as:
|
|
*
|
|
* f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - vo)^2 = 0
|
|
*
|
|
* Using substitution constants
|
|
*
|
|
* a = n + 1
|
|
* b = Vddt
|
|
* c = n*(Vddt - vi)^2
|
|
*
|
|
* the equations for the root function and its derivative can be written as:
|
|
*
|
|
* f = a*(b - vx)^2 - c - (b - vo)^2
|
|
* df = 2*((b - vo)*dvo - a*(b - vx))
|
|
*/
|
|
class OpAmp
|
|
{
|
|
private:
|
|
/// Current root position (cached as guess to speed up next iteration)
|
|
double x;
|
|
|
|
const double kVddt, vmin, vmax;
|
|
|
|
std::auto_ptr<Spline> const opamp;
|
|
|
|
public:
|
|
/**
|
|
* Opamp input -> output voltage conversion
|
|
*
|
|
* @param opamp opamp mapping table as pairs of points (in -> out)
|
|
* @param opamplength length of the opamp array
|
|
* @param kVddt transistor dt parameter (in volts)
|
|
*/
|
|
OpAmp(const Spline::Point opamp[], int opamplength, double kVddt) :
|
|
x(0.),
|
|
kVddt(kVddt),
|
|
vmin(opamp[0].x),
|
|
vmax(opamp[opamplength - 1].x),
|
|
opamp(new Spline(opamp, opamplength)) {}
|
|
|
|
void reset()
|
|
{
|
|
x = vmin;
|
|
}
|
|
|
|
/**
|
|
* Solve the opamp equation for input vi in loading context n
|
|
*
|
|
* @param n the ratio of input/output loading
|
|
* @param vi input
|
|
* @return vo
|
|
*/
|
|
double solve(double n, double vi);
|
|
};
|
|
|
|
} // namespace reSIDfp
|
|
|
|
#endif
|