trunk/src/emu/cpu/ucom4/ucom4.c
| r243502 | r243503 | |
| 10 | 10 | I've also looked at asterick's JavaScript D553 emulator for verification, with permission. |
| 11 | 11 | |
| 12 | 12 | TODO: |
| 13 | - add external interrupt |
| 13 | 14 | - what happens with uCOM-43 opcodes on an uCOM-44/45 MCU? |
| 14 | 15 | - what's the data after the ROM data for? (eg. 2000-2047, official ROM size is 2000) |
| 15 | 16 | |
| r243502 | r243503 | |
| 122 | 123 | m_datamask = (1 << m_datawidth) - 1; |
| 123 | 124 | m_dph_mask = m_datamask >> 4; |
| 124 | 125 | |
| 126 | m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ucom4_cpu_device::simple_timer_cb), this)); |
| 127 | |
| 125 | 128 | m_read_a.resolve_safe(0xf); |
| 126 | 129 | m_read_b.resolve_safe(0xf); |
| 127 | 130 | m_read_c.resolve_safe(0xf); |
| r243502 | r243503 | |
| 187 | 190 | |
| 188 | 191 | void ucom4_cpu_device::device_reset() |
| 189 | 192 | { |
| 190 | | m_inte_f = 1; |
| 191 | 193 | m_pc = 0; |
| 192 | 194 | m_op = 0; |
| 193 | 195 | m_skip = false; |
| 194 | 196 | |
| 197 | m_timer->adjust(attotime::never); |
| 198 | |
| 195 | 199 | // clear i/o |
| 196 | 200 | for (int i = NEC_UCOM4_PORTC; i <= NEC_UCOM4_PORTI; i++) |
| 197 | 201 | output_w(i, 0xf); |
trunk/src/emu/cpu/ucom4/ucom4.h
| r243502 | r243503 | |
| 141 | 141 | UINT8 m_bitmask; // opcode bit argument |
| 142 | 142 | bool m_skip; // skip next opcode |
| 143 | 143 | int m_icount; |
| 144 | emu_timer *m_timer; |
| 144 | 145 | |
| 145 | 146 | UINT16 m_pc; // program counter |
| 146 | 147 | UINT8 m_acc; // 4-bit accumulator |
| r243502 | r243503 | |
| 179 | 180 | void output_w(int index, UINT8 data); |
| 180 | 181 | |
| 181 | 182 | bool check_op_43(); |
| 183 | TIMER_CALLBACK_MEMBER( simple_timer_cb ); |
| 182 | 184 | UINT8 ucom43_reg_r(int index); |
| 183 | 185 | void ucom43_reg_w(int index, UINT8 data); |
| 184 | 186 | |
trunk/src/emu/cpu/ucom4/ucom4op.inc
| r243502 | r243503 | |
| 429 | 429 | void ucom4_cpu_device::op_tit() |
| 430 | 430 | { |
| 431 | 431 | // TIT: skip next on Interrupt F/F, reset Interrupt F/F |
| 432 | | op_illegal(); |
| 432 | m_skip = (m_int_f != 0); |
| 433 | m_int_f = 0; |
| 433 | 434 | } |
| 434 | 435 | |
| 435 | 436 | |
| r243502 | r243503 | |
| 489 | 490 | return (m_family == NEC_UCOM43); |
| 490 | 491 | } |
| 491 | 492 | |
| 493 | TIMER_CALLBACK_MEMBER( ucom4_cpu_device::simple_timer_cb ) |
| 494 | { |
| 495 | m_timer_f = 1; |
| 496 | } |
| 497 | |
| 492 | 498 | // extra registers reside in RAM |
| 493 | 499 | enum |
| 494 | 500 | { |
| r243502 | r243503 | |
| 512 | 518 | } |
| 513 | 519 | |
| 514 | 520 | |
| 521 | |
| 515 | 522 | // Transfer |
| 516 | 523 | |
| 517 | 524 | void ucom4_cpu_device::op_taw() |
| r243502 | r243503 | |
| 712 | 719 | if (!check_op_43()) return; |
| 713 | 720 | |
| 714 | 721 | // STM X: Reset Timer F/F, Start Timer with X |
| 715 | | op_illegal(); |
| 722 | m_timer_f = 0; |
| 716 | 723 | |
| 724 | // on the default clockrate of 400kHz, the minimum time interval is |
| 725 | // 630usec and the maximum interval is 40320usec(630*64) |
| 726 | attotime base = attotime::from_hz(unscaled_clock() / 4 / 63); |
| 727 | m_timer->adjust(base * ((m_arg & 0x3f) + 1)); |
| 728 | |
| 717 | 729 | if ((m_arg & 0xc0) != 0x80) |
| 718 | 730 | logerror("%s STM opcode unexpected upper arg $%02X at $%03X\n", tag(), m_arg & 0xc0, m_pc); |
| 719 | 731 | } |
| r243502 | r243503 | |
| 723 | 735 | if (!check_op_43()) return; |
| 724 | 736 | |
| 725 | 737 | // TTM: skip next on Timer F/F |
| 726 | | op_illegal(); |
| 738 | m_skip = (m_timer_f != 0); |
| 727 | 739 | } |
| 728 | 740 | |
| 729 | 741 | |
| r243502 | r243503 | |
| 734 | 746 | if (!check_op_43()) return; |
| 735 | 747 | |
| 736 | 748 | // EI: Set Interrupt Enable F/F |
| 737 | | op_illegal(); |
| 749 | m_inte_f = 1; |
| 738 | 750 | } |
| 739 | 751 | |
| 740 | 752 | void ucom4_cpu_device::op_di() |
| r243502 | r243503 | |
| 742 | 754 | if (!check_op_43()) return; |
| 743 | 755 | |
| 744 | 756 | // DI: Reset Interrupt Enable F/F |
| 745 | | op_illegal(); |
| 757 | m_inte_f = 0; |
| 746 | 758 | } |