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