From fc7c9363a2ace1f67c08cd822d5158ade31a7493 Mon Sep 17 00:00:00 2001 From: AJR Date: Thu, 7 Nov 2019 22:46:30 -0500 Subject: st2204: Emulate Timer 1 (nw) st2xxx: Add register stubs for BRG; rename port registers for debugger; a little more refactoring (nw) --- src/devices/cpu/m6502/st2204.cpp | 119 +++++++++++++++++++++++++++++--------- src/devices/cpu/m6502/st2204.h | 12 ++-- src/devices/cpu/m6502/st2205u.cpp | 20 +++---- src/devices/cpu/m6502/st2205u.h | 6 +- src/devices/cpu/m6502/st2xxx.cpp | 50 ++++++++++++++++ src/devices/cpu/m6502/st2xxx.h | 32 +++++++--- 6 files changed, 183 insertions(+), 56 deletions(-) diff --git a/src/devices/cpu/m6502/st2204.cpp b/src/devices/cpu/m6502/st2204.cpp index b56d4482336..55c837fb8d6 100644 --- a/src/devices/cpu/m6502/st2204.cpp +++ b/src/devices/cpu/m6502/st2204.cpp @@ -45,7 +45,7 @@ st2204_device::st2204_device(const machine_config &mconfig, device_type type, co , m_tmode{0} , m_tcntr{0} , m_tload{0} - , m_t0_timer(nullptr) + , m_timer{0} , m_psg{0} , m_psgc(0) , m_dms(0) @@ -78,7 +78,8 @@ void st2204_device::device_start() init_base_timer(0x0020); - m_t0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::t0_interrupt), this)); + m_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::t0_interrupt), this)); + m_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::t1_interrupt), this)); save_item(NAME(m_tmode)); save_item(NAME(m_tcntr)); @@ -100,14 +101,14 @@ void st2204_device::device_start() state_add(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(st2xxx_ireq_mask()); for (int i = 0; i < 5; i++) { - state_add(ST_PDA + i, string_format("PD%c", 'A' + i).c_str(), m_pdata[i]); + state_add(ST_PAOUT + i, string_format("P%cOUT", 'A' + i).c_str(), m_pdata[i]); state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]); if (i == 2) state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]); if (i == 2 || i == 3) state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]); } - state_add(ST_PDL, "PDL", m_pdata[6]); + state_add(ST_PLOUT, "PLOUT", m_pdata[6]); state_add(ST_PCL, "PCL", m_pctrl[6]); state_add(ST_PMCR, "PMCR", m_pmcr); state_add(ST_PRS, "PRS", [this]() { return m_prs; }, [this](u8 data) { prs_w(data); }).mask(0x60); @@ -132,6 +133,9 @@ void st2204_device::device_start() state_add(ST_LFRA, "LFRA", m_lfra).mask(0x3f); state_add(ST_LAC, "LAC", m_lac).mask(0x1f); state_add(ST_LPWM, "LPWM", m_lpwm).mask(st2xxx_lpwm_mask()); + state_add(ST_BCTR, "BCTR", m_bctr).mask(0x87); + state_add(ST_BRS, "BRS", m_brs); + state_add(ST_BDIV, "BDIV", m_bdiv); state_add(ST_DMS, "DMS", m_dms); state_add(ST_DMR, "DMR", downcast(*mintf).dmr).mask(0x7ff); state_add(ST_DMD, "DMD", m_dmd); @@ -144,7 +148,8 @@ void st2204_device::device_reset() m_tmode[0] = m_tmode[1] = 0; m_tcntr[0] = m_tcntr[1] = 0; m_tload[0] = m_tload[1] = 0; - m_t0_timer->adjust(attotime::never); + m_timer[0]->adjust(attotime::never); + m_timer[1]->adjust(attotime::never); m_psg[0] = m_psg[1] = 0; m_psgc = 0; @@ -235,16 +240,6 @@ void st2204_device::mi_st2204::write(u16 adr, u8 val) program->write_byte(adr, val); } -u8 st2204_device::pmcr_r() -{ - return m_pmcr; -} - -void st2204_device::pmcr_w(u8 data) -{ - m_pmcr = data; -} - unsigned st2204_device::st2xxx_bt_divider(int n) const { // 2 Hz, 8 Hz, 64 Hz, 256 Hz, 2048 Hz @@ -261,13 +256,32 @@ TIMER_CALLBACK_MEMBER(st2204_device::t0_interrupt) // Bit 4 allows auto-reload m_tcntr[0] = BIT(m_tmode[0], 4) ? m_tload[0] : 0; - m_t0_timer->adjust(cycles_to_attotime((256 - m_tcntr[0]) * tclk_pres_div(m_tmode[0] & 0x07))); + m_timer[0]->adjust(cycles_to_attotime((256 - m_tcntr[0]) * tclk_pres_div(m_tmode[0] & 0x07))); +} + +TIMER_CALLBACK_MEMBER(st2204_device::t1_interrupt) +{ + m_ireq |= 0x008; + update_irq_state(); + + // Bit 4 allows auto-reload + m_tcntr[1] = BIT(m_tmode[1], 4) ? m_tload[1] : 0; + if (!BIT(m_tmode[1], 3)) + m_timer[1]->adjust(cycles_to_attotime((256 - m_tcntr[1]) * tclk_pres_div(m_tmode[1] & 0x07))); + else if ((m_tmode[1] & 0x07) < 3) + t1_start_from_oscx(); } -void st2204_device::t0_start() +void st2204_device::timer_start_from_tclk(int t) { - u32 div = tclk_pres_div(m_tmode[0] & 0x07); - m_t0_timer->adjust(cycles_to_attotime((255 - m_tcntr[0]) * div + div - (pres_count() & (div - 1)))); + u32 div = tclk_pres_div(m_tmode[t] & 0x07); + m_timer[t]->adjust(cycles_to_attotime((255 - m_tcntr[t]) * div + div - (pres_count() & (div - 1)))); +} + +void st2204_device::t1_start_from_oscx() +{ + u32 div = 256 >> (m_tmode[1] & 0x03); + m_timer[1]->adjust(attotime::from_ticks(div, 32768)); } u8 st2204_device::t0m_r() @@ -285,9 +299,9 @@ void st2204_device::t0m_w(u8 data) m_tcntr[0] = t0c_r(); if (BIT(data, 5)) - t0_start(); + timer_start_from_tclk(0); else if (BIT(t0m_old, 5)) - m_t0_timer->adjust(attotime::never); + m_timer[0]->adjust(attotime::never); } } @@ -298,7 +312,7 @@ u8 st2204_device::t0c_r() else { u32 div = tclk_pres_div(m_tmode[0] & 0x07); - return 255 - u8(attotime_to_cycles(m_t0_timer->remaining()) / div); + return 255 - u8(attotime_to_cycles(m_timer[0]->remaining()) / div); } } @@ -306,7 +320,7 @@ void st2204_device::t0c_w(u8 data) { m_tcntr[0] = m_tload[0] = data; if ((m_prs & 0x60) == 0x40 && BIT(m_tmode[0], 5)) - t0_start(); + timer_start_from_tclk(0); } u8 st2204_device::t1m_r() @@ -316,12 +330,48 @@ u8 st2204_device::t1m_r() void st2204_device::t1m_w(u8 data) { - m_tmode[1] = data & 0x1f; + data &= 0x1f; + u8 t1m_old = std::exchange(m_tmode[1], data); + + if ((data & 0x0f) != (t1m_old & 0x0f)) + { + // forced update + m_tcntr[1] = t1c_r(); + + if (!BIT(data, 3)) + { + if ((m_prs & 0x60) == 0x40) + timer_start_from_tclk(1); + else + m_timer[1]->adjust(attotime::never); + } + else if (data < 0x0b) + t1_start_from_oscx(); + + // TODO: BGRCK source + } + } u8 st2204_device::t1c_r() { - return m_tcntr[1]; + if (!BIT(m_tmode[1], 3)) + { + if ((m_prs & 0x60) != 0x40) + return m_tcntr[1]; + else + { + u32 div = tclk_pres_div(m_tmode[1] & 0x07); + return 255 - u8(attotime_to_cycles(m_timer[1]->remaining()) / div); + } + } + else if ((m_tmode[1] & 0x07) < 3) + { + u32 div = 256 >> (m_tmode[1] & 0x03); + return 255 - u8(m_timer[1]->remaining().as_ticks(32768) / div); + } + else + return m_tcntr[1]; } void st2204_device::t1c_w(u8 data) @@ -332,13 +382,23 @@ void st2204_device::t1c_w(u8 data) void st2204_device::st2xxx_tclk_start() { if (BIT(m_tmode[0], 5)) - t0_start(); + timer_start_from_tclk(0); + if (!BIT(m_tmode[1], 3)) + timer_start_from_tclk(1); } void st2204_device::st2xxx_tclk_stop() { - m_tcntr[0] = t0c_r(); - m_t0_timer->adjust(attotime::never); + if (m_timer[0]->enabled()) + { + m_tcntr[0] = t0c_r(); + m_timer[0]->adjust(attotime::never); + } + if (!BIT(m_tmode[1], 3)) + { + m_tcntr[1] = t1c_r(); + m_timer[1]->adjust(attotime::never); + } } void st2204_device::psg_w(offs_t offset, u8 data) @@ -500,6 +560,9 @@ void st2204_device::common_map(address_map &map) map(0x004c, 0x004c).rw(FUNC(st2204_device::pl_r), FUNC(st2204_device::pl_w)); // PCL is listed as write-only in ST2202 specification, but DynamiDesk suggests otherwise map(0x004e, 0x004e).rw(FUNC(st2204_device::pcl_r), FUNC(st2204_device::pcl_w)); + map(0x0063, 0x0063).rw(FUNC(st2204_device::bctr_r), FUNC(st2204_device::bctr_w)); + map(0x0066, 0x0066).rw(FUNC(st2204_device::brs_r), FUNC(st2204_device::brs_w)); + map(0x0067, 0x0067).rw(FUNC(st2204_device::bdiv_r), FUNC(st2204_device::bdiv_w)); map(0x4000, 0x7fff).rw(FUNC(st2204_device::pmem_r), FUNC(st2204_device::pmem_w)); map(0x8000, 0xffff).rw(FUNC(st2204_device::dmem_r), FUNC(st2204_device::dmem_w)); } diff --git a/src/devices/cpu/m6502/st2204.h b/src/devices/cpu/m6502/st2204.h index 46c071d3c9b..8cca3c57085 100644 --- a/src/devices/cpu/m6502/st2204.h +++ b/src/devices/cpu/m6502/st2204.h @@ -18,7 +18,7 @@ class st2204_device : public st2xxx_device { public: enum { - ST_T0M = ST_LPWM + 1, + ST_T0M = ST_BDIV + 1, ST_T0C, ST_T1M, ST_T1C, @@ -38,6 +38,7 @@ protected: virtual u16 st2xxx_ireq_mask() const override { return 0x0f7f; } virtual const char *st2xxx_irq_name(int i) const override; + virtual u8 st2xxx_pmcr_mask() const override { return 0xff; } virtual unsigned st2xxx_bt_divider(int n) const override; virtual u8 st2xxx_prs_mask() const override { return 0xe0; } virtual void st2xxx_tclk_start() override; @@ -49,6 +50,7 @@ protected: virtual u8 st2xxx_lctr_mask() const override { return 0xff; } virtual u8 st2xxx_lckr_mask() const override { return 0x1f; } virtual u8 st2xxx_lpwm_mask() const override { return 0x3f; } + virtual u8 st2xxx_bctr_mask() const override { return 0x87; } void common_map(address_map &map); @@ -70,10 +72,10 @@ private: void dwrite(u16 adr, u8 val); }; - u8 pmcr_r(); - void pmcr_w(u8 data); TIMER_CALLBACK_MEMBER(t0_interrupt); - void t0_start(); + TIMER_CALLBACK_MEMBER(t1_interrupt); + void timer_start_from_tclk(int t); + void t1_start_from_oscx(); u8 t0m_r(); void t0m_w(u8 data); u8 t0c_r(); @@ -106,7 +108,7 @@ private: u8 m_tmode[2]; u8 m_tcntr[2]; u8 m_tload[2]; - emu_timer *m_t0_timer; + emu_timer *m_timer[2]; u16 m_psg[2]; u8 m_psgc; u16 m_dms; diff --git a/src/devices/cpu/m6502/st2205u.cpp b/src/devices/cpu/m6502/st2205u.cpp index 007d012b71c..100169584a9 100644 --- a/src/devices/cpu/m6502/st2205u.cpp +++ b/src/devices/cpu/m6502/st2205u.cpp @@ -83,14 +83,14 @@ void st2205u_device::device_start() state_add(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(st2xxx_ireq_mask()); for (int i = 0; i < 6; i++) { - state_add(ST_PDA + i, string_format("PD%c", 'A' + i).c_str(), m_pdata[i]); + state_add(ST_PAOUT + i, string_format("P%cOUT", 'A' + i).c_str(), m_pdata[i]); state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]); if (i == 2 || i == 4) state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]); if (i == 2 || i == 3) state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]).mask(i == 2 ? 0xfe : 0xff); } - state_add(ST_PDL, "PDL", m_pdata[6]); + state_add(ST_PLOUT, "PLOUT", m_pdata[6]); state_add(ST_PCL, "PCL", m_pctrl[6]); state_add(ST_PMCR, "PMCR", m_pmcr); state_add(ST_MISC, "MISC", m_misc).mask(st2xxx_misc_mask()); @@ -113,6 +113,9 @@ void st2205u_device::device_start() state_add(ST_LFRA, "LFRA", m_lfra).mask(0x3f); state_add(ST_LAC, "LAC", m_lac).mask(0x1f); state_add(ST_LPWM, "LPWM", m_lpwm).mask(st2xxx_lpwm_mask()); + state_add(ST_BCTR, "BCTR", m_bctr).mask(0xb7); + state_add(ST_BRS, "BRS", m_brs); + state_add(ST_BDIV, "BDIV", m_bdiv); state_add(ST_LVCTR, "LVCTR", m_lvctr).mask(0x0f); } @@ -276,16 +279,6 @@ void st2205u_device::brrh_w(u8 data) brr = (data & 0x9f) << 8 | (brr & 0x00ff); } -u8 st2205u_device::pmcr_r() -{ - return m_pmcr; -} - -void st2205u_device::pmcr_w(u8 data) -{ - m_pmcr = data; -} - unsigned st2205u_device::st2xxx_bt_divider(int n) const { // 2 Hz @@ -452,6 +445,9 @@ void st2205u_device::int_map(address_map &map) map(0x0057, 0x0057).rw(FUNC(st2205u_device::lvctr_r), FUNC(st2205u_device::lvctr_w)); map(0x005a, 0x005a).rw(FUNC(st2205u_device::dmrl_r), FUNC(st2205u_device::dmrl_w)); map(0x005b, 0x005b).rw(FUNC(st2205u_device::dmrh_r), FUNC(st2205u_device::dmrh_w)); + map(0x0063, 0x0063).rw(FUNC(st2205u_device::bctr_r), FUNC(st2205u_device::bctr_w)); + map(0x0066, 0x0066).rw(FUNC(st2205u_device::brs_r), FUNC(st2205u_device::brs_w)); + map(0x0067, 0x0067).rw(FUNC(st2205u_device::bdiv_r), FUNC(st2205u_device::bdiv_w)); map(0x0080, 0x1fff).rw(FUNC(st2205u_device::ram_r), FUNC(st2205u_device::ram_w)); // assumed to be shared with banked RAM map(0x2000, 0x3fff).rw(FUNC(st2205u_device::bmem_r), FUNC(st2205u_device::bmem_w)); map(0x4000, 0x7fff).rw(FUNC(st2205u_device::pmem_r), FUNC(st2205u_device::pmem_w)); diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h index 00a120e3bb8..edde62aea71 100644 --- a/src/devices/cpu/m6502/st2205u.h +++ b/src/devices/cpu/m6502/st2205u.h @@ -17,7 +17,7 @@ class st2205u_device : public st2xxx_device { public: enum { - ST_BTC = ST_LPWM + 1, + ST_BTC = ST_BDIV + 1, ST_T0C, ST_T1C, ST_T2C, @@ -36,6 +36,7 @@ protected: virtual u16 st2xxx_ireq_mask() const override { return 0xdfff; } virtual const char *st2xxx_irq_name(int i) const override; + virtual u8 st2xxx_pmcr_mask() const override { return 0xff; } virtual unsigned st2xxx_bt_divider(int n) const override; virtual u8 st2xxx_prs_mask() const override { return 0xc0; } virtual void st2xxx_tclk_start() override; @@ -48,6 +49,7 @@ protected: virtual u8 st2xxx_lctr_mask() const override { return 0xef; } virtual u8 st2xxx_lckr_mask() const override { return 0x3f; } virtual u8 st2xxx_lpwm_mask() const override { return 0xff; } + virtual u8 st2xxx_bctr_mask() const override { return 0xb7; } private: class mi_st2205u : public mi_st2xxx { @@ -79,8 +81,6 @@ private: void brrl_w(u8 data); u8 brrh_r(); void brrh_w(u8 data); - u8 pmcr_r(); - void pmcr_w(u8 data); u8 btc_r(); void btc_w(u8 data); u8 tc_12bit_r(offs_t offset); diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp index 51a6a6094c6..62fd8871f85 100644 --- a/src/devices/cpu/m6502/st2xxx.cpp +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -66,6 +66,7 @@ st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, co , m_lfra(0) , m_lac(0) , m_lpwm(0) + , m_bctr(0) { program_config.m_internal_map = std::move(internal_map); } @@ -171,6 +172,12 @@ void st2xxx_device::save_common_registers() save_item(NAME(m_lfra)); save_item(NAME(m_lac)); save_item(NAME(m_lpwm)); + if (st2xxx_bctr_mask() != 0) + { + save_item(NAME(m_bctr)); + save_item(NAME(m_brs)); + save_item(NAME(m_bdiv)); + } } void st2xxx_device::device_reset() @@ -221,6 +228,9 @@ void st2xxx_device::device_reset() m_lfra = 0; m_lac = 0; m_lpwm = 0; + + // reset UART and BRG + m_bctr = 0; } u8 st2xxx_device::acknowledge_irq() @@ -336,6 +346,16 @@ void st2xxx_device::pcl_w(u8 data) pctrl_w(6, data); } +u8 st2xxx_device::pmcr_r() +{ + return m_pmcr; +} + +void st2xxx_device::pmcr_w(u8 data) +{ + m_pmcr = data & st2xxx_pmcr_mask(); +} + u8 st2xxx_device::bten_r() { return m_bten; @@ -718,4 +738,34 @@ void st2xxx_device::lpwm_w(u8 data) m_lpwm = data & st2xxx_lpwm_mask(); } +u8 st2xxx_device::bctr_r() +{ + return m_bctr; +} + +void st2xxx_device::bctr_w(u8 data) +{ + m_bctr = data & st2xxx_bctr_mask(); +} + +u8 st2xxx_device::brs_r() +{ + return m_brs; +} + +void st2xxx_device::brs_w(u8 data) +{ + m_brs = data; +} + +u8 st2xxx_device::bdiv_r() +{ + return m_bdiv; +} + +void st2xxx_device::bdiv_w(u8 data) +{ + m_bdiv = data; +} + #include "cpu/m6502/st2xxx.hxx" diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h index cc6be615e35..e72e5c36d95 100644 --- a/src/devices/cpu/m6502/st2xxx.h +++ b/src/devices/cpu/m6502/st2xxx.h @@ -8,13 +8,13 @@ class st2xxx_device : public r65c02_device { public: enum { - ST_PDA = M6502_IR + 1, - ST_PDB, - ST_PDC, - ST_PDD, - ST_PDE, - ST_PDF, - ST_PDL, + ST_PAOUT = M6502_IR + 1, + ST_PBOUT, + ST_PCOUT, + ST_PDOUT, + ST_PEOUT, + ST_PFOUT, + ST_PLOUT, ST_PCA, ST_PCB, ST_PCC, @@ -53,7 +53,10 @@ public: ST_LCKR, ST_LFRA, ST_LAC, - ST_LPWM + ST_LPWM, + ST_BCTR, + ST_BRS, + ST_BDIV }; auto in_pa_callback() { return m_in_port_cb[0].bind(); } @@ -83,6 +86,7 @@ protected: virtual u16 st2xxx_ireq_mask() const = 0; virtual const char *st2xxx_irq_name(int i) const = 0; + virtual u8 st2xxx_pmcr_mask() const = 0; virtual unsigned st2xxx_bt_divider(int n) const = 0; virtual u8 st2xxx_prs_mask() const = 0; virtual void st2xxx_tclk_start() { } @@ -95,6 +99,7 @@ protected: virtual u8 st2xxx_lctr_mask() const = 0; virtual u8 st2xxx_lckr_mask() const = 0; virtual u8 st2xxx_lpwm_mask() const = 0; + virtual u8 st2xxx_bctr_mask() const = 0; class mi_st2xxx : public memory_interface { public: @@ -138,6 +143,8 @@ protected: void pfc_w(u8 data); u8 pfd_r(); void pfd_w(u8 data); + u8 pmcr_r(); + void pmcr_w(u8 data); u8 sys_r(); void sys_w(u8 data); @@ -198,6 +205,12 @@ protected: void lac_w(u8 data); u8 lpwm_r(); void lpwm_w(u8 data); + u8 bctr_r(); + void bctr_w(u8 data); + u8 brs_r(); + void brs_w(u8 data); + u8 bdiv_r(); + void bdiv_w(u8 data); #define O(o) void o ## _full(); void o ## _partial() @@ -247,6 +260,9 @@ protected: u8 m_lfra; u8 m_lac; u8 m_lpwm; + u8 m_bctr; + u8 m_brs; + u8 m_bdiv; }; #endif // MAME_CPU_M6502_ST2XXX_H -- cgit v1.2.3