diff --git a/src/emu/cpu/ucom4/ucom4.c b/src/emu/cpu/ucom4/ucom4.c index 8c30de7de3f..abc5d017b34 100644 --- a/src/emu/cpu/ucom4/ucom4.c +++ b/src/emu/cpu/ucom4/ucom4.c @@ -10,6 +10,7 @@ I've also looked at asterick's JavaScript D553 emulator for verification, with permission. TODO: + - add external interrupt - what happens with uCOM-43 opcodes on an uCOM-44/45 MCU? - what's the data after the ROM data for? (eg. 2000-2047, official ROM size is 2000) @@ -122,6 +123,8 @@ void ucom4_cpu_device::device_start() m_datamask = (1 << m_datawidth) - 1; m_dph_mask = m_datamask >> 4; + m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ucom4_cpu_device::simple_timer_cb), this)); + m_read_a.resolve_safe(0xf); m_read_b.resolve_safe(0xf); m_read_c.resolve_safe(0xf); @@ -187,11 +190,12 @@ void ucom4_cpu_device::device_start() void ucom4_cpu_device::device_reset() { - m_inte_f = 1; m_pc = 0; m_op = 0; m_skip = false; + m_timer->adjust(attotime::never); + // clear i/o for (int i = NEC_UCOM4_PORTC; i <= NEC_UCOM4_PORTI; i++) output_w(i, 0xf); diff --git a/src/emu/cpu/ucom4/ucom4.h b/src/emu/cpu/ucom4/ucom4.h index 92b73e1e270..718937b235a 100644 --- a/src/emu/cpu/ucom4/ucom4.h +++ b/src/emu/cpu/ucom4/ucom4.h @@ -141,6 +141,7 @@ protected: UINT8 m_bitmask; // opcode bit argument bool m_skip; // skip next opcode int m_icount; + emu_timer *m_timer; UINT16 m_pc; // program counter UINT8 m_acc; // 4-bit accumulator @@ -179,6 +180,7 @@ protected: void output_w(int index, UINT8 data); bool check_op_43(); + TIMER_CALLBACK_MEMBER( simple_timer_cb ); UINT8 ucom43_reg_r(int index); void ucom43_reg_w(int index, UINT8 data); diff --git a/src/emu/cpu/ucom4/ucom4op.inc b/src/emu/cpu/ucom4/ucom4op.inc index 6c6faddeae5..82d54950e24 100644 --- a/src/emu/cpu/ucom4/ucom4op.inc +++ b/src/emu/cpu/ucom4/ucom4op.inc @@ -429,7 +429,8 @@ void ucom4_cpu_device::op_tpb() void ucom4_cpu_device::op_tit() { // TIT: skip next on Interrupt F/F, reset Interrupt F/F - op_illegal(); + m_skip = (m_int_f != 0); + m_int_f = 0; } @@ -489,6 +490,11 @@ inline bool ucom4_cpu_device::check_op_43() return (m_family == NEC_UCOM43); } +TIMER_CALLBACK_MEMBER( ucom4_cpu_device::simple_timer_cb ) +{ + m_timer_f = 1; +} + // extra registers reside in RAM enum { @@ -512,6 +518,7 @@ inline void ucom4_cpu_device::ucom43_reg_w(int index, UINT8 data) } + // Transfer void ucom4_cpu_device::op_taw() @@ -712,7 +719,12 @@ void ucom4_cpu_device::op_stm() if (!check_op_43()) return; // STM X: Reset Timer F/F, Start Timer with X - op_illegal(); + m_timer_f = 0; + + // on the default clockrate of 400kHz, the minimum time interval is + // 630usec and the maximum interval is 40320usec(630*64) + attotime base = attotime::from_hz(unscaled_clock() / 4 / 63); + m_timer->adjust(base * ((m_arg & 0x3f) + 1)); if ((m_arg & 0xc0) != 0x80) logerror("%s STM opcode unexpected upper arg $%02X at $%03X\n", tag(), m_arg & 0xc0, m_pc); @@ -723,7 +735,7 @@ void ucom4_cpu_device::op_ttm() if (!check_op_43()) return; // TTM: skip next on Timer F/F - op_illegal(); + m_skip = (m_timer_f != 0); } @@ -734,7 +746,7 @@ void ucom4_cpu_device::op_ei() if (!check_op_43()) return; // EI: Set Interrupt Enable F/F - op_illegal(); + m_inte_f = 1; } void ucom4_cpu_device::op_di() @@ -742,5 +754,5 @@ void ucom4_cpu_device::op_di() if (!check_op_43()) return; // DI: Reset Interrupt Enable F/F - op_illegal(); + m_inte_f = 0; }