epg3231: Add Timers 1 & 2

This commit is contained in:
AJR 2023-08-30 19:02:35 -04:00
parent c06c4fd132
commit 513495070b
2 changed files with 97 additions and 17 deletions

View file

@ -200,7 +200,9 @@ void riscii_series_device::device_start()
set_icountptr(m_icount);
m_timer0 = timer_alloc(FUNC(riscii_series_device::timer0), this);
m_timer[0] = timer_alloc(FUNC(riscii_series_device::timer0), this);
m_timer[1] = timer_alloc(FUNC(riscii_series_device::timer1), this);
m_timer[2] = timer_alloc(FUNC(riscii_series_device::timer2), this);
m_speech_timer = timer_alloc(FUNC(riscii_series_device::speech_timer), this);
state_add<u32>(RII_PC, "PC", [this]() { return m_pc; }, [this](u32 pc) { debug_set_pc(pc); }).mask(m_pcmask);
@ -346,7 +348,9 @@ void riscii_series_device::device_reset()
m_tr01con = 0x00;
m_tr2con = 0x00;
m_sfcr = 0x00;
m_timer0->adjust(attotime::never);
m_timer[0]->adjust(attotime::never);
m_timer[1]->adjust(attotime::never);
m_timer[2]->adjust(attotime::never);
// reset synthesizer
std::fill_n(&m_env[0], 4, 0x00);
@ -821,11 +825,12 @@ void riscii_series_device::sprh_w(u8 data)
void riscii_series_device::timer0_reload()
{
// Prescaler values are 1:1, 1:4, 1:16, 1:64
const unsigned prescale = 1 << ((m_tr01con & 0x03) << 1);
if (BIT(m_tr01con, 2))
m_timer0->adjust(cycles_to_attotime((m_trl0 + 1) * prescale * 2));
m_timer[0]->adjust(cycles_to_attotime((m_trl0 + 1) * prescale * 2));
else
m_timer0->adjust(attotime::from_ticks((m_trl0 + 1) * prescale, 32768));
m_timer[0]->adjust(attotime::from_ticks((m_trl0 + 1) * prescale, 32768));
}
TIMER_CALLBACK_MEMBER(riscii_series_device::timer0)
@ -836,12 +841,73 @@ TIMER_CALLBACK_MEMBER(riscii_series_device::timer0)
u16 riscii_series_device::timer0_count() const
{
if (!m_timer0->enabled())
if (!m_timer[0]->enabled())
return 0;
else if (BIT(m_tr01con, 2))
return m_trl0 - m_timer0->remaining().as_ticks(32768);
else
return m_trl0 - attotime_to_cycles(m_timer0->remaining()) / 2;
{
// Timer 0 counts up
const unsigned prescale = 1 << ((m_tr01con & 0x03) << 1);
if (BIT(m_tr01con, 2))
return m_trl0 - attotime_to_cycles(m_timer[0]->remaining()) / 2 / prescale;
else
return m_trl0 - m_timer[0]->remaining().as_ticks(32768) / prescale;
}
}
void riscii_series_device::timer1_reload()
{
// Prescaler values are 1:4, 1:16, 1:64, 1:256
const unsigned prescale = 1 << (((m_tr01con & 0x30) >> 3) + 2);
m_timer[1]->adjust(attotime::from_ticks((m_trl1 + 1) * prescale, 32768));
}
TIMER_CALLBACK_MEMBER(riscii_series_device::timer1)
{
m_intsta |= 0x02;
timer1_reload();
}
u8 riscii_series_device::timer1_count() const
{
if (!m_timer[1]->enabled())
return 0;
else
{
// Timer 1 counts down
const unsigned prescale = 1 << (((m_tr01con & 0x30) >> 3) + 2);
return m_timer[1]->remaining().as_ticks(32768) / prescale;
}
}
void riscii_series_device::timer2_reload()
{
// Prescaler values are 1:1, 1:2, 1:4, 1:8
const unsigned prescale = 1 << (m_tr2con & 0x03);
if (BIT(m_tr2con, 2))
m_timer[2]->adjust(cycles_to_attotime((m_trl2 + 1) * prescale * 2));
else
m_timer[2]->adjust(attotime::from_ticks((m_trl2 + 1) * prescale, 32768));
}
TIMER_CALLBACK_MEMBER(riscii_series_device::timer2)
{
m_intsta |= 0x04;
timer2_reload();
}
u8 riscii_series_device::timer2_count() const
{
if (!m_timer[2]->enabled())
return 0;
else
{
// Timer 2 counts down
const unsigned prescale = 1 << (m_tr2con & 0x03);
if (BIT(m_tr2con, 2))
return attotime_to_cycles(m_timer[2]->remaining()) / 2 / prescale;
else
return m_timer[2]->remaining().as_ticks(32768) / prescale;
}
}
u8 riscii_series_device::trl0l_r()
@ -891,7 +957,11 @@ u8 riscii_series_device::tr01con_r()
void riscii_series_device::tr01con_w(u8 data)
{
m_tr01con = data;
u8 old_tr01con = std::exchange(m_tr01con, data);
if (BIT(data, 6) && !BIT(old_tr01con, 6))
timer1_reload();
else if (!BIT(data, 6) && BIT(old_tr01con, 6))
m_timer[1]->adjust(attotime::never);
}
u8 riscii_series_device::tr2con_r()
@ -901,12 +971,16 @@ u8 riscii_series_device::tr2con_r()
void riscii_series_device::tr2con_w(u8 data)
{
// TODO: capture mode, event counter mode
if ((data & 0x30) == 0x10 && (m_tr2con & 0x30) == 0)
// TODO: Timer 0 capture mode, event counter mode
u8 old_tr2con = std::exchange(m_tr2con, data);
if ((data & 0x30) == 0x10 && (old_tr2con & 0x30) == 0)
timer0_reload();
else if ((data & 0x30) == 0x10 && (m_tr2con & 0x30) == 0)
m_timer0->adjust(attotime::never);
m_tr2con = data;
else if ((data & 0x30) == 0x10 && (old_tr2con & 0x30) == 0)
m_timer[0]->adjust(attotime::never);
if (BIT(data, 3) && !BIT(old_tr2con, 3))
timer2_reload();
else if (!BIT(data, 3) && BIT(old_tr2con, 3))
m_timer[2]->adjust(attotime::never);
}
u8 riscii_series_device::trlir_r()
@ -931,12 +1005,12 @@ u8 riscii_series_device::t0ch_r()
u8 riscii_series_device::tr1c_r()
{
return 0xff;
return timer1_count();
}
u8 riscii_series_device::tr2c_r()
{
return 0xff;
return timer2_count();
}
u8 riscii_series_device::sfcr_r()

View file

@ -187,6 +187,12 @@ protected:
void timer0_reload();
TIMER_CALLBACK_MEMBER(timer0);
u16 timer0_count() const;
void timer1_reload();
TIMER_CALLBACK_MEMBER(timer1);
u8 timer1_count() const;
void timer2_reload();
TIMER_CALLBACK_MEMBER(timer2);
u8 timer2_count() const;
u8 trl0l_r();
void trl0l_w(u8 data);
u8 trl0h_r();
@ -361,7 +367,7 @@ private:
u8 m_tr01con;
u8 m_tr2con;
u8 m_trlir;
emu_timer *m_timer0;
emu_timer *m_timer[3];
// synthesizer state
u8 m_sfcr;