DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/reSID/voice.cpp
00001 //  ---------------------------------------------------------------------------
00002 //  This file is part of reSID, a MOS6581 SID emulator engine.
00003 //  Copyright (C) 2004  Dag Lem <resid@nimrod.no>
00004 //
00005 //  This program is free software; you can redistribute it and/or modify
00006 //  it under the terms of the GNU General Public License as published by
00007 //  the Free Software Foundation; either version 2 of the License, or
00008 //  (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License along
00016 //  with this program; if not, write to the Free Software Foundation, Inc.,
00017 //  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 //  ---------------------------------------------------------------------------
00019 
00020 #define __VOICE_CC__
00021 #include "voice.h"
00022 
00023 // ----------------------------------------------------------------------------
00024 // Constructor.
00025 // ----------------------------------------------------------------------------
00026 Voice::Voice()
00027 {
00028   set_chip_model(MOS6581);
00029 }
00030 
00031 // ----------------------------------------------------------------------------
00032 // Set chip model.
00033 // ----------------------------------------------------------------------------
00034 void Voice::set_chip_model(chip_model model)
00035 {
00036   wave.set_chip_model(model);
00037 
00038   if (model == MOS6581) {
00039     // The waveform D/A converter introduces a DC offset in the signal
00040     // to the envelope multiplying D/A converter. The "zero" level of
00041     // the waveform D/A converter can be found as follows:
00042     //
00043     // Measure the "zero" voltage of voice 3 on the SID audio output
00044     // pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 =
00045     // $0f, all other registers zeroed).
00046     //
00047     // Then set the sustain level for voice 3 to maximum and search for
00048     // the waveform output value yielding the same voltage as found
00049     // above. This is done by trying out different waveform output
00050     // values until the correct value is found, e.g. with the following
00051     // program:
00052     //
00053     //  lda #$08
00054     //  sta $d412
00055     //  lda #$0b
00056     //  sta $d417
00057     //  lda #$0f
00058     //  sta $d418
00059     //  lda #$f0
00060     //  sta $d414
00061     //  lda #$21
00062     //  sta $d412
00063     //  lda #$01
00064     //  sta $d40e
00065     //
00066     //  ldx #$00
00067     //  lda #$38        ; Tweak this to find the "zero" level
00068     //l cmp $d41b
00069     //  bne l
00070     //  stx $d40e       ; Stop frequency counter - freeze waveform output
00071     //  brk
00072     //
00073     // The waveform output range is 0x000 to 0xfff, so the "zero"
00074     // level should ideally have been 0x800. In the measured chip, the
00075     // waveform output "zero" level was found to be 0x380 (i.e. $d41b
00076     // = 0x38) at 5.94V.
00077 
00078     wave_zero = 0x380;
00079 
00080     // The envelope multiplying D/A converter introduces another DC
00081     // offset. This is isolated by the following measurements:
00082     //
00083     // * The "zero" output level of the mixer at full volume is 5.44V.
00084     // * Routing one voice to the mixer at full volume yields
00085     //     6.75V at maximum voice output (wave = 0xfff, sustain = 0xf)
00086     //     5.94V at "zero" voice output  (wave = any,   sustain = 0x0)
00087     //     5.70V at minimum voice output (wave = 0x000, sustain = 0xf)
00088     // * The DC offset of one voice is (5.94V - 5.44V) = 0.50V
00089     // * The dynamic range of one voice is |6.75V - 5.70V| = 1.05V
00090     // * The DC offset is thus 0.50V/1.05V ~ 1/2 of the dynamic range.
00091     //
00092     // Note that by removing the DC offset, we get the following ranges for
00093     // one voice:
00094     //     y > 0: (6.75V - 5.44V) - 0.50V =  0.81V
00095     //     y < 0: (5.70V - 5.44V) - 0.50V = -0.24V
00096     // The scaling of the voice amplitude is not symmetric about y = 0;
00097     // this follows from the DC level in the waveform output.
00098 
00099     voice_DC = 0x800*0xff;
00100   }
00101   else {
00102     // No DC offsets in the MOS8580.
00103     wave_zero = 0x800;
00104     voice_DC = 0;
00105   }
00106 }
00107 
00108 // ----------------------------------------------------------------------------
00109 // Set sync source.
00110 // ----------------------------------------------------------------------------
00111 void Voice::set_sync_source(Voice* source)
00112 {
00113   wave.set_sync_source(&source->wave);
00114 }
00115 
00116 // ----------------------------------------------------------------------------
00117 // Register functions.
00118 // ----------------------------------------------------------------------------
00119 void Voice::writeCONTROL_REG(reg8 control)
00120 {
00121   wave.writeCONTROL_REG(control);
00122   envelope.writeCONTROL_REG(control);
00123 }
00124 
00125 // ----------------------------------------------------------------------------
00126 // SID reset.
00127 // ----------------------------------------------------------------------------
00128 void Voice::reset()
00129 {
00130   wave.reset();
00131   envelope.reset();
00132 }
00133