summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua22
-rw-r--r--src/devices/cpu/f2mc16/f2mc16.cpp296
-rw-r--r--src/devices/cpu/f2mc16/f2mc16.h17
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_adc.cpp304
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_adc.h72
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_clock.cpp355
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_clock.h74
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_intc.cpp269
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_intc.h64
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_port.cpp127
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_port.h57
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_ppg.cpp348
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_ppg.h70
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_reload.cpp381
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_reload.h75
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_uart.cpp456
-rw-r--r--src/devices/cpu/f2mc16/f2mc16_uart.h98
-rw-r--r--src/devices/cpu/f2mc16/mb90570.cpp169
-rw-r--r--src/devices/cpu/f2mc16/mb90570.h55
-rw-r--r--src/devices/cpu/f2mc16/mb90610a.cpp138
-rw-r--r--src/devices/cpu/f2mc16/mb90610a.h59
-rw-r--r--src/devices/cpu/f2mc16/mb9061x.cpp457
-rw-r--r--src/devices/cpu/f2mc16/mb9061x.h180
-rw-r--r--src/devices/cpu/f2mc16/mb90640a.cpp134
-rw-r--r--src/devices/cpu/f2mc16/mb90640a.h52
-rw-r--r--src/mame/sony/dpsv55.cpp23
-rw-r--r--src/mame/tomy/tomy_princ.cpp479
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