From a5a8e0cbdb29b256d08497ea122b40eff241d471 Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Mon, 20 Nov 2017 01:37:08 +0100 Subject: einstein: Improve interrupts, add WIP Speculator support Also removes a bogus character in the initial centronics output. --- scripts/src/bus.lua | 2 + src/devices/bus/einstein/pipe/pipe.cpp | 15 ++ src/devices/bus/einstein/pipe/pipe.h | 6 + src/devices/bus/einstein/pipe/speculator.cpp | 206 +++++++++++++++++++++++++++ src/devices/bus/einstein/pipe/speculator.h | 66 +++++++++ src/mame/drivers/einstein.cpp | 45 +++++- 6 files changed, 336 insertions(+), 4 deletions(-) create mode 100644 src/devices/bus/einstein/pipe/speculator.cpp create mode 100644 src/devices/bus/einstein/pipe/speculator.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index a0cadb5e4cd..4c329ee49a3 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3300,6 +3300,8 @@ if (BUSES["TATUNG_PIPE"]~=null) then MAME_DIR .. "src/devices/bus/einstein/pipe/pipe.h", MAME_DIR .. "src/devices/bus/einstein/pipe/silicon_disc.cpp", MAME_DIR .. "src/devices/bus/einstein/pipe/silicon_disc.h", + MAME_DIR .. "src/devices/bus/einstein/pipe/speculator.cpp", + MAME_DIR .. "src/devices/bus/einstein/pipe/speculator.h", MAME_DIR .. "src/devices/bus/einstein/pipe/tk02.cpp", MAME_DIR .. "src/devices/bus/einstein/pipe/tk02.h", } diff --git a/src/devices/bus/einstein/pipe/pipe.cpp b/src/devices/bus/einstein/pipe/pipe.cpp index 106dbe0f8ec..51169544ba7 100644 --- a/src/devices/bus/einstein/pipe/pipe.cpp +++ b/src/devices/bus/einstein/pipe/pipe.cpp @@ -11,6 +11,7 @@ // supported devices #include "silicon_disc.h" +#include "speculator.h" #include "tk02.h" @@ -55,6 +56,9 @@ tatung_pipe_device::~tatung_pipe_device() void tatung_pipe_device::device_start() { + // get inserted module + m_card = dynamic_cast(get_card_device()); + // resolve callbacks m_int_handler.resolve_safe(); m_nmi_handler.resolve_safe(); @@ -69,6 +73,16 @@ void tatung_pipe_device::device_reset() { } +//------------------------------------------------- +// host to module interface +//------------------------------------------------- + +WRITE_LINE_MEMBER( tatung_pipe_device::host_int_w ) +{ + if (m_card) + m_card->int_w(state); +} + //------------------------------------------------- // set_program_space - set address space we are attached to //------------------------------------------------- @@ -117,5 +131,6 @@ device_tatung_pipe_interface::~device_tatung_pipe_interface() SLOT_INTERFACE_START( tatung_pipe_cards ) SLOT_INTERFACE("silicon_disc", EINSTEIN_SILICON_DISC) + SLOT_INTERFACE("speculator", EINSTEIN_SPECULATOR) SLOT_INTERFACE("tk02", TK02_80COL) SLOT_INTERFACE_END diff --git a/src/devices/bus/einstein/pipe/pipe.h b/src/devices/bus/einstein/pipe/pipe.h index 759103595c6..02be494cb2e 100644 --- a/src/devices/bus/einstein/pipe/pipe.h +++ b/src/devices/bus/einstein/pipe/pipe.h @@ -90,6 +90,9 @@ public: template static devcb_base &set_reset_handler(device_t &device, Object &&cb) { return downcast(device).m_reset_handler.set_callback(std::forward(cb)); } + // called from host + DECLARE_WRITE_LINE_MEMBER( host_int_w ); + // called from card device DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); } DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); } @@ -119,6 +122,9 @@ public: device_tatung_pipe_interface(const machine_config &mconfig, device_t &device); virtual ~device_tatung_pipe_interface(); + // host to card + virtual void int_w(int state) { } + protected: address_space &program_space() { return *m_slot->m_program; } address_space &io_space() { return *m_slot->m_io; } diff --git a/src/devices/bus/einstein/pipe/speculator.cpp b/src/devices/bus/einstein/pipe/speculator.cpp new file mode 100644 index 00000000000..51918b018ca --- /dev/null +++ b/src/devices/bus/einstein/pipe/speculator.cpp @@ -0,0 +1,206 @@ +// license: GPL-2.0+ +// copyright-holders: Dirk Best +/*************************************************************************** + + Speculator + + TODO: Not working, based on the schematics of the Memotech MTX version + +***************************************************************************/ + +#include "emu.h" +#include "speculator.h" +#include "machine/rescap.h" +#include "sound/wave.h" +#include "formats/tzx_cas.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(EINSTEIN_SPECULATOR, einstein_speculator_device, "einstein_speculator", "Einstein Speculator") + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +MACHINE_CONFIG_MEMBER( einstein_speculator_device::device_add_mconfig ) + MCFG_DEVICE_ADD("ic5a", TTL74123, 0) + MCFG_TTL74123_CONNECTION_TYPE(TTL74123_NOT_GROUNDED_NO_DIODE) + MCFG_TTL74123_RESISTOR_VALUE(RES_K(47)) + MCFG_TTL74123_CAPACITOR_VALUE(CAP_P(560)) + MCFG_TTL74123_A_PIN_VALUE(1) + MCFG_TTL74123_B_PIN_VALUE(1) + MCFG_TTL74123_CLEAR_PIN_VALUE(0) + MCFG_TTL74123_OUTPUT_CHANGED_CB(WRITELINE(einstein_speculator_device, ic5a_q_w)) + + MCFG_DEVICE_ADD("ic5b", TTL74123, 0) + MCFG_TTL74123_CONNECTION_TYPE(TTL74123_NOT_GROUNDED_NO_DIODE) + MCFG_TTL74123_RESISTOR_VALUE(RES_K(47)) + MCFG_TTL74123_CAPACITOR_VALUE(CAP_P(560)) + MCFG_TTL74123_A_PIN_VALUE(1) + MCFG_TTL74123_B_PIN_VALUE(1) + MCFG_TTL74123_CLEAR_PIN_VALUE(0) + MCFG_TTL74123_OUTPUT_CHANGED_CB(WRITELINE(einstein_speculator_device, ic5b_q_w)) + + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette") + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) + + MCFG_CASSETTE_ADD("cassette") + MCFG_CASSETTE_FORMATS(tzx_cassette_formats) + MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED) + MCFG_CASSETTE_INTERFACE("spectrum_cass") +MACHINE_CONFIG_END + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// einstein_speculator_device - constructor +//------------------------------------------------- + +einstein_speculator_device::einstein_speculator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, EINSTEIN_SPECULATOR, tag, owner, clock), + device_tatung_pipe_interface(mconfig, *this), + m_ic5a(*this, "ic5a"), m_ic5b(*this, "ic5b"), + m_cassette(*this, "cassette"), + m_speaker(*this, "speaker"), + m_nmisel(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void einstein_speculator_device::device_start() +{ + // setup ram + m_ram = std::make_unique(0x800); + memset(m_ram.get(), 0xff, 0x800); + + // register for save states + save_pointer(NAME(m_ram.get()), 0x800); + save_item(NAME(m_nmisel)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void einstein_speculator_device::device_reset() +{ + // ram: range 0x1f, 0x3f, 0x5f, 0x7f, 0x9f, 0xbf, 0xdf, 0xff + io_space().install_readwrite_handler(0x1f, 0x1f, 0, 0, 0xffe0, + read8_delegate(FUNC(einstein_speculator_device::ram_r), this), + write8_delegate(FUNC(einstein_speculator_device::ram_w), this)); + + // ram: range 0x60 - 0xff + io_space().install_readwrite_handler(0x60, 0x60, 0, 0, 0xff9f, + read8_delegate(FUNC(einstein_speculator_device::ram_r), this), + write8_delegate(FUNC(einstein_speculator_device::ram_w), this)); + + // tape read/nmi write register: range 0xff + io_space().install_readwrite_handler(0xff, 0xff, 0, 0, 0xff00, + read8_delegate(FUNC(einstein_speculator_device::tape_r), this), + write8_delegate(FUNC(einstein_speculator_device::nmi_w), this)); +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +WRITE_LINE_MEMBER( einstein_speculator_device::ic5a_q_w ) +{ + m_ic5b->a_w(state); + + if (m_nmisel == 1) + { + logerror("imm nmi: %d\n", state); + m_slot->nmi_w(state); + } +} + +WRITE_LINE_MEMBER( einstein_speculator_device::ic5b_q_w ) +{ + if (m_nmisel == 0) + { + logerror("del nmi: %d\n", state); + m_slot->nmi_w(state); + } +} + +void einstein_speculator_device::int_w(int state) +{ + logerror("int_w: %d\n", state); + m_ic5a->a_w(!state); +} + +// pal ic4 +offs_t einstein_speculator_device::address_translate(offs_t offset) +{ + int ra3, ra2, ra1, ra0; + + ra3 = !BIT(offset, 7) && BIT(offset, 0); + + ra2 = BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 13) && BIT(offset, 12) && !BIT(offset, 11); + ra2 |= BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 13) && BIT(offset, 12) && !BIT(offset, 10); + ra2 |= BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 13) && BIT(offset, 12) && !BIT(offset, 9); + ra2 |= BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 13) && BIT(offset, 12) && !BIT(offset, 8); + + ra1 = BIT(offset, 15) && BIT(offset, 14) && !BIT(offset, 13); + ra1 |= BIT(offset, 15) && BIT(offset, 14) && !BIT(offset, 12); + ra1 |= BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 11) && BIT(offset, 10) && !BIT(offset, 9); + ra1 |= BIT(offset, 15) && BIT(offset, 14) && BIT(offset, 11) && BIT(offset, 10) && !BIT(offset, 8); + + ra0 = BIT(offset, 15) && !BIT(offset, 14); + ra0 |= BIT(offset, 15) && BIT(offset, 13) && !BIT(offset, 12); + ra0 |= BIT(offset, 15) && BIT(offset, 13) && BIT(offset, 11) && !BIT(offset, 10); + ra0 |= BIT(offset, 15) && BIT(offset, 13) && BIT(offset, 11) && BIT(offset, 9) && !BIT(offset, 8); + + return (ra3 << 3) | (ra2 << 2) | (ra1 << 1) | (ra0 << 0); +} + +READ8_MEMBER( einstein_speculator_device::ram_r ) +{ + offs_t addr = ((offset << 4) & 0x7f) | address_translate(offset); + return m_ram[addr]; +} + +WRITE8_MEMBER( einstein_speculator_device::ram_w ) +{ + offs_t addr = ((offset << 4) & 0x7f) | address_translate(offset); + m_ram[addr] = data; +} + +READ8_MEMBER( einstein_speculator_device::tape_r ) +{ + // 7654321- unknown + // -------0 cassette input + + return m_cassette->input() > 0.0038 ? 1 : 0; +} + +WRITE8_MEMBER( einstein_speculator_device::nmi_w ) +{ + logerror("nmi_w offset %04x data %02x\n", offset, data); + + // 76543--- unknown + // -----2-- nmi enable? + // ------1- nmi select? + // -------0 speaker? + + m_ic5a->clear_w(BIT(data, 2)); + m_ic5b->clear_w(BIT(data, 2)); + + m_nmisel = BIT(data, 1); + + m_speaker->level_w(BIT(data, 0)); +} diff --git a/src/devices/bus/einstein/pipe/speculator.h b/src/devices/bus/einstein/pipe/speculator.h new file mode 100644 index 00000000000..348187012c5 --- /dev/null +++ b/src/devices/bus/einstein/pipe/speculator.h @@ -0,0 +1,66 @@ +// license: GPL-2.0+ +// copyright-holders: Dirk Best +/*************************************************************************** + + Speculator + + A Spectrum emulator + +***************************************************************************/ + +#ifndef MAME_BUS_EINSTEIN_PIPE_SPECULATOR_H +#define MAME_BUS_EINSTEIN_PIPE_SPECULATOR_H + +#pragma once + +#include "pipe.h" +#include "machine/74123.h" +#include "imagedev/cassette.h" +#include "sound/spkrdev.h" +#include "speaker.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> einstein_speculator_device + +class einstein_speculator_device : public device_t, public device_tatung_pipe_interface +{ +public: + // construction/destruction + einstein_speculator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void int_w(int state) override; + + DECLARE_READ8_MEMBER(ram_r); + DECLARE_WRITE8_MEMBER(ram_w); + DECLARE_READ8_MEMBER(tape_r); + DECLARE_WRITE8_MEMBER(nmi_w); + + DECLARE_WRITE_LINE_MEMBER(ic5a_q_w); + DECLARE_WRITE_LINE_MEMBER(ic5b_q_w); + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + offs_t address_translate(offs_t offset); + + required_device m_ic5a; + required_device m_ic5b; + required_device m_cassette; + required_device m_speaker; + + std::unique_ptr m_ram; + + int m_nmisel; +}; + +// device type definition +DECLARE_DEVICE_TYPE(EINSTEIN_SPECULATOR, einstein_speculator_device) + +#endif // MAME_BUS_EINSTEIN_PIPE_SPECULATOR_H diff --git a/src/mame/drivers/einstein.cpp b/src/mame/drivers/einstein.cpp index f0f9421e9cd..a08d6c95498 100644 --- a/src/mame/drivers/einstein.cpp +++ b/src/mame/drivers/einstein.cpp @@ -83,7 +83,8 @@ public: m_buttons(*this, "BUTTONS"), m_rom_enabled(0), m_keyboard_line(0), m_keyboard_data(0xff), - m_centronics_busy(0), m_centronics_perror(0), m_centronics_fault(0) + m_centronics_busy(0), m_centronics_perror(0), m_centronics_fault(0), m_strobe(-1), + m_int(0) {} DECLARE_INPUT_CHANGED_MEMBER(joystick_button); @@ -94,6 +95,7 @@ public: DECLARE_WRITE8_MEMBER(reset_w); DECLARE_READ8_MEMBER(rom_r); DECLARE_WRITE8_MEMBER(rom_w); + template DECLARE_WRITE_LINE_MEMBER(int_w); DECLARE_READ8_MEMBER(kybint_msk_r); DECLARE_WRITE8_MEMBER(kybint_msk_w); DECLARE_WRITE8_MEMBER(adcint_msk_w); @@ -139,6 +141,9 @@ private: int m_centronics_busy; int m_centronics_perror; int m_centronics_fault; + int m_strobe; + + int m_int; }; @@ -245,11 +250,13 @@ WRITE_LINE_MEMBER( einstein_state::write_centronics_fault ) WRITE_LINE_MEMBER( einstein_state::ardy_w ) { - if (state) + if (m_strobe == 0 && state == 1) { m_centronics->write_strobe(1); m_strobe_timer->adjust(attotime::from_double(TIME_OF_74LS123(RES_K(10), CAP_N(1)))); } + + m_strobe = state; } TIMER_DEVICE_CALLBACK_MEMBER( einstein_state::strobe_callback ) @@ -272,6 +279,30 @@ static const z80_daisy_config einstein_daisy_chain[] = { nullptr } }; +template WRITE_LINE_MEMBER( einstein_state::int_w ) +{ + int old = m_int; + + if (state) + { + m_int |= (1 << source); + if (!old) + { + m_maincpu->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); + m_pipe->host_int_w(ASSERT_LINE); + } + } + else + { + m_int &= ~(1 << source); + if (old && !m_int) + { + m_maincpu->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); + m_pipe->host_int_w(CLEAR_LINE); + } + } +} + READ8_MEMBER( einstein_state::kybint_msk_r ) { uint8_t data = 0; @@ -370,6 +401,8 @@ void einstein_state::machine_reset() m_keyboard_daisy->mask_w(1); m_adc_daisy->mask_w(1); m_fire_daisy->mask_w(1); + + m_strobe = -1; } @@ -548,7 +581,7 @@ static MACHINE_CONFIG_START( einstein ) MCFG_TIMER_DRIVER_ADD_PERIODIC("keyboard", einstein_state, keyboard_timer_callback, attotime::from_hz(50)) MCFG_DEVICE_ADD(IC_I063, Z80PIO, XTAL_X002 / 2) - MCFG_Z80PIO_OUT_INT_CB(INPUTLINE(IC_I001, INPUT_LINE_IRQ0)) + MCFG_Z80PIO_OUT_INT_CB(WRITELINE(einstein_state, int_w<0>)) MCFG_Z80PIO_OUT_PA_CB(DEVWRITE8("cent_data_out", output_latch_device, write)) MCFG_Z80PIO_OUT_ARDY_CB(WRITELINE(einstein_state, ardy_w)) MCFG_Z80PIO_IN_PB_CB(DEVREAD8("user", einstein_userport_device, read)) @@ -556,7 +589,7 @@ static MACHINE_CONFIG_START( einstein ) MCFG_Z80PIO_OUT_BRDY_CB(DEVWRITELINE("user", einstein_userport_device, brdy_w)) MCFG_DEVICE_ADD(IC_I058, Z80CTC, XTAL_X002 / 2) - MCFG_Z80CTC_INTR_CB(INPUTLINE(IC_I001, INPUT_LINE_IRQ0)) + MCFG_Z80CTC_INTR_CB(WRITELINE(einstein_state, int_w<1>)) MCFG_Z80CTC_ZC0_CB(DEVWRITELINE(IC_I060, i8251_device, write_txc)) MCFG_Z80CTC_ZC1_CB(DEVWRITELINE(IC_I060, i8251_device, write_rxc)) MCFG_Z80CTC_ZC2_CB(DEVWRITELINE(IC_I058, z80ctc_device, trg3)) @@ -568,8 +601,11 @@ static MACHINE_CONFIG_START( einstein ) /* Einstein daisy chain support for non-Z80 devices */ MCFG_Z80DAISY_GENERIC_ADD("keyboard_daisy", 0xf7) + MCFG_Z80DAISY_GENERIC_INT_CB(WRITELINE(einstein_state, int_w<2>)) MCFG_Z80DAISY_GENERIC_ADD("adc_daisy", 0xfb) + MCFG_Z80DAISY_GENERIC_INT_CB(WRITELINE(einstein_state, int_w<3>)) MCFG_Z80DAISY_GENERIC_ADD("fire_daisy", 0xfd) + MCFG_Z80DAISY_GENERIC_INT_CB(WRITELINE(einstein_state, int_w<4>)) /* video hardware */ MCFG_DEVICE_ADD("vdp", TMS9129, XTAL_10_738635MHz / 2) @@ -633,6 +669,7 @@ static MACHINE_CONFIG_START( einstein ) // tatung pipe connector MCFG_TATUNG_PIPE_ADD("pipe") + MCFG_TATUNG_PIPE_NMI_HANDLER(INPUTLINE(IC_I001, INPUT_LINE_NMI)) // user port MCFG_EINSTEIN_USERPORT_ADD("user") -- cgit v1.2.3