summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-10-16 00:16:14 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-10-16 00:16:14 -0400
commitf398123bc3ce7d20074da016f5703aa92c055db9 (patch)
treed4b1998e7c9c59d6f6018d32ac9a2c0bccb79131
parent3e6734da05c8867b625a3b23126a91d71de301fe (diff)
Emulate ADC0804 and add device to various drivers
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/arcade.lua1
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/machine/adc0804.cpp256
-rw-r--r--src/devices/machine/adc0804.h108
-rw-r--r--src/mame/drivers/polepos.cpp13
-rw-r--r--src/mame/drivers/segae.cpp51
-rw-r--r--src/mame/drivers/segahang.cpp21
-rw-r--r--src/mame/drivers/segaorun.cpp31
-rw-r--r--src/mame/drivers/segaxbd.cpp31
-rw-r--r--src/mame/drivers/wallc.cpp14
-rw-r--r--src/mame/includes/polepos.h5
-rw-r--r--src/mame/includes/segahang.h8
-rw-r--r--src/mame/includes/segaorun.h4
-rw-r--r--src/mame/includes/segaxbd.h3
15 files changed, 491 insertions, 68 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index fb14dd8ba3a..27a5069ce51 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -575,6 +575,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/adc0804.h,MACHINES["ADC0804"] = true
+---------------------------------------------------
+
+if (MACHINES["ADC0804"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/adc0804.cpp",
+ MAME_DIR .. "src/devices/machine/adc0804.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/adc0808.h,MACHINES["ADC0808"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 7479bafb003..899b1b7e916 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -411,6 +411,7 @@ MACHINES["KBDC8042"] = true
MACHINES["I8257"] = true
MACHINES["AAKARTDEV"] = true
--MACHINES["ACIA6850"] = true
+MACHINES["ADC0804"] = true
MACHINES["ADC0808"] = true
MACHINES["ADC083X"] = true
MACHINES["ADC1038"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 739e3f38866..27cad92e159 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -418,6 +418,7 @@ MACHINES["8530SCC"] = true
MACHINES["AAKARTDEV"] = true
MACHINES["ACIA6850"] = true
MACHINES["ACORN_VIDC"] = true
+--MACHINES["ADC0804"] = true
MACHINES["ADC0808"] = true
MACHINES["ADC083X"] = true
MACHINES["ADC1038"] = true
diff --git a/src/devices/machine/adc0804.cpp b/src/devices/machine/adc0804.cpp
new file mode 100644
index 00000000000..ad39b1d8e81
--- /dev/null
+++ b/src/devices/machine/adc0804.cpp
@@ -0,0 +1,256 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ National Semiconductor ADC0804 8-bit µP Compatible A/D Converter
+
+ The ADC0804 is the most widely used member of a family of five
+ CMOS 8-bit ADCs with microprocessor-compatible interfaces, which
+ differ from each other only in error specifications:
+
+ ADC0801 ±¼ LSB Full-scale adjusted
+ ADC0802 ±½ LSB Vref/2 = 2.500 Vdc
+ ADC0803 ±½ LSB Full-scale adjusted
+ ADC0804 ±1 LSB Vref/2 = 2.500 Vdc
+ ADC0805 ±1 LSB Vref/2 = NC
+
+ Though these devices are designed to convert differential analog
+ inputs, single-phase conversion can be achieved by tying pin 7
+ (negative Vin) to pin 8 (analog GND). A CD4051B or other analog
+ switch IC is often used to multiplex several input sources.
+
+ Pin 4 should be connected to either an externally generated clock
+ signal (640 kHz typical, 1460 kHz maximum) or a timing capacitor
+ plus a resistor bridged to pin 19. The resistor is typically 10 kΩ
+ but higher values may be needed due to loading conditions when
+ multiple other devices are also clocked through pin 19, which
+ yields the output of the internal Schmitt trigger clock circuit.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "adc0804.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ADC0804, adc0804_device, "adc0804", "ADC0804 A/D Converter")
+
+ALLOW_SAVE_TYPE(adc0804_device::read_mode);
+
+
+//**************************************************************************
+// DEVICE CONSTRUCTION AND INITIALIZATION
+//**************************************************************************
+
+//-------------------------------------------------
+// adc0804_device - constructor
+//-------------------------------------------------
+
+adc0804_device::adc0804_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ADC0804, tag, owner, clock)
+ , m_vin_callback(*this)
+ , m_intr_callback(*this)
+ , m_res(0.0)
+ , m_cap(0.0)
+ , m_fclk_rc(attotime::zero)
+ , m_timer(nullptr)
+ , m_rd_mode(RD_STROBED)
+ , m_rd_active(false)
+ , m_wr_active(false)
+ , m_result(0)
+ , m_intr_active(false)
+{
+}
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void adc0804_device::device_resolve_objects()
+{
+ m_vin_callback.resolve_safe(0);
+ m_intr_callback.resolve_safe();
+
+ if (m_rd_mode == RD_GROUNDED)
+ m_rd_active = true;
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void adc0804_device::device_start()
+{
+ // calculate RC timing
+ if (m_res == 0.0 || m_cap == 0.0)
+ m_fclk_rc = attotime::zero;
+ else
+ m_fclk_rc = attotime::from_double(m_res * m_cap / 1.1);
+
+ // create timer
+ m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(adc0804_device::conversion_done), this));
+
+ // save state
+ if (m_rd_mode == RD_BITBANGED)
+ save_item(NAME(m_rd_active));
+ save_item(NAME(m_wr_active));
+ save_item(NAME(m_result));
+ save_item(NAME(m_intr_active));
+}
+
+
+//**************************************************************************
+// CONVERSION SEQUENCE
+//**************************************************************************
+
+// Conversion occurs over a busy period of 66–73 cycles, after 1–8 cycles of latency
+const int adc0804_device::s_conversion_cycles = 74;
+
+
+//-------------------------------------------------
+// set_interrupt - set or clear INTR output
+//-------------------------------------------------
+
+void adc0804_device::set_interrupt(bool state)
+{
+ if (m_intr_active != state)
+ {
+ m_intr_active = state;
+ m_intr_callback(state ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+
+//-------------------------------------------------
+// conversion_start - begin the busy period
+//-------------------------------------------------
+
+void adc0804_device::conversion_start()
+{
+ if (!m_timer->enabled())
+ m_timer->adjust(m_fclk_rc != attotime::zero ? m_fclk_rc * s_conversion_cycles : clocks_to_attotime(s_conversion_cycles));
+ else
+ logerror("%s: Tried to start conversion when already in progress\n", machine().describe_context());
+}
+
+
+//-------------------------------------------------
+// conversion_done - load result and signal
+// interrupt
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(adc0804_device::conversion_done)
+{
+ m_result = m_vin_callback();
+
+ if (!m_rd_active && !m_wr_active)
+ set_interrupt(true);
+}
+
+
+//**************************************************************************
+// BUS INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// read - read the 8-bit conversion result
+//-------------------------------------------------
+
+u8 adc0804_device::read()
+{
+ switch (m_rd_mode)
+ {
+ case RD_STROBED:
+ if (!machine().side_effects_disabled())
+ set_interrupt(false);
+ break;
+
+ case RD_BITBANGED:
+ if (!m_rd_active)
+ return 0xff; // open bus
+ break;
+
+ case RD_GROUNDED:
+ break;
+ }
+
+ return m_result;
+}
+
+
+//-------------------------------------------------
+// write - begin a new conversion
+//-------------------------------------------------
+
+void adc0804_device::write(u8 data)
+{
+ // data is ignored
+ set_interrupt(false);
+ conversion_start();
+}
+
+
+//-------------------------------------------------
+// read_and_write - read the result of the last
+// conversion and begin a new one
+//-------------------------------------------------
+
+u8 adc0804_device::read_and_write()
+{
+ if (!machine().side_effects_disabled())
+ {
+ set_interrupt(false);
+ conversion_start();
+ }
+
+ if (m_rd_mode == RD_BITBANGED && !m_rd_active)
+ return 0xff; // open bus
+ else
+ return m_result;
+}
+
+
+//-------------------------------------------------
+// rd_w - enable data bus by line write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(adc0804_device::rd_w)
+{
+ assert(m_rd_mode == RD_BITBANGED);
+
+ // RD input is active low
+ if (!state && !m_rd_active)
+ {
+ m_rd_active = true;
+ set_interrupt(false);
+ }
+ else if (state && m_rd_active)
+ m_rd_active = false;
+}
+
+
+//-------------------------------------------------
+// wr_w - begin conversion by line write
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(adc0804_device::wr_w)
+{
+ // WR input is active low
+ if (!state && !m_wr_active)
+ {
+ m_wr_active = true;
+ set_interrupt(false);
+ }
+ else if (state && m_wr_active)
+ {
+ m_wr_active = false;
+ conversion_start();
+ }
+}
diff --git a/src/devices/machine/adc0804.h b/src/devices/machine/adc0804.h
new file mode 100644
index 00000000000..50e59ad5615
--- /dev/null
+++ b/src/devices/machine/adc0804.h
@@ -0,0 +1,108 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ National Semiconductor ADC0804 8-bit µP Compatible A/D Converter
+
+***********************************************************************
+ ____ ____
+ /CS 1 |* \_/ | 20 Vcc (or Vref)
+ /RD 2 | | 19 CLK R
+ /WR 3 | | 18 DB0
+ CLK IN 4 | ADC0801 | 17 DB1
+ /INTR 5 | ADC0802 | 16 DB2
+ Vin(+) 6 | ADC0803 | 15 DB3
+ Vin(-) 7 | ADC0804 | 14 DB4
+ A GND 8 | ADC0805 | 13 DB5
+ Vref/2 9 | | 12 DB6
+ GND 10 |___________| 11 DB7
+
+**********************************************************************/
+
+#ifndef MAME_MACHINE_ADC0804_H
+#define MAME_MACHINE_ADC0804_H
+
+#pragma once
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> adc0804_device
+
+class adc0804_device : public device_t
+{
+ static const int s_conversion_cycles;
+
+public:
+ enum read_mode {
+ RD_STROBED = 0,
+ RD_BITBANGED,
+ RD_GROUNDED
+ };
+
+ // device type constructors
+ adc0804_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ adc0804_device(const machine_config &mconfig, const char *tag, device_t *owner, double r, double c)
+ : adc0804_device(mconfig, tag, owner, 0U)
+ {
+ set_rc(r, c);
+ }
+
+ // callback configuration
+ auto vin_callback() { return m_vin_callback.bind(); }
+ auto intr_callback() { return m_intr_callback.bind(); }
+
+ // misc. configuration
+ void set_rc(double res, double cap) { assert(!configured()); m_res = res; m_cap = cap; }
+ void set_rd_mode(read_mode mode) { assert(!configured()); m_rd_mode = mode; }
+
+ // data bus interface
+ u8 read();
+ u8 read_and_write();
+ void write(u8 data = 0);
+
+ // control line interface
+ DECLARE_WRITE_LINE_MEMBER(rd_w);
+ DECLARE_WRITE_LINE_MEMBER(wr_w);
+
+ // status line interface
+ DECLARE_READ_LINE_MEMBER(intr_r) { return m_intr_active ? 0 : 1; }
+
+protected:
+ // device-level overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+private:
+ // internal helpers
+ void set_interrupt(bool state);
+ void conversion_start();
+ TIMER_CALLBACK_MEMBER(conversion_done);
+
+ // callback objects
+ devcb_read8 m_vin_callback;
+ devcb_write_line m_intr_callback;
+
+ // timing parameters
+ double m_res;
+ double m_cap;
+ attotime m_fclk_rc;
+
+ // conversion timer
+ emu_timer *m_timer;
+
+ // inputs
+ read_mode m_rd_mode;
+ bool m_rd_active;
+ bool m_wr_active;
+
+ // internal state
+ u8 m_result;
+ bool m_intr_active;
+};
+
+// device type declarations
+DECLARE_DEVICE_TYPE(ADC0804, adc0804_device)
+
+#endif // MAME_MACHINE_ADC0804_H
diff --git a/src/mame/drivers/polepos.cpp b/src/mame/drivers/polepos.cpp
index df70e540201..75c1f7ec103 100644
--- a/src/mame/drivers/polepos.cpp
+++ b/src/mame/drivers/polepos.cpp
@@ -272,7 +272,7 @@ READ16_MEMBER(polepos_state::polepos2_ic25_r)
}
-READ8_MEMBER(polepos_state::adc_r)
+uint8_t polepos_state::analog_r()
{
return ioport(m_adc_input ? "ACCEL" : "BRAKE")->read();
}
@@ -284,7 +284,8 @@ READ8_MEMBER(polepos_state::ready_r)
if (m_screen->vpos() >= 128)
ret ^= 0x02;
- ret ^= 0x08; /* ADC End Flag */
+ if (!m_adc->intr_r())
+ ret ^= 0x08; /* ADC End Flag */
return ret;
}
@@ -440,7 +441,7 @@ void polepos_state::z80_map(address_map &map)
void polepos_state::z80_io(address_map &map)
{
map.global_mask(0xff);
- map(0x00, 0x00).r(FUNC(polepos_state::adc_r)).nopw();
+ map(0x00, 0x00).rw(m_adc, FUNC(adc0804_device::read), FUNC(adc0804_device::write));
}
@@ -914,6 +915,9 @@ void polepos_state::polepos(machine_config &config)
m_latch->q_out_cb<6>().set(FUNC(polepos_state::sb0_w));
m_latch->q_out_cb<7>().set(FUNC(polepos_state::chacl_w));
+ ADC0804(config, m_adc, MASTER_CLOCK/8/8);
+ m_adc->vin_callback().set(FUNC(polepos_state::analog_r));
+
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(MASTER_CLOCK/4, 384, 0, 256, 264, 16, 224+16);
@@ -1020,6 +1024,9 @@ void polepos_state::topracern(machine_config &config)
m_latch->q_out_cb<6>().set(FUNC(polepos_state::sb0_w));
m_latch->q_out_cb<7>().set(FUNC(polepos_state::chacl_w));
+ ADC0804(config, m_adc, MASTER_CLOCK/8/8);
+ m_adc->vin_callback().set(FUNC(polepos_state::analog_r));
+
/* video hardware */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(MASTER_CLOCK/4, 384, 0, 256, 264, 16, 224+16);
diff --git a/src/mame/drivers/segae.cpp b/src/mame/drivers/segae.cpp
index debd5e4319e..0e319bd175a 100644
--- a/src/mame/drivers/segae.cpp
+++ b/src/mame/drivers/segae.cpp
@@ -304,8 +304,10 @@ GND 8A 8B GND
#include "includes/segaipt.h"
#include "cpu/z80/z80.h"
+#include "machine/adc0804.h"
#include "machine/i8255.h"
#include "machine/mc8123.h"
+#include "machine/rescap.h"
#include "machine/segacrp2_device.h"
#include "machine/upd4701.h"
#include "video/315_5124.h"
@@ -326,6 +328,7 @@ public:
m_bank1(*this, "bank1"),
m_bank0d(*this, "bank0d"),
m_bank1d(*this, "bank1d"),
+ m_analog_ports(*this, "IN%u", 2U),
m_lamp(*this, "lamp0")
{ }
@@ -340,11 +343,11 @@ public:
void init_fantzn2();
private:
- DECLARE_WRITE8_MEMBER(bank_write);
- DECLARE_WRITE8_MEMBER(coin_counters_write);
+ void bank_write(uint8_t data);
+ void coin_counters_write(uint8_t data);
- DECLARE_READ8_MEMBER( hangonjr_port_f8_read );
- DECLARE_WRITE8_MEMBER( hangonjr_port_fa_write );
+ uint8_t hangonjr_analog_read();
+ void hangonjr_analog_select(uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
@@ -369,6 +372,7 @@ private:
required_memory_bank m_bank1;
optional_memory_bank m_bank0d;
optional_memory_bank m_bank1d;
+ optional_ioport_array<2> m_analog_ports;
output_finder<> m_lamp;
// Analog input related
@@ -440,7 +444,7 @@ void systeme_state::vdp2_map(address_map &map)
}
-WRITE8_MEMBER(systeme_state::bank_write)
+void systeme_state::bank_write(uint8_t data)
{
membank("vdp1_bank")->set_entry((data >> 7) & 1);
membank("vdp2_bank")->set_entry((data >> 6) & 1);
@@ -450,7 +454,7 @@ WRITE8_MEMBER(systeme_state::bank_write)
m_bank1d->set_entry(data & 0x0f);
}
-WRITE8_MEMBER(systeme_state::coin_counters_write)
+void systeme_state::coin_counters_write(uint8_t data)
{
machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
machine().bookkeeping().coin_counter_w(1, BIT(data, 1)); // only one counter used in most games?
@@ -487,25 +491,14 @@ void systeme_state::machine_start()
/*- Hang On Jr. Specific -*/
-READ8_MEMBER( systeme_state::hangonjr_port_f8_read )
+uint8_t systeme_state::hangonjr_analog_read()
{
- uint8_t temp;
-
- temp = 0;
-
- if (m_port_select == 0x08) /* 0000 1000 */ /* Angle */
- temp = ioport("IN2")->read();
-
- if (m_port_select == 0x09) /* 0000 1001 */ /* Accel */
- temp = ioport("IN3")->read();
-
- return temp;
+ return m_analog_ports[m_port_select & 0x01]->read();
}
-WRITE8_MEMBER( systeme_state::hangonjr_port_fa_write)
+void systeme_state::hangonjr_analog_select(uint8_t data)
{
- /* Seems to write the same pattern again and again bits ---- xx-x used */
- m_port_select = data & 0x0f;
+ m_port_select = data;
}
@@ -654,10 +647,10 @@ static INPUT_PORTS_START( segae_hangonjr_generic )
//PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
//PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_START("IN2") /* Read from Port 0xf8 */
+ PORT_START("IN2") /* Angle - Read from Port 0xf8 */
PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_MINMAX(0x20,0xe0) PORT_SENSITIVITY(100) PORT_KEYDELTA(4)
- PORT_START("IN3") /* Read from Port 0xf8 */
+ PORT_START("IN3") /* Accel - Read from Port 0xf8 */
PORT_BIT( 0xff, 0x00, IPT_PEDAL ) PORT_MINMAX(0x00,0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(20)
INPUT_PORTS_END
@@ -920,9 +913,15 @@ void systeme_state::systeme(machine_config &config)
void systeme_state::hangonjr(machine_config &config)
{
systeme(config);
- m_ppi->in_pa_callback().set(FUNC(systeme_state::hangonjr_port_f8_read));
- m_ppi->in_pc_callback().set_constant(0); // bit 4 must be the ADC0804 /INTR signal
- m_ppi->out_pc_callback().set(FUNC(systeme_state::hangonjr_port_fa_write)); // CD4051 selector input
+ m_ppi->in_pa_callback().set("adc", FUNC(adc0804_device::read));
+ m_ppi->in_pc_callback().set("adc", FUNC(adc0804_device::intr_r)).lshift(4);
+ m_ppi->out_pc_callback().set(FUNC(systeme_state::hangonjr_analog_select)); // CD4051 selector input
+ m_ppi->out_pc_callback().append("adc", FUNC(adc0804_device::rd_w)).bit(2);
+ m_ppi->out_pc_callback().append("adc", FUNC(adc0804_device::wr_w)).bit(3);
+
+ adc0804_device &adc(ADC0804(config, "adc", RES_K(10), CAP_P(82))); // R1=10K/C11=82pF circuit on 834-5805 card
+ adc.vin_callback().set(FUNC(systeme_state::hangonjr_analog_read));
+ adc.set_rd_mode(adc0804_device::RD_BITBANGED);
}
void systeme_state::ridleofp(machine_config &config)
diff --git a/src/mame/drivers/segahang.cpp b/src/mame/drivers/segahang.cpp
index 744746acf63..d6a030d7154 100644
--- a/src/mame/drivers/segahang.cpp
+++ b/src/mame/drivers/segahang.cpp
@@ -149,7 +149,7 @@ READ8_MEMBER( segahang_state::adc_status_r )
// D5 = 0 (left open)
// D4 = 0 (left open)
//
- return 0x00;
+ return m_adc->intr_r() << 6;
}
@@ -179,7 +179,7 @@ READ16_MEMBER( segahang_state::hangon_io_r )
return m_i8255_2->read(offset & 3);
case 0x3020/2: // ADC0804 data output
- return m_adc_ports[m_adc_select].read_safe(0);
+ return m_adc->read();
}
//logerror("%06X:hangon_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2);
@@ -207,6 +207,7 @@ WRITE16_MEMBER( segahang_state::hangon_io_w )
return;
case 0x3020/2: // ADC0804
+ m_adc->write();
return;
}
@@ -237,7 +238,7 @@ READ16_MEMBER( segahang_state::sharrier_io_r )
return m_i8255_2->read(offset & 3);
case 0x0030/2: // ADC0804 data output
- return m_adc_ports[m_adc_select].read_safe(0);
+ return m_adc->read();
}
//logerror("%06X:sharrier_io_r - unknown read access to address %04X\n", m_maincpu->pc(), offset * 2);
@@ -266,6 +267,7 @@ WRITE16_MEMBER( segahang_state::sharrier_io_w )
return;
case 0x0030/2: // ADC0804
+ m_adc->write();
return;
}
@@ -273,6 +275,16 @@ WRITE16_MEMBER( segahang_state::sharrier_io_w )
}
+//-------------------------------------------------
+// analog_r - read multiplexed analog ports
+//-------------------------------------------------
+
+uint8_t segahang_state::analog_r()
+{
+ return m_adc_ports[m_adc_select].read_safe(0);
+}
+
+
#if 0
TIMER_DEVICE_CALLBACK_MEMBER(segahang_state::hangon_irq)
{
@@ -778,6 +790,9 @@ void segahang_state::shared_base(machine_config &config)
m_i8255_2->out_pa_callback().set(FUNC(segahang_state::sub_control_adc_w));
m_i8255_2->in_pc_callback().set(FUNC(segahang_state::adc_status_r));
+ ADC0804(config, m_adc, MASTER_CLOCK_25MHz/4/6);
+ m_adc->vin_callback().set(FUNC(segahang_state::analog_r));
+
SEGAIC16VID(config, m_segaic16vid, 0, "gfxdecode");
SEGAIC16_ROAD(config, m_segaic16road, 0);
diff --git a/src/mame/drivers/segaorun.cpp b/src/mame/drivers/segaorun.cpp
index e108111ee1c..2ce4221a57f 100644
--- a/src/mame/drivers/segaorun.cpp
+++ b/src/mame/drivers/segaorun.cpp
@@ -303,7 +303,7 @@ const auto MASTER_CLOCK_25MHz = XTAL(25'174'800);
READ8_MEMBER( segaorun_state::unknown_porta_r )
{
//logerror("%06X:read from 8255 port A\n", m_maincpu->pc());
- return 0;
+ return m_adc->intr_r() << 6;
}
READ8_MEMBER( segaorun_state::unknown_portb_r )
@@ -366,6 +366,7 @@ READ8_MEMBER( segaorun_state::bankmotor_limit_r )
uint8_t ret = 0xff;
// PPI Input port A:
+ // D6: ADC interrupt
// D5: left limit
// D4: center
// D3: right limit
@@ -385,6 +386,9 @@ READ8_MEMBER( segaorun_state::bankmotor_limit_r )
else if (pos >= right_limit - tolerance)
ret ^= 0x08;
+ if (!m_adc->intr_r())
+ ret ^= 0x40;
+
return ret;
}
@@ -650,9 +654,7 @@ READ16_MEMBER( segaorun_state::outrun_custom_io_r )
}
case 0x30/2:
- {
- return m_adc_ports[m_adc_select].read_safe(0x0010);
- }
+ return m_adc->read();
case 0x60/2:
return m_watchdog->reset_r(space);
@@ -698,7 +700,7 @@ WRITE16_MEMBER( segaorun_state::outrun_custom_io_w )
return;
case 0x30/2:
- // ADC trigger
+ m_adc->write();
return;
case 0x60/2:
@@ -736,9 +738,7 @@ READ16_MEMBER( segaorun_state::shangon_custom_io_r )
}
case 0x3020/2:
- {
- return m_adc_ports[m_adc_select].read_safe(0x0010);
- }
+ return m_adc->read();
default:
break;
@@ -789,7 +789,7 @@ WRITE16_MEMBER( segaorun_state::shangon_custom_io_w )
return;
case 0x3020/2:
- // ADC trigger
+ m_adc->write();
return;
default:
@@ -800,6 +800,16 @@ WRITE16_MEMBER( segaorun_state::shangon_custom_io_w )
}
+//-------------------------------------------------
+// analog_r - read multiplexed analog ports
+//-------------------------------------------------
+
+uint8_t segaorun_state::analog_r()
+{
+ return m_adc_ports[m_adc_select].read_safe(0x10);
+}
+
+
//**************************************************************************
// INTERNAL HELPERS
@@ -1169,6 +1179,9 @@ void segaorun_state::outrun_base(machine_config &config)
m_i8255->in_pc_callback().set(FUNC(segaorun_state::unknown_portc_r));
m_i8255->out_pc_callback().set(FUNC(segaorun_state::video_control_w));
+ ADC0804(config, m_adc, MASTER_CLOCK_25MHz/4/6);
+ m_adc->vin_callback().set(FUNC(segaorun_state::analog_r));
+
SEGA_315_5195_MEM_MAPPER(config, m_mapper, MASTER_CLOCK/4, m_maincpu);
m_mapper->set_mapper(FUNC(segaorun_state::memory_mapper), this);
m_mapper->pbf().set_inputline(m_soundcpu, INPUT_LINE_NMI);
diff --git a/src/mame/drivers/segaxbd.cpp b/src/mame/drivers/segaxbd.cpp
index 31068b0b3e4..e03ebf82bc9 100644
--- a/src/mame/drivers/segaxbd.cpp
+++ b/src/mame/drivers/segaxbd.cpp
@@ -269,6 +269,7 @@ ROMs:
#include "includes/segaxbd.h"
#include "includes/segaipt.h"
+#include "machine/adc0804.h"
#include "machine/nvram.h"
#include "sound/ym2151.h"
#include "sound/segapcm.h"
@@ -469,14 +470,14 @@ WRITE_LINE_MEMBER(segaxbd_state::timer_irq_w)
//**************************************************************************
//-------------------------------------------------
-// adc_w - handle reads from the ADC
+// analog_r - provide input to the ADC
//-------------------------------------------------
-READ16_MEMBER( segaxbd_state::adc_r )
+uint8_t segaxbd_state::analog_r()
{
// on the write, latch the selected input port and stash the value
int which = (m_pc_0 >> 2) & 7;
- int value = m_adc_ports[which].read_safe(0x0010);
+ uint8_t value = m_adc_ports[which].read_safe(0x10);
// reverse some port values
if (m_adc_reverse[which])
@@ -488,15 +489,6 @@ READ16_MEMBER( segaxbd_state::adc_r )
//-------------------------------------------------
-// adc_w - handle writes to the ADC
-//-------------------------------------------------
-
-WRITE16_MEMBER( segaxbd_state::adc_w )
-{
-}
-
-
-//-------------------------------------------------
// pc_0_w - handle writes to port C on the first
// I/O chip
//-------------------------------------------------
@@ -941,7 +933,7 @@ void segaxbd_state::main_map(address_map &map)
map(0x100000, 0x100fff).mirror(0x00f000).ram().share("sprites");
map(0x110000, 0x11ffff).w("sprites", FUNC(sega_xboard_sprite_device::draw_write));
map(0x120000, 0x123fff).mirror(0x00c000).ram().w(FUNC(segaxbd_state::paletteram_w)).share("paletteram");
- map(0x130000, 0x13ffff).rw(FUNC(segaxbd_state::adc_r), FUNC(segaxbd_state::adc_w));
+ map(0x130001, 0x130001).mirror(0x00fffe).rw("adc", FUNC(adc0804_device::read), FUNC(adc0804_device::write));
map(0x140000, 0x14000f).mirror(0x00fff0).rw(m_iochip[0], FUNC(cxd1095_device::read), FUNC(cxd1095_device::write)).umask16(0x00ff);
map(0x150000, 0x15000f).mirror(0x00fff0).rw(m_iochip[1], FUNC(cxd1095_device::read), FUNC(cxd1095_device::write)).umask16(0x00ff);
map(0x160000, 0x16ffff).w(FUNC(segaxbd_state::iocontrol_w));
@@ -1103,7 +1095,7 @@ void segaxbd_rascot_state::comm_map(address_map &map)
static INPUT_PORTS_START( xboard_generic )
PORT_START("mainpcb:IO0PORTA")
PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNKNOWN ) // D5-D0: CN C pin 24-19 (switch state 0= open, 1= closed)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) // D6: /INTR of ADC0804
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("mainpcb:adc", adc0804_device, intr_r)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // D7: (Not connected)
// I/O port: CN C pins 17,15,13,11,9,7,5,3
@@ -1540,7 +1532,7 @@ INPUT_PORTS_END
static INPUT_PORTS_START( gprider )
PORT_START("mainpcb:IO0PORTA")
PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) // /INTR of ADC0804
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("mainpcb:adc", adc0804_device, intr_r)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("mainpcb:IO0PORTB")
@@ -1597,7 +1589,7 @@ static INPUT_PORTS_START( gprider_double )
PORT_START("subpcb:IO0PORTA")
PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNKNOWN )
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) // /INTR of ADC0804
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("subpcb:adc", adc0804_device, intr_r)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("subpcb:IO0PORTB")
@@ -1702,18 +1694,21 @@ void segaxbd_state::xboard_base_mconfig(machine_config &config)
SEGA_315_5250_COMPARE_TIMER(config, "cmptimer_subx", 0);
- CXD1095(config, m_iochip[0], 0); // IC160
+ CXD1095(config, m_iochip[0]); // IC160
m_iochip[0]->in_porta_cb().set_ioport("IO0PORTA");
m_iochip[0]->in_portb_cb().set_ioport("IO0PORTB");
m_iochip[0]->out_portc_cb().set(FUNC(segaxbd_state::pc_0_w));
m_iochip[0]->out_portd_cb().set(FUNC(segaxbd_state::pd_0_w));
- CXD1095(config, m_iochip[1], 0); // IC159
+ CXD1095(config, m_iochip[1]); // IC159
m_iochip[1]->in_porta_cb().set_ioport("IO1PORTA");
m_iochip[1]->in_portb_cb().set_ioport("IO1PORTB");
m_iochip[1]->in_portc_cb().set_ioport("IO1PORTC");
m_iochip[1]->in_portd_cb().set_ioport("IO1PORTD");
+ adc0804_device &adc(ADC0804(config, "adc", MASTER_CLOCK/4/10)); // uses E clock from main CPU
+ adc.vin_callback().set(FUNC(segaxbd_state::analog_r));
+
// video hardware
GFXDECODE(config, "gfxdecode", m_palette, gfx_segaxbd);
PALETTE(config, m_palette).set_entries(8192*2);
diff --git a/src/mame/drivers/wallc.cpp b/src/mame/drivers/wallc.cpp
index 2e2f738e2e0..88fbf57ed72 100644
--- a/src/mame/drivers/wallc.cpp
+++ b/src/mame/drivers/wallc.cpp
@@ -51,6 +51,7 @@ Thanks to HIGHWAYMAN for providing info on how to get to these epoxies
#include "emu.h"
#include "cpu/z80/z80.h"
+#include "machine/adc0804.h"
#include "sound/ay8910.h"
#include "video/resnet.h"
#include "emupal.h"
@@ -294,14 +295,13 @@ void wallc_state::wallc_map(address_map &map)
map(0xb000, 0xb000).portr("DSW1");
map(0xb200, 0xb200).portr("SYSTEM");
- map(0xb400, 0xb400).portr("DIAL");
- map(0xb600, 0xb600).portr("DSW2");
+ map(0xb400, 0xb400).r("adc", FUNC(adc0804_device::read_and_write));
map(0xb000, 0xb000).nopw();
map(0xb100, 0xb100).w(FUNC(wallc_state::wallc_coin_counter_w));
map(0xb200, 0xb200).nopw();
map(0xb500, 0xb500).w("aysnd", FUNC(ay8912_device::address_w));
- map(0xb600, 0xb600).w("aysnd", FUNC(ay8912_device::data_w));
+ map(0xb600, 0xb600).rw("aysnd", FUNC(ay8912_device::data_r), FUNC(ay8912_device::data_w));
}
void wallc_state::unkitpkr_map(address_map &map)
@@ -522,6 +522,8 @@ void wallc_state::wallc(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &wallc_state::wallc_map);
m_maincpu->set_vblank_int("screen", FUNC(wallc_state::irq0_line_hold));
+ ADC0804(config, "adc", 640000).vin_callback().set_ioport("DIAL"); // clock not verified
+
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
@@ -536,7 +538,9 @@ void wallc_state::wallc(machine_config &config)
/* sound hardware */
SPEAKER(config, "mono").front_center();
- AY8912(config, "aysnd", 12288000 / 8).add_route(ALL_OUTPUTS, "mono", 0.30);
+ ay8912_device &aysnd(AY8912(config, "aysnd", 12288000 / 8));
+ aysnd.port_a_read_callback().set_ioport("DSW2");
+ aysnd.add_route(ALL_OUTPUTS, "mono", 0.30);
}
void wallc_state::wallca(machine_config &config)
@@ -548,6 +552,7 @@ void wallc_state::wallca(machine_config &config)
void wallc_state::unkitpkr(machine_config &config)
{
wallc(config);
+ config.device_remove("adc");
m_maincpu->set_addrmap(AS_PROGRAM, &wallc_state::unkitpkr_map);
@@ -555,7 +560,6 @@ void wallc_state::unkitpkr(machine_config &config)
subdevice<palette_device>("palette")->set_init(FUNC(wallc_state::unkitpkr_palette));
/* sound hardware */
- subdevice<ay8912_device>("aysnd")->port_a_read_callback().set_ioport("DSW2");
subdevice<ay8912_device>("aysnd")->reset_routes().add_route(ALL_OUTPUTS, "mono", 0.50);
}
diff --git a/src/mame/includes/polepos.h b/src/mame/includes/polepos.h
index af7dde9f267..644bcc19962 100644
--- a/src/mame/includes/polepos.h
+++ b/src/mame/includes/polepos.h
@@ -11,6 +11,7 @@
#pragma once
#include "machine/74259.h"
+#include "machine/adc0804.h"
#include "machine/gen_latch.h"
#include "machine/timer.h"
#include "sound/namco.h"
@@ -31,6 +32,7 @@ public:
m_soundlatch(*this, "soundlatch"),
m_namco_sound(*this, "namco"),
m_latch(*this, "latch"),
+ m_adc(*this, "adc"),
m_sprite16_memory(*this, "sprite16_memory"),
m_road16_memory(*this, "road16_memory"),
m_alpha16_memory(*this, "alpha16_memory"),
@@ -61,6 +63,7 @@ private:
optional_device<generic_latch_8_device> m_soundlatch;
optional_device<namco_device> m_namco_sound;
required_device<ls259_device> m_latch;
+ required_device<adc0804_device> m_adc;
required_shared_ptr<uint16_t> m_sprite16_memory;
required_shared_ptr<uint16_t> m_road16_memory;
required_shared_ptr<uint16_t> m_alpha16_memory;
@@ -87,7 +90,7 @@ private:
uint8_t m_sub_irq_mask;
DECLARE_READ16_MEMBER(polepos2_ic25_r);
- DECLARE_READ8_MEMBER(adc_r);
+ uint8_t analog_r();
DECLARE_READ8_MEMBER(ready_r);
DECLARE_WRITE_LINE_MEMBER(iosel_w);
DECLARE_WRITE_LINE_MEMBER(gasel_w);
diff --git a/src/mame/includes/segahang.h b/src/mame/includes/segahang.h
index 8c47ddccb1b..134e8dbec89 100644
--- a/src/mame/includes/segahang.h
+++ b/src/mame/includes/segahang.h
@@ -9,6 +9,7 @@
#include "cpu/m68000/m68000.h"
#include "cpu/mcs51/mcs51.h"
#include "cpu/z80/z80.h"
+#include "machine/adc0804.h"
#include "machine/i8255.h"
#include "machine/gen_latch.h"
#include "machine/segaic16.h"
@@ -31,6 +32,7 @@ public:
, m_mcu(*this, "mcu")
, m_i8255_1(*this, "i8255_1")
, m_i8255_2(*this, "i8255_2")
+ , m_adc(*this, "adc")
, m_sprites(*this, "sprites")
, m_segaic16vid(*this, "segaic16vid")
, m_segaic16road(*this, "segaic16road")
@@ -38,7 +40,7 @@ public:
, m_workram(*this, "workram")
, m_sharrier_video(false)
, m_adc_select(0)
- , m_adc_ports(*this, {"ADC0", "ADC1", "ADC2", "ADC3"})
+ , m_adc_ports(*this, "ADC%u", 0U)
, m_decrypted_opcodes(*this, "decrypted_opcodes")
, m_lamps(*this, "lamp%u", 0U)
{ }
@@ -82,6 +84,9 @@ private:
DECLARE_READ16_MEMBER( sharrier_io_r );
DECLARE_WRITE16_MEMBER( sharrier_io_w );
+ // ADC0804 read handler
+ uint8_t analog_r();
+
// Z80 sound CPU read/write handlers
DECLARE_READ8_MEMBER( sound_data_r );
@@ -129,6 +134,7 @@ private:
optional_device<i8751_device> m_mcu;
required_device<i8255_device> m_i8255_1;
required_device<i8255_device> m_i8255_2;
+ required_device<adc0804_device> m_adc;
required_device<sega_16bit_sprite_device> m_sprites;
required_device<segaic16_video_device> m_segaic16vid;
required_device<segaic16_road_device> m_segaic16road;
diff --git a/src/mame/includes/segaorun.h b/src/mame/includes/segaorun.h
index 03d21d99cc0..d2cc1c9146e 100644
--- a/src/mame/includes/segaorun.h
+++ b/src/mame/includes/segaorun.h
@@ -8,6 +8,7 @@
#include "cpu/m68000/m68000.h"
#include "cpu/z80/z80.h"
+#include "machine/adc0804.h"
#include "machine/i8255.h"
#include "machine/nvram.h"
#include "machine/segaic16.h"
@@ -31,6 +32,7 @@ public:
m_subcpu(*this, "subcpu"),
m_soundcpu(*this, "soundcpu"),
m_i8255(*this, "i8255"),
+ m_adc(*this, "adc"),
m_nvram(*this, "nvram"),
m_watchdog(*this, "watchdog"),
m_sprites(*this, "sprites"),
@@ -124,6 +126,7 @@ protected:
DECLARE_WRITE16_MEMBER( outrun_custom_io_w );
DECLARE_READ16_MEMBER( shangon_custom_io_r );
DECLARE_WRITE16_MEMBER( shangon_custom_io_w );
+ uint8_t analog_r();
// devices
required_device<sega_315_5195_mapper_device> m_mapper;
@@ -131,6 +134,7 @@ protected:
required_device<m68000_device> m_subcpu;
required_device<z80_device> m_soundcpu;
required_device<i8255_device> m_i8255;
+ required_device<adc0804_device> m_adc;
optional_device<nvram_device> m_nvram;
required_device<watchdog_timer_device> m_watchdog;
required_device<sega_16bit_sprite_device> m_sprites;
diff --git a/src/mame/includes/segaxbd.h b/src/mame/includes/segaxbd.h
index 1209b9f025a..b93f9be1a57 100644
--- a/src/mame/includes/segaxbd.h
+++ b/src/mame/includes/segaxbd.h
@@ -60,8 +60,7 @@ public:
protected:
// main CPU read/write handlers
- DECLARE_READ16_MEMBER(adc_r);
- DECLARE_WRITE16_MEMBER(adc_w);
+ uint8_t analog_r();
DECLARE_WRITE16_MEMBER(iocontrol_w);
// video updates