diff options
author | 2018-04-02 11:51:02 +0200 | |
---|---|---|
committer | 2018-04-02 12:02:53 +0200 | |
commit | 0086d473b7902f078f0c1a5725817237255af4f5 (patch) | |
tree | 847e4f63dcaa68a02da183d234c6bcee98a9e187 /src/devices/machine/adc0808.cpp | |
parent | 7079fa8fa60f741d4aa277598ff2ff61b1fd54f2 (diff) |
adc0808: Rewrite and make it work
Diffstat (limited to 'src/devices/machine/adc0808.cpp')
-rw-r--r-- | src/devices/machine/adc0808.cpp | 241 |
1 files changed, 122 insertions, 119 deletions
diff --git a/src/devices/machine/adc0808.cpp b/src/devices/machine/adc0808.cpp index d279850f32e..a977c05ffb8 100644 --- a/src/devices/machine/adc0808.cpp +++ b/src/devices/machine/adc0808.cpp @@ -1,42 +1,74 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/********************************************************************** +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** - National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation + ADC0808/ADC0809 - The only difference between ADC0808 and ADC0809 is that the latter - chip allows twice as much adjusted error. Mitsubishi parts M58990P - and M58990P-1 are equivalent to ADC0808 and ADC0809. + A/D Converter with 8 Channel-Multiplexer -**********************************************************************/ +***************************************************************************/ #include "emu.h" #include "adc0808.h" +//************************************************************************** +// CONSTANTS/MACROS +//************************************************************************** + +#define VERBOSE 0 + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(ADC0808, adc0808_device, "adc0808", "ADC0808 A/D Converter") +DEFINE_DEVICE_TYPE(ADC0809, adc0809_device, "adc0809", "ADC0809 A/D Converter") +DEFINE_DEVICE_TYPE(M58990P, m58990p_device, "m58990p", "M58990P A/D Converter") //************************************************************************** // LIVE DEVICE //************************************************************************** -// device type definition -DEFINE_DEVICE_TYPE(ADC0808, adc0808_device, "adc0808", "ADC0808") +// permit our enum to be saved +ALLOW_SAVE_TYPE(adc0808_device::state); //------------------------------------------------- // adc0808_device - constructor //------------------------------------------------- -adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, ADC0808, tag, owner, clock), - m_out_eoc_cb(*this), - m_address(0), - m_start(0), - m_eoc(0), - m_next_eoc(0), m_sar(0), - m_cycle(0), - m_bit(0), - m_cycle_timer(nullptr) +adc0808_device::adc0808_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + m_eoc_cb(*this), m_eoc_ff_cb(*this), + m_in_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} }, + m_state(STATE_IDLE), + m_cycle_timer(nullptr), + m_start(0), m_cycle(0), m_step(0), m_address(0), m_sar(0xff), m_eoc_pending(false) +{ +} + +adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + adc0808_device(mconfig, ADC0808, tag, owner, clock) +{ +} + +//------------------------------------------------- +// adc0809_device - constructor +//------------------------------------------------- + +adc0809_device::adc0809_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + adc0808_device(mconfig, ADC0809, tag, owner, clock) +{ +} + +//------------------------------------------------- +// m58990p_device - constructor +//------------------------------------------------- + +m58990p_device::m58990p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + adc0808_device(mconfig, M58990P, tag, owner, clock) { } @@ -47,146 +79,117 @@ adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, d void adc0808_device::device_start() { // resolve callbacks - m_out_eoc_cb.resolve_safe(); - m_in_vref_pos_cb.bind_relative_to(*owner()); - m_in_vref_neg_cb.bind_relative_to(*owner()); - m_in_in_0_cb.bind_relative_to(*owner()); - m_in_in_1_cb.bind_relative_to(*owner()); - m_in_in_2_cb.bind_relative_to(*owner()); - m_in_in_3_cb.bind_relative_to(*owner()); - m_in_in_4_cb.bind_relative_to(*owner()); - m_in_in_5_cb.bind_relative_to(*owner()); - m_in_in_6_cb.bind_relative_to(*owner()); - m_in_in_7_cb.bind_relative_to(*owner()); + m_eoc_cb.resolve_safe(); + m_eoc_ff_cb.resolve_safe(); + + for (int i = 0; i < 8; i++) + m_in_cb[i].resolve_safe(0xff); // allocate timers m_cycle_timer = timer_alloc(); m_cycle_timer->adjust(attotime::zero, 0, attotime::from_hz(clock())); - // register for state saving - save_item(NAME(m_address)); + // register for save states + save_item(NAME(m_state)); save_item(NAME(m_start)); - save_item(NAME(m_eoc)); - save_item(NAME(m_next_eoc)); - save_item(NAME(m_sar)); save_item(NAME(m_cycle)); - save_item(NAME(m_bit)); + save_item(NAME(m_step)); + save_item(NAME(m_address)); + save_item(NAME(m_sar)); + save_item(NAME(m_eoc_pending)); } - //------------------------------------------------- // device_timer - handler timer events //------------------------------------------------- void adc0808_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - if (!m_start) + // eoc is delayed one cycle + if (m_eoc_pending) { - if (m_cycle == 7) - { - m_bit++; - - if (m_bit == 8) - { - /* sample input */ - double vref_pos = m_in_vref_pos_cb(); - double vref_neg = m_in_vref_neg_cb(); - - double input = 0; - - switch (m_address) - { - case 0: - input = m_in_in_0_cb(); - break; - case 1: - input = m_in_in_1_cb(); - break; - case 2: - input = m_in_in_2_cb(); - break; - case 3: - input = m_in_in_3_cb(); - break; - case 4: - input = m_in_in_4_cb(); - break; - case 5: - input = m_in_in_5_cb(); - break; - case 6: - input = m_in_in_6_cb(); - break; - case 7: - input = m_in_in_7_cb(); - break; - } - m_sar = (255 * (input - vref_neg)) / (vref_pos - vref_neg); - - /* trigger end of conversion */ - m_next_eoc = 1; - } - } + m_eoc_cb(1); + m_eoc_ff_cb(1); + m_eoc_pending = false; } - if (m_cycle == 0) + // start of conversion cycle + if (m_cycle == 0 && m_state == STATE_CONVERSION_START) + m_state = STATE_CONVERSION_RUNNING; + + // end of conversion cycle + if (m_cycle == 7 && m_state == STATE_CONVERSION_RUNNING) { - /* set end of conversion pin */ - if (m_next_eoc != m_eoc) + // the conversion takes 8 steps every 8 cycles + if (m_step++ == 7) { - m_out_eoc_cb(m_next_eoc); - m_eoc = m_next_eoc; + m_step = 0; + m_sar = m_in_cb[m_address](0); + m_eoc_pending = true; + m_state = STATE_IDLE; + + if (VERBOSE) + logerror("Conversion finished, result %02x\n", m_sar); } } - m_cycle++; - - if (m_cycle == 8) - { - m_cycle = 0; - } + // next cycle + m_cycle = (m_cycle + 1) & 7; } -//------------------------------------------------- -// data_r - data read -//------------------------------------------------- +//************************************************************************** +// INTERFACE +//************************************************************************** READ8_MEMBER( adc0808_device::data_r ) { - return m_sar; -} + if (VERBOSE) + logerror("data_r: %02x\n", m_sar); + // oe connected to flip-flop clear + m_eoc_ff_cb(0); -//------------------------------------------------- -// ale_w - address write -//------------------------------------------------- + return m_sar; +} -WRITE8_MEMBER( adc0808_device::ale_w ) +WRITE8_MEMBER( adc0808_device::address_w ) { - m_address = data; + m_address = data & 7; } - -//------------------------------------------------- -// start_w - start conversion -//------------------------------------------------- - WRITE_LINE_MEMBER( adc0808_device::start_w ) { - if (!m_start && state) // rising edge + if (m_start == 1 && state == 0) { - // reset registers - - m_sar = 0; - m_bit = 0; + m_state = STATE_CONVERSION_START; } - else if (m_start && !state) // falling edge + else if (m_start == 0 && state == 1) { - // start conversion - - m_next_eoc = 0; + m_sar = 0; + m_eoc_cb(0); + m_eoc_pending = false; } m_start = state; } + +WRITE8_MEMBER( adc0808_device::address_offset_start_w ) +{ + if (VERBOSE) + logerror("address_offset_start_w %02x %02x\n", offset, data); + + start_w(1); + address_w(space, 0, offset); + start_w(0); +} + +WRITE8_MEMBER( adc0808_device::address_data_start_w ) +{ + if (VERBOSE) + logerror("address_data_start_w %02x %02x\n", offset, data); + + start_w(1); + address_w(space, 0, data); + start_w(0); +} |