reSIDfp::Filter6581 Class Referencefinal

`#include <Filter6581.h>`

Inheritance diagram for reSIDfp::Filter6581:

## Public Member Functions

unsigned short | clock (int voice1, int voice2, int voice3) override
void | input (int sample) override
void | setFilterCurve (double curvePosition)
Public Member Functions inherited from reSIDfp::Filter
void | enable (bool enable)
void | reset ()
void | writeFC_LO (unsigned char fc_lo)
void | writeFC_HI (unsigned char fc_hi)
void | writeRES_FILT (unsigned char res_filt)
void | writeMODE_VOL (unsigned char mode_vol)

## Protected Member Functions

void | updatedCenterFrequency () override
void | updateResonance (unsigned char res) override
void | updatedMixing () override

## Additional Inherited Members

Protected Attributes inherited from reSIDfp::Filter
unsigned short * | currentGain
| Current volume amplifier setting.
unsigned short * | currentMixer
| Current filter/voice mixer setting.
unsigned short * | currentSummer
| Filter input summer setting.
unsigned short * | currentResonance
| Filter resonance value.
int | Vhp
| Filter highpass state.
int | Vbp
| Filter bandpass state.
int | Vlp
| Filter lowpass state.
int | ve
| Filter external input.
unsigned int | fc
| Filter cutoff frequency.
bool | filt1
| Routing to filter or outside filter.
bool | filt2
bool | filt3
bool | filtE
bool | voice3off
| Switch voice 3 off.
bool | hp
| Highpass, bandpass, and lowpass filter modes.
bool | bp
bool | lp
unsigned char | vol
| Current volume.

## Detailed Description

The SID filter is modeled with a two-integrator-loop biquadratic filter, which has been confirmed by Bob Yannes to be the actual circuit used in the SID chip.

Measurements show that excellent emulation of the SID filter is achieved, except when high resonance is combined with high sustain levels. In this case the SID op-amps are performing less than ideally and are causing some peculiar behavior of the SID filter. This however seems to have more effect on the overall amplitude than on the color of the sound.

The theory for the filter circuit can be found in "Microelectric Circuits" by Adel S. Sedra and Kenneth C. Smith. The circuit is modeled based on the explanation found there except that an additional inverter is used in the feedback from the bandpass output, allowing the summer op-amp to operate in single-ended mode. This yields filter outputs with levels independent of Q, which corresponds with the results obtained from a real SID.

We have been able to model the summer and the two integrators of the circuit to form components of an IIR filter. Vhp is the output of the summer, Vbp is the output of the first integrator, and Vlp is the output of the second integrator in the filter circuit.

According to Bob Yannes, the active stages of the SID filter are not really op-amps. Rather, simple NMOS inverters are used. By biasing an inverter into its region of quasi-linear operation using a feedback resistor from input to output, a MOS inverter can be made to act like an op-amp for small signals centered around the switching threshold.

In 2008, Michael Huth facilitated closer investigation of the SID 6581 filter circuit by publishing high quality microscope photographs of the die. Tommi Lempinen has done an impressive work on re-vectorizing and annotating the die photographs, substantially simplifying further analysis of the filter circuit.

The filter schematics below are reverse engineered from these re-vectorized and annotated die photographs. While the filter first depicted in reSID 0.9 is a correct model of the basic filter, the schematics are now completed with the audio mixer and output stage, including details on intended relative resistor values. Also included are schematics for the NMOS FET voltage controlled resistors (VCRs) used to control cutoff frequency, the DAC which controls the VCRs, the NMOS op-amps, and the output buffer.

## SID filter / mixer / output

