libsidplayfp 2.4.1
filter8580new.h
1// ---------------------------------------------------------------------------
2// This file is part of reSID, a MOS6581 SID emulator engine.
3// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18// ---------------------------------------------------------------------------
19
20#ifndef RESID_FILTER_H
21#define RESID_FILTER_H
22
23#include "resid-config.h"
24
25namespace reSID
26{
27
28// ----------------------------------------------------------------------------
29// The SID filter is modeled with a two-integrator-loop biquadratic filter,
30// which has been confirmed by Bob Yannes to be the actual circuit used in
31// the SID chip.
32//
33// Measurements show that excellent emulation of the SID filter is achieved,
34// except when high resonance is combined with high sustain levels.
35// In this case the SID op-amps are performing less than ideally and are
36// causing some peculiar behavior of the SID filter. This however seems to
37// have more effect on the overall amplitude than on the color of the sound.
38//
39// The theory for the filter circuit can be found in "Microelectric Circuits"
40// by Adel S. Sedra and Kenneth C. Smith.
41// The circuit is modeled based on the explanation found there except that
42// an additional inverter is used in the feedback from the bandpass output,
43// allowing the summer op-amp to operate in single-ended mode. This yields
44// filter outputs with levels independent of Q, which corresponds with the
45// results obtained from a real SID.
46//
47// We have been able to model the summer and the two integrators of the circuit
48// to form components of an IIR filter.
49// Vhp is the output of the summer, Vbp is the output of the first integrator,
50// and Vlp is the output of the second integrator in the filter circuit.
51//
52// According to Bob Yannes, the active stages of the SID filter are not really
53// op-amps. Rather, simple NMOS inverters are used. By biasing an inverter
54// into its region of quasi-linear operation using a feedback resistor from
55// input to output, a MOS inverter can be made to act like an op-amp for
56// small signals centered around the switching threshold.
57//
58// In 2008, Michael Huth facilitated closer investigation of the SID 6581
59// filter circuit by publishing high quality microscope photographs of the die.
60// Tommi Lempinen has done an impressive work on re-vectorizing and annotating
61// the die photographs, substantially simplifying further analysis of the
62// filter circuit.
63//
64// The filter schematics below are reverse engineered from these re-vectorized
65// and annotated die photographs. While the filter first depicted in reSID 0.9
66// is a correct model of the basic filter, the schematics are now completed
67// with the audio mixer and output stage, including details on intended
68// relative resistor values. Also included are schematics for the NMOS FET
69// voltage controlled resistors (VCRs) used to control cutoff frequency, the
70// DAC which controls the VCRs, the NMOS op-amps, and the output buffer.
71//
72//
73// SID 6581 filter / mixer / output
74// --------------------------------
75//
76// ---------------------------------------------------
77// | |
78// | --1R1-- \-- D7 |
79// | ---R1-- | | |
80// | | | |--2R1-- \--| D6 |
81// | ------------<A]-----| | $17 |
82// | | |--4R1-- \--| D5 1=open | (3.5R1)
83// | | | | |
84// | | --8R1-- \--| D4 | (7.0R1)
85// | | | |
86// $17 | | (CAP2B) | (CAP1B) |
87// 0=to mixer | --R8-- ---R8-- ---C---| ---C---|
88// 1=to filter | | | | | | | |
89// ------R8--|-----[A>--|--Rw-----[A>--|--Rw-----[A>--|
90// ve (EXT IN) | | | |
91// D3 \ ---------------R8--| | | (CAP2A) | (CAP1A)
92// | v3 | | vhp | vbp | vlp
93// D2 | \ -----------R8--| ----- | |
94// | | v2 | | | |
95// D1 | | \ -------R8--| | ---------------- |
96// | | | v1 | | | |
97// D0 | | | \ ---R8-- | | ---------------------------
98// | | | | | | |
99// R6 R6 R6 R6 R6 R6 R6
100// | | | | $18 | | | $18
101// | \ | | D7: 1=open \ \ \ D6 - D4: 0=open
102// | | | | | | |
103// --------------------------------- 12V
104// |
105// | D3 --/ --1R4-- |
106// | ---R8-- | | ---R3-- |
107// | | | D2 |--/ --2R4--| | | ||--
108// ------[A>---------| |-----[A>-----||
109// D1 |--/ --4R4--| (4.25R2) ||--
110// $18 | | |
111// 0=open D0 --/ --8R4-- (8.75R2) |
112//
113// vo (AUDIO
114// OUT)
115//
116//
117// v1 - voice 1
118// v2 - voice 2
119// v3 - voice 3
120// ve - ext in
121// vhp - highpass output
122// vbp - bandpass output
123// vlp - lowpass output
124// vo - audio out
125// [A> - single ended inverting op-amp (self-biased NMOS inverter)
126// Rn - "resistors", implemented with custom NMOS FETs
127// Rw - cutoff frequency resistor (VCR)
128// C - capacitor
129//
130// Notes:
131//
132// R2 ~ 2.0*R1
133// R6 ~ 6.0*R1
134// R8 ~ 8.0*R1
135// R24 ~ 24.0*R1
136//
137// The Rn "resistors" in the circuit are implemented with custom NMOS FETs,
138// probably because of space constraints on the SID die. The silicon substrate
139// is laid out in a narrow strip or "snake", with a strip length proportional
140// to the intended resistance. The polysilicon gate electrode covers the entire
141// silicon substrate and is fixed at 12V in order for the NMOS FET to operate
142// in triode mode (a.k.a. linear mode or ohmic mode).
143//
144// Even in "linear mode", an NMOS FET is only an approximation of a resistor,
145// as the apparant resistance increases with increasing drain-to-source
146// voltage. If the drain-to-source voltage should approach the gate voltage
147// of 12V, the NMOS FET will enter saturation mode (a.k.a. active mode), and
148// the NMOS FET will not operate anywhere like a resistor.
149//
150//
151//
152// NMOS FET voltage controlled resistor (VCR)
153// ------------------------------------------
154//
155// Vw
156//
157// |
158// |
159// R1
160// |
161// --R1--|
162// | __|__
163// | -----
164// | | |
165// vi ---------- -------- vo
166// | |
167// ----R24----
168//
169//
170// vi - input
171// vo - output
172// Rn - "resistors", implemented with custom NMOS FETs
173// Vw - voltage from 11-bit DAC (frequency cutoff control)
174//
175// Notes:
176//
177// An approximate value for R24 can be found by using the formula for the
178// filter cutoff frequency:
179//
180// FCmin = 1/(2*pi*Rmax*C)
181//
182// Assuming that a the setting for minimum cutoff frequency in combination with
183// a low level input signal ensures that only negligible current will flow
184// through the transistor in the schematics above, values for FCmin and C can
185// be substituted in this formula to find Rmax.
186// Using C = 470pF and FCmin = 220Hz (measured value), we get:
187//
188// FCmin = 1/(2*pi*Rmax*C)
189// Rmax = 1/(2*pi*FCmin*C) = 1/(2*pi*220*470e-12) ~ 1.5MOhm
190//
191// From this it follows that:
192// R24 = Rmax ~ 1.5MOhm
193// R1 ~ R24/24 ~ 64kOhm
194// R2 ~ 2.0*R1 ~ 128kOhm
195// R6 ~ 6.0*R1 ~ 384kOhm
196// R8 ~ 8.0*R1 ~ 512kOhm
197//
198// Note that these are only approximate values for one particular SID chip,
199// due to process variations the values can be substantially different in
200// other chips.
201//
202//
203//
204// Filter frequency cutoff DAC
205// ---------------------------
206//
207//
208// 12V 10 9 8 7 6 5 4 3 2 1 0 VGND
209// | | | | | | | | | | | | | Missing
210// 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R termination
211// | | | | | | | | | | | | |
212// Vw ----R---R---R---R---R---R---R---R---R---R---R-- ---
213//
214// Bit on: 12V
215// Bit off: 5V (VGND)
216//
217// As is the case with all MOS 6581 DACs, the termination to (virtual) ground
218// at bit 0 is missing.
219//
220// Furthermore, the control of the two VCRs imposes a load on the DAC output
221// which varies with the input signals to the VCRs. This can be seen from the
222// VCR figure above.
223//
224//
225//
226// "Op-amp" (self-biased NMOS inverter)
227// ------------------------------------
228//
229//
230// 12V
231//
232// |
233// -----------|
234// | |
235// | ------|
236// | | |
237// | | ||--
238// | --||
239// | ||--
240// ||-- |
241// vi -----|| |--------- vo
242// ||-- | |
243// | ||-- |
244// |-------|| |
245// | ||-- |
246// ||-- | |
247// --|| | |
248// | ||-- | |
249// | | | |
250// | -----------| |
251// | | |
252// | |
253// | GND |
254// | |
255// ----------------------
256//
257//
258// vi - input
259// vo - output
260//
261// Notes:
262//
263// The schematics above are laid out to show that the "op-amp" logically
264// consists of two building blocks; a saturated load NMOS inverter (on the
265// right hand side of the schematics) with a buffer / bias input stage
266// consisting of a variable saturated load NMOS inverter (on the left hand
267// side of the schematics).
268//
269// Provided a reasonably high input impedance and a reasonably low output
270// impedance, the "op-amp" can be modeled as a voltage transfer function
271// mapping input voltage to output voltage.
272//
273//
274//
275// Output buffer (NMOS voltage follower)
276// -------------------------------------
277//
278//
279// 12V
280//
281// |
282// |
283// ||--
284// vi -----||
285// ||--
286// |
287// |------ vo
288// | (AUDIO
289// Rext OUT)
290// |
291// |
292//
293// GND
294//
295// vi - input
296// vo - output
297// Rext - external resistor, 1kOhm
298//
299// Notes:
300//
301// The external resistor Rext is needed to complete the NMOS voltage follower,
302// this resistor has a recommended value of 1kOhm.
303//
304// Die photographs show that actually, two NMOS transistors are used in the
305// voltage follower. However the two transistors are coupled in parallel (all
306// terminals are pairwise common), which implies that we can model the two
307// transistors as one.
308//
309// ----------------------------------------------------------------------------
310//
311// SID 8580 filter / mixer / output
312// --------------------------------
313//
314// +---------------------------------------------------+
315// | $17 +----Rf-+ |
316// | | | |
317// | D4&!D5 o- \-R3-o |
318// | | | $17 |
319// | !D4&!D5 o- \-R2-o |
320// | | | +---R8-- \--+ !D6&D7 |
321// | D4&!D5 o- \-R1-o | | |
322// | | | o---RC-- \--o D6&D7 |
323// | +---------o--<A]--o--o | |
324// | | o---R4-- \--o D6&!D7 |
325// | | | | |
326// | | +---Ri-- \--o !D6&!D7 |
327// | | | |
328// $17 | | (CAP2B) | (CAP1B) |
329// 0=to mixer | +--R7--+ +---R7--+ +---C---o +---C---o
330// 1=to filter | | | | | | | |
331// +------R7--o--o--[A>--o--Rfc-o--[A>--o--Rfc-o--[A>--o
332// ve (EXT IN) | | | |
333// D3 \ --------------R12--o | | (CAP2A) | (CAP1A)
334// | v3 | | vhp | vbp | vlp
335// D2 | \ -----------R7--o +-----+ | |
336// | | v2 | | | |
337// D1 | | \ -------R7--o | +----------------+ |
338// | | | v1 | | | |
339// D0 | | | \ ---R7--+ | | +---------------------------+
340// | | | | | | |
341// R9 R5 R5 R5 R5 R5 R5
342// | | | | $18 | | | $18
343// | \ | | D7: 1=open \ \ \ D6 - D4: 0=open
344// | | | | | | |
345// +---o---o---o-------------o---o---+
346// |
347// | D3 +--/ --1R4--+
348// | +---R8--+ | | +---R2--+
349// | | | D2 o--/ --2R4--o | |
350// +---o--[A>--o------o o--o--[A>--o-- vo (AUDIO OUT)
351// D1 o--/ --4R4--o
352// $18 | |
353// 0=open D0 +--/ --8R4--+
354//
355//
356//
357//
358// R1 = 15.3*Ri
359// R2 = 7.3*Ri
360// R3 = 4.7*Ri
361// Rf = 1.4*Ri
362// R4 = 1.4*Ri
363// R8 = 2.0*Ri
364// RC = 2.8*Ri
365//
366//
367//
368// Op-amps
369// -------
370// Unlike the 6581, the 8580 has real OpAmps.
371//
372// Temperature compensated differential amplifier:
373//
374// 9V
375//
376// |
377// +-------o-o-o-------+
378// | | | |
379// | R R |
380// +--|| | | ||--+
381// ||---o o---||
382// +--|| | | ||--+
383// | | | |
384// o-----+ | | o--- Va
385// | | | | |
386// +--|| | | | ||--+
387// ||-o-+---+---||
388// +--|| | | ||--+
389// | | | |
390// | |
391// GND | | GND
392// ||--+ +--||
393// in- -----|| ||------ in+
394// ||----o----||
395// |
396// 8 Current sink
397// |
398//
399// GND
400//
401// Inverter + non-inverting output amplifier:
402//
403// Va ---o---||-------------------o--------------------+
404// | | 9V |
405// | +----------+----------+ | |
406// | 9V | | 9V | ||--+ |
407// | | | 9V | | +-|| |
408// | R | | | ||--+ ||--+ |
409// | | | ||--+ +--|| o---o--- Vout
410// | o---o---|| ||--+ ||--+
411// | | ||--+ o-----||
412// | ||--+ | ||--+ ||--+
413// +-----|| o-----|| |
414// ||--+ | ||--+
415// | R | GND
416// |
417// GND GND
418// GND
419//
420//
421//
422// Virtual ground
423// --------------
424// A PolySi resitive voltage divider provides the voltage
425// for the non-inverting input of the filter op-amps.
426//
427// 5V
428// +----------+
429// | | |\ |
430// R1 +---|-\ |
431// 5V | |A >---o--- Vref
432// o-------|+/
433// | | |/
434// R10 R4
435// | |
436// o---+
437// |
438// R10
439// |
440//
441// GND
442//
443// Rn = n*R1
444//
445//
446//
447// Rfc - freq control DAC resistance ladder
448// ----------------------------------------
449// The resistance for the bandpass and lowpass integrator stages of the filter are determined
450// by an 11 bit DAC driven by the FC register.
451// If all 11 bits are '0', the impedance of the DAC would be "infinitely high".
452// To get around this, there is an 11 input NOR gate below the DAC sensing those 11 bits.
453// If they are all 0, the NOR gate gives the gate control voltage to the 12 bit DAC LSB.
454//
455//
456//
457// Crystal stabilized precision switched capacitor voltage divider
458// ---------------------------------------------------------------
459// There is a FET working as a temperature sensor close to the DACs which changes the gate voltage
460// of the frequency control DACs according to the temperature, to reduce its effects on the filter curve.
461// An asynchronous 3 bit binary counter, running at the speed of PHI2, drives two big capacitors
462// which AC resistance is then used as a voltage divider.
463// This implicates that frequency difference between PAL and NTSC might shift the filter curve by 4% or such.
464//
465// https://en.wikipedia.org/wiki/Switched_capacitor
466//
467// |\ OpAmp has a smaller capacitor
468// Vref ---|+\ than the other OPs
469// |A >---o--- Vdac
470// o-------|-/ |
471// | |/ |
472// | |
473// C1 | C2 |
474// +---||---o---+ +---o-----||-------o
475// | | | | | |
476// o----+ | ----- | |
477// | | | ----- +----+ +-----+
478// | ----- | | | |
479// | ----- | ----- |
480// | | | ----- |
481// | +-----------+ | |
482// | /Q Q | +-------+
483// GND +-----------+ FET close to DAC
484// | clk/8 | working as temperature sensor
485// +-----------+
486// | |
487// clk1 clk2
488//
489
490// Compile-time computation of op-amp summer and mixer table offsets.
491
492// The highpass summer has 2 - 6 inputs (bandpass, lowpass, and 0 - 4 voices).
493template<int i>
494struct summer_offset
495{
496 enum { value = summer_offset<i - 1>::value + ((2 + i - 1) << 16) };
497};
498
499template<>
500struct summer_offset<0>
501{
502 enum { value = 0 };
503};
504
505// The mixer has 0 - 7 inputs (0 - 4 voices and 0 - 3 filter outputs).
506template<int i>
507struct mixer_offset
508{
509 enum { value = mixer_offset<i - 1>::value + ((i - 1) << 16) };
510};
511
512template<>
513struct mixer_offset<1>
514{
515 enum { value = 1 };
516};
517
518template<>
519struct mixer_offset<0>
520{
521 enum { value = 0 };
522};
523
524
525class Filter
526{
527public:
528 Filter();
529
530 void enable_filter(bool enable);
531 void adjust_filter_bias(double dac_bias);
532 void set_chip_model(chip_model model);
533 void set_voice_mask(reg4 mask);
534
535 void clock(int voice1, int voice2, int voice3);
536 void clock(cycle_count delta_t, int voice1, int voice2, int voice3);
537 void reset();
538
539 // Write registers.
540 void writeFC_LO(reg8);
541 void writeFC_HI(reg8);
542 void writeRES_FILT(reg8);
543 void writeMODE_VOL(reg8);
544
545 // SID audio input (16 bits).
546 void input(short sample);
547
548 // SID audio output (16 bits).
549 short output();
550
551protected:
552 void set_sum_mix();
553 void set_w0();
554
555 // Filter enabled.
556 bool enabled;
557
558 // Filter cutoff frequency.
559 reg12 fc;
560
561 // Filter resonance.
562 reg8 res;
563
564 // Selects which voices to route through the filter.
565 reg8 filt;
566
567 // Selects which filter outputs to route into the mixer.
568 reg4 mode;
569
570 // Output master volume.
571 reg4 vol;
572
573 // Used to mask out EXT IN if not connected, and for test purposes
574 // (voice muting).
575 reg8 voice_mask;
576
577 // Select which inputs to route into the summer / mixer.
578 // These are derived from filt, mode, and voice_mask.
579 reg8 sum;
580 reg8 mix;
581
582 // State of filter.
583 int Vhp; // highpass
584 int Vbp; // bandpass
585 int Vbp_x, Vbp_vc;
586 int Vlp; // lowpass
587 int Vlp_x, Vlp_vc;
588 // Filter / mixer inputs.
589 int ve;
590 int v3;
591 int v2;
592 int v1;
593
594 chip_model sid_model;
595
596 typedef struct {
597 unsigned short vx;
598 short dvx;
599 } opamp_t;
600
601 typedef struct {
602 int kVddt; // K*(Vdd - Vth)
603 int voice_scale_s14;
604 int voice_DC;
605 int ak;
606 int bk;
607 int vc_min;
608 int vc_max;
609 double vo_N16; // Fixed point scaling for 16 bit op-amp output.
610
611 // Reverse op-amp transfer function.
612 unsigned short opamp_rev[1 << 16];
613 // Lookup tables for gain and summer op-amps in output stage / filter.
614 unsigned short summer[summer_offset<5>::value];
615 unsigned short gain[16][1 << 16];
616 unsigned short resonance[16][1 << 16];
617 unsigned short mixer[mixer_offset<8>::value];
618 // Cutoff frequency DAC output voltage table. FC is an 11 bit register.
619 unsigned short f0_dac[1 << 11];
620 } model_filter_t;
621
622 // 6581 only
623 // Cutoff frequency DAC voltage, resonance.
624 int Vddt_Vw_2, Vw_bias;
625
626 static int n_snake;
627
628 // 8580 only
629 int n_dac;
630
631 static int n_param;
632
633 // DAC gate voltage
634 int nVgt;
635
636 int solve_gain(opamp_t* opamp, int n, int vi_t, int& x, model_filter_t& mf);
637 int solve_integrate_6581(int dt, int vi_t, int& x, int& vc, model_filter_t& mf);
638 int solve_integrate_8580(int dt, int vi_t, int& x, int& vc, model_filter_t& mf);
639
640 // VCR - 6581 only.
641 static unsigned short vcr_kVg[1 << 16];
642 static unsigned short vcr_n_Ids_term[1 << 16];
643 // Common parameters.
644 static model_filter_t model_filter[2];
645
646friend class SID;
647};
648
649
650// ----------------------------------------------------------------------------
651// Inline functions.
652// The following functions are defined inline because they are called every
653// time a sample is calculated.
654// ----------------------------------------------------------------------------
655
656#if RESID_INLINING || defined(RESID_FILTER_CC)
657
658// ----------------------------------------------------------------------------
659// SID clocking - 1 cycle.
660// ----------------------------------------------------------------------------
661RESID_INLINE
662void Filter::clock(int voice1, int voice2, int voice3)
663{
664 model_filter_t& f = model_filter[sid_model];
665
666 v1 = (voice1*f.voice_scale_s14 >> 18) + f.voice_DC;
667 v2 = (voice2*f.voice_scale_s14 >> 18) + f.voice_DC;
668 v3 = (voice3*f.voice_scale_s14 >> 18) + f.voice_DC;
669
670 // Sum inputs routed into the filter.
671 int Vi = 0;
672 int offset = 0;
673
674 switch (sum & 0xf) {
675 case 0x0:
676 Vi = 0;
677 offset = summer_offset<0>::value;
678 break;
679 case 0x1:
680 Vi = v1;
681 offset = summer_offset<1>::value;
682 break;
683 case 0x2:
684 Vi = v2;
685 offset = summer_offset<1>::value;
686 break;
687 case 0x3:
688 Vi = v2 + v1;
689 offset = summer_offset<2>::value;
690 break;
691 case 0x4:
692 Vi = v3;
693 offset = summer_offset<1>::value;
694 break;
695 case 0x5:
696 Vi = v3 + v1;
697 offset = summer_offset<2>::value;
698 break;
699 case 0x6:
700 Vi = v3 + v2;
701 offset = summer_offset<2>::value;
702 break;
703 case 0x7:
704 Vi = v3 + v2 + v1;
705 offset = summer_offset<3>::value;
706 break;
707 case 0x8:
708 Vi = ve;
709 offset = summer_offset<1>::value;
710 break;
711 case 0x9:
712 Vi = ve + v1;
713 offset = summer_offset<2>::value;
714 break;
715 case 0xa:
716 Vi = ve + v2;
717 offset = summer_offset<2>::value;
718 break;
719 case 0xb:
720 Vi = ve + v2 + v1;
721 offset = summer_offset<3>::value;
722 break;
723 case 0xc:
724 Vi = ve + v3;
725 offset = summer_offset<2>::value;
726 break;
727 case 0xd:
728 Vi = ve + v3 + v1;
729 offset = summer_offset<3>::value;
730 break;
731 case 0xe:
732 Vi = ve + v3 + v2;
733 offset = summer_offset<3>::value;
734 break;
735 case 0xf:
736 Vi = ve + v3 + v2 + v1;
737 offset = summer_offset<4>::value;
738 break;
739 }
740
741 // Calculate filter outputs.
742 if (sid_model == 0) {
743 // MOS 6581.
744 Vlp = solve_integrate_6581(1, Vbp, Vlp_x, Vlp_vc, f);
745 Vbp = solve_integrate_6581(1, Vhp, Vbp_x, Vbp_vc, f);
746 Vhp = f.summer[offset + f.resonance[res][Vbp] + Vlp + Vi];
747 }
748 else {
749 // MOS 8580.
750 Vlp = solve_integrate_8580(1, Vbp, Vlp_x, Vlp_vc, f);
751 Vbp = solve_integrate_8580(1, Vhp, Vbp_x, Vbp_vc, f);
752 Vhp = f.summer[offset + f.resonance[res][Vbp] + Vlp + Vi];
753 }
754}
755
756// ----------------------------------------------------------------------------
757// SID clocking - delta_t cycles.
758// ----------------------------------------------------------------------------
759RESID_INLINE
760void Filter::clock(cycle_count delta_t, int voice1, int voice2, int voice3)
761{
762 model_filter_t& f = model_filter[sid_model];
763
764 v1 = (voice1*f.voice_scale_s14 >> 18) + f.voice_DC;
765 v2 = (voice2*f.voice_scale_s14 >> 18) + f.voice_DC;
766 v3 = (voice3*f.voice_scale_s14 >> 18) + f.voice_DC;
767
768 // Enable filter on/off.
769 // This is not really part of SID, but is useful for testing.
770 // On slow CPUs it may be necessary to bypass the filter to lower the CPU
771 // load.
772 if (unlikely(!enabled)) {
773 return;
774 }
775
776 // Sum inputs routed into the filter.
777 int Vi = 0;
778 int offset = 0;
779
780 switch (sum & 0xf) {
781 case 0x0:
782 Vi = 0;
783 offset = summer_offset<0>::value;
784 break;
785 case 0x1:
786 Vi = v1;
787 offset = summer_offset<1>::value;
788 break;
789 case 0x2:
790 Vi = v2;
791 offset = summer_offset<1>::value;
792 break;
793 case 0x3:
794 Vi = v2 + v1;
795 offset = summer_offset<2>::value;
796 break;
797 case 0x4:
798 Vi = v3;
799 offset = summer_offset<1>::value;
800 break;
801 case 0x5:
802 Vi = v3 + v1;
803 offset = summer_offset<2>::value;
804 break;
805 case 0x6:
806 Vi = v3 + v2;
807 offset = summer_offset<2>::value;
808 break;
809 case 0x7:
810 Vi = v3 + v2 + v1;
811 offset = summer_offset<3>::value;
812 break;
813 case 0x8:
814 Vi = ve;
815 offset = summer_offset<1>::value;
816 break;
817 case 0x9:
818 Vi = ve + v1;
819 offset = summer_offset<2>::value;
820 break;
821 case 0xa:
822 Vi = ve + v2;
823 offset = summer_offset<2>::value;
824 break;
825 case 0xb:
826 Vi = ve + v2 + v1;
827 offset = summer_offset<3>::value;
828 break;
829 case 0xc:
830 Vi = ve + v3;
831 offset = summer_offset<2>::value;
832 break;
833 case 0xd:
834 Vi = ve + v3 + v1;
835 offset = summer_offset<3>::value;
836 break;
837 case 0xe:
838 Vi = ve + v3 + v2;
839 offset = summer_offset<3>::value;
840 break;
841 case 0xf:
842 Vi = ve + v3 + v2 + v1;
843 offset = summer_offset<4>::value;
844 break;
845 }
846
847 // Maximum delta cycles for filter fixpoint iteration to converge
848 // is approximately 3.
849 cycle_count delta_t_flt = 3;
850
851 if (sid_model == 0) {
852 // MOS 6581.
853 while (delta_t) {
854 if (unlikely(delta_t < delta_t_flt)) {
855 delta_t_flt = delta_t;
856 }
857
858 // Calculate filter outputs.
859 Vlp = solve_integrate_6581(delta_t_flt, Vbp, Vlp_x, Vlp_vc, f);
860 Vbp = solve_integrate_6581(delta_t_flt, Vhp, Vbp_x, Vbp_vc, f);
861 Vhp = f.summer[offset + f.resonance[res][Vbp] + Vlp + Vi];
862
863 delta_t -= delta_t_flt;
864 }
865 }
866 else {
867 // MOS 8580.
868 while (delta_t) {
869 if (unlikely(delta_t < delta_t_flt)) {
870 delta_t_flt = delta_t;
871 }
872
873 // Calculate filter outputs.
874 Vlp = solve_integrate_8580(delta_t_flt, Vbp, Vlp_x, Vlp_vc, f);
875 Vbp = solve_integrate_8580(delta_t_flt, Vhp, Vbp_x, Vbp_vc, f);
876 Vhp = f.summer[offset + f.resonance[res][Vbp] + Vlp + Vi];
877
878 delta_t -= delta_t_flt;
879 }
880 }
881}
882
883
884// ----------------------------------------------------------------------------
885// SID audio input (16 bits).
886// ----------------------------------------------------------------------------
887RESID_INLINE
888void Filter::input(short sample)
889{
890 // Scale to three times the peak-to-peak for one voice and add the op-amp
891 // "zero" DC level.
892 // NB! Adding the op-amp "zero" DC level is a (wildly inaccurate)
893 // approximation of feeding the input through an AC coupling capacitor.
894 // This could be implemented as a separate filter circuit, however the
895 // primary use of the emulator is not to process external signals.
896 // The upside is that the MOS8580 "digi boost" works without a separate (DC)
897 // input interface.
898 // Note that the input is 16 bits, compared to the 20 bit voice output.
899 model_filter_t& f = model_filter[sid_model];
900 ve = (sample*f.voice_scale_s14*3 >> 14) + f.mixer[0];
901}
902
903
904// ----------------------------------------------------------------------------
905// SID audio output (16 bits).
906// ----------------------------------------------------------------------------
907RESID_INLINE
908short Filter::output()
909{
910 model_filter_t& f = model_filter[sid_model];
911
912 // Writing the switch below manually would be tedious and error-prone;
913 // it is rather generated by the following Perl program:
914
915 /*
916my @i = qw(v1 v2 v3 ve Vlp Vbp Vhp);
917for my $mix (0..2**@i-1) {
918 print sprintf(" case 0x%02x:\n", $mix);
919 my @sum;
920 for (@i) {
921 unshift(@sum, $_) if $mix & 0x01;
922 $mix >>= 1;
923 }
924 my $sum = join(" + ", @sum) || "0";
925 print " Vi = $sum;\n";
926 print " offset = mixer_offset<" . @sum . ">::value;\n";
927 print " break;\n";
928}
929 */
930
931 // Sum inputs routed into the mixer.
932 int Vi = 0;
933 int offset = 0;
934
935 switch (mix & 0x7f) {
936 case 0x00:
937 Vi = 0;
938 offset = mixer_offset<0>::value;
939 break;
940 case 0x01:
941 Vi = v1;
942 offset = mixer_offset<1>::value;
943 break;
944 case 0x02:
945 Vi = v2;
946 offset = mixer_offset<1>::value;
947 break;
948 case 0x03:
949 Vi = v2 + v1;
950 offset = mixer_offset<2>::value;
951 break;
952 case 0x04:
953 Vi = v3;
954 offset = mixer_offset<1>::value;
955 break;
956 case 0x05:
957 Vi = v3 + v1;
958 offset = mixer_offset<2>::value;
959 break;
960 case 0x06:
961 Vi = v3 + v2;
962 offset = mixer_offset<2>::value;
963 break;
964 case 0x07:
965 Vi = v3 + v2 + v1;
966 offset = mixer_offset<3>::value;
967 break;
968 case 0x08:
969 Vi = ve;
970 offset = mixer_offset<1>::value;
971 break;
972 case 0x09:
973 Vi = ve + v1;
974 offset = mixer_offset<2>::value;
975 break;
976 case 0x0a:
977 Vi = ve + v2;
978 offset = mixer_offset<2>::value;
979 break;
980 case 0x0b:
981 Vi = ve + v2 + v1;
982 offset = mixer_offset<3>::value;
983 break;
984 case 0x0c:
985 Vi = ve + v3;
986 offset = mixer_offset<2>::value;
987 break;
988 case 0x0d:
989 Vi = ve + v3 + v1;
990 offset = mixer_offset<3>::value;
991 break;
992 case 0x0e:
993 Vi = ve + v3 + v2;
994 offset = mixer_offset<3>::value;
995 break;
996 case 0x0f:
997 Vi = ve + v3 + v2 + v1;
998 offset = mixer_offset<4>::value;
999 break;
1000 case 0x10:
1001 Vi = Vlp;
1002 offset = mixer_offset<1>::value;
1003 break;
1004 case 0x11:
1005 Vi = Vlp + v1;
1006 offset = mixer_offset<2>::value;
1007 break;
1008 case 0x12:
1009 Vi = Vlp + v2;
1010 offset = mixer_offset<2>::value;
1011 break;
1012 case 0x13:
1013 Vi = Vlp + v2 + v1;
1014 offset = mixer_offset<3>::value;
1015 break;
1016 case 0x14:
1017 Vi = Vlp + v3;
1018 offset = mixer_offset<2>::value;
1019 break;
1020 case 0x15:
1021 Vi = Vlp + v3 + v1;
1022 offset = mixer_offset<3>::value;
1023 break;
1024 case 0x16:
1025 Vi = Vlp + v3 + v2;
1026 offset = mixer_offset<3>::value;
1027 break;
1028 case 0x17:
1029 Vi = Vlp + v3 + v2 + v1;
1030 offset = mixer_offset<4>::value;
1031 break;
1032 case 0x18:
1033 Vi = Vlp + ve;
1034 offset = mixer_offset<2>::value;
1035 break;
1036 case 0x19:
1037 Vi = Vlp + ve + v1;
1038 offset = mixer_offset<3>::value;
1039 break;
1040 case 0x1a:
1041 Vi = Vlp + ve + v2;
1042 offset = mixer_offset<3>::value;
1043 break;
1044 case 0x1b:
1045 Vi = Vlp + ve + v2 + v1;
1046 offset = mixer_offset<4>::value;
1047 break;
1048 case 0x1c:
1049 Vi = Vlp + ve + v3;
1050 offset = mixer_offset<3>::value;
1051 break;
1052 case 0x1d:
1053 Vi = Vlp + ve + v3 + v1;
1054 offset = mixer_offset<4>::value;
1055 break;
1056 case 0x1e:
1057 Vi = Vlp + ve + v3 + v2;
1058 offset = mixer_offset<4>::value;
1059 break;
1060 case 0x1f:
1061 Vi = Vlp + ve + v3 + v2 + v1;
1062 offset = mixer_offset<5>::value;
1063 break;
1064 case 0x20:
1065 Vi = Vbp;
1066 offset = mixer_offset<1>::value;
1067 break;
1068 case 0x21:
1069 Vi = Vbp + v1;
1070 offset = mixer_offset<2>::value;
1071 break;
1072 case 0x22:
1073 Vi = Vbp + v2;
1074 offset = mixer_offset<2>::value;
1075 break;
1076 case 0x23:
1077 Vi = Vbp + v2 + v1;
1078 offset = mixer_offset<3>::value;
1079 break;
1080 case 0x24:
1081 Vi = Vbp + v3;
1082 offset = mixer_offset<2>::value;
1083 break;
1084 case 0x25:
1085 Vi = Vbp + v3 + v1;
1086 offset = mixer_offset<3>::value;
1087 break;
1088 case 0x26:
1089 Vi = Vbp + v3 + v2;
1090 offset = mixer_offset<3>::value;
1091 break;
1092 case 0x27:
1093 Vi = Vbp + v3 + v2 + v1;
1094 offset = mixer_offset<4>::value;
1095 break;
1096 case 0x28:
1097 Vi = Vbp + ve;
1098 offset = mixer_offset<2>::value;
1099 break;
1100 case 0x29:
1101 Vi = Vbp + ve + v1;
1102 offset = mixer_offset<3>::value;
1103 break;
1104 case 0x2a:
1105 Vi = Vbp + ve + v2;
1106 offset = mixer_offset<3>::value;
1107 break;
1108 case 0x2b:
1109 Vi = Vbp + ve + v2 + v1;
1110 offset = mixer_offset<4>::value;
1111 break;
1112 case 0x2c:
1113 Vi = Vbp + ve + v3;
1114 offset = mixer_offset<3>::value;
1115 break;
1116 case 0x2d:
1117 Vi = Vbp + ve + v3 + v1;
1118 offset = mixer_offset<4>::value;
1119 break;
1120 case 0x2e:
1121 Vi = Vbp + ve + v3 + v2;
1122 offset = mixer_offset<4>::value;
1123 break;
1124 case 0x2f:
1125 Vi = Vbp + ve + v3 + v2 + v1;
1126 offset = mixer_offset<5>::value;
1127 break;
1128 case 0x30:
1129 Vi = Vbp + Vlp;
1130 offset = mixer_offset<2>::value;
1131 break;
1132 case 0x31:
1133 Vi = Vbp + Vlp + v1;
1134 offset = mixer_offset<3>::value;
1135 break;
1136 case 0x32:
1137 Vi = Vbp + Vlp + v2;
1138 offset = mixer_offset<3>::value;
1139 break;
1140 case 0x33:
1141 Vi = Vbp + Vlp + v2 + v1;
1142 offset = mixer_offset<4>::value;
1143 break;
1144 case 0x34:
1145 Vi = Vbp + Vlp + v3;
1146 offset = mixer_offset<3>::value;
1147 break;
1148 case 0x35:
1149 Vi = Vbp + Vlp + v3 + v1;
1150 offset = mixer_offset<4>::value;
1151 break;
1152 case 0x36:
1153 Vi = Vbp + Vlp + v3 + v2;
1154 offset = mixer_offset<4>::value;
1155 break;
1156 case 0x37:
1157 Vi = Vbp + Vlp + v3 + v2 + v1;
1158 offset = mixer_offset<5>::value;
1159 break;
1160 case 0x38:
1161 Vi = Vbp + Vlp + ve;
1162 offset = mixer_offset<3>::value;
1163 break;
1164 case 0x39:
1165 Vi = Vbp + Vlp + ve + v1;
1166 offset = mixer_offset<4>::value;
1167 break;
1168 case 0x3a:
1169 Vi = Vbp + Vlp + ve + v2;
1170 offset = mixer_offset<4>::value;
1171 break;
1172 case 0x3b:
1173 Vi = Vbp + Vlp + ve + v2 + v1;
1174 offset = mixer_offset<5>::value;
1175 break;
1176 case 0x3c:
1177 Vi = Vbp + Vlp + ve + v3;
1178 offset = mixer_offset<4>::value;
1179 break;
1180 case 0x3d:
1181 Vi = Vbp + Vlp + ve + v3 + v1;
1182 offset = mixer_offset<5>::value;
1183 break;
1184 case 0x3e:
1185 Vi = Vbp + Vlp + ve + v3 + v2;
1186 offset = mixer_offset<5>::value;
1187 break;
1188 case 0x3f:
1189 Vi = Vbp + Vlp + ve + v3 + v2 + v1;
1190 offset = mixer_offset<6>::value;
1191 break;
1192 case 0x40:
1193 Vi = Vhp;
1194 offset = mixer_offset<1>::value;
1195 break;
1196 case 0x41:
1197 Vi = Vhp + v1;
1198 offset = mixer_offset<2>::value;
1199 break;
1200 case 0x42:
1201 Vi = Vhp + v2;
1202 offset = mixer_offset<2>::value;
1203 break;
1204 case 0x43:
1205 Vi = Vhp + v2 + v1;
1206 offset = mixer_offset<3>::value;
1207 break;
1208 case 0x44:
1209 Vi = Vhp + v3;
1210 offset = mixer_offset<2>::value;
1211 break;
1212 case 0x45:
1213 Vi = Vhp + v3 + v1;
1214 offset = mixer_offset<3>::value;
1215 break;
1216 case 0x46:
1217 Vi = Vhp + v3 + v2;
1218 offset = mixer_offset<3>::value;
1219 break;
1220 case 0x47:
1221 Vi = Vhp + v3 + v2 + v1;
1222 offset = mixer_offset<4>::value;
1223 break;
1224 case 0x48:
1225 Vi = Vhp + ve;
1226 offset = mixer_offset<2>::value;
1227 break;
1228 case 0x49:
1229 Vi = Vhp + ve + v1;
1230 offset = mixer_offset<3>::value;
1231 break;
1232 case 0x4a:
1233 Vi = Vhp + ve + v2;
1234 offset = mixer_offset<3>::value;
1235 break;
1236 case 0x4b:
1237 Vi = Vhp + ve + v2 + v1;
1238 offset = mixer_offset<4>::value;
1239 break;
1240 case 0x4c:
1241 Vi = Vhp + ve + v3;
1242 offset = mixer_offset<3>::value;
1243 break;
1244 case 0x4d:
1245 Vi = Vhp + ve + v3 + v1;
1246 offset = mixer_offset<4>::value;
1247 break;
1248 case 0x4e:
1249 Vi = Vhp + ve + v3 + v2;
1250 offset = mixer_offset<4>::value;
1251 break;
1252 case 0x4f:
1253 Vi = Vhp + ve + v3 + v2 + v1;
1254 offset = mixer_offset<5>::value;
1255 break;
1256 case 0x50:
1257 Vi = Vhp + Vlp;
1258 offset = mixer_offset<2>::value;
1259 break;
1260 case 0x51:
1261 Vi = Vhp + Vlp + v1;
1262 offset = mixer_offset<3>::value;
1263 break;
1264 case 0x52:
1265 Vi = Vhp + Vlp + v2;
1266 offset = mixer_offset<3>::value;
1267 break;
1268 case 0x53:
1269 Vi = Vhp + Vlp + v2 + v1;
1270 offset = mixer_offset<4>::value;
1271 break;
1272 case 0x54:
1273 Vi = Vhp + Vlp + v3;
1274 offset = mixer_offset<3>::value;
1275 break;
1276 case 0x55:
1277 Vi = Vhp + Vlp + v3 + v1;
1278 offset = mixer_offset<4>::value;
1279 break;
1280 case 0x56:
1281 Vi = Vhp + Vlp + v3 + v2;
1282 offset = mixer_offset<4>::value;
1283 break;
1284 case 0x57:
1285 Vi = Vhp + Vlp + v3 + v2 + v1;
1286 offset = mixer_offset<5>::value;
1287 break;
1288 case 0x58:
1289 Vi = Vhp + Vlp + ve;
1290 offset = mixer_offset<3>::value;
1291 break;
1292 case 0x59:
1293 Vi = Vhp + Vlp + ve + v1;
1294 offset = mixer_offset<4>::value;
1295 break;
1296 case 0x5a:
1297 Vi = Vhp + Vlp + ve + v2;
1298 offset = mixer_offset<4>::value;
1299 break;
1300 case 0x5b:
1301 Vi = Vhp + Vlp + ve + v2 + v1;
1302 offset = mixer_offset<5>::value;
1303 break;
1304 case 0x5c:
1305 Vi = Vhp + Vlp + ve + v3;
1306 offset = mixer_offset<4>::value;
1307 break;
1308 case 0x5d:
1309 Vi = Vhp + Vlp + ve + v3 + v1;
1310 offset = mixer_offset<5>::value;
1311 break;
1312 case 0x5e:
1313 Vi = Vhp + Vlp + ve + v3 + v2;
1314 offset = mixer_offset<5>::value;
1315 break;
1316 case 0x5f:
1317 Vi = Vhp + Vlp + ve + v3 + v2 + v1;
1318 offset = mixer_offset<6>::value;
1319 break;
1320 case 0x60:
1321 Vi = Vhp + Vbp;
1322 offset = mixer_offset<2>::value;
1323 break;
1324 case 0x61:
1325 Vi = Vhp + Vbp + v1;
1326 offset = mixer_offset<3>::value;
1327 break;
1328 case 0x62:
1329 Vi = Vhp + Vbp + v2;
1330 offset = mixer_offset<3>::value;
1331 break;
1332 case 0x63:
1333 Vi = Vhp + Vbp + v2 + v1;
1334 offset = mixer_offset<4>::value;
1335 break;
1336 case 0x64:
1337 Vi = Vhp + Vbp + v3;
1338 offset = mixer_offset<3>::value;
1339 break;
1340 case 0x65:
1341 Vi = Vhp + Vbp + v3 + v1;
1342 offset = mixer_offset<4>::value;
1343 break;
1344 case 0x66:
1345 Vi = Vhp + Vbp + v3 + v2;
1346 offset = mixer_offset<4>::value;
1347 break;
1348 case 0x67:
1349 Vi = Vhp + Vbp + v3 + v2 + v1;
1350 offset = mixer_offset<5>::value;
1351 break;
1352 case 0x68:
1353 Vi = Vhp + Vbp + ve;
1354 offset = mixer_offset<3>::value;
1355 break;
1356 case 0x69:
1357 Vi = Vhp + Vbp + ve + v1;
1358 offset = mixer_offset<4>::value;
1359 break;
1360 case 0x6a:
1361 Vi = Vhp + Vbp + ve + v2;
1362 offset = mixer_offset<4>::value;
1363 break;
1364 case 0x6b:
1365 Vi = Vhp + Vbp + ve + v2 + v1;
1366 offset = mixer_offset<5>::value;
1367 break;
1368 case 0x6c:
1369 Vi = Vhp + Vbp + ve + v3;
1370 offset = mixer_offset<4>::value;
1371 break;
1372 case 0x6d:
1373 Vi = Vhp + Vbp + ve + v3 + v1;
1374 offset = mixer_offset<5>::value;
1375 break;
1376 case 0x6e:
1377 Vi = Vhp + Vbp + ve + v3 + v2;
1378 offset = mixer_offset<5>::value;
1379 break;
1380 case 0x6f:
1381 Vi = Vhp + Vbp + ve + v3 + v2 + v1;
1382 offset = mixer_offset<6>::value;
1383 break;
1384 case 0x70:
1385 Vi = Vhp + Vbp + Vlp;
1386 offset = mixer_offset<3>::value;
1387 break;
1388 case 0x71:
1389 Vi = Vhp + Vbp + Vlp + v1;
1390 offset = mixer_offset<4>::value;
1391 break;
1392 case 0x72:
1393 Vi = Vhp + Vbp + Vlp + v2;
1394 offset = mixer_offset<4>::value;
1395 break;
1396 case 0x73:
1397 Vi = Vhp + Vbp + Vlp + v2 + v1;
1398 offset = mixer_offset<5>::value;
1399 break;
1400 case 0x74:
1401 Vi = Vhp + Vbp + Vlp + v3;
1402 offset = mixer_offset<4>::value;
1403 break;
1404 case 0x75:
1405 Vi = Vhp + Vbp + Vlp + v3 + v1;
1406 offset = mixer_offset<5>::value;
1407 break;
1408 case 0x76:
1409 Vi = Vhp + Vbp + Vlp + v3 + v2;
1410 offset = mixer_offset<5>::value;
1411 break;
1412 case 0x77:
1413 Vi = Vhp + Vbp + Vlp + v3 + v2 + v1;
1414 offset = mixer_offset<6>::value;
1415 break;
1416 case 0x78:
1417 Vi = Vhp + Vbp + Vlp + ve;
1418 offset = mixer_offset<4>::value;
1419 break;
1420 case 0x79:
1421 Vi = Vhp + Vbp + Vlp + ve + v1;
1422 offset = mixer_offset<5>::value;
1423 break;
1424 case 0x7a:
1425 Vi = Vhp + Vbp + Vlp + ve + v2;
1426 offset = mixer_offset<5>::value;
1427 break;
1428 case 0x7b:
1429 Vi = Vhp + Vbp + Vlp + ve + v2 + v1;
1430 offset = mixer_offset<6>::value;
1431 break;
1432 case 0x7c:
1433 Vi = Vhp + Vbp + Vlp + ve + v3;
1434 offset = mixer_offset<5>::value;
1435 break;
1436 case 0x7d:
1437 Vi = Vhp + Vbp + Vlp + ve + v3 + v1;
1438 offset = mixer_offset<6>::value;
1439 break;
1440 case 0x7e:
1441 Vi = Vhp + Vbp + Vlp + ve + v3 + v2;
1442 offset = mixer_offset<6>::value;
1443 break;
1444 case 0x7f:
1445 Vi = Vhp + Vbp + Vlp + ve + v3 + v2 + v1;
1446 offset = mixer_offset<7>::value;
1447 break;
1448 }
1449
1450 // Sum the inputs in the mixer and run the mixer output through the gain.
1451 return (short)(f.gain[vol][f.mixer[offset + Vi]] - (1 << 15));
1452}
1453
1454
1455/*
1456Find output voltage in inverting gain and inverting summer SID op-amp
1457circuits, using a combination of Newton-Raphson and bisection.
1458
1459 ---R2--
1460 | |
1461 vi ---R1-----[A>----- vo
1462 vx
1463
1464From Kirchoff's current law it follows that
1465
1466 IR1f + IR2r = 0
1467
1468Substituting the triode mode transistor model K*W/L*(Vgst^2 - Vgdt^2)
1469for the currents, we get:
1470
1471 n*((Vddt - vx)^2 - (Vddt - vi)^2) + (Vddt - vx)^2 - (Vddt - vo)^2 = 0
1472
1473Our root function f can thus be written as:
1474
1475 f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - vo)^2 = 0
1476
1477We are using the mapping function x = vo - vx -> vx. We thus substitute
1478for vo = vx + x and get:
1479
1480 f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - (vx + x))^2 = 0
1481
1482Using substitution constants
1483
1484 a = n + 1
1485 b = Vddt
1486 c = n*(Vddt - vi)^2
1487
1488the equations for the root function and its derivative can be written as:
1489
1490 f = a*(b - vx)^2 - c - (b - (vx + x))^2
1491 df = 2*((b - (vx + x))*dvx - a*(b - vx)*dvx)
1492*/
1493RESID_INLINE
1494int Filter::solve_gain(opamp_t* opamp, int n, int vi, int& x, model_filter_t& mf)
1495{
1496 // Note that all variables are translated and scaled in order to fit
1497 // in 16 bits. It is not necessary to explicitly translate the variables here,
1498 // since they are all used in subtractions which cancel out the translation:
1499 // (a - t) - (b - t) = a - b
1500
1501 // Start off with an estimate of x and a root bracket [ak, bk].
1502 // f is increasing, so that f(ak) < 0 and f(bk) > 0.
1503 int ak = mf.ak, bk = mf.bk;
1504
1505 int a = n + (1 << 7); // Scaled by 2^7
1506 int b = mf.kVddt; // Scaled by m*2^16
1507 int b_vi = b - vi; // Scaled by m*2^16
1508 if (b_vi < 0) b_vi = 0;
1509 int c = n*int(unsigned(b_vi)*unsigned(b_vi) >> 12); // Scaled by m^2*2^27
1510
1511 for (;;) {
1512 int xk = x;
1513
1514 // Calculate f and df.
1515 int vx = opamp[x].vx; // Scaled by m*2^16
1516 int dvx = opamp[x].dvx; // Scaled by 2^11
1517
1518 // f = a*(b - vx)^2 - c - (b - vo)^2
1519 // df = 2*((b - vo)*dvx - a*(b - vx)*dvx)
1520 //
1521 int vo = vx + (x << 1) - (1 << 16);
1522 if (vo >= (1 << 16)) {
1523 vo = (1 << 16) - 1;
1524 }
1525 else if (vo < 0) {
1526 vo = 0;
1527 }
1528 int b_vx = b - vx;
1529 if (b_vx < 0) b_vx = 0;
1530 int b_vo = b - vo;
1531 if (b_vo < 0) b_vo = 0;
1532 // The dividend is scaled by m^2*2^27.
1533 int f = a*int(unsigned(b_vx)*unsigned(b_vx) >> 12) - c - int(unsigned(b_vo)*unsigned(b_vo) >> 5);
1534 // The divisor is scaled by m*2^11.
1535 int df = (((b_vo >> 1) - ((a*b_vx) >> 8))*dvx) >> 14;
1536 // The resulting quotient is thus scaled by m*2^16.
1537
1538 // Newton-Raphson step: xk1 = xk - f(xk)/f'(xk)
1539 // If f(xk) or f'(xk) are zero then we can't improve further.
1540 if (df) {
1541 x -= f/df;
1542 }
1543 if (unlikely(x == xk)) {
1544 // No further root improvement possible.
1545 return vo;
1546 }
1547
1548 // Narrow down root bracket.
1549 if (f < 0) {
1550 // f(xk) < 0
1551 ak = xk;
1552 }
1553 else {
1554 // f(xk) > 0
1555 bk = xk;
1556 }
1557
1558 if (unlikely(x <= ak) || unlikely(x >= bk)) {
1559 // Bisection step (ala Dekker's method).
1560 x = (ak + bk) >> 1;
1561 if (unlikely(x == ak)) {
1562 // No further bisection possible.
1563 return vo;
1564 }
1565 }
1566 }
1567}
1568
1569
1570/*
1571Find output voltage in inverting integrator SID op-amp circuits, using a
1572single fixpoint iteration step.
1573
1574A circuit diagram of a MOS 6581 integrator is shown below.
1575
1576 ---C---
1577 | |
1578 vi -----Rw-------[A>----- vo
1579 | | vx
1580 --Rs--
1581
1582From Kirchoff's current law it follows that
1583
1584 IRw + IRs + ICr = 0
1585
1586Using the formula for current through a capacitor, i = C*dv/dt, we get
1587
1588 IRw + IRs + C*(vc - vc0)/dt = 0
1589 dt/C*(IRw + IRs) + vc - vc0 = 0
1590 vc = vc0 - n*(IRw(vi,vx) + IRs(vi,vx))
1591
1592which may be rewritten as the following iterative fixpoint function:
1593
1594 vc = vc0 - n*(IRw(vi,g(vc)) + IRs(vi,g(vc)))
1595
1596To accurately calculate the currents through Rs and Rw, we need to use
1597transistor models. Rs has a gate voltage of Vdd = 12V, and can be
1598assumed to always be in triode mode. For Rw, the situation is rather
1599more complex, as it turns out that this transistor will operate in
1600both subthreshold, triode, and saturation modes.
1601
1602The Shichman-Hodges transistor model routinely used in textbooks may
1603be written as follows:
1604
1605 Ids = 0 , Vgst < 0 (subthreshold mode)
1606 Ids = K/2*W/L*(2*Vgst - Vds)*Vds , Vgst >= 0, Vds < Vgst (triode mode)
1607 Ids = K/2*W/L*Vgst^2 , Vgst >= 0, Vds >= Vgst (saturation mode)
1608
1609 where
1610 K = u*Cox (conductance)
1611 W/L = ratio between substrate width and length
1612 Vgst = Vg - Vs - Vt (overdrive voltage)
1613
1614This transistor model is also called the quadratic model.
1615
1616Note that the equation for the triode mode can be reformulated as
1617independent terms depending on Vgs and Vgd, respectively, by the
1618following substitution:
1619
1620 Vds = Vgst - (Vgst - Vds) = Vgst - Vgdt
1621
1622 Ids = K/2*W/L*(2*Vgst - Vds)*Vds
1623 = K/2*W/L*(2*Vgst - (Vgst - Vgdt)*(Vgst - Vgdt)
1624 = K/2*W/L*(Vgst + Vgdt)*(Vgst - Vgdt)
1625 = K/2*W/L*(Vgst^2 - Vgdt^2)
1626
1627This turns out to be a general equation which covers both the triode
1628and saturation modes (where the second term is 0 in saturation mode).
1629The equation is also symmetrical, i.e. it can calculate negative
1630currents without any change of parameters (since the terms for drain
1631and source are identical except for the sign).
1632
1633FIXME: Subthreshold as function of Vgs, Vgd.
1634 Ids = I0*e^(Vgst/(n*VT)) , Vgst < 0 (subthreshold mode)
1635
1636The remaining problem with the textbook model is that the transition
1637from subthreshold the triode/saturation is not continuous.
1638
1639Realizing that the subthreshold and triode/saturation modes may both
1640be defined by independent (and equal) terms of Vgs and Vds,
1641respectively, the corresponding terms can be blended into (equal)
1642continuous functions suitable for table lookup.
1643
1644The EKV model (Enz, Krummenacher and Vittoz) essentially performs this
1645blending using an elegant mathematical formulation:
1646
1647 Ids = Is*(if - ir)
1648 Is = ((2*u*Cox*Ut^2)/k)*W/L
1649 if = ln^2(1 + e^((k*(Vg - Vt) - Vs)/(2*Ut))
1650 ir = ln^2(1 + e^((k*(Vg - Vt) - Vd)/(2*Ut))
1651
1652For our purposes, the EKV model preserves two important properties
1653discussed above:
1654
1655- It consists of two independent terms, which can be represented by
1656 the same lookup table.
1657- It is symmetrical, i.e. it calculates current in both directions,
1658 facilitating a branch-free implementation.
1659
1660Rw in the circuit diagram above is a VCR (voltage controlled resistor),
1661as shown in the circuit diagram below.
1662
1663 Vw
1664
1665 |
1666 Vdd |
1667 |---|
1668 _|_ |
1669 -- --| Vg
1670 | __|__
1671 | ----- Rw
1672 | | |
1673 vi ------------ -------- vo
1674
1675
1676In order to calculalate the current through the VCR, its gate voltage
1677must be determined.
1678
1679Assuming triode mode and applying Kirchoff's current law, we get the
1680following equation for Vg:
1681
1682u*Cox/2*W/L*((Vddt - Vg)^2 - (Vddt - vi)^2 + (Vddt - Vg)^2 - (Vddt - Vw)^2) = 0
16832*(Vddt - Vg)^2 - (Vddt - vi)^2 - (Vddt - Vw)^2 = 0
1684(Vddt - Vg) = sqrt(((Vddt - vi)^2 + (Vddt - Vw)^2)/2)
1685
1686Vg = Vddt - sqrt(((Vddt - vi)^2 + (Vddt - Vw)^2)/2)
1687
1688*/
1689RESID_INLINE
1690int Filter::solve_integrate_6581(int dt, int vi, int& vx, int& vc, model_filter_t& mf)
1691{
1692 // Note that all variables are translated and scaled in order to fit
1693 // in 16 bits. It is not necessary to explicitly translate the variables here,
1694 // since they are all used in subtractions which cancel out the translation:
1695 // (a - t) - (b - t) = a - b
1696
1697 int kVddt = mf.kVddt; // Scaled by m*2^16
1698
1699 // "Snake" voltages for triode mode calculation.
1700 unsigned int Vgst = kVddt - vx;
1701 unsigned int Vgdt = kVddt - vi;
1702 unsigned int Vgdt_2 = Vgdt*Vgdt;
1703
1704 // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
1705 int n_I_snake = n_snake*(int(Vgst*Vgst - Vgdt_2) >> 15);
1706
1707 // VCR gate voltage. // Scaled by m*2^16
1708 // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
1709 int kVg = vcr_kVg[(Vddt_Vw_2 + (Vgdt_2 >> 1)) >> 16];
1710
1711 // VCR voltages for EKV model table lookup.
1712 int Vgs = kVg - vx;
1713 if (Vgs < 0) Vgs = 0;
1714 int Vgd = kVg - vi;
1715 if (Vgd < 0) Vgd = 0;
1716
1717 // VCR current, scaled by m*2^15*2^15 = m*2^30
1718 int n_I_vcr = int(unsigned(vcr_n_Ids_term[Vgs] - vcr_n_Ids_term[Vgd]) << 15);
1719
1720 // Change in capacitor charge.
1721 vc -= (n_I_snake + n_I_vcr)*dt;
1722
1723/*
1724 // FIXME: Determine whether this check is necessary.
1725 if (vc < mf.vc_min) {
1726 vc = mf.vc_min;
1727 }
1728 else if (vc > mf.vc_max) {
1729 vc = mf.vc_max;
1730 }
1731*/
1732
1733 // vx = g(vc)
1734 vx = mf.opamp_rev[(vc >> 15) + (1 << 15)];
1735
1736 // Return vo.
1737 return vx + (vc >> 14);
1738}
1739
1740/*
1741The 8580 integrator is similar to those found in 6581
1742but the resistance is formed by multiple NMOS transistors
1743in parallel controlled by the fc bits where the gate voltage
1744is driven by a temperature dependent voltage divider.
1745
1746 ---C---
1747 | |
1748 vi -----Rfc------[A>----- vo
1749 vx
1750
1751 IRfc + ICr = 0
1752 IRfc + C*(vc - vc0)/dt = 0
1753 dt/C*(IRfc) + vc - vc0 = 0
1754 vc = vc0 - n*(IRfc(vi,vx))
1755 vc = vc0 - n*(IRfc(vi,g(vc)))
1756
1757IRfc = K/2*W/L*(Vgst^2 - Vgdt^2) = n*((Vgt - vx)^2 - (Vgt - vi)^2)
1758*/
1759RESID_INLINE
1760int Filter::solve_integrate_8580(int dt, int vi, int& vx, int& vc, model_filter_t& mf)
1761{
1762 // Note that all variables are translated and scaled in order to fit
1763 // in 16 bits. It is not necessary to explicitly translate the variables here,
1764 // since they are all used in subtractions which cancel out the translation:
1765 // (a - t) - (b - t) = a - b
1766
1767 // Dac voltages.
1768 unsigned int Vgst = nVgt - vx;
1769 unsigned int Vgdt = (vi < nVgt) ? nVgt - vi : 0; // triode/saturation mode
1770
1771 // Dac current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
1772 int n_I_rfc = n_dac*(int(Vgst*Vgst - Vgdt*Vgdt) >> 15);
1773
1774 // Change in capacitor charge.
1775 vc -= n_I_rfc*dt;
1776
1777 // vx = g(vc)
1778 vx = mf.opamp_rev[(vc >> 15) + (1 << 15)];
1779
1780 // Return vo.
1781 return vx + (vc >> 14);
1782}
1783
1784#endif // RESID_INLINING || defined(RESID_FILTER_CC)
1785
1786} // namespace reSID
1787
1788#endif // not RESID_FILTER_H