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 #define RESID_FILTER_CC
21 
22 #ifdef _M_ARM
23 #undef _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE
24 #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1
25 #endif
26 
27 #include "filter8580new.h"
28 #include "dac.h"
29 #include "spline.h"
30 #include <math.h>
31 
32 namespace reSID
33 {
34 
35 // This is the SID 6581 op-amp voltage transfer function, measured on
36 // CAP1B/CAP1A on a chip marked MOS 6581R4AR 0687 14.
37 // All measured chips have op-amps with output voltages (and thus input
38 // voltages) within the range of 0.81V - 10.31V.
39 
40 static double_point opamp_voltage_6581[] = {
41   {  0.81, 10.31 },  // Approximate start of actual range
42   {  0.81, 10.31 },  // Repeated point
43   {  2.40, 10.31 },
44   {  2.60, 10.30 },
45   {  2.70, 10.29 },
46   {  2.80, 10.26 },
47   {  2.90, 10.17 },
48   {  3.00, 10.04 },
49   {  3.10,  9.83 },
50   {  3.20,  9.58 },
51   {  3.30,  9.32 },
52   {  3.50,  8.69 },
53   {  3.70,  8.00 },
54   {  4.00,  6.89 },
55   {  4.40,  5.21 },
56   {  4.54,  4.54 },  // Working point (vi = vo)
57   {  4.60,  4.19 },
58   {  4.80,  3.00 },
59   {  4.90,  2.30 },  // Change of curvature
60   {  4.95,  2.03 },
61   {  5.00,  1.88 },
62   {  5.05,  1.77 },
63   {  5.10,  1.69 },
64   {  5.20,  1.58 },
65   {  5.40,  1.44 },
66   {  5.60,  1.33 },
67   {  5.80,  1.26 },
68   {  6.00,  1.21 },
69   {  6.40,  1.12 },
70   {  7.00,  1.02 },
71   {  7.50,  0.97 },
72   {  8.50,  0.89 },
73   { 10.00,  0.81 },
74   { 10.31,  0.81 },  // Approximate end of actual range
75   { 10.31,  0.81 }   // Repeated end point
76 };
77 
78 // This is the SID 8580 op-amp voltage transfer function, measured on
79 // CAP1B/CAP1A on a chip marked CSG 8580R5 1690 25.
80 static double_point opamp_voltage_8580[] = {
81   {  1.30,  8.91 },  // Approximate start of actual range
82   {  1.30,  8.91 },  // Repeated end point
83   {  4.76,  8.91 },
84   {  4.77,  8.90 },
85   {  4.78,  8.88 },
86   {  4.785, 8.86 },
87   {  4.79,  8.80 },
88   {  4.795, 8.60 },
89   {  4.80,  8.25 },
90   {  4.805, 7.50 },
91   {  4.81,  6.10 },
92   {  4.815, 4.05 },  // Change of curvature
93   {  4.82,  2.27 },
94   {  4.825, 1.65 },
95   {  4.83,  1.55 },
96   {  4.84,  1.47 },
97   {  4.85,  1.43 },
98   {  4.87,  1.37 },
99   {  4.90,  1.34 },
100   {  5.00,  1.30 },
101   {  5.10,  1.30 },
102   {  8.91,  1.30 },  // Approximate end of actual range
103   {  8.91,  1.30 }   // Repeated end point
104 };
105 
106 
107 /*
108  * R1 = 15.3*Ri
109  * R2 =  7.3*Ri
110  * R3 =  4.7*Ri
111  * Rf =  1.4*Ri
112  * R4 =  1.4*Ri
113  * R8 =  2.0*Ri
114  * RC =  2.8*Ri
115  *
116  * res  feedback  input
117  * ---  --------  -----
118  *  0   Rf        Ri
119  *  1   Rf|R1     Ri
120  *  2   Rf|R2     Ri
121  *  3   Rf|R3     Ri
122  *  4   Rf        R4
123  *  5   Rf|R1     R4
124  *  6   Rf|R2     R4
125  *  7   Rf|R3     R4
126  *  8   Rf        R8
127  *  9   Rf|R1     R8
128  *  A   Rf|R2     R8
129  *  B   Rf|R3     R8
130  *  C   Rf        RC
131  *  D   Rf|R1     RC
132  *  E   Rf|R2     RC
133  *  F   Rf|R3     RC
134  */
135 static int resGain[16] =
136 {
137   (int)((1<<7)*(1.4/1.0)),                     //      Rf/Ri   1.4
138   (int)((1<<7)*(((1.4*15.3)/(1.4+15.3))/1.0)), // (Rf|R1)/Ri   1.28263
139   (int)((1<<7)*(((1.4*7.3)/(1.4+7.3))/1.0)),   // (Rf|R2)/Ri   1.17471
140   (int)((1<<7)*(((1.4*4.7)/(1.4+4.7))/1.0)),   // (Rf|R3)/Ri   1.07869
141   (int)((1<<7)*(1.4/1.4)),                     //      Rf/R4   1.0
142   (int)((1<<7)*(((1.4*15.3)/(1.4+15.3))/1.4)), // (Rf|R1)/R4   0.916168
143   (int)((1<<7)*(((1.4*7.3)/(1.4+7.3))/1.4)),   // (Rf|R2)/R4   0.83908
144   (int)((1<<7)*(((1.4*4.7)/(1.4+4.7))/1.4)),   // (Rf|R3)/R4   0.770492
145   (int)((1<<7)*(1.4/2.0)),                     //      Rf/R8   0.7
146   (int)((1<<7)*(((1.4*15.3)/(1.4+15.3))/2.0)), // (Rf|R1)/R8   0.641317
147   (int)((1<<7)*(((1.4*7.3)/(1.4+7.3))/2.0)),   // (Rf|R2)/R8   0.587356
148   (int)((1<<7)*(((1.4*4.7)/(1.4+4.7))/2.0)),   // (Rf|R3)/R8   0.539344
149   (int)((1<<7)*(1.4/2.8)),                     //      Rf/RC   0.5
150   (int)((1<<7)*(((1.4*15.3)/(1.4+15.3))/2.8)), // (Rf|R1)/RC   0.458084
151   (int)((1<<7)*(((1.4*7.3)/(1.4+7.3))/2.8)),   // (Rf|R2)/RC   0.41954
152   (int)((1<<7)*(((1.4*4.7)/(1.4+4.7))/2.8)),   // (Rf|R3)/RC   0.385246
153 };
154 
155 typedef struct {
156   // Op-amp transfer function.
157   double_point* opamp_voltage;
158   int opamp_voltage_size;
159   // Voice output characteristics.
160   double voice_voltage_range;
161   double voice_DC_voltage;
162   // Capacitor value.
163   double C;
164   // Transistor parameters.
165   double Vdd;
166   double Vth;        // Threshold voltage
167   double Ut;         // Thermal voltage: Ut = k*T/q = 8.61734315e-5*T ~ 26mV
168   double k;          // Gate coupling coefficient: K = Cox/(Cox+Cdep) ~ 0.7
169   double uCox;       // u*Cox
170   double WL_vcr;     // W/L for VCR
171   double WL_snake;   // W/L for "snake"
172   // DAC parameters.
173   double dac_zero;
174   double dac_scale;
175   double dac_2R_div_R;
176   bool dac_term;
177 } model_filter_init_t;
178 
179 static model_filter_init_t model_filter_init[2] = {
180   {
181     opamp_voltage_6581,
182     sizeof(opamp_voltage_6581)/sizeof(*opamp_voltage_6581),
183     // The dynamic analog range of one voice is approximately 1.5V,
184     1.5,
185     // riding at a DC level of approximately 5.0V.
186     5.0,
187     // Capacitor value.
188     470e-12,
189     // Transistor parameters.
190     12.18,
191     1.31,
192     26.0e-3,
193     1.0,
194     20e-6,
195     9.0/1.0,
196     1.0/115,
197     // DAC parameters.
198     6.65,
199     2.63,
200     2.20,
201     false
202   },
203   {
204     opamp_voltage_8580,
205     sizeof(opamp_voltage_8580)/sizeof(*opamp_voltage_8580),
206     // FIXME: Measure for the 8580.
207     0.2,
208     // The 4.75V voltage for the virtual ground is generated by a PolySi resistor divider
209     4.80, // FIXME
210     // Capacitor value.
211     22e-9,
212     // Transistor parameters.
213     9.09,
214     0.80,
215     26.0e-3,
216     1.0,   // Unused, leave at 1
217     100e-6,
218     // FIXME: 6581 only
219     0,
220     0,
221     0,
222     0,
223     2.00,
224     true
225   }
226 };
227 
228 unsigned short Filter::resonance[16][1 << 16];
229 unsigned short Filter::vcr_kVg[1 << 16];
230 unsigned short Filter::vcr_n_Ids_term[1 << 16];
231 int Filter::n_snake;
232 int Filter::n_param;
233 
234 #if defined(__amiga__) && defined(__mc68000__)
235 #undef HAS_LOG1P
236 #endif
237 
238 #ifndef HAS_LOG1P
log1p(double x)239 static double log1p(double x)
240 {
241     return log(1 + x) - (((1 + x) - 1) - x) / (1 + x);
242 }
243 #endif
244 
245 Filter::model_filter_t Filter::model_filter[2];
246 
247 
248 // ----------------------------------------------------------------------------
249 // Constructor.
250 // ----------------------------------------------------------------------------
Filter()251 Filter::Filter()
252 {
253   static bool class_init;
254 
255   if (!class_init) {
256     double tmp_n_param[2];
257 
258     // Temporary tables for op-amp transfer function.
259     unsigned int* voltages = new unsigned int[1 << 16];
260     opamp_t* opamp = new opamp_t[1 << 16];
261 
262     for (int m = 0; m < 2; m++) {
263       model_filter_init_t& fi = model_filter_init[m];
264       model_filter_t& mf = model_filter[m];
265 
266       // Convert op-amp voltage transfer to 16 bit values.
267       double vmin = fi.opamp_voltage[0][0];
268       double opamp_max = fi.opamp_voltage[0][1];
269       double kVddt = fi.k*(fi.Vdd - fi.Vth);
270       double vmax = kVddt < opamp_max ? opamp_max : kVddt;
271       double denorm = vmax - vmin;
272       double norm = 1.0/denorm;
273 
274       // Scaling and translation constants.
275       double N16 = norm*((1u << 16) - 1);
276       double N30 = norm*((1u << 30) - 1);
277       double N31 = norm*((1u << 31) - 1);
278       mf.vo_N16 = N16;
279 
280       // The "zero" output level of the voices.
281       // The digital range of one voice is 20 bits; create a scaling term
282       // for multiplication which fits in 11 bits.
283       double N14 = norm*(1u << 14);
284       mf.voice_scale_s14 = (int)(N14*fi.voice_voltage_range);
285       mf.voice_DC = (int)(N16*(fi.voice_DC_voltage - vmin));
286 
287       // Vdd - Vth, normalized so that translated values can be subtracted:
288       // k*Vddt - x = (k*Vddt - t) - (x - t)
289       mf.kVddt = (int)(N16*(kVddt - vmin) + 0.5);
290 
291       tmp_n_param[m] = denorm*(1 << 13)*((fi.uCox/2.)*1.0e-6/fi.C);
292 
293       // Create lookup table mapping op-amp voltage across output and input
294       // to input voltage: vo - vx -> vx
295       // FIXME: No variable length arrays in ISO C++, hardcoding to max 50
296       // points.
297       // double_point scaled_voltage[fi.opamp_voltage_size];
298       double_point scaled_voltage[50];
299 
300       for (int i = 0; i < fi.opamp_voltage_size; i++) {
301         // The target output range is 16 bits, in order to fit in an unsigned
302         // short.
303         //
304         // The y axis is temporarily scaled to 31 bits for maximum accuracy in
305         // the calculated derivative.
306         //
307         // Values are normalized using
308         //
309         //   x_n = m*2^N*(x - xmin)
310         //
311         // and are translated back later (for fixed point math) using
312         //
313         //   m*2^N*x = x_n - m*2^N*xmin
314         //
315         scaled_voltage[fi.opamp_voltage_size - 1 - i][0] = int(N16*(fi.opamp_voltage[i][1] - fi.opamp_voltage[i][0] + denorm)/2 + 0.5);
316         scaled_voltage[fi.opamp_voltage_size - 1 - i][1] = N31*(fi.opamp_voltage[i][0] - vmin);
317       }
318 
319       // Clamp x to 16 bits (rounding may cause overflow).
320       if (scaled_voltage[fi.opamp_voltage_size - 1][0] >= (1 << 16)) {
321         // The last point is repeated.
322         scaled_voltage[fi.opamp_voltage_size - 1][0] =
323             scaled_voltage[fi.opamp_voltage_size - 2][0] = (1 << 16) - 1;
324       }
325 
326       interpolate(scaled_voltage, scaled_voltage + fi.opamp_voltage_size - 1,
327                     PointPlotter<unsigned int>(voltages), 1.0);
328 
329       // Store both fn and dfn in the same table.
330       mf.ak = (int)scaled_voltage[0][0];
331       mf.bk = (int)scaled_voltage[fi.opamp_voltage_size - 1][0];
332       int j;
333       for (j = 0; j < mf.ak; j++) {
334         opamp[j].vx = 0;
335         opamp[j].dvx = 0;
336       }
337       unsigned int f = voltages[j];
338       for (; j <= mf.bk; j++) {
339         unsigned int fp = f;
340         f = voltages[j];  // Scaled by m*2^31
341         // m*2^31*dy/1 = (m*2^31*dy)/(m*2^16*dx) = 2^15*dy/dx
342         int df = f - fp;  // Scaled by 2^15
343 
344         // 16 bits unsigned: m*2^16*(fn - xmin)
345         opamp[j].vx = f > (0xffff << 15) ? 0xffff : f >> 15;
346         // 16 bits (15 bits + sign bit): 2^11*dfn
347         opamp[j].dvx = df >> (15 - 11);
348       }
349       for (; j < (1 << 16); j++) {
350         opamp[j].vx = 0;
351         opamp[j].dvx = 0;
352       }
353 
354       // We don't have the differential for the first point so just assume
355       // it's the same as the second point's
356       opamp[mf.ak].dvx = opamp[mf.ak+1].dvx;
357 
358       // Create lookup tables for gains / summers.
359 
360       // 4 bit "resistor" ladders in the bandpass resonance gain and the audio
361       // output gain necessitate 16 gain tables.
362       // From die photographs of the bandpass and volume "resistor" ladders
363       // it follows that gain ~ vol/8 and 1/Q ~ ~res/8 (assuming ideal
364       // op-amps and ideal "resistors").
365       for (int n8 = 0; n8 < 16; n8++) {
366         int n = n8 << 4;  // Scaled by 2^7
367         int x = mf.ak;
368         for (int vi = 0; vi < (1 << 16); vi++) {
369           mf.gain[n8][vi] = solve_gain(opamp, n, vi, x, mf);
370         }
371       }
372 
373       // The filter summer operates at n ~ 1, and has 5 fundamentally different
374       // input configurations (2 - 6 input "resistors").
375       //
376       // Note that all "on" transistors are modeled as one. This is not
377       // entirely accurate, since the input for each transistor is different,
378       // and transistors are not linear components. However modeling all
379       // transistors separately would be extremely costly.
380       int offset = 0;
381       int size;
382       for (int k = 0; k < 5; k++) {
383         int idiv = 2 + k;        // 2 - 6 input "resistors".
384         int n_idiv = idiv << 7;  // n*idiv, scaled by 2^7
385         size = idiv << 16;
386         int x = mf.ak;
387         for (int vi = 0; vi < size; vi++) {
388           mf.summer[offset + vi] =
389             solve_gain(opamp, n_idiv, vi/idiv, x, mf);
390         }
391         offset += size;
392       }
393 
394       // The audio mixer operates at n ~ 8/6, and has 8 fundamentally different
395       // input configurations (0 - 7 input "resistors").
396       //
397       // All "on", transistors are modeled as one - see comments above for
398       // the filter summer.
399       offset = 0;
400       size = 1;  // Only one lookup element for 0 input "resistors".
401       for (int l = 0; l < 8; l++) {
402         int idiv = l;                 // 0 - 7 input "resistors".
403         int n_idiv = (idiv << 7)*8/6; // n*idiv, scaled by 2^7
404         if (idiv == 0) {
405           // Avoid division by zero; the result will be correct since
406           // n_idiv = 0.
407           idiv = 1;
408         }
409         int x = mf.ak;
410         for (int vi = 0; vi < size; vi++) {
411           mf.mixer[offset + vi] =
412             solve_gain(opamp, n_idiv, vi/idiv, x, mf);
413         }
414         offset += size;
415         size = (l + 1) << 16;
416       }
417 
418       // Create lookup table mapping capacitor voltage to op-amp input voltage:
419       // vc -> vx
420       for (int m = 0; m < (1 << 16); m++) {
421         mf.opamp_rev[m] = opamp[m].vx;
422       }
423 
424       mf.vc_max = (int)(N30*(fi.opamp_voltage[0][1] - fi.opamp_voltage[0][0]));
425       mf.vc_min = (int)(N30*(fi.opamp_voltage[fi.opamp_voltage_size - 1][1] - fi.opamp_voltage[fi.opamp_voltage_size - 1][0]));
426     }
427 
428     // Free temporary table.
429     delete[] voltages;
430 
431     unsigned int dac_bits = 11;
432 
433     {
434       // 8580 only
435       for (int n8 = 0; n8 < 16; n8++) {
436         int x = model_filter[1].ak;
437         for (int vi = 0; vi < (1 << 16); vi++) {
438           resonance[n8][vi] = solve_gain(opamp, resGain[n8], vi, x, model_filter[1]);
439         }
440       }
441 
442       // scaled 5 bits
443       n_param = (int)(tmp_n_param[1] * 32 + 0.5);
444 
445       model_filter_init_t& fi = model_filter_init[1];
446       model_filter_t& f = model_filter[1];
447 
448       double Vgt = (4.75 * 1.6) - fi.Vth;
449       nVgt = (int)(f.vo_N16 * (Vgt - fi.opamp_voltage[0][0]) + 0.5);
450 
451       // DAC table.
452       // W/L ratio for frequency DAC, bits are proportional.
453       // scaled 5 bits
454       unsigned short dacWL = 3; // 0,0029296875 * 1024 (actual value is ~= 0.003075)
455       f.f0_dac[0] = dacWL;
456       for (int n = 1; n < (1 << dac_bits); n++) {
457         // Calculate W/L ratio for parallel NMOS resistances
458         unsigned short wl = 0;
459         for (unsigned int i = 0; i < dac_bits; i++) {
460           unsigned int bitmask = 1 << i;
461           if (n & bitmask) {
462             wl += dacWL * (bitmask<<1);
463           }
464         }
465         f.f0_dac[n] = wl;
466       }
467     }
468 
469     // Free temporary table.
470     delete[] opamp;
471 
472     {
473       // 6581 only
474       model_filter_init_t& fi = model_filter_init[0];
475       model_filter_t& f = model_filter[0];
476       double N16 = f.vo_N16;
477       double vmin = fi.opamp_voltage[0][0];
478 
479       Vw_bias = 0;
480 
481       // Normalized snake current factor, 1 cycle at 1MHz.
482       // Fit in 5 bits.
483       n_snake = (int)(fi.WL_snake * tmp_n_param[0] + 0.5);
484 
485       // DAC table.
486       build_dac_table(f.f0_dac, dac_bits, fi.dac_2R_div_R, fi.dac_term);
487       for (int n = 0; n < (1 << dac_bits); n++) {
488         f.f0_dac[n] = (unsigned short)(N16*(fi.dac_zero + f.f0_dac[n]*fi.dac_scale/(1 << dac_bits) - vmin) + 0.5);
489       }
490 
491       // VCR table.
492       double k = fi.k;
493       double kVddt = N16*(k*(fi.Vdd - fi.Vth));
494       vmin *= N16;
495 
496       for (int i = 0; i < (1 << 16); i++) {
497         // The table index is right-shifted 16 times in order to fit in
498         // 16 bits; the argument to sqrt is thus multiplied by (1 << 16).
499         //
500         // The returned value must be corrected for translation. Vg always
501         // takes part in a subtraction as follows:
502         //
503         //   k*Vg - Vx = (k*Vg - t) - (Vx - t)
504         //
505         // I.e. k*Vg - t must be returned.
506         double Vg = kVddt - sqrt((double)i*(1 << 16));
507         vcr_kVg[i] = (unsigned short)(k*Vg - vmin + 0.5);
508       }
509 
510       /*
511         EKV model:
512 
513         Ids = Is*(if - ir)
514         Is = ((2*u*Cox*Ut^2)/k)*W/L
515         if = ln^2(1 + e^((k*(Vg - Vt) - Vs)/(2*Ut))
516         ir = ln^2(1 + e^((k*(Vg - Vt) - Vd)/(2*Ut))
517       */
518       double kVt = fi.k*fi.Vth;
519       double Ut = fi.Ut;
520       double Is = ((2*fi.uCox*Ut*Ut)/fi.k)*fi.WL_vcr;
521       // Normalized current factor for 1 cycle at 1MHz.
522       double N15 = N16/2;
523       double n_Is = N15*1.0e-6/fi.C*Is;
524 
525       // kVg_Vx = k*Vg - Vx
526       // I.e. if k != 1.0, Vg must be scaled accordingly.
527       for (int kVg_Vx = 0; kVg_Vx < (1 << 16); kVg_Vx++) {
528         double log_term = log1p(exp((kVg_Vx/N16 - kVt)/(2*Ut)));
529         // Scaled by m*2^15
530         vcr_n_Ids_term[kVg_Vx] = (unsigned short)(n_Is*log_term*log_term);
531       }
532     }
533 
534     class_init = true;
535   }
536 
537   enable_filter(true);
538   set_chip_model(MOS6581);
539   set_voice_mask(0x07);
540   input(0);
541   reset();
542 }
543 
544 
545 // ----------------------------------------------------------------------------
546 // Enable filter.
547 // ----------------------------------------------------------------------------
enable_filter(bool enable)548 void Filter::enable_filter(bool enable)
549 {
550   enabled = enable;
551   set_sum_mix();
552 }
553 
554 
555 // ----------------------------------------------------------------------------
556 // Adjust the DAC bias parameter of the filter.
557 // This gives user variable control of the exact CF -> center frequency
558 // mapping used by the filter.
559 // ----------------------------------------------------------------------------
adjust_filter_bias(double dac_bias)560 void Filter::adjust_filter_bias(double dac_bias)
561 {
562   Vw_bias = int(dac_bias*model_filter[0].vo_N16);
563   set_w0();
564 
565   // Gate voltage is controlled by the switched capacitor voltage divider
566   // Ua = Ue * v = 4.75v  1<v<2
567   model_filter_init_t& fi = model_filter_init[1];
568   double Vg = 4.75 * (dac_bias*6./100. + 1.6);
569   double Vgt = Vg - fi.Vth;
570   double vmin = fi.opamp_voltage[0][0];
571 
572   // Vg - Vth, normalized so that translated values can be subtracted:
573   // Vgt - x = (Vgt - t) - (x - t)
574   nVgt = (int)(model_filter[1].vo_N16 * (Vgt - vmin) + 0.5);
575 }
576 
577 // ----------------------------------------------------------------------------
578 // Set chip model.
579 // ----------------------------------------------------------------------------
set_chip_model(chip_model model)580 void Filter::set_chip_model(chip_model model)
581 {
582   sid_model = model;
583   /* We initialize the state variables again just to make sure that
584    * the earlier model didn't leave behind some foreign, unrecoverable
585    * state. Hopefully set_chip_model() only occurs simultaneously with
586    * reset(). */
587   Vhp = 0;
588   Vbp = Vbp_x = Vbp_vc = 0;
589   Vlp = Vlp_x = Vlp_vc = 0;
590 }
591 
592 
593 // ----------------------------------------------------------------------------
594 // Mask for voices routed into the filter / audio output stage.
595 // Used to physically connect/disconnect EXT IN, and for test purposes
596 // (voice muting).
597 // ----------------------------------------------------------------------------
set_voice_mask(reg4 mask)598 void Filter::set_voice_mask(reg4 mask)
599 {
600   voice_mask = 0xf0 | (mask & 0x0f);
601   set_sum_mix();
602 }
603 
604 
605 // ----------------------------------------------------------------------------
606 // SID reset.
607 // ----------------------------------------------------------------------------
reset()608 void Filter::reset()
609 {
610   fc = 0;
611   res = 0;
612   filt = 0;
613   mode = 0;
614   vol = 0;
615 
616   Vhp = 0;
617   Vbp = Vbp_x = Vbp_vc = 0;
618   Vlp = Vlp_x = Vlp_vc = 0;
619 
620   set_w0();
621   set_Q();
622   set_sum_mix();
623 }
624 
625 
626 // ----------------------------------------------------------------------------
627 // Register functions.
628 // ----------------------------------------------------------------------------
writeFC_LO(reg8 fc_lo)629 void Filter::writeFC_LO(reg8 fc_lo)
630 {
631   fc = (fc & 0x7f8) | (fc_lo & 0x007);
632   set_w0();
633 }
634 
writeFC_HI(reg8 fc_hi)635 void Filter::writeFC_HI(reg8 fc_hi)
636 {
637   fc = ((fc_hi << 3) & 0x7f8) | (fc & 0x007);
638   set_w0();
639 }
640 
writeRES_FILT(reg8 res_filt)641 void Filter::writeRES_FILT(reg8 res_filt)
642 {
643   res = (res_filt >> 4) & 0x0f;
644   set_Q();
645 
646   filt = res_filt & 0x0f;
647   set_sum_mix();
648 }
649 
writeMODE_VOL(reg8 mode_vol)650 void Filter::writeMODE_VOL(reg8 mode_vol)
651 {
652   mode = mode_vol & 0xf0;
653   set_sum_mix();
654 
655   vol = mode_vol & 0x0f;
656 }
657 
658 // Set filter cutoff frequency.
set_w0()659 void Filter::set_w0()
660 {
661   {
662     // MOS 6581
663     model_filter_t& f = model_filter[0];
664     int Vw = Vw_bias + f.f0_dac[fc];
665     Vddt_Vw_2 = unsigned(f.kVddt - Vw)*unsigned(f.kVddt - Vw) >> 1;
666   }
667 
668   {
669     // MOS 8580 cutoff: 0 - 12.5kHz.
670     model_filter_t& f = model_filter[1];
671     n_dac = (n_param * f.f0_dac[fc]) >> 15;
672   }
673 }
674 
675 /*
676 Set filter resonance.
677 
678 In the MOS 6581, 1/Q is controlled linearly by res. From die photographs
679 of the resonance "resistor" ladder it follows that 1/Q ~ ~res/8
680 (assuming an ideal op-amp and ideal "resistors"). This implies that Q
681 ranges from 0.533 (res = 0) to 8 (res = E). For res = F, Q is actually
682 theoretically unlimited, which is quite unheard of in a filter
683 circuit.
684 
685 To obtain Q ~ 1/sqrt(2) = 0.707 for maximally flat frequency response,
686 res should be set to 4: Q = 8/~4 = 8/11 = 0.7272 (again assuming an ideal
687 op-amp and ideal "resistors").
688 
689 Q as low as 0.707 is not achievable because of low gain op-amps; res = 0
690 should yield the flattest possible frequency response at Q ~ 0.8 - 1.0
691 in the op-amp's pseudo-linear range (high amplitude signals will be
692 clipped). As resonance is increased, the filter must be clocked more
693 often to keep it stable.
694 
695 In the MOS 8580, the resonance "resistor" ladder above the bp feedback
696 op-amp is split in two parts; one ladder for the op-amp input and one
697 ladder for the op-amp feedback.
698 
699 input:         feedback:
700 
701                Rf
702 Ri R4 RC R8    R3
703                R2
704                R1
705 
706 
707 The "resistors" are switched in as follows by bits in register $17:
708 
709 feedback:
710 R1: bit4&!bit5
711 R2: !bit4&bit5
712 R3: bit4&bit5
713 Rf: always on
714 
715 input:
716 R4: bit6&!bit7
717 R8: !bit6&bit7
718 RC: bit6&bit7
719 Ri: !(R4|R8|RC) = !(bit6|bit7) = !bit6&!bit7
720 
721 
722 The relative "resistor" values are approximately (using channel length):
723 
724 R1 = 15.3*Ri
725 R2 =  7.3*Ri
726 R3 =  4.7*Ri
727 Rf =  1.4*Ri
728 R4 =  1.4*Ri
729 R8 =  2.0*Ri
730 RC =  2.8*Ri
731 
732 
733 Approximate values for 1/Q can now be found as follows (assuming an
734 ideal op-amp):
735 
736 res  feedback  input  -gain (1/Q)
737 ---  --------  -----  ----------
738  0   Rf        Ri     Rf/Ri      = 1/(Ri*(1/Rf))      = 1/0.71
739  1   Rf|R1     Ri     (Rf|R1)/Ri = 1/(Ri*(1/Rf+1/R1)) = 1/0.78
740  2   Rf|R2     Ri     (Rf|R2)/Ri = 1/(Ri*(1/Rf+1/R2)) = 1/0.85
741  3   Rf|R3     Ri     (Rf|R3)/Ri = 1/(Ri*(1/Rf+1/R3)) = 1/0.92
742  4   Rf        R4     Rf/R4      = 1/(R4*(1/Rf))      = 1/1.00
743  5   Rf|R1     R4     (Rf|R1)/R4 = 1/(R4*(1/Rf+1/R1)) = 1/1.10
744  6   Rf|R2     R4     (Rf|R2)/R4 = 1/(R4*(1/Rf+1/R2)) = 1/1.20
745  7   Rf|R3     R4     (Rf|R3)/R4 = 1/(R4*(1/Rf+1/R3)) = 1/1.30
746  8   Rf        R8     Rf/R8      = 1/(R8*(1/Rf))      = 1/1.43
747  9   Rf|R1     R8     (Rf|R1)/R8 = 1/(R8*(1/Rf+1/R1)) = 1/1.56
748  A   Rf|R2     R8     (Rf|R2)/R8 = 1/(R8*(1/Rf+1/R2)) = 1/1.70
749  B   Rf|R3     R8     (Rf|R3)/R8 = 1/(R8*(1/Rf+1/R3)) = 1/1.86
750  C   Rf        RC     Rf/RC      = 1/(RC*(1/Rf))      = 1/2.00
751  D   Rf|R1     RC     (Rf|R1)/RC = 1/(RC*(1/Rf+1/R1)) = 1/2.18
752  E   Rf|R2     RC     (Rf|R2)/RC = 1/(RC*(1/Rf+1/R2)) = 1/2.38
753  F   Rf|R3     RC     (Rf|R3)/RC = 1/(RC*(1/Rf+1/R3)) = 1/2.60
754 
755 
756 These data indicate that the following function for 1/Q has been
757 modeled in the MOS 8580:
758 
759   1/Q = 2^(1/2)*2^(-x/8) = 2^(1/2 - x/8) = 2^((4 - x)/8)
760 
761 */
set_Q()762 void Filter::set_Q()
763 {
764   // Cutoff for MOS 6581.
765   // The coefficient 8 is dispensed of later by right-shifting 3 times
766   // (2 ^ 3 = 8).
767   _8_div_Q = ~res & 0x0f;
768 }
769 
770 // Set input routing bits.
set_sum_mix()771 void Filter::set_sum_mix()
772 {
773   // NB! voice3off (mode bit 7) only affects voice 3 if it is routed directly
774   // to the mixer.
775   sum = (enabled ? filt : 0x00) & voice_mask;
776   mix =
777     (enabled ? (mode & 0x70) | ((~(filt | (mode & 0x80) >> 5)) & 0x0f) : 0x0f)
778     & voice_mask;
779 }
780 
781 } // namespace reSID
782