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