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_DAC_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 "dac.h"
28 #include <math.h>
29
30 #ifdef __IBMC__
31 #include <float.h>
32 #define INFINITY _INF
33 #endif
34
35 #ifndef INFINITY
36 union MSVC_EVIL_FLOAT_HACK
37 {
38 unsigned char Bytes[4];
39 float Value;
40 };
41 static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}};
42 #define INFINITY (INFINITY_HACK.Value)
43 #endif
44
45 namespace reSID
46 {
47
48 // ----------------------------------------------------------------------------
49 // Calculation of lookup tables for SID DACs.
50 // ----------------------------------------------------------------------------
51
52 // The SID DACs are built up as follows:
53 //
54 // n n-1 2 1 0 VGND
55 // | | | | | | Termination
56 // 2R 2R 2R 2R 2R 2R only for
57 // | | | | | | MOS 8580
58 // Vo --R---R--...--R---R-- ---
59 //
60 //
61 // All MOS 6581 DACs are missing a termination resistor at bit 0. This causes
62 // pronounced errors for the lower 4 - 5 bits (e.g. the output for bit 0 is
63 // actually equal to the output for bit 1), resulting in DAC discontinuities
64 // for the lower bits.
65 // In addition to this, the 6581 DACs exhibit further severe discontinuities
66 // for higher bits, which may be explained by a less than perfect match between
67 // the R and 2R resistors, or by output impedance in the NMOS transistors
68 // providing the bit voltages. A good approximation of the actual DAC output is
69 // achieved for 2R/R ~ 2.20.
70 //
71 // The MOS 8580 DACs, on the other hand, do not exhibit any discontinuities.
72 // These DACs include the correct termination resistor, and also seem to have
73 // very accurately matched R and 2R resistors (2R/R = 2.00).
74
build_dac_table(unsigned short * dac,int bits,double _2R_div_R,bool term)75 void build_dac_table(unsigned short* dac, int bits, double _2R_div_R, bool term)
76 {
77 // FIXME: No variable length arrays in ISO C++, hardcoding to max 12 bits.
78 // double vbit[bits];
79 double vbit[12];
80
81 // Calculate voltage contribution by each individual bit in the R-2R ladder.
82 for (int set_bit = 0; set_bit < bits; set_bit++) {
83 int bit;
84
85 double Vn = 1.0; // Normalized bit voltage.
86 double R = 1.0; // Normalized R
87 double _2R = _2R_div_R*R; // 2R
88 double Rn = term ? // Rn = 2R for correct termination,
89 _2R : INFINITY; // INFINITY for missing termination.
90
91 // Calculate DAC "tail" resistance by repeated parallel substitution.
92 for (bit = 0; bit < set_bit; bit++) {
93 if (Rn == INFINITY) {
94 Rn = R + _2R;
95 }
96 else {
97 Rn = R + _2R*Rn/(_2R + Rn); // R + 2R || Rn
98 }
99 }
100
101 // Source transformation for bit voltage.
102 if (Rn == INFINITY) {
103 Rn = _2R;
104 }
105 else {
106 Rn = _2R*Rn/(_2R + Rn); // 2R || Rn
107 Vn = Vn*Rn/_2R;
108 }
109
110 // Calculate DAC output voltage by repeated source transformation from
111 // the "tail".
112 for (++bit; bit < bits; bit++) {
113 Rn += R;
114 double I = Vn/Rn;
115 Rn = _2R*Rn/(_2R + Rn); // 2R || Rn
116 Vn = Rn*I;
117 }
118
119 vbit[set_bit] = Vn;
120 }
121
122 // Calculate the voltage for any combination of bits by superpositioning.
123 for (int i = 0; i < (1 << bits); i++) {
124 int x = i;
125 double Vo = 0;
126 for (int j = 0; j < bits; j++) {
127 Vo += (x & 0x1)*vbit[j];
128 x >>= 1;
129 }
130
131 // Scale maximum output to 2^bits - 1.
132 dac[i] = (unsigned short)(((1 << bits) - 1)*Vo + 0.5);
133 }
134 }
135
136 } // namespace reSID
137