diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp index b8cad3534e2..12bcf3920a7 100644 --- a/src/devices/cpu/m6502/st2xxx.cpp +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -49,6 +49,9 @@ st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, co , m_btsr(0) , m_bt_mask(0) , m_bt_ireq(0) + , m_pres_base(0) + , m_pres_started(attotime::zero) + , m_prs(0) , m_sys(0) , m_misc(0) , m_ireq(0) @@ -149,6 +152,9 @@ void st2xxx_device::save_common_registers() save_item(NAME(m_bten)); save_item(NAME(m_btsr)); } + save_item(NAME(m_pres_base)); + save_item(NAME(m_pres_started)); + save_item(NAME(m_prs)); save_item(NAME(m_sys)); if (st2xxx_misc_mask() != 0) save_item(NAME(m_misc)); @@ -197,6 +203,9 @@ void st2xxx_device::device_reset() bten_w(0); m_btsr = 0; + // reset prescaler + prs_w(0x80); + // reset miscellaneous registers m_sys = 0; m_misc = st2xxx_wdten_on_reset() ? 0x0c : 0; @@ -374,6 +383,56 @@ void st2xxx_device::btclr_all_w(u8 data) m_btsr = 0; } +u32 st2xxx_device::tclk_pres_div(u8 mode) const +{ + assert(mode < 8); + if (mode == 0) + return 0x10000; + else if (mode < 4) + return 0x20000 >> (mode * 2); + else if (mode == 4) + return 0x100; + else + return 0x8000 >> (mode * 2); +} + +u8 st2xxx_device::prs_r() +{ + return (m_pres_base + ((m_prs & 0x60) == 0x40 ? attotime_to_cycles(machine().time() - m_pres_started) : 0)) & 0xff; +} + +void st2xxx_device::prs_w(u8 data) +{ + data &= st2xxx_prs_mask(); + + // Bit 7 produces prescaler reset pulse + if (BIT(data, 7)) + { + st2xxx_tclk_stop(); + m_pres_base = 0; + if ((m_prs & 0x60) == 0x40) + { + m_pres_started = machine().time(); + st2xxx_tclk_start(); + } + data &= 0x7f; + } + + // Bit 6 enables prescaler; bit 5 selects clock source + if ((data & 0x60) == 0x40 && (m_prs & 0x60) != 0x40) + { + m_pres_started = machine().time(); + st2xxx_tclk_start(); + } + else if ((data & 0x60) == 0x40 && (m_prs & 0x60) != 0x40) + { + st2xxx_tclk_stop(); + m_pres_base += attotime_to_cycles(machine().time() - m_pres_started); + } + + m_prs = data; +} + u8 st2xxx_device::sys_r() { return m_sys | 0x01; diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h index eea1058079a..be33598a3e1 100644 --- a/src/devices/cpu/m6502/st2xxx.h +++ b/src/devices/cpu/m6502/st2xxx.h @@ -35,6 +35,7 @@ public: ST_PSGC, ST_BTEN, ST_BTSR, + ST_PRS, ST_SYS, ST_IRR, ST_PRR, @@ -83,6 +84,9 @@ protected: virtual u16 st2xxx_ireq_mask() const = 0; virtual const char *st2xxx_irq_name(int i) const = 0; virtual unsigned st2xxx_bt_divider(int n) const = 0; + virtual u8 st2xxx_prs_mask() const = 0; + virtual void st2xxx_tclk_start() { } + virtual void st2xxx_tclk_stop() { } virtual u8 st2xxx_sys_mask() const = 0; virtual u8 st2xxx_misc_mask() const = 0; virtual bool st2xxx_wdten_on_reset() const { return false; } @@ -163,6 +167,10 @@ protected: void btclr_w(u8 data); void btclr_all_w(u8 data); + u32 tclk_pres_div(u8 mode) const; + u8 prs_r(); + void prs_w(u8 data); + u8 ireql_r(); void ireql_w(u8 data); u8 ireqh_r(); @@ -218,6 +226,10 @@ protected: u8 m_bt_mask; u16 m_bt_ireq; + u16 m_pres_base; + attotime m_pres_started; + u8 m_prs; + u8 m_sys; u8 m_misc;