mirror of
https://github.com/holub/mame
synced 2025-07-06 10:29:38 +03:00
st2xxx: Refactoring (nw)
- Centralize emulation of several common features - Add logging for interrupts and base timer - Fix error in debug state registration of IREQ and IENA - Correct base timer interrupt vector for ST2205U
This commit is contained in:
parent
b6ba86f4cb
commit
273ec503fb
@ -37,24 +37,13 @@ st2204_device::st2204_device(const machine_config &mconfig, const char *tag, dev
|
||||
: st2xxx_device(mconfig, ST2204, tag, owner, clock,
|
||||
address_map_constructor(FUNC(st2204_device::int_map), this),
|
||||
26, // logical; only 23 address lines are brought out
|
||||
0x0f7f)
|
||||
, m_bten(0)
|
||||
, m_btsr(0)
|
||||
, m_base_timer{0}
|
||||
false)
|
||||
, m_dms(0)
|
||||
, m_dmd(0)
|
||||
, m_dcnth(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<int N>
|
||||
TIMER_CALLBACK_MEMBER(st2204_device::bt_interrupt)
|
||||
{
|
||||
m_btsr |= 1 << N;
|
||||
m_ireq |= 0x020;
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
void st2204_device::device_start()
|
||||
{
|
||||
std::unique_ptr<mi_st2204> intf = std::make_unique<mi_st2204>();
|
||||
@ -67,43 +56,21 @@ void st2204_device::device_start()
|
||||
intf->dmr = 0;
|
||||
intf->irq_service = false;
|
||||
|
||||
m_base_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::bt_interrupt<0>), this));
|
||||
m_base_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::bt_interrupt<1>), this));
|
||||
m_base_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::bt_interrupt<2>), this));
|
||||
m_base_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::bt_interrupt<3>), this));
|
||||
m_base_timer[4] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2204_device::bt_interrupt<4>), this));
|
||||
init_base_timer(0x0020);
|
||||
|
||||
save_item(NAME(m_pdata));
|
||||
save_item(NAME(m_pctrl));
|
||||
save_item(NAME(m_psel));
|
||||
save_item(NAME(m_pfun));
|
||||
save_item(NAME(m_bten));
|
||||
save_item(NAME(m_btsr));
|
||||
save_item(NAME(m_dms));
|
||||
save_item(NAME(m_dmd));
|
||||
save_item(NAME(m_dcnth));
|
||||
save_item(NAME(m_sys));
|
||||
save_item(NAME(m_pmcr));
|
||||
save_item(NAME(m_ireq));
|
||||
save_item(NAME(m_iena));
|
||||
save_item(NAME(m_lssa));
|
||||
save_item(NAME(m_lvpw));
|
||||
save_item(NAME(m_lxmax));
|
||||
save_item(NAME(m_lymax));
|
||||
save_item(NAME(intf->irr_enable));
|
||||
save_item(NAME(intf->irr));
|
||||
save_item(NAME(intf->prr));
|
||||
save_item(NAME(intf->drr));
|
||||
save_item(NAME(intf->irq_service));
|
||||
|
||||
mintf = std::move(intf);
|
||||
save_common_registers();
|
||||
init();
|
||||
|
||||
state_add(ST_IRR, "IRR", downcast<mi_st2204 &>(*mintf).irr).mask(0xff);
|
||||
state_add(ST_PRR, "PRR", downcast<mi_st2204 &>(*mintf).prr).mask(0xfff);
|
||||
state_add(ST_DRR, "DRR", downcast<mi_st2204 &>(*mintf).drr).mask(0x7ff);
|
||||
state_add<u8>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(m_ireq_mask);
|
||||
state_add<u8>(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(m_ireq_mask);
|
||||
state_add<u16>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
|
||||
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]);
|
||||
@ -131,16 +98,25 @@ void st2204_device::device_start()
|
||||
void st2204_device::device_reset()
|
||||
{
|
||||
st2xxx_device::device_reset();
|
||||
}
|
||||
|
||||
mi_st2204 &m = downcast<mi_st2204 &>(*mintf);
|
||||
m.irr_enable = false;
|
||||
m.irr = 0;
|
||||
m.prr = 0;
|
||||
m.drr = 0;
|
||||
m.dmr = 0;
|
||||
|
||||
bten_w(0);
|
||||
m_btsr = 0;
|
||||
const char *st2204_device::st2xxx_irq_name(int i) const
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return "PC0 edge";
|
||||
case 1: return "DAC reload";
|
||||
case 2: return "Timer 0";
|
||||
case 3: return "Timer 1";
|
||||
case 4: return "PA transition";
|
||||
case 5: return "Base timer";
|
||||
case 6: return "LCD frame";
|
||||
case 8: return "SPI TX empty";
|
||||
case 9: return "SPI RX ready";
|
||||
case 10: return "UART TX";
|
||||
case 11: return "UART RX";
|
||||
default: return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
u8 st2204_device::mi_st2204::pread(u16 adr)
|
||||
@ -219,103 +195,13 @@ void st2204_device::pmcr_w(u8 data)
|
||||
m_pmcr = data;
|
||||
}
|
||||
|
||||
u8 st2204_device::bten_r()
|
||||
unsigned st2204_device::st2xxx_bt_divider(int n) const
|
||||
{
|
||||
return m_bten;
|
||||
}
|
||||
|
||||
void st2204_device::bten_w(u8 data)
|
||||
{
|
||||
for (int n = 0; n < 5; n++)
|
||||
{
|
||||
if (BIT(data, n) && !BIT(m_bten, n))
|
||||
{
|
||||
// 2 Hz, 8 Hz, 64 Hz, 256 Hz, 2048 Hz
|
||||
attotime period = attotime::from_hz(2 << ((n & 1) * 2 + (n >> 1) * 5));
|
||||
m_base_timer[n]->adjust(period, 0, period);
|
||||
}
|
||||
else if (!BIT(data, n) && BIT(m_bten, n))
|
||||
m_base_timer[n]->adjust(attotime::never);
|
||||
}
|
||||
|
||||
m_bten = data & 0x1f;
|
||||
}
|
||||
|
||||
u8 st2204_device::btsr_r()
|
||||
{
|
||||
return m_btsr;
|
||||
}
|
||||
|
||||
void st2204_device::btsr_w(u8 data)
|
||||
{
|
||||
// Only bit 7 has any effect
|
||||
if (BIT(data, 7))
|
||||
m_btsr = 0;
|
||||
}
|
||||
|
||||
u8 st2204_device::sys_r()
|
||||
{
|
||||
return m_sys | 0x01;
|
||||
}
|
||||
|
||||
void st2204_device::sys_w(u8 data)
|
||||
{
|
||||
m_sys = data;
|
||||
downcast<mi_st2204 &>(*mintf).irr_enable = BIT(data, 1);
|
||||
}
|
||||
|
||||
u8 st2204_device::irr_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).irr;
|
||||
}
|
||||
|
||||
void st2204_device::irr_w(u8 data)
|
||||
{
|
||||
downcast<mi_st2204 &>(*mintf).irr = data;
|
||||
}
|
||||
|
||||
u8 st2204_device::prrl_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).prr & 0xff;
|
||||
}
|
||||
|
||||
void st2204_device::prrl_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2204 &>(*mintf).prr;
|
||||
prr = data | (prr & 0x0f00);
|
||||
}
|
||||
|
||||
u8 st2204_device::prrh_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).prr >> 8;
|
||||
}
|
||||
|
||||
void st2204_device::prrh_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2204 &>(*mintf).prr;
|
||||
prr = u16(data & 0x0f) << 8 | (prr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2204_device::drrl_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).drr & 0xff;
|
||||
}
|
||||
|
||||
void st2204_device::drrl_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2204 &>(*mintf).drr;
|
||||
drr = data | (drr & 0x0700);
|
||||
}
|
||||
|
||||
u8 st2204_device::drrh_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).drr >> 8;
|
||||
}
|
||||
|
||||
void st2204_device::drrh_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2204 &>(*mintf).drr;
|
||||
drr = u16(data & 0x07) << 8 | (drr & 0x00ff);
|
||||
// 2 Hz, 8 Hz, 64 Hz, 256 Hz, 2048 Hz
|
||||
if (n < 5)
|
||||
return 16384 >> ((n & 1) * 2 + (n >> 1) * 5);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 st2204_device::dmsl_r()
|
||||
@ -388,28 +274,6 @@ void st2204_device::dcnth_w(u8 data)
|
||||
m_dcnth = data & 0x1f;
|
||||
}
|
||||
|
||||
u8 st2204_device::dmrl_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).dmr & 0xff;
|
||||
}
|
||||
|
||||
void st2204_device::dmrl_w(u8 data)
|
||||
{
|
||||
u16 &dmr = downcast<mi_st2204 &>(*mintf).dmr;
|
||||
dmr = data | (dmr & 0x0700);
|
||||
}
|
||||
|
||||
u8 st2204_device::dmrh_r()
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).dmr >> 8;
|
||||
}
|
||||
|
||||
void st2204_device::dmrh_w(u8 data)
|
||||
{
|
||||
u16 &dmr = downcast<mi_st2204 &>(*mintf).dmr;
|
||||
dmr = (data & 0x07) << 8 | (dmr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2204_device::pmem_r(offs_t offset)
|
||||
{
|
||||
return downcast<mi_st2204 &>(*mintf).pread(offset);
|
||||
@ -439,7 +303,7 @@ void st2204_device::int_map(address_map &map)
|
||||
map(0x000e, 0x000e).rw(FUNC(st2204_device::pfd_r), FUNC(st2204_device::pfd_w));
|
||||
map(0x000f, 0x000f).rw(FUNC(st2204_device::pmcr_r), FUNC(st2204_device::pmcr_w));
|
||||
map(0x0020, 0x0020).rw(FUNC(st2204_device::bten_r), FUNC(st2204_device::bten_w));
|
||||
map(0x0021, 0x0021).rw(FUNC(st2204_device::btsr_r), FUNC(st2204_device::btsr_w));
|
||||
map(0x0021, 0x0021).rw(FUNC(st2204_device::btsr_r), FUNC(st2204_device::btclr_all_w));
|
||||
// Source/destination registers are not readable on ST2202, but may be readable here (count register isn't)
|
||||
map(0x0028, 0x0028).rw(FUNC(st2204_device::dmsl_r), FUNC(st2204_device::dmsl_w));
|
||||
map(0x0029, 0x0029).rw(FUNC(st2204_device::dmsh_r), FUNC(st2204_device::dmsh_w));
|
||||
@ -448,7 +312,7 @@ void st2204_device::int_map(address_map &map)
|
||||
map(0x002c, 0x002c).w(FUNC(st2204_device::dcntl_w));
|
||||
map(0x002d, 0x002d).w(FUNC(st2204_device::dcnth_w));
|
||||
map(0x0030, 0x0030).rw(FUNC(st2204_device::sys_r), FUNC(st2204_device::sys_w));
|
||||
map(0x0031, 0x0031).rw(FUNC(st2204_device::irr_r), FUNC(st2204_device::irr_w));
|
||||
map(0x0031, 0x0031).rw(FUNC(st2204_device::irrl_r), FUNC(st2204_device::irrl_w));
|
||||
map(0x0032, 0x0032).rw(FUNC(st2204_device::prrl_r), FUNC(st2204_device::prrl_w));
|
||||
map(0x0033, 0x0033).rw(FUNC(st2204_device::prrh_r), FUNC(st2204_device::prrh_w));
|
||||
map(0x0034, 0x0034).rw(FUNC(st2204_device::drrl_r), FUNC(st2204_device::drrl_w));
|
||||
|
@ -17,11 +17,8 @@ class st2204_device : public st2xxx_device
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
ST_BTEN = ST_LYMAX + 1,
|
||||
ST_BTSR,
|
||||
ST_DMS,
|
||||
ST_DMD,
|
||||
ST_DMR
|
||||
ST_DMS = ST_LYMAX + 1,
|
||||
ST_DMD
|
||||
};
|
||||
|
||||
st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
@ -30,6 +27,12 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual u16 st2xxx_ireq_mask() const override { return 0x0f7f; }
|
||||
virtual const char *st2xxx_irq_name(int i) const override;
|
||||
virtual unsigned st2xxx_bt_divider(int n) const override;
|
||||
virtual u8 st2xxx_sys_mask() const override { return 0xff; }
|
||||
virtual bool st2xxx_has_dma() const override { return true; }
|
||||
|
||||
private:
|
||||
class mi_st2204 : public mi_st2xxx {
|
||||
public:
|
||||
@ -46,34 +49,10 @@ private:
|
||||
u8 dread(u16 adr);
|
||||
u8 dreadc(u16 adr);
|
||||
void dwrite(u16 adr, u8 val);
|
||||
|
||||
bool irr_enable;
|
||||
u8 irr;
|
||||
u16 prr;
|
||||
u16 drr;
|
||||
u16 dmr;
|
||||
};
|
||||
|
||||
template<int N> TIMER_CALLBACK_MEMBER(bt_interrupt);
|
||||
|
||||
u8 sys_r();
|
||||
void sys_w(u8 data);
|
||||
u8 irr_r();
|
||||
void irr_w(u8 data);
|
||||
u8 prrl_r();
|
||||
void prrl_w(u8 data);
|
||||
u8 prrh_r();
|
||||
void prrh_w(u8 data);
|
||||
u8 drrl_r();
|
||||
void drrl_w(u8 data);
|
||||
u8 drrh_r();
|
||||
void drrh_w(u8 data);
|
||||
u8 pmcr_r();
|
||||
void pmcr_w(u8 data);
|
||||
u8 bten_r();
|
||||
void bten_w(u8 data);
|
||||
u8 btsr_r();
|
||||
void btsr_w(u8 data);
|
||||
u8 dmsl_r();
|
||||
void dmsl_w(u8 data);
|
||||
u8 dmsh_r();
|
||||
@ -84,10 +63,6 @@ private:
|
||||
void dmdh_w(u8 data);
|
||||
void dcntl_w(u8 data);
|
||||
void dcnth_w(u8 data);
|
||||
u8 dmrl_r();
|
||||
void dmrl_w(u8 data);
|
||||
u8 dmrh_r();
|
||||
void dmrh_w(u8 data);
|
||||
|
||||
u8 pmem_r(offs_t offset);
|
||||
void pmem_w(offs_t offset, u8 data);
|
||||
@ -96,10 +71,6 @@ private:
|
||||
|
||||
void int_map(address_map &map);
|
||||
|
||||
u8 m_bten;
|
||||
u8 m_btsr;
|
||||
emu_timer *m_base_timer[5];
|
||||
|
||||
u16 m_dms;
|
||||
u16 m_dmd;
|
||||
u8 m_dcnth;
|
||||
|
@ -39,23 +39,12 @@ st2205u_device::st2205u_device(const machine_config &mconfig, const char *tag, d
|
||||
: st2xxx_device(mconfig, ST2205U, tag, owner, clock,
|
||||
address_map_constructor(FUNC(st2205u_device::int_map), this),
|
||||
26, // logical; only 23 address lines are brought out
|
||||
0xdfff)
|
||||
, m_bten(0)
|
||||
, m_btreq(0)
|
||||
true)
|
||||
, m_btc(0)
|
||||
, m_base_timer{0}
|
||||
, m_lvctr(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<int N>
|
||||
TIMER_CALLBACK_MEMBER(st2205u_device::bt_interrupt)
|
||||
{
|
||||
m_btreq |= 1 << N;
|
||||
m_ireq |= 0x0020;
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
void st2205u_device::device_start()
|
||||
{
|
||||
std::unique_ptr<mi_st2205u> intf = std::make_unique<mi_st2205u>();
|
||||
@ -67,51 +56,24 @@ void st2205u_device::device_start()
|
||||
intf->drr = 0;
|
||||
intf->brr = 0;
|
||||
intf->irq_service = false;
|
||||
|
||||
m_base_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<0>), this));
|
||||
m_base_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<1>), this));
|
||||
m_base_timer[2] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<2>), this));
|
||||
m_base_timer[3] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<3>), this));
|
||||
m_base_timer[4] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<4>), this));
|
||||
m_base_timer[5] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<5>), this));
|
||||
m_base_timer[6] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<6>), this));
|
||||
m_base_timer[7] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2205u_device::bt_interrupt<7>), this));
|
||||
|
||||
intf->ram = make_unique_clear<u8[]>(0x8000);
|
||||
|
||||
save_item(NAME(m_pdata));
|
||||
save_item(NAME(m_pctrl));
|
||||
save_item(NAME(m_psel));
|
||||
save_item(NAME(m_pfun));
|
||||
save_item(NAME(m_bten));
|
||||
save_item(NAME(m_btreq));
|
||||
init_base_timer(0x0040);
|
||||
|
||||
save_item(NAME(m_btc));
|
||||
save_item(NAME(m_sys));
|
||||
save_item(NAME(m_pmcr));
|
||||
save_item(NAME(m_ireq));
|
||||
save_item(NAME(m_iena));
|
||||
save_item(NAME(m_lssa));
|
||||
save_item(NAME(m_lvpw));
|
||||
save_item(NAME(m_lxmax));
|
||||
save_item(NAME(m_lymax));
|
||||
save_item(NAME(m_lvctr));
|
||||
save_item(NAME(intf->irr_enable));
|
||||
save_item(NAME(intf->irr));
|
||||
save_item(NAME(intf->prr));
|
||||
save_item(NAME(intf->drr));
|
||||
save_item(NAME(intf->brr));
|
||||
save_item(NAME(intf->irq_service));
|
||||
save_pointer(NAME(intf->ram), 0x8000);
|
||||
|
||||
mintf = std::move(intf);
|
||||
save_common_registers();
|
||||
init();
|
||||
|
||||
state_add(ST_IRR, "IRR", downcast<mi_st2205u &>(*mintf).irr).mask(0x87ff);
|
||||
state_add(ST_PRR, "PRR", downcast<mi_st2205u &>(*mintf).prr).mask(0x87ff);
|
||||
state_add(ST_DRR, "DRR", downcast<mi_st2205u &>(*mintf).drr).mask(0x8fff);
|
||||
state_add(ST_BRR, "BRR", downcast<mi_st2205u &>(*mintf).brr).mask(0x9fff);
|
||||
state_add<u8>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(m_ireq_mask);
|
||||
state_add<u8>(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(m_ireq_mask);
|
||||
state_add<u16>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(st2xxx_ireq_mask());
|
||||
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 < 6; i++)
|
||||
{
|
||||
state_add(ST_PDA + i, string_format("PD%c", 'A' + i).c_str(), m_pdata[i]);
|
||||
@ -126,7 +88,7 @@ void st2205u_device::device_start()
|
||||
state_add(ST_PMCR, "PMCR", m_pmcr);
|
||||
state_add<u8>(ST_SYS, "SYS", [this]() { return m_sys; }, [this](u8 data) { sys_w(data); }).mask(0xfe);
|
||||
state_add<u8>(ST_BTEN, "BTEN", [this]() { return m_bten; }, [this](u8 data) { bten_w(data); });
|
||||
state_add(ST_BTREQ, "BTREQ", m_btreq);
|
||||
state_add(ST_BTSR, "BTREQ", m_btsr);
|
||||
state_add(ST_BTC, "BTC", m_btc);
|
||||
state_add(ST_LSSA, "LSSA", m_lssa);
|
||||
state_add(ST_LVPW, "LVPW", m_lvpw);
|
||||
@ -139,22 +101,39 @@ void st2205u_device::device_reset()
|
||||
{
|
||||
st2xxx_device::device_reset();
|
||||
|
||||
mi_st2205u &m = downcast<mi_st2205u &>(*mintf);
|
||||
m.irr_enable = false;
|
||||
m.irr = 0;
|
||||
m.prr = 0;
|
||||
m.drr = 0;
|
||||
downcast<mi_st2205u &>(*mintf).brr = 0;
|
||||
|
||||
bten_w(0);
|
||||
m_btreq = 0;
|
||||
m_btc = 0;
|
||||
|
||||
m_lvctr = 0;
|
||||
}
|
||||
|
||||
const char *st2205u_device::st2xxx_irq_name(int i) const
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: return "PE0/1/2 edge";
|
||||
case 1: return "Timer 0";
|
||||
case 2: return "Timer 1";
|
||||
case 3: return "Timer 2";
|
||||
case 4: return "Timer 3";
|
||||
case 5: return "PA transition";
|
||||
case 6: return "Base timer";
|
||||
case 7: return "LCD buffer";
|
||||
case 8: return "SPI TX empty";
|
||||
case 9: return "SPI RX ready";
|
||||
case 10: return "UART TX";
|
||||
case 11: return "UART RX";
|
||||
case 12: return "USB";
|
||||
case 14: return "PCM";
|
||||
case 15: return "RTC";
|
||||
default: return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
u8 st2205u_device::mi_st2205u::pread(u16 adr)
|
||||
{
|
||||
u16 bank = irq_service ? irr : prr;
|
||||
u16 bank = irq_service && irr_enable ? irr : prr;
|
||||
if (BIT(bank, 15))
|
||||
return ram[0x4000 | (adr & 0x3fff)];
|
||||
else
|
||||
@ -163,7 +142,7 @@ u8 st2205u_device::mi_st2205u::pread(u16 adr)
|
||||
|
||||
u8 st2205u_device::mi_st2205u::preadc(u16 adr)
|
||||
{
|
||||
u16 bank = irq_service ? irr : prr;
|
||||
u16 bank = irq_service && irr_enable ? irr : prr;
|
||||
if (BIT(bank, 15))
|
||||
return ram[0x4000 | (adr & 0x3fff)];
|
||||
else
|
||||
@ -172,7 +151,7 @@ u8 st2205u_device::mi_st2205u::preadc(u16 adr)
|
||||
|
||||
void st2205u_device::mi_st2205u::pwrite(u16 adr, u8 val)
|
||||
{
|
||||
u16 bank = irq_service ? irr : prr;
|
||||
u16 bank = irq_service && irr_enable ? irr : prr;
|
||||
if (BIT(bank, 15))
|
||||
ram[0x4000 | (adr & 0x3fff)] = val;
|
||||
else
|
||||
@ -252,72 +231,6 @@ void st2205u_device::mi_st2205u::write(u16 adr, u8 val)
|
||||
program->write_byte(adr, val);
|
||||
}
|
||||
|
||||
u8 st2205u_device::irrl_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).irr & 0xff;
|
||||
}
|
||||
|
||||
void st2205u_device::irrl_w(u8 data)
|
||||
{
|
||||
u16 &irr = downcast<mi_st2205u &>(*mintf).irr;
|
||||
irr = data | (irr & 0x8f00);
|
||||
}
|
||||
|
||||
u8 st2205u_device::irrh_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).irr >> 8;
|
||||
}
|
||||
|
||||
void st2205u_device::irrh_w(u8 data)
|
||||
{
|
||||
u16 &irr = downcast<mi_st2205u &>(*mintf).irr;
|
||||
irr = (data & 0x8f) << 8 | (irr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2205u_device::prrl_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).prr & 0xff;
|
||||
}
|
||||
|
||||
void st2205u_device::prrl_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2205u &>(*mintf).prr;
|
||||
prr = data | (prr & 0x8f00);
|
||||
}
|
||||
|
||||
u8 st2205u_device::prrh_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).prr >> 8;
|
||||
}
|
||||
|
||||
void st2205u_device::prrh_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2205u &>(*mintf).prr;
|
||||
prr = (data & 0x8f) << 8 | (prr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2205u_device::drrl_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).drr & 0xff;
|
||||
}
|
||||
|
||||
void st2205u_device::drrl_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2205u &>(*mintf).drr;
|
||||
drr = data | (drr & 0x8700);
|
||||
}
|
||||
|
||||
u8 st2205u_device::drrh_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).drr >> 8;
|
||||
}
|
||||
|
||||
void st2205u_device::drrh_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2205u &>(*mintf).drr;
|
||||
drr = (data & 0x87) << 8 | (drr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2205u_device::brrl_r()
|
||||
{
|
||||
return downcast<mi_st2205u &>(*mintf).brr & 0xff;
|
||||
@ -350,61 +263,23 @@ void st2205u_device::pmcr_w(u8 data)
|
||||
m_pmcr = data;
|
||||
}
|
||||
|
||||
u8 st2205u_device::sys_r()
|
||||
unsigned st2205u_device::st2xxx_bt_divider(int n) const
|
||||
{
|
||||
return m_sys;
|
||||
}
|
||||
// 2 Hz
|
||||
if (n == 0)
|
||||
return 16384;
|
||||
|
||||
void st2205u_device::sys_w(u8 data)
|
||||
{
|
||||
m_sys = data & 0xfe;
|
||||
downcast<mi_st2205u &>(*mintf).irr_enable = BIT(data, 1);
|
||||
}
|
||||
// 32 Hz, 64 Hz, 128 Hz, 256 Hz, 512 Hz
|
||||
if (n <= 5)
|
||||
return 2048 >> n;
|
||||
|
||||
u8 st2205u_device::bten_r()
|
||||
{
|
||||
return m_bten;
|
||||
}
|
||||
// 2048 Hz
|
||||
if (n == 6)
|
||||
return 16;
|
||||
|
||||
void st2205u_device::bten_w(u8 data)
|
||||
{
|
||||
if (BIT(data, 0) && !BIT(m_bten, 0))
|
||||
m_base_timer[0]->adjust(attotime::from_hz(2), 0, attotime::from_hz(2));
|
||||
else if (!BIT(data, 0) && BIT(m_bten, 0))
|
||||
m_base_timer[0]->adjust(attotime::never);
|
||||
|
||||
for (int n = 1; n <= 5; n++)
|
||||
{
|
||||
if (BIT(data, n) && !BIT(m_bten, n))
|
||||
m_base_timer[n]->adjust(attotime::from_hz(16 << n), 0, attotime::from_hz(16 << n));
|
||||
else if (!BIT(data, n) && BIT(m_bten, n))
|
||||
m_base_timer[n]->adjust(attotime::never);
|
||||
}
|
||||
|
||||
if (BIT(data, 6) && !BIT(m_bten, 6))
|
||||
m_base_timer[6]->adjust(attotime::from_hz(2048), 0, attotime::from_hz(2048));
|
||||
else if (!BIT(data, 6) && BIT(m_bten, 6))
|
||||
m_base_timer[6]->adjust(attotime::never);
|
||||
|
||||
if (BIT(data, 7) && !BIT(m_bten, 7))
|
||||
{
|
||||
attotime period = attotime::from_hz(8192) * (m_btc ? m_btc : 256);
|
||||
m_base_timer[7]->adjust(period, 0, period);
|
||||
}
|
||||
else if (!BIT(data, 7) && BIT(m_bten, 7))
|
||||
m_base_timer[7]->adjust(attotime::never);
|
||||
|
||||
m_bten = data;
|
||||
}
|
||||
|
||||
u8 st2205u_device::btreq_r()
|
||||
{
|
||||
return m_btreq;
|
||||
}
|
||||
|
||||
void st2205u_device::btclr_w(u8 data)
|
||||
{
|
||||
m_btreq &= ~data;
|
||||
// 8192 Hz / BTC
|
||||
assert(n == 7);
|
||||
return 4 * (m_btc != 0 ? m_btc : 256);
|
||||
}
|
||||
|
||||
u8 st2205u_device::btc_r()
|
||||
@ -476,7 +351,7 @@ void st2205u_device::int_map(address_map &map)
|
||||
map(0x000e, 0x000e).rw(FUNC(st2205u_device::pfc_r), FUNC(st2205u_device::pfc_w));
|
||||
map(0x000f, 0x000f).rw(FUNC(st2205u_device::pfd_r), FUNC(st2205u_device::pfd_w));
|
||||
map(0x002a, 0x002a).rw(FUNC(st2205u_device::bten_r), FUNC(st2205u_device::bten_w));
|
||||
map(0x002b, 0x002b).rw(FUNC(st2205u_device::btreq_r), FUNC(st2205u_device::btclr_w));
|
||||
map(0x002b, 0x002b).rw(FUNC(st2205u_device::btsr_r), FUNC(st2205u_device::btclr_w));
|
||||
map(0x002c, 0x002c).rw(FUNC(st2205u_device::btc_r), FUNC(st2205u_device::btc_w));
|
||||
map(0x0030, 0x0030).rw(FUNC(st2205u_device::irrl_r), FUNC(st2205u_device::irrl_w));
|
||||
map(0x0031, 0x0031).rw(FUNC(st2205u_device::irrh_r), FUNC(st2205u_device::irrh_w));
|
||||
@ -500,6 +375,8 @@ void st2205u_device::int_map(address_map &map)
|
||||
map(0x004e, 0x004e).rw(FUNC(st2205u_device::pl_r), FUNC(st2205u_device::pl_w));
|
||||
map(0x004f, 0x004f).rw(FUNC(st2205u_device::pcl_r), FUNC(st2205u_device::pcl_w));
|
||||
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(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));
|
||||
|
@ -17,9 +17,7 @@ class st2205u_device : public st2xxx_device
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
ST_BTEN = ST_LYMAX + 1,
|
||||
ST_BTREQ,
|
||||
ST_BTC,
|
||||
ST_BTC = ST_LYMAX + 1,
|
||||
ST_BRR,
|
||||
ST_LVCTR
|
||||
};
|
||||
@ -30,6 +28,12 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual u16 st2xxx_ireq_mask() const override { return 0xdfff; }
|
||||
virtual const char *st2xxx_irq_name(int i) const override;
|
||||
virtual unsigned st2xxx_bt_divider(int n) const override;
|
||||
virtual u8 st2xxx_sys_mask() const override { return 0xfe; }
|
||||
virtual bool st2xxx_has_dma() const override { return true; }
|
||||
|
||||
private:
|
||||
class mi_st2205u : public mi_st2xxx {
|
||||
public:
|
||||
@ -49,10 +53,6 @@ private:
|
||||
u8 breadc(u16 adr);
|
||||
void bwrite(u16 adr, u8 val);
|
||||
|
||||
bool irr_enable;
|
||||
u16 irr;
|
||||
u16 prr;
|
||||
u16 drr;
|
||||
u16 brr;
|
||||
|
||||
std::unique_ptr<u8[]> ram;
|
||||
@ -60,30 +60,12 @@ private:
|
||||
|
||||
template<int N> TIMER_CALLBACK_MEMBER(bt_interrupt);
|
||||
|
||||
u8 irrl_r();
|
||||
void irrl_w(u8 data);
|
||||
u8 irrh_r();
|
||||
void irrh_w(u8 data);
|
||||
u8 prrl_r();
|
||||
void prrl_w(u8 data);
|
||||
u8 prrh_r();
|
||||
void prrh_w(u8 data);
|
||||
u8 drrl_r();
|
||||
void drrl_w(u8 data);
|
||||
u8 drrh_r();
|
||||
void drrh_w(u8 data);
|
||||
u8 brrl_r();
|
||||
void brrl_w(u8 data);
|
||||
u8 brrh_r();
|
||||
void brrh_w(u8 data);
|
||||
u8 sys_r();
|
||||
void sys_w(u8 data);
|
||||
u8 pmcr_r();
|
||||
void pmcr_w(u8 data);
|
||||
u8 bten_r();
|
||||
void bten_w(u8 data);
|
||||
u8 btreq_r();
|
||||
void btclr_w(u8 data);
|
||||
u8 btc_r();
|
||||
void btc_w(u8 data);
|
||||
u8 lvctr_r();
|
||||
@ -100,10 +82,7 @@ private:
|
||||
|
||||
void int_map(address_map &map);
|
||||
|
||||
u8 m_bten;
|
||||
u8 m_btreq;
|
||||
u8 m_btc;
|
||||
emu_timer *m_base_timer[8];
|
||||
u8 m_lvctr;
|
||||
};
|
||||
|
||||
|
@ -28,20 +28,34 @@
|
||||
#include "emu.h"
|
||||
#include "st2xxx.h"
|
||||
|
||||
st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, u16 ireq_mask)
|
||||
#define LOG_IRQ (1 << 1U)
|
||||
#define LOG_BT (1 << 2U)
|
||||
//#define VERBOSE (LOG_IRQ | LOG_BT)
|
||||
#include "logmacro.h"
|
||||
|
||||
st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram)
|
||||
: r65c02_device(mconfig, type, tag, owner, clock)
|
||||
, m_data_config("data", ENDIANNESS_LITTLE, 8, data_bits, 0)
|
||||
, m_in_port_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
|
||||
, m_out_port_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
|
||||
, m_prr_mask(data_bits <= 14 ? 0 : ((u16(1) << (data_bits - 14)) - 1) | (has_banked_ram ? 0x8000 : 0))
|
||||
, m_drr_mask(data_bits <= 15 ? 0 : ((u16(1) << (data_bits - 15)) - 1) | (has_banked_ram ? 0x8000 : 0))
|
||||
, m_pdata{0}
|
||||
, m_pctrl{0}
|
||||
, m_psel{0}
|
||||
, m_pfun{0}
|
||||
, m_pmcr(0)
|
||||
, m_bten(0)
|
||||
, m_btsr(0)
|
||||
, m_bt_mask(0)
|
||||
, m_bt_ireq(0)
|
||||
, m_sys(0)
|
||||
, m_ireq(0)
|
||||
, m_iena(0)
|
||||
, m_ireq_mask(ireq_mask)
|
||||
, m_sys(0)
|
||||
, m_lssa(0)
|
||||
, m_lvpw(0)
|
||||
, m_lxmax(0)
|
||||
, m_lymax(0)
|
||||
{
|
||||
program_config.m_internal_map = std::move(internal_map);
|
||||
}
|
||||
@ -62,6 +76,81 @@ void st2xxx_device::device_resolve_objects()
|
||||
cb.resolve_safe();
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(st2xxx_device::bt_interrupt)
|
||||
{
|
||||
// BTSR must be cleared each time the interrupt is serviced
|
||||
bool interrupt = (m_btsr == 0);
|
||||
|
||||
m_btsr |= 1 << param;
|
||||
|
||||
unsigned div = st2xxx_bt_divider(param);
|
||||
assert(div != 0);
|
||||
m_base_timer[param]->adjust(attotime::from_ticks(32768, div), param);
|
||||
|
||||
if (interrupt)
|
||||
{
|
||||
LOGMASKED(LOG_BT, "Interrupt caused by %.1f Hz base timer\n", 32768.0 / div);
|
||||
m_ireq |= m_bt_ireq;
|
||||
update_irq_state();
|
||||
}
|
||||
}
|
||||
|
||||
void st2xxx_device::init_base_timer(u16 ireq)
|
||||
{
|
||||
m_bt_ireq = ireq;
|
||||
|
||||
for (int n = 0; n < 8; n++)
|
||||
{
|
||||
if (st2xxx_bt_divider(n) != 0)
|
||||
{
|
||||
m_bt_mask |= 1 << n;
|
||||
m_base_timer[n] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(st2xxx_device::bt_interrupt), this));
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_bt_mask != 0);
|
||||
assert(m_bt_ireq != 0);
|
||||
}
|
||||
|
||||
void st2xxx_device::save_common_registers()
|
||||
{
|
||||
mi_st2xxx *intf = downcast<mi_st2xxx *>(mintf.get());
|
||||
|
||||
save_item(NAME(m_pdata));
|
||||
save_item(NAME(m_pctrl));
|
||||
save_item(NAME(m_psel));
|
||||
save_item(NAME(m_pfun));
|
||||
save_item(NAME(m_pmcr));
|
||||
if (m_prr_mask != 0)
|
||||
{
|
||||
if (BIT(st2xxx_sys_mask(), 1))
|
||||
{
|
||||
save_item(NAME(intf->irq_service));
|
||||
save_item(NAME(intf->irr_enable));
|
||||
save_item(NAME(intf->irr));
|
||||
}
|
||||
save_item(NAME(intf->prr));
|
||||
}
|
||||
if (m_drr_mask != 0)
|
||||
{
|
||||
save_item(NAME(intf->drr));
|
||||
if (st2xxx_has_dma())
|
||||
save_item(NAME(intf->dmr));
|
||||
}
|
||||
if (m_bt_mask != 0)
|
||||
{
|
||||
save_item(NAME(m_bten));
|
||||
save_item(NAME(m_btsr));
|
||||
}
|
||||
save_item(NAME(m_sys));
|
||||
save_item(NAME(m_ireq));
|
||||
save_item(NAME(m_iena));
|
||||
save_item(NAME(m_lssa));
|
||||
save_item(NAME(m_lvpw));
|
||||
save_item(NAME(m_lxmax));
|
||||
save_item(NAME(m_lymax));
|
||||
}
|
||||
|
||||
void st2xxx_device::device_reset()
|
||||
{
|
||||
m6502_device::device_reset();
|
||||
@ -75,11 +164,23 @@ void st2xxx_device::device_reset()
|
||||
cb(0xff);
|
||||
m_pmcr = 0x80;
|
||||
|
||||
// reset bank registers
|
||||
mi_st2xxx &m = downcast<mi_st2xxx &>(*mintf);
|
||||
m.irr_enable = false;
|
||||
m.irr = 0;
|
||||
m.prr = 0;
|
||||
m.drr = 0;
|
||||
m.dmr = 0;
|
||||
|
||||
// reset interrupt registers
|
||||
m_ireq = 0;
|
||||
m_iena = 0;
|
||||
update_irq_state();
|
||||
|
||||
// reset base timer
|
||||
bten_w(0);
|
||||
m_btsr = 0;
|
||||
|
||||
// reset miscellaneous registers
|
||||
m_sys = 0;
|
||||
|
||||
@ -93,19 +194,15 @@ void st2xxx_device::device_reset()
|
||||
u8 st2xxx_device::acknowledge_irq()
|
||||
{
|
||||
// IREQH interrupts have priority over IREQL interrupts
|
||||
for (int level = 8; level < 16; level++)
|
||||
{
|
||||
if (BIT(m_ireq & m_iena, level))
|
||||
{
|
||||
m_ireq &= ~(1 << level);
|
||||
update_irq_state();
|
||||
return level;
|
||||
}
|
||||
}
|
||||
for (int level = 0; level < 8; level++)
|
||||
for (int pri = 0; pri < 16; pri++)
|
||||
{
|
||||
int level = pri ^ 8;
|
||||
if (BIT(m_ireq & m_iena, level))
|
||||
{
|
||||
LOGMASKED(LOG_IRQ, "%s interrupt acknowledged (PC = $%04X, vector = $%04X)\n",
|
||||
st2xxx_irq_name(level),
|
||||
PPC,
|
||||
0x7ff8 - (level << 1));
|
||||
m_ireq &= ~(1 << level);
|
||||
update_irq_state();
|
||||
return level;
|
||||
@ -207,6 +304,154 @@ void st2xxx_device::pcl_w(u8 data)
|
||||
pctrl_w(6, data);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::bten_r()
|
||||
{
|
||||
return m_bten;
|
||||
}
|
||||
|
||||
void st2xxx_device::bten_w(u8 data)
|
||||
{
|
||||
data &= m_bt_mask;
|
||||
|
||||
for (int n = 0; n < 8; n++)
|
||||
{
|
||||
if (BIT(data, n) && !BIT(m_bten, n))
|
||||
{
|
||||
unsigned div = st2xxx_bt_divider(n);
|
||||
assert(div != 0);
|
||||
assert(m_base_timer[n] != nullptr);
|
||||
m_base_timer[n]->adjust(attotime::from_ticks(32768, div), n);
|
||||
LOGMASKED(LOG_BT, "Base timer %d enabled at %.1f Hz (PC = $%04X)\n", n, 32768.0 / div, PPC);
|
||||
}
|
||||
else if (!BIT(data, n) && BIT(m_bten, n))
|
||||
{
|
||||
m_base_timer[n]->adjust(attotime::never);
|
||||
LOGMASKED(LOG_BT, "Base timer %d disabled (PC = $%04X)\n", n, PPC);
|
||||
}
|
||||
}
|
||||
|
||||
m_bten = data;
|
||||
}
|
||||
|
||||
u8 st2xxx_device::btsr_r()
|
||||
{
|
||||
return m_btsr;
|
||||
}
|
||||
|
||||
void st2xxx_device::btclr_w(u8 data)
|
||||
{
|
||||
// Write 1 to clear each individual bit
|
||||
m_btsr &= ~data;
|
||||
}
|
||||
|
||||
void st2xxx_device::btclr_all_w(u8 data)
|
||||
{
|
||||
// Only bit 7 has any effect
|
||||
if (BIT(data, 7))
|
||||
m_btsr = 0;
|
||||
}
|
||||
|
||||
u8 st2xxx_device::sys_r()
|
||||
{
|
||||
return m_sys | 0x01;
|
||||
}
|
||||
|
||||
void st2xxx_device::sys_w(u8 data)
|
||||
{
|
||||
u8 mask = st2xxx_sys_mask();
|
||||
m_sys = data & mask;
|
||||
if (BIT(mask, 1))
|
||||
downcast<mi_st2xxx &>(*mintf).irr_enable = BIT(data, 1);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::irrl_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).irr & 0xff;
|
||||
}
|
||||
|
||||
void st2xxx_device::irrl_w(u8 data)
|
||||
{
|
||||
u16 &irr = downcast<mi_st2xxx &>(*mintf).irr;
|
||||
irr = (data & m_prr_mask) | (irr & 0xff00);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::irrh_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).irr >> 8;
|
||||
}
|
||||
|
||||
void st2xxx_device::irrh_w(u8 data)
|
||||
{
|
||||
u16 &irr = downcast<mi_st2xxx &>(*mintf).irr;
|
||||
irr = ((u16(data) << 8) & m_prr_mask) | (irr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::prrl_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).prr & 0xff;
|
||||
}
|
||||
|
||||
void st2xxx_device::prrl_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2xxx &>(*mintf).prr;
|
||||
prr = (data & m_prr_mask) | (prr & 0xff00);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::prrh_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).prr >> 8;
|
||||
}
|
||||
|
||||
void st2xxx_device::prrh_w(u8 data)
|
||||
{
|
||||
u16 &prr = downcast<mi_st2xxx &>(*mintf).prr;
|
||||
prr = ((u16(data) << 8) & m_prr_mask) | (prr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::drrl_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).drr & 0xff;
|
||||
}
|
||||
|
||||
void st2xxx_device::drrl_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2xxx &>(*mintf).drr;
|
||||
drr = (data & m_drr_mask) | (drr & 0xff00);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::drrh_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).drr >> 8;
|
||||
}
|
||||
|
||||
void st2xxx_device::drrh_w(u8 data)
|
||||
{
|
||||
u16 &drr = downcast<mi_st2xxx &>(*mintf).drr;
|
||||
drr = ((u16(data) << 8) & m_drr_mask) | (drr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::dmrl_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).dmr & 0xff;
|
||||
}
|
||||
|
||||
void st2xxx_device::dmrl_w(u8 data)
|
||||
{
|
||||
u16 &dmr = downcast<mi_st2xxx &>(*mintf).dmr;
|
||||
dmr = (data & m_drr_mask) | (dmr & 0xff00);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::dmrh_r()
|
||||
{
|
||||
return downcast<mi_st2xxx &>(*mintf).dmr >> 8;
|
||||
}
|
||||
|
||||
void st2xxx_device::dmrh_w(u8 data)
|
||||
{
|
||||
u16 &dmr = downcast<mi_st2xxx &>(*mintf).dmr;
|
||||
dmr = ((u16(data) << 8) & m_drr_mask) | (dmr & 0x00ff);
|
||||
}
|
||||
|
||||
u8 st2xxx_device::ireql_r()
|
||||
{
|
||||
return m_ireq & 0x00ff;
|
||||
@ -216,6 +461,11 @@ void st2xxx_device::ireql_w(u8 data)
|
||||
{
|
||||
if ((m_ireq & ~data & 0x00ff) != 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!BIT(data, i) && BIT(m_ireq, i))
|
||||
LOGMASKED(LOG_IRQ, "%s interrupt cleared (PC = $%04X)\n", st2xxx_irq_name(i), PPC);
|
||||
}
|
||||
m_ireq &= data | 0xff00;
|
||||
update_irq_state();
|
||||
}
|
||||
@ -230,6 +480,11 @@ void st2xxx_device::ireqh_w(u8 data)
|
||||
{
|
||||
if ((m_ireq & ~(u16(data) << 8) & 0xff00) != 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (!BIT(data, i) && BIT(m_ireq, i + 8))
|
||||
LOGMASKED(LOG_IRQ, "%s interrupt cleared (PC = $%04X)\n", st2xxx_irq_name(i + 8), PPC);
|
||||
}
|
||||
m_ireq &= u16(data) << 8 | 0x00ff;
|
||||
update_irq_state();
|
||||
}
|
||||
@ -242,8 +497,20 @@ u8 st2xxx_device::ienal_r()
|
||||
|
||||
void st2xxx_device::ienal_w(u8 data)
|
||||
{
|
||||
m_iena = (m_iena & 0xff00) | (data & m_ireq_mask);
|
||||
update_irq_state();
|
||||
data &= st2xxx_ireq_mask();
|
||||
if (data != (m_iena & 0x00ff))
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (BIT(data, i) != BIT(m_iena, i))
|
||||
LOGMASKED(LOG_IRQ, "%s interrupt %sabled (PC = $%04X)\n",
|
||||
st2xxx_irq_name(i),
|
||||
BIT(data, i) ? "en" : "dis",
|
||||
PPC);
|
||||
}
|
||||
m_iena = (m_iena & 0xff00) | data;
|
||||
update_irq_state();
|
||||
}
|
||||
}
|
||||
|
||||
u8 st2xxx_device::ienah_r()
|
||||
@ -253,8 +520,20 @@ u8 st2xxx_device::ienah_r()
|
||||
|
||||
void st2xxx_device::ienah_w(u8 data)
|
||||
{
|
||||
m_iena = (m_iena & 0x00ff) | ((u16(data) << 8) & m_ireq_mask);
|
||||
update_irq_state();
|
||||
data &= st2xxx_ireq_mask() >> 8;
|
||||
if (data != (m_iena >> 8))
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (BIT(data, i) != BIT(m_iena, i + 8))
|
||||
LOGMASKED(LOG_IRQ, "%s interrupt %sabled (PC = $%04X)\n",
|
||||
st2xxx_irq_name(i + 8),
|
||||
BIT(data, i) ? "en" : "dis",
|
||||
PPC);
|
||||
}
|
||||
m_iena = (m_iena & 0x00ff) | (u16(data) << 8);
|
||||
update_irq_state();
|
||||
}
|
||||
}
|
||||
|
||||
void st2xxx_device::lssal_w(u8 data)
|
||||
|
@ -32,10 +32,13 @@ public:
|
||||
ST_PFC,
|
||||
ST_PFD,
|
||||
ST_PMCR,
|
||||
ST_BTEN,
|
||||
ST_BTSR,
|
||||
ST_SYS,
|
||||
ST_IRR,
|
||||
ST_PRR,
|
||||
ST_DRR,
|
||||
ST_DMR,
|
||||
ST_IREQ,
|
||||
ST_IENA,
|
||||
ST_LSSA,
|
||||
@ -60,7 +63,7 @@ public:
|
||||
auto out_pl_callback() { return m_out_port_cb[6].bind(); }
|
||||
|
||||
protected:
|
||||
st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, u16 ireq_mask);
|
||||
st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, bool has_banked_ram);
|
||||
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
virtual void device_resolve_objects() override;
|
||||
@ -69,21 +72,38 @@ protected:
|
||||
virtual void do_exec_full() override;
|
||||
virtual void do_exec_partial() override;
|
||||
|
||||
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_sys_mask() const = 0;
|
||||
virtual bool st2xxx_has_dma() const { return false; }
|
||||
|
||||
class mi_st2xxx : public memory_interface {
|
||||
public:
|
||||
virtual u8 read_vector(u16 adr) = 0;
|
||||
|
||||
address_space *data;
|
||||
memory_access_cache<0, 0, ENDIANNESS_LITTLE> *dcache;
|
||||
|
||||
bool irq_service;
|
||||
bool irr_enable;
|
||||
u16 irr;
|
||||
u16 prr;
|
||||
u16 drr;
|
||||
u16 dmr;
|
||||
};
|
||||
|
||||
void init_base_timer(u16 ireq);
|
||||
void save_common_registers();
|
||||
|
||||
u8 read_vector(u16 adr) { return downcast<mi_st2xxx &>(*mintf).read_vector(adr); }
|
||||
void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; }
|
||||
|
||||
void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; }
|
||||
u8 acknowledge_irq();
|
||||
|
||||
TIMER_CALLBACK_MEMBER(bt_interrupt);
|
||||
|
||||
u8 pdata_r(offs_t offset);
|
||||
void pdata_w(offs_t offset, u8 data);
|
||||
u8 pctrl_r(offs_t offset);
|
||||
@ -101,6 +121,32 @@ protected:
|
||||
u8 pfd_r();
|
||||
void pfd_w(u8 data);
|
||||
|
||||
u8 sys_r();
|
||||
void sys_w(u8 data);
|
||||
|
||||
u8 irrl_r();
|
||||
void irrl_w(u8 data);
|
||||
u8 irrh_r();
|
||||
void irrh_w(u8 data);
|
||||
u8 prrl_r();
|
||||
void prrl_w(u8 data);
|
||||
u8 prrh_r();
|
||||
void prrh_w(u8 data);
|
||||
u8 drrl_r();
|
||||
void drrl_w(u8 data);
|
||||
u8 drrh_r();
|
||||
void drrh_w(u8 data);
|
||||
u8 dmrl_r();
|
||||
void dmrl_w(u8 data);
|
||||
u8 dmrh_r();
|
||||
void dmrh_w(u8 data);
|
||||
|
||||
u8 bten_r();
|
||||
void bten_w(u8 data);
|
||||
u8 btsr_r();
|
||||
void btclr_w(u8 data);
|
||||
void btclr_all_w(u8 data);
|
||||
|
||||
u8 ireql_r();
|
||||
void ireql_w(u8 data);
|
||||
u8 ireqh_r();
|
||||
@ -131,15 +177,22 @@ protected:
|
||||
devcb_read8 m_in_port_cb[7];
|
||||
devcb_write8 m_out_port_cb[7];
|
||||
|
||||
const u16 m_prr_mask;
|
||||
const u16 m_drr_mask;
|
||||
|
||||
u8 m_pdata[7];
|
||||
u8 m_pctrl[7];
|
||||
u8 m_psel[7];
|
||||
u8 m_pfun[2];
|
||||
u8 m_pmcr;
|
||||
u8 m_bten;
|
||||
u8 m_btsr;
|
||||
emu_timer *m_base_timer[8];
|
||||
u8 m_bt_mask;
|
||||
u16 m_bt_ireq;
|
||||
u8 m_sys;
|
||||
u16 m_ireq;
|
||||
u16 m_iena;
|
||||
const u16 m_ireq_mask;
|
||||
u8 m_sys;
|
||||
u16 m_lssa;
|
||||
u8 m_lvpw;
|
||||
u8 m_lxmax;
|
||||
|
Loading…
Reference in New Issue
Block a user