st2xxx: Add base timers and some of the LCD registers; fix IRR enable (nw)

This commit is contained in:
AJR 2019-11-03 16:31:47 -05:00
parent 2435f3cfed
commit ed087f295e
7 changed files with 271 additions and 5 deletions

View File

@ -35,9 +35,20 @@ st2204_device::st2204_device(const machine_config &mconfig, const char *tag, dev
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}
{
}
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>();
@ -49,14 +60,26 @@ void st2204_device::device_start()
intf->drr = 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));
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_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));
@ -83,7 +106,13 @@ void st2204_device::device_start()
state_add(ST_PDL, "PDL", m_pdata[6]);
state_add(ST_PCL, "PCL", m_pctrl[6]);
state_add(ST_PMCR, "PMCR", m_pmcr);
state_add<u8>(ST_BTEN, "BTEN", [this]() { return m_bten; }, [this](u8 data) { bten_w(data); }).mask(0x1f);
state_add(ST_BTSR, "BTSR", m_btsr).mask(0x1f);
state_add<u8>(ST_SYS, "SYS", [this]() { return m_sys; }, [this](u8 data) { sys_w(data); });
state_add(ST_LSSA, "LSSA", m_lssa);
state_add(ST_LVPW, "LVPW", m_lvpw);
state_add(ST_LXMAX, "LXMAX", m_lxmax);
state_add(ST_LYMAX, "LYMAX", m_lymax);
}
void st2204_device::device_reset()
@ -95,6 +124,9 @@ void st2204_device::device_reset()
m.irr = 0;
m.prr = 0;
m.drr = 0;
bten_w(0);
m_btsr = 0;
}
u8 st2204_device::mi_st2204::pread(u16 adr)
@ -165,6 +197,40 @@ void st2204_device::pmcr_w(u8 data)
m_pmcr = data;
}
u8 st2204_device::bten_r()
{
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;
@ -173,7 +239,7 @@ u8 st2204_device::sys_r()
void st2204_device::sys_w(u8 data)
{
m_sys = data;
downcast<mi_st2204 &>(*mintf).irr_enable = BIT(data, 2);
downcast<mi_st2204 &>(*mintf).irr_enable = BIT(data, 1);
}
u8 st2204_device::irr_r()
@ -258,6 +324,8 @@ void st2204_device::int_map(address_map &map)
map(0x000d, 0x000d).rw(FUNC(st2204_device::pfc_r), FUNC(st2204_device::pfc_w));
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(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(0x0032, 0x0032).rw(FUNC(st2204_device::prrl_r), FUNC(st2204_device::prrl_w));
@ -268,6 +336,11 @@ void st2204_device::int_map(address_map &map)
map(0x003d, 0x003d).rw(FUNC(st2204_device::ireqh_r), FUNC(st2204_device::ireqh_w));
map(0x003e, 0x003e).rw(FUNC(st2204_device::ienal_r), FUNC(st2204_device::ienal_w));
map(0x003f, 0x003f).rw(FUNC(st2204_device::ienah_r), FUNC(st2204_device::ienah_w));
map(0x0040, 0x0040).w(FUNC(st2204_device::lssal_w));
map(0x0041, 0x0041).w(FUNC(st2204_device::lssah_w));
map(0x0042, 0x0042).w(FUNC(st2204_device::lvpw_w));
map(0x0043, 0x0043).rw(FUNC(st2204_device::lxmax_r), FUNC(st2204_device::lxmax_w));
map(0x0044, 0x0044).rw(FUNC(st2204_device::lymax_r), FUNC(st2204_device::lymax_w));
map(0x004c, 0x004c).rw(FUNC(st2204_device::pl_r), FUNC(st2204_device::pl_w));
map(0x004e, 0x004e).w(FUNC(st2204_device::pcl_w));
map(0x0080, 0x27ff).ram(); // 10K internal SRAM; extent of mapping guessed

View File

@ -16,6 +16,11 @@
class st2204_device : public st2xxx_device
{
public:
enum {
ST_BTEN = ST_LYMAX + 1,
ST_BTSR
};
st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
@ -44,6 +49,8 @@ private:
u16 drr;
};
template<int N> TIMER_CALLBACK_MEMBER(bt_interrupt);
u8 sys_r();
void sys_w(u8 data);
u8 irr_r();
@ -58,6 +65,10 @@ private:
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 pmem_r(offs_t offset);
void pmem_w(offs_t offset, u8 data);
@ -65,6 +76,10 @@ private:
void dmem_w(offs_t offset, u8 data);
void int_map(address_map &map);
u8 m_bten;
u8 m_btsr;
emu_timer *m_base_timer[5];
};
DECLARE_DEVICE_TYPE(ST2204, st2204_device)

View File

@ -36,10 +36,22 @@ st2205u_device::st2205u_device(const machine_config &mconfig, const char *tag, d
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)
, 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>();
@ -52,16 +64,32 @@ void st2205u_device::device_start()
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));
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));
@ -93,6 +121,13 @@ void st2205u_device::device_start()
state_add(ST_PCL, "PCL", m_pctrl[6]);
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_BTC, "BTC", m_btc);
state_add(ST_LSSA, "LSSA", m_lssa);
state_add(ST_LVPW, "LVPW", m_lvpw);
state_add(ST_LXMAX, "LXMAX", m_lxmax);
state_add(ST_LYMAX, "LYMAX", m_lymax);
state_add(ST_LVCTR, "LVCTR", m_lvctr).mask(0x0f);
}
@ -106,6 +141,10 @@ void st2205u_device::device_reset()
m.prr = 0;
m.drr = 0;
bten_w(0);
m_btreq = 0;
m_btc = 0;
m_lvctr = 0;
}
@ -315,7 +354,63 @@ u8 st2205u_device::sys_r()
void st2205u_device::sys_w(u8 data)
{
m_sys = data & 0xfe;
downcast<mi_st2205u &>(*mintf).irr_enable = BIT(data, 2);
downcast<mi_st2205u &>(*mintf).irr_enable = BIT(data, 1);
}
u8 st2205u_device::bten_r()
{
return m_bten;
}
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;
}
u8 st2205u_device::btc_r()
{
return m_btc;
}
void st2205u_device::btc_w(u8 data)
{
m_btc = data;
}
u8 st2205u_device::lvctr_r()
@ -376,6 +471,9 @@ void st2205u_device::int_map(address_map &map)
map(0x0008, 0x000d).rw(FUNC(st2205u_device::pctrl_r), FUNC(st2205u_device::pctrl_w));
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(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));
map(0x0032, 0x0032).rw(FUNC(st2205u_device::prrl_r), FUNC(st2205u_device::prrl_w));
@ -390,6 +488,11 @@ void st2205u_device::int_map(address_map &map)
map(0x003d, 0x003d).rw(FUNC(st2205u_device::ireqh_r), FUNC(st2205u_device::ireqh_w));
map(0x003e, 0x003e).rw(FUNC(st2205u_device::ienal_r), FUNC(st2205u_device::ienal_w));
map(0x003f, 0x003f).rw(FUNC(st2205u_device::ienah_r), FUNC(st2205u_device::ienah_w));
map(0x0040, 0x0040).w(FUNC(st2205u_device::lssal_w));
map(0x0041, 0x0041).w(FUNC(st2205u_device::lssah_w));
map(0x0042, 0x0042).w(FUNC(st2205u_device::lvpw_w));
map(0x0043, 0x0043).rw(FUNC(st2205u_device::lxmax_r), FUNC(st2205u_device::lxmax_w));
map(0x0044, 0x0044).rw(FUNC(st2205u_device::lymax_r), FUNC(st2205u_device::lymax_w));
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));

