diff options
Diffstat (limited to 'src/devices/cpu/m6502/st2204.cpp')
-rw-r--r-- | src/devices/cpu/m6502/st2204.cpp | 119 |
1 files changed, 91 insertions, 28 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<u16>(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<u8>(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<mi_st2204 &>(*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)); } |