1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4
5 RCA CDP1863 CMOS 8-Bit Programmable Frequency Generator emulation
6
7 **********************************************************************/
8
9 /*
10
11 TODO:
12
13 - what happens if you connect both clocks?
14
15 */
16
17 #include "emu.h"
18 #include "cdp1863.h"
19
20 //#define VERBOSE 1
21 #include "logmacro.h"
22
23
24
25 //**************************************************************************
26 // MACROS / CONSTANTS
27 //**************************************************************************
28
29 #define CDP1863_DEFAULT_LATCH 0x35
30
31
32
33 //**************************************************************************
34 // GLOBAL VARIABLES
35 //**************************************************************************
36
37 // devices
38 DEFINE_DEVICE_TYPE(CDP1863, cdp1863_device, "cdp1863", "RCA CDP1863")
39
40
41
42 //**************************************************************************
43 // LIVE DEVICE
44 //**************************************************************************
45
46 //-------------------------------------------------
47 // cdp1863_device - constructor
48 //-------------------------------------------------
49
cdp1863_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)50 cdp1863_device::cdp1863_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
51 : device_t(mconfig, CDP1863, tag, owner, clock)
52 , device_sound_interface(mconfig, *this)
53 , m_stream(nullptr)
54 , m_clock1(clock)
55 , m_clock2(0)
56 {
57 }
58
59
60 //-------------------------------------------------
61 // device_start - device-specific startup
62 //-------------------------------------------------
63
device_start()64 void cdp1863_device::device_start()
65 {
66 // create sound stream
67 m_stream = stream_alloc(0, 1, SAMPLE_RATE_OUTPUT_ADAPTIVE);
68
69 // register for state saving
70 save_item(NAME(m_clock1));
71 save_item(NAME(m_clock2));
72 save_item(NAME(m_oe));
73 save_item(NAME(m_latch));
74 save_item(NAME(m_signal));
75 save_item(NAME(m_incr));
76 }
77
78
79 //-------------------------------------------------
80 // sound_stream_update - handle update requests for
81 // our sound stream
82 //-------------------------------------------------
83
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)84 void cdp1863_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
85 {
86 stream_buffer::sample_t signal = m_signal;
87 auto &buffer = outputs[0];
88
89 if (m_oe)
90 {
91 double frequency;
92 int rate = buffer.sample_rate() / 2;
93
94 // get progress through wave
95 int incr = m_incr;
96
97 if (m_clock1 > 0)
98 {
99 // CLK1 is pre-divided by 4
100 frequency = m_clock1 / 4 / (m_latch + 1) / 2;
101 }
102 else
103 {
104 // CLK2 is pre-divided by 8
105 frequency = m_clock2 / 8 / (m_latch + 1) / 2;
106 }
107
108 if (signal < 0)
109 {
110 signal = -1.0;
111 }
112 else
113 {
114 signal = 1.0;
115 }
116
117 for (int sampindex = 0; sampindex < buffer.samples(); sampindex++)
118 {
119 buffer.put(sampindex, signal);
120 incr -= frequency;
121 while( incr < 0 )
122 {
123 incr += rate;
124 signal = -signal;
125 }
126 }
127
128 // store progress through wave
129 m_incr = incr;
130 m_signal = signal;
131 }
132 else
133 buffer.fill(0);
134 }
135
136
137 //-------------------------------------------------
138 // oe_w - output enable write
139 //-------------------------------------------------
140
oe_w(int state)141 void cdp1863_device::oe_w(int state)
142 {
143 m_oe = state;
144 }
145
146
147 //-------------------------------------------------
148 // set_clk1 - set clock 1
149 //-------------------------------------------------
150
set_clk1(int clock)151 void cdp1863_device::set_clk1(int clock)
152 {
153 m_clock1 = clock;
154 }
155
156
157 //-------------------------------------------------
158 // set_clk2 - set clock 2
159 //-------------------------------------------------
160
set_clk2(int clock)161 void cdp1863_device::set_clk2(int clock)
162 {
163 m_clock2 = clock;
164 }
165