View File

@ -17,7 +17,10 @@ class st2205u_device : public st2xxx_device
{
public:
enum {
ST_BRR = ST_IENA + 1,
ST_BTEN = ST_LYMAX + 1,
ST_BTREQ,
ST_BTC,
ST_BRR,
ST_LVCTR
};
@ -55,6 +58,8 @@ private:
std::unique_ptr<u8[]> ram;
};
template<int N> TIMER_CALLBACK_MEMBER(bt_interrupt);
u8 irrl_r();
void irrl_w(u8 data);
u8 irrh_r();
@ -75,6 +80,12 @@ private:
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();
void lvctr_w(u8 data);
@ -89,6 +100,10 @@ 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;
};

View File

@ -76,6 +76,12 @@ void st2xxx_device::device_reset()
// reset miscellaneous registers
m_sys = 0;
// reset LCDC registers
m_lssa = 0;
m_lvpw = 0;
m_lxmax = 0;
m_lymax = 0;
}
std::unique_ptr<util::disasm_interface> st2xxx_device::create_disassembler()
@ -249,4 +255,39 @@ void st2xxx_device::ienah_w(u8 data)
update_irq_state();
}
void st2xxx_device::lssal_w(u8 data)
{
m_lssa = (m_lssa & 0xff00) | data;
}
void st2xxx_device::lssah_w(u8 data)
{
m_lssa = (m_lssa & 0x00ff) | (u16(data) << 8);
}
void st2xxx_device::lvpw_w(u8 data)
{
m_lvpw = data;
}
u8 st2xxx_device::lxmax_r()
{
return m_lxmax;
}
void st2xxx_device::lxmax_w(u8 data)
{
m_lxmax = data;
}
u8 st2xxx_device::lymax_r()
{
return m_lymax;
}
void st2xxx_device::lymax_w(u8 data)
{
m_lymax = data;
}
#include "cpu/m6502/st2xxx.hxx"

View File

@ -37,7 +37,11 @@ public:
ST_PRR,
ST_DRR,
ST_IREQ,
ST_IENA
ST_IENA,
ST_LSSA,
ST_LVPW,
ST_LXMAX,
ST_LYMAX
};
auto in_pa_callback() { return m_in_port_cb[0].bind(); }
@ -107,6 +111,14 @@ protected:
u8 ienah_r();
void ienah_w(u8 data);
void lssal_w(u8 data);
void lssah_w(u8 data);
void lvpw_w(u8 data);
u8 lxmax_r();
void lxmax_w(u8 data);
u8 lymax_r();
void lymax_w(u8 data);
#define O(o) void o ## _full(); void o ## _partial()
O(brk_st_imp);
@ -129,6 +141,10 @@ protected:
u16 m_iena;
const u16 m_ireq_mask;
u8 m_sys;
u16 m_lssa;
u8 m_lvpw;
u8 m_lxmax;
u8 m_lymax;
};
#endif // MAME_CPU_M6502_ST2XXX_H

View File

@ -4,6 +4,9 @@
VTech Intelligence Advance E/R Lerncomputer
TODO: dyndesk writes to low memory go to external RAM instead? It also
eventually runs off into nonexistent memory.
***************************************************************************/
#include "emu.h"
@ -36,7 +39,7 @@ void inteladv_state::inteladv_map(address_map &map)
void inteladv_state::dyndesk_map(address_map &map)
{
map(0x000000, 0x1fffff).rom().region("maincpu", 0).nopw(); // writes to low memory go to external RAM instead?
map(0x000000, 0x1fffff).rom().region("maincpu", 0).nopw();
}
static INPUT_PORTS_START( inteladv )