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