diff options
author | 2019-10-16 00:16:14 -0400 | |
---|---|---|
committer | 2019-10-16 00:16:14 -0400 | |
commit | f398123bc3ce7d20074da016f5703aa92c055db9 (patch) | |
tree | d4b1998e7c9c59d6f6018d32ac9a2c0bccb79131 | |
parent | 3e6734da05c8867b625a3b23126a91d71de301fe (diff) |
Emulate ADC0804 and add device to various drivers
-rw-r--r-- | scripts/src/machine.lua | 12 | ||||
-rw-r--r-- | scripts/target/mame/arcade.lua | 1 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/machine/adc0804.cpp | 256 | ||||
-rw-r--r-- | src/devices/machine/adc0804.h | 108 | ||||
-rw-r--r-- | src/mame/drivers/polepos.cpp | 13 | ||||
-rw-r--r-- | src/mame/drivers/segae.cpp | 51 | ||||
-rw-r--r-- | src/mame/drivers/segahang.cpp | 21 | ||||
-rw-r--r-- | src/mame/drivers/segaorun.cpp | 31 | ||||
-rw-r--r-- | src/mame/drivers/segaxbd.cpp | 31 | ||||
-rw-r--r-- | src/mame/drivers/wallc.cpp | 14 | ||||
-rw-r--r-- | src/mame/includes/polepos.h | 5 | ||||
-rw-r--r-- | src/mame/includes/segahang.h | 8 | ||||
-rw-r--r-- | src/mame/includes/segaorun.h | 4 | ||||
-rw-r--r-- | src/mame/includes/segaxbd.h | 3 |
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 |