mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
-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]
This commit is contained in:
parent
f779db85df
commit
8689ada5a3
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
306
src/devices/machine/am2910.cpp
Normal file
306
src/devices/machine/am2910.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
83
src/devices/machine/am2910.h
Normal file
83
src/devices/machine/am2910.h
Normal file
@ -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
|
@ -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<m68000_base_device> m_maincpu;
|
||||
required_device_array<acia6850_device, 3> m_acia;
|
||||
required_device<input_merger_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<am2910_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 )
|
||||
|
Loading…
Reference in New Issue
Block a user