1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// license:BSD-3-Clause
// copyright-holders:smf
/***************************************************************************
dac.cpp
Four quadrant multiplying DAC.
Binary Weighted Resistor Network, R-2R Ladder & PWM
Binary, Ones Complement, or Twos Complement coding
***************************************************************************/
#include "emu.h"
#define DAC_GENERATOR_EPILOG(_dac_type, _dac_class, _dac_description, _dac_shortname) \
DEFINE_DEVICE_TYPE(_dac_type, _dac_class, _dac_shortname, _dac_description)
#include "dac.h"
//-------------------------------------------------
// dac_mapper_unsigned - map an unsigned value of
// the given number of bits to a sample value
//-------------------------------------------------
stream_buffer::sample_t dac_mapper_unsigned(u32 input, u8 bits)
{
stream_buffer::sample_t scale = 1.0 / stream_buffer::sample_t((bits > 1) ? (1 << bits) : 1);
input &= (1 << bits) - 1;
return stream_buffer::sample_t(input) * scale;
}
//-------------------------------------------------
// dac_mapper_signed - map a signed (2s complement)
// value of the given number of bits to a sample value
//-------------------------------------------------
stream_buffer::sample_t dac_mapper_signed(u32 input, u8 bits)
{
return dac_mapper_unsigned(input ^ (1 << (bits - 1)), bits);
}
//-------------------------------------------------
// dac_mapper_ones_complement - map a value where
// the top bit indicates the lower bits should be
// treated as a negative 1s complement
//-------------------------------------------------
stream_buffer::sample_t dac_mapper_ones_complement(u32 input, u8 bits)
{
// this mapping assumes symmetric reference voltages,
// which is true for all existing cases
if (BIT(input, bits - 1))
return 0.5 - 0.5 * dac_mapper_unsigned(~input, bits - 1);
else
return 0.5 + 0.5 * dac_mapper_unsigned(input, bits - 1);
}
//-------------------------------------------------
// dac_device_base - constructor
//-------------------------------------------------
dac_device_base::dac_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock, u8 bits, dac_mapper_callback mapper, stream_buffer::sample_t gain) :
device_t(mconfig, type, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_stream(nullptr),
m_curval(0),
m_value_map(1 << bits),
m_bits(bits),
m_mapper(mapper),
m_gain(gain),
m_range_min((bits == 1) ? 0.0 : -1.0),
m_range_max(1.0)
{
}
//-------------------------------------------------
// device_start - device startup
//-------------------------------------------------
void dac_device_base::device_start()
{
// precompute all gain-applied values
for (s32 code = 0; code < m_value_map.size(); code++)
m_value_map[code] = m_mapper(code, m_bits) * m_gain;
// determine the number of inputs
int inputs = (m_specified_inputs_mask == 0) ? 0 : 2;
// create the stream
m_stream = stream_alloc(inputs, 1, 48000 * 4);
// save data
save_item(NAME(m_curval));
}
//-------------------------------------------------
// sound_stream_update - stream updates
//-------------------------------------------------
void dac_device_base::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
auto &out = outputs[0];
// rails are constant
if (inputs.size() == 0)
{
out.fill(m_range_min + m_curval * (m_range_max - m_range_min));
return;
}
auto &hi = inputs[DAC_INPUT_RANGE_HI];
auto &lo = inputs[DAC_INPUT_RANGE_LO];
// constant lo, streaming hi
if (!BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_LO))
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, m_range_min + m_curval * (hi.get(sampindex) - m_range_min));
}
// constant hi, streaming lo
else if (!BIT(m_specified_inputs_mask, DAC_INPUT_RANGE_HI))
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, lo.get(sampindex) + m_curval * (m_range_max - lo.get(sampindex)));
}
// both streams provided
else
{
for (int sampindex = 0; sampindex < out.samples(); sampindex++)
out.put(sampindex, lo.get(sampindex) + m_curval * (hi.get(sampindex) - lo.get(sampindex)));
}
}
|