summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/adc0808.cpp
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2018-04-02 11:51:02 +0200
committer Dirk Best <mail@dirk-best.de>2018-04-02 12:02:53 +0200
commit0086d473b7902f078f0c1a5725817237255af4f5 (patch)
tree847e4f63dcaa68a02da183d234c6bcee98a9e187 /src/devices/machine/adc0808.cpp
parent7079fa8fa60f741d4aa277598ff2ff61b1fd54f2 (diff)
adc0808: Rewrite and make it work
Diffstat (limited to 'src/devices/machine/adc0808.cpp')
-rw-r--r--src/devices/machine/adc0808.cpp241
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);
+}