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