diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/devices/machine/adc083x.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/devices/machine/adc083x.cpp')
-rw-r--r-- | src/devices/machine/adc083x.cpp | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/src/devices/machine/adc083x.cpp b/src/devices/machine/adc083x.cpp new file mode 100644 index 00000000000..40259e595f1 --- /dev/null +++ b/src/devices/machine/adc083x.cpp @@ -0,0 +1,448 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + National Semiconductor ADC0831 / ADC0832 / ADC0834 / ADC0838 + + 8-Bit serial I/O A/D Converters with Muliplexer Options + +***************************************************************************/ + +#include "emu.h" +#include "adc083x.h" + +#define VERBOSE_LEVEL ( 0 ) + +INLINE void ATTR_PRINTF( 3, 4 ) verboselog( int n_level, device_t &device, const char *s_fmt, ... ) +{ + if( VERBOSE_LEVEL >= n_level ) + { + va_list v; + char buf[ 32768 ]; + va_start( v, s_fmt ); + vsprintf( buf, s_fmt, v ); + va_end( v ); + device.logerror( "%s: %s", device.machine().describe_context( ), buf ); + } +} + +/*************************************************************************** + PARAMETERS +***************************************************************************/ + +enum +{ + STATE_IDLE, + STATE_WAIT_FOR_START, + STATE_SHIFT_MUX, + STATE_MUX_SETTLE, + STATE_OUTPUT_MSB_FIRST, + STATE_WAIT_FOR_SE, + STATE_OUTPUT_LSB_FIRST, + STATE_FINISHED +}; + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +const device_type ADC0831 = &device_creator<adc0831_device>; +const device_type ADC0832 = &device_creator<adc0832_device>; +const device_type ADC0834 = &device_creator<adc0834_device>; +const device_type ADC0838 = &device_creator<adc0838_device>; + +adc083x_device::adc083x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_cs(0), + m_clk(0), + m_di(0), + m_se(0), + m_do(1), + m_sgl(0), + m_odd(0), + m_sel1(0), + m_sel0(0), + m_state(STATE_IDLE), + m_bit(0), + m_output(0) +{ +} + +adc0831_device::adc0831_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : adc083x_device(mconfig, ADC0831, "ADC0831", tag, owner, clock, "adc0831", __FILE__) +{ + m_mux_bits = 0; +} + +adc0832_device::adc0832_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : adc083x_device(mconfig, ADC0832, "ADC0832", tag, owner, clock, "adc0832", __FILE__) +{ + m_mux_bits = 2; +} + +adc0834_device::adc0834_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : adc083x_device(mconfig, ADC0834, "ADC0834", tag, owner, clock, "adc0834", __FILE__) +{ + m_mux_bits = 3; +} + +adc0838_device::adc0838_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : adc083x_device(mconfig, ADC0838, "ADC0838", tag, owner, clock, "adc0838", __FILE__) +{ + m_mux_bits = 4; +} + +/*------------------------------------------------- + adc083x_device::device_start +-------------------------------------------------*/ + +void adc083x_device::device_start() +{ + clear_sars(); + + /* resolve callbacks */ + m_input_callback.bind_relative_to(*owner()); + + /* register for state saving */ + save_item( NAME(m_cs) ); + save_item( NAME(m_clk) ); + save_item( NAME(m_di) ); + save_item( NAME(m_se) ); + save_item( NAME(m_sars) ); + save_item( NAME(m_do) ); + save_item( NAME(m_sgl) ); + save_item( NAME(m_odd) ); + save_item( NAME(m_sel1) ); + save_item( NAME(m_sel0) ); + save_item( NAME(m_state) ); + save_item( NAME(m_bit) ); + save_item( NAME(m_output) ); + save_item( NAME(m_mux_bits) ); +} + +/*------------------------------------------------- + adc083x_device::clear_sars +-------------------------------------------------*/ + +void adc083x_device::clear_sars() +{ + if( type() == ADC0834 || type() == ADC0838 ) + { + m_sars = 1; + } + else + { + m_sars = 0; + } +} + +/*------------------------------------------------- + adc083x_device::cs_write +-------------------------------------------------*/ + +WRITE_LINE_MEMBER( adc083x_device::cs_write ) +{ + if( m_cs != state ) + { + verboselog( 2, *this, "adc083x_cs_write( %s, %d )\n", tag(), state ); + } + + if( m_cs == 0 && state != 0 ) + { + m_state = STATE_IDLE; + clear_sars(); + m_do = 1; + } + + if( m_cs != 0 && state == 0 ) + { + if( type() == ADC0831 ) + { + m_state = STATE_MUX_SETTLE; + } + else + { + m_state = STATE_WAIT_FOR_START; + } + + clear_sars(); + m_do = 1; + } + + m_cs = state; +} + +/*------------------------------------------------- + adc083x_device::conversion +-------------------------------------------------*/ + +UINT8 adc083x_device::conversion() +{ + int result; + int positive_channel = ADC083X_AGND; + int negative_channel = ADC083X_AGND; + double positive = 0; + double negative = 0; + double gnd = m_input_callback(ADC083X_AGND); + double vref = m_input_callback(ADC083X_VREF); + + if( type() == ADC0831 ) + { + positive_channel = ADC083X_CH0; + negative_channel = ADC083X_CH1; + } + else if( type() == ADC0832 ) + { + positive_channel = ADC083X_CH0 + m_odd; + if( m_sgl == 0 ) + { + negative_channel = positive_channel ^ 1; + } + else + { + negative_channel = ADC083X_AGND; + } + } + else if( type() == ADC0834 ) + { + positive_channel = ADC083X_CH0 + m_odd + ( m_sel1 * 2 ); + if( m_sgl == 0 ) + { + negative_channel = positive_channel ^ 1; + } + else + { + negative_channel = ADC083X_AGND; + } + } + else if( type() == ADC0838 ) + { + positive_channel = ADC083X_CH0 + m_odd + ( m_sel0 * 2 ) + ( m_sel1 * 4 ); + if( m_sgl == 0 ) + { + negative_channel = positive_channel ^ 1; + } + else + { + negative_channel = ADC083X_COM; + } + } + + if( positive_channel != ADC083X_AGND ) + { + positive = m_input_callback(positive_channel) - gnd; + } + + if( negative_channel != ADC083X_AGND ) + { + negative = m_input_callback(negative_channel) - gnd; + } + + result = (int) ( ( ( positive - negative ) * 255 ) / vref ); + if( result < 0 ) + { + result = 0; + } + else if( result > 255 ) + { + result = 255; + } + + return result; +} + +/*------------------------------------------------- + adc083x_device::clk_write +-------------------------------------------------*/ + +WRITE_LINE_MEMBER( adc083x_device::clk_write ) +{ + if( m_clk != state ) + { + verboselog( 2, *this, "adc083x_clk_write( %s, %d )\n", tag(), state ); + } + + if( m_cs == 0 ) + { + if( m_clk == 0 && state != 0 ) + { + switch( m_state ) + { + case STATE_WAIT_FOR_START: + if( m_di != 0 ) + { + verboselog( 1, *this, "adc083x %s got start bit\n", tag() ); + m_state = STATE_SHIFT_MUX; + m_sars = 0; + m_sgl = 0; + m_odd = 0; + m_sel1 = 0; + m_sel0 = 0; + m_bit = 0; + } + else + { + verboselog( 1, *this, "adc083x %s not start bit\n", tag() ); + } + break; + + case STATE_SHIFT_MUX: + switch( m_bit ) + { + case 0: + if( m_di != 0 ) + { + m_sgl = 1; + } + verboselog( 1, *this, "adc083x %s sgl <- %d\n", tag(), m_sgl ); + break; + + case 1: + if( m_di != 0 ) + { + m_odd = 1; + } + verboselog( 1, *this, "adc083x %s odd <- %d\n", tag(), m_odd ); + break; + + case 2: + if( m_di != 0 ) + { + m_sel1 = 1; + } + verboselog( 1, *this, "adc083x %s sel1 <- %d\n", tag(), m_sel1 ); + break; + + case 3: + if( m_di != 0 ) + { + m_sel0 = 1; + } + verboselog( 1, *this, "adc083x %s sel0 <- %d\n", tag(), m_sel0 ); + break; + } + + m_bit++; + if( m_bit == m_mux_bits ) + { + m_state = STATE_MUX_SETTLE; + } + + break; + + case STATE_WAIT_FOR_SE: + m_sars = 0; + if( type() == ADC0838 && m_se != 0 ) + { + verboselog( 1, *this, "adc083x %s not se\n", tag() ); + } + else + { + verboselog( 1, *this, "adc083x %s got se\n", tag() ); + m_state = STATE_OUTPUT_LSB_FIRST; + m_bit = 1; + } + break; + } + } + + if( m_clk != 0 && state == 0 ) + { + switch( m_state ) + { + case STATE_MUX_SETTLE: + verboselog( 1, *this, "adc083x %s mux settle\n", tag() ); + m_output = conversion(); + m_state = STATE_OUTPUT_MSB_FIRST; + m_bit = 7; + clear_sars(); + m_do = 0; + break; + + case STATE_OUTPUT_MSB_FIRST: + m_do = ( m_output >> m_bit ) & 1; + verboselog( 1, *this, "adc083x %s msb %d -> %d\n", tag(), m_bit, m_do ); + + m_bit--; + if( m_bit < 0 ) + { + if( type() == ADC0831 ) + { + m_state = STATE_FINISHED; + } + else + { + m_state = STATE_WAIT_FOR_SE; + } + } + break; + + case STATE_OUTPUT_LSB_FIRST: + m_do = ( m_output >> m_bit ) & 1; + verboselog( 1, *this, "adc083x %s lsb %d -> %d\n", tag(), m_bit, m_do ); + + m_bit++; + if( m_bit == 8 ) + { + m_state = STATE_FINISHED; + } + break; + + case STATE_FINISHED: + m_state = STATE_IDLE; + m_do = 0; + break; + } + } + } + + m_clk = state; +} + +/*------------------------------------------------- + adc083x_device::di_write +-------------------------------------------------*/ + +WRITE_LINE_MEMBER( adc083x_device::di_write ) +{ + if( m_di != state ) + { + verboselog( 2, *this, "adc083x_di_write( %s, %d )\n", tag(), state ); + } + + m_di = state; +} + +/*------------------------------------------------- + adc083x_device::se_write +-------------------------------------------------*/ + +WRITE_LINE_MEMBER( adc083x_device::se_write ) +{ + if( m_se != state ) + { + verboselog( 2, *this, "adc083x_se_write( %s, %d )\n", tag(), state ); + } + + m_se = state; +} + +/*------------------------------------------------- + adc083x_device::sars_read +-------------------------------------------------*/ + +READ_LINE_MEMBER( adc083x_device::sars_read ) +{ + verboselog( 1, *this, "adc083x_sars_read( %s ) %d\n", tag(), m_sars ); + return m_sars; +} + +/*------------------------------------------------- + adc083x_device::do_read +-------------------------------------------------*/ + +READ_LINE_MEMBER( adc083x_device::do_read ) +{ + verboselog( 1, *this, "adc083x_do_read( %s ) %d\n", tag(), m_do ); + return m_do; +} |