From 8689ada5a3fc34f07d3d0971ef57f78c8097e1c6 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Wed, 5 Jun 2019 04:40:56 +0200 Subject: [PATCH] -am2910: Added prelminary, largely-untested Am2910 Microprogram Controller device emulation. [Ryan Holtz] -dpb7000: Initial pass at Disk Sequencer Card emulation. Needs debugging. [Ryan Holtz, Mark Nias] --- scripts/src/machine.lua | 12 ++ scripts/target/mame/arcade.lua | 1 + scripts/target/mame/mess.lua | 1 + src/devices/machine/am2910.cpp | 306 +++++++++++++++++++++++++++++++ src/devices/machine/am2910.h | 83 +++++++++ src/mame/drivers/dpb7000.cpp | 316 +++++++++++++++++++++++++++++++-- 6 files changed, 703 insertions(+), 16 deletions(-) create mode 100644 src/devices/machine/am2910.cpp create mode 100644 src/devices/machine/am2910.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 62433da41f2..a456bf31ef8 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -610,6 +610,18 @@ if (MACHINES["AM2847"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/am2910.h,MACHINES["AM2910"] = true +--------------------------------------------------- + +if (MACHINES["AM2910"]~=null) then + files { + MAME_DIR .. "src/devices/machine/am2910.cpp", + MAME_DIR .. "src/devices/machine/am2910.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/am53cf96.h,MACHINES["AM53CF96"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 6fd132e28e9..06605c1c415 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -408,6 +408,7 @@ MACHINES["ADC1038"] = true MACHINES["ADC1213X"] = true MACHINES["AICARTC"] = true --MACHINES["AM2847"] = true +--MACHINES["AM2910"] = true MACHINES["AM53CF96"] = true MACHINES["AM79C90"] = true --MACHINES["AM9513"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 78dd31a5065..cca71c28c8e 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -412,6 +412,7 @@ MACHINES["ADC1038"] = true MACHINES["ADC1213X"] = true MACHINES["AICARTC"] = true MACHINES["AM2847"] = true +MACHINES["AM2910"] = true MACHINES["AM53CF96"] = true MACHINES["AM79C90"] = true MACHINES["AM9513"] = true diff --git a/src/devices/machine/am2910.cpp b/src/devices/machine/am2910.cpp new file mode 100644 index 00000000000..f547d93f00b --- /dev/null +++ b/src/devices/machine/am2910.cpp @@ -0,0 +1,306 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + am2910.cpp + AMD Am2910 Microprogram Controller emulation + + TODO: + - Check /RLD behavior + - Find and fix bugs that almost surely exist + +***************************************************************************/ + +#include "emu.h" +#include "am2910.h" + +#define LOG_INSN (1 << 0) +#define LOG_STACK (1 << 1) +#define LOG_ERROR (1 << 2) +#define LOG_ALL (LOG_INSN | LOG_STACK | LOG_ERROR) + +#define VERBOSE (0) +#include "logmacro.h" + +/*****************************************************************************/ + +DEFINE_DEVICE_TYPE(AM2910, am2910_device, "am2910", "AMD Am2910 Microprogram Controller") + +//------------------------------------------------- +// am2910_device - constructor +//------------------------------------------------- + +am2910_device::am2910_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, AM2910, tag, owner, clock) + , m_pc(0) + , m_r(0) + , m_sp(0) + , m_cc(0) + , m_ccen(0) + , m_ci(0) + , m_rld(0) + , m_cp(0) + , m_y(*this) + , m_full(*this) + , m_pl(*this) + , m_map(*this) + , m_vect(*this) +{ +} + + +void am2910_device::device_start() +{ + save_item(NAME(m_pc)); + save_item(NAME(m_r)); + save_item(NAME(m_sp)); + save_item(NAME(m_stack)); + save_item(NAME(m_cc)); + save_item(NAME(m_ccen)); + save_item(NAME(m_ci)); + save_item(NAME(m_rld)); + save_item(NAME(m_cp)); + save_item(NAME(m_d)); + save_item(NAME(m_i)); + + m_y.resolve_safe(); + m_full.resolve_safe(); + m_pl.resolve_safe(); + m_map.resolve_safe(); + m_vect.resolve_safe(); + + if (clock()) + m_execute_timer = timer_alloc(TIMER_CLOCK); + else + m_execute_timer = nullptr; +} + +void am2910_device::device_reset() +{ + m_pc = 0; + m_r = 0; + m_sp = 0; + memset(m_stack, 0, sizeof(uint16_t) * 5); + + if (m_execute_timer) + m_execute_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock())); +} + +void am2910_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_CLOCK) + { + cp_w(m_cp ? 0 : 1); + } +} + +WRITE_LINE_MEMBER(am2910_device::cc_w) +{ + m_cc = state; +} + +WRITE_LINE_MEMBER(am2910_device::ccen_w) +{ + m_ccen = state; +} + +WRITE_LINE_MEMBER(am2910_device::ci_w) +{ + m_ci = state; +} + +WRITE_LINE_MEMBER(am2910_device::rld_w) +{ + m_rld = state; +} + +WRITE_LINE_MEMBER(am2910_device::cp_w) +{ + int old_state = m_cp; + m_cp = state; + if (!old_state && state) + execute(); +} + +void am2910_device::d_w(uint16_t data) +{ + m_d = data; +} + +void am2910_device::i_w(uint8_t data) +{ + m_i = data; +} + +void am2910_device::update_source() +{ + switch (m_i) + { + case 2: + m_pl(0); + m_map(1); + m_vect(0); + break; + case 6: + m_pl(0); + m_map(0); + m_vect(1); + break; + default: + m_pl(1); + m_map(0); + m_vect(0); + break; + } +} + +void am2910_device::execute() +{ + if (m_rld == 0) + m_r = m_d; + + m_pc += (uint16_t)m_ci; + switch (m_i) + { + case 0: // JZ, Jump Zero + LOGMASKED(LOG_INSN, "%04x: JZ\n", m_pc); + m_pc = 0; + m_sp = 0; + break; + case 1: // CJS, Conditional Jump-To-Subroutine PL + LOGMASKED(LOG_INSN, "%04x: CJS\n", m_pc); + if (test_pass()) + { + push(m_pc); + m_pc = m_d; + } + break; + case 2: // JMAP, Jump Map + LOGMASKED(LOG_INSN, "%04x: JMAP\n", m_pc); + m_pc = m_d; + break; + case 3: // CJP, Conditional Jump PL + LOGMASKED(LOG_INSN, "%04x: CJP\n", m_pc); + if (test_pass()) + m_pc = m_d; + break; + case 4: // PUSH, Push / Conditional Load Counter + LOGMASKED(LOG_INSN, "%04x: PUSH\n", m_pc); + push(m_pc); + if (test_pass()) + m_r = m_d; + break; + case 5: // JSRP, Conditional JSB R/PL + LOGMASKED(LOG_INSN, "%04x: JSRP\n", m_pc); + push(m_pc); + if (test_pass()) + m_pc = m_d; + else + m_pc = m_r; + break; + case 6: // CJV, Conditional Jump Vector + LOGMASKED(LOG_INSN, "%04x: CJV\n", m_pc); + if (test_pass()) + { + m_pc = m_d; + } + break; + case 7: // JRP, Conditional Jump R/PL + LOGMASKED(LOG_INSN, "%04x: JRP\n", m_pc); + if (test_pass()) + m_pc = m_d; + else + m_pc = m_r; + break; + case 8: // RFCT, Repeat Loop, Counter != 0 + LOGMASKED(LOG_INSN, "%04x: RFCT\n", m_pc); + if (m_r != 0) + { + m_r--; + m_pc = m_stack[m_sp]; + } + break; + case 9: // RPCT, Repeat PL, Counter != 0 + LOGMASKED(LOG_INSN, "%04x: RPCT\n", m_pc); + if (m_r != 0) + { + m_r--; + m_pc = m_d; + } + break; + case 10: // CRTN, Conditional Return + LOGMASKED(LOG_INSN, "%04x: CRTN\n", m_pc); + if (test_pass()) + m_pc = m_stack[m_sp]; + break; + case 11: // CJPP, Conditional Jump PL & Pop + LOGMASKED(LOG_INSN, "%04x: CJPP\n", m_pc); + if (test_pass()) + { + m_pc = m_d; + pop(); + } + break; + case 12: // LDCT, Load Counter & Continue + LOGMASKED(LOG_INSN, "%04x: LDCT\n", m_pc); + m_r = m_d; + break; + case 13: // LOOP, Test End Loop + LOGMASKED(LOG_INSN, "%04x: LOOP\n", m_pc); + if (!test_pass()) + m_pc = m_stack[m_sp]; + break; + case 14: // CONT, Continue + LOGMASKED(LOG_INSN, "%04x: CONT\n", m_pc); + break; + case 15: // TWB, Three-Way Branch + LOGMASKED(LOG_INSN, "%04x: TWB\n", m_pc); + if (!test_pass()) + { + if (m_r != 0) + { + m_r--; + m_pc = m_stack[m_sp]; + } + else + { + m_pc = m_d; + } + } + break; + default: + LOGMASKED(LOG_ERROR, "Unrecognized Instruction: %08x\n", m_i); + } + + m_y(m_pc); +} + +bool am2910_device::test_pass() +{ + return m_ccen != 0 || m_cc == 0; +} + +void am2910_device::push(uint16_t value) +{ + if (m_sp < 4) + { + m_sp++; + if (m_sp == 4) + { + m_full(1); + } + } + m_stack[m_sp] = value; +} + +void am2910_device::pop() +{ + if (m_sp > 0) + { + m_sp--; + if (m_sp == 3) + { + m_full(0); + } + } +} diff --git a/src/devices/machine/am2910.h b/src/devices/machine/am2910.h new file mode 100644 index 00000000000..6990944e572 --- /dev/null +++ b/src/devices/machine/am2910.h @@ -0,0 +1,83 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + am2910.h + AMD Am2910 Microprogram Controller emulation + +***************************************************************************/ + +#ifndef MAME_MACHINE_AM2910_AM2910_H +#define MAME_MACHINE_AM2910_AM2910_H + +#pragma once + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> am2910_device + +class am2910_device : public device_t +{ +public: + // construction/destruction + am2910_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_WRITE_LINE_MEMBER(cc_w); // !CC + DECLARE_WRITE_LINE_MEMBER(ccen_w); // !CCEN + DECLARE_WRITE_LINE_MEMBER(ci_w); // CI + DECLARE_WRITE_LINE_MEMBER(rld_w); // !RLD + DECLARE_WRITE_LINE_MEMBER(cp_w); // CP + void d_w(uint16_t data); + void i_w(uint8_t data); + + auto y() { return m_y.bind(); } + auto pl() { return m_pl.bind(); } + auto full() { return m_full.bind(); } + auto map() { return m_map.bind(); } + auto vect() { return m_vect.bind(); } + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + static constexpr device_timer_id TIMER_CLOCK = 0; + + emu_timer *m_execute_timer; + + void execute(); + bool test_pass(); + void push(uint16_t value); + void pop(); + void update_source(); + + // internal state + uint16_t m_pc; + uint16_t m_r; + uint8_t m_sp; + uint16_t m_stack[5]; + + // inputs + int m_cc; + int m_ccen; + int m_ci; + int m_rld; + int m_cp; + uint16_t m_d; + uint8_t m_i; + + // outputs + devcb_write16 m_y; + devcb_write_line m_full; + devcb_write_line m_pl; + devcb_write_line m_map; + devcb_write_line m_vect; +}; + +// device type definition +DECLARE_DEVICE_TYPE(AM2910, am2910_device) + +#endif // MAME_MACHINE_AM2910_AM2910_H diff --git a/src/mame/drivers/dpb7000.cpp b/src/mame/drivers/dpb7000.cpp index a326544cd40..ff3c373a8ed 100644 --- a/src/mame/drivers/dpb7000.cpp +++ b/src/mame/drivers/dpb7000.cpp @@ -12,6 +12,7 @@ #include "bus/rs232/rs232.h" #include "cpu/m68000/m68000.h" #include "machine/6850acia.h" +#include "machine/am2910.h" #include "machine/com8116.h" #include "machine/input_merger.h" #include "video/mc6845.h" @@ -36,6 +37,9 @@ public: , m_auto_start(*this, "AUTOSTART") , m_config_sw12(*this, "CONFIGSW12") , m_config_sw34(*this, "CONFIGSW34") + , m_diskseq(*this, "diskseq") + , m_diskseq_ucode(*this, "diskseq_ucode") + , m_diskseq_prom(*this, "diskseq_prom") { } @@ -46,6 +50,9 @@ private: virtual void machine_start() override; virtual void machine_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + static constexpr device_timer_id TIMER_DISKSEQ = 0; DECLARE_READ16_MEMBER(bus_error_r); DECLARE_WRITE16_MEMBER(bus_error_w); @@ -55,21 +62,28 @@ private: DECLARE_READ16_MEMBER(cpu_ctrlbus_r); DECLARE_WRITE16_MEMBER(cpu_ctrlbus_w); + DECLARE_WRITE_LINE_MEMBER(req_a_w); + DECLARE_WRITE_LINE_MEMBER(req_b_w); + enum : uint16_t { SYSCTRL_AUTO_START = 0x0001, - SYSCTRL_REQ_B_OUT = 0x0020, - SYSCTRL_REQ_A_OUT = 0x0040, + SYSCTRL_REQ_B_EN = 0x0020, + SYSCTRL_REQ_A_EN = 0x0040, SYSCTRL_REQ_A_IN = 0x0080, SYSCTRL_REQ_B_IN = 0x8000 }; DECLARE_READ16_MEMBER(cpu_sysctrl_r); DECLARE_WRITE16_MEMBER(cpu_sysctrl_w); + void update_req_irqs(); MC6845_UPDATE_ROW(crtc_update_row); MC6845_ON_UPDATE_ADDR_CHANGED(crtc_addr_changed); + DECLARE_WRITE16_MEMBER(diskseq_y_w); + void diskseq_tick(); + required_device m_maincpu; required_device_array m_acia; required_device m_p_int; @@ -83,9 +97,54 @@ private: required_ioport m_auto_start; required_ioport m_config_sw12; required_ioport m_config_sw34; + required_device m_diskseq; + required_memory_region m_diskseq_ucode; + required_memory_region m_diskseq_prom; + + emu_timer *m_diskseq_clk; + + enum : uint8_t + { + DSEQ_STATUS_READY_BIT = 0, // C5 + DSEQ_STATUS_FAULT_BIT = 1, // C6 + DSEQ_STATUS_ONCYL_BIT = 2, // C7 + DSEQ_STATUS_SKERR_BIT = 3, // C8 + DSEQ_STATUS_INDEX_BIT = 4, // C9 + DSEQ_STATUS_SECTOR_BIT = 5, // C10 + DSEQ_STATUS_AMFND_BIT = 6, // C11 + DSEQ_STATUS_WTPROT_BIT = 7, // C12 + DSEQ_STATUS_SELECTED_BIT = 8, // C13 + DSEQ_STATUS_SEEKEND_BIT = 9, // C14 + DSEQ_STATUS_SYNC_DET_BIT = 10, // C15 + DSEQ_STATUS_RAM_ADDR_OVFLO_BIT = 11, // C16 + + DSEQ_CTRLOUT_CK_SEL_1 = (1 << 0), // S40 + DSEQ_CTRLOUT_CK_SEL_0 = (1 << 1), // S41 + DSEQ_CTRLOUT_ADDR_W_PERMIT = (1 << 2), // S42 + DSEQ_CTRLOUT_ZERO_RAM = (1 << 3), // S43 + DSEQ_CTRLOUT_WRITE_RAM = (1 << 4), // S44 + DSEQ_CTRLOUT_WORD_READ_RAM = (1 << 5), // S45 + DSEQ_CTRLOUT_WRITE_SYNC = (1 << 6), // S46 + DSEQ_CTRLOUT_SYNC_DET_EN = (1 << 7), // S47 + + DSEQ_CTRLOUT_WRITE_ZERO = (1 << 5), // S53 + DSEQ_CTRLOUT_LINE_CK = (1 << 6), // S54 + DSEQ_CTRLOUT_DISC_CLEAR = (1 << 7), // S55 + }; uint8_t m_csr; uint16_t m_sys_ctrl; + int m_diskseq_cp; + bool m_diskseq_reset; + uint8_t m_diskseq_line_cnt; // EF/EE + uint8_t m_diskseq_ed_cnt; // ED + uint8_t m_diskseq_head_cnt; // EC + uint16_t m_diskseq_cyl; // AE/BH + uint16_t m_diskseq_cmd; // DD/CC + uint8_t m_diskseq_status_in; // CG + uint8_t m_diskseq_status_out; // BC + uint8_t m_diskseq_ucode_latch[7]; // GG/GF/GE/GD/GC/GB/GA + uint8_t m_diskseq_cc_inputs[4]; // Inputs to FE/FD/FC/FB }; void dpb7000_state::main_map(address_map &map) @@ -237,12 +296,47 @@ void dpb7000_state::machine_start() { save_item(NAME(m_csr)); save_item(NAME(m_sys_ctrl)); + save_item(NAME(m_diskseq_cp)); + save_item(NAME(m_diskseq_reset)); + save_item(NAME(m_diskseq_line_cnt)); + save_item(NAME(m_diskseq_ed_cnt)); + save_item(NAME(m_diskseq_head_cnt)); + save_item(NAME(m_diskseq_cyl)); + save_item(NAME(m_diskseq_cmd)); + save_item(NAME(m_diskseq_status_in)); + save_item(NAME(m_diskseq_status_out)); + save_item(NAME(m_diskseq_ucode_latch)); + save_item(NAME(m_diskseq_cc_inputs)); + + m_diskseq_clk = timer_alloc(TIMER_DISKSEQ); } void dpb7000_state::machine_reset() { m_brg->stt_w(m_baud_dip->read()); m_csr = 0; + m_sys_ctrl = 0; + m_diskseq_cp = 0; + m_diskseq_reset = false; + m_diskseq_line_cnt = 0; + m_diskseq_ed_cnt = 0; + m_diskseq_head_cnt = 0; + m_diskseq_cyl = 0; + m_diskseq_cmd = 0; + m_diskseq_status_in = 0; + m_diskseq_status_out = 0; + memset(m_diskseq_ucode_latch, 0, 7); + memset(m_diskseq_cc_inputs, 0, 4); + + m_diskseq_clk->adjust(attotime::from_hz(1000000), 0, attotime::from_hz(1000000)); +} + +void dpb7000_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_DISKSEQ) + { + diskseq_tick(); + } } MC6845_UPDATE_ROW(dpb7000_state::crtc_update_row) @@ -277,6 +371,117 @@ MC6845_ON_UPDATE_ADDR_CHANGED(dpb7000_state::crtc_addr_changed) { } +WRITE16_MEMBER(dpb7000_state::diskseq_y_w) +{ + uint8_t old_prom_latch[7]; + memcpy(old_prom_latch, m_diskseq_ucode_latch, 7); + + const uint8_t *ucode_prom = m_diskseq_ucode->base(); + for (int i = 0; i < 7; i++) + { + m_diskseq_ucode_latch[i] = ucode_prom[data | (i << 8)]; + } + + if (m_diskseq_reset) + { + m_diskseq->i_w(0); + } + else + { + m_diskseq->i_w(m_diskseq_ucode_latch[1] & 0x0f); + } + m_diskseq->d_w(m_diskseq_ucode_latch[0]); + + if (!BIT(old_prom_latch[2], 1) && BIT(m_diskseq_ucode_latch[2], 1)) // S17: Line Counter Clock + m_diskseq_line_cnt++; + if (BIT(m_diskseq_ucode_latch[2], 2)) // S18: Line Counter Reset + m_diskseq_line_cnt = 0; + + if (!BIT(old_prom_latch[2], 3) && BIT(m_diskseq_ucode_latch[2], 3)) // S19: ED Counter Clock + m_diskseq_ed_cnt++; + if (BIT(m_diskseq_ucode_latch[2], 4)) // S20: ED Counter Reset + m_diskseq_ed_cnt = 0; + + if (!BIT(old_prom_latch[2], 5) && BIT(m_diskseq_ucode_latch[2], 5)) // S21: Auto-Head Clock + m_diskseq_head_cnt++; + if (BIT(m_diskseq_ucode_latch[2], 6)) // S22: Auto-Head Reset + m_diskseq_head_cnt = 0; + + memset(m_diskseq_cc_inputs, 0, 4); + m_diskseq_cc_inputs[0] |= m_diskseq_prom->base()[m_diskseq_line_cnt & 0x1f] & 3; + m_diskseq_cc_inputs[0] |= BIT(m_diskseq_ed_cnt, 2) << 2; + m_diskseq_cc_inputs[0] |= BIT(m_diskseq_head_cnt, 0) << 3; + m_diskseq_cc_inputs[0] |= BIT(m_diskseq_status_in, DSEQ_STATUS_READY_BIT) << 5; + m_diskseq_cc_inputs[0] |= BIT(m_diskseq_status_in, DSEQ_STATUS_FAULT_BIT) << 6; + m_diskseq_cc_inputs[0] |= BIT(m_diskseq_status_in, DSEQ_STATUS_ONCYL_BIT) << 7; + + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_SKERR_BIT); + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_INDEX_BIT) << 1; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_SECTOR_BIT) << 2; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_AMFND_BIT) << 3; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_WTPROT_BIT) << 4; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_SELECTED_BIT) << 5; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_SEEKEND_BIT) << 6; + m_diskseq_cc_inputs[1] |= BIT(m_diskseq_status_in, DSEQ_STATUS_SYNC_DET_BIT) << 7; + + m_diskseq_cc_inputs[2] |= BIT(m_diskseq_status_in, DSEQ_STATUS_RAM_ADDR_OVFLO_BIT); + // C17..C19 tied low + m_diskseq_cc_inputs[2] |= (m_diskseq_cmd & 0xf) << 4; + + m_diskseq_cc_inputs[3] = (m_diskseq_cmd >> 4) & 0xff; + + // S15, S16: Select which bank of 8 lines is treated as /CC input to Am2910 + const uint8_t fx_bank_sel = (BIT(m_diskseq_ucode_latch[2], 0) << 1) | BIT(m_diskseq_ucode_latch[1], 7); + + // S12, S13, S14: Select which bit from the bank is treated as /CC input to Am2910 + const uint8_t fx_bit_sel = (BIT(m_diskseq_ucode_latch[1], 6) << 2) | (BIT(m_diskseq_ucode_latch[1], 5) << 1) | BIT(m_diskseq_ucode_latch[1], 4); + + m_diskseq->cc_w(BIT(m_diskseq_cc_inputs[fx_bank_sel], fx_bit_sel) ? 0 : 1); + + // S25: End of sequencer program + //logerror("ucode latches %02x: %02x %02x %02x %02x %02x %02x %02x\n", data, + //m_diskseq_ucode_latch[0], m_diskseq_ucode_latch[1], m_diskseq_ucode_latch[2], m_diskseq_ucode_latch[3], + //m_diskseq_ucode_latch[4], m_diskseq_ucode_latch[5], m_diskseq_ucode_latch[6]); + req_b_w(BIT(m_diskseq_ucode_latch[3], 1) ? 0 : 1); + + // S23: FCYL TAG + // S24: Push cylinder number onto the bus cable + // S26, S28..S34: Command word to push onto bus cable + // S27: Push command word from S26, S28..S34 onto bus cable + // S35: FHD TAG + // S36: FCMD TAG + // S37: FSEL TAG + // S38: N/C + // S39: N/C from PROM, contains D INDEX status bit + // S40..S47: Outgoing control signals + // S48: CPU Status Byte D0 + // S49: CPU Status Byte D1 + // S50: CPU Status Byte D2 + // C5 (D READY): CPU Status Byte D3 + // C12 (D WTPROT): CPU Status Byte D4 + // ED Bit 0: CPU Status Byte D5 + // ED Bit 1: CPU Status Byte D6 + // C6 (D FAULT): CPU Status Byte D7 + + m_diskseq_status_out = m_diskseq_ucode_latch[6] & 7; + m_diskseq_status_out |= BIT(m_diskseq_status_in, DSEQ_STATUS_READY_BIT) << 3; + m_diskseq_status_out |= BIT(m_diskseq_status_in, DSEQ_STATUS_WTPROT_BIT) << 4; + m_diskseq_status_out |= (m_diskseq_ed_cnt & 3) << 5; + m_diskseq_status_out |= BIT(m_diskseq_status_in, DSEQ_STATUS_FAULT_BIT) << 7; +} + +void dpb7000_state::diskseq_tick() +{ + m_diskseq_cp = (m_diskseq_cp ? 0 : 1); + m_diskseq->cp_w(m_diskseq_cp); + + if (m_diskseq_cp && m_diskseq_reset) + { + req_b_w(0); + m_diskseq_reset = false; + } +} + READ16_MEMBER(dpb7000_state::bus_error_r) { if(!machine().side_effects_disabled()) @@ -309,24 +514,77 @@ READ16_MEMBER(dpb7000_state::cpu_ctrlbus_r) uint16_t ret = 0; switch (m_csr) { - case 12: - ret = m_config_sw34->read(); - logerror("%s: CPU read from Control Bus, Config Switches 1/2: %04x\n", machine().describe_context(), ret); - break; - case 14: - ret = m_config_sw12->read(); - logerror("%s: CPU read from Control Bus, Config Switches 3/4: %04x\n", machine().describe_context(), ret); - break; - default: - logerror("%s: CPU read from Control Bus, unknown CSR %d\n", machine().describe_context(), m_csr); - break; + case 12: + ret = m_config_sw34->read(); + logerror("%s: CPU read from Control Bus, Config Switches 1/2: %04x\n", machine().describe_context(), ret); + break; + case 14: + ret = m_config_sw12->read(); + logerror("%s: CPU read from Control Bus, Config Switches 3/4: %04x\n", machine().describe_context(), ret); + break; + case 15: + logerror("%s: CPU read from Control Bus, Disk Sequencer Card status: %02x\n", machine().describe_context(), m_diskseq_status_out); + ret = m_diskseq_status_out; + break; + default: + logerror("%s: CPU read from Control Bus, unknown CSR %d\n", machine().describe_context(), m_csr); + break; } return ret; } WRITE16_MEMBER(dpb7000_state::cpu_ctrlbus_w) { - logerror("%s: CPU to Control Bus write: %04x\n", machine().describe_context(), data); + switch (m_csr) + { + case 1: // Disk Sequencer Card, disc access + { + const uint8_t hi_nybble = data >> 12; + if (hi_nybble == 0) + { + m_diskseq_cyl = data & 0x3ff; + logerror("%s: CPU write to Control Bus, Disk Sequencer Card, Cylinder Number: %04x\n", machine().describe_context(), m_diskseq_cyl); + } + else if (hi_nybble == 2) + { + m_diskseq_cmd = data & 0xfff; + req_b_w(1); + logerror("%s: CPU write to Control Bus, Disk Sequencer Card, Command: %04x\n", machine().describe_context(), m_diskseq_cmd); + } + else + { + logerror("%s: CPU write to Control Bus, Disk Sequencer Card, Unrecognized hi nybble: %04x\n", machine().describe_context(), data); + } + break; + } + case 15: // Disk Sequencer Card, panic reset + logerror("%s: CPU write to Control Bus, Disk Sequencer Card, panic reset\n", machine().describe_context()); + m_diskseq_reset = true; + break; + default: + logerror("%s: CPU write to Control Bus, unknown CSR %d: %04x\n", machine().describe_context(), m_csr, data); + break; + } +} + +WRITE_LINE_MEMBER(dpb7000_state::req_a_w) +{ + if (state) + m_sys_ctrl |= SYSCTRL_REQ_A_IN; + else + m_sys_ctrl &= ~SYSCTRL_REQ_A_IN; + + update_req_irqs(); +} + +WRITE_LINE_MEMBER(dpb7000_state::req_b_w) +{ + if (state) + m_sys_ctrl |= SYSCTRL_REQ_B_IN; + else + m_sys_ctrl &= ~SYSCTRL_REQ_B_IN; + + update_req_irqs(); } READ16_MEMBER(dpb7000_state::cpu_sysctrl_r) @@ -340,10 +598,18 @@ READ16_MEMBER(dpb7000_state::cpu_sysctrl_r) WRITE16_MEMBER(dpb7000_state::cpu_sysctrl_w) { - const uint16_t mask = (SYSCTRL_REQ_A_OUT | SYSCTRL_REQ_B_OUT); + const uint16_t mask = (SYSCTRL_REQ_A_EN | SYSCTRL_REQ_B_EN); logerror("%s: CPU to Control Bus write: %04x\n", machine().describe_context(), data); m_sys_ctrl &= ~mask; m_sys_ctrl |= (data & mask); + + update_req_irqs(); +} + +void dpb7000_state::update_req_irqs() +{ + m_maincpu->set_input_line(5, (m_sys_ctrl & SYSCTRL_REQ_A_IN) && (m_sys_ctrl & SYSCTRL_REQ_A_EN) ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(4, (m_sys_ctrl & SYSCTRL_REQ_B_IN) && (m_sys_ctrl & SYSCTRL_REQ_B_EN) ? ASSERT_LINE : CLEAR_LINE); } void dpb7000_state::dpb7000(machine_config &config) @@ -393,6 +659,12 @@ void dpb7000_state::dpb7000(machine_config &config) m_crtc->set_screen("screen"); m_crtc->set_update_row_callback(FUNC(dpb7000_state::crtc_update_row), this); m_crtc->set_on_update_addr_change_callback(FUNC(dpb7000_state::crtc_addr_changed), this); + + AM2910(config, m_diskseq, 0); // We drive the clock manually from the driver + m_diskseq->ci_w(1); + m_diskseq->rld_w(1); + m_diskseq->ccen_w(0); + m_diskseq->y().set(FUNC(dpb7000_state::diskseq_y_w)); } @@ -416,7 +688,19 @@ ROM_START( dpb7000 ) ROM_LOAD16_BYTE("01616a-gad-397d.bin", 0x70000, 0x8000, CRC(0b95f9ed) SHA1(77126ee6c1f3dcdb8aa669ab74ff112e3f01918a)) ROM_REGION(0x1000, "vduchar", 0) - ROM_LOAD( "bw14char.ic1", 0x0000, 0x1000, BAD_DUMP CRC(f9dd68b5) SHA1(50132b759a6d84c22c387c39c0f57535cd380411) ) + ROM_LOAD("bw14char.ic1", 0x0000, 0x1000, BAD_DUMP CRC(f9dd68b5) SHA1(50132b759a6d84c22c387c39c0f57535cd380411)) + + ROM_REGION(0x700, "diskseq_ucode", 0) + ROM_LOAD("17704a-hga-256.bin", 0x000, 0x100, CRC(ab59d8fd) SHA1(6dcbbb48838a5e370e22a708cea44e3db80d6505)) + ROM_LOAD("17704a-hfa-256.bin", 0x100, 0x100, CRC(f2475396) SHA1(b525ba58d37128cadf1e7285fb421c14e2495587)) + ROM_LOAD("17704a-hea-256.bin", 0x200, 0x100, CRC(0a19cc11) SHA1(13b72368d7cb5b7f685adfa07f07029026426b80)) + ROM_LOAD("17704a-hda-256.bin", 0x300, 0x100, CRC(a431cdf6) SHA1(027eea87ccafde727208277b40e3a3f88433343a)) + ROM_LOAD("17704a-hca-256.bin", 0x400, 0x100, CRC(610ef462) SHA1(f495647cc8420b7470ad68bccc069370f8f2af93)) + ROM_LOAD("17704a-hba-256.bin", 0x500, 0x100, CRC(94c16baf) SHA1(13baef1359bf92a8ebb9a0c39f4223e810c3cdc1)) + ROM_LOAD("17704a-haa-256.bin", 0x600, 0x100, CRC(0080f2a9) SHA1(63c7b31e5f65cc6e2c5fc67883c84284652cb4a7)) + + ROM_REGION(0x700, "diskseq_prom", 0) + ROM_LOAD("17704a-dfa-32.bin", 0x00, 0x20, CRC(ce5b8b46) SHA1(49a1e619f52101b6078e2f51d82ce5947fe2c011)) ROM_END COMP( 1981, dpb7000, 0, 0, dpb7000, dpb7000, dpb7000_state, empty_init, "Quantel", "DPB-7000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )