libsidplayfp 2.3.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 --/ --1R2-- |
106// | ---R8-- | | ---R2-- |
107// | | | D2 |--/ --2R2--| | | ||--
108// ------[A>---------| |-----[A>-----||
109// D1 |--/ --4R2--| (4.25R2) ||--
110// $18 | | |
111// 0=open D0 --/ --8R2-- (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 | +--R8--+ +---R8--+ +---C---o +---C---o
330// 1=to filter | | | | | | | |
331// +------R8--o--o--[A>--o--Rfc-o--[A>--o--Rfc-o--[A>--o
332// ve (EXT IN) | | | |
333// D3 \ ---------------R8--o | | (CAP2A) | (CAP1A)
334// | v3 | | vhp | vbp | vlp
335// D2 | \ -----------R8--o +-----+ | |
336// | | v2 | | | |
337// D1 | | \ -------R8--o | +----------------+ |
338// | | | v1 | | | |
339// D0 | | | \ ---R8--+ | | +---------------------------+
340// | | | | | | |
341// R6 R6 R6 R6 R6 R6 R6
342// | | | | $18 | | | $18
343// | \ | | D7: 1=open \ \ \ D6 - D4: 0=open
344// | | | | | | |
345// +---o---o---o-------------o---o---+
346// |
347// | D3 +--/ --1R2--+
348// | +---R8--+ | | +---R2--+
349// | | | D2 o--/ --2R2--o | |
350// +---o--[A>--o------o o--o--[A>--o-- vo (AUDIO OUT)
351// D1 o--/ --4R2--o (4.25R2)
352// $18 | |
353// 0=open D0 +--/ --8R2--+ (8.75R2)
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 void set_Q();
555
556 // Filter enabled.
557 bool enabled;
558
559 // Filter cutoff frequency.
560 reg12 fc;
561
562 // Filter resonance.
563 reg8 res;
564
565 // Selects which voices to route through the filter.
566 reg8 filt;
567
568 // Selects which filter outputs to route into the mixer.
569 reg4 mode;
570
571 // Output master volume.
572 reg4 vol;
573
574 // Used to mask out EXT IN if not connected, and for test purposes
575 // (voice muting).
576 reg8 voice_mask;
577
578 // Select which inputs to route into the summer / mixer.
579 // These are derived from filt, mode, and voice_mask.
580 reg8 sum;
581 reg8 mix;
582
583 // State of filter.
584 int Vhp; // highpass
585 int Vbp; // bandpass
586 int Vbp_x, Vbp_vc;
587 int Vlp; // lowpass
588 int Vlp_x, Vlp_vc;
589 // Filter / mixer inputs.
590 int ve;
591 int v3;
592 int v2;
593 int v1;
594
595 chip_model sid_model;
596
597 typedef struct {
598 unsigned short vx;
599 short dvx;
600 } opamp_t;
601
602 typedef struct {
603 int kVddt; // K*(Vdd - Vth)
604 int voice_scale_s14;
605 int voice_DC;
606 int ak;
607 int bk;
608 int vc_min;
609 int vc_max;
610 double vo_N16; // Fixed point scaling for 16 bit op-amp output.
611
612 // Reverse op-amp transfer function.
613 unsigned short opamp_rev[1 << 16];
614 // Lookup tables for gain and summer op-amps in output stage / filter.
615 unsigned short summer[summer_offset<5>::value];
616 unsigned short gain[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 int _8_div_Q;
626
627 static int n_snake;
628
629 // 8580 only
630 int n_dac;
631
632 static int n_param;
633
634 // DAC gate voltage
635 int nVgt;
636
637 // Lookup tables for resonance
638 static unsigned short resonance[16][1 << 16];
639
640 int solve_gain(opamp_t* opamp, int n, int vi_t, int& x, model_filter_t& mf);
641 int solve_integrate_6581(int dt, int vi_t, int& x, int& vc, model_filter_t& mf);
642 int solve_integrate_8580(int dt, int vi_t, int& x, int& vc, model_filter_t& mf);
643
644 // VCR - 6581 only.
645 static unsigned short vcr_kVg[1 << 16];
646 static unsigned short vcr_n_Ids_term[1 << 16];
647 // Common parameters.
648 static model_filter_t model_filter[2];
649
650friend class SID;
651};
652
653
654// ----------------------------------------------------------------------------
655// Inline functions.
656// The following functions are defined inline because they are called every
657// time a sample is calculated.
658// ----------------------------------------------------------------------------
659
660#if RESID_INLINING || defined(RESID_FILTER_CC)
661
662// ----------------------------------------------------------------------------
663// SID clocking - 1 cycle.
664// ----------------------------------------------------------------------------
665RESID_INLINE
666void Filter::clock(int voice1, int voice2, int voice3)
667{
668 model_filter_t& f = model_filter[sid_model];
669
670 v1 = (voice1*f.voice_scale_s14 >> 18) + f.voice_DC;
671 v2 = (voice2*f.voice_scale_s14 >> 18) + f.voice_DC;
672 v3 = (voice3*f.voice_scale_s14 >> 18) + f.voice_DC;
673
674 // Sum inputs routed into the filter.
675 int Vi = 0;
676 int offset = 0;
677
678 switch (sum & 0xf) {
679 case 0x0:
680 Vi = 0;
681 offset = summer_offset<0>::value;
682 break;
683 case 0x1:
684 Vi = v1;
685 offset = summer_offset<1>::value;
686 break;
687 case 0x2:
688 Vi = v2;
689 offset = summer_offset<1>::value;
690 break;
691 case 0x3:
692 Vi = v2 + v1;
693 offset = summer_offset<2>::value;
694 break;
695 case 0x4:
696 Vi = v3;
697 offset = summer_offset<1>::value;
698 break;
699 case 0x5:
700 Vi = v3 + v1;
701 offset = summer_offset<2>::value;
702 break;
703 case 0x6:
704 Vi = v3 + v2;
705 offset = summer_offset<2>::value;
706 break;
707 case 0x7:
708 Vi = v3 + v2 + v1;
709 offset = summer_offset<3>::value;
710 break;
711 case 0x8:
712 Vi = ve;
713 offset = summer_offset<1>::value;
714 break;
715 case 0x9:
716 Vi = ve + v1;
717 offset = summer_offset<2>::value;
718 break;
719 case 0xa:
720 Vi = ve + v2;
721 offset = summer_offset<2>::value;
722 break;
723 case 0xb:
724 Vi = ve + v2 + v1;
725 offset = summer_offset<3>::value;
726 break;
727 case 0xc:
728 Vi = ve + v3;
729 offset = summer_offset<2>::value;
730 break;
731 case 0xd:
732 Vi = ve + v3 + v1;
733 offset = summer_offset<3>::value;
734 break;
735 case 0xe:
736 Vi = ve + v3 + v2;
737 offset = summer_offset<3>::value;
738 break;
739 case 0xf:
740 Vi = ve + v3 + v2 + v1;
741 offset = summer_offset<4>::value;
742 break;
743 }
744
745 // Calculate filter outputs.
746 if (sid_model == 0) {
747 // MOS 6581.
748 Vlp = solve_integrate_6581(1, Vbp, Vlp_x, Vlp_vc, f);
749 Vbp = solve_integrate_6581(1, Vhp, Vbp_x, Vbp_vc, f);
750 Vhp = f.summer[offset + f.gain[_8_div_Q][Vbp] + Vlp + Vi];
751 }
752 else {
753 // MOS 8580.
754 Vlp = solve_integrate_8580(1, Vbp, Vlp_x, Vlp_vc, f);
755 Vbp = solve_integrate_8580(1, Vhp, Vbp_x, Vbp_vc, f);
756 Vhp = f.summer[offset + resonance[res][Vbp] + Vlp + Vi];
757 }
758}
759
760// ----------------------------------------------------------------------------
761// SID clocking - delta_t cycles.
762// ----------------------------------------------------------------------------
763RESID_INLINE
764void Filter::clock(cycle_count delta_t, int voice1, int voice2, int voice3)
765{
766 model_filter_t& f = model_filter[sid_model];
767
768 v1 = (voice1*f.voice_scale_s14 >> 18) + f.voice_DC;
769 v2 = (voice2*f.voice_scale_s14 >> 18) + f.voice_DC;
770 v3 = (voice3*f.voice_scale_s14 >> 18) + f.voice_DC;
771
772 // Enable filter on/off.
773 // This is not really part of SID, but is useful for testing.
774 // On slow CPUs it may be necessary to bypass the filter to lower the CPU
775 // load.
776 if (unlikely(!enabled)) {
777 return;
778 }
779
780 // Sum inputs routed into the filter.
781 int Vi = 0;
782 int offset = 0;
783
784 switch (sum & 0xf) {
785 case 0x0:
786 Vi = 0;
787 offset = summer_offset<0>::value;
788 break;
789 case 0x1:
790 Vi = v1;
791 offset = summer_offset<1>::value;
792 break;
793 case 0x2:
794 Vi = v2;
795 offset = summer_offset<1>::value;
796 break;
797 case 0x3:
798 Vi = v2 + v1;
799 offset = summer_offset<2>::value;
800 break;
801 case 0x4:
802 Vi = v3;
803 offset = summer_offset<1>::value;
804 break;
805 case 0x5:
806 Vi = v3 + v1;
807 offset = summer_offset<2>::value;
808 break;
809 case 0x6:
810 Vi = v3 + v2;
811 offset = summer_offset<2>::value;
812 break;
813 case 0x7:
814 Vi = v3 + v2 + v1;
815 offset = summer_offset<3>::value;
816 break;
817 case 0x8:
818 Vi = ve;
819 offset = summer_offset<1>::value;
820 break;
821 case 0x9:
822 Vi = ve + v1;
823 offset = summer_offset<2>::value;
824 break;
825 case 0xa:
826 Vi = ve + v2;
827 offset = summer_offset<2>::value;
828 break;
829 case 0xb:
830 Vi = ve + v2 + v1;
831 offset = summer_offset<3>::value;
832 break;
833 case 0xc:
834 Vi = ve + v3;
835 offset = summer_offset<2>::value;
836 break;
837 case 0xd:
838 Vi = ve + v3 + v1;
839 offset = summer_offset<3>::value;
840 break;
841 case 0xe:
842 Vi = ve + v3 + v2;
843 offset = summer_offset<3>::value;
844 break;
845 case 0xf:
846 Vi = ve + v3 + v2 + v1;
847 offset = summer_offset<4>::value;
848 break;
849 }
850
851 // Maximum delta cycles for filter fixpoint iteration to converge
852 // is approximately 3.
853 cycle_count delta_t_flt = 3;
854
855 if (sid_model == 0) {
856 // MOS 6581.
857 while (delta_t) {
858 if (unlikely(delta_t < delta_t_flt)) {
859 delta_t_flt = delta_t;
860 }
861
862 // Calculate filter outputs.
863 Vlp = solve_integrate_6581(delta_t_flt, Vbp, Vlp_x, Vlp_vc, f);
864 Vbp = solve_integrate_6581(delta_t_flt, Vhp, Vbp_x, Vbp_vc, f);
865 Vhp = f.summer[offset + f.gain[_8_div_Q][Vbp] + Vlp + Vi];
866
867 delta_t -= delta_t_flt;
868 }
869 }
870 else {
871 // MOS 8580.
872 while (delta_t) {
873 if (unlikely(delta_t < delta_t_flt)) {
874 delta_t_flt = delta_t;
875 }
876
877 // Calculate filter outputs.
878 Vlp = solve_integrate_8580(delta_t_flt, Vbp, Vlp_x, Vlp_vc, f);
879 Vbp = solve_integrate_8580(delta_t_flt, Vhp, Vbp_x, Vbp_vc, f);
880 Vhp = f.summer[offset + resonance[res][Vbp] + Vlp + Vi];
881
882 delta_t -= delta_t_flt;
883 }
884 }
885}
886
887
888// ----------------------------------------------------------------------------
889// SID audio input (16 bits).
890// ----------------------------------------------------------------------------
891RESID_INLINE
892void Filter::input(short sample)
893{
894 // Scale to three times the peak-to-peak for one voice and add the op-amp
895 // "zero" DC level.
896 // NB! Adding the op-amp "zero" DC level is a (wildly inaccurate)
897 // approximation of feeding the input through an AC coupling capacitor.
898 // This could be implemented as a separate filter circuit, however the
899 // primary use of the emulator is not to process external signals.
900 // The upside is that the MOS8580 "digi boost" works without a separate (DC)
901 // input interface.
902 // Note that the input is 16 bits, compared to the 20 bit voice output.
903 model_filter_t& f = model_filter[sid_model];
904 ve = (sample*f.voice_scale_s14*3 >> 14) + f.mixer[0];
905}
906
907
908// ----------------------------------------------------------------------------
909// SID audio output (16 bits).
910// ----------------------------------------------------------------------------
911RESID_INLINE
912short Filter::output()
913{
914 model_filter_t& f = model_filter[sid_model];
915
916 // Writing the switch below manually would be tedious and error-prone;
917 // it is rather generated by the following Perl program:
918
919 /*
920my @i = qw(v1 v2 v3 ve Vlp Vbp Vhp);
921for my $mix (0..2**@i-1) {
922 print sprintf(" case 0x%02x:\n", $mix);
923 my @sum;
924 for (@i) {
925 unshift(@sum, $_) if $mix & 0x01;
926 $mix >>= 1;
927 }
928 my $sum = join(" + ", @sum) || "0";
929 print " Vi = $sum;\n";
930 print " offset = mixer_offset<" . @sum . ">::value;\n";
931 print " break;\n";
932}
933 */
934
935 // Sum inputs routed into the mixer.
936 int Vi = 0;
937 int offset = 0;
938
939 switch (mix & 0x7f) {
940 case 0x00:
941 Vi = 0;
942 offset = mixer_offset<0>::value;
943 break;
944 case 0x01:
945 Vi = v1;
946 offset = mixer_offset<1>::value;
947 break;
948 case 0x02:
949 Vi = v2;
950 offset = mixer_offset<1>::value;
951 break;
952 case 0x03:
953 Vi = v2 + v1;
954 offset = mixer_offset<2>::value;
955 break;
956 case 0x04:
957 Vi = v3;
958 offset = mixer_offset<1>::value;
959 break;
960 case 0x05:
961 Vi = v3 + v1;
962 offset = mixer_offset<2>::value;
963 break;
964 case 0x06:
965 Vi = v3 + v2;
966 offset = mixer_offset<2>::value;
967 break;
968 case 0x07:
969 Vi = v3 + v2 + v1;
970 offset = mixer_offset<3>::value;
971 break;
972 case 0x08:
973 Vi = ve;
974 offset = mixer_offset<1>::value;
975 break;
976 case 0x09:
977 Vi = ve + v1;
978 offset = mixer_offset<2>::value;
979 break;
980 case 0x0a:
981 Vi = ve + v2;
982 offset = mixer_offset<2>::value;
983 break;
984 case 0x0b:
985 Vi = ve + v2 + v1;
986 offset = mixer_offset<3>::value;
987 break;
988 case 0x0c:
989 Vi = ve + v3;
990 offset = mixer_offset<2>::value;
991 break;
992 case 0x0d:
993 Vi = ve + v3 + v1;
994 offset = mixer_offset<3>::value;
995 break;
996 case 0x0e:
997 Vi = ve + v3 + v2;
998 offset = mixer_offset<3>::value;
999 break;
1000 case 0x0f:
1001 Vi = ve + v3 + v2 + v1;
1002 offset = mixer_offset<4>::value;
1003 break;
1004 case 0x10:
1005 Vi = Vlp;
1006 offset = mixer_offset<1>::value;
1007 break;
1008 case 0x11:
1009 Vi = Vlp + v1;
1010 offset = mixer_offset<2>::value;
1011 break;
1012 case 0x12:
1013 Vi = Vlp + v2;
1014 offset = mixer_offset<2>::value;
1015 break;
1016 case 0x13:
1017 Vi = Vlp + v2 + v1;
1018 offset = mixer_offset<3>::value;
1019 break;
1020 case 0x14:
1021 Vi = Vlp + v3;
1022 offset = mixer_offset<2>::value;
1023 break;
1024 case 0x15:
1025 Vi = Vlp + v3 + v1;
1026 offset = mixer_offset<3>::value;
1027 break;
1028 case 0x16:
1029 Vi = Vlp + v3 + v2;
1030 offset = mixer_offset<3>::value;
1031 break;
1032 case 0x17:
1033 Vi = Vlp + v3 + v2 + v1;
1034 offset = mixer_offset<4>::value;
1035 break;
1036 case 0x18:
1037 Vi = Vlp + ve;
1038 offset = mixer_offset<2>::value;
1039 break;
1040 case 0x19:
1041 Vi = Vlp + ve + v1;
1042 offset = mixer_offset<3>::value;
1043 break;
1044 case 0x1a:
1045 Vi = Vlp + ve + v2;
1046 offset = mixer_offset<3>::value;
1047 break;
1048 case 0x1b:
1049 Vi = Vlp + ve + v2 + v1;
1050 offset = mixer_offset<4>::value;
1051 break;
1052 case 0x1c:
1053 Vi = Vlp + ve + v3;
1054 offset = mixer_offset<3>::value;
1055 break;
1056 case 0x1d:
1057 Vi = Vlp + ve + v3 + v1;
1058 offset = mixer_offset<4>::value;
1059 break;
1060 case 0x1e:
1061 Vi = Vlp + ve + v3 + v2;
1062 offset = mixer_offset<4>::value;
1063 break;
1064 case 0x1f:
1065 Vi = Vlp + ve + v3 + v2 + v1;
1066 offset = mixer_offset<5>::value;
1067 break;
1068 case 0x20:
1069 Vi = Vbp;
1070 offset = mixer_offset<1>::value;
1071 break;
1072 case 0x21:
1073 Vi = Vbp + v1;
1074 offset = mixer_offset<2>::value;
1075 break;
1076 case 0x22:
1077 Vi = Vbp + v2;
1078 offset = mixer_offset<2>::value;
1079 break;
1080 case 0x23:
1081 Vi = Vbp + v2 + v1;
1082 offset = mixer_offset<3>::value;
1083 break;
1084 case 0x24:
1085 Vi = Vbp + v3;
1086 offset = mixer_offset<2>::value;
1087 break;
1088 case 0x25:
1089 Vi = Vbp + v3 + v1;
1090 offset = mixer_offset<3>::value;
1091 break;
1092 case 0x26:
1093 Vi = Vbp + v3 + v2;
1094 offset = mixer_offset<3>::value;
1095 break;
1096 case 0x27:
1097 Vi = Vbp + v3 + v2 + v1;
1098 offset = mixer_offset<4>::value;
1099 break;
1100 case 0x28:
1101 Vi = Vbp + ve;
1102 offset = mixer_offset<2>::value;
1103 break;
1104 case 0x29:
1105 Vi = Vbp + ve + v1;
1106 offset = mixer_offset<3>::value;
1107 break;
1108 case 0x2a:
1109 Vi = Vbp + ve + v2;
1110 offset = mixer_offset<3>::value;
1111 break;
1112 case 0x2b:
1113 Vi = Vbp + ve + v2 + v1;
1114 offset = mixer_offset<4>::value;
1115 break;
1116 case 0x2c:
1117 Vi = Vbp + ve + v3;
1118 offset = mixer_offset<3>::value;
1119 break;
1120 case 0x2d:
1121 Vi = Vbp + ve + v3 + v1;
1122 offset = mixer_offset<4>::value;
1123 break;
1124 case 0x2e:
1125 Vi = Vbp + ve + v3 + v2;
1126 offset = mixer_offset<4>::value;
1127 break;
1128 case 0x2f:
1129 Vi = Vbp + ve + v3 + v2 + v1;
1130 offset = mixer_offset<5>::value;
1131 break;
1132 case 0x30:
1133 Vi = Vbp + Vlp;
1134 offset = mixer_offset<2>::value;
1135 break;
1136 case 0x31:
1137 Vi = Vbp + Vlp + v1;
1138 offset = mixer_offset<3>::value;
1139 break;
1140 case 0x32:
1141 Vi = Vbp + Vlp + v2;
1142 offset = mixer_offset<3>::value;
1143 break;
1144 case 0x33:
1145 Vi = Vbp + Vlp + v2 + v1;
1146 offset = mixer_offset<4>::value;
1147 break;
1148 case 0x34:
1149 Vi = Vbp + Vlp + v3;
1150 offset = mixer_offset<3>::value;
1151 break;
1152 case 0x35:
1153 Vi = Vbp + Vlp + v3 + v1;
1154 offset = mixer_offset<4>::value;
1155 break;
1156 case 0x36:
1157 Vi = Vbp + Vlp + v3 + v2;
1158 offset = mixer_offset<4>::value;
1159 break;
1160 case 0x37:
1161 Vi = Vbp + Vlp + v3 + v2 + v1;
1162 offset = mixer_offset<5>::value;
1163 break;
1164 case 0x38:
1165 Vi = Vbp + Vlp + ve;
1166 offset = mixer_offset<3>::value;
1167 break;
1168 case 0x39:
1169 Vi = Vbp + Vlp + ve + v1;
1170 offset = mixer_offset<4>::value;
1171 break;
1172 case 0x3a:
1173 Vi = Vbp + Vlp + ve + v2;
1174 offset = mixer_offset<4>::value;
1175 break;
1176 case 0x3b:
1177 Vi = Vbp + Vlp + ve + v2 + v1;
1178 offset = mixer_offset<5>::value;
1179 break;
1180 case 0x3c:
1181 Vi = Vbp + Vlp + ve + v3;
1182 offset = mixer_offset<4>::value;
1183 break;
1184 case 0x3d:
1185 Vi = Vbp + Vlp + ve + v3 + v1;
1186 offset = mixer_offset<5>::value;
1187 break;
1188 case 0x3e:
1189 Vi = Vbp + Vlp + ve + v3 + v2;
1190 offset = mixer_offset<5>::value;
1191 break;
1192 case 0x3f:
1193 Vi = Vbp + Vlp + ve + v3 + v2 + v1;
1194 offset = mixer_offset<6>::value;
1195 break;
1196 case 0x40:
1197 Vi = Vhp;
1198 offset = mixer_offset<1>::value;
1199 break;
1200 case 0x41:
1201 Vi = Vhp + v1;
1202 offset = mixer_offset<2>::value;
1203 break;
1204 case 0x42:
1205 Vi = Vhp + v2;
1206 offset = mixer_offset<2>::value;
1207 break;
1208 case 0x43:
1209 Vi = Vhp + v2 + v1;
1210 offset = mixer_offset<3>::value;
1211 break;
1212 case 0x44:
1213 Vi = Vhp + v3;
1214 offset = mixer_offset<2>::value;
1215 break;
1216 case 0x45:
1217 Vi = Vhp + v3 + v1;
1218 offset = mixer_offset<3>::value;
1219 break;
1220 case 0x46:
1221 Vi = Vhp + v3 + v2;
1222 offset = mixer_offset<3>::value;
1223 break;
1224 case 0x47:
1225 Vi = Vhp + v3 + v2 + v1;
1226 offset = mixer_offset<4>::value;
1227 break;
1228 case 0x48:
1229 Vi = Vhp + ve;
1230 offset = mixer_offset<2>::value;
1231 break;
1232 case 0x49:
1233 Vi = Vhp + ve + v1;
1234 offset = mixer_offset<3>::value;
1235 break;
1236 case 0x4a:
1237 Vi = Vhp + ve + v2;
1238 offset = mixer_offset<3>::value;
1239 break;
1240 case 0x4b:
1241 Vi = Vhp + ve + v2 + v1;
1242 offset = mixer_offset<4>::value;
1243 break;
1244 case 0x4c:
1245 Vi = Vhp + ve + v3;
1246 offset = mixer_offset<3>::value;
1247 break;
1248 case 0x4d:
1249 Vi = Vhp + ve + v3 + v1;
1250 offset = mixer_offset<4>::value;
1251 break;
1252 case 0x4e:
1253 Vi = Vhp + ve + v3 + v2;
1254 offset = mixer_offset<4>::value;
1255 break;
1256 case 0x4f:
1257 Vi = Vhp + ve + v3 + v2 + v1;
1258 offset = mixer_offset<5>::value;
1259 break;
1260 case 0x50:
1261 Vi = Vhp + Vlp;
1262 offset = mixer_offset<2>::value;
1263 break;
1264 case 0x51:
1265 Vi = Vhp + Vlp + v1;
1266 offset = mixer_offset<3>::value;
1267 break;
1268 case 0x52:
1269 Vi = Vhp + Vlp + v2;
1270 offset = mixer_offset<3>::value;
1271 break;
1272 case 0x53:
1273 Vi = Vhp + Vlp + v2 + v1;
1274 offset = mixer_offset<4>::value;
1275 break;
1276 case 0x54:
1277 Vi = Vhp + Vlp + v3;
1278 offset = mixer_offset<3>::value;
1279 break;
1280 case 0x55:
1281 Vi = Vhp + Vlp + v3 + v1;
1282 offset = mixer_offset<4>::value;
1283 break;
1284 case 0x56:
1285 Vi = Vhp + Vlp + v3 + v2;
1286 offset = mixer_offset<4>::value;
1287 break;
1288 case 0x57:
1289 Vi = Vhp + Vlp + v3 + v2 + v1;
1290 offset = mixer_offset<5>::value;
1291 break;
1292 case 0x58:
1293 Vi = Vhp + Vlp + ve;
1294 offset = mixer_offset<3>::value;
1295 break;
1296 case 0x59:
1297 Vi = Vhp + Vlp + ve + v1;
1298 offset = mixer_offset<4>::value;
1299 break;
1300 case 0x5a:
1301 Vi = Vhp + Vlp + ve + v2;
1302 offset = mixer_offset<4>::value;
1303 break;
1304 case 0x5b:
1305 Vi = Vhp + Vlp + ve + v2 + v1;
1306 offset = mixer_offset<5>::value;
1307 break;
1308 case 0x5c:
1309 Vi = Vhp + Vlp + ve + v3;
1310 offset = mixer_offset<4>::value;
1311 break;
1312 case 0x5d:
1313 Vi = Vhp + Vlp + ve + v3 + v1;
1314 offset = mixer_offset<5>::value;
1315 break;
1316 case 0x5e:
1317 Vi = Vhp + Vlp + ve + v3 + v2;
1318 offset = mixer_offset<5>::value;
1319 break;
1320 case 0x5f:
1321 Vi = Vhp + Vlp + ve + v3 + v2 + v1;
1322 offset = mixer_offset<6>::value;
1323 break;
1324 case 0x60:
1325 Vi = Vhp + Vbp;
1326 offset = mixer_offset<2>::value;
1327 break;
1328 case 0x61:
1329 Vi = Vhp + Vbp + v1;
1330 offset = mixer_offset<3>::value;
1331 break;
1332 case 0x62:
1333 Vi = Vhp + Vbp + v2;
1334 offset = mixer_offset<3>::value;
1335 break;
1336 case 0x63:
1337 Vi = Vhp + Vbp + v2 + v1;
1338 offset = mixer_offset<4>::value;
1339 break;
1340 case 0x64:
1341 Vi = Vhp + Vbp + v3;
1342 offset = mixer_offset<3>::value;
1343 break;
1344 case 0x65:
1345 Vi = Vhp + Vbp + v3 + v1;
1346 offset = mixer_offset<4>::value;
1347 break;
1348 case 0x66:
1349 Vi = Vhp + Vbp + v3 + v2;
1350 offset = mixer_offset<4>::value;
1351 break;
1352 case 0x67:
1353 Vi = Vhp + Vbp + v3 + v2 + v1;
1354 offset = mixer_offset<5>::value;
1355 break;
1356 case 0x68:
1357 Vi = Vhp + Vbp + ve;
1358 offset = mixer_offset<3>::value;
1359 break;
1360 case 0x69:
1361 Vi = Vhp + Vbp + ve + v1;
1362 offset = mixer_offset<4>::value;
1363 break;
1364 case 0x6a:
1365 Vi = Vhp + Vbp + ve + v2;
1366 offset = mixer_offset<4>::value;
1367 break;
1368 case 0x6b:
1369 Vi = Vhp + Vbp + ve + v2 + v1;
1370 offset = mixer_offset<5>::value;
1371 break;
1372 case 0x6c:
1373 Vi = Vhp + Vbp + ve + v3;
1374 offset = mixer_offset<4>::value;
1375 break;
1376 case 0x6d:
1377 Vi = Vhp + Vbp + ve + v3 + v1;
1378 offset = mixer_offset<5>::value;
1379 break;
1380 case 0x6e:
1381 Vi = Vhp + Vbp + ve + v3 + v2;
1382 offset = mixer_offset<5>::value;
1383 break;
1384 case 0x6f:
1385 Vi = Vhp + Vbp + ve + v3 + v2 + v1;
1386 offset = mixer_offset<6>::value;
1387 break;
1388 case 0x70:
1389 Vi = Vhp + Vbp + Vlp;
1390 offset = mixer_offset<3>::value;
1391 break;
1392 case 0x71:
1393 Vi = Vhp + Vbp + Vlp + v1;
1394 offset = mixer_offset<4>::value;
1395 break;
1396 case 0x72:
1397 Vi = Vhp + Vbp + Vlp + v2;
1398 offset = mixer_offset<4>::value;
1399 break;
1400 case 0x73:
1401 Vi = Vhp + Vbp + Vlp + v2 + v1;
1402 offset = mixer_offset<5>::value;
1403 break;
1404 case 0x74:
1405 Vi = Vhp + Vbp + Vlp + v3;
1406 offset = mixer_offset<4>::value;
1407 break;
1408 case 0x75:
1409 Vi = Vhp + Vbp + Vlp + v3 + v1;
1410 offset = mixer_offset<5>::value;
1411 break;
1412 case 0x76:
1413 Vi = Vhp + Vbp + Vlp + v3 + v2;
1414 offset = mixer_offset<5>::value;
1415 break;
1416 case 0x77:
1417 Vi = Vhp + Vbp + Vlp + v3 + v2 + v1;
1418 offset = mixer_offset<6>::value;
1419 break;
1420 case 0x78:
1421 Vi = Vhp + Vbp + Vlp + ve;
1422 offset = mixer_offset<4>::value;
1423 break;
1424 case 0x79:
1425 Vi = Vhp + Vbp + Vlp + ve + v1;
1426 offset = mixer_offset<5>::value;
1427 break;
1428 case 0x7a:
1429 Vi = Vhp + Vbp + Vlp + ve + v2;
1430 offset = mixer_offset<5>::value;
1431 break;
1432 case 0x7b:
1433 Vi = Vhp + Vbp + Vlp + ve + v2 + v1;
1434 offset = mixer_offset<6>::value;
1435 break;
1436 case 0x7c:
1437 Vi = Vhp + Vbp + Vlp + ve + v3;
1438 offset = mixer_offset<5>::value;
1439 break;
1440 case 0x7d:
1441 Vi = Vhp + Vbp + Vlp + ve + v3 + v1;
1442 offset = mixer_offset<6>::value;
1443 break;
1444 case 0x7e:
1445 Vi = Vhp + Vbp + Vlp + ve + v3 + v2;
1446 offset = mixer_offset<6>::value;
1447 break;
1448 case 0x7f:
1449 Vi = Vhp + Vbp + Vlp + ve + v3 + v2 + v1;
1450 offset = mixer_offset<7>::value;
1451 break;
1452 }
1453
1454 // Sum the inputs in the mixer and run the mixer output through the gain.
1455 return (short)(f.gain[vol][f.mixer[offset + Vi]] - (1 << 15));
1456}
1457
1458
1459/*
1460Find output voltage in inverting gain and inverting summer SID op-amp
1461circuits, using a combination of Newton-Raphson and bisection.
1462
1463 ---R2--
1464 | |
1465 vi ---R1-----[A>----- vo
1466 vx
1467
1468From Kirchoff's current law it follows that
1469
1470 IR1f + IR2r = 0
1471
1472Substituting the triode mode transistor model K*W/L*(Vgst^2 - Vgdt^2)
1473for the currents, we get:
1474
1475 n*((Vddt - vx)^2 - (Vddt - vi)^2) + (Vddt - vx)^2 - (Vddt - vo)^2 = 0
1476
1477Our root function f can thus be written as:
1478
1479 f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - vo)^2 = 0
1480
1481We are using the mapping function x = vo - vx -> vx. We thus substitute
1482for vo = vx + x and get:
1483
1484 f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - (vx + x))^2 = 0
1485
1486Using substitution constants
1487
1488 a = n + 1
1489 b = Vddt
1490 c = n*(Vddt - vi)^2
1491
1492the equations for the root function and its derivative can be written as:
1493
1494 f = a*(b - vx)^2 - c - (b - (vx + x))^2
1495 df = 2*((b - (vx + x))*(dvx + 1) - a*(b - vx)*dvx)
1496*/
1497RESID_INLINE
1498int Filter::solve_gain(opamp_t* opamp, int n, int vi, int& x, model_filter_t& mf)
1499{
1500 // Note that all variables are translated and scaled in order to fit
1501 // in 16 bits. It is not necessary to explicitly translate the variables here,
1502 // since they are all used in subtractions which cancel out the translation:
1503 // (a - t) - (b - t) = a - b
1504
1505 // Start off with an estimate of x and a root bracket [ak, bk].
1506 // f is increasing, so that f(ak) < 0 and f(bk) > 0.
1507 int ak = mf.ak, bk = mf.bk;
1508
1509 int a = n + (1 << 7); // Scaled by 2^7
1510 int b = mf.kVddt; // Scaled by m*2^16
1511 int b_vi = b - vi; // Scaled by m*2^16
1512 if (b_vi < 0) b_vi = 0;
1513 int c = n*int(unsigned(b_vi)*unsigned(b_vi) >> 12); // Scaled by m^2*2^27
1514
1515 for (;;) {
1516 int xk = x;
1517
1518 // Calculate f and df.
1519 int vx = opamp[x].vx; // Scaled by m*2^16
1520 int dvx = opamp[x].dvx; // Scaled by 2^11
1521
1522 // f = a*(b - vx)^2 - c - (b - vo)^2
1523 // df = 2*((b - vo)*(dvx + 1) - a*(b - vx)*dvx)
1524 //
1525 int vo = vx + (x << 1) - (1 << 16);
1526 if (vo >= (1 << 16)) {
1527 vo = (1 << 16) - 1;
1528 }
1529 else if (vo < 0) {
1530 vo = 0;
1531 }
1532 int b_vx = b - vx;
1533 if (b_vx < 0) b_vx = 0;
1534 int b_vo = b - vo;
1535 if (b_vo < 0) b_vo = 0;
1536 // The dividend is scaled by m^2*2^27.
1537 int f = a*int(unsigned(b_vx)*unsigned(b_vx) >> 12) - c - int(unsigned(b_vo)*unsigned(b_vo) >> 5);
1538 // The divisor is scaled by m*2^11.
1539 int df = ((b_vo*(dvx + (1 << 11)) >> 1) - (a*(b_vx*dvx >> 8))) >> 14;
1540 // The resulting quotient is thus scaled by m*2^16.
1541
1542 // Newton-Raphson step: xk1 = xk - f(xk)/f'(xk)
1543 // If f(xk) or f'(xk) are zero then we can't improve further.
1544 if (df) {
1545 x -= f/df;
1546 }
1547 if (unlikely(x == xk)) {
1548 // No further root improvement possible.
1549 return vo;
1550 }
1551
1552 // Narrow down root bracket.
1553 if (f < 0) {
1554 // f(xk) < 0
1555 ak = xk;
1556 }
1557 else {
1558 // f(xk) > 0
1559 bk = xk;
1560 }
1561
1562 if (unlikely(x <= ak) || unlikely(x >= bk)) {
1563 // Bisection step (ala Dekker's method).
1564 x = (ak + bk) >> 1;
1565 if (unlikely(x == ak)) {
1566 // No further bisection possible.
1567 return vo;
1568 }
1569 }
1570 }
1571}
1572
1573
1574/*
1575Find output voltage in inverting integrator SID op-amp circuits, using a
1576single fixpoint iteration step.
1577
1578A circuit diagram of a MOS 6581 integrator is shown below.
1579
1580 ---C---
1581 | |
1582 vi -----Rw-------[A>----- vo
1583 | | vx
1584 --Rs--
1585
1586From Kirchoff's current law it follows that
1587
1588 IRw + IRs + ICr = 0
1589
1590Using the formula for current through a capacitor, i = C*dv/dt, we get
1591
1592 IRw + IRs + C*(vc - vc0)/dt = 0
1593 dt/C*(IRw + IRs) + vc - vc0 = 0
1594 vc = vc0 - n*(IRw(vi,vx) + IRs(vi,vx))
1595
1596which may be rewritten as the following iterative fixpoint function:
1597
1598 vc = vc0 - n*(IRw(vi,g(vc)) + IRs(vi,g(vc)))
1599
1600To accurately calculate the currents through Rs and Rw, we need to use
1601transistor models. Rs has a gate voltage of Vdd = 12V, and can be
1602assumed to always be in triode mode. For Rw, the situation is rather
1603more complex, as it turns out that this transistor will operate in
1604both subthreshold, triode, and saturation modes.
1605
1606The Shichman-Hodges transistor model routinely used in textbooks may
1607be written as follows:
1608
1609 Ids = 0 , Vgst < 0 (subthreshold mode)
1610 Ids = K/2*W/L*(2*Vgst - Vds)*Vds , Vgst >= 0, Vds < Vgst (triode mode)
1611 Ids = K/2*W/L*Vgst^2 , Vgst >= 0, Vds >= Vgst (saturation mode)
1612
1613 where
1614 K = u*Cox (conductance)
1615 W/L = ratio between substrate width and length
1616 Vgst = Vg - Vs - Vt (overdrive voltage)
1617
1618This transistor model is also called the quadratic model.
1619
1620Note that the equation for the triode mode can be reformulated as
1621independent terms depending on Vgs and Vgd, respectively, by the
1622following substitution:
1623
1624 Vds = Vgst - (Vgst - Vds) = Vgst - Vgdt
1625
1626 Ids = K/2*W/L*(2*Vgst - Vds)*Vds
1627 = K/2*W/L*(2*Vgst - (Vgst - Vgdt)*(Vgst - Vgdt)
1628 = K/2*W/L*(Vgst + Vgdt)*(Vgst - Vgdt)
1629 = K/2*W/L*(Vgst^2 - Vgdt^2)
1630
1631This turns out to be a general equation which covers both the triode
1632and saturation modes (where the second term is 0 in saturation mode).
1633The equation is also symmetrical, i.e. it can calculate negative
1634currents without any change of parameters (since the terms for drain
1635and source are identical except for the sign).
1636
1637FIXME: Subthreshold as function of Vgs, Vgd.
1638 Ids = I0*e^(Vgst/(n*VT)) , Vgst < 0 (subthreshold mode)
1639
1640The remaining problem with the textbook model is that the transition
1641from subthreshold the triode/saturation is not continuous.
1642
1643Realizing that the subthreshold and triode/saturation modes may both
1644be defined by independent (and equal) terms of Vgs and Vds,
1645respectively, the corresponding terms can be blended into (equal)
1646continuous functions suitable for table lookup.
1647
1648The EKV model (Enz, Krummenacher and Vittoz) essentially performs this
1649blending using an elegant mathematical formulation:
1650
1651 Ids = Is*(if - ir)
1652 Is = ((2*u*Cox*Ut^2)/k)*W/L
1653 if = ln^2(1 + e^((k*(Vg - Vt) - Vs)/(2*Ut))
1654 ir = ln^2(1 + e^((k*(Vg - Vt) - Vd)/(2*Ut))
1655
1656For our purposes, the EKV model preserves two important properties
1657discussed above:
1658
1659- It consists of two independent terms, which can be represented by
1660 the same lookup table.
1661- It is symmetrical, i.e. it calculates current in both directions,
1662 facilitating a branch-free implementation.
1663
1664Rw in the circuit diagram above is a VCR (voltage controlled resistor),
1665as shown in the circuit diagram below.
1666
1667 Vw
1668
1669 |
1670 Vdd |
1671 |---|
1672 _|_ |
1673 -- --| Vg
1674 | __|__
1675 | ----- Rw
1676 | | |
1677 vi ------------ -------- vo
1678
1679
1680In order to calculalate the current through the VCR, its gate voltage
1681must be determined.
1682
1683Assuming triode mode and applying Kirchoff's current law, we get the
1684following equation for Vg:
1685
1686u*Cox/2*W/L*((Vddt - Vg)^2 - (Vddt - vi)^2 + (Vddt - Vg)^2 - (Vddt - Vw)^2) = 0
16872*(Vddt - Vg)^2 - (Vddt - vi)^2 - (Vddt - Vw)^2 = 0
1688(Vddt - Vg) = sqrt(((Vddt - vi)^2 + (Vddt - Vw)^2)/2)
1689
1690Vg = Vddt - sqrt(((Vddt - vi)^2 + (Vddt - Vw)^2)/2)
1691
1692*/
1693RESID_INLINE
1694int Filter::solve_integrate_6581(int dt, int vi, int& vx, int& vc, model_filter_t& mf)
1695{
1696 // Note that all variables are translated and scaled in order to fit
1697 // in 16 bits. It is not necessary to explicitly translate the variables here,
1698 // since they are all used in subtractions which cancel out the translation:
1699 // (a - t) - (b - t) = a - b
1700
1701 int kVddt = mf.kVddt; // Scaled by m*2^16
1702
1703 // "Snake" voltages for triode mode calculation.
1704 unsigned int Vgst = kVddt - vx;
1705 unsigned int Vgdt = kVddt - vi;
1706 unsigned int Vgdt_2 = Vgdt*Vgdt;
1707
1708 // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
1709 int n_I_snake = n_snake*(int(Vgst*Vgst - Vgdt_2) >> 15);
1710
1711 // VCR gate voltage. // Scaled by m*2^16
1712 // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2)
1713 int kVg = vcr_kVg[(Vddt_Vw_2 + (Vgdt_2 >> 1)) >> 16];
1714
1715 // VCR voltages for EKV model table lookup.
1716 int Vgs = kVg - vx;
1717 if (Vgs < 0) Vgs = 0;
1718 int Vgd = kVg - vi;
1719 if (Vgd < 0) Vgd = 0;
1720
1721 // VCR current, scaled by m*2^15*2^15 = m*2^30
1722 int n_I_vcr = int(unsigned(vcr_n_Ids_term[Vgs] - vcr_n_Ids_term[Vgd]) << 15);
1723
1724 // Change in capacitor charge.
1725 vc -= (n_I_snake + n_I_vcr)*dt;
1726
1727/*
1728 // FIXME: Determine whether this check is necessary.
1729 if (vc < mf.vc_min) {
1730 vc = mf.vc_min;
1731 }
1732 else if (vc > mf.vc_max) {
1733 vc = mf.vc_max;
1734 }
1735*/
1736
1737 // vx = g(vc)
1738 vx = mf.opamp_rev[(vc >> 15) + (1 << 15)];
1739
1740 // Return vo.
1741 return vx + (vc >> 14);
1742}
1743
1744/*
1745The 8580 integrator is similar to those found in 6581
1746but the resistance is formed by multiple NMOS transistors
1747in parallel controlled by the fc bits where the gate voltage
1748is driven by a temperature dependent voltage divider.
1749
1750 ---C---
1751 | |
1752 vi -----Rfc------[A>----- vo
1753 vx
1754
1755 IRfc + ICr = 0
1756 IRfc + C*(vc - vc0)/dt = 0
1757 dt/C*(IRfc) + vc - vc0 = 0
1758 vc = vc0 - n*(IRfc(vi,vx))
1759 vc = vc0 - n*(IRfc(vi,g(vc)))
1760
1761IRfc = K/2*W/L*(Vgst^2 - Vgdt^2) = n*((Vgt - vx)^2 - (Vgt - vi)^2)
1762*/
1763RESID_INLINE
1764int Filter::solve_integrate_8580(int dt, int vi, int& vx, int& vc, model_filter_t& mf)
1765{
1766 // Note that all variables are translated and scaled in order to fit
1767 // in 16 bits. It is not necessary to explicitly translate the variables here,
1768 // since they are all used in subtractions which cancel out the translation:
1769 // (a - t) - (b - t) = a - b
1770
1771 // Dac voltages.
1772 unsigned int Vgst = nVgt - vx;
1773 unsigned int Vgdt = (vi < nVgt) ? nVgt - vi : 0; // triode/saturation mode
1774
1775 // Dac current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30
1776 int n_I_rfc = n_dac*(int(Vgst*Vgst - Vgdt*Vgdt) >> 15);
1777
1778 // Change in capacitor charge.
1779 vc -= n_I_rfc*dt;
1780
1781 // vx = g(vc)
1782 vx = mf.opamp_rev[(vc >> 15) + (1 << 15)];
1783
1784 // Return vo.
1785 return vx + (vc >> 14);
1786}
1787
1788#endif // RESID_INLINING || defined(RESID_FILTER_CC)
1789
1790} // namespace reSID
1791
1792#endif // not RESID_FILTER_H