1 // license:BSD-3-Clause
2 // copyright-holders:smf
3 /***************************************************************************
4 
5     National Semiconductor ADC0831 / ADC0832 / ADC0834 / ADC0838
6 
7     8-Bit serial I/O A/D Converters with Muliplexer Options
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "adc083x.h"
13 
14 #define VERBOSE_LEVEL ( 0 )
15 
verboselog(int n_level,device_t & device,const char * s_fmt,...)16 static inline void ATTR_PRINTF( 3, 4 ) verboselog( int n_level, device_t &device, const char *s_fmt, ... )
17 {
18 	if( VERBOSE_LEVEL >= n_level )
19 	{
20 		va_list v;
21 		char buf[ 32768 ];
22 		va_start( v, s_fmt );
23 		vsprintf( buf, s_fmt, v );
24 		va_end( v );
25 		device.logerror( "%s: %s", device.machine().describe_context( ), buf );
26 	}
27 }
28 
29 /***************************************************************************
30     PARAMETERS
31 ***************************************************************************/
32 
33 enum
34 {
35 	STATE_IDLE,
36 	STATE_WAIT_FOR_START,
37 	STATE_SHIFT_MUX,
38 	STATE_MUX_SETTLE,
39 	STATE_OUTPUT_MSB_FIRST,
40 	STATE_WAIT_FOR_SE,
41 	STATE_OUTPUT_LSB_FIRST,
42 	STATE_FINISHED
43 };
44 
45 /***************************************************************************
46     TYPE DEFINITIONS
47 ***************************************************************************/
48 
49 DEFINE_DEVICE_TYPE(ADC0831, adc0831_device, "adc0831", "ADC0831 A/D Converter")
50 DEFINE_DEVICE_TYPE(ADC0832, adc0832_device, "adc0832", "ADC0832 A/D Converter")
51 DEFINE_DEVICE_TYPE(ADC0834, adc0834_device, "adc0834", "ADC0834 A/D Converter")
52 DEFINE_DEVICE_TYPE(ADC0838, adc0838_device, "adc0838", "ADC0838 A/D Converter")
53 
adc083x_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,uint32_t mux_bits)54 adc083x_device::adc083x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t mux_bits) :
55 	device_t(mconfig, type, tag, owner, clock),
56 	m_mux_bits(mux_bits),
57 	m_cs(0),
58 	m_clk(0),
59 	m_di(0),
60 	m_se(0),
61 	m_do(1),
62 	m_sgl(0),
63 	m_odd(0),
64 	m_sel1(0),
65 	m_sel0(0),
66 	m_state(STATE_IDLE),
67 	m_bit(0),
68 	m_output(0),
69 	m_input_callback(*this)
70 {
71 }
72 
adc0831_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)73 adc0831_device::adc0831_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
74 	: adc083x_device(mconfig, ADC0831, tag, owner, clock, 0)
75 {
76 }
77 
adc0832_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)78 adc0832_device::adc0832_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
79 	: adc083x_device(mconfig, ADC0832, tag, owner, clock, 2)
80 {
81 }
82 
adc0834_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)83 adc0834_device::adc0834_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
84 	: adc083x_device(mconfig, ADC0834, tag, owner, clock, 3)
85 {
86 }
87 
adc0838_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)88 adc0838_device::adc0838_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
89 	: adc083x_device(mconfig, ADC0838, tag, owner, clock, 4)
90 {
91 }
92 
93 /*-------------------------------------------------
94     adc083x_device::device_start
95 -------------------------------------------------*/
96 
device_start()97 void adc083x_device::device_start()
98 {
99 	clear_sars();
100 
101 	// resolve callbacks
102 	m_input_callback.resolve();
103 
104 	// register for state saving
105 	save_item( NAME(m_cs) );
106 	save_item( NAME(m_clk) );
107 	save_item( NAME(m_di) );
108 	save_item( NAME(m_se) );
109 	save_item( NAME(m_sars) );
110 	save_item( NAME(m_do) );
111 	save_item( NAME(m_sgl) );
112 	save_item( NAME(m_odd) );
113 	save_item( NAME(m_sel1) );
114 	save_item( NAME(m_sel0) );
115 	save_item( NAME(m_state) );
116 	save_item( NAME(m_bit) );
117 	save_item( NAME(m_output) );
118 }
119 
120 /*-------------------------------------------------
121     adc083x_device::clear_sars
122 -------------------------------------------------*/
123 
clear_sars()124 void adc083x_device::clear_sars()
125 {
126 	if( type() == ADC0834 || type() == ADC0838 )
127 	{
128 		m_sars = 1;
129 	}
130 	else
131 	{
132 		m_sars = 0;
133 	}
134 }
135 
136 /*-------------------------------------------------
137     adc083x_device::cs_write
138 -------------------------------------------------*/
139 
WRITE_LINE_MEMBER(adc083x_device::cs_write)140 WRITE_LINE_MEMBER( adc083x_device::cs_write )
141 {
142 	if( m_cs != state )
143 	{
144 		verboselog( 2, *this, "adc083x_cs_write( %s, %d )\n", tag(), state );
145 	}
146 
147 	if( m_cs == 0 && state != 0 )
148 	{
149 		m_state = STATE_IDLE;
150 		clear_sars();
151 		m_do = 1;
152 	}
153 
154 	if( m_cs != 0 && state == 0 )
155 	{
156 		if( type() == ADC0831 )
157 		{
158 			m_state = STATE_MUX_SETTLE;
159 		}
160 		else
161 		{
162 			m_state = STATE_WAIT_FOR_START;
163 		}
164 
165 		clear_sars();
166 		m_do = 1;
167 	}
168 
169 	m_cs = state;
170 }
171 
172 /*-------------------------------------------------
173     adc083x_device::conversion
174 -------------------------------------------------*/
175 
conversion()176 uint8_t adc083x_device::conversion()
177 {
178 	int result;
179 	int positive_channel = ADC083X_AGND;
180 	int negative_channel = ADC083X_AGND;
181 	double positive = 0;
182 	double negative = 0;
183 	double gnd = m_input_callback(ADC083X_AGND);
184 	double vref = m_input_callback(ADC083X_VREF);
185 
186 	if( type() == ADC0831 )
187 	{
188 		positive_channel = ADC083X_CH0;
189 		negative_channel = ADC083X_CH1;
190 	}
191 	else if( type() == ADC0832 )
192 	{
193 		positive_channel = ADC083X_CH0 + m_odd;
194 		if( m_sgl == 0 )
195 		{
196 			negative_channel = positive_channel ^ 1;
197 		}
198 		else
199 		{
200 			negative_channel = ADC083X_AGND;
201 		}
202 	}
203 	else if( type() == ADC0834 )
204 	{
205 		positive_channel = ADC083X_CH0 + m_odd + ( m_sel1 * 2 );
206 		if( m_sgl == 0 )
207 		{
208 			negative_channel = positive_channel ^ 1;
209 		}
210 		else
211 		{
212 			negative_channel = ADC083X_AGND;
213 		}
214 	}
215 	else if( type() == ADC0838 )
216 	{
217 		positive_channel = ADC083X_CH0 + m_odd + ( m_sel0 * 2 ) + ( m_sel1 * 4 );
218 		if( m_sgl == 0 )
219 		{
220 			negative_channel = positive_channel ^ 1;
221 		}
222 		else
223 		{
224 			negative_channel = ADC083X_COM;
225 		}
226 	}
227 
228 	if( positive_channel != ADC083X_AGND )
229 	{
230 		positive = m_input_callback(positive_channel) - gnd;
231 	}
232 
233 	if( negative_channel != ADC083X_AGND )
234 	{
235 		negative = m_input_callback(negative_channel) - gnd;
236 	}
237 
238 	result = (int) ( ( ( positive - negative ) * 255 ) / vref );
239 	if( result < 0 )
240 	{
241 		result = 0;
242 	}
243 	else if( result > 255 )
244 	{
245 		result = 255;
246 	}
247 
248 	return result;
249 }
250 
251 /*-------------------------------------------------
252     adc083x_device::clk_write
253 -------------------------------------------------*/
254 
WRITE_LINE_MEMBER(adc083x_device::clk_write)255 WRITE_LINE_MEMBER( adc083x_device::clk_write )
256 {
257 	if( m_clk != state )
258 	{
259 		verboselog( 2, *this, "adc083x_clk_write( %s, %d )\n", tag(), state );
260 	}
261 
262 	if( m_cs == 0 )
263 	{
264 		if( m_clk == 0 && state != 0 )
265 		{
266 			switch( m_state )
267 			{
268 			case STATE_WAIT_FOR_START:
269 				if( m_di != 0 )
270 				{
271 					verboselog( 1, *this, "adc083x %s got start bit\n", tag() );
272 					m_state = STATE_SHIFT_MUX;
273 					m_sars = 0;
274 					m_sgl = 0;
275 					m_odd = 0;
276 					m_sel1 = 0;
277 					m_sel0 = 0;
278 					m_bit = 0;
279 				}
280 				else
281 				{
282 					verboselog( 1, *this, "adc083x %s not start bit\n", tag() );
283 				}
284 				break;
285 
286 			case STATE_SHIFT_MUX:
287 				switch( m_bit )
288 				{
289 				case 0:
290 					if( m_di != 0 )
291 					{
292 						m_sgl = 1;
293 					}
294 					verboselog( 1, *this, "adc083x %s sgl <- %d\n", tag(), m_sgl );
295 					break;
296 
297 				case 1:
298 					if( m_di != 0 )
299 					{
300 						m_odd = 1;
301 					}
302 					verboselog( 1, *this, "adc083x %s odd <- %d\n", tag(), m_odd );
303 					break;
304 
305 				case 2:
306 					if( m_di != 0 )
307 					{
308 						m_sel1 = 1;
309 					}
310 					verboselog( 1, *this, "adc083x %s sel1 <- %d\n", tag(), m_sel1 );
311 					break;
312 
313 				case 3:
314 					if( m_di != 0 )
315 					{
316 						m_sel0 = 1;
317 					}
318 					verboselog( 1, *this, "adc083x %s sel0 <- %d\n", tag(), m_sel0 );
319 					break;
320 				}
321 
322 				m_bit++;
323 				if( m_bit == m_mux_bits )
324 				{
325 					m_state = STATE_MUX_SETTLE;
326 				}
327 
328 				break;
329 
330 			case STATE_WAIT_FOR_SE:
331 				m_sars = 0;
332 				if( type() == ADC0838 && m_se != 0 )
333 				{
334 					verboselog( 1, *this, "adc083x %s not se\n", tag() );
335 				}
336 				else
337 				{
338 					verboselog( 1, *this, "adc083x %s got se\n", tag() );
339 					m_state = STATE_OUTPUT_LSB_FIRST;
340 					m_bit = 1;
341 				}
342 				break;
343 			}
344 		}
345 
346 		if( m_clk != 0 && state == 0 )
347 		{
348 			switch( m_state )
349 			{
350 			case STATE_MUX_SETTLE:
351 				verboselog( 1, *this, "adc083x %s mux settle\n", tag() );
352 				m_output = conversion();
353 				m_state = STATE_OUTPUT_MSB_FIRST;
354 				m_bit = 7;
355 				clear_sars();
356 				m_do = 0;
357 				break;
358 
359 			case STATE_OUTPUT_MSB_FIRST:
360 				m_do = ( m_output >> m_bit ) & 1;
361 				verboselog( 1, *this, "adc083x %s msb %d -> %d\n", tag(), m_bit, m_do );
362 
363 				m_bit--;
364 				if( m_bit < 0 )
365 				{
366 					if( type() == ADC0831 )
367 					{
368 						m_state = STATE_FINISHED;
369 					}
370 					else
371 					{
372 						m_state = STATE_WAIT_FOR_SE;
373 					}
374 				}
375 				break;
376 
377 			case STATE_OUTPUT_LSB_FIRST:
378 				m_do = ( m_output >> m_bit ) & 1;
379 				verboselog( 1, *this, "adc083x %s lsb %d -> %d\n", tag(), m_bit, m_do );
380 
381 				m_bit++;
382 				if( m_bit == 8 )
383 				{
384 					m_state = STATE_FINISHED;
385 				}
386 				break;
387 
388 			case STATE_FINISHED:
389 				m_state = STATE_IDLE;
390 				m_do = 0;
391 				break;
392 			}
393 		}
394 	}
395 
396 	m_clk = state;
397 }
398 
399 /*-------------------------------------------------
400     adc083x_device::di_write
401 -------------------------------------------------*/
402 
WRITE_LINE_MEMBER(adc083x_device::di_write)403 WRITE_LINE_MEMBER( adc083x_device::di_write )
404 {
405 	if( m_di != state )
406 	{
407 		verboselog( 2, *this, "adc083x_di_write( %s, %d )\n", tag(), state );
408 	}
409 
410 	m_di = state;
411 }
412 
413 /*-------------------------------------------------
414     adc083x_device::se_write
415 -------------------------------------------------*/
416 
WRITE_LINE_MEMBER(adc083x_device::se_write)417 WRITE_LINE_MEMBER( adc083x_device::se_write )
418 {
419 	if( m_se != state )
420 	{
421 		verboselog( 2, *this, "adc083x_se_write( %s, %d )\n", tag(), state );
422 	}
423 
424 	m_se = state;
425 }
426 
427 /*-------------------------------------------------
428     adc083x_device::sars_read
429 -------------------------------------------------*/
430 
READ_LINE_MEMBER(adc083x_device::sars_read)431 READ_LINE_MEMBER( adc083x_device::sars_read )
432 {
433 	verboselog( 1, *this, "adc083x_sars_read( %s ) %d\n", tag(), m_sars );
434 	return m_sars;
435 }
436 
437 /*-------------------------------------------------
438     adc083x_device::do_read
439 -------------------------------------------------*/
440 
READ_LINE_MEMBER(adc083x_device::do_read)441 READ_LINE_MEMBER( adc083x_device::do_read )
442 {
443 	verboselog( 1, *this, "adc083x_do_read( %s ) %d\n", tag(), m_do );
444 	return m_do;
445 }
446