summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6502/st2204.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6502/st2204.cpp')
-rw-r--r--src/devices/cpu/m6502/st2204.cpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/src/devices/cpu/m6502/st2204.cpp b/src/devices/cpu/m6502/st2204.cpp
new file mode 100644
index 00000000000..7f70fd70b89
--- /dev/null
+++ b/src/devices/cpu/m6502/st2204.cpp
@@ -0,0 +1,276 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Sitronix ST2204 8-Bit Integrated Microcontroller
+
+ Functional blocks:
+ * Interrupt controller (11 levels excluding BRK and RESET)
+ * GPIO (6 ports, 8 bits each)
+ * External bus (up to 7 CS outputs, 48M maximum addressable)
+ * Timers/event counters with clocking outputs (2 plus base timer)
+ * Programmable sound generator (2 channels plus DAC)
+ * LCD controller (320x240 B/W or 240x160 4-gray)
+ * Serial peripheral interface
+ * UART (built-in BRG; RS-232 and IrDA modes)
+ * Direct memory access
+ * Power down modes (WAI-0, WAI-1, STP)
+ * Watchdog timer
+ * Low voltage detector
+ * 512K ROM (may be disabled)
+ * 10K RAM
+
+ Emulation is largely based on documentation for the ST2202, which
+ has similar though somewhat lesser capabilities.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "st2204.h"
+
+DEFINE_DEVICE_TYPE(ST2204, st2204_device, "st2204", "Sitronix ST2204 Integrated Microcontroller")
+
+st2204_device::st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : 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)
+{
+}
+
+void st2204_device::device_start()
+{
+ std::unique_ptr<mi_st2204> intf = std::make_unique<mi_st2204>();
+ intf->data = &space(AS_DATA);
+ intf->dcache = space(AS_DATA).cache<0, 0, ENDIANNESS_LITTLE>();
+ intf->irr_enable = false;
+ intf->irr = 0;
+ intf->prr = 0;
+ intf->drr = 0;
+ intf->irq_service = false;
+
+ save_item(NAME(m_pdata));
+ save_item(NAME(m_pctrl));
+ save_item(NAME(m_psel));
+ save_item(NAME(m_pfun));
+ save_item(NAME(m_sys));
+ save_item(NAME(m_pmcr));
+ save_item(NAME(m_ireq));
+ save_item(NAME(m_iena));
+ 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);
+ 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);
+ 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_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_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); });
+}
+
+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;
+}
+
+u8 st2204_device::mi_st2204::pread(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return data->read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff));
+}
+
+u8 st2204_device::mi_st2204::preadc(u16 adr)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ return dcache->read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff));
+}
+
+void st2204_device::mi_st2204::pwrite(u16 adr, u8 val)
+{
+ u16 bank = irq_service && irr_enable ? irr : prr;
+ data->write_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff), val);
+}
+
+u8 st2204_device::mi_st2204::dread(u16 adr)
+{
+ return data->read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+u8 st2204_device::mi_st2204::dreadc(u16 adr)
+{
+ return dcache->read_byte(u32(drr) << 15 | (adr & 0x7fff));
+}
+
+void st2204_device::mi_st2204::dwrite(u16 adr, u8 val)
+{
+ data->write_byte(u32(drr) << 15 | (adr & 0x7fff), val);
+}
+
+u8 st2204_device::mi_st2204::read(u16 adr)
+{
+ return program->read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_sync(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cache->read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_arg(u16 adr)
+{
+ return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cache->read_byte(adr);
+}
+
+u8 st2204_device::mi_st2204::read_vector(u16 adr)
+{
+ return pread(adr);
+}
+
+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;
+}
+
+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, 2);
+}
+
+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 = (data & 0x0f) << 16 | (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 = (data & 0x07) << 16 | (drr & 0x00ff);
+}
+
+u8 st2204_device::pmem_r(offs_t offset)
+{
+ return downcast<mi_st2204 &>(*mintf).pread(offset);
+}
+
+void st2204_device::pmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2204 &>(*mintf).pwrite(offset, data);
+}
+
+u8 st2204_device::dmem_r(offs_t offset)
+{
+ return downcast<mi_st2204 &>(*mintf).dread(offset);
+}
+
+void st2204_device::dmem_w(offs_t offset, u8 data)
+{
+ downcast<mi_st2204 &>(*mintf).dwrite(offset, data);
+}
+
+void st2204_device::int_map(address_map &map)
+{
+ map(0x0000, 0x0004).rw(FUNC(st2204_device::pdata_r), FUNC(st2204_device::pdata_w));
+ map(0x0005, 0x0005).rw(FUNC(st2204_device::psc_r), FUNC(st2204_device::psc_w));
+ map(0x0008, 0x000c).rw(FUNC(st2204_device::pdata_r), FUNC(st2204_device::pdata_w));
+ 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(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));
+ 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));
+ map(0x0035, 0x0035).rw(FUNC(st2204_device::drrh_r), FUNC(st2204_device::drrh_w));
+ map(0x003c, 0x003c).rw(FUNC(st2204_device::ireql_r), FUNC(st2204_device::ireql_w));
+ 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(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
+ 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));
+}