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