From beb51eaa9330b0113cca501e8e671fe8abe3e4be Mon Sep 17 00:00:00 2001 From: smf- Date: Fri, 25 Oct 2024 12:13:22 +0100 Subject: f2mc16: Created devices for the onboard analogue to digital converter, clock generator, interrupt controller/Extended intelligent I/O service, I/O port, Programmable Pulse Generator, reload timer and UART. CPU core exposes the RMW line for onboard devices. Log messages will contain the address of the start of the instruction, rather than the next byte the CPU is about to fetch. Added INT9/INT addr16 & INT addr24 software interrupt instructions. Fixed INCW @RWx & DECW @RWx instruction length Added missing fetch of immediate value in MOV @RWx + RW7, #imm8. Rewrote Tomy Prin-C keyboard handling and pen to use new onboard devices, substantially increasing the reload timer 0 frequency as it's now correctly waiting for 0x7530 underflows with reload = 0x37f at startup. --- scripts/src/cpu.lua | 22 +- src/devices/cpu/f2mc16/f2mc16.cpp | 296 ++++++++++++------- src/devices/cpu/f2mc16/f2mc16.h | 17 +- src/devices/cpu/f2mc16/f2mc16_adc.cpp | 304 ++++++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_adc.h | 72 +++++ src/devices/cpu/f2mc16/f2mc16_clock.cpp | 355 +++++++++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_clock.h | 74 +++++ src/devices/cpu/f2mc16/f2mc16_intc.cpp | 269 +++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_intc.h | 64 +++++ src/devices/cpu/f2mc16/f2mc16_port.cpp | 127 ++++++++ src/devices/cpu/f2mc16/f2mc16_port.h | 57 ++++ src/devices/cpu/f2mc16/f2mc16_ppg.cpp | 348 ++++++++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_ppg.h | 70 +++++ src/devices/cpu/f2mc16/f2mc16_reload.cpp | 381 ++++++++++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_reload.h | 75 +++++ src/devices/cpu/f2mc16/f2mc16_uart.cpp | 456 +++++++++++++++++++++++++++++ src/devices/cpu/f2mc16/f2mc16_uart.h | 98 +++++++ src/devices/cpu/f2mc16/mb90570.cpp | 169 +++++++++++ src/devices/cpu/f2mc16/mb90570.h | 55 ++++ src/devices/cpu/f2mc16/mb90610a.cpp | 138 +++++++++ src/devices/cpu/f2mc16/mb90610a.h | 59 ++++ src/devices/cpu/f2mc16/mb9061x.cpp | 457 ----------------------------- src/devices/cpu/f2mc16/mb9061x.h | 180 ------------ src/devices/cpu/f2mc16/mb90640a.cpp | 134 +++++++++ src/devices/cpu/f2mc16/mb90640a.h | 52 ++++ src/mame/sony/dpsv55.cpp | 23 +- src/mame/tomy/tomy_princ.cpp | 479 ++++++++++++++----------------- 27 files changed, 3804 insertions(+), 1027 deletions(-) create mode 100644 src/devices/cpu/f2mc16/f2mc16_adc.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_adc.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_clock.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_clock.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_intc.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_intc.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_port.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_port.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_ppg.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_ppg.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_reload.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_reload.h create mode 100644 src/devices/cpu/f2mc16/f2mc16_uart.cpp create mode 100644 src/devices/cpu/f2mc16/f2mc16_uart.h create mode 100644 src/devices/cpu/f2mc16/mb90570.cpp create mode 100644 src/devices/cpu/f2mc16/mb90570.h create mode 100644 src/devices/cpu/f2mc16/mb90610a.cpp create mode 100644 src/devices/cpu/f2mc16/mb90610a.h delete mode 100644 src/devices/cpu/f2mc16/mb9061x.cpp delete mode 100644 src/devices/cpu/f2mc16/mb9061x.h create mode 100644 src/devices/cpu/f2mc16/mb90640a.cpp create mode 100644 src/devices/cpu/f2mc16/mb90640a.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 8fee66cc946..48d2f317f55 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -3630,8 +3630,26 @@ if CPUS["F2MC16"] then files { MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16.cpp", MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16.h", - MAME_DIR .. "src/devices/cpu/f2mc16/mb9061x.cpp", - MAME_DIR .. "src/devices/cpu/f2mc16/mb9061x.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_adc.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_adc.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_clock.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_clock.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_intc.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_intc.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_port.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_port.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_ppg.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_ppg.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_reload.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_reload.h", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_uart.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/f2mc16_uart.h", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90570.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90570.h", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90610a.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90610a.h", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90640a.cpp", + MAME_DIR .. "src/devices/cpu/f2mc16/mb90640a.h", } end diff --git a/src/devices/cpu/f2mc16/f2mc16.cpp b/src/devices/cpu/f2mc16/f2mc16.cpp index fdfac5d16cd..1a8dd533f5f 100644 --- a/src/devices/cpu/f2mc16/f2mc16.cpp +++ b/src/devices/cpu/f2mc16/f2mc16.cpp @@ -37,6 +37,7 @@ f2mc16_device::f2mc16_device(const machine_config &mconfig, device_type type, co : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0) , m_program(nullptr) + , m_irq_level((7 << 13) | 0x1fff) { m_tmp8 = 0; m_tmp16 = 0; @@ -61,10 +62,10 @@ void f2mc16_device::device_start() set_icountptr(m_icount); - state_add(F2MC16_PCB, "PCB", m_pcb); - state_add(F2MC16_PC, "PC", m_pc).formatstr("%04X"); + state_add(F2MC16_PCB, "PCB", m_pcb).callimport(); + state_add(F2MC16_PC, "PC", m_pc).callimport().formatstr("%04X"); state_add(STATE_GENPC, "GENPC", m_temp).callimport().callexport().noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_temp).callimport().callexport().noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_pcbase).callimport().noshow(); state_add(F2MC16_PS, "PS", m_ps).formatstr("%04X"); state_add(STATE_GENFLAGS, "GENFLAGS", m_ps).callimport().formatstr("%7s").noshow(); state_add(F2MC16_DTB, "DTB", m_dtb).formatstr("%02X"); @@ -110,12 +111,14 @@ void f2mc16_device::device_start() save_item(NAME(m_dpr)); save_item(NAME(m_tmp8)); save_item(NAME(m_prefix)); + save_item(NAME(m_pcbase)); save_item(NAME(m_acc)); save_item(NAME(m_temp)); save_item(NAME(m_tmp32)); save_item(NAME(m_tmpea)); save_item(NAME(m_prefix_valid)); - save_item(NAME(m_outstanding_irqs)); + save_item(NAME(m_irq_level)); + save_item(NAME(m_rmw)); } void f2mc16_device::device_reset() @@ -128,16 +131,11 @@ void f2mc16_device::device_reset() m_dpr = 0x01; m_dtb = 0; - for (int &entry : m_vector_level) - { - entry = 7; - } - m_outstanding_irqs = 0; - m_pc = read_16_vector(0xffffdc); m_pcb = read_8_vector(0xffffde); m_prefix_valid = false; + m_rmw = false; } void f2mc16_device::state_import(const device_state_entry &entry) @@ -145,9 +143,19 @@ void f2mc16_device::state_import(const device_state_entry &entry) switch (entry.index()) { case STATE_GENPC: + m_pcbase = m_temp; + m_pc = (m_pcbase & 0xffff); + m_pcb = (m_pcbase >> 16) & 0xff; + break; + case STATE_GENPCBASE: - m_pc = (m_temp & 0xffff); - m_pcb = (m_temp >> 16) & 0xff; + m_pc = (m_pcbase & 0xffff); + m_pcb = (m_pcbase >> 16) & 0xff; + break; + + case F2MC16_PCB: + case F2MC16_PC: + m_pcbase = ((m_pcb & 0xff) << 16) | m_pc; break; case F2MC16_RW0: write_rwX(0, m_temp); break; @@ -206,7 +214,6 @@ void f2mc16_device::state_export(const device_state_entry &entry) case F2MC16_R7: m_temp = read_rX(7); break; case STATE_GENPC: - case STATE_GENPCBASE: m_temp = m_pc; m_temp |= (m_pcb << 16); break; @@ -234,33 +241,41 @@ void f2mc16_device::execute_run() { while (m_icount > 0) { - if (m_outstanding_irqs && !m_prefix_valid) + if (!m_prefix_valid && m_irq_level < m_ps && (m_ps & F_I)) { - int cpulevel = m_ps >> 13; - - for (int irq = 0; irq < 256; irq++) + uint8_t irq_level = m_irq_level; + uint8_t irq_vector = standard_irq_callback(irq_level, m_pc); + if (irq_vector) { - if (m_vector_level[irq] < cpulevel) - { - take_irq(irq, m_vector_level[irq]); - break; - } + take_irq_vector(irq_vector); + m_ps = (m_ps | (7 << 13)) & irq_level; } } //m_icount--; if (!m_prefix_valid) + { + m_pcbase = (m_pcb << 16) | m_pc; debugger_instruction_hook((m_pcb << 16) | m_pc); + } u8 opcode = read_8((m_pcb << 16) | m_pc); switch (opcode) { - case 0x00: // NOP + // NOP + case 0x00: m_icount--; m_pc++; break; + // INT9 + case 0x01: + m_pc++; + take_irq_vector(9); + m_ps &= ~F_I; + break; + // NEG A case 0x03: m_tmp8 = doSUB_8(0, m_acc & 0xff); @@ -1286,64 +1301,45 @@ void f2mc16_device::execute_run() // INT #vct8 case 0x68: m_tmp8 = read_8((m_pcb << 16) | (m_pc + 1)); - push_16_ssp((m_acc >> 16) & 0xffff); - push_16_ssp(m_acc & 0xffff); - push_16_ssp((m_dpr << 8) | m_adb); - push_16_ssp((m_dtb << 8) | m_pcb); - push_16_ssp(m_pc + 2); - push_16_ssp(m_ps); + m_pc += 2; + take_irq_vector(m_tmp8); m_ps &= ~F_I; - m_ps |= F_S; - m_tmpea = 0xfffffc - (m_tmp8 * 4); - m_pc = read_16_vector(m_tmpea); - m_pcb = read_8_vector(m_tmpea + 2); - m_icount -= 12; break; - // RETI - case 0x6b: - { - bool bFoundVec = false; + // INT addr16 + case 0x69: + m_tmp16 = read_16((m_pcb << 16) | (m_pc + 1)); + m_pc += 3; + take_irq(); + m_pc = m_tmp16; + m_ps &= ~F_I; + break; - // there's an IRQ chaining facility, let's do it - if (m_outstanding_irqs) - { - int cpulevel = peek_stack_16() >> 13; - for (int irq = 0; irq < 256; irq++) - { - if (m_vector_level[irq] < cpulevel) - { - m_ps = read_16((m_ssb << 16) | m_ssp); - m_ps |= F_S; - m_ps &= ~0x7000; - m_ps |= (m_vector_level[irq] & 7) << 13; - - u32 uVecAddr = 0xfffffc - (irq * 4); - m_pc = read_16_vector(uVecAddr); - m_pcb = read_8_vector(uVecAddr + 2); - bFoundVec = true; - //printf("RETI vector chain to %02x%04x\n", m_pcb, m_pc); + // INTP addr24 + case 0x6a: + m_tmp16 = read_16((m_pcb << 16) | (m_pc + 1)); + m_tmp8 = read_8((m_pcb << 16) | (m_pc + 3)); + m_pc += 4; + take_irq(); + m_pcb = m_tmp8; + m_pc = m_tmp16; + m_ps &= ~F_I; break; - } - } - } - // if no new IRQ was found or could be dispatched by the level - if (!bFoundVec) - { - m_ps = pull_16_ssp(); - m_pc = pull_16_ssp(); - m_tmp16 = pull_16_ssp(); - m_pcb = m_tmp16 & 0xff; - m_dtb = m_tmp16 >> 8; - m_tmp16 = pull_16_ssp(); - m_adb = m_tmp16 & 0xff; - m_dpr = m_tmp16 >> 8; - m_acc = pull_16_ssp(); - m_acc |= (pull_16_ssp() << 16); - m_icount -= 17; - } - } + // RETI + case 0x6b: + m_ps = pull_16_ssp(); + m_pc = pull_16_ssp(); + m_tmp16 = pull_16_ssp(); + m_pcb = m_tmp16 & 0xff; + m_dtb = m_tmp16 >> 8; + m_tmp16 = pull_16_ssp(); + m_adb = m_tmp16 & 0xff; + m_dpr = m_tmp16 >> 8; + m_acc = 0; + m_acc = pull_16_ssp(); + m_acc |= (pull_16_ssp() << 16); + m_icount -= 17; break; case 0x6c: // bit operation instructions @@ -1644,7 +1640,7 @@ void f2mc16_device::execute_run() break; // BT - case 0xf8:; + case 0xf8: if (m_ps & F_T) { take_branch(); @@ -1892,9 +1888,11 @@ void f2mc16_device::opcodes_bo6c(u8 operand) // CLRB io:bp case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: m_tmpea = read_8((m_pcb << 16) | (m_pc + 2)); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 &= ~(1 << (operand & 7)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -1902,9 +1900,11 @@ void f2mc16_device::opcodes_bo6c(u8 operand) // CLRB dir:bp case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: m_tmpea = getdirbank(read_8((m_pcb << 16) | (m_pc + 2))); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 &= ~(1 << (operand & 7)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -1919,9 +1919,11 @@ void f2mc16_device::opcodes_bo6c(u8 operand) } else m_tmpea |= (m_dtb<<16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 &= ~(1 << (operand & 7)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 7; break; @@ -1929,9 +1931,11 @@ void f2mc16_device::opcodes_bo6c(u8 operand) // SETB io:bp case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: m_tmpea = read_8((m_pcb << 16) | (m_pc + 2)); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 |= (1 << (operand & 7)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -1939,9 +1943,11 @@ void f2mc16_device::opcodes_bo6c(u8 operand) // SETB dir:bp case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: m_tmpea = getdirbank(read_8((m_pcb << 16) | (m_pc + 2))); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 |= (1 << (operand & 7)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -1949,6 +1955,7 @@ void f2mc16_device::opcodes_bo6c(u8 operand) // SETB addr16:bp case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); + m_rmw = true; if (m_prefix_valid) { m_prefix_valid = false; @@ -1962,6 +1969,7 @@ void f2mc16_device::opcodes_bo6c(u8 operand) m_tmp8 |= (1 << (operand & 7)); write_8((m_dtb<<16) | m_tmp16, m_tmp8); } + m_rmw = false; m_pc += 4; m_icount -= 7; break; @@ -2085,7 +2093,7 @@ void f2mc16_device::opcodes_bo6c(u8 operand) m_icount -= 7; break; - // WTBS io:bp + // WBTS io:bp case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: m_tmpea = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp8 = read_8(m_tmpea); @@ -2094,7 +2102,7 @@ void f2mc16_device::opcodes_bo6c(u8 operand) m_icount -= 4; break; - // WTBC io:bp + // WBTC io:bp case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: m_tmpea = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp8 = read_8(m_tmpea); @@ -2922,8 +2930,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 3; m_icount -= 11; break; @@ -2933,8 +2943,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 4; m_icount -= 11; break; @@ -2943,8 +2955,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) case 0x5c: case 0x5d: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); + m_rmw = true; m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 2; m_icount -= 13; break; @@ -2959,8 +2973,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) } else m_tmpea |= (m_dtb << 16); + m_rmw = true; m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 4; m_icount -= 10; break; @@ -2978,8 +2994,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp32 = doDEC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 3; m_icount -= 11; break; @@ -2989,8 +3007,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp32 = doDEC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 4; m_icount -= 11; break; @@ -2999,8 +3019,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) case 0x7c: case 0x7d: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); + m_rmw = true; m_tmp32 = doDEC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 2; m_icount -= 13; break; @@ -3015,8 +3037,10 @@ void f2mc16_device::opcodes_ea71(u8 operand) } else m_tmpea |= (m_dtb << 16); + m_rmw = true; m_tmp32 = doDEC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); + m_rmw = false; m_pc += 4; m_icount -= 10; break; @@ -3185,6 +3209,7 @@ void f2mc16_device::opcodes_ea71(u8 operand) // MOV @RWx + RW7, #imm8 case 0xdc: case 0xdd: + m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); @@ -3297,8 +3322,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) case 0x48: case 0x49: case 0x4a: case 0x4b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 2; m_icount -= 7; break; @@ -3308,8 +3335,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -3319,8 +3348,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 7; break; @@ -3329,8 +3360,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) case 0x5c: case 0x5d: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); + m_rmw = true; m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 2; m_icount -= 9; break; @@ -3347,8 +3380,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) { m_tmpea |= (m_dtb << 16); } + m_rmw = true; m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 5; break; @@ -3365,8 +3400,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) case 0x68: case 0x69: case 0x6a: case 0x6b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 2; m_icount -= 7; break; @@ -3376,8 +3413,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 7; break; @@ -3387,8 +3426,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 7; break; @@ -3397,8 +3438,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) case 0x7c: case 0x7d: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); + m_rmw = true; m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 2; m_icount -= 9; break; @@ -3415,8 +3458,10 @@ void f2mc16_device::opcodes_ea72(u8 operand) { m_tmpea |= (m_dtb << 16); } + m_rmw = true; m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 6; break; @@ -3616,9 +3661,11 @@ void f2mc16_device::opcodes_ea73(u8 operand) case 0x48: case 0x49: case 0x4a: case 0x4b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doINC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); - m_pc += 3; + m_rmw = false; + m_pc += 2; m_icount -= 5; break; @@ -3627,8 +3674,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp16 = doINC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 3; m_icount -= 5; break; @@ -3638,8 +3687,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doINC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 4; m_icount -= 5; break; @@ -3656,8 +3707,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) { m_tmpea |= (m_dtb << 16); } + m_rmw = true; m_tmp16 = doINC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 4; m_icount -= 5; break; @@ -3674,9 +3727,11 @@ void f2mc16_device::opcodes_ea73(u8 operand) case 0x68: case 0x69: case 0x6a: case 0x6b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doDEC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); - m_pc += 3; + m_rmw = false; + m_pc += 2; m_icount -= 5; break; @@ -3685,8 +3740,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp16 = doDEC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 3; m_icount -= 5; break; @@ -3696,8 +3753,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doDEC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 4; m_icount -= 5; break; @@ -3714,8 +3773,10 @@ void f2mc16_device::opcodes_ea73(u8 operand) { m_tmpea |= (m_dtb << 16); } + m_rmw = true; m_tmp16 = doDEC_16(read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 4; m_icount -= 5; break; @@ -4237,8 +4298,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) case 0x08: case 0x09: case 0x0a: case 0x0b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doADD_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 2; m_icount -= 7; break; @@ -4248,8 +4311,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = doADD_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 6; break; @@ -4259,8 +4324,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doADD_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 6; break; @@ -4278,8 +4345,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = doSUB_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 6; break; @@ -4289,8 +4358,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doSUB_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 6; break; @@ -4308,8 +4379,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = doSUBC_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 3; m_icount -= 6; break; @@ -4319,8 +4392,10 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = doSUBC_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); + m_rmw = false; m_pc += 4; m_icount -= 6; break; @@ -4341,9 +4416,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 &= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 3; @@ -4355,9 +4432,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 &= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 4; @@ -4380,9 +4459,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 |= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 3; @@ -4394,9 +4475,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 |= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 4; @@ -4419,9 +4502,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp8 = read_8((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 7) + s8(m_tmp8); m_tmpea = getRWbank(operand & 7, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 ^= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 4; @@ -4433,9 +4518,11 @@ void f2mc16_device::opcodes_ea75(u8 operand) m_tmp16 = read_16((m_pcb << 16) | (m_pc + 2)); m_tmp16 = read_rwX(operand & 3) + s16(m_tmp16); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp8 = read_8(m_tmpea); m_tmp8 ^= m_acc & 0xff; write_8(m_tmpea, m_tmp8); + m_rmw = false; setNZ_8(m_tmp8); m_ps &= ~F_V; m_pc += 4; @@ -4937,8 +5024,10 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0x08: case 0x09: case 0x0a: case 0x0b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doADD_16(read_16(m_tmpea), m_acc & 0xffff); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 2; m_icount -= 6; break; @@ -4955,8 +5044,10 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0x28: case 0x29: case 0x2a: case 0x2b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doSUB_16(read_16(m_tmpea), m_acc & 0xffff); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 2; m_icount -= 6; break; @@ -4982,8 +5073,10 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0x68: case 0x69: case 0x6a: case 0x6b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = doSUB_16(0, read_16(m_tmpea)); write_16(m_tmpea, m_tmp16); + m_rmw = false; m_pc += 2; m_icount -= 6; break; @@ -5003,9 +5096,11 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0x88: case 0x89: case 0x8a: case 0x8b: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = read_16(m_tmpea); m_tmp16 &= (m_acc & 0xffff); write_16(m_tmpea, m_tmp16); + m_rmw = false; setNZ_16(m_tmp16); m_ps &= ~F_V; m_pc += 2; @@ -5027,9 +5122,11 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0xa8: case 0xa9: case 0xaa: case 0xab: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = read_16(m_tmpea); m_tmp16 |= (m_acc & 0xffff); write_16(m_tmpea, m_tmp16); + m_rmw = false; setNZ_16(m_tmp16); m_ps &= ~F_V; m_pc += 2; @@ -5051,9 +5148,11 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0xc8: case 0xc9: case 0xca: case 0xcb: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = read_16(m_tmpea); m_tmp16 ^= (m_acc & 0xffff); write_16(m_tmpea, m_tmp16); + m_rmw = false; setNZ_16(m_tmp16); m_ps &= ~F_V; m_pc += 2; @@ -5074,8 +5173,10 @@ void f2mc16_device::opcodes_ea77(u8 operand) case 0xe8: case 0xe9: case 0xea: case 0xeb: m_tmp16 = read_rwX(operand & 3); m_tmpea = getRWbank(operand & 3, m_tmp16); + m_rmw = true; m_tmp16 = read_16(m_tmpea) ^ 0xffff; write_16(m_tmpea, m_tmp16); + m_rmw = false; setNZ_16(m_tmp16); m_ps &= ~F_V; m_pc += 2; @@ -5482,31 +5583,23 @@ void f2mc16_device::execute_set_input(int inputnum, int state) { } -void f2mc16_device::set_irq(int vector, int level) +void f2mc16_device::set_irq_level(int irq_level) { - if (m_vector_level[vector] != level) - { - m_outstanding_irqs++; - m_vector_level[vector] = level; -// printf("set_irq: vec %d, level %d, %d outstanding\n", vector, level, m_outstanding_irqs); - } + m_irq_level = (irq_level << 13) | 0x1fff; } -void f2mc16_device::clear_irq(int vector) +void f2mc16_device::take_irq_vector(uint8_t irq_vector) { - if (m_vector_level[vector] < 7) - { - m_outstanding_irqs--; - m_vector_level[vector] = 7; - //printf("clear_irq: vec %d, %d outstanding\n", vector, m_outstanding_irqs); - } + take_irq(); + + u32 uVecAddr = 0xfffffc - (irq_vector * 4); + m_pc = read_16(uVecAddr); + m_pcb = read_8(uVecAddr + 2); } -// note: this function must not use m_tmp16 unless you change RETI -void f2mc16_device::take_irq(int vector, int level) +// note: this function must not use m_tmp8/m_tmp16 +void f2mc16_device::take_irq() { - standard_irq_callback(vector, (m_pcb << 16) | m_pc); -// printf("take_irq: vector %d, level %d, old PC = %02x%04x\n", vector, level, m_pcb, m_pc); push_16_ssp(m_acc>>16); push_16_ssp(m_acc & 0xffff); push_16_ssp((m_dpr<<8) | m_adb); @@ -5515,11 +5608,4 @@ void f2mc16_device::take_irq(int vector, int level) push_16_ssp(m_ps); m_ps |= F_S; - m_ps &= ~0xe000; - m_ps |= (level & 7) << 13; - - u32 uVecAddr = 0xfffffc - (vector * 4); - m_pc = read_16(uVecAddr); - m_pcb = read_8(uVecAddr + 2); - //printf("New PC = %02x%04x, new level=%d\n", m_pcb, m_pc, m_ps>>13); } diff --git a/src/devices/cpu/f2mc16/f2mc16.h b/src/devices/cpu/f2mc16/f2mc16.h index ffacb4dd158..495722272e1 100644 --- a/src/devices/cpu/f2mc16/f2mc16.h +++ b/src/devices/cpu/f2mc16/f2mc16.h @@ -14,8 +14,6 @@ class f2mc16_device : public cpu_device { public: - friend class mb9061x_device; - enum { F2MC16_PC, F2MC16_PS, F2MC16_USP, F2MC16_SSP, F2MC16_ACC, @@ -40,6 +38,9 @@ public: // construction/destruction f2mc16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + bool rmw() { return m_rmw; } + void set_irq_level(int level); + protected: f2mc16_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); @@ -67,9 +68,11 @@ private: u16 m_pc, m_usp, m_ssp, m_ps, m_tmp16, m_tmp16aux; u8 m_pcb, m_dtb, m_usb, m_ssb, m_adb, m_dpr, m_tmp8, m_tmp8aux, m_shifted_carry, m_prefix; - u32 m_acc, m_temp, m_tmp32, m_tmpea; + u32 m_pcbase, m_acc, m_temp, m_tmp32, m_tmpea; s32 m_icount; bool m_prefix_valid; + u16 m_irq_level; + bool m_rmw; inline u8 read_8(u32 addr) { @@ -720,12 +723,8 @@ private: void opcodes_earwi7d(u8 operand); void opcodes_rwiea7f(u8 operand); - void set_irq(int vector, int level); - void clear_irq(int vector); - void take_irq(int vector, int level); - - int m_vector_level[256]; - int m_outstanding_irqs; + void take_irq(); + void take_irq_vector(uint8_t irq_vector); }; DECLARE_DEVICE_TYPE(F2MC16, f2mc16_device) diff --git a/src/devices/cpu/f2mc16/f2mc16_adc.cpp b/src/devices/cpu/f2mc16/f2mc16_adc.cpp new file mode 100644 index 00000000000..5be1b30cd4d --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_adc.cpp @@ -0,0 +1,304 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series ADC + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16_adc.h" + +namespace { + +struct ADCS { enum : uint16_t +{ + ANE = 7 << 0, + ANS = 7 << 3, + MD = 3 << 6, + MD_SINGLE_REACTIVATION = 0 << 6, + MD_SINGLE = 1 << 6, + MD_CONTINUOUS = 2 << 6, + MD_STOP = 3 << 6, + RESERVED = 1 << 8, + STRT = 1 << 9, + STS = 3 << 10, + STS_ATGX = 1 << 10, + STS_TIMER = 2 << 10, + PAUS = 1 << 12, + INTE = 1 << 13, + INT = 1 << 14, + BUSY = 1 << 15 +}; }; + +struct ADCR { enum : uint16_t +{ + D07 = 0xff << 0, + S10 = 1 << 15, + D89 = 3 << 8 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_ADC, f2mc16_adc_device, "f2mc16_adc", "F2MC16 ADC") + +f2mc16_adc_device::f2mc16_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t vector) : + f2mc16_adc_device(mconfig, tag, owner, clock) +{ + m_intc.set_tag(intc); + m_vector = vector; +} + +f2mc16_adc_device::f2mc16_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_ADC, tag, owner, clock), + m_intc(*this, finder_base::DUMMY_TAG), + m_channel_cb(*this, 0x000), + m_peripheral_clock_changed(attotime::zero), + m_internal_timer_changed(attotime::zero), + m_internal_timer_expired(attotime::never), + m_conversion_start_time(attotime::never), + m_conversion_finished(attotime::never), + m_peripheral_clock_hz(0), + m_internal_timer_hz(0), + m_conversion_ticks(0), + m_channel(-1), + m_atgx(1), + m_i2osclr(0), + m_adcs(0), + m_adcr(0) +{ +} + +void f2mc16_adc_device::device_start() +{ + m_timer = timer_alloc(FUNC(f2mc16_adc_device::timer_callback), this); + + save_item(NAME(m_peripheral_clock_changed)); + save_item(NAME(m_internal_timer_changed)); + save_item(NAME(m_internal_timer_expired)); + save_item(NAME(m_conversion_start_time)); + save_item(NAME(m_conversion_finished)); + save_item(NAME(m_peripheral_clock_hz)); + save_item(NAME(m_internal_timer_hz)); + save_item(NAME(m_conversion_ticks)); + save_item(NAME(m_channel)); + save_item(NAME(m_atgx)); + save_item(NAME(m_i2osclr)); + save_item(NAME(m_adcs)); + save_item(NAME(m_adcr)); +} + +void f2mc16_adc_device::device_reset() +{ + m_adcs = 0; + m_adcr &= ~ADCR::S10; + update(); +} + +void f2mc16_adc_device::device_clock_changed() +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_adc_device::update_peripheral_clock), this), clock()); + else + update_peripheral_clock(clock()); +} + +void f2mc16_adc_device::i2osclr(int state) +{ + if (state && !m_i2osclr) + { + m_adcs &= ~ADCS::INT; + + update(); + } + + m_i2osclr = state; +} + +void f2mc16_adc_device::internal_timer_hz(uint32_t hz) +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_adc_device::update_internal_timer), this), hz); + else + update_internal_timer(hz); +} + +void f2mc16_adc_device::atgx(int state) +{ + if (!m_atgx && state && (m_adcs & ADCS::STS_ATGX)) + { + trigger(); + update(); + } + + m_atgx = state; +} + +uint16_t f2mc16_adc_device::adcs_r() +{ + return m_adcs; +} + +void f2mc16_adc_device::adcs_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint16_t prev = m_adcs; + COMBINE_DATA(&m_adcs); + + if (ACCESSING_BITS_8_15) + { + m_adcs = m_adcs & (prev | ~(ADCS::BUSY | ADCS::INT | ADCS::PAUS)); + if (m_adcs != prev) + { + if (m_adcs & ADCS::STRT) + { + m_adcs &= ~ADCS::STRT; + trigger(); + } + + update(); + } + } +} + +uint16_t f2mc16_adc_device::adcr_r() +{ + if (!machine().side_effects_disabled()) + { + m_adcs &= ~ADCS::PAUS; + + if ((m_adcs & ADCS::BUSY) && (m_adcs & ADCS::MD) != ADCS::MD_STOP) + start_conversion(); + + update(); + } + + return m_adcr; +} + +void f2mc16_adc_device::adcr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + if (ACCESSING_BITS_8_15) + m_adcr = (m_adcr & ~ADCR::S10) | (data & ADCR::S10); +} + +void f2mc16_adc_device::trigger() +{ + if (!(m_adcs & ADCS::BUSY) || (m_adcs & ADCS::MD) == ADCS::MD_SINGLE_REACTIVATION) + { + m_channel = (m_adcs & ADCS::ANS) >> 3; + m_adcs |= ADCS::BUSY; + start_conversion(); + } + else if ((m_adcs & ADCS::MD) == ADCS::MD_STOP) + start_conversion(); +} + +TIMER_CALLBACK_MEMBER(f2mc16_adc_device::update_peripheral_clock) +{ + if (m_adcs & ADCS::BUSY) + update_conversion_ticks(); + + m_peripheral_clock_hz = param; + m_peripheral_clock_changed = machine().time(); + + if (m_adcs & ADCS::BUSY) + update(); +} + +TIMER_CALLBACK_MEMBER(f2mc16_adc_device::update_internal_timer) +{ + m_internal_timer_hz = param; + m_internal_timer_changed = machine().time(); + + if (m_adcs & ADCS::STS_TIMER) + update(); +} + +void f2mc16_adc_device::start_conversion() +{ + m_conversion_ticks = 98; +} + +void f2mc16_adc_device::update_conversion_ticks() +{ + if (!m_conversion_start_time.is_never()) + { + attotime now = machine().time(); + if (m_peripheral_clock_hz) + m_conversion_ticks -= ((now - m_conversion_start_time) + attotime::zero).as_ticks(m_peripheral_clock_hz); + m_conversion_start_time = now; + } +} + +void f2mc16_adc_device::update() +{ + attotime now = machine().time(); + + attotime event_time = attotime::never; + + if (m_conversion_finished <= now) + { + uint16_t data = m_channel_cb[m_channel](); + if (m_channel_cb[m_channel].isunset()) + logerror("unmapped read AN%d\n", m_channel); + + if (m_adcr & ADCR::S10) + m_adcr = (ADCR::S10) | data >> 2; + else + m_adcr = data; + + m_adcs |= ADCS::PAUS | ADCS::INT; + + if (m_channel == (m_adcs & ADCS::ANE)) + { + if ((m_adcs & ADCS::MD) == ADCS::MD_CONTINUOUS || (m_adcs & ADCS::MD) == ADCS::MD_STOP) + m_channel = (m_adcs & ADCS::ANS) >> 3; + else + m_adcs &= ~ADCS::BUSY; + } + else + m_channel = (m_channel + 1) & 7; + + m_conversion_ticks = 0; + m_conversion_start_time = attotime::never; + } + + if (!(m_adcs & ADCS::BUSY) && m_channel >= 0) + { + m_channel = -1; + m_conversion_ticks = 0; + m_conversion_start_time = attotime::never; + } + + if (m_conversion_start_time.is_never() && m_conversion_ticks && m_peripheral_clock_hz) + { + m_conversion_start_time = m_peripheral_clock_changed + attotime::from_ticks((now - m_peripheral_clock_changed).as_ticks(m_peripheral_clock_hz) + 1, m_peripheral_clock_hz); + if (m_conversion_start_time <= now) + m_conversion_start_time += attotime::from_ticks(1, m_peripheral_clock_hz); + } + + m_conversion_finished = m_conversion_start_time.is_never() || !m_peripheral_clock_hz ? attotime::never : + m_conversion_start_time + attotime::from_ticks(m_conversion_ticks, m_peripheral_clock_hz); + + if (event_time > m_conversion_finished) + event_time = m_conversion_finished; + + if (m_internal_timer_expired <= now) + trigger(); + + m_internal_timer_expired = !(m_adcs & ADCS::STS_TIMER) || !m_internal_timer_hz ? attotime::never : + m_internal_timer_changed + attotime::from_ticks((now - m_internal_timer_changed).as_ticks(m_internal_timer_hz) + 1, m_internal_timer_hz); + if (m_internal_timer_expired <= now) + m_internal_timer_expired += attotime::from_ticks(1, m_internal_timer_hz); + + if (event_time > m_internal_timer_expired) + event_time = m_internal_timer_expired; + + m_timer->adjust(event_time.is_never() ? event_time : event_time - now); + m_intc->set_irq(m_vector, (m_adcs & ADCS::INTE) && (m_adcs & ADCS::INT)); +} + +TIMER_CALLBACK_MEMBER(f2mc16_adc_device::timer_callback) +{ + update(); +} diff --git a/src/devices/cpu/f2mc16/f2mc16_adc.h b/src/devices/cpu/f2mc16/f2mc16_adc.h new file mode 100644 index 00000000000..5196904787b --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_adc.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series I/O Port + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_ADC_H +#define MAME_CPU_F2MC16_F2MC16_ADC_H + +#include "f2mc16_intc.h" + +#pragma once + +class f2mc16_adc_device : + public device_t +{ +public: + f2mc16_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t vector); + f2mc16_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template auto channel() { return m_channel_cb[N].bind(); } + + void i2osclr(int state); + + void internal_timer_hz(uint32_t hz); + void atgx(int state); + + uint16_t adcs_r(); + void adcs_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint16_t adcr_r(); + void adcr_w(offs_t offset, uint16_t data, uint16_t mem_mask); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_clock_changed() override; + virtual void device_reset() override ATTR_COLD; + + TIMER_CALLBACK_MEMBER(update_peripheral_clock); + TIMER_CALLBACK_MEMBER(update_internal_timer); + TIMER_CALLBACK_MEMBER(timer_callback); + + void trigger(); + void update(); + void start_conversion(); + void update_conversion_ticks(); + + required_device m_intc; + devcb_read16::array<16> m_channel_cb; + uint8_t m_vector; + + emu_timer *m_timer; + attotime m_peripheral_clock_changed; + attotime m_internal_timer_changed; + attotime m_internal_timer_expired; + attotime m_conversion_start_time; + attotime m_conversion_finished; + uint32_t m_peripheral_clock_hz; + uint32_t m_internal_timer_hz; + uint8_t m_conversion_ticks; + int8_t m_channel; + int8_t m_atgx; + int8_t m_i2osclr; + uint16_t m_adcs; + uint16_t m_adcr; +}; + +DECLARE_DEVICE_TYPE(F2MC16_ADC, f2mc16_adc_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_clock.cpp b/src/devices/cpu/f2mc16/f2mc16_clock.cpp new file mode 100644 index 00000000000..82111f60299 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_clock.cpp @@ -0,0 +1,355 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Clock Generator + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16_clock.h" + +namespace { + +struct CKSCR { enum : uint8_t +{ + RESERVED1 = 1 << 7, + MCM = 1 << 6, + WS = 3 << 4, + RESERVED2 = 1 << 3, + MCS = 1 << 2, + CS = 3 << 0 +}; }; + +struct LPMCR { enum : uint8_t +{ + RESERVED3 = (1 << 0), + CG = 3 << 1, + RESERVED4 = (1 << 3), + RST = 1 << 4, + SPL = 1 << 5, + SLP = 1 << 6, + STP = 1 << 7 +}; }; + +struct TBTC { enum : uint8_t +{ + TEST = 1 << 7, + TBIE = 1 << 4, + TBOF = 1 << 3, + TBR = 1 << 2, + TBC = 3 << 0, + TBC_2_12 = 0 << 0, + TBC_2_14 = 1 << 0, + TBC_2_16 = 2 << 0, + TBC_2_19 = 3 << 0, +}; }; + +struct WDTC { enum : uint8_t +{ + WT = 3 << 0, + WTE = 1 << 2, + SRST = 1 << 3, + ERST = 1 << 4, + WRST = 1 << 5, + STBR = 1 << 6, + PONR = 1 << 7 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_CLOCK_GENERATOR, f2mc16_clock_generator_device, "f2mc16_clock_generator", "F2MC16 Clock Generator") + +f2mc16_clock_generator_device::f2mc16_clock_generator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t tbtc_vector) : + f2mc16_clock_generator_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast(owner); + m_intc.set_tag(intc); + m_tbtc_vector = tbtc_vector; +} + +f2mc16_clock_generator_device::f2mc16_clock_generator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_CLOCK_GENERATOR, tag, owner, clock), + m_cpu(nullptr), + m_intc(*this, finder_base::DUMMY_TAG), + m_tbtc_vector(0), + m_timebase_hz_cb(*this), + m_timebase_start_time(attotime::zero), + m_tbtc_overflow_time(attotime::never), + m_watchdog_overflow_time(attotime::never), + m_mainclock_changed(attotime::zero), + m_timebase_counter(0), + m_tbtc_hz(0), + m_mainclock_hz(0), + m_reset_reason(WDTC::PONR), + m_watchdog_overflow_count(0), + m_wt(0), + m_ckscr(0), + m_lpmcr(0), + m_tbtc(0), + m_wdtc(WDTC::WTE | WDTC::WT) +{ +} + +void f2mc16_clock_generator_device::device_start() +{ + m_timebase_timer = timer_alloc(FUNC(f2mc16_clock_generator_device::timebase_timer_callback), this); + + save_item(NAME(m_timebase_start_time)); + save_item(NAME(m_tbtc_overflow_time)); + save_item(NAME(m_mainclock_changed)); + save_item(NAME(m_timebase_counter)); + save_item(NAME(m_tbtc_hz)); + save_item(NAME(m_mainclock_hz)); + save_item(NAME(m_reset_reason)); + save_item(NAME(m_ckscr)); + save_item(NAME(m_lpmcr)); + save_item(NAME(m_tbtc)); + save_item(NAME(m_wdtc)); +} + +void f2mc16_clock_generator_device::device_clock_changed() +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_clock_generator_device::update_mainclock_hz), this), m_cpu->unscaled_clock()); + else + update_mainclock_hz(m_cpu->unscaled_clock()); +} + +void f2mc16_clock_generator_device::device_reset() +{ + if (!m_reset_reason) + m_reset_reason = WDTC::ERST; + + m_ckscr = ~CKSCR::MCS; + m_lpmcr = LPMCR::RESERVED4 | LPMCR::RESERVED3 | LPMCR::RST; + m_wdtc |= m_reset_reason | WDTC::WTE | WDTC::WT; + m_tbtc = TBTC::TEST | TBTC::TBR; + m_reset_reason = 0; + m_watchdog_overflow_time = attotime::never; + + timebase_reset(); + timebase_update(); +} + +uint8_t f2mc16_clock_generator_device::ckscr_r() +{ + return m_ckscr; +} + +void f2mc16_clock_generator_device::ckscr_w(uint8_t data) +{ + data = (m_ckscr & ~(CKSCR::WS | CKSCR::MCS | CKSCR::CS)) | (data & (CKSCR::WS | CKSCR::MCS | CKSCR::CS)); + + if (m_ckscr != data) + { + if (!(m_ckscr & CKSCR::MCS) && (data & CKSCR::MCS)) + { + timebase_reset(); + timebase_update(); + } + + m_ckscr = data; + + m_cpu->set_clock_scale((m_ckscr & CKSCR::MCS) ? 1 : (m_ckscr & CKSCR::CS) + 1); + } +} + +uint8_t f2mc16_clock_generator_device::lpmcr_r() +{ + return m_lpmcr & (LPMCR::SPL | LPMCR::CG); +} + +void f2mc16_clock_generator_device::lpmcr_w(uint8_t data) +{ + data |= LPMCR::RESERVED4 | LPMCR::RESERVED3; + + if (m_lpmcr != data) + { + m_lpmcr = data; + + if (!(m_lpmcr & LPMCR::RST)) + { + m_lpmcr |= LPMCR::RST; + m_reset_reason |= WDTC::SRST; + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_clock_generator_device::soft_reset), this)); + } + } +} + +TIMER_CALLBACK_MEMBER(f2mc16_clock_generator_device::soft_reset) +{ + m_cpu->reset(); +} + +uint8_t f2mc16_clock_generator_device::wdtc_r() +{ + uint8_t data = m_wdtc; + + if (!machine().side_effects_disabled()) + m_wdtc &= ~(WDTC::PONR | WDTC::STBR | WDTC::WRST | WDTC::SRST); + + return data | WDTC::WTE | WDTC::WT; +} + +void f2mc16_clock_generator_device::wdtc_w(uint8_t data) +{ + uint8_t prev = m_wdtc; + m_wdtc = data & (m_wdtc | ~WDTC::WTE); + + if (!(data & WDTC::WTE)) + { + m_watchdog_overflow_count = 0; + + if (prev & WDTC::WTE) + { + m_wt = m_wdtc & WDTC::WT; + + timebase_update_counter(); + timebase_update(); + } + } +} + +uint8_t f2mc16_clock_generator_device::tbtc_r() +{ + if (!m_cpu->rmw() && m_tbtc_overflow_time > machine().time()) + return m_tbtc & ~TBTC::TBOF; + + return m_tbtc; +} + +void f2mc16_clock_generator_device::tbtc_w(uint8_t data) +{ + if (m_tbtc != data) + { + timebase_update_counter(); + + m_tbtc = data; + + if (!(data & TBTC::TBR)) + { + timebase_reset(); + m_tbtc |= TBTC::TBR; + } + + if (!(data & TBTC::TBOF)) + { + if (m_tbtc_overflow_time <= machine().time()) + m_tbtc_overflow_time = attotime::never; + + m_tbtc |= TBTC::TBOF; + } + + timebase_update(); + } +} + +void f2mc16_clock_generator_device::timebase_reset() +{ + m_timebase_counter = 0; + m_timebase_start_time = attotime::never; + m_tbtc_overflow_time = attotime::never; + m_tbtc_hz = 0; +} + +void f2mc16_clock_generator_device::timebase_update() +{ + static const int cycles[4] = { 1 << 12, 1 << 14, 1 << 16, 1 << 19 }; + attotime now = machine().time(); + + if (m_timebase_start_time == attotime::never) + m_timebase_start_time = now; + + uint32_t event_ticks = 0; + attotime event_time = attotime::never; + + if (m_tbtc_overflow_time > now) + { + uint32_t tbtc_ticks = cycles[m_tbtc & TBTC::TBC] - (m_timebase_counter & (cycles[m_tbtc & TBTC::TBC] - 1)); + m_tbtc_overflow_time = m_timebase_start_time.is_never() || !m_mainclock_hz ? attotime::never : + m_timebase_start_time + attotime::from_ticks(tbtc_ticks, m_mainclock_hz); + + if ((m_tbtc & TBTC::TBIE) && event_time > m_tbtc_overflow_time) + { + event_time = m_tbtc_overflow_time; + event_ticks = tbtc_ticks; + } + } + + if (!(m_wdtc & WDTC::WTE)) + { + if (m_watchdog_overflow_time < now) + { + m_watchdog_overflow_count++; + if (m_watchdog_overflow_count == 4) + { + m_reset_reason |= WDTC::WRST; + m_cpu->reset(); + } + } + + uint32_t watchdog_ticks = cycles[m_wt] - (m_timebase_counter & (cycles[m_wt] - 1)); + attotime wdof = m_timebase_start_time.is_never() || !m_mainclock_hz ? attotime::never : + m_timebase_start_time + attotime::from_ticks(watchdog_ticks, m_mainclock_hz); + m_watchdog_overflow_time = wdof; + + if (event_time > wdof) + { + event_time = wdof; + event_ticks = watchdog_ticks; + } + } + + if (m_tbtc_hz != m_mainclock_hz && !m_timebase_hz_cb.isunset()) + { + if ((m_timebase_counter % 512) != 0 && m_mainclock_hz) + { + uint32_t sync_ticks = 512 - (m_timebase_counter & (512 - 1)); + attotime sync_time = m_timebase_start_time.is_never() || !m_mainclock_hz ? attotime::never : + m_timebase_start_time + attotime::from_ticks(sync_ticks, m_mainclock_hz); + + if (event_time > sync_time) + { + event_time = sync_time; + event_ticks = sync_ticks; + } + } + else + { + m_timebase_hz_cb(m_mainclock_hz / 512); + m_tbtc_hz = m_mainclock_hz; + } + } + + m_timebase_timer->adjust(event_time.is_never() ? event_time : event_time - now, event_ticks); + m_intc->set_irq(m_tbtc_vector, ((m_tbtc & TBTC::TBIE) && m_tbtc_overflow_time <= now) ? 1 : 0); +} + +void f2mc16_clock_generator_device::timebase_update_counter() +{ + attotime now = machine().time(); + uint64_t ticks = ((now - m_timebase_start_time) + attotime::zero).as_ticks(m_mainclock_hz); + m_timebase_counter += ticks; + m_timebase_counter &= 0x3ffff; + m_timebase_start_time = now; +} + +TIMER_CALLBACK_MEMBER(f2mc16_clock_generator_device::update_mainclock_hz) +{ + timebase_update_counter(); + + m_mainclock_hz = param; + m_mainclock_changed = machine().time(); + + timebase_update(); +} + +TIMER_CALLBACK_MEMBER(f2mc16_clock_generator_device::timebase_timer_callback) +{ + m_timebase_counter += param; + m_timebase_counter &= 0x3ffff; + m_timebase_start_time = machine().time(); + + timebase_update(); +} diff --git a/src/devices/cpu/f2mc16/f2mc16_clock.h b/src/devices/cpu/f2mc16/f2mc16_clock.h new file mode 100644 index 00000000000..c0774bb2a90 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_clock.h @@ -0,0 +1,74 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Clock Generator + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_CLOCK_H +#define MAME_CPU_F2MC16_F2MC16_CLOCK_H + +#pragma once + +#include "f2mc16.h" +#include "f2mc16_intc.h" + +class f2mc16_clock_generator_device : + public device_t +{ +public: + f2mc16_clock_generator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t m_tbtc_vector); + f2mc16_clock_generator_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + auto timebase_hz() { return m_timebase_hz_cb.bind(); } + + uint8_t lpmcr_r(); + void lpmcr_w(uint8_t data); + + uint8_t wdtc_r(); + void wdtc_w(uint8_t data); + + uint8_t tbtc_r(); + void tbtc_w(uint8_t data); + uint8_t ckscr_r(); + void ckscr_w(uint8_t data); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_clock_changed() override; + virtual void device_reset() override ATTR_COLD; + + void timebase_reset(); + void timebase_update(); + void timebase_update_counter(); + TIMER_CALLBACK_MEMBER(soft_reset); + TIMER_CALLBACK_MEMBER(update_mainclock_hz); + TIMER_CALLBACK_MEMBER(timebase_timer_callback); + + f2mc16_device *m_cpu; + required_device m_intc; + uint8_t m_tbtc_vector; + devcb_write32 m_timebase_hz_cb; + + emu_timer *m_timebase_timer; + attotime m_timebase_start_time; + attotime m_tbtc_overflow_time; + attotime m_watchdog_overflow_time; + attotime m_mainclock_changed; + uint32_t m_timebase_counter; + uint32_t m_tbtc_hz; + uint32_t m_mainclock_hz; + uint8_t m_reset_reason; + uint8_t m_watchdog_overflow_count; + uint8_t m_wt; + uint8_t m_ckscr; + uint8_t m_lpmcr; + uint8_t m_tbtc; + uint8_t m_wdtc; +}; + +DECLARE_DEVICE_TYPE(F2MC16_CLOCK_GENERATOR, f2mc16_clock_generator_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_intc.cpp b/src/devices/cpu/f2mc16/f2mc16_intc.cpp new file mode 100644 index 00000000000..b9ba1bf65e4 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_intc.cpp @@ -0,0 +1,269 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Interrupt Controller/EI2OS + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16.h" +#include "f2mc16_intc.h" + +namespace { + +struct ICR { enum : uint16_t +{ + IL = 7 << 0, + ISE = 1 << 3, + S = 3 << 4, + S_COUNT_COMPLETION = 1 << 4, + S_COMPLETION_REQUEST = 3 << 4, + ICS = 15 << 4, +}; }; + +struct ISCS { enum : uint8_t +{ + RESERVED = 7 << 5, + IF = 1 << 4, + BW = 1 << 3, + BF = 1 << 2, + DIR = 1 << 1, + SE = 1 << 0 +}; }; + +struct DIRR { enum : uint16_t +{ + R0 = 1 << 0 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_INTC, f2mc16_intc_device, "f2mc16_intc", "F2MC16 INTC") + +f2mc16_intc_device::f2mc16_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_INTC, tag, owner, clock), + m_cpu(nullptr), + m_i2osclr_cb(*this), + m_digm_vector(0x2a), + m_irq_state(0), + m_completion_request_state(0), + m_active_irq(0) +{ +} + +void f2mc16_intc_device::device_start() +{ + m_cpu = downcast(owner()); + std::fill_n(m_icr, std::size(m_icr), ICR::IL); + std::fill_n(m_ics, std::size(m_ics), 0); + save_item(NAME(m_icr)); + save_item(NAME(m_dirr)); + save_item(NAME(m_enir)); + save_item(NAME(m_eirr)); + save_item(NAME(m_elvr)); + save_item(NAME(m_irq_state)); + save_item(NAME(m_completion_request_state)); + save_item(NAME(m_active_irq)); +} + +void f2mc16_intc_device::device_reset() +{ + std::fill_n(m_icr, std::size(m_icr), ICR::IL); + m_enir = 0; + m_eirr = 0; + m_elvr = 0; + m_dirr = 0; +} + +uint8_t f2mc16_intc_device::icr_r(offs_t offset) +{ + return m_icr[offset]; +} + +void f2mc16_intc_device::icr_w(offs_t offset, uint8_t data) +{ + m_ics[offset] = (data & ICR::ICS) >> 4; + m_icr[offset] = (m_icr[offset] & ICR::ICS) | (data & ~ICR::ICS); + update(); +} + +uint8_t f2mc16_intc_device::enir_r() +{ + return m_enir; +} + +void f2mc16_intc_device::enir_w(uint8_t data) +{ + m_enir = data; +} + +uint8_t f2mc16_intc_device::eirr_r() +{ + if (m_cpu->rmw()) + return 0xff; + return m_eirr; +} + +void f2mc16_intc_device::eirr_w(uint8_t data) +{ + m_eirr &= data; +} + +uint8_t f2mc16_intc_device::elvr_r(offs_t offset) +{ + if (offset == 0) + return m_elvr >> 0; + else + return m_elvr >> 8; +} + +void f2mc16_intc_device::elvr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + COMBINE_DATA(&m_elvr); +} + +uint8_t f2mc16_intc_device::dirr_r() +{ + return m_dirr; +} + +void f2mc16_intc_device::dirr_w(uint8_t data) +{ + data &= DIRR::R0; + + if (m_dirr != data) + { + m_dirr = data; + + set_irq(m_digm_vector, m_dirr & DIRR::R0); + } +} + +void f2mc16_intc_device::set_irq(uint8_t vector, int state) +{ + int irq = vector - m_external_interrupt_vector; + + if (BIT(m_irq_state, irq) != state) + { + if (state) + m_irq_state |= 1 << irq; + else + m_irq_state &= ~(1 << irq); + + update(); + } +} + +void f2mc16_intc_device::set_completion_request(uint8_t vector, int state) +{ + int irq = vector - m_external_interrupt_vector; + + if (state) + m_completion_request_state |= 1 << irq; + else + m_completion_request_state &= ~(1 << irq); +} + +void f2mc16_intc_device::update() +{ + int level = 7; + + if (m_irq_state) + for (int i = 0; i < 32; i++) + { + if (BIT(m_irq_state, i)) + { + int il = m_icr[i / 2] & ICR::IL; + if (level > il) + { + m_active_irq = i; + level = il; + } + } + } + + m_cpu->set_irq_level(level); +} + +IRQ_CALLBACK_MEMBER(f2mc16_intc_device::irq_acknowledge_callback) +{ + int irq = m_active_irq; + int icr = irq / 2; + + if (m_icr[icr] & ICR::ISE) + { + offs_t isd = 0x100 + (m_ics[icr] * 8); + address_space &space = m_cpu->space(AS_PROGRAM); + uint8_t iscs = space.read_byte(isd + 3); m_cpu->adjust_icount(-1); + + m_icr[icr] &= ~ICR::S; + + if ((iscs & ISCS::SE) && BIT(m_completion_request_state, irq)) + { + m_icr[icr] &= ~ICR::ISE; + m_icr[icr] |= ICR::S_COMPLETION_REQUEST; + } + else + { + uint32_t bap = space.read_word(isd + 0) | (space.read_byte(isd + 2) << 16); m_cpu->adjust_icount(-1); + uint16_t ioa = space.read_word(isd + 4); m_cpu->adjust_icount(-1); + uint16_t dc = space.read_word(isd + 6); m_cpu->adjust_icount(-1); + + uint16_t data = (iscs & ISCS::DIR) ? + ((iscs & ISCS::BW) ? + space.read_word(bap) : + space.read_byte(bap)) : + ((iscs & ISCS::BW) ? + space.read_word(ioa) : + space.read_byte(ioa)); + m_cpu->adjust_icount(-1); + + if (iscs & ISCS::DIR) + { + if (iscs & ISCS::BW) + space.write_word(ioa, data); + else + space.write_byte(ioa, data); + } + else + { + if (iscs & ISCS::BW) + space.write_word(bap, data); + else + space.write_byte(bap, data); + } + + m_cpu->adjust_icount(-1); + + if (!(iscs & ISCS::BF)) + { + space.write_word(isd + 0, bap + ((iscs & ISCS::BW) ? 2 : 1)); m_cpu->adjust_icount(-1); + } + + if (!(iscs & ISCS::IF)) + { + space.write_word(isd + 4, ioa + ((iscs & ISCS::BW) ? 2 : 1)); m_cpu->adjust_icount(-1); + } + + dc--; + space.write_word(isd + 6, dc); m_cpu->adjust_icount(-1); + + if (!m_i2osclr_cb[irq].isunset()) + { + m_i2osclr_cb[irq](1); + m_i2osclr_cb[irq](0); + } + + if (dc == 0) + { + m_icr[icr] &= ~ICR::ISE; + m_icr[icr] |= ICR::S_COUNT_COMPLETION; + } + else + return 0; + } + } + + return irq + m_external_interrupt_vector; +} diff --git a/src/devices/cpu/f2mc16/f2mc16_intc.h b/src/devices/cpu/f2mc16/f2mc16_intc.h new file mode 100644 index 00000000000..8389bce1efb --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_intc.h @@ -0,0 +1,64 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series INTC + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_INTC_H +#define MAME_CPU_F2MC16_F2MC16_INTC_H + +#pragma once + +#include "f2mc16.h" + +class f2mc16_intc_device : + public device_t +{ +public: + f2mc16_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template auto i2osclr() { return m_i2osclr_cb[N - m_external_interrupt_vector].bind(); } + + uint8_t icr_r(offs_t offset); + void icr_w(offs_t offset, uint8_t data); + uint8_t enir_r(); + void enir_w(uint8_t data); + uint8_t eirr_r(); + void eirr_w(uint8_t data); + uint8_t elvr_r(offs_t offset); + void elvr_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint8_t dirr_r(); + void dirr_w(uint8_t data); + + void set_irq(uint8_t vector, int state); + void set_completion_request(uint8_t vector, int state); + IRQ_CALLBACK_MEMBER(irq_acknowledge_callback); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void update(); + + f2mc16_device *m_cpu; + devcb_write_line::array<0x20> m_i2osclr_cb; + static constexpr uint8_t m_external_interrupt_vector = 0x0b; + uint8_t m_digm_vector; + + uint8_t m_icr[0x10]; + uint8_t m_ics[0x10]; + uint8_t m_dirr; + uint8_t m_enir; + uint8_t m_eirr; + uint16_t m_elvr; + uint32_t m_irq_state; + uint32_t m_completion_request_state; + uint8_t m_active_irq; +}; + +DECLARE_DEVICE_TYPE(F2MC16_INTC, f2mc16_intc_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_port.cpp b/src/devices/cpu/f2mc16/f2mc16_port.cpp new file mode 100644 index 00000000000..1d32afe5a37 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_port.cpp @@ -0,0 +1,127 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series I/O Port + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16.h" +#include "f2mc16_port.h" + +DEFINE_DEVICE_TYPE(F2MC16_PORT, f2mc16_port_device, "f2mc16_port", "F2MC16 Port") + +f2mc16_port_device::f2mc16_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_PORT, tag, owner, clock), + m_cpu(nullptr), + m_defval(0), + m_mask(0), + m_read_cb(*this, 0xff), + m_write_cb(*this), + m_pdr(0xff), + m_output(0) +{ +} + +f2mc16_port_device::f2mc16_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint8_t defval, uint8_t mask) : + f2mc16_port_device(mconfig, tag, owner) +{ + m_cpu = downcast(owner); + m_defval = defval; + m_mask = mask; +} + +void f2mc16_port_device::device_start() +{ + save_item(NAME(m_pdr)); + save_item(NAME(m_ddr)); + save_item(NAME(m_ader)); + save_item(NAME(m_output)); +} + +void f2mc16_port_device::device_reset() +{ + if (m_defval) + m_pdr = m_defval; + m_ddr = m_defval; + m_ader = m_defval; + + update_output(true); +} + +uint8_t f2mc16_port_device::pdr_r() +{ + uint8_t mask = ~m_ddr & m_mask; + + if (mask) + { + if (!m_read_cb.isunset()) + return (m_read_cb(0, mask) & mask) | (m_pdr & m_ddr); + else if (!machine().side_effects_disabled()) + logerror("%s unmapped read %02x\n", machine().describe_context(), mask); + return m_pdr | mask; + } + + return m_pdr; +} + +uint8_t f2mc16_port_device::pdr_adc_r() +{ + if (m_cpu->rmw()) + return m_pdr; + + uint8_t mask = ~m_ader & m_pdr & m_mask; + + if (mask) + { + if (!m_read_cb.isunset()) + return m_read_cb(0, mask) & mask; + else if (!machine().side_effects_disabled()) + logerror("%s unmapped read (mask=0x%02x)\n", machine().describe_context(), mask); + } + + return 0x00; +} + +void f2mc16_port_device::pdr_w(uint8_t data) +{ + m_pdr = data & m_mask; + update_output(); +} + +uint8_t f2mc16_port_device::ddr_r() +{ + return m_ddr; +} + +void f2mc16_port_device::ddr_w(uint8_t data) +{ + m_ddr = data & m_mask; + update_output(); +} + +uint8_t f2mc16_port_device::ader_r() +{ + return m_ader; +} + +void f2mc16_port_device::ader_w(uint8_t data) +{ + m_ader = data; +} + +void f2mc16_port_device::update_output(bool initial) +{ + uint8_t output = m_pdr | (~m_ddr & m_mask); + + if (m_output != output || initial) + { + m_output = output; + + if (!m_write_cb.isunset()) + m_write_cb(0, m_output, m_ddr & m_mask); + else if (!initial) + logerror("%s unmapped write %02x (mask=0x%02x)\n", machine().describe_context(), m_pdr & m_ddr, m_ddr); + } +} diff --git a/src/devices/cpu/f2mc16/f2mc16_port.h b/src/devices/cpu/f2mc16/f2mc16_port.h new file mode 100644 index 00000000000..30b487136e4 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_port.h @@ -0,0 +1,57 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Port + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_PORT_H +#define MAME_CPU_F2MC16_F2MC16_PORT_H + +#pragma once + +#include "f2mc16.h" + +class f2mc16_port_device : + public device_t +{ +public: + f2mc16_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint8_t defval, uint8_t mask); + f2mc16_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + auto read() { return m_read_cb.bind(); } + auto write() { return m_write_cb.bind(); } + + uint8_t pdr_r(); + uint8_t pdr_adc_r(); + void pdr_w(uint8_t data); + + uint8_t ddr_r(); + void ddr_w(uint8_t data); + + uint8_t ader_r(); + void ader_w(uint8_t data); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void update_output(bool initial = false); + + f2mc16_device *m_cpu; + uint8_t m_defval; + uint8_t m_mask; + devcb_read8 m_read_cb; + devcb_write8 m_write_cb; + + uint8_t m_pdr; + uint8_t m_ddr; + uint8_t m_ader; + uint8_t m_output; +}; + +DECLARE_DEVICE_TYPE(F2MC16_PORT, f2mc16_port_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_ppg.cpp b/src/devices/cpu/f2mc16/f2mc16_ppg.cpp new file mode 100644 index 00000000000..547a993f420 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_ppg.cpp @@ -0,0 +1,348 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Programmable Pulse Generator + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16_ppg.h" + +namespace { + +struct PPGC { enum : uint8_t +{ + PEN = 1 << 7, + PCS = 1 << 6, // channel 1 + POE = 1 << 5, + PIE = 1 << 4, + PUF = 1 << 3, + PCM = 3 << 1, // channel 0 + PCM_DIV1 = 0 << 1, + PCM_DIV4 = 1 << 1, + PCM_DIV16 = 2 << 1, + PCM_TIMEBASE = 3 << 1, + MD = 3 << 1, // channel 1 + MD_2_CHANNEL = 0 << 1, + MD_SINGLE_CHANNEL_8BIT_PRESCALER = 1 << 1, + MD_SINGLE_CHANNEL_16BIT = 3 << 1, + RESERVED = 1 << 0 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_PPG, f2mc16_ppg_device, "f2mc16_ppg", "F2MC16 Programmable Pulse Generator") + +f2mc16_ppg_device::f2mc16_ppg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t ppg0_vector, uint8_t ppg1_vector) : + f2mc16_ppg_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast(owner); + m_intc.set_tag(intc); + m_vector[0] = ppg0_vector; + m_vector[1] = ppg1_vector; +} + +f2mc16_ppg_device::f2mc16_ppg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_PPG, tag, owner, clock), + m_cpu(nullptr), + m_intc(*this, finder_base::DUMMY_TAG), + m_vector{ 0,0 }, + m_output_cb(*this), + m_peripheral_clock_hz(0), + m_peripheral_clock_changed(attotime::zero), + m_timebase_hz(0), + m_timebase_changed(attotime::zero), + m_clocksel(), + m_hz(), + m_duty(), + m_pcnt(), + m_pcntrl(), + m_lh(), + m_ppgc(), + m_prll(), + m_prlh() +{ +} + +void f2mc16_ppg_device::device_start() +{ + m_timer[0] = timer_alloc(FUNC(f2mc16_ppg_device::timer_callback<0>), this); + m_timer[1] = timer_alloc(FUNC(f2mc16_ppg_device::timer_callback<1>), this); + m_start_time[0] = attotime::never; + m_start_time[1] = attotime::never; + + save_item(NAME(m_peripheral_clock_hz)); + save_item(NAME(m_timebase_hz)); + save_item(NAME(m_start_time)); + save_item(NAME(m_underflow_time)); + save_item(NAME(m_clocksel)); + save_item(NAME(m_hz)); + save_item(NAME(m_duty)); + save_item(NAME(m_pcnt)); + save_item(NAME(m_pcntrl)); + save_item(NAME(m_lh)); + save_item(NAME(m_ppgc)); + save_item(NAME(m_prll)); + save_item(NAME(m_prlh)); +} + +void f2mc16_ppg_device::device_clock_changed() +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_ppg_device::update_peripheral_clock), this), clock()); + else + update_peripheral_clock(clock()); +} + +void f2mc16_ppg_device::device_reset() +{ + update_pcnt(); + + for (int i = 0; i < 2; i++) + m_ppgc[i] = PPGC::PUF | PPGC::RESERVED; + + update(); +} + +void f2mc16_ppg_device::timebase_hz(uint32_t hz) +{ + if (started() && machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_ppg_device::update_timebase_hz), this), hz); + else + update_timebase_hz(hz); +} + +uint8_t f2mc16_ppg_device::ppgc_r(offs_t offset) +{ + if (!m_cpu->rmw() && m_underflow_time[offset] >= machine().time()) + return m_ppgc[offset] & ~PPGC::PUF; + + return m_ppgc[offset]; +} + +void f2mc16_ppg_device::ppgc_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint16_t ppgc = (m_ppgc[1] << 8) | m_ppgc[0]; + uint16_t prev = ppgc; + COMBINE_DATA(&ppgc); + + if (ppgc != prev) + { + update_pcnt(); + + m_ppgc[0] = ppgc >> 0; + m_ppgc[1] = ppgc >> 8; + + if (ACCESSING_BITS_0_7 && !(m_ppgc[0] & PPGC::PUF) && m_underflow_time[0] <= machine().time()) + { + m_ppgc[0] |= PPGC::PUF; + m_underflow_time[0] = attotime::never; + } + + if (ACCESSING_BITS_8_15 && !(m_ppgc[1] & PPGC::PUF) && m_underflow_time[1] <= machine().time()) + { + m_ppgc[1] |= PPGC::PUF; + m_underflow_time[1] = attotime::never; + } + + update(); + } +} + +template +uint16_t f2mc16_ppg_device::prl_r() +{ + return (m_prlh[N] << 8) | m_prll[N]; +} + +template +void f2mc16_ppg_device::prl_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint16_t prl = (m_prlh[N] << 8) | m_prll[N]; + uint16_t prev = prl; + COMBINE_DATA(&prl); + if (prl != prev) + { + update_pcnt(); + + m_prll[N] = prl >> 0; + m_prlh[N] = prl >> 8; + + update(); + } +} + +void f2mc16_ppg_device::update() +{ + attotime now = machine().time(); + + for (int i = 0; i < 2; i++) + { + bool start = false; + + if (!(m_ppgc[i] & PPGC::PEN)) + m_start_time[i] = attotime::never; + else if (m_start_time[i].is_never()) + { + m_start_time[i] = now; + start = true; + } + + uint8_t pcm = (i == 0 || (m_ppgc[1] & PPGC::MD) != PPGC::MD_2_CHANNEL) ? + (m_ppgc[0] & PPGC::PCM) : + (m_ppgc[1] & PPGC::PCS) ? PPGC::PCM_TIMEBASE : PPGC::PCM_DIV1; + + m_clocksel[i] = m_start_time[i].is_never() ? 0 : + (pcm == PPGC::PCM_DIV1) ? m_peripheral_clock_hz : + (pcm == PPGC::PCM_DIV4) ? m_peripheral_clock_hz / 4 : + (pcm == PPGC::PCM_DIV16) ? m_peripheral_clock_hz / 16 : + (pcm == PPGC::PCM_TIMEBASE) ? m_timebase_hz : + 0; + + if ((m_ppgc[1] & PPGC::MD) == PPGC::MD_2_CHANNEL) + { + m_pcntrl[i][0] = m_prll[i] + 1; + m_pcntrl[i][1] = m_prlh[i] + 1; + } + else if ((m_ppgc[1] & PPGC::MD) == PPGC::MD_SINGLE_CHANNEL_8BIT_PRESCALER) + { + if (i == 0) + { + m_pcntrl[i][0] = m_prll[i] + 1; + m_pcntrl[i][1] = m_prlh[i] + 1; + } + else + { + uint16_t prescale = (m_prll[0] + 1) + (m_prlh[0] + 1); + m_pcntrl[i][0] = (m_prll[i] + 1) * prescale; + m_pcntrl[i][1] = (m_prlh[i] + 1) * prescale; + } + } + else if ((m_ppgc[1] & PPGC::MD) == PPGC::MD_SINGLE_CHANNEL_16BIT) + { + m_pcntrl[i][0] = ((m_prll[1] << 8) | m_prll[0]) + 1; + m_pcntrl[i][1] = ((m_prlh[1] << 8) | m_prlh[0]) + 1; + } + else + { + m_pcntrl[i][0] = 0; + m_pcntrl[i][1] = 0; + } + + if (start) + m_pcnt[i][m_lh[i]] = m_pcntrl[i][m_lh[i]]; + + m_pcnt[i][!m_lh[i]] = m_pcntrl[i][!m_lh[i]]; + + attotime event_time = attotime::never; + + attotime puf = m_start_time[i].is_never() || !m_clocksel[i] ? attotime::never : + m_start_time[i] + attotime::from_ticks(m_pcnt[i][m_lh[i]], m_clocksel[i]); + + if (m_underflow_time[i] > now) + { + m_underflow_time[i] = puf; + + if ((m_ppgc[i] & PPGC::PIE) && event_time > puf) + event_time = puf; + } + + uint32_t total = (m_ppgc[i] & PPGC::POE) ? m_pcntrl[i][0] + m_pcntrl[i][1] : 0; + uint32_t hz = total ? m_clocksel[i] / total : 0; + uint32_t duty = hz ? (0x100000000ULL * m_pcntrl[i][1]) / total : 0; + + if (m_hz[i] != hz || m_duty[i] != duty) + { + if ((m_lh[i] || m_pcnt[i][0] != m_pcntrl[i][0] || m_pcnt[i][1] != m_pcntrl[i][1]) && hz) + { + if (event_time > puf) + event_time = puf; + } + else + { + if (!m_output_cb[i].isunset()) + m_output_cb[i](0, hz, duty); + else if ((m_ppgc[1] & PPGC::MD) != PPGC::MD_SINGLE_CHANNEL_8BIT_PRESCALER || (m_output_cb[0].isunset() && m_output_cb[1].isunset())) + logerror("%s PPG%d unmapped write %d, %d, %08x\n", machine().describe_context(), i, 0, hz, duty); + + m_hz[i] = hz; + m_duty[i] = duty; + } + } + + m_timer[i]->adjust(event_time.is_never() ? event_time : event_time - now); + m_intc->set_irq(m_vector[i], ((m_ppgc[i] & PPGC::PIE) && m_underflow_time[i] <= now) ? 1 : 0); + } +} + +void f2mc16_ppg_device::update_pcnt() +{ + for (int i = 0; i < 2; i++) + { + if (m_start_time[i] != attotime::never) + { + attotime now = machine().time(); + int64_t ticks = (now - m_start_time[i]).as_ticks(m_clocksel[i]); + + for (int p = 0; p < 4 && ticks; p++) + { + if (m_pcnt[i][m_lh[i]] > ticks) + { + m_pcnt[i][m_lh[i]] -= ticks; + ticks = 0; + } + else + { + ticks -= m_pcnt[i][m_lh[i]]; + m_pcnt[i][m_lh[i]] = m_pcntrl[i][m_lh[i]]; + m_lh[i] = !m_lh[i]; + } + + if (p == 1 && (m_pcntrl[i][0] + m_pcntrl[i][1])) + ticks %= (m_pcntrl[i][0] + m_pcntrl[i][1]); + } + + m_start_time[i] = now; + } + } +} + +TIMER_CALLBACK_MEMBER(f2mc16_ppg_device::update_timebase_hz) +{ + update_pcnt(); + + m_timebase_hz = param; + + if (started()) + { + m_timebase_changed = machine().time(); + + update(); + } +} + +TIMER_CALLBACK_MEMBER(f2mc16_ppg_device::update_peripheral_clock) +{ + update_pcnt(); + + m_peripheral_clock_hz = param; + m_peripheral_clock_changed = machine().time(); + + update(); +} + +template +TIMER_CALLBACK_MEMBER(f2mc16_ppg_device::timer_callback) +{ + m_lh[N] = !m_lh[N]; + m_pcnt[N][m_lh[N]] = m_pcntrl[N][m_lh[N]]; + m_start_time[N] = machine().time(); + + update(); +} + +template uint16_t f2mc16_ppg_device::prl_r<0>(); +template uint16_t f2mc16_ppg_device::prl_r<1>(); +template void f2mc16_ppg_device::prl_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask); +template void f2mc16_ppg_device::prl_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask); diff --git a/src/devices/cpu/f2mc16/f2mc16_ppg.h b/src/devices/cpu/f2mc16/f2mc16_ppg.h new file mode 100644 index 00000000000..3022e8593e5 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_ppg.h @@ -0,0 +1,70 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series Programmable Pulse Generator + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_PPG_H +#define MAME_CPU_F2MC16_F2MC16_PPG_H + +#pragma once + +#include "f2mc16.h" +#include "f2mc16_intc.h" + +class f2mc16_ppg_device : + public device_t +{ +public: + f2mc16_ppg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t vector0, uint8_t vector1); + f2mc16_ppg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template auto output() { return m_output_cb[N].bind(); } + + void timebase_hz(uint32_t hz); + + uint8_t ppgc_r(offs_t offset); + void ppgc_w(offs_t offset, uint16_t data, uint16_t mem_mask); + template uint16_t prl_r(); + template void prl_w(offs_t offset, uint16_t data, uint16_t mem_mask); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_clock_changed() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void update(); + void update_pcnt(); + TIMER_CALLBACK_MEMBER(update_timebase_hz); + TIMER_CALLBACK_MEMBER(update_peripheral_clock); + template TIMER_CALLBACK_MEMBER(timer_callback); + + f2mc16_device *m_cpu; + required_device m_intc; + uint8_t m_vector[2]; + devcb_write32::array<2> m_output_cb; + uint32_t m_peripheral_clock_hz; + attotime m_peripheral_clock_changed; + uint32_t m_timebase_hz; + attotime m_timebase_changed; + + emu_timer *m_timer[2]; + attotime m_start_time[2]; + attotime m_underflow_time[2]; + uint32_t m_clocksel[2]; + uint32_t m_hz[2]; + uint32_t m_duty[2]; + uint16_t m_pcnt[2][2]; + uint16_t m_pcntrl[2][2]; + uint8_t m_lh[2]; + uint8_t m_ppgc[2]; + uint8_t m_prll[2]; + uint8_t m_prlh[2]; +}; + +DECLARE_DEVICE_TYPE(F2MC16_PPG, f2mc16_ppg_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_reload.cpp b/src/devices/cpu/f2mc16/f2mc16_reload.cpp new file mode 100644 index 00000000000..33ff2aa53b5 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_reload.cpp @@ -0,0 +1,381 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series 16-bit timer + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16_reload.h" + +namespace { + +struct TMCSR { enum : uint16_t +{ + CSL = 3 << 10, + CSL_DIV2 = 0 << 10, + CSL_DIV8 = 1 << 10, + CSL_DIV32 = 2 << 10, + CSL_EXTERNAL = 3 << 10, + MOD2 = 1 << 9, + MOD1 = 1 << 8, + MOD0 = 1 << 7, + MOD_INT = 7 << 7, + MOD_EXT = 3 << 7, + MOD_DISABLE = 0 << 7, + MOD_RISING = 1 << 7, + MOD_FALLING = 2 << 7, + MOD_BOTH = 3 << 7, + MOD_GATE = 5 << 7, + MOD_GATE_LOW = 4 << 7, + MOD_GATE_HIGH = 5 << 7, + OUTE = 1 << 6, + OUTL = 1 << 5, + RELD = 1 << 4, + INTE = 1 << 3, + UF = 1 << 2, + CNTE = 1 << 1, + TRG = 1 << 0 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_RELOAD_TIMER, f2mc16_reload_timer_device, "f2mc16_reload_timer", "F2MC16 16-bit reload timer") + +f2mc16_reload_timer_device::f2mc16_reload_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t vector) : + f2mc16_reload_timer_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast(owner); + m_intc.set_tag(intc); + m_vector = vector; +} + +f2mc16_reload_timer_device::f2mc16_reload_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_RELOAD_TIMER, tag, owner, clock), + m_cpu(nullptr), + m_intc(*this, finder_base::DUMMY_TAG), + m_vector(0), + m_internal_hz_cb(*this), + m_tot_hz_cb(*this), + m_peripheral_clock_changed(attotime::zero), + m_tin_changed(attotime::zero), + m_start_time(attotime::never), + m_underflow_time(attotime::never), + m_clocksel(0), + m_peripheral_clock_hz(0), + m_tin_hz(0), + m_internal_hz(0), + m_tot_hz(0), + m_tin(1), + m_i2osclr(0), + m_tmcsr(TMCSR::UF), + m_tmr(0), + m_tmrlr(0) +{ +} + +void f2mc16_reload_timer_device::device_start() +{ + m_timer = timer_alloc(FUNC(f2mc16_reload_timer_device::timer_callback), this); + + save_item(NAME(m_peripheral_clock_changed)); + save_item(NAME(m_tin_changed)); + save_item(NAME(m_start_time)); + save_item(NAME(m_underflow_time)); + save_item(NAME(m_clocksel)); + save_item(NAME(m_peripheral_clock_hz)); + save_item(NAME(m_tin_hz)); + save_item(NAME(m_internal_hz)); + save_item(NAME(m_tot_hz)); + save_item(NAME(m_tin)); + save_item(NAME(m_i2osclr)); + save_item(NAME(m_tmcsr)); + save_item(NAME(m_tmr)); + save_item(NAME(m_tmrlr)); +} + +void f2mc16_reload_timer_device::device_clock_changed() +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_reload_timer_device::update_peripheral_clock), this), clock()); + else + update_peripheral_clock(clock()); +} + +void f2mc16_reload_timer_device::device_reset() +{ + update_tmr(); + m_tmcsr = TMCSR::UF; + update(); +} + +void f2mc16_reload_timer_device::tin_hz(uint32_t hz) +{ + if (started() && machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_reload_timer_device::update_tin_hz), this), hz); + else + update_tin_hz(hz); +} + +void f2mc16_reload_timer_device::tin(int state) +{ + bool rising_edge = (state && !m_tin); + bool falling_edge = (!state && m_tin); + + if (m_tin_hz == 0 && (m_tmcsr & TMCSR::CNTE) && (rising_edge || falling_edge)) + { + if ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_EXTERNAL) + { + if ((((m_tmcsr & TMCSR::MOD_EXT) == TMCSR::MOD_RISING) && rising_edge) || + (((m_tmcsr & TMCSR::MOD_EXT) == TMCSR::MOD_RISING) && falling_edge) || + ((m_tmcsr & TMCSR::MOD_EXT) == TMCSR::MOD_BOTH)) + { + m_tmr--; + + if (m_tmr == 0xffff) + { + if (m_tmcsr & TMCSR::RELD) + m_tmr = m_tmrlr; + else + m_start_time = attotime::never; + + m_underflow_time = machine().time(); + update(); + } + } + } + else + { + if ((((m_tmcsr & TMCSR::MOD_INT) == TMCSR::MOD_RISING) && rising_edge) || + (((m_tmcsr & TMCSR::MOD_INT) == TMCSR::MOD_RISING) && falling_edge) || + ((m_tmcsr & TMCSR::MOD_INT) == TMCSR::MOD_BOTH)) + { + trigger(); + update(); + } + else if ((m_tmcsr & TMCSR::MOD_GATE) == TMCSR::MOD_GATE_LOW || + (m_tmcsr & TMCSR::MOD_GATE) == TMCSR::MOD_GATE_HIGH) + { + update_tmr(); + update(); + } + } + } + + m_tin = state; +} + +void f2mc16_reload_timer_device::i2osclr(int state) +{ + if (state && !m_i2osclr) + { + update_tmr(); + + m_underflow_time = attotime::never; + + update(); + } + + m_i2osclr = state; +} + +uint16_t f2mc16_reload_timer_device::tmcsr_r(offs_t offset, uint16_t mem_mask) +{ + if (ACCESSING_BITS_0_7 && !m_cpu->rmw() && m_underflow_time > machine().time()) + return m_tmcsr & ~TMCSR::UF; + + return m_tmcsr; +} + +void f2mc16_reload_timer_device::tmcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint16_t tmcsr = m_tmcsr; + COMBINE_DATA(&tmcsr); + tmcsr &= TMCSR::CSL | TMCSR::MOD_INT | TMCSR::OUTE | TMCSR::OUTL | TMCSR::RELD | TMCSR::INTE | TMCSR::UF | TMCSR::CNTE | TMCSR::TRG; + + if (m_tmcsr != tmcsr) + { + update_tmr(); + + m_tmcsr = tmcsr; + + if (ACCESSING_BITS_0_7) + { + if (m_tmcsr & TMCSR::TRG) + { + if (m_tmcsr & TMCSR::CNTE) + trigger(); + + m_tmcsr &= ~TMCSR::TRG; + } + + if (!(m_tmcsr & TMCSR::UF)) + { + if (m_underflow_time <= machine().time()) + m_underflow_time = attotime::never; + + m_tmcsr |= TMCSR::UF; + } + } + + update(); + } +} + +uint16_t f2mc16_reload_timer_device::tmr_r() +{ + return calculate_tmr(); +} + +void f2mc16_reload_timer_device::tmrlr_w(offs_t offset, uint16_t data, uint16_t mem_mask) +{ + uint32_t tmrlr = m_tmrlr; + COMBINE_DATA(&tmrlr); + + if (m_tmrlr != tmrlr) + { + if (m_tmcsr & TMCSR::RELD) + update_tmr(); + + m_tmrlr = tmrlr; + + if (m_tmcsr & TMCSR::RELD) + update(); + } +} + +void f2mc16_reload_timer_device::update() +{ + attotime now = machine().time(); + + if (!(m_tmcsr & TMCSR::CNTE)) + m_start_time = attotime::never; + + m_clocksel = m_start_time.is_never() ? 0 : + ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_EXTERNAL) ? + (((m_tmcsr & TMCSR::MOD_EXT) == TMCSR::MOD_DISABLE) ? 0 : + ((m_tmcsr & TMCSR::MOD_EXT) == TMCSR::MOD_BOTH) ? m_tin_hz * 2 : + m_tin_hz) : + (((m_tmcsr & TMCSR::MOD_GATE) == TMCSR::MOD_GATE_LOW && m_tin) ? 0 : + ((m_tmcsr & TMCSR::MOD_GATE) == TMCSR::MOD_GATE_HIGH && !m_tin) ? 0 : + ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_DIV2) ? clock() / 2 : + ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_DIV8) ? clock() / 8 : + ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_DIV32) ? clock() / 32 : + 0); + + attotime event_time = attotime::never; + + attotime uf = (m_start_time.is_never() || !m_clocksel) ? attotime::never : + m_start_time + attotime::from_ticks(m_tmr + 1, m_clocksel); + + if (m_underflow_time > now) + { + m_underflow_time = uf; + + if ((m_tmcsr & TMCSR::INTE) && event_time > uf) + event_time = uf; + } + + uint32_t internal_hz = (m_tmcsr & TMCSR::RELD) ? m_clocksel / (m_tmrlr + 1) / 2: 0; + uint32_t tot_hz = (m_tmcsr & TMCSR::OUTE) ? internal_hz : 0; + + if ((m_internal_hz != internal_hz && !m_internal_hz_cb.isunset()) || + (m_tot_hz != tot_hz && !m_tot_hz_cb.isunset())) + { + if (m_tmr != m_tmrlr && (m_tmcsr & TMCSR::RELD) && internal_hz) + { + if (event_time > uf) + event_time = uf; + } + else + { + if (m_internal_hz != internal_hz && !m_internal_hz_cb.isunset()) + { + m_internal_hz_cb(internal_hz); + m_internal_hz = internal_hz; + } + + if (m_tot_hz != tot_hz && !m_tot_hz_cb.isunset()) + { + m_tot_hz_cb(tot_hz); + m_tot_hz = tot_hz; + } + } + } + + m_timer->adjust(event_time.is_never() ? event_time : event_time - now); + m_intc->set_irq(m_vector, ((m_tmcsr & TMCSR::INTE) && m_underflow_time <= now) ? 1 : 0); +} + +void f2mc16_reload_timer_device::trigger() +{ + m_tmr = m_tmrlr; + m_start_time = machine().time(); +} + +void f2mc16_reload_timer_device::update_tmr() +{ + m_tmr = calculate_tmr(); + if (m_start_time != attotime::never) + m_start_time = machine().time(); +} + +uint16_t f2mc16_reload_timer_device::calculate_tmr() +{ + if (m_start_time.is_never() || m_clocksel == 0) + return m_tmr; + + uint64_t ticks = (machine().time() - m_start_time).as_ticks(m_clocksel); + if (m_tmr >= ticks) + return m_tmr - ticks; + + if (m_tmcsr & TMCSR::RELD) + return m_tmrlr - ((ticks - m_tmr - 1) % (m_tmrlr + 1)); + + return 0xffff; +} + +TIMER_CALLBACK_MEMBER(f2mc16_reload_timer_device::update_tin_hz) +{ + if ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_EXTERNAL) + update_tmr(); + + m_tin_hz = param; + + if (started()) + { + m_tin_changed = machine().time(); + + if ((m_tmcsr & TMCSR::CSL) == TMCSR::CSL_EXTERNAL) + update(); + } +} + +TIMER_CALLBACK_MEMBER(f2mc16_reload_timer_device::update_peripheral_clock) +{ + if ((m_tmcsr & TMCSR::CSL) != TMCSR::CSL_EXTERNAL) + update_tmr(); + + m_peripheral_clock_hz = param; + m_peripheral_clock_changed = machine().time(); + + if ((m_tmcsr & TMCSR::CSL) != TMCSR::CSL_EXTERNAL) + update(); +} + +TIMER_CALLBACK_MEMBER(f2mc16_reload_timer_device::timer_callback) +{ + if (m_tmcsr & TMCSR::RELD) + { + m_tmr = m_tmrlr; + m_start_time = machine().time(); + } + else + { + m_tmr = 0xffff; + m_start_time = attotime::never; + } + + update(); +} diff --git a/src/devices/cpu/f2mc16/f2mc16_reload.h b/src/devices/cpu/f2mc16/f2mc16_reload.h new file mode 100644 index 00000000000..185f2bbabb3 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_reload.h @@ -0,0 +1,75 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series 16-bit reload timer + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_TIMER_H +#define MAME_CPU_F2MC16_F2MC16_TIMER_H + +#pragma once + +#include "f2mc16_intc.h" + +class f2mc16_reload_timer_device : + public device_t +{ +public: + f2mc16_reload_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t vector); + f2mc16_reload_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + auto internal_hz() { return m_internal_hz_cb.bind(); } + auto tot_hz() { return m_tot_hz_cb.bind(); } + + void tin_hz(const XTAL xtal) { tin_hz(xtal.value()); } + void tin_hz(uint32_t hz); + void tin(int state); + void i2osclr(int state); + + uint16_t tmcsr_r(offs_t offset, uint16_t mem_mask); + void tmcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask); + uint16_t tmr_r(); + void tmrlr_w(offs_t offset, uint16_t data, uint16_t mem_mask); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_clock_changed() override; + virtual void device_reset() override ATTR_COLD; + + void update(); + void trigger(); + void update_tmr(); + uint16_t calculate_tmr(); + TIMER_CALLBACK_MEMBER(update_tin_hz); + TIMER_CALLBACK_MEMBER(update_peripheral_clock); + TIMER_CALLBACK_MEMBER(timer_callback); + + f2mc16_device *m_cpu; + required_device m_intc; + uint8_t m_vector; + devcb_write32 m_internal_hz_cb; + devcb_write32 m_tot_hz_cb; + + emu_timer *m_timer; + attotime m_peripheral_clock_changed; + attotime m_tin_changed; + attotime m_start_time; + attotime m_underflow_time; + uint32_t m_clocksel; + uint32_t m_peripheral_clock_hz; + uint32_t m_tin_hz; + uint32_t m_internal_hz; + uint32_t m_tot_hz; + int8_t m_tin; + int8_t m_i2osclr; + uint16_t m_tmcsr; + uint16_t m_tmr; + uint16_t m_tmrlr; +}; + +DECLARE_DEVICE_TYPE(F2MC16_RELOAD_TIMER, f2mc16_reload_timer_device) + +#endif diff --git a/src/devices/cpu/f2mc16/f2mc16_uart.cpp b/src/devices/cpu/f2mc16/f2mc16_uart.cpp new file mode 100644 index 00000000000..80dbb75fe93 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_uart.cpp @@ -0,0 +1,456 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series UART + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16_uart.h" + +#define LOG_READ (1U << 1) +#define LOG_WRITE (1U << 2) + +//#define VERBOSE (LOG_GENERAL | LOG_READ | LOG_WRITE) +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +#define LOGREAD(...) LOGMASKED(LOG_READ, __VA_ARGS__) +#define LOGWRITE(...) LOGMASKED(LOG_WRITE, __VA_ARGS__) + +namespace { + +struct SMR { enum : uint8_t +{ + SOE = 1 << 0, + SCKE = 1 << 1, + CS = 7 << 3, + CS_RESERVED = 5 << 3, + CS_INTERNAL_TIMER = 6 << 3, + CS_EXTERNAL_CLOCK = 7 << 3, + MD = 3 << 6, + MD_ASYNC_NORMAL = 0 << 6, + MD_ASYNC_MULTIPROCESSOR = 1 << 6, + MD_SYNC = 2 << 6, + MD_PROHIBITED = 3 << 6 +}; }; + +struct SCR { enum : uint8_t +{ + PEN = 1 << 7, + P = 1 << 6, + SBL = 1 << 5, + CL = 1 << 4, + AD = 1 << 3, + REC = 1 << 2, + RXE = 1 << 1, + TXE = 1 << 0 +}; }; + +struct SSR { enum : uint8_t +{ + PE = 1 << 7, + ORE = 1 << 6, + FRE = 1 << 5, + RDRF = 1 << 4, + TDRE = 1 << 3, + RIE = 1 << 1, + TIE = 1 << 0 +}; }; + +struct CDCR { enum : uint8_t +{ + DIV = 15 << 0 +}; }; + +} // anonymous namespace + +DEFINE_DEVICE_TYPE(F2MC16_UART, f2mc16_uart_device, "f2mc16_uart", "F2MC16 UART") + +f2mc16_uart_device::f2mc16_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t rx_vector, uint8_t tx_vector) : + f2mc16_uart_device(mconfig, tag, owner, clock) +{ + m_intc.set_tag(intc); + m_rx_vector = rx_vector; + m_tx_vector = tx_vector; +} + +f2mc16_uart_device::f2mc16_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, F2MC16_UART, tag, owner, clock), + m_intc(*this, finder_base::DUMMY_TAG), + m_sck_cb(*this), + m_sck_hz_cb(*this), + m_sot_cb(*this), + m_internal_timer_changed(attotime::zero), + m_internal_timer_hz(0), + m_peripheral_clock_hz(0), + m_sck_in_hz(0), + m_sck_in(1), + m_sck_out(1), + m_sck_out_hz(0), + m_sin(1), + m_sin_prev(0), + m_sot(1), + m_hz(0), + m_clock_count(0), + m_tx_bit(-1), + m_tx_bits(0), + m_tx_shift(0), + m_rx_bit(-1), + m_rx_shift(0), + m_smr(0), + m_sidr(0), + m_sodr(0) +{ +} + +void f2mc16_uart_device::device_start() +{ + m_rx_timer = timer_alloc(FUNC(f2mc16_uart_device::rx_timer_callback), this); + m_tx_timer = timer_alloc(FUNC(f2mc16_uart_device::tx_timer_callback), this); + + save_item(NAME(m_internal_timer_changed)); + save_item(NAME(m_rx_start_time)); + save_item(NAME(m_tx_start_time)); + save_item(NAME(m_rx_ticks)); + save_item(NAME(m_tx_ticks)); + save_item(NAME(m_sck_in)); + save_item(NAME(m_sck_in_hz)); + save_item(NAME(m_sck_out)); + save_item(NAME(m_sck_out_hz)); + save_item(NAME(m_sin)); + save_item(NAME(m_sin_prev)); + save_item(NAME(m_sot)); + save_item(NAME(m_internal_timer_hz)); + save_item(NAME(m_hz)); + save_item(NAME(m_clock_count)); + save_item(NAME(m_tx_bit)); + save_item(NAME(m_tx_bits)); + save_item(NAME(m_tx_shift)); + save_item(NAME(m_rx_bit)); + save_item(NAME(m_rx_shift)); + save_item(NAME(m_smr)); + save_item(NAME(m_scr)); + save_item(NAME(m_sidr)); + save_item(NAME(m_sodr)); + save_item(NAME(m_ssr)); + save_item(NAME(m_cdcr)); + + m_sck_cb(m_sck_out); + m_sck_hz_cb(m_sck_out_hz); + m_sot_cb(m_sot); + + update_serial(); +} + +void f2mc16_uart_device::device_reset() +{ + m_smr = 0; + m_scr = SCR::REC; + m_ssr = SSR::TDRE; + m_cdcr = CDCR::DIV; + + update_serial(); +} + +void f2mc16_uart_device::device_clock_changed() +{ + m_peripheral_clock_hz = clock(); + update_serial(); +} + +void f2mc16_uart_device::internal_timer_hz(uint32_t hz) +{ + if (machine().scheduler().currently_executing()) + machine().scheduler().synchronize(timer_expired_delegate(FUNC(f2mc16_uart_device::update_internal_timer), this), hz); + else + update_internal_timer(hz); +} + +void f2mc16_uart_device::internal_timer(int state) +{ + // TODO: +} + +void f2mc16_uart_device::sck_hz(uint32_t hz) +{ + // TODO: track when hz changes. + m_sck_in_hz = hz; + + update_serial(); +} + +void f2mc16_uart_device::sck(int state) +{ + if (m_sck_in != state) + { + m_sck_in = state; + + update_serial(); + } +} + +void f2mc16_uart_device::sin(int state) +{ + if (m_sin != state) + { + m_sin = state; + + update_serial(); + } +} + +uint8_t f2mc16_uart_device::smr_r() +{ + return m_smr; +} + +void f2mc16_uart_device::smr_w(uint8_t data) +{ + m_smr = data & (SMR::MD | SMR::CS | SMR::SCKE | SMR::SOE); + + update_serial(); +} + +uint8_t f2mc16_uart_device::scr_r() +{ + return m_scr | SMR::CS; +} + +void f2mc16_uart_device::scr_w(uint8_t data) +{ + if (!(data & SCR::REC)) + { + m_ssr &= ~(SSR::PE | SSR::ORE | SSR::FRE); + data |= SCR::REC; + } + + m_scr = data & (SCR::PEN | SCR::P | SCR::SBL | SCR::CL | SCR::AD | SCR::REC | SCR::RXE | SCR::TXE); + + update_serial(); +} + +uint8_t f2mc16_uart_device::sidr_r() +{ + if (!machine().side_effects_disabled()) + { + LOGREAD("%s read data %02x\n",machine().describe_context(), tag(), m_sidr); + + if (m_ssr & SSR::RDRF) + { + m_ssr &= ~SSR::RDRF; + update_serial(); + } + } + + return m_sidr; +} + +void f2mc16_uart_device::sodr_w(uint8_t data) +{ + LOGWRITE("%s write data %02x\n", machine().describe_context(), data); + + m_sodr = data; + m_ssr &= ~SSR::TDRE; + + update_serial(); +} + +uint8_t f2mc16_uart_device::ssr_r() +{ + return m_ssr; +} + +void f2mc16_uart_device::ssr_w(uint8_t data) +{ + m_ssr = (m_ssr & ~(SSR::TIE | SSR::RIE)) | (data & (SSR::TIE | SSR::RIE)); + + update_serial(); +} + +void f2mc16_uart_device::cdcr_w(uint8_t data) +{ + m_cdcr = data & CDCR::DIV; + + update_serial(); +} + +TIMER_CALLBACK_MEMBER(f2mc16_uart_device::update_internal_timer) +{ + m_internal_timer_hz = param; + m_internal_timer_changed = machine().time(); + + update_serial(); +} + +void f2mc16_uart_device::update_serial() +{ + const int clock_counts[] = { 16, 16, 1, 0 }; + const int baud_rate_generator[][5] = + { + { 13, 4, 26, 52, 104 }, + { 0, 0, 2, 4, 8 } + }; + + uint8_t clock_count = clock_counts[(m_smr & SMR::MD) >> 6]; + uint32_t hz; + + if ((m_smr & SMR::CS) == SMR::CS_RESERVED) + hz = 0; + else if ((m_smr & SMR::CS) == SMR::CS_INTERNAL_TIMER) + hz = m_internal_timer_hz; + else if ((m_smr & SMR::CS) == SMR::CS_EXTERNAL_CLOCK) + hz = (m_smr & SMR::SCKE) ? 0 : m_sck_in_hz; + else if (baud_rate_generator[(m_smr & SMR::MD) == SMR::MD_SYNC][(m_smr & SMR::CS) >> 3]) + hz = m_peripheral_clock_hz / (0x10 - m_cdcr) / baud_rate_generator[(m_smr & SMR::MD) == SMR::MD_SYNC][(m_smr & SMR::CS) >> 3]; + else + hz = 0; + + //if (m_hz != hz || m_clock_count != clock_count) + //printf("%s baud %d\n", tag(), clock_count ? (hz / clock_count) : 0); + + m_clock_count = clock_count; + m_hz = hz; + + uint32_t sck_out_clock = (m_smr & SMR::SCKE) ? m_hz : 0; + if (m_sck_out_hz != sck_out_clock) + { + m_sck_out_hz = sck_out_clock; + m_sck_hz_cb(m_sck_out_hz); + } + + if (!m_sin && m_sin_prev && m_rx_bit < 0 && + ((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL || (m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR)) + m_rx_timer->adjust(attotime::from_hz((m_hz / m_clock_count) * 2)); + + m_sin_prev = m_sin; + + if (m_tx_bit < 0 && !(m_ssr & SSR::TDRE)) + m_tx_timer->adjust(attotime::zero); + + m_intc->set_irq(m_tx_vector, (m_ssr & SSR::TIE) && (m_ssr & SSR::TDRE)); + m_intc->set_irq(m_rx_vector, (m_ssr & SSR::RIE) && (m_ssr & SSR::RDRF)); + m_intc->set_completion_request(m_rx_vector, (SSR::PE | SSR::ORE | SSR::FRE) != 0); +} + +TIMER_CALLBACK_MEMBER(f2mc16_uart_device::rx_timer_callback) +{ + int data_bits = ((m_smr & SMR::MD) != SMR::MD_ASYNC_NORMAL || (m_scr & SCR::CL)) ? 8 : 7; + int parity_bits = ((m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR || + ((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL && (m_scr & SCR::P))) ? 1 : 0; + int start_stop_bits = (((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL || + (m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR)) ? 2 : 0; + int length = data_bits + parity_bits + start_stop_bits; + + if (m_rx_bit < 0) + { + if (start_stop_bits && m_sin) + return; + + m_rx_bit = 0; + m_rx_shift = 0; + } + + if (m_sin) + m_rx_shift |= 1 << m_rx_bit; + m_rx_bit++; + + if (m_rx_bit >= length) + { + if ((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL || + (m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR) + { + m_rx_shift >>= 1; + + if (!m_sin) + m_ssr |= SSR::FRE; + + if ((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL && (m_scr & SCR::PEN)) + { + int parity = (m_scr & SCR::P) ? 1 : 0; + for (int i = 0; i < data_bits; i++) + parity ^= BIT(m_rx_shift, i); + + if (parity) + m_ssr |= SSR::PE; + } + + if (!(m_rx_shift & (1 << data_bits))) + m_ssr |= SSR::FRE; + } + + m_rx_bit = -1; + + if (m_ssr & SSR::RDRF) + m_ssr |= SSR::ORE; + else + { + m_ssr |= SSR::RDRF; + m_sidr = BIT(m_rx_shift, 0, data_bits); + } + + update_serial(); + return; + } + + m_rx_timer->adjust(attotime::from_hz(m_hz / m_clock_count)); +} + +TIMER_CALLBACK_MEMBER(f2mc16_uart_device::tx_timer_callback) +{ + if (m_tx_bit == m_tx_bits) + m_tx_bit = -1; + + if (m_tx_bit < 0) + { + if (!(m_ssr & SSR::TDRE)) + { + m_tx_bit = 0; + m_tx_bits = ((m_smr & SMR::MD) != SMR::MD_ASYNC_NORMAL || (m_scr & SCR::CL)) ? 8 : 7; + m_tx_shift = BIT(m_sodr, 0, m_tx_bits); + + if ((m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR) + { + if (m_scr & SCR::AD) + m_tx_shift |= 1 << m_tx_bits; + m_tx_bits++; + } + else if ((m_scr & SCR::PEN) && (m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL) + { + int parity = (m_scr & SCR::P) ? 1 : 0; + for (int i = 0; i < m_tx_bits; i++) + parity ^= BIT(m_tx_shift, i); + + if (parity) + m_tx_shift |= 1 << m_tx_bits; + m_tx_bits++; + } + + if ((m_smr & SMR::MD) == SMR::MD_ASYNC_NORMAL || + (m_smr & SMR::MD) == SMR::MD_ASYNC_MULTIPROCESSOR) + { + int stop_bits = (m_scr & SCR::SBL) ? 2 : 1; + for (int i = 0; i < stop_bits; i++) + { + m_tx_shift |= 1 << m_tx_bits; + m_tx_bits++; + } + + m_tx_shift <<= 1; + m_tx_bits++; + } + else if (m_rx_bit < 0 && (m_scr & SCR::RXE) && (m_smr & SMR::MD) == SMR::MD_SYNC) + m_rx_timer->adjust(attotime::from_hz((m_hz / m_clock_count) * 2)); + + m_ssr |= SSR::TDRE; + update_serial(); + } + else + return; + } + + m_sot_cb(BIT(m_tx_shift, m_tx_bit)); + m_tx_bit++; + m_tx_timer->adjust(attotime::from_hz(m_hz / m_clock_count)); +} diff --git a/src/devices/cpu/f2mc16/f2mc16_uart.h b/src/devices/cpu/f2mc16/f2mc16_uart.h new file mode 100644 index 00000000000..c24c1d4e243 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16_uart.h @@ -0,0 +1,98 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/*************************************************************************** + + Fujitsu Micro F2MC-16 series UART + +***************************************************************************/ + +#ifndef MAME_CPU_F2MC16_F2MC16_UART_H +#define MAME_CPU_F2MC16_F2MC16_UART_H + +#include "f2mc16_intc.h" + +#pragma once + +class f2mc16_uart_device : + public device_t +{ +public: + f2mc16_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + f2mc16_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, required_device &intc, uint8_t rx_vector, uint8_t tx_vector); + + auto sck() { return m_sck_cb.bind(); } + auto sck_hz() { return m_sck_hz_cb.bind(); } + auto sot() { return m_sot_cb.bind(); } + + void internal_timer_hz(uint32_t hz); + void internal_timer(int state); + void sck_hz(uint32_t hz); + void sck(int state); + void sin(int state); + + uint8_t smr_r(); + void smr_w(uint8_t data); + uint8_t scr_r(); + void scr_w(uint8_t data); + uint8_t sidr_r(); + void sodr_w(uint8_t data); + uint8_t ssr_r(); + void ssr_w(uint8_t data); + void cdcr_w(uint8_t data); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_clock_changed() override; + virtual void device_reset() override ATTR_COLD; + + void update_serial(); + TIMER_CALLBACK_MEMBER(update_internal_timer); + TIMER_CALLBACK_MEMBER(rx_timer_callback); + TIMER_CALLBACK_MEMBER(tx_timer_callback); + + required_device m_intc; + uint8_t m_rx_vector; + uint8_t m_tx_vector; + devcb_write_line m_sck_cb; + devcb_write32 m_sck_hz_cb; + devcb_write_line m_sot_cb; + + emu_timer *m_tx_timer; + emu_timer *m_rx_timer; + + attotime m_sck_in_changed; + attotime m_peripheral_clock_changed; + attotime m_internal_timer_changed; + attotime m_rx_start_time; + attotime m_tx_start_time; + uint32_t m_internal_timer_hz; + uint32_t m_peripheral_clock_hz; + uint32_t m_sck_in_hz; + + uint8_t m_rx_ticks; + uint8_t m_tx_ticks; + int8_t m_sck_in; + int8_t m_sck_out; + uint32_t m_sck_out_hz; + int8_t m_sin; + int8_t m_sin_prev; + int8_t m_sot; + uint32_t m_hz; + uint8_t m_clock_count; + int8_t m_tx_bit; + int8_t m_tx_bits; + uint16_t m_tx_shift; + int8_t m_rx_bit; + uint16_t m_rx_shift; + uint8_t m_smr; + uint8_t m_scr; + uint8_t m_sidr; + uint8_t m_sodr; + uint8_t m_ssr; + uint8_t m_cdcr; +}; + +DECLARE_DEVICE_TYPE(F2MC16_UART, f2mc16_uart_device) + +#endif diff --git a/src/devices/cpu/f2mc16/mb90570.cpp b/src/devices/cpu/f2mc16/mb90570.cpp new file mode 100644 index 00000000000..ebc4e88a614 --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90570.cpp @@ -0,0 +1,169 @@ +// license:BSD-3-Clause +// copyright-holders:smf + +#include "emu.h" +#include "mb90570.h" + +DEFINE_DEVICE_TYPE(MB90F574, mb90f574_device, "mb90f574", "Fujitsu MB90F574") + +mb90f574_device::mb90f574_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb90570_device(mconfig, MB90F574, tag, owner, clock, 0x28ff) +{ +} + +mb90570_device::mb90570_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t internal_ram_end) : + f2mc16_device(mconfig, type, tag, owner, clock), + m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(mb90570_device::internal_map), this)), + m_internal_ram_end(internal_ram_end), + m_adc(*this, "adc"), + m_clock_generator(*this, "clock_generator"), + m_intc(*this, "intc"), + m_port(*this, "port%x", 1U), + m_ppg(*this, "ppg"), + m_uart(*this, "uart%u", 0U) +{ +} + +device_memory_interface::space_config_vector mb90570_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +void mb90570_device::device_add_mconfig(machine_config &mconfig) +{ + F2MC16_PORT(mconfig, m_port[0x0], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x2], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x3], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x4], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x5], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x6], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x7], 0x00, 0x1f); + F2MC16_PORT(mconfig, m_port[0x8], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x9], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0xa], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0xb], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0xc], 0x00, 0xff); + + F2MC16_INTC(mconfig, m_intc); + set_irq_acknowledge_callback(m_intc, FUNC(f2mc16_intc_device::irq_acknowledge_callback)); + F2MC16_CLOCK_GENERATOR(mconfig, m_clock_generator, DERIVED_CLOCK(1, 1), m_intc, 34); + F2MC16_ADC(mconfig, m_adc, DERIVED_CLOCK(1, 1), m_intc, 11); + m_intc->i2osclr<0x1f>().set(m_adc, FUNC(f2mc16_adc_device::i2osclr)); + F2MC16_UART(mconfig, m_uart[0], DERIVED_CLOCK(1, 1), m_intc, 39, 40); + F2MC16_UART(mconfig, m_uart[1], DERIVED_CLOCK(1, 1), m_intc, 37, 38); + F2MC16_PPG(mconfig, m_ppg, DERIVED_CLOCK(1, 1), m_intc, 26, 28); + m_clock_generator->timebase_hz().set(m_ppg, FUNC(f2mc16_ppg_device::timebase_hz)); +} + +void mb90570_device::internal_map(address_map &map) +{ + //*7: This register is only available when the address/data bus is in multiplex mode. Access to the register is prohibited in non-multiplex mode. + //*8: This register is only available when the external data bus is in 8-bit mode. Access to the register is prohibited in 16-bit mode. + map(0x0000, 0x0000).rw(m_port[0x0], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 0 data register + map(0x0001, 0x0001).rw(m_port[0x1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 1 data register + map(0x0002, 0x0002).rw(m_port[0x2], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 2 data register + map(0x0003, 0x0003).rw(m_port[0x3], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 3 data register + map(0x0004, 0x0004).rw(m_port[0x4], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 4 data register + map(0x0005, 0x0005).rw(m_port[0x5], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 5 data register + map(0x0006, 0x0006).rw(m_port[0x6], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 6 data register + map(0x0007, 0x0007).rw(m_port[0x7], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 7 data register + map(0x0008, 0x0008).rw(m_port[0x8], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 8 data register + map(0x0009, 0x0009).rw(m_port[0x9], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 9 data register + map(0x000a, 0x000a).rw(m_port[0xa], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port a data register + map(0x000b, 0x000b).rw(m_port[0xa], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port b data register + map(0x000c, 0x000c).rw(m_port[0xa], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port c data register + map(0x0010, 0x0010).rw(m_port[0x0], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 1 direction register + map(0x0011, 0x0011).rw(m_port[0x1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 1 direction register + map(0x0012, 0x0012).rw(m_port[0x2], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 2 direction register + map(0x0013, 0x0013).rw(m_port[0x3], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 3 direction register + map(0x0014, 0x0014).rw(m_port[0x4], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 4 direction register + map(0x0015, 0x0015).rw(m_port[0x5], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 5 direction register + map(0x0016, 0x0016).rw(m_port[0x6], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 6 direction register + map(0x0017, 0x0017).rw(m_port[0x7], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 7 direction register + map(0x0018, 0x0018).rw(m_port[0x8], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 8 direction register + map(0x0019, 0x0019).rw(m_port[0x9], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 9 direction register + map(0x001a, 0x001a).rw(m_port[0xa], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port a direction register + map(0x001b, 0x001b).rw(m_port[0xb], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port b direction register + map(0x001c, 0x001c).rw(m_port[0xc], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port c direction register + // 0x1d odr4 Port 4 output register + // 0x1e ader Analog input enable register + map(0x0020, 0x0020).rw(m_uart[0], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 0 + map(0x0021, 0x0021).rw(m_uart[0], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 0 + map(0x0022, 0x0022).rw(m_uart[0], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 0/Serial output data register 0 + map(0x0023, 0x0023).rw(m_uart[0], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 0 + map(0x0024, 0x0024).rw(m_uart[1], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 1 + map(0x0025, 0x0025).rw(m_uart[1], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 1 + map(0x0026, 0x0026).rw(m_uart[1], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 1/Serial output data register 1 + map(0x0027, 0x0027).rw(m_uart[1], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 1 + map(0x0028, 0x0028).w(m_uart[0], FUNC(f2mc16_uart_device::cdcr_w)); // UART0 (uart) machine clock division control register + map(0x002a, 0x002a).w(m_uart[1], FUNC(f2mc16_uart_device::cdcr_w)); // UART1 (uart) machine clock division control register + map(0x0030, 0x0030).rw(m_intc, FUNC(f2mc16_intc_device::enir_r), FUNC(f2mc16_intc_device::enir_w)); // Interrupt/DTP enable register + map(0x0031, 0x0031).rw(m_intc, FUNC(f2mc16_intc_device::eirr_r), FUNC(f2mc16_intc_device::eirr_w)); // Interrupt/DTP source register + map(0x0032, 0x0033).rw(m_intc, FUNC(f2mc16_intc_device::elvr_r), FUNC(f2mc16_intc_device::elvr_w)); // Interrupt level setting register + map(0x0036, 0x0037).rw(m_adc, FUNC(f2mc16_adc_device::adcs_r), FUNC(f2mc16_adc_device::adcs_w)); // AD control status register + map(0x0038, 0x0039).rw(m_adc, FUNC(f2mc16_adc_device::adcr_r), FUNC(f2mc16_adc_device::adcr_w)); // AD data register + // 0x3a dadr0 d/a converter data register ch.0 + // 0x3b dadr1 d/a converter data register ch.1 + // 0x3c dacr0 d/a control register ch.0 + // 0x3d dacr1 d/a control register ch.1 + // 0x3e clkr Clock output enable register + map(0x0040, 0x0041).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<0>), FUNC(f2mc16_ppg_device::prl_w<0>)); // reload register + map(0x0042, 0x0043).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<1>), FUNC(f2mc16_ppg_device::prl_w<1>)); // reload register + map(0x0044, 0x0045).rw(m_ppg, FUNC(f2mc16_ppg_device::ppgc_r), FUNC(f2mc16_ppg_device::ppgc_w)); // operation mode control register + // 0x46 ppgoe PPG0 and 1 output control registers ch.0 and ch.1 + // 0x48 smcsl0 Serial mode control lower status register 0 + // 0x49 smcsh0 Serial mode control upper status register 0 + // 0x4a sdr0 Serial data register 0 + // 0x4c smcsl1 Serial mode control lower status register 1 + // 0x4d smcsh1 Serial mode control upper status register 1 + // 0x4e sdr1 Serial data register 1 + // 0x50, 0x51 ipcp0 ICU data register ch.0 + // 0x52, 0x53 ipcp1 ICU data register ch.1 + // 0x54 ics01 ICU control status register + // 0x56, 0x57 tcdt Free run timer data register + // 0x58 tccs Free run timer control status register + // 0x5a, 0x5b occp0 OCU compare register ch.0 + // 0x5c, 0x5d occp1 OCU compare register ch.1 + // 0x5e, 0x5f occp2 OCU compare register ch.2 + // 0x60, 0x61 occp3 OCU compare register ch.3 + // 0x62 ocs0 OCU control status register ch.0 + // 0x63 ocs1 OCU control status register ch.1 + // 0x64 ocs2 OCU control status register ch.2 + // 0x65 ocs3 OCU control status register ch.3 + // 0x68 ibsr I2C bus status register + // 0x69 ibcr I2C bus control register + // 0x6a iccr I2C bus clock control register + // 0x6b iadr I2C bus address register + // 0x6c idar I2C bus data register + // 0x6f romm ROM mirroring function selection register + // 0x70 udcr0 Up/down count register 0 + // 0x71 udcr1 Up/down count register 1 + // 0x72 rcr0 Reload compare register 0 + // 0x73 rcr1 Reload compare register 1 + // 0x74 csr0 Counter status register 0 + // 0x76, 0x77 ccr0/ccr0 Counter control register 0 + // 0x78 csr1 Counter status register 1 + // 0x7a, 0x7b ccr1/ccr1 Counter control register 1 + // 0x7c smcsl2 Serial mode control lower status register 2 + // 0x7d smcsh2 Serial mode control higher status register 2 + // 0x7e Serial data register 2 + map(0x0080, 0x0087).ram(); // CSCR0-CSCR6 + // 0x9e pacsr Program address detection control status register + map(0x009f, 0x009f).rw(m_intc, FUNC(f2mc16_intc_device::dirr_r), FUNC(f2mc16_intc_device::dirr_w)); // Delay interrupt generate/release register + map(0x00a0, 0x00a0).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::lpmcr_r), FUNC(f2mc16_clock_generator_device::lpmcr_w)); // Low power mode control register + map(0x00a1, 0x00a1).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::ckscr_r), FUNC(f2mc16_clock_generator_device::ckscr_w)); // Clock selection register + // 0x00a5 arsr Auto-ready function selection register + // 0x00a6 hacr External address output control register + // 0x00a7 ecsr Bus control signal selection register + map(0x00a8, 0x00a8).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::wdtc_r), FUNC(f2mc16_clock_generator_device::wdtc_w)); // Watchdog timer control register + map(0x00a9, 0x00a9).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::tbtc_r), FUNC(f2mc16_clock_generator_device::tbtc_w)); + // 0xaa wtc Clock timer control register + // 0xae fmcs Flash control register + map(0x00b0, 0x00bf).rw(m_intc, FUNC(f2mc16_intc_device::icr_r), FUNC(f2mc16_intc_device::icr_w)); + map(0x0100, m_internal_ram_end).ram(); + // 0x1ff0, 0x1ff2 padr0 + // 0x1ff3, 0x1ff5 padr1 +} diff --git a/src/devices/cpu/f2mc16/mb90570.h b/src/devices/cpu/f2mc16/mb90570.h new file mode 100644 index 00000000000..455094f8f39 --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90570.h @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#ifndef MAME_CPU_F2MC16_MB90570_H +#define MAME_CPU_F2MC16_MB90570_H + +#pragma once + +#include "f2mc16.h" +#include "f2mc16_adc.h" +#include "f2mc16_clock.h" +#include "f2mc16_intc.h" +#include "f2mc16_port.h" +#include "f2mc16_ppg.h" +#include "f2mc16_uart.h" + +class mb90570_device : + public f2mc16_device +{ +public: + mb90570_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto &adc() const { if (m_adc) return *m_adc; return *subdevice(m_adc.finder_tag()); } + template typename std::enable_if::type &port() const { if (m_port[N]) return *m_port[N]; return *subdevice(m_port[N].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice(m_ppg.finder_tag()); } + template typename std::enable_if::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice(m_uart[N].finder_tag()); } + +protected: + mb90570_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t internal_ram_end); + + // device_t + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual space_config_vector memory_space_config() const override ATTR_COLD; + + void internal_map(address_map &map) ATTR_COLD; + + const address_space_config m_program_config; + const uint16_t m_internal_ram_end; + + required_device m_adc; + required_device m_clock_generator; + required_device m_intc; + required_device_array m_port; + required_device m_ppg; + required_device_array m_uart; +}; + +class mb90f574_device : public mb90570_device +{ +public: + mb90f574_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(MB90F574, mb90f574_device) + +#endif // MAME_CPU_F2MC16_MB90570_H diff --git a/src/devices/cpu/f2mc16/mb90610a.cpp b/src/devices/cpu/f2mc16/mb90610a.cpp new file mode 100644 index 00000000000..31a4dc1390a --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90610a.cpp @@ -0,0 +1,138 @@ +// license:BSD-3-Clause +// copyright-holders:smf + +#include "emu.h" +#include "mb90610a.h" + +DEFINE_DEVICE_TYPE(MB90610A, mb90610a_device, "mb90610a", "Fujitsu MB90610A") // "Evaluation device" with extra RAM + +mb90610a_device::mb90610a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb90610a_device(mconfig, MB90610A, tag, owner, clock, 0x10ff) +{ +} + +DEFINE_DEVICE_TYPE(MB90611A, mb90611a_device, "mb90611a", "Fujitsu MB90611A") // Production version + +mb90611a_device::mb90611a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb90610a_device(mconfig, MB90611A, tag, owner, clock, 0x04ff) +{ +} + +mb90610a_device::mb90610a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t internal_ram_end) : + f2mc16_device(mconfig, type, tag, owner, clock), + m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(mb90610a_device::internal_map), this)), + m_internal_ram_end(internal_ram_end), + m_adc(*this, "adc"), + m_clock_generator(*this, "clock_generator"), + m_intc(*this, "intc"), + m_port(*this, "port%x", 1U), + m_ppg(*this, "ppg"), + m_reload_timer(*this, "reload_timer%u", 0U), + m_uart(*this, "uart%u", 0U) +{ +} + +device_memory_interface::space_config_vector mb90610a_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +void mb90610a_device::device_add_mconfig(machine_config &mconfig) +{ + F2MC16_PORT(mconfig, m_port[0x1 - 1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x2 - 1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x3 - 1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x4 - 1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x5 - 1], 0x00, 0x3f); + F2MC16_PORT(mconfig, m_port[0x6 - 1], 0xff, 0xff); + F2MC16_PORT(mconfig, m_port[0x7 - 1], 0x00, 0x7f); + F2MC16_PORT(mconfig, m_port[0x8 - 1], 0x00, 0x7f); + F2MC16_PORT(mconfig, m_port[0x9 - 1], 0x00, 0x3f); + F2MC16_PORT(mconfig, m_port[0xa - 1], 0x00, 0xfe); + + F2MC16_INTC(mconfig, m_intc); + set_irq_acknowledge_callback(m_intc, FUNC(f2mc16_intc_device::irq_acknowledge_callback)); + F2MC16_CLOCK_GENERATOR(mconfig, m_clock_generator, DERIVED_CLOCK(1, 1), m_intc, 0x22); + F2MC16_ADC(mconfig, m_adc, DERIVED_CLOCK(1, 1), m_intc, 0x1f); + m_intc->i2osclr<0x1f>().set(m_adc, FUNC(f2mc16_adc_device::i2osclr)); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[0], DERIVED_CLOCK(1, 1), m_intc, 0x1d); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[1], DERIVED_CLOCK(1, 1), m_intc, 0x1e); + m_intc->i2osclr<0x1d>().set(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::i2osclr)); + m_intc->i2osclr<0x1e>().set(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::i2osclr)); + F2MC16_UART(mconfig, m_uart[0], DERIVED_CLOCK(1, 1), m_intc, 0x27, 0x18); + F2MC16_UART(mconfig, m_uart[1], DERIVED_CLOCK(1, 1), m_intc, 0x25, 0x1a); + F2MC16_UART(mconfig, m_uart[2], DERIVED_CLOCK(1, 1), m_intc, 0x23, 0x21); + m_reload_timer[0]->internal_hz().set(m_uart[0], FUNC(f2mc16_uart_device::internal_timer_hz)); + m_reload_timer[0]->internal_hz().append(m_uart[1], FUNC(f2mc16_uart_device::internal_timer_hz)); + m_reload_timer[0]->internal_hz().append(m_uart[2], FUNC(f2mc16_uart_device::internal_timer_hz)); + m_reload_timer[1]->internal_hz().set(m_adc, FUNC(f2mc16_adc_device::internal_timer_hz)); + F2MC16_PPG(mconfig, m_ppg, DERIVED_CLOCK(1, 1), m_intc, 0x1b, 0x1c); + m_clock_generator->timebase_hz().set(m_ppg, FUNC(f2mc16_ppg_device::timebase_hz)); +} + +void mb90610a_device::internal_map(address_map &map) +{ +//*7: This register is only available when the address/data bus is in multiplex mode. Access to the register is prohibited in non-multiplex mode. +//*8: This register is only available when the external data bus is in 8-bit mode. Access to the register is prohibited in 16-bit mode. + map(0x0001, 0x0001).rw(m_port[0x1 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 1 data register *8 + map(0x0002, 0x0002).rw(m_port[0x2 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 2 data register *7 + map(0x0003, 0x0003).rw(m_port[0x3 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 3 data register + map(0x0004, 0x0004).rw(m_port[0x4 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 4 data register + map(0x0005, 0x0005).rw(m_port[0x5 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 5 data register + map(0x0006, 0x0006).rw(m_port[0x6 - 1], FUNC(f2mc16_port_device::pdr_adc_r), FUNC(f2mc16_port_device::pdr_w)); // Port 6 data register + map(0x0007, 0x0007).rw(m_port[0x7 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 7 data register + map(0x0008, 0x0008).rw(m_port[0x8 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 8 data register + map(0x0009, 0x0009).rw(m_port[0x9 - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 9 data register + map(0x000a, 0x000a).rw(m_port[0xa - 1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port a data register + map(0x0011, 0x0011).rw(m_port[0x1 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 1 direction register *8 + map(0x0012, 0x0012).rw(m_port[0x2 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 2 direction register *7 + map(0x0013, 0x0013).rw(m_port[0x3 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 3 direction register + map(0x0014, 0x0014).rw(m_port[0x4 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 4 direction register + map(0x0015, 0x0015).rw(m_port[0x5 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 5 direction register + map(0x0016, 0x0016).rw(m_port[0x6 - 1], FUNC(f2mc16_port_device::ader_r), FUNC(f2mc16_port_device::ader_w)); // Analog input enable register + map(0x0017, 0x0017).rw(m_port[0x7 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 7 direction register + map(0x0018, 0x0018).rw(m_port[0x8 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 8 direction register + map(0x0019, 0x0019).rw(m_port[0x9 - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 9 direction register + map(0x001a, 0x001a).rw(m_port[0xa - 1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port a direction register + map(0x0020, 0x0020).rw(m_uart[0], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 0 + map(0x0021, 0x0021).rw(m_uart[0], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 0 + map(0x0022, 0x0022).rw(m_uart[0], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 0/Serial output data register 0 + map(0x0023, 0x0023).rw(m_uart[0], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 0 + map(0x0024, 0x0024).rw(m_uart[1], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 1 + map(0x0025, 0x0025).rw(m_uart[1], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 1 + map(0x0026, 0x0026).rw(m_uart[1], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 1/Serial output data register 1 + map(0x0027, 0x0027).rw(m_uart[1], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 1 + map(0x0028, 0x0028).rw(m_intc, FUNC(f2mc16_intc_device::enir_r), FUNC(f2mc16_intc_device::enir_w)); // Interrupt/DTP enable register + map(0x0029, 0x0029).rw(m_intc, FUNC(f2mc16_intc_device::eirr_r), FUNC(f2mc16_intc_device::eirr_w)); // Interrupt/DTP source register + map(0x002a, 0x002b).rw(m_intc, FUNC(f2mc16_intc_device::elvr_r), FUNC(f2mc16_intc_device::elvr_w)); // Interrupt level setting register + map(0x002c, 0x002d).rw(m_adc, FUNC(f2mc16_adc_device::adcs_r), FUNC(f2mc16_adc_device::adcs_w)); // AD control status register + map(0x002e, 0x002f).rw(m_adc, FUNC(f2mc16_adc_device::adcr_r), FUNC(f2mc16_adc_device::adcr_w)); // AD data register + map(0x0030, 0x0031).rw(m_ppg, FUNC(f2mc16_ppg_device::ppgc_r), FUNC(f2mc16_ppg_device::ppgc_w)); // operation mode control register + map(0x0034, 0x0035).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<0>), FUNC(f2mc16_ppg_device::prl_w<0>)); // reload register + map(0x0036, 0x0037).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<1>), FUNC(f2mc16_ppg_device::prl_w<1>)); // reload register + map(0x0038, 0x0039).rw(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x003a, 0x003b).rw(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x003c, 0x003d).rw(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x003e, 0x003f).rw(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x0044, 0x0044).rw(m_uart[2], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 2 + map(0x0045, 0x0045).rw(m_uart[2], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 2 + map(0x0046, 0x0046).rw(m_uart[2], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 2/Serial output data register 2 + map(0x0047, 0x0047).rw(m_uart[2], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 2 + map(0x0048, 0x004f).ram(); // CSCR0-CSCR7 + map(0x0051, 0x0051).w(m_uart[0], FUNC(f2mc16_uart_device::cdcr_w)); // UART0 (uart) machine clock division control register + map(0x0053, 0x0053).w(m_uart[1], FUNC(f2mc16_uart_device::cdcr_w)); // UART1 (uart) machine clock division control register + map(0x0055, 0x0055).w(m_uart[2], FUNC(f2mc16_uart_device::cdcr_w)); // UART2 (uart) machine clock division control register + map(0x009f, 0x009f).rw(m_intc, FUNC(f2mc16_intc_device::dirr_r), FUNC(f2mc16_intc_device::dirr_w)); // Delay interrupt generate/release register + map(0x00a0, 0x00a0).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::lpmcr_r), FUNC(f2mc16_clock_generator_device::lpmcr_w)); // Low power mode control register + map(0x00a1, 0x00a1).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::ckscr_r), FUNC(f2mc16_clock_generator_device::ckscr_w)); // Clock selection register + map(0x00a4, 0x00a7).nopw(); // HACK + //map(0x00a5, 0x00a5).nopw(); // ARSR Auto-ready function selection register + //map(0x00a6, 0x00a6).nopw(); // HACR External address output control register + //map(0x00a7, 0x00a7).nopw(); // ECSR Bus control signal selection register + map(0x00a8, 0x00a8).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::wdtc_r), FUNC(f2mc16_clock_generator_device::wdtc_w)); // Watchdog timer control register + map(0x00a9, 0x00a9).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::tbtc_r), FUNC(f2mc16_clock_generator_device::tbtc_w)); + map(0x00b0, 0x00bf).rw(m_intc, FUNC(f2mc16_intc_device::icr_r), FUNC(f2mc16_intc_device::icr_w)); + map(0x0100, m_internal_ram_end).ram(); +} diff --git a/src/devices/cpu/f2mc16/mb90610a.h b/src/devices/cpu/f2mc16/mb90610a.h new file mode 100644 index 00000000000..08976e9d32f --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90610a.h @@ -0,0 +1,59 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#ifndef MAME_CPU_F2MC16_MB90610A_H +#define MAME_CPU_F2MC16_MB90610A_H + +#pragma once + +#include "f2mc16.h" +#include "f2mc16_adc.h" +#include "f2mc16_clock.h" +#include "f2mc16_intc.h" +#include "f2mc16_port.h" +#include "f2mc16_ppg.h" +#include "f2mc16_reload.h" +#include "f2mc16_uart.h" + +class mb90610a_device : + public f2mc16_device +{ +public: + mb90610a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto &adc() const { if (m_adc) return *m_adc; return *subdevice(m_adc.finder_tag()); } + template typename std::enable_if= 1 && N <= 10, f2mc16_port_device>::type &port() const { if (m_port[N - 1]) return *m_port[N - 1]; return *subdevice(m_port[N - 1].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice(m_ppg.finder_tag()); } + template typename std::enable_if::type &reload_timer() const { if (m_reload_timer[N]) return *m_reload_timer[N]; return *subdevice(m_reload_timer[N].finder_tag()); } + template typename std::enable_if::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice(m_uart[N].finder_tag()); } + +protected: + mb90610a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint16_t internal_ram_end); + + // device_t + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual space_config_vector memory_space_config() const override ATTR_COLD; + + void internal_map(address_map &map) ATTR_COLD; + + const address_space_config m_program_config; + const uint16_t m_internal_ram_end; + + required_device m_adc; + required_device m_clock_generator; + required_device m_intc; + required_device_array m_port; + required_device m_ppg; + required_device_array m_reload_timer; + required_device_array m_uart; +}; + +class mb90611a_device : public mb90610a_device +{ +public: + mb90611a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(MB90610A, mb90610a_device) +DECLARE_DEVICE_TYPE(MB90611A, mb90611a_device) + +#endif // MAME_CPU_F2MC16_MB90610A_H diff --git a/src/devices/cpu/f2mc16/mb9061x.cpp b/src/devices/cpu/f2mc16/mb9061x.cpp deleted file mode 100644 index 4cfa0d6dd55..00000000000 --- a/src/devices/cpu/f2mc16/mb9061x.cpp +++ /dev/null @@ -1,457 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/* - Fujitsu Micro MB9061x Microcontroller Family - Emulation by R. Belmont -*/ - -#include "emu.h" -#include "mb9061x.h" - -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(MB90610A, mb90610_device, "mb90610a", "Fujitsu MB90610A") -DEFINE_DEVICE_TYPE(MB90611A, mb90611_device, "mb90611a", "Fujitsu MB90611A") -DEFINE_DEVICE_TYPE(MB90641A, mb90641_device, "mb90641a", "Fujitsu MB90641A") - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// mb9061x_device - constructor -//------------------------------------------------- -mb9061x_device::mb9061x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map) : - f2mc16_device(mconfig, type, tag, owner, clock), - m_program_config("program", ENDIANNESS_LITTLE, 8, 24, 0, internal_map), - m_read_port(*this, 0xff), - m_write_port(*this), - m_read_adcs(*this, 0xff), - m_write_adcs(*this), - m_read_adcr(*this, 0xff), - m_write_adcr(*this) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void mb9061x_device::device_start() -{ - f2mc16_device::device_start(); - - m_tbtc_timer = timer_alloc(FUNC(mb9061x_device::tbtc_tick), this); - m_tbtc_timer->adjust(attotime::never); - m_timer[0] = timer_alloc(FUNC(mb9061x_device::timer0_tick), this); - m_timer[0]->adjust(attotime::never); - m_timer[1] = timer_alloc(FUNC(mb9061x_device::timer1_tick), this); - m_timer[1]->adjust(attotime::never); -} - - -device_memory_interface::space_config_vector mb9061x_device::memory_space_config() const -{ - return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config) - }; -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void mb9061x_device::device_reset() -{ - f2mc16_device::device_reset(); - m_tbtc = 0; - memset(m_timer_regs, 0, sizeof(m_timer_regs)); - memset(m_event_count, 0, sizeof(m_event_count)); - m_event_state[0] = m_event_state[1] = CLEAR_LINE; -} - -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(0x0001, 0x000a).rw(FUNC(mb9061x_device::port_r), FUNC(mb9061x_device::port_w)); - map(0x002c, 0x002d).rw(FUNC(mb9061x_device::adcs_r), FUNC(mb9061x_device::adcs_w)); - map(0x002e, 0x002f).rw(FUNC(mb9061x_device::adcr_r), FUNC(mb9061x_device::adcr_w)); - 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 -} - -mb90610_device::mb90610_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - mb90610_device(mconfig, MB90610A, tag, owner, clock) -{ -} - -mb90610_device::mb90610_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - mb9061x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(mb90610_device::mb90610_map), this)) -{ -} - -/* 16-bit preload timers with event count function */ -enum -{ - TCTH_CSL1 = 0x08, // clock source select bit 1 - TCTH_CSL0 = 0x04, // clock source select bit 0 - TCTH_MOD2 = 0x02, // mode bit 2 - TCTH_MOD1 = 0x01, // mode bit 1 - - TCTL_MOD0 = 0x80, // mode bit 0 - TCTL_OUTE = 0x40, // output enable - TCTL_OUTL = 0x20, // output level - TCTL_RELD = 0x10, // reload - TCTL_INTE = 0x08, // IRQ enable - TCTL_UF = 0x04, // expire flag - TCTL_CNTE = 0x02, // enable counting - TCTL_TRG = 0x01 // force a reload and start counting -}; - -TIMER_CALLBACK_MEMBER(mb9061x_device::timer0_tick) -{ - u8 ctl = m_timer_regs[0]; - m_timer_regs[0] |= TCTL_UF; - if (ctl & TCTL_INTE) - { -// printf("timer 0 IRQ\n"); - intc_trigger_irq(9, 0x1d); - } - - if (ctl & TCTL_RELD) - { - recalc_timer(0); - m_timer[0]->adjust(attotime::from_hz(m_timer_hz[0])); - } -} - -TIMER_CALLBACK_MEMBER(mb9061x_device::timer1_tick) -{ - u8 ctl = m_timer_regs[4]; - m_timer_regs[4] |= TCTL_UF; - if (ctl & TCTL_INTE) - { - // printf("timer 1 IRQ\n"); - intc_trigger_irq(9, 0x1e); - } - - if (ctl & TCTL_RELD) - { - recalc_timer(0); - m_timer[1]->adjust(attotime::from_hz(m_timer_hz[1])); - } -} - -u8 mb9061x_device::timer_r(offs_t offset) -{ - //printf("timer_r: offset %d = %02x\n", offset, m_timer_regs[offset]); - return m_timer_regs[offset]; -} - -void mb9061x_device::timer_w(offs_t offset, u8 data) -{ - int timer = offset / 4; - int reg = offset % 4; - - //printf("timer_w: %x to %d\n", data, offset); -#if 0 - switch (reg) - { - case 0: // control/status, lower - printf("%02x to timer %d lower control\n", data, timer); - break; - - case 1: // control/status, upper - printf("%02x to timer %d upper control\n", data, timer); - break; - - case 2: // timer/reload, lower - printf("%02x to timer %d lower reload\n", data, timer); - break; - - case 3: // timer/reload, upper - printf("%02x to timer %d upper reload\n", data, timer); - break; - } -#endif - if (reg == 0) - { - m_timer_regs[offset] &= (TCTL_TRG|TCTL_UF); - m_timer_regs[offset] |= data; - } - else - { - m_timer_regs[offset] = data; - } - - int rbase = timer << 2; - u8 csl = (m_timer_regs[rbase+1] >> 2) & 3; - if (reg == 0) - { - if (data & TCTL_TRG) - { - //printf("Got TRG\n"); - recalc_timer(timer); - if ((m_timer_regs[rbase] & TCTL_CNTE) && (csl != 3)) - { - m_timer[timer]->adjust(attotime::from_hz(m_timer_hz[timer])); - } - } - - if ((data & TCTL_CNTE) && (csl != 3)) - { - //printf("CNTE set, starting timer at %d Hz\n", m_timer_hz[timer]); - m_timer[timer]->adjust(attotime::from_hz(m_timer_hz[timer])); - } - - if ((data & TCTL_CNTE) && (csl == 3)) - { - m_event_count[timer] = m_timer_regs[2] | (m_timer_regs[3]<<8); - //printf("CNTE set in event counter mode, reseeding count to %04x\n", m_event_count[timer]); - } - - if (!(data & TCTL_UF)) - { - intc_clear_irq(9, 0x1d + timer); - } - } -} - -void mb9061x_device::tin0_w(int state) -{ - tin_common(0, 0, state); -} - -void mb9061x_device::tin1_w(int state) -{ - tin_common(1, 4, state); -} - -void mb9061x_device::tin_common(int timer, int base, int state) -{ - // emsure event counter mode - if ((m_timer_regs[base + 1] & (TCTH_CSL0|TCTH_CSL1)) == (TCTH_CSL0|TCTH_CSL1) && - (m_timer_regs[base] & TCTL_CNTE)) - { - bool bTickIt = false; - - // rising edge - if ((state && !m_event_state[base/4]) && (m_timer_regs[base] & TCTL_MOD0) && !(m_timer_regs[base+1] & TCTH_MOD1)) - { - bTickIt = true; - } - - // falling edge - if ((!state && m_event_state[base/4]) && !(m_timer_regs[base] & TCTL_MOD0) && (m_timer_regs[base+1] & TCTH_MOD1)) - { - bTickIt = true; - } - - // any edge - if ((state != m_event_state[base/4]) && !(m_timer_regs[base] & TCTL_MOD0) && (m_timer_regs[base+1] & TCTH_MOD1)) - { - bTickIt = true; - } - - if (bTickIt) - { - m_event_count[timer]--; - //printf("Tick timer %d, new value %04x\n", timer, m_event_count[timer]); - - if (m_event_count[timer] == 0xffff) - { - u8 ctl = m_timer_regs[base]; - m_timer_regs[base] |= TCTL_UF; - //printf("Timer %d exp, CL %02x\n", timer, m_timer_regs[base]); - if (ctl & TCTL_INTE) - { - //printf("timer %d IRQ\n", timer); - intc_trigger_irq(9, 0x1d + timer); - } - - if (m_timer_regs[timer * 4] & TCTL_RELD) - { - m_event_count[timer] = m_timer_regs[2] | (m_timer_regs[3]<<8); - //printf("timer %d reload to %04x\n", timer, m_event_count[timer]); - } - } - } - - m_event_state[timer] = state; - } -} - -void mb9061x_device::recalc_timer(int tnum) -{ - int rbase = tnum << 2; - u32 divider = 1; - u8 csl = (m_timer_regs[rbase+1] >> 2) & 3; - - // check clock select - switch (csl) - { - case 0: divider = 2; break; - case 1: divider = 16; break; - case 2: divider = 64; break; - - case 3: // event counter mode - return; - } - - u32 tclk = clock() / divider; - u32 tval = m_timer_regs[rbase+2] | (m_timer_regs[rbase+3]<<8); - //printf("CSL %d, tclk %d, tval %d\n", csl, tclk, tval); - //printf("Timer is %d Hz\n", tclk / tval); - m_timer_hz[tnum] = tclk / tval; -} - -/* 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 -}; - -u8 mb9061x_device::tbtc_r() -{ - return m_tbtc; -} - -void mb9061x_device::tbtc_w(u8 data) -{ - static const float periods[4] = { 1.024f, 4.096f, 16.384f, 131.072f }; - - //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); - } -} - -u8 mb9061x_device::intc_r(offs_t offset) -{ - return m_intc[offset]; -} - -void mb9061x_device::intc_w(offs_t offset, u8 data) -{ - //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(0x0001, 0x000a).rw(FUNC(mb9061x_device::port_r), FUNC(mb9061x_device::port_w)); - map(0x002c, 0x002d).rw(FUNC(mb9061x_device::adcs_r), FUNC(mb9061x_device::adcs_w)); - map(0x002e, 0x002f).rw(FUNC(mb9061x_device::adcr_r), FUNC(mb9061x_device::adcr_w)); - map(0x0038, 0x003f).rw(FUNC(mb9061x_device::timer_r), FUNC(mb9061x_device::timer_w)); - 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 -} - -mb90611_device::mb90611_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - mb90611_device(mconfig, MB90611A, tag, owner, clock) -{ -} - -mb90611_device::mb90611_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - mb9061x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(mb90611_device::mb90611_map), this)) -{ -} - -/* MB90641 - no A/D, extra UART and timers, optional internal ROM */ -void mb90641_device::mb90641_map(address_map &map) -{ - map(0x0001, 0x000a).rw(FUNC(mb9061x_device::port_r), FUNC(mb9061x_device::port_w)); - map(0x002c, 0x002d).rw(FUNC(mb9061x_device::adcs_r), FUNC(mb9061x_device::adcs_w)); - map(0x002e, 0x002f).rw(FUNC(mb9061x_device::adcr_r), FUNC(mb9061x_device::adcr_w)); - map(0x0038, 0x003f).rw(FUNC(mb9061x_device::timer_r), FUNC(mb9061x_device::timer_w)); - 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, 0x08ff).ram(); // 2K of internal RAM -} - -mb90641_device::mb90641_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - mb90641_device(mconfig, MB90641A, tag, owner, clock) -{ -} - -mb90641_device::mb90641_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - mb9061x_device(mconfig, type, tag, owner, clock, address_map_constructor(FUNC(mb90641_device::mb90641_map), this)) -{ -} diff --git a/src/devices/cpu/f2mc16/mb9061x.h b/src/devices/cpu/f2mc16/mb9061x.h deleted file mode 100644 index 4b5b8d31253..00000000000 --- a/src/devices/cpu/f2mc16/mb9061x.h +++ /dev/null @@ -1,180 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -#ifndef MAME_CPU_F2MC16_MB9061X_H -#define MAME_CPU_F2MC16_MB9061X_H - -#pragma once - -#include "f2mc16.h" - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> mb9061x_device - -class mb9061x_device : public f2mc16_device -{ - friend class mb90610_device; - friend class mb90611_device; - friend class mb90641_device; - -public: - const address_space_config m_program_config; - - // port registers - enum - { - PDR1 = 0, PDR2, PDR3, PDR4, PDR5, PDR6, PDR7, PDR8, PDR9, PDRA - }; - - // interrupts handled by the interrupt controller - enum - { - ICR0 = 0, ICR1, ICR2, ICR3, ICR4, ICR5, ICR6, ICR7, ICR8, ICR9, ICR10, ICR11, ICR12, ICR13, ICR14, ICR15 - }; - - auto read_pdr1() { return m_read_port [PDR1].bind(); } - auto write_pdr1() { return m_write_port[PDR1].bind(); } - auto read_pdr2() { return m_read_port [PDR2].bind(); } - auto write_pdr2() { return m_write_port[PDR2].bind(); } - auto read_pdr3() { return m_read_port [PDR3].bind(); } - auto write_pdr3() { return m_write_port[PDR3].bind(); } - auto read_pdr4() { return m_read_port [PDR4].bind(); } - auto write_pdr4() { return m_write_port[PDR4].bind(); } - auto read_pdr5() { return m_read_port [PDR5].bind(); } - auto write_pdr5() { return m_write_port[PDR5].bind(); } - auto read_pdr6() { return m_read_port [PDR6].bind(); } - auto write_pdr6() { return m_write_port[PDR6].bind(); } - auto read_pdr7() { return m_read_port [PDR7].bind(); } - auto write_pdr7() { return m_write_port[PDR7].bind(); } - auto read_pdr8() { return m_read_port [PDR8].bind(); } - auto write_pdr8() { return m_write_port[PDR8].bind(); } - auto read_pdr9() { return m_read_port [PDR9].bind(); } - auto write_pdr9() { return m_write_port[PDR9].bind(); } - auto read_pdra() { return m_read_port [PDRA].bind(); } - auto write_pdra() { return m_write_port[PDRA].bind(); } - auto read_adcs() { return m_read_adcs .bind(); } - auto write_adcs() { return m_write_adcs.bind(); } - auto read_adcr() { return m_read_adcr .bind(); } - auto write_adcr() { return m_write_adcr.bind(); } - - // port functions - u8 read_port(offs_t offset) { return m_ports[offset]; } - void write_port(offs_t offset, u8 data) { m_ports[offset] = data; } - u8 port_r(offs_t offset) { return m_read_port[offset](); } - void port_w(offs_t offset, u8 data) { write_port(offset, data); m_write_port[offset](0, data); } - - // analog/digital control status functions - u16 read_reg_adcs() { return m_adcs; } - void write_reg_adcs(offs_t offset, u8 data) { m_adcs = (offset == 0) ? (data | (m_adcs & 0xff00)) : ((data << 8) | (m_adcs & 0x00ff)); } - u8 adcs_r(offs_t offset) { return (offset == 0 ? m_read_adcs() : m_read_adcs() >> 8) & 0xff; } - void adcs_w(offs_t offset, u8 data) { write_reg_adcs(offset, data); m_write_adcs(offset, data); } - - // analog/digital data functions - u16 read_reg_adcr() { return m_adcr; } - void write_reg_adcr(offs_t offset, u8 data) { m_adcr = (offset == 0) ? (data | (m_adcr & 0xff00)) : ((data << 8) | (m_adcr & 0x00ff)); } - u8 adcr_r(offs_t offset) { return (offset == 0 ? m_read_adcr() : m_read_adcr() >> 8) & 0xff; } - void adcr_w(offs_t offset, u8 data) { write_reg_adcr(offset, data); m_write_adcr(offset, data); } - - // timer external counter tick functions - void tin0_w(int state); - void tin1_w(int state); - -protected: - // construction/destruction - mb9061x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_map); - - // device-level overrides - virtual void device_start() override ATTR_COLD; - virtual void device_reset() override ATTR_COLD; - virtual void execute_set_input(int inputnum, int state) override; - virtual space_config_vector memory_space_config() const override; - -private: - static inline constexpr u8 PORT_COUNT = 10; - - // TBC - TIMER_CALLBACK_MEMBER(tbtc_tick); - u8 tbtc_r(); - void tbtc_w(u8 data); - - // INTC - u8 intc_r(offs_t offset); - void intc_w(offs_t offset, u8 data); - void intc_trigger_irq(int icr, int vector); - void intc_clear_irq(int icr, int vector); - - // TIMERS - TIMER_CALLBACK_MEMBER(timer0_tick); - TIMER_CALLBACK_MEMBER(timer1_tick); - u8 timer_r(offs_t offset); - void timer_w(offs_t offset, u8 data); - void recalc_timer(int tnum); - void tin_common(int timer, int base, int state); - - // PORTS - // TODO: Control input and output values with direction registers - u8 m_ports[PORT_COUNT]; - devcb_read8::array m_read_port; - devcb_write8::array m_write_port; - - // AD - u16 m_adcs; - u16 m_adcr; - devcb_read16 m_read_adcs; - devcb_write8 m_write_adcs; - devcb_read16 m_read_adcr; - devcb_write8 m_write_adcr; - - u8 m_timer_regs[8]; - u32 m_timer_hz[2]; - emu_timer *m_timer[2]; - int m_event_state[2]; - u16 m_event_count[2]; - - u8 m_tbtc; - emu_timer *m_tbtc_timer; - - u8 m_intc[0x10]; -}; - -class mb90610_device : public mb9061x_device -{ -public: - mb90610_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - void mb90610_map(address_map &map) ATTR_COLD; -protected: - mb90610_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); -}; - -class mb90611_device : public mb9061x_device -{ -public: - mb90611_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - void mb90611_map(address_map &map) ATTR_COLD; -protected: - mb90611_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); -}; - -class mb90641_device : public mb9061x_device -{ -public: - mb90641_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - void mb90641_map(address_map &map) ATTR_COLD; -protected: - mb90641_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); -}; - -DECLARE_DEVICE_TYPE(MB90610A, mb90610_device) -DECLARE_DEVICE_TYPE(MB90611A, mb90611_device) -DECLARE_DEVICE_TYPE(MB90641A, mb90641_device) - -#endif // MAME_CPU_F2MC16_MB9061X_H diff --git a/src/devices/cpu/f2mc16/mb90640a.cpp b/src/devices/cpu/f2mc16/mb90640a.cpp new file mode 100644 index 00000000000..bddb45805d6 --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90640a.cpp @@ -0,0 +1,134 @@ +// license:BSD-3-Clause +// copyright-holders:smf + +#include "emu.h" +#include "mb90640a.h" + +DEFINE_DEVICE_TYPE(MB90641A, mb90641a_device, "mb90641a", "Fujitsu MB90641A") + +mb90640a_device::mb90640a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + f2mc16_device(mconfig, type, tag, owner, clock), + m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(mb90640a_device::internal_map), this)), + m_clock_generator(*this, "clock_generator"), + m_intc(*this, "intc"), + m_port(*this, "port%x", 1U), + m_ppg(*this, "ppg"), + m_reload_timer(*this, "reload_timer%u", 0U), + m_uart(*this, "uart%u", 0U) +{ +} + +mb90641a_device::mb90641a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb90640a_device(mconfig, MB90641A, tag, owner, clock) +{ +} + +device_memory_interface::space_config_vector mb90640a_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_program_config) + }; +} + +void mb90640a_device::device_add_mconfig(machine_config &mconfig) +{ + F2MC16_PORT(mconfig, m_port[0x0], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x1], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x2], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x3], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x4], 0x00, 0xff); + F2MC16_PORT(mconfig, m_port[0x5], 0x00, 0x3f); + F2MC16_PORT(mconfig, m_port[0x6], 0xff, 0xff); + F2MC16_PORT(mconfig, m_port[0x7], 0x00, 0x7f); + F2MC16_PORT(mconfig, m_port[0x8], 0x00, 0x7f); + F2MC16_PORT(mconfig, m_port[0x9], 0x00, 0x3f); + F2MC16_PORT(mconfig, m_port[0xa], 0x00, 0xfe); + + F2MC16_INTC(mconfig, m_intc); + set_irq_acknowledge_callback(m_intc, FUNC(f2mc16_intc_device::irq_acknowledge_callback)); + F2MC16_CLOCK_GENERATOR(mconfig, m_clock_generator, DERIVED_CLOCK(1, 1), m_intc, 0x22); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[0], DERIVED_CLOCK(1, 1), m_intc, 0x1d); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[1], DERIVED_CLOCK(1, 1), m_intc, 0x1e); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[2], DERIVED_CLOCK(1, 1), m_intc, 0x12); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[3], DERIVED_CLOCK(1, 1), m_intc, 0x14); + F2MC16_RELOAD_TIMER(mconfig, m_reload_timer[4], DERIVED_CLOCK(1, 1), m_intc, 0x16); + m_intc->i2osclr<0x1d>().set(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::i2osclr)); + m_intc->i2osclr<0x1e>().set(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::i2osclr)); + m_intc->i2osclr<0x12>().set(m_reload_timer[2], FUNC(f2mc16_reload_timer_device::i2osclr)); + m_intc->i2osclr<0x14>().set(m_reload_timer[3], FUNC(f2mc16_reload_timer_device::i2osclr)); + m_intc->i2osclr<0x16>().set(m_reload_timer[4], FUNC(f2mc16_reload_timer_device::i2osclr)); + F2MC16_UART(mconfig, m_uart[0], DERIVED_CLOCK(1, 1), m_intc, 0x27, 0x18); + F2MC16_UART(mconfig, m_uart[1], DERIVED_CLOCK(1, 1), m_intc, 0x25, 0x1a); + m_reload_timer[0]->internal_hz().set(m_uart[0], FUNC(f2mc16_uart_device::internal_timer_hz)); + m_reload_timer[0]->internal_hz().append(m_uart[1], FUNC(f2mc16_uart_device::internal_timer_hz)); + F2MC16_PPG(mconfig, m_ppg, DERIVED_CLOCK(1, 1), m_intc, 0x1b, 0x1c); + m_clock_generator->timebase_hz().set(m_ppg, FUNC(f2mc16_ppg_device::timebase_hz)); +} + +void mb90640a_device::internal_map(address_map &map) +{ + map(0x0000, 0x0000).rw(m_port[0x0], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 0 data register *8 + map(0x0001, 0x0001).rw(m_port[0x1], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 1 data register *7 + map(0x0002, 0x0002).rw(m_port[0x2], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 2 data register *6 + map(0x0003, 0x0003).rw(m_port[0x3], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 3 data register *6 + map(0x0004, 0x0004).rw(m_port[0x4], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 4 data register + map(0x0005, 0x0005).rw(m_port[0x5], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 5 data register *8 + map(0x0006, 0x0006).rw(m_port[0x6], FUNC(f2mc16_port_device::pdr_adc_r), FUNC(f2mc16_port_device::pdr_w)); // Port 6 data register + map(0x0007, 0x0007).rw(m_port[0x7], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 7 data register + map(0x0008, 0x0008).rw(m_port[0x8], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 8 data register + map(0x0009, 0x0009).rw(m_port[0x9], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port 9 data register + map(0x000a, 0x000a).rw(m_port[0xa], FUNC(f2mc16_port_device::pdr_r), FUNC(f2mc16_port_device::pdr_w)); // Port a data register *8 + map(0x0010, 0x0010).rw(m_port[0x0], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 0 direction register *8 + map(0x0011, 0x0011).rw(m_port[0x1], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 1 direction register *7 + map(0x0012, 0x0012).rw(m_port[0x2], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 2 direction register *6 + map(0x0013, 0x0013).rw(m_port[0x3], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 3 direction register *6 + map(0x0014, 0x0014).rw(m_port[0x4], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 4 direction register + map(0x0015, 0x0015).rw(m_port[0x5], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 5 direction register *8 + map(0x0016, 0x0016).rw(m_port[0x6], FUNC(f2mc16_port_device::ader_r), FUNC(f2mc16_port_device::ader_w)); // Analog input enable register + map(0x0017, 0x0017).rw(m_port[0x7], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 7 direction register + map(0x0018, 0x0018).rw(m_port[0x8], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 8 direction register + map(0x0019, 0x0019).rw(m_port[0x9], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port 9 direction register + map(0x001a, 0x001a).rw(m_port[0xa], FUNC(f2mc16_port_device::ddr_r), FUNC(f2mc16_port_device::ddr_w)); // Port a direction register + map(0x0020, 0x0020).rw(m_uart[0], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 0 + map(0x0021, 0x0021).rw(m_uart[0], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 0 + map(0x0022, 0x0022).rw(m_uart[0], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 0/Serial output data register 0 + map(0x0023, 0x0023).rw(m_uart[0], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 0 + map(0x0024, 0x0024).rw(m_uart[1], FUNC(f2mc16_uart_device::smr_r), FUNC(f2mc16_uart_device::smr_w)); // Serial mode register 1 + map(0x0025, 0x0025).rw(m_uart[1], FUNC(f2mc16_uart_device::scr_r), FUNC(f2mc16_uart_device::scr_w)); // Serial control register 1 + map(0x0026, 0x0026).rw(m_uart[1], FUNC(f2mc16_uart_device::sidr_r), FUNC(f2mc16_uart_device::sodr_w)); // Serial input data register 1/Serial output data register 1 + map(0x0027, 0x0027).rw(m_uart[1], FUNC(f2mc16_uart_device::ssr_r), FUNC(f2mc16_uart_device::ssr_w)); // Serial control register 1 + map(0x0028, 0x0028).rw(m_intc, FUNC(f2mc16_intc_device::enir_r), FUNC(f2mc16_intc_device::enir_w)); // Interrupt/DTP enable register + map(0x0029, 0x0029).rw(m_intc, FUNC(f2mc16_intc_device::eirr_r), FUNC(f2mc16_intc_device::eirr_w)); // Interrupt/DTP source register + map(0x002a, 0x002b).rw(m_intc, FUNC(f2mc16_intc_device::elvr_r), FUNC(f2mc16_intc_device::elvr_w)); // Interrupt level setting register + map(0x0030, 0x0031).rw(m_ppg, FUNC(f2mc16_ppg_device::ppgc_r), FUNC(f2mc16_ppg_device::ppgc_w)); // operation mode control register + map(0x0034, 0x0035).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<0>), FUNC(f2mc16_ppg_device::prl_w<0>)); // reload register + map(0x0036, 0x0037).rw(m_ppg, FUNC(f2mc16_ppg_device::prl_r<1>), FUNC(f2mc16_ppg_device::prl_w<1>)); // reload register + map(0x0038, 0x0039).rw(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x003a, 0x003b).rw(m_reload_timer[0], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x003c, 0x003d).rw(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x003e, 0x003f).rw(m_reload_timer[1], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x0048, 0x004f).ram(); // CSCR0-CSCR7 + map(0x0051, 0x0051).w(m_uart[0], FUNC(f2mc16_uart_device::cdcr_w)); // UART0 (uart) machine clock division control register + map(0x0053, 0x0053).w(m_uart[1], FUNC(f2mc16_uart_device::cdcr_w)); // UART1 (uart) machine clock division control register + map(0x0058, 0x0059).rw(m_reload_timer[2], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x005a, 0x005b).rw(m_reload_timer[2], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x005c, 0x005d).rw(m_reload_timer[3], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x005e, 0x005f).rw(m_reload_timer[3], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x0060, 0x0061).rw(m_reload_timer[4], FUNC(f2mc16_reload_timer_device::tmcsr_r), FUNC(f2mc16_reload_timer_device::tmcsr_w)); + map(0x0062, 0x0063).rw(m_reload_timer[4], FUNC(f2mc16_reload_timer_device::tmr_r), FUNC(f2mc16_reload_timer_device::tmrlr_w)); + map(0x0064, 0x0067).ram(); // HACK + //map(0x0064, 0x0066).ram(); // TPCR Timer pin control register + map(0x006e, 0x006f).ram(); // HACK + //map(0x006f, 0x006f).ram(); // ROMM ROM mirror function + map(0x009f, 0x009f).rw(m_intc, FUNC(f2mc16_intc_device::dirr_r), FUNC(f2mc16_intc_device::dirr_w)); // Delay interrupt generate/release register + map(0x00a0, 0x00a0).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::lpmcr_r), FUNC(f2mc16_clock_generator_device::lpmcr_w)); // Low power mode control register + map(0x00a1, 0x00a1).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::ckscr_r), FUNC(f2mc16_clock_generator_device::ckscr_w)); // Clock selection register + map(0x00a4, 0x00a7).nopw(); // HACK + //map(0x00a5, 0x00a5).nopw(); // ARSR Auto-ready function selection register + //map(0x00a6, 0x00a6).nopw(); // HACR External address output control register + //map(0x00a7, 0x00a7).nopw(); // ECSR Bus control signal selection register + map(0x00a8, 0x00a8).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::wdtc_r), FUNC(f2mc16_clock_generator_device::wdtc_w)); // Watchdog timer control register + map(0x00a9, 0x00a9).rw(m_clock_generator, FUNC(f2mc16_clock_generator_device::tbtc_r), FUNC(f2mc16_clock_generator_device::tbtc_w)); + map(0x00b0, 0x00bf).rw(m_intc, FUNC(f2mc16_intc_device::icr_r), FUNC(f2mc16_intc_device::icr_w)); + map(0x0100, 0x08ff).ram(); +} diff --git a/src/devices/cpu/f2mc16/mb90640a.h b/src/devices/cpu/f2mc16/mb90640a.h new file mode 100644 index 00000000000..dbf5b198960 --- /dev/null +++ b/src/devices/cpu/f2mc16/mb90640a.h @@ -0,0 +1,52 @@ +// license:BSD-3-Clause +// copyright-holders:smf +#ifndef MAME_CPU_F2MC16_MB90640_H +#define MAME_CPU_F2MC16_MB90640_H + +#pragma once + +#include "f2mc16.h" +#include "f2mc16_clock.h" +#include "f2mc16_intc.h" +#include "f2mc16_port.h" +#include "f2mc16_ppg.h" +#include "f2mc16_reload.h" +#include "f2mc16_uart.h" + +class mb90640a_device : + public f2mc16_device +{ +public: + template typename std::enable_if::type &port() const { if (m_port[N]) return *m_port[N]; return *subdevice(m_port[N].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice(m_ppg.finder_tag()); } + template typename std::enable_if::type &reload_timer() const { if (m_reload_timer[N]) return *m_reload_timer[N]; return *subdevice(m_reload_timer[N].finder_tag()); } + template typename std::enable_if::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice(m_uart[N].finder_tag()); } + +protected: + mb90640a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device_t + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual space_config_vector memory_space_config() const override ATTR_COLD; + + void internal_map(address_map &map) ATTR_COLD; + + const address_space_config m_program_config; + + required_device m_clock_generator; + required_device m_intc; + required_device_array m_port; + required_device m_ppg; + required_device_array m_reload_timer; + required_device_array m_uart; +}; + +class mb90641a_device : public mb90640a_device +{ +public: + mb90641a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + +DECLARE_DEVICE_TYPE(MB90641A, mb90641a_device) + +#endif // MAME_CPU_F2MC16_MB90640_H diff --git a/src/mame/sony/dpsv55.cpp b/src/mame/sony/dpsv55.cpp index ae80e5929a7..89033ccc70a 100644 --- a/src/mame/sony/dpsv55.cpp +++ b/src/mame/sony/dpsv55.cpp @@ -10,7 +10,7 @@ ****************************************************************************/ #include "emu.h" -#include "cpu/f2mc16/mb9061x.h" +#include "cpu/f2mc16/mb90640a.h" #include "machine/nvram.h" #include "video/hd44780.h" #include "emupal.h" @@ -38,11 +38,10 @@ private: HD44780_PIXEL_UPDATE(pixel_update); u8 p5_r(); void p5_w(u8 data); - u8 sci_ssr0_r(); void mem_map(address_map &map) ATTR_COLD; - required_device m_maincpu; + required_device m_maincpu; required_device m_lcdc; u8 m_p5; @@ -73,17 +72,9 @@ void dpsv55_state::p5_w(u8 data) m_p5 = data; } -u8 dpsv55_state::sci_ssr0_r() -{ - return 0x18; -} - void dpsv55_state::mem_map(address_map &map) { - map(0x000011, 0x000011).nopw(); - map(0x000022, 0x000022).noprw(); - map(0x000023, 0x000023).r(FUNC(dpsv55_state::sci_ssr0_r)); map(0xfc0000, 0xfc7fff).mirror(0x18000).ram().share("nvram"); // CS1 map(0xfe0000, 0xffffff).rom().region("eprom", 0); // CS0 } @@ -96,10 +87,10 @@ void dpsv55_state::dpsv55(machine_config &config) { MB90641A(config, m_maincpu, 4_MHz_XTAL); // MB90641APF-G-105BND m_maincpu->set_addrmap(AS_PROGRAM, &dpsv55_state::mem_map); - m_maincpu->read_pdr1().set(m_lcdc, FUNC(hd44780_device::db_r)); - m_maincpu->write_pdr1().set(m_lcdc, FUNC(hd44780_device::db_w)); - m_maincpu->read_pdr5().set(FUNC(dpsv55_state::p5_r)); - m_maincpu->write_pdr5().set(FUNC(dpsv55_state::p5_w)); + m_maincpu->port<1>().read().set(m_lcdc, FUNC(hd44780_device::db_r)); + m_maincpu->port<1>().write().set(m_lcdc, FUNC(hd44780_device::db_w)); + m_maincpu->port<5>().read().set(FUNC(dpsv55_state::p5_r)); + m_maincpu->port<5>().write().set(FUNC(dpsv55_state::p5_w)); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // CY62256LL-70SNC-T2 + 3V lithium battery + M62021FP-600C reset generator + M5239L voltage detector @@ -140,7 +131,7 @@ Sony Corporation (c)1998 */ ROM_START(dpsv55) - ROM_REGION(0x20000, "eprom", 0) + ROM_REGION16_LE(0x20000, "eprom", 0) ROM_LOAD("dps-v55_m__ver.1.02__759-499-74.ic704", 0x00000, 0x20000, CRC(138c2fe0) SHA1(0916ccb1d7567639b382a19240a56274c5c2fa4a)) ROM_END diff --git a/src/mame/tomy/tomy_princ.cpp b/src/mame/tomy/tomy_princ.cpp index dd87ead5d64..c4fa7d7aabc 100644 --- a/src/mame/tomy/tomy_princ.cpp +++ b/src/mame/tomy/tomy_princ.cpp @@ -116,7 +116,7 @@ #include "bus/generic/carts.h" #include "bus/generic/slot.h" -#include "cpu/f2mc16/mb9061x.h" +#include "cpu/f2mc16/mb90610a.h" #include "machine/timer.h" #include "emupal.h" @@ -146,6 +146,7 @@ public: , m_palette(*this, "palette") , m_scantimer(*this, "scantimer") , m_io_keys(*this, "KEY%u", 1U) + , m_key(~0) { #ifdef VIDEO_DEBUG SCREEN_W = BITPLANE_W; @@ -221,7 +222,8 @@ protected: u8 pdr8_r(); u8 pdra_r(); u8 key_r(); - virtual u8 key_to_pdr_bit(u8 port, u8 bit); + virtual void pdr6_w(u8 data); + virtual void pdr8_w(u8 data); enum render_cmd_type : u8 { @@ -235,7 +237,7 @@ protected: PUT_SHAPE_PIXEL = 0x80, }; - required_device m_maincpu; + required_device m_maincpu; required_device m_cart; required_device m_screen; @@ -302,7 +304,6 @@ protected: bool m_is_bound_found; bool m_is_overlay_enabled; -private: enum layer_target : u8 { DEFAULT_TARGET, @@ -350,18 +351,16 @@ private: u8 m_ext_reg0C; bool m_is_ext_reg00_read; + uint16_t m_key; }; TIMER_DEVICE_CALLBACK_MEMBER(tomy_princ_state::scan_interrupt) { - for (size_t i = 0; i < 128; i++) + for (int i = 0; i < 128; i++) { - m_maincpu->tin0_w(ASSERT_LINE); - m_maincpu->tin0_w(CLEAR_LINE); + m_maincpu->reload_timer<0>().tin(ASSERT_LINE); + m_maincpu->reload_timer<0>().tin(CLEAR_LINE); } - - m_maincpu->tin1_w(ASSERT_LINE); - m_maincpu->tin1_w(CLEAR_LINE); } void tomy_princ_state::machine_start() @@ -374,6 +373,7 @@ void tomy_princ_state::machine_start() save_item(NAME(m_ext_reg0C)); save_item(NAME(m_is_ext_reg00_read)); + save_item(NAME(m_key)); } void tomy_princ_state::machine_reset() @@ -1042,56 +1042,24 @@ DEVICE_IMAGE_LOAD_MEMBER(tomy_princ_state::cart_load) u8 tomy_princ_state::key_r() { - u8 pdr_bits = 0; + LOGMASKED(LOG_REG, "%s: key=%04x\n", machine().describe_context(), m_key); + + u8 data = 0xff; for (u8 port = 0; port < 9; port++) - { - u32 port_bit = m_io_keys[port]->read(); - for (u8 bit = 0; bit < 8; bit++) - { - if (BIT(port_bit, bit) != 0) - { - pdr_bits |= key_to_pdr_bit(port, bit); - } - } - } + if (!BIT(m_key, port)) + data &= m_io_keys[port]->read(); - return pdr_bits ^ 0xff; + return data; } -u8 tomy_princ_state::key_to_pdr_bit(u8 port, u8 bit) +void tomy_princ_state::pdr6_w(u8 data) { - const u8 pdr6 = m_maincpu->read_port(mb9061x_device::PDR6); - const u8 pdr8 = m_maincpu->read_port(mb9061x_device::PDR8); - - LOGMASKED(LOG_REG, "%s: pdr6=%02x pdr8=%02x\n", machine().describe_context(), pdr6 ^ 0xff, pdr8 ^ 0xff); - - u8 target_port = 0; - for (size_t i = 0; i < 7; i++) - { - if (BIT(pdr6 ^ 0xff, i)) - { - target_port = i; - if (port == target_port) - { - LOGMASKED(LOG_REG, "%s: matched port=%02x bit=%02x\n", machine().describe_context(), port, bit); - return 1 << bit; - } - } - } - for (size_t i = 5; i < 7; i++) - { - if (BIT(pdr8 ^ 0xff, i)) - { - target_port = 7 + (i - 5); - if (port == target_port) - { - LOGMASKED(LOG_REG, "%s: matched port=%02x bit=%02x\n", machine().describe_context(), port, bit); - return 1 << bit; - } - } - } + m_key = (m_key & ~0x7f) | BIT(data, 0, 7); +} - return 0; +void tomy_princ_state::pdr8_w(u8 data) +{ + m_key = (m_key & 0x7f) | (BIT(data, 5, 2) << 7); } void tomy_princ_state::princ_map(address_map &map) @@ -1111,103 +1079,106 @@ void tomy_princ_state::princ_map(address_map &map) // FIXME: Identify unknown keys static INPUT_PORTS_START( tomy_princ ) PORT_START( "KEY1" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ho") PORT_CODE(KEYCODE_EQUALS) // ほ 82D9h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Memory") PORT_CODE(KEYCODE_F8) // メモリー FF08h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ho") PORT_CODE(KEYCODE_EQUALS) // ほ 82D9h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Memory") PORT_CODE(KEYCODE_F8) // メモリー FF08h PORT_START( "KEY2" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Menu") PORT_CODE(KEYCODE_F7) // メニュー FF07h - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("He") PORT_CODE(KEYCODE_BACKSPACE) // へ 82D6h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Print") PORT_CODE(KEYCODE_F9) // 印刷 FF09h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Menu") PORT_CODE(KEYCODE_F7) // メニュー FF07h + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("He") PORT_CODE(KEYCODE_BACKSPACE) // へ 82D6h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Print") PORT_CODE(KEYCODE_F9) // 印刷 FF09h PORT_START( "KEY3" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF17h") PORT_CODE(KEYCODE_END) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Symbol") PORT_CODE(KEYCODE_F11) // 絵記号 FF0Bh + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF17h") PORT_CODE(KEYCODE_END) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Symbol") PORT_CODE(KEYCODE_F11) // 絵記号 FF0Bh PORT_START( "KEY4" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Font Color") PORT_CODE(KEYCODE_F10) // 字体色 FF0Ah - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF16h") PORT_CODE(KEYCODE_DEL) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Complete") PORT_CODE(KEYCODE_F12) // 文完了 FF0Ch + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Font Color") PORT_CODE(KEYCODE_F10) // 字体色 FF0Ah + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF16h") PORT_CODE(KEYCODE_DEL) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Complete") PORT_CODE(KEYCODE_F12) // 文完了 FF0Ch PORT_START( "KEY5" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Re") PORT_CODE(KEYCODE_BACKSLASH) // れ 82EAh - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("!") PORT_CODE(KEYCODE_COLON) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Romaji") PORT_CODE(KEYCODE_HOME) // ローマ字 FF0Eh + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Re") PORT_CODE(KEYCODE_BACKSLASH) // れ 82EAh + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("!") PORT_CODE(KEYCODE_COLON) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Romaji") PORT_CODE(KEYCODE_HOME) // ローマ字 FF0Eh PORT_START( "KEY6" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_INSERT) // ー字消す FF0Dh - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("?") PORT_CODE(KEYCODE_SLASH) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Zoom") PORT_CODE(KEYCODE_PGUP) // ズーム FF0Fh + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Delete") PORT_CODE(KEYCODE_INSERT) // ー字消す FF0Dh + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("?") PORT_CODE(KEYCODE_SLASH) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Zoom") PORT_CODE(KEYCODE_PGUP) // ズーム FF0Fh PORT_START( "KEY7" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) // FF13h - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ne") PORT_CODE(KEYCODE_RCONTROL) // ね 82CBh - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("NO") PORT_CODE(KEYCODE_RSHIFT) // FF10h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) // FF12h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) // FF13h + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ne") PORT_CODE(KEYCODE_RCONTROL) // ね 82CBh + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("NO") PORT_CODE(KEYCODE_RSHIFT) // FF10h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) // FF12h PORT_START( "KEY8" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) // FF14h - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ru") PORT_CODE(KEYCODE_QUOTE) // る 82E9h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) // FF15h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) // FF14h + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ru") PORT_CODE(KEYCODE_QUOTE) // る 82E9h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) // FF15h PORT_START( "KEY9" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Extra Kanji") PORT_CODE(KEYCODE_F6) // 別漢字 FF06h - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("No conversion") PORT_CODE(KEYCODE_F5) // 無変換 FF05h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A/a Numeral") PORT_CODE(KEYCODE_F3) // A/a 数 FF03h - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_F1) // シフト FF01h - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Hira/Kata") PORT_CODE(KEYCODE_F2) // ひら/カタ FF02h - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Kanji conversion") PORT_CODE(KEYCODE_F4) // 漢字変換 FF04h - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) // スペース 8140h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("OK") PORT_CODE(KEYCODE_ENTER) // FF11h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Extra Kanji") PORT_CODE(KEYCODE_F6) // 別漢字 FF06h + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("No conversion") PORT_CODE(KEYCODE_F5) // 無変換 FF05h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A/a Numeral") PORT_CODE(KEYCODE_F3) // A/a 数 FF03h + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_F1) // シフト FF01h + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Hira/Kata") PORT_CODE(KEYCODE_F2) // ひら/カタ FF02h + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Kanji conversion") PORT_CODE(KEYCODE_F4) // 漢字変換 FF04h + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) // スペース 8140h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("OK") PORT_CODE(KEYCODE_ENTER) // FF11h INPUT_PORTS_END void tomy_princ_state::tomy_princ(machine_config &config) { MB90611A(config, m_maincpu, 16_MHz_XTAL); m_maincpu->set_addrmap(AS_PROGRAM, &tomy_princ_state::princ_map); - m_maincpu->read_pdr1().set(FUNC(tomy_princ_state::key_r)); - m_maincpu->read_pdr8().set(FUNC(tomy_princ_state::pdr8_r)); - m_maincpu->read_pdra().set(FUNC(tomy_princ_state::pdra_r)); + m_maincpu->port<0x1>().read().set(FUNC(tomy_princ_state::key_r)); + m_maincpu->port<0x6>().write().set(FUNC(tomy_princ_state::pdr6_w)); + m_maincpu->port<0x8>().read().set(FUNC(tomy_princ_state::pdr8_r)); + m_maincpu->port<0x8>().write().set(FUNC(tomy_princ_state::pdr8_w)); + m_maincpu->port<0xa>().read().set(FUNC(tomy_princ_state::pdra_r)); + m_maincpu->reload_timer<1>().tin_hz(16_MHz_XTAL); // Guessed. Waits at startup for 0x7530 underflows with reload = 0x37f SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); @@ -1238,6 +1209,7 @@ public: , m_io_pen_x(*this, "PENX") , m_io_pen_y(*this, "PENY") , m_config(*this, "CONFIG") + , m_pdra(~0) { #ifdef VIDEO_DEBUG SCREEN_W = BITPLANE_W; @@ -1273,28 +1245,38 @@ public: void tomy_princ_tablet(machine_config &config); protected: + virtual void machine_start() override ATTR_COLD; virtual u8 vdp_stat_r() override; - virtual u8 key_to_pdr_bit(u8 port, u8 bit) override; + virtual void pdr6_w(u8 data) override; + virtual void pdr8_w(u8 data) override; private: - u16 adcr_r(); - - static constexpr s32 rescale(s32 x, s32 min_x, s32 max_x, s32 a, s32 b) - { - // Rescaling (min-max normalization) from [min_x..max_x] to [a..b]. - return a + (((x - min_x) * (b - a)) / (max_x - min_x)); - } + void pdr9_w(u8 data); + void pdra_w(u8 data); + u16 adc5_r(); + u16 adc6_r(); required_ioport m_io_pen_x; required_ioport m_io_pen_y; required_ioport m_config; + u8 m_pdra; }; void tomy_princ_tablet_state::tomy_princ_tablet(machine_config &config) { tomy_princ_state::tomy_princ(config); - m_maincpu->read_adcr().set(FUNC(tomy_princ_tablet_state::adcr_r)); + m_maincpu->port<0x9>().write().set(FUNC(tomy_princ_tablet_state::pdr9_w)); + m_maincpu->port<0xa>().write().set(FUNC(tomy_princ_tablet_state::pdra_w)); + m_maincpu->adc().channel<5>().set(FUNC(tomy_princ_tablet_state::adc5_r)); + m_maincpu->adc().channel<6>().set(FUNC(tomy_princ_tablet_state::adc6_r)); +} + +void tomy_princ_tablet_state::machine_start() +{ + tomy_princ_state::machine_start(); + + save_item(NAME(m_pdra)); } u8 tomy_princ_tablet_state::vdp_stat_r() @@ -1318,83 +1300,64 @@ u8 tomy_princ_tablet_state::vdp_stat_r() return stat; } -u8 tomy_princ_tablet_state::key_to_pdr_bit(u8 port, u8 bit) +void tomy_princ_tablet_state::pdr6_w(u8 data) { - const u8 pdr6 = m_maincpu->read_port(mb9061x_device::PDR6); - const u8 pdr9 = m_maincpu->read_port(mb9061x_device::PDR9); + m_key = (m_key & ~0x1f) | BIT(data, 0, 5); +} - LOGMASKED(LOG_REG, "%s: pdr6=%02x pdr9=%02x\n", machine().describe_context(), pdr6 ^ 0xff, pdr9 ^ 0xff); +void tomy_princ_tablet_state::pdr8_w(u8 data) +{ +} - u8 target_port = 0; - for (size_t i = 0; i < 5; i++) - { - if (BIT(pdr6 ^ 0xff, i)) - { - target_port = i; - if (port == target_port) - { - LOGMASKED(LOG_REG, "%s: matched port=%02x bit=%02x\n", machine().describe_context(), port, bit); - return 1 << bit; - } - } - } - if (pdr9 != 0) +void tomy_princ_tablet_state::pdr9_w(u8 data) +{ + m_key = (m_key & 0x1f) | (BIT(data, 2, 3) << 5); +} + +void tomy_princ_tablet_state::pdra_w(u8 data) +{ + m_pdra = data; +} + +u16 tomy_princ_tablet_state::adc5_r() +{ + if (BIT(m_config->read(), 0)) { - for (size_t i = 2; i < 5; i++) + if (BIT(m_pdra, 3)) // PDRA = u8 & 0x80 | 0x48; ADCS = 5 | (5 << 3); { - if (BIT(pdr9 ^ 0xff, i)) - { - target_port = 5 + (i - 2); - if (port == target_port) - { - LOGMASKED(LOG_REG, "%s: matched port=%02x bit=%02x\n", machine().describe_context(), port, bit); - return 1 << bit; - } - } + // Pen y-position + const s16 pen_y = m_io_pen_y->read(); + LOGMASKED(LOG_REG, "%s: adcr_r pen y=%04x, PDRA=%02x\n", machine().describe_context(), pen_y, m_pdra); + return pen_y; } + + LOGMASKED(LOG_REG, "%s: adc5_r unknown state, PDRA=%02x\n", machine().describe_context(), m_pdra); } return 0; } -u16 tomy_princ_tablet_state::adcr_r() +u16 tomy_princ_tablet_state::adc6_r() { - u8 pdra = m_maincpu->read_port(mb9061x_device::PDRA); - u16 adcs = m_maincpu->read_reg_adcs(); - - // Is pen enabled? if (BIT(m_config->read(), 0)) { - if (BIT(pdra, 3) && (adcs & 0b101101) == 0b101101) // PDRA = u8 & 0x80 | 0x48; ADCS = 5 | (5 << 3); - { - // Pen y-position - const s16 io_pen_y_min = m_io_pen_y->field(0xff)->minval(); - const s16 io_pen_y_max = m_io_pen_y->field(0xff)->maxval(); - const s16 io_pen_y = m_io_pen_y->read(); - const u16 pen_y = rescale(io_pen_y, io_pen_y_min, io_pen_y_max, 0x078, 0x3b0); - LOGMASKED(LOG_REG, "%s: adcr_r pen y=%04x, PDRA=%02x, ADCS=%04x\n", machine().describe_context(), pen_y, pdra, adcs); - return pen_y; - } - else if (BIT(pdra, 4) && (adcs & 0b110110) == 0b110110) // PDRA = u8 & 0x80 | 0x30; ADCS = 6 | (6 << 3); + if (BIT(m_pdra, 4)) // PDRA = u8 & 0x80 | 0x30; ADCS = 6 | (6 << 3); { // Pen x-position - const s16 io_pen_x_min = m_io_pen_x->field(0xff)->minval(); - const s16 io_pen_x_max = m_io_pen_x->field(0xff)->maxval(); - const s16 io_pen_x = m_io_pen_x->read(); - const u16 pen_x = rescale(io_pen_x, io_pen_x_min, io_pen_x_max, 0x068, 0x3c0); - LOGMASKED(LOG_REG, "%s: adcr_r pen x=%04x, PDRA=%02x, ADCS=%04x\n", machine().describe_context(), pen_x, pdra, adcs); + const s16 pen_x = m_io_pen_x->read(); + LOGMASKED(LOG_REG, "%s: adc6_r pen x=%04x, PDRA=%02x\n", machine().describe_context(), pen_x, m_pdra); return pen_x; } - else if (BIT(pdra, 5)) // PDRA = u8 & 0x80 | 0x20; + else if (BIT(m_pdra, 5)) // PDRA = u8 & 0x80 | 0x20; { // Program code checks for value >= 600 before reading pen position, // likely some time-based counter of pen touching tablet. We just send max value. const u16 pen_stat = 0x3ff; - LOGMASKED(LOG_REG, "%s: adcr_r pen stat=%04x, PDRA=%02x, ADCS=%04x\n", machine().describe_context(), pen_stat, pdra, adcs); + LOGMASKED(LOG_REG, "%s: adcr_r pen stat=%04x, PDRA=%02x\n", machine().describe_context(), pen_stat, m_pdra); return pen_stat; } - LOGMASKED(LOG_REG, "%s: adcr_r unknown state, PDRA=%02x, ADCS=%04x\n", machine().describe_context(), pdra, adcs); + LOGMASKED(LOG_REG, "%s: adc6_r unknown state, PDRA=%02x\n", machine().describe_context(), m_pdra); } return 0; @@ -1406,95 +1369,95 @@ static INPUT_PORTS_START( tomy_princ_tablet ) PORT_CONFNAME( 0x01, 0x00, "Controller" ) PORT_CONFSETTING( 0x00, DEF_STR( None ) ) PORT_CONFSETTING( 0x01, "Pen" ) - + PORT_START( "PENX" ) - PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("PEN X") + PORT_BIT( 0x3ff, 0x214, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(0x068, 0x03c0) PORT_PLAYER(1) PORT_NAME("PEN X") PORT_START( "PENY" ) - PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(10) PORT_MINMAX(0, 255) PORT_PLAYER(1) PORT_NAME("PEN Y") + PORT_BIT( 0x3ff, 0x214, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(0x078, 0x3b0) PORT_PLAYER(1) PORT_NAME("PEN Y") PORT_START( "KEY1" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_F1) // シフト FF01h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ho") PORT_CODE(KEYCODE_EQUALS) // ほ 82D9h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_F1) // シフト FF01h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ho") PORT_CODE(KEYCODE_EQUALS) // ほ 82D9h PORT_START( "KEY2" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Hira/Kata") PORT_CODE(KEYCODE_F2) // ひら/カタ FF02h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF07h") PORT_CODE(KEYCODE_F7) // F378h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Hira/Kata") PORT_CODE(KEYCODE_F2) // ひら/カタ FF02h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF07h") PORT_CODE(KEYCODE_F7) // F378h PORT_START( "KEY3" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A/a Numeral") PORT_CODE(KEYCODE_F3) // A/a 数 FF03h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("?") PORT_CODE(KEYCODE_SLASH) + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("A/a Numeral") PORT_CODE(KEYCODE_F3) // A/a 数 FF03h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("?") PORT_CODE(KEYCODE_SLASH) PORT_START( "KEY4" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Kanji conversion") PORT_CODE(KEYCODE_F4) // 漢字変換 FF04h - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ru") PORT_CODE(KEYCODE_QUOTE) // る 82E9h - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Kanji conversion") PORT_CODE(KEYCODE_F4) // 漢字変換 FF04h + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ru") PORT_CODE(KEYCODE_QUOTE) // る 82E9h + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_START( "KEY5" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ne") PORT_CODE(KEYCODE_RCONTROL) // ね 82CBh - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("No conversion") PORT_CODE(KEYCODE_F5) // 無変換 FF05h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF0Bh") PORT_CODE(KEYCODE_F11) + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ne") PORT_CODE(KEYCODE_RCONTROL) // ね 82CBh + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("No conversion") PORT_CODE(KEYCODE_F5) // 無変換 FF05h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF0Bh") PORT_CODE(KEYCODE_F11) PORT_START( "KEY6" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Re") PORT_CODE(KEYCODE_BACKSLASH) // れ 82EAh - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) // スペース 8140h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("!") PORT_CODE(KEYCODE_COLON) + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_UNUSED) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Re") PORT_CODE(KEYCODE_BACKSLASH) // れ 82EAh + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) // スペース 8140h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("!") PORT_CODE(KEYCODE_COLON) PORT_START( "KEY7" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF0Ah") PORT_CODE(KEYCODE_F10) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Extra Kanji") PORT_CODE(KEYCODE_F6) // 別漢字 FF06h - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF08h") PORT_CODE(KEYCODE_F8) // F379h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF0Ah") PORT_CODE(KEYCODE_F10) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Extra Kanji") PORT_CODE(KEYCODE_F6) // 別漢字 FF06h + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF08h") PORT_CODE(KEYCODE_F8) // F379h PORT_START( "KEY8" ) - PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) - PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("FF09h") PORT_CODE(KEYCODE_F9) - PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) - PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) - PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) - PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) - PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Ok (T)") PORT_CODE(KEYCODE_ENTER) // FF0Ch - PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("He") PORT_CODE(KEYCODE_BACKSPACE) // へ 82D6h + PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) + PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("FF09h") PORT_CODE(KEYCODE_F9) + PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) + PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) + PORT_BIT(0x10,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) + PORT_BIT(0x20,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) + PORT_BIT(0x40,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("Ok (T)") PORT_CODE(KEYCODE_ENTER) // FF0Ch + PORT_BIT(0x80,IP_ACTIVE_LOW,IPT_KEYBOARD) PORT_NAME("He") PORT_CODE(KEYCODE_BACKSPACE) // へ 82D6h PORT_START( "KEY9" ) - PORT_BIT(0xff,IP_ACTIVE_HIGH,IPT_UNUSED) + PORT_BIT(0xff,IP_ACTIVE_LOW,IPT_UNUSED) INPUT_PORTS_END // PCB markings: Prin-C Tablet E100-T201-11 -- cgit v1.2.3