summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/adc0808.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/adc0808.c')
-rw-r--r--src/devices/machine/adc0808.c187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/devices/machine/adc0808.c b/src/devices/machine/adc0808.c
new file mode 100644
index 00000000000..dc173cc178e
--- /dev/null
+++ b/src/devices/machine/adc0808.c
@@ -0,0 +1,187 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "adc0808.h"
+
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+// device type definition
+const device_type ADC0808 = &device_creator<adc0808_device>;
+
+//-------------------------------------------------
+// adc0808_device - constructor
+//-------------------------------------------------
+
+adc0808_device::adc0808_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ADC0808, "ADC0808", tag, owner, clock, "adc0808", __FILE__),
+ m_out_eoc_cb(*this),
+ m_address(0),
+ m_start(0),
+ m_eoc(0),
+ m_next_eoc(0),
+ m_cycle(0),
+ m_bit(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+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());
+
+ // 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));
+ 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));
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void adc0808_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (!m_start)
+ {
+ 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;
+ }
+ }
+ }
+
+ if (m_cycle == 0)
+ {
+ /* set end of conversion pin */
+ if (m_next_eoc != m_eoc)
+ {
+ m_out_eoc_cb(m_next_eoc);
+ m_eoc = m_next_eoc;
+ }
+ }
+
+ m_cycle++;
+
+ if (m_cycle == 8)
+ {
+ m_cycle = 0;
+ }
+}
+
+
+//-------------------------------------------------
+// data_r - data read
+//-------------------------------------------------
+
+READ8_MEMBER( adc0808_device::data_r )
+{
+ return m_sar;
+}
+
+
+//-------------------------------------------------
+// ale_w - address write
+//-------------------------------------------------
+
+WRITE8_MEMBER( adc0808_device::ale_w )
+{
+ m_address = data;
+}
+
+
+//-------------------------------------------------
+// start_w - start conversion
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER( adc0808_device::start_w )
+{
+ if (!m_start && state) // rising edge
+ {
+ // reset registers
+
+ m_sar = 0;
+ m_bit = 0;
+ }
+ else if (m_start && !state) // falling edge
+ {
+ // start conversion
+
+ m_next_eoc = 0;
+ }
+
+ m_start = state;
+}