summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/f2mc16/mb9061x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/f2mc16/mb9061x.cpp')
-rw-r--r--src/devices/cpu/f2mc16/mb9061x.cpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/devices/cpu/f2mc16/mb9061x.cpp b/src/devices/cpu/f2mc16/mb9061x.cpp
index 7576f8287ea..aea77406f79 100644
--- a/src/devices/cpu/f2mc16/mb9061x.cpp
+++ b/src/devices/cpu/f2mc16/mb9061x.cpp
@@ -39,6 +39,9 @@ mb9061x_device::mb9061x_device(const machine_config &mconfig, device_type type,
void mb9061x_device::device_start()
{
f2mc16_device::device_start();
+
+ m_tbtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mb9061x_device::tbtc_tick), this));
+ m_tbtc_timer->adjust(attotime::never);
}
@@ -65,6 +68,8 @@ void mb9061x_device::execute_set_input(int inputnum, int state)
/* MB90610 - "Evaluation device" with extra RAM */
void mb90610_device::mb90610_map(address_map &map)
{
+ map(0x00a9, 0x00a9).rw(FUNC(mb9061x_device::tbtc_r), FUNC(mb9061x_device::tbtc_w));
+ map(0x00b0, 0x00bf).rw(FUNC(mb9061x_device::intc_r), FUNC(mb9061x_device::intc_w));
map(0x0100, 0x10ff).ram(); // 4K of internal RAM from 0x100 to 0x1100
}
@@ -78,9 +83,107 @@ mb90610_device::mb90610_device(const machine_config &mconfig, device_type type,
{
}
+/* TBTC: timebase counter */
+enum
+{
+ TBTC_TEST = 0x80, // test, must always write 1
+ TBTC_TBIE = 0x10, // interrupt enable
+ TBTC_TBOF = 0x08, // expire flag
+ TBTC_TBR = 0x04, // write 0 to restart
+ TBTC_TBC1 = 0x02, // rate select bit 1
+ TBTC_TBC0 = 0x01 // rate select bit 0
+};
+
+READ8_MEMBER(mb9061x_device::tbtc_r)
+{
+ return m_tbtc;
+}
+
+WRITE8_MEMBER(mb9061x_device::tbtc_w)
+{
+ static const float periods[4] = { 1.024, 4.096, 16.384, 131.072 };
+
+ //printf("%02x to TBTC\n", data);
+ if ((!(data & TBTC_TBR)) || ((data & (TBTC_TBC1|TBTC_TBC0)) != (m_tbtc & (TBTC_TBC1|TBTC_TBC0))))
+ {
+ m_tbtc_timer->adjust(attotime(0, ATTOSECONDS_IN_MSEC(periods[data & (TBTC_TBC1|TBTC_TBC0)])));
+
+ if (!(data & TBTC_TBR))
+ {
+ intc_clear_irq(11, 0x22);
+ }
+ }
+
+ if (!(data & TBTC_TBOF) && (m_tbtc & TBTC_TBOF))
+ {
+ intc_clear_irq(11, 0x22);
+ }
+
+ m_tbtc = data;
+}
+
+/* INTC: Interrupt controller */
+TIMER_CALLBACK_MEMBER(mb9061x_device::tbtc_tick)
+{
+ //printf("TBTC tick\n");
+ m_tbtc_timer->adjust(attotime::never);
+ m_tbtc |= TBTC_TBOF;
+ if (m_tbtc & TBTC_TBIE)
+ {
+ intc_trigger_irq(11, 0x22);
+ }
+}
+
+READ8_MEMBER(mb9061x_device::intc_r)
+{
+ return m_intc[offset];
+}
+
+WRITE8_MEMBER(mb9061x_device::intc_w)
+{
+ //printf("INTC ICR %d to %02x\n", offset, data);
+ m_intc[offset] = data;
+}
+
+void mb9061x_device::intc_trigger_irq(int icr, int vector)
+{
+ int level = m_intc[icr] & 7;
+
+ //printf("trigger_irq: ICR %d, level %d\n", icr, level);
+
+ // Extended Intelligent I/O Service?
+ if (m_intc[icr] & 8)
+ {
+ fatalerror("MB9061X: ICR %d (vector %x) calls for EI2OS, not implemented\n", icr, vector);
+ }
+ else
+ {
+ if (level != 7)
+ {
+ set_irq(vector, level);
+ }
+ }
+}
+
+void mb9061x_device::intc_clear_irq(int icr, int vector)
+{
+ int level = m_intc[icr] & 7;
+
+ // Make sure this isn't the Extended Intelligent I/O Service
+ if (!(m_intc[icr] & 8))
+ {
+ if (level != 7)
+ {
+ clear_irq(vector);
+ }
+ }
+}
+
/* MB90611 - Production version of this series */
void mb90611_device::mb90611_map(address_map &map)
{
+ map(0x00a9, 0x00a9).rw(FUNC(mb9061x_device::tbtc_r), FUNC(mb9061x_device::tbtc_w));
+ map(0x00b0, 0x00bf).rw(FUNC(mb9061x_device::intc_r), FUNC(mb9061x_device::intc_w));
map(0x0100, 0x04ff).ram(); // 1K of internal RAM from 0x100 to 0x500
}