+---------------------------------------------------+
| |
| +--1R1-- \--+ D7 |
| +---R1--+ | | |
| | | o--2R1-- \--o D6 |
| +---------o--<A]--o--o | $17 |
| | o--4R1-- \--o D5 1=open | (3.5R1)
| | | | |
| | +--8R1-- \--o D4 | (7.0R1)
| | | |
$17 | | (CAP2B) | (CAP1B) |
0=to mixer | +--R8--+ +---R8--+ +---C---o +---C---o
1=to filter | | | | | | | |
------R8--o--o--[A>--o--Rw--o--[A>--o--Rw--o--[A>--o
ve (EXT IN) | | | |
D3 \ ---------------R8--o | | (CAP2A) | (CAP1A)
| v3 | | vhp | vbp | vlp
D2 | \ -----------R8--o +-----+ | |
| | v2 | | | |
D1 | | \ -------R8--o | +----------------+ |
| | | v1 | | | |
D0 | | | \ ---R8--+ | | +---------------------------+
| | | | | | |
R6 R6 R6 R6 R6 R6 R6
| | | | $18 | | | $18
| \ | | D7: 1=open \ \ \ D6 - D4: 0=open
| | | | | | |
+---o---o---o-------------o---o---+ 12V
|
| D3 +--/ --1R2--+ |
| +---R8--+ | | +---R2--+ |
| | | D2 o--/ --2R2--o | | ||--+
+---o--[A>--o------o o--o--[A>--o--||
D1 o--/ --4R2--o (4.25R2) ||--+
$18 | | |
0=open D0 +--/ --8R2--+ (8.75R2) |
vo (AUDIO
OUT)
v1 - voice 1
v2 - voice 2
v3 - voice 3
ve - ext in
vhp - highpass output
vbp - bandpass output
vlp - lowpass output
vo - audio out
[A> - single ended inverting op-amp (self-biased NMOS inverter)
Rn - "resistors", implemented with custom NMOS FETs
Rw - cutoff frequency resistor (VCR)
C - capacitor
reSIDfp::Filter::ve
int ve
Filter external input.
Definition Filter.h:57

Notes:

    R2  ~  2.0*R1
    R6  ~  6.0*R1
    R8  ~  8.0*R1
    R24 ~ 24.0*R1

The Rn "resistors" in the circuit are implemented with custom NMOS FETs, probably because of space constraints on the SID die. The silicon substrate is laid out in a narrow strip or "snake", with a strip length proportional to the intended resistance. The polysilicon gate electrode covers the entire silicon substrate and is fixed at 12V in order for the NMOS FET to operate in triode mode (a.k.a. linear mode or ohmic mode).

Even in "linear mode", an NMOS FET is only an approximation of a resistor, as the apparant resistance increases with increasing drain-to-source voltage. If the drain-to-source voltage should approach the gate voltage of 12V, the NMOS FET will enter saturation mode (a.k.a. active mode), and the NMOS FET will not operate anywhere like a resistor.

## NMOS FET voltage controlled resistor (VCR)

Vw
|
|
R1
|
+--R1--o
| __|__
| -----
| | |
vi -----o----+ +--o----- vo
| |
+----R24----+
vi - input
vo - output
Rn - "resistors", implemented with custom NMOS FETs
Vw - voltage from 11-bit DAC (frequency cutoff control)

Notes:

An approximate value for R24 can be found by using the formula for the filter cutoff frequency:

    FCmin = 1/(2*pi*Rmax*C)

Assuming that a the setting for minimum cutoff frequency in combination with a low level input signal ensures that only negligible current will flow through the transistor in the schematics above, values for FCmin and C can be substituted in this formula to find Rmax. Using C = 470pF and FCmin = 220Hz (measured value), we get:

    FCmin = 1/(2*pi*Rmax*C)
    Rmax = 1/(2*pi*FCmin*C) = 1/(2*pi*220*470e-12) ~ 1.5MOhm

From this it follows that: R24 = Rmax ~ 1.5MOhm R1 ~ R24/24 ~ 64kOhm R2 ~ 2.0*R1 ~ 128kOhm R6 ~ 6.0*R1 ~ 384kOhm R8 ~ 8.0*R1 ~ 512kOhm

Note that these are only approximate values for one particular SID chip, due to process variations the values can be substantially different in other chips.

## Filter frequency cutoff DAC

12V 10 9 8 7 6 5 4 3 2 1 0 VGND
| | | | | | | | | | | | | Missing
2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R termination
| | | | | | | | | | | | |
Vw --o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o- -+
Bit on: 12V
Bit off: 5V (VGND)

As is the case with all MOS 6581 DACs, the termination to (virtual) ground at bit 0 is missing.

Furthermore, the control of the two VCRs imposes a load on the DAC output which varies with the input signals to the VCRs. This can be seen from the VCR figure above.

## "Op-amp" (self-biased NMOS inverter)

12V
|
+-----------o
| |
| +------o
| | |
| | ||--+
| +--||
| ||--+
||--+ |
vi -----|| o---o----- vo
||--+ | |
| ||--+ |
|-------|| |
| ||--+ |
||--+ | |
+--|| | |
| ||--+ | |
| | | |
| +-----------o |
| | |
| |
| GND |
| |
+----------------------+
vi - input
vo - output

Notes:

The schematics above are laid out to show that the "op-amp" logically consists of two building blocks; a saturated load NMOS inverter (on the right hand side of the schematics) with a buffer / bias input stage consisting of a variable saturated load NMOS inverter (on the left hand side of the schematics).

Provided a reasonably high input impedance and a reasonably low output impedance, the "op-amp" can be modeled as a voltage transfer function mapping input voltage to output voltage.

## Output buffer (NMOS voltage follower)

12V
|
|
||--+
vi -----||
||--+
|
o------ vo
| (AUDIO
Rext OUT)
|
|
GND
vi - input
vo - output
Rext - external resistor, 1kOhm

Notes:

The external resistor Rext is needed to complete the NMOS voltage follower, this resistor has a recommended value of 1kOhm.

Die photographs show that actually, two NMOS transistors are used in the voltage follower. However the two transistors are coupled in parallel (all terminals are pairwise common), which implies that we can model the two transistors as one.

## Member Function Documentation

## clock()

RESID_INLINE unsigned short reSIDfp::Filter6581::clock | ( | int | v1,
|  | int | v2,
|  | int | v3
| ) |  |

override virtual

SID clocking - 1 cycle

Parameters

  v1 | voice 1 in
  v2 | voice 2 in
  v3 | voice 3 in

Returns
  filtered output

Implements reSIDfp::Filter.

## input()

void reSIDfp::Filter6581::input | ( | int | sample | ) |

inline override virtual

Implements reSIDfp::Filter.

## setFilterCurve()

void reSIDfp::Filter6581::setFilterCurve | ( | double | curvePosition | ) |

Set filter curve type based on single parameter.

Parameters

  curvePosition | 0 .. 1, where 0 sets center frequency high ("light") and 1 sets it low ("dark"), default is 0.5

## updatedCenterFrequency()

void reSIDfp::Filter6581::updatedCenterFrequency | ( |  | ) |

override protected virtual

Set filter cutoff frequency.

Implements reSIDfp::Filter.

## updatedMixing()

void reSIDfp::Filter6581::updatedMixing | ( |  | ) |

override protected virtual

Mixing configuration modified (offsets change)

Implements reSIDfp::Filter.

## updateResonance()

void reSIDfp::Filter6581::updateResonance | ( | unsigned char | res | ) |

inline override protected virtual

Set filter resonance.

In the MOS 6581, 1/Q is controlled linearly by res.

Implements reSIDfp::Filter.

The documentation for this class was generated from the following files:

- Filter6581.h
- Filter6581.cpp