diff options
27 files changed, 3804 insertions, 1027 deletions
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<f2mc16_intc_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<f2mc16_intc_device> &intc, uint8_t vector); + f2mc16_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + template<unsigned N> 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<f2mc16_intc_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<f2mc16_intc_device> &intc, uint8_t tbtc_vector) : + f2mc16_clock_generator_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast<f2mc16_device *>(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<f2mc16_intc_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<f2mc16_intc_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<f2mc16_device *>(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<unsigned N> 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<f2mc16_device *>(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<f2mc16_intc_device> &intc, uint8_t ppg0_vector, uint8_t ppg1_vector) : + f2mc16_ppg_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast<f2mc16_device *>(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<unsigned N> +uint16_t f2mc16_ppg_device::prl_r() +{ + return (m_prlh[N] << 8) | m_prll[N]; +} + +template<unsigned N> +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 <unsigned N> +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<f2mc16_intc_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<unsigned N> 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<unsigned N> uint16_t prl_r(); + template<unsigned N> 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 <unsigned N> TIMER_CALLBACK_MEMBER(timer_callback); + + f2mc16_device *m_cpu; + required_device<f2mc16_intc_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<f2mc16_intc_device> &intc, uint8_t vector) : + f2mc16_reload_timer_device(mconfig, tag, owner, clock) +{ + m_cpu = downcast<f2mc16_device *>(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<f2mc16_intc_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<f2mc16_intc_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<f2mc16_intc_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<f2mc16_intc_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<f2mc16_intc_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<f2mc16_adc_device>(m_adc.finder_tag()); } + template<unsigned N> typename std::enable_if<N < 13, f2mc16_port_device>::type &port() const { if (m_port[N]) return *m_port[N]; return *subdevice<f2mc16_port_device>(m_port[N].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice<f2mc16_ppg_device>(m_ppg.finder_tag()); } + template<unsigned N> typename std::enable_if<N < 2, f2mc16_uart_device>::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice<f2mc16_uart_device>(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<f2mc16_adc_device> m_adc; + required_device<f2mc16_clock_generator_device> m_clock_generator; + required_device<f2mc16_intc_device> m_intc; + required_device_array<f2mc16_port_device, 13> m_port; + required_device<f2mc16_ppg_device> m_ppg; + required_device_array<f2mc16_uart_device, 2> 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<f2mc16_adc_device>(m_adc.finder_tag()); } + template<unsigned N> typename std::enable_if<N >= 1 && N <= 10, f2mc16_port_device>::type &port() const { if (m_port[N - 1]) return *m_port[N - 1]; return *subdevice<f2mc16_port_device>(m_port[N - 1].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice<f2mc16_ppg_device>(m_ppg.finder_tag()); } + template<unsigned N> typename std::enable_if<N < 2, f2mc16_reload_timer_device>::type &reload_timer() const { if (m_reload_timer[N]) return *m_reload_timer[N]; return *subdevice<f2mc16_reload_timer_device>(m_reload_timer[N].finder_tag()); } + template<unsigned N> typename std::enable_if<N < 3, f2mc16_uart_device>::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice<f2mc16_uart_device>(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<f2mc16_adc_device> m_adc; + required_device<f2mc16_clock_generator_device> m_clock_generator; + required_device<f2mc16_intc_device> m_intc; + required_device_array<f2mc16_port_device, 10> m_port; + required_device<f2mc16_ppg_device> m_ppg; + required_device_array<f2mc16_reload_timer_device, 2> m_reload_timer; + required_device_array<f2mc16_uart_device, 3> 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<PORT_COUNT> m_read_port; - devcb_write8::array<PORT_COUNT> 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<unsigned N> typename std::enable_if<N < 11, f2mc16_port_device>::type &port() const { if (m_port[N]) return *m_port[N]; return *subdevice<f2mc16_port_device>(m_port[N].finder_tag()); } + auto &ppg() const { if (m_ppg) return *m_ppg; return *subdevice<f2mc16_ppg_device>(m_ppg.finder_tag()); } + template<unsigned N> typename std::enable_if<N < 5, f2mc16_reload_timer_device>::type &reload_timer() const { if (m_reload_timer[N]) return *m_reload_timer[N]; return *subdevice<f2mc16_reload_timer_device>(m_reload_timer[N].finder_tag()); } + template<unsigned N> typename std::enable_if<N < 2, f2mc16_uart_device>::type &uart() const { if (m_uart[N]) return *m_uart[N]; return *subdevice<f2mc16_uart_device>(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<f2mc16_clock_generator_device> m_clock_generator; + required_device<f2mc16_intc_device> m_intc; + required_device_array<f2mc16_port_device, 11> m_port; + required_device<f2mc16_ppg_device> m_ppg; + required_device_array<f2mc16_reload_timer_device, 5> m_reload_timer; + required_device_array<f2mc16_uart_device, 2> 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<mb90641_device> m_maincpu; + required_device<mb90641a_device> m_maincpu; required_device<hd44780_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<mb90611_device> m_maincpu; + required_device<mb90611a_device> m_maincpu; required_device<generic_slot_device> m_cart; required_device<screen_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 |