summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/machine/adc0808.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/machine/adc0808.c')
-rw-r--r--trunk/src/emu/machine/adc0808.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/adc0808.c b/trunk/src/emu/machine/adc0808.c
new file mode 100644
index 00000000000..1c7f125e026
--- /dev/null
+++ b/trunk/src/emu/machine/adc0808.c
@@ -0,0 +1,171 @@
+/**********************************************************************
+
+ National Semiconductor ADC0808/ADC0809 8-Bit A/D Converter emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "adc0808.h"
+#include "machine/devhelpr.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),
+ m_address(0),
+ m_start(0),
+ m_next_eoc(0),
+ m_cycle(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void adc0808_device::device_config_complete()
+{
+ // inherit a copy of the static data
+ const adc0808_interface *intf = reinterpret_cast<const adc0808_interface *>(static_config());
+ if (intf != NULL)
+ *static_cast<adc0808_interface *>(this) = *intf;
+
+ // or initialize to defaults if none provided
+ else
+ {
+ memset(&m_out_eoc_cb, 0, sizeof(m_out_eoc_cb));
+ }
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void adc0808_device::device_start()
+{
+ // resolve callbacks
+ m_out_eoc_func.resolve(m_out_eoc_cb, *this);
+
+ // 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_func(this);
+ double vref_neg = m_in_vref_neg_func(this);
+
+ double input = m_in_in_func[m_address](this);
+
+ 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_func(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;
+}