summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Devin Acker <d@revenant1.net>2021-10-27 04:21:46 -0400
committer GitHub <noreply@github.com>2021-10-27 10:21:46 +0200
commit935d28a67573f4cd1333639927f19798ce953f1e (patch)
tree6fccc4072e472f8caf6d062779d417b5eb820da1
parent163659b50aabc57aaeeb55e35e88d85523cdbc4c (diff)
new NOT_WORKING machine (Casio CTK-2100) (#8757)
* ctk2100: preliminary work * ctk2100: possible keyboard hookup * ctk2100: hook up rudimentary timers * ctk2100: add ports and hook up the LCD * ctk2100: timer tweaks, input tweaks * ctk2100: fix I/O port reads (stops constant LCD resets) * gt913: increase key polling rate (fixes ctk2100 test mode) * ctk2100: add ADCs, clean up and comment some other stuff * lpc210x: add the PL190 VIC here too while i'm at it * vic_pl192: fix clang build * unidasm: add gt913
-rw-r--r--scripts/src/cpu.lua2
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/cpu/arm7/lpc210x.cpp29
-rw-r--r--src/devices/cpu/arm7/lpc210x.h7
-rw-r--r--src/devices/cpu/arm7/upd800468.cpp252
-rw-r--r--src/devices/cpu/arm7/upd800468.h103
-rw-r--r--src/devices/cpu/h8/gt913.cpp3
-rw-r--r--src/devices/machine/gt913_kbd.cpp14
-rw-r--r--src/devices/machine/gt913_kbd.h16
-rw-r--r--src/devices/machine/vic_pl192.cpp375
-rw-r--r--src/devices/machine/vic_pl192.h99
-rw-r--r--src/mame/drivers/ctk2000.cpp300
-rw-r--r--src/mame/drivers/ctk551.cpp29
-rw-r--r--src/mame/mess.flt1
-rw-r--r--src/tools/unidasm.cpp2
15 files changed, 1114 insertions, 119 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 9c612457313..78f18f4430a 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -160,6 +160,8 @@ if CPUS["ARM7"] then
MAME_DIR .. "src/devices/cpu/arm7/arm7ops.cpp",
MAME_DIR .. "src/devices/cpu/arm7/lpc210x.cpp",
MAME_DIR .. "src/devices/cpu/arm7/lpc210x.h",
+ MAME_DIR .. "src/devices/cpu/arm7/upd800468.cpp",
+ MAME_DIR .. "src/devices/cpu/arm7/upd800468.h",
MAME_DIR .. "src/devices/cpu/arm7/arm7core.h",
MAME_DIR .. "src/devices/cpu/arm7/arm7core.hxx",
MAME_DIR .. "src/devices/cpu/arm7/arm7drc.hxx",
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 580e9460a3f..0694b048902 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -2025,6 +2025,7 @@ files {
MAME_DIR .. "src/mame/drivers/fp6000.cpp",
MAME_DIR .. "src/mame/machine/fp6000_kbd.cpp",
MAME_DIR .. "src/mame/machine/fp6000_kbd.h",
+ MAME_DIR .. "src/mame/drivers/ctk2000.cpp",
MAME_DIR .. "src/mame/drivers/ctk551.cpp",
MAME_DIR .. "src/mame/drivers/ht6000.cpp",
MAME_DIR .. "src/mame/drivers/pb1000.cpp",
diff --git a/src/devices/cpu/arm7/lpc210x.cpp b/src/devices/cpu/arm7/lpc210x.cpp
index 9e63b5785d0..75a322f01a2 100644
--- a/src/devices/cpu/arm7/lpc210x.cpp
+++ b/src/devices/cpu/arm7/lpc210x.cpp
@@ -37,13 +37,14 @@ void lpc210x_device::lpc2103_map(address_map &map)
map(0xE01FC100, 0xE01FC103).rw(FUNC(lpc210x_device::apbdiv_r), FUNC(lpc210x_device::apbdiv_w));
map(0xE01FC1a0, 0xE01FC1a3).rw(FUNC(lpc210x_device::scs_r), FUNC(lpc210x_device::scs_w));
- map(0xFFFFF000, 0xFFFFF2ff).rw(FUNC(lpc210x_device::vic_r), FUNC(lpc210x_device::vic_w)); // interrupt controller
+ map(0xfffff000, 0xffffffff).m(m_vic, FUNC(vic_pl190_device::map)); // interrupt controller
}
lpc210x_device::lpc210x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: arm7_cpu_device(mconfig, LPC2103, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_LITTLE)
, m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0, address_map_constructor(FUNC(lpc210x_device::lpc2103_map), this))
+ , m_vic(*this, "vic")
{
}
@@ -98,29 +99,6 @@ void lpc210x_device::device_reset()
m_TxPR[1] = 0;
}
-/* VIC (Vectored Interrupt Controller) */
-
-uint32_t lpc210x_device::vic_r(offs_t offset, uint32_t mem_mask)
-{
- switch (offset*4)
- {
- default:
- logerror("%s unhandled read from VIC offset %08x mem_mask %08x\n", machine().describe_context(), offset * 4, mem_mask);
- }
-
- return 0x00000000;
-}
-
-
-void lpc210x_device::vic_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- switch (offset * 4)
- {
- default:
- logerror("%s unhandled write VIC offset %02x data %08x mem_mask %08x\n", machine().describe_context(), offset * 4, data, mem_mask);
- }
-}
-
/* PIN Select block */
uint32_t lpc210x_device::pin_r(offs_t offset, uint32_t mem_mask)
@@ -278,4 +256,7 @@ void lpc210x_device::write_timer(int timer, int offset, uint32_t data, uint32_t
void lpc210x_device::device_add_mconfig(machine_config &config)
{
+ PL190_VIC(config, m_vic, 0);
+ m_vic->out_irq_cb().set_inputline(*this, ARM7_IRQ_LINE);
+ m_vic->out_fiq_cb().set_inputline(*this, ARM7_FIRQ_LINE);
}
diff --git a/src/devices/cpu/arm7/lpc210x.h b/src/devices/cpu/arm7/lpc210x.h
index c21b346a5e3..47a801a6058 100644
--- a/src/devices/cpu/arm7/lpc210x.h
+++ b/src/devices/cpu/arm7/lpc210x.h
@@ -8,6 +8,7 @@
#include "arm7.h"
#include "arm7core.h"
+#include "machine/vic_pl192.h"
/***************************************************************************
DEVICE CONFIGURATION MACROS
@@ -37,10 +38,6 @@ public:
void write_timer(int timer, int offset, uint32_t data, uint32_t mem_mask);
uint32_t read_timer(int timer, int offset, uint32_t mem_mask);
- // VIC
- uint32_t vic_r(offs_t offset, uint32_t mem_mask = ~0);
- void vic_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
-
// PIN select block
uint32_t pin_r(offs_t offset, uint32_t mem_mask = ~0);
void pin_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
@@ -81,6 +78,8 @@ protected:
private:
address_space_config m_program_config;
+
+ required_device<vic_pl190_device> m_vic;
};
diff --git a/src/devices/cpu/arm7/upd800468.cpp b/src/devices/cpu/arm7/upd800468.cpp
new file mode 100644
index 00000000000..471e16098f4
--- /dev/null
+++ b/src/devices/cpu/arm7/upd800468.cpp
@@ -0,0 +1,252 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/***************************************************************************
+
+ NEC uPD800468
+ ARM7TDMI core with internal peripherals and external ROM/flash
+
+ Used in late 2000s/early 2010s Casio keyboards, like the CTK-2000 series.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "upd800468.h"
+
+DEFINE_DEVICE_TYPE(UPD800468_TIMER, upd800468_timer_device, "upd800468_timer", "NEC uPD800468 timer")
+
+upd800468_timer_device::upd800468_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, UPD800468_TIMER, tag, owner, clock)
+ , m_irq_cb(*this)
+{
+}
+
+u32 upd800468_timer_device::rate_r()
+{
+ return m_rate;
+}
+
+void upd800468_timer_device::rate_w(u32 data)
+{
+ m_rate = data;
+}
+
+u8 upd800468_timer_device::control_r()
+{
+ return m_control;
+}
+
+void upd800468_timer_device::control_w(u8 data)
+{
+ if (BIT(data, 1) != BIT(m_control, 1))
+ {
+ if (BIT(data, 1))
+ {
+ attotime period = clocks_to_attotime(m_rate);
+ m_timer->adjust(period, 0, period);
+ }
+ else
+ {
+ m_timer->adjust(attotime::never);
+ m_irq_cb(0);
+ }
+ }
+
+ if (!BIT(data, 0))
+ {
+ m_irq_cb(0);
+ }
+
+ m_control = data;
+}
+
+void upd800468_timer_device::device_start()
+{
+ m_timer = timer_alloc(0);
+
+ m_irq_cb.resolve_safe();
+
+ save_item(NAME(m_rate));
+ save_item(NAME(m_control));
+}
+
+void upd800468_timer_device::device_reset()
+{
+ m_rate = m_control = 0;
+}
+
+void upd800468_timer_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (BIT(m_control, 0))
+ m_irq_cb(1);
+}
+
+DEFINE_DEVICE_TYPE(UPD800468, upd800468_device, "upd800468", "NEC uPD800468")
+
+void upd800468_device::upd800468_map(address_map &map)
+{
+ map(0x00000000, 0x0000ffff).view(m_ram_view);
+ m_ram_view[0](0x00000000, 0x0000ffff).ram();
+
+ // RAM used for storing user samples (TODO: is this actually supposed to be part of the main 64kb RAM?)
+ map(0x1ffe8400, 0x1ffedfff).ram();
+
+ map(0x1fff00a0, 0x1fff00a1).r(m_kbd, FUNC(gt913_kbd_hle_device::read)).umask32(0x0000ffff);
+ map(0x1fff00a2, 0x1fff00a3).r(m_kbd, FUNC(gt913_kbd_hle_device::status_r)).umask32(0xffff0000);
+ map(0x1fff00a4, 0x1fff00a5).w(m_kbd, FUNC(gt913_kbd_hle_device::status_w)).umask32(0x0000ffff);
+
+ map(0x1fff00c0, 0x1fff00cf).r(FUNC(upd800468_device::adc_r));
+
+ map(0x1fff0141, 0x1fff0141).rw(FUNC(upd800468_device::port_ddr_r<0>), FUNC(upd800468_device::port_ddr_w<0>)).umask32(0x0000ff00);
+ map(0x1fff0142, 0x1fff0142).rw(FUNC(upd800468_device::port_r<0>), FUNC(upd800468_device::port_w<0>)).umask32(0x00ff0000);
+ map(0x1fff0145, 0x1fff0145).rw(FUNC(upd800468_device::port_ddr_r<1>), FUNC(upd800468_device::port_ddr_w<1>)).umask32(0x0000ff00);
+ map(0x1fff0146, 0x1fff0146).rw(FUNC(upd800468_device::port_r<1>), FUNC(upd800468_device::port_w<1>)).umask32(0x00ff0000);
+ map(0x1fff0149, 0x1fff0149).rw(FUNC(upd800468_device::port_ddr_r<2>), FUNC(upd800468_device::port_ddr_w<2>)).umask32(0x0000ff00);
+ map(0x1fff014a, 0x1fff014a).rw(FUNC(upd800468_device::port_r<2>), FUNC(upd800468_device::port_w<2>)).umask32(0x00ff0000);
+ map(0x1fff014d, 0x1fff014d).rw(FUNC(upd800468_device::port_ddr_r<3>), FUNC(upd800468_device::port_ddr_w<3>)).umask32(0x0000ff00);
+ map(0x1fff014e, 0x1fff014e).rw(FUNC(upd800468_device::port_r<3>), FUNC(upd800468_device::port_w<3>)).umask32(0x00ff0000);
+
+ map(0x2a003504, 0x2a003507).rw(m_timer[0], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w));
+ map(0x2a003508, 0x2a003508).rw(m_timer[0], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff);
+ map(0x2a003514, 0x2a003517).rw(m_timer[1], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w));
+ map(0x2a003518, 0x2a003518).rw(m_timer[1], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff);
+ map(0x2a003524, 0x2a003527).rw(m_timer[2], FUNC(upd800468_timer_device::rate_r), FUNC(upd800468_timer_device::rate_w));
+ map(0x2a003528, 0x2a003528).rw(m_timer[2], FUNC(upd800468_timer_device::control_r), FUNC(upd800468_timer_device::control_w)).umask32(0x000000ff);
+
+ map(0x2a003e00, 0x2a003e03).rw(FUNC(upd800468_device::ram_enable_r), FUNC(upd800468_device::ram_enable_w));
+
+ // keep whatever this is from spamming the error log for now
+ map(0x50000070, 0x50000077).noprw();
+
+ // TODO: USB controller at 0x50000400
+
+ map(0xfffff000, 0xffffffff).m(m_vic, FUNC(vic_upd800468_device::map));
+}
+
+upd800468_device::upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : arm7_cpu_device(mconfig, UPD800468, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_LITTLE)
+ , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0, address_map_constructor(FUNC(upd800468_device::upd800468_map), this))
+ , m_vic(*this, "vic")
+ , m_timer(*this, "timer%u", 0)
+ , m_kbd(*this, "kbd")
+ , m_adc_cb(*this), m_in_cb(*this), m_out_cb(*this)
+ , m_ram_view(*this, "ramview")
+{
+}
+
+device_memory_interface::space_config_vector upd800468_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_program_config)
+ };
+}
+
+void upd800468_device::device_add_mconfig(machine_config &config)
+{
+ UPD800468_VIC(config, m_vic, 0);
+ m_vic->out_irq_cb().set_inputline(*this, ARM7_IRQ_LINE);
+ m_vic->out_fiq_cb().set_inputline(*this, ARM7_FIRQ_LINE);
+
+ // this is probably not 100% accurate timing-wise
+ // for the ctk2100 it works ok for e.g. MIDI tempo and the auto power off interval
+ // it's unclear if there's supposed to be a register for setting a divider for each timer
+ UPD800468_TIMER(config, m_timer[0], clock() >> 3);
+ UPD800468_TIMER(config, m_timer[1], clock() >> 3);
+ UPD800468_TIMER(config, m_timer[2], clock() >> 3);
+ m_timer[0]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<21>));
+ m_timer[1]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<22>));
+ m_timer[2]->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<23>));
+
+ // key/button controller is compatible with the one from earlier keyboards
+ GT913_KBD_HLE(config, m_kbd, 0);
+ m_kbd->irq_cb().set(m_vic, FUNC(vic_upd800468_device::irq_w<31>));
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void upd800468_device::device_start()
+{
+ arm7_cpu_device::device_start();
+
+ m_adc_cb.resolve_all_safe(0x000);
+ m_in_cb.resolve_all_safe(0x00);
+ m_out_cb.resolve_all_safe();
+
+ save_item(NAME(m_port_data));
+ save_item(NAME(m_port_ddr));
+ save_item(NAME(m_ram_enable));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void upd800468_device::device_reset()
+{
+ arm7_cpu_device::device_reset();
+
+ for (offs_t i = 0; i < 4; i++)
+ {
+ m_port_data[i] = 0;
+ m_port_ddr[i] = 0xff;
+ port_update(i);
+ }
+
+ m_ram_enable = 0;
+ m_ram_view.disable();
+}
+
+u16 upd800468_device::adc_r(offs_t num)
+{
+ // TODO: verify strange-seeming ADC behavior
+ // ctk2100 reads a 10-bit value, then inverts the highest bit, and seemingly treats the result as unsigned
+ return m_adc_cb[num]() ^ 0x200;
+}
+
+u8 upd800468_device::port_ddr_r(offs_t num)
+{
+ return m_port_ddr[num];
+}
+
+void upd800468_device::port_ddr_w(offs_t num, u8 data)
+{
+ m_port_ddr[num] = data;
+// logerror("port %u ddr_w: %02x\n", num, data);
+ port_update(num);
+}
+
+u8 upd800468_device::port_r(offs_t num)
+{
+ // port input seemingly does not use the ddr value
+ // (ctk2100 port 2 ddr lower 4 bits are always high, but the corresponding data bits
+ // are apparently expected to be bidirectional, otherwise reading LCD status fails)
+ return m_in_cb[num]();
+}
+
+void upd800468_device::port_w(offs_t num, u8 data)
+{
+ m_port_data[num] = data;
+ port_update(num);
+}
+
+void upd800468_device::port_update(offs_t num)
+{
+// logerror("port %u out: %02x\n", num, m_port_data[num] & m_port_ddr[num]);
+ m_out_cb[num](m_port_data[num] & m_port_ddr[num]);
+}
+
+u32 upd800468_device::ram_enable_r()
+{
+ return m_ram_enable;
+}
+
+void upd800468_device::ram_enable_w(u32 data)
+{
+ m_ram_enable = data;
+
+ if (BIT(m_ram_enable, 0))
+ m_ram_view.select(0);
+ else
+ m_ram_view.disable();
+}
diff --git a/src/devices/cpu/arm7/upd800468.h b/src/devices/cpu/arm7/upd800468.h
new file mode 100644
index 00000000000..afd47d9bab9
--- /dev/null
+++ b/src/devices/cpu/arm7/upd800468.h
@@ -0,0 +1,103 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+
+#ifndef MAME_CPU_ARM7_UPD800468_H
+#define MAME_CPU_ARM7_UPD800468_H
+
+#pragma once
+
+#include "arm7.h"
+#include "arm7core.h"
+#include "machine/gt913_kbd.h"
+#include "machine/vic_pl192.h"
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+class upd800468_timer_device : public device_t
+{
+public:
+ upd800468_timer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ auto irq_cb() { return m_irq_cb.bind(); }
+
+ u32 rate_r();
+ void rate_w(u32);
+
+ u8 control_r();
+ void control_w(u8);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ devcb_write_line m_irq_cb;
+
+ emu_timer *m_timer;
+ u32 m_rate;
+ u8 m_control;
+};
+
+class upd800468_device : public arm7_cpu_device
+{
+public:
+ upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t);
+
+ void upd800468_map(address_map &map);
+
+ template<offs_t i> auto adc_cb() { return m_adc_cb[i].bind(); }
+
+ template<offs_t i> auto port_in_cb() { return m_in_cb[i].bind(); }
+ template<offs_t i> auto port_out_cb() { return m_out_cb[i].bind(); }
+
+ template<offs_t i> u8 port_ddr_r() { return port_ddr_r(i); }
+ template<offs_t i> void port_ddr_w(u8 data) { port_ddr_w(i, data); }
+
+ template<offs_t i> u8 port_r() { return port_r(i); }
+ template<offs_t i> void port_w(u8 data) { port_w(i, data); }
+
+ u32 ram_enable_r();
+ void ram_enable_w(u32 data);
+
+protected:
+ u16 adc_r(offs_t);
+
+ u8 port_ddr_r(offs_t);
+ void port_ddr_w(offs_t, u8);
+
+ u8 port_r(offs_t);
+ void port_w(offs_t, u8);
+ void port_update(offs_t);
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ address_space_config m_program_config;
+
+ required_device<vic_upd800468_device> m_vic;
+ required_device_array<upd800468_timer_device, 3> m_timer;
+ required_device<gt913_kbd_hle_device> m_kbd;
+
+ devcb_read16::array<8> m_adc_cb;
+ devcb_read8::array<4> m_in_cb;
+ devcb_write8::array<4> m_out_cb;
+ u8 m_port_ddr[4], m_port_data[4];
+
+ memory_view m_ram_view;
+ u32 m_ram_enable;
+};
+
+// device type
+DECLARE_DEVICE_TYPE(UPD800468_TIMER, upd800468_timer_device)
+DECLARE_DEVICE_TYPE(UPD800468, upd800468_device)
+
+#endif // MAME_CPU_ARM7_UPD800468_H
diff --git a/src/devices/cpu/h8/gt913.cpp b/src/devices/cpu/h8/gt913.cpp
index 5f5e8ff34cb..bc8e11f5dc5 100644
--- a/src/devices/cpu/h8/gt913.cpp
+++ b/src/devices/cpu/h8/gt913.cpp
@@ -89,7 +89,8 @@ void gt913_device::device_add_mconfig(machine_config &config)
GT913_INTC(config, "intc");
GT913_SOUND_HLE(config, m_sound, 0);
- GT913_KBD_HLE(config, m_kbd, "intc", 5);
+ GT913_KBD_HLE(config, m_kbd, 0);
+ m_kbd->irq_cb().set([this](int val) { if (val) m_intc->internal_interrupt(5); });
GT913_IO_HLE(config, m_io_hle, "intc", 6, 7);
H8_SCI(config, m_sci, "intc", 8, 9, 10, 0);
diff --git a/src/devices/machine/gt913_kbd.cpp b/src/devices/machine/gt913_kbd.cpp
index b22197153b8..ba7a2ff521c 100644
--- a/src/devices/machine/gt913_kbd.cpp
+++ b/src/devices/machine/gt913_kbd.cpp
@@ -28,15 +28,15 @@ DEFINE_DEVICE_TYPE(GT913_KBD_HLE, gt913_kbd_hle_device, "gt913_kbd_hle", "Casio
gt913_kbd_hle_device::gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, GT913_KBD_HLE, tag, owner, clock),
- device_matrix_keyboard_interface(mconfig, *this, "KO0", "KO1", "KO2", "KO3", "KO4", "KO5", "KO6", "KO7", "KO8", "KO9", "KO10", "KO11", "KO12"),
- m_intc(nullptr), m_intc_tag(nullptr), m_irq(0),
- m_velocity(*this, "VELOCITY")
+ device_matrix_keyboard_interface(mconfig, *this, "FI0", "FI1", "FI2", "FI3", "FI4", "FI5", "FI6", "FI7", "FI8", "FI9", "FI10", "KI0", "KI1", "KI2"),
+ m_velocity(*this, "VELOCITY"),
+ m_irq_cb(*this)
{
}
void gt913_kbd_hle_device::device_start()
{
- m_intc = siblingdevice<h8_intc_device>(m_intc_tag);
+ m_irq_cb.resolve_safe();
save_item(NAME(m_status));
save_item(NAME(m_fifo));
@@ -51,7 +51,7 @@ void gt913_kbd_hle_device::device_reset()
m_fifo_read = m_fifo_write = 0;
reset_key_state();
- start_processing(attotime::from_hz(1200));
+ start_processing(attotime::from_hz(9600));
}
void gt913_kbd_hle_device::key_add(uint8_t row, uint8_t column, int state)
@@ -75,7 +75,9 @@ void gt913_kbd_hle_device::update_status()
m_status |= 0x8000;
if (BIT(m_status, 15) && BIT(m_status, 14))
- m_intc->internal_interrupt(m_irq);
+ m_irq_cb(1);
+ else
+ m_irq_cb(0);
}
uint16_t gt913_kbd_hle_device::read()
diff --git a/src/devices/machine/gt913_kbd.h b/src/devices/machine/gt913_kbd.h
index 3823442ff86..3bf2ced327e 100644
--- a/src/devices/machine/gt913_kbd.h
+++ b/src/devices/machine/gt913_kbd.h
@@ -9,7 +9,6 @@
#pragma once
-#include "cpu/h8/h8_intc.h"
#include "keyboard.h"
//**************************************************************************
@@ -18,17 +17,13 @@
// ======================> gt913_kbd_hle_device
-class gt913_kbd_hle_device : public device_t, protected device_matrix_keyboard_interface<13>
+class gt913_kbd_hle_device : public device_t, protected device_matrix_keyboard_interface<14>
{
public:
// construction/destruction
gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- gt913_kbd_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, const char *intc, int irq)
- : gt913_kbd_hle_device(mconfig, tag, owner, 0)
- {
- m_intc_tag = intc;
- m_irq = irq;
- }
+
+ auto irq_cb() { return m_irq_cb.bind(); }
uint16_t read();
void status_w(uint16_t data);
@@ -46,11 +41,10 @@ protected:
void key_add(uint8_t row, uint8_t column, int state);
void update_status();
private:
- h8_intc_device *m_intc;
- const char *m_intc_tag;
- int m_irq;
optional_ioport m_velocity;
+ devcb_write_line m_irq_cb;
+
uint16_t m_status;
uint8_t m_fifo[16];
uint8_t m_fifo_read, m_fifo_write;
diff --git a/src/devices/machine/vic_pl192.cpp b/src/devices/machine/vic_pl192.cpp
index 5c37d03abee..bd7c4de4e2c 100644
--- a/src/devices/machine/vic_pl192.cpp
+++ b/src/devices/machine/vic_pl192.cpp
@@ -1,10 +1,9 @@
// license:BSD-3-Clause
-// copyright-holders:Melissa Goad
+// copyright-holders:Devin Acker, Melissa Goad
-// ARM PrimeCell PL192 VIC emulation
+// ARM PrimeCell PL910/PL192 VIC emulation
#include "emu.h"
-#include "machine/bankdev.h"
#include "machine/vic_pl192.h"
#define LOG_GENERAL (1U << 0)
@@ -12,19 +11,22 @@
#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
-void vic_pl192_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+DEFINE_DEVICE_TYPE(PL190_VIC, vic_pl190_device, "vic_pl190", "ARM PL190 VIC")
+DEFINE_DEVICE_TYPE(UPD800468_VIC, vic_upd800468_device, "vic_upd800468", "NEC uPD800468 VIC")
+DEFINE_DEVICE_TYPE(PL192_VIC, vic_pl192_device, "vic_pl192", "ARM PL192 VIC")
+
+void vic_pl190_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
- if(u32 intrs = (raw_intr | soft_intr) & intr_en)
- {
- if(intrs & intr_select) m_out_fiq_func(1);
- else m_out_fiq_func(0);
+ u32 intrs = (raw_intr | soft_intr) & intr_en;
- if(intrs & ~intr_select) m_out_irq_func(1);
- else m_out_irq_func(0);
- }
+ if (intrs & intr_select) m_out_fiq_func(1);
+ else m_out_fiq_func(0);
+
+ if (intrs & ~intr_select & priority_mask) m_out_irq_func(1);
+ else m_out_irq_func(0);
}
-void vic_pl192_device::set_irq_line(int irq, int state)
+void vic_pl190_device::set_irq_line(int irq, int state)
{
u32 mask = (1 << irq);
@@ -40,22 +42,173 @@ void vic_pl192_device::set_irq_line(int irq, int state)
timer_set(attotime::zero, TIMER_CHECK_IRQ);
}
-void vic_pl192_device::map(address_map &map)
+u32 vic_pl190_device::irq_status_r()
+{
+ return raw_intr & ~intr_select;
+}
+
+u32 vic_pl190_device::fiq_status_r()
+{
+ return raw_intr & intr_select;
+}
+
+u32 vic_pl190_device::raw_intr_r()
+{
+ return raw_intr;
+}
+
+u32 vic_pl190_device::int_select_r()
+{
+ return intr_select;
+}
+
+void vic_pl190_device::int_select_w(u32 data)
+{
+ intr_select = data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+u32 vic_pl190_device::int_enable_r()
+{
+ return intr_en;
+}
+
+void vic_pl190_device::int_enable_w(u32 data)
+{
+ intr_en |= data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+void vic_pl190_device::int_en_clear_w(u32 data)
+{
+ intr_en &= ~data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+u32 vic_pl190_device::soft_int_r()
+{
+ return soft_intr;
+}
+
+void vic_pl190_device::soft_int_w(u32 data)
+{
+ soft_intr |= data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+void vic_pl190_device::soft_int_clear_w(u32 data)
+{
+ soft_intr &= ~data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+u8 vic_pl190_device::protection_r()
+{
+ return protection;
+}
+
+void vic_pl190_device::protection_w(u8 data)
{
- map(0x000, 0x003).lr32([this](offs_t offset){ return raw_intr & ~intr_select; }, "irq_status"); //IRQ_STATUS
- map(0x004, 0x007).lr32([this](offs_t offset){ return raw_intr & intr_select; }, "fiq_status"); //FIQ_STATUS
- map(0x008, 0x00b).lr32([this](offs_t offset){ return raw_intr; }, "raw_intr");
- map(0x00c, 0x00f).lrw32(NAME([this](offs_t offset){ return intr_select; }), NAME([this](offs_t offset, u32 data){ intr_select = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
- map(0x010, 0x013).lrw32(NAME([this](offs_t offset){ return intr_en; }), NAME([this](offs_t offset, u32 data){ intr_en = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
- map(0x014, 0x017).lw32([this](u32 data){ intr_en &= ~data; }, "intr_en_clear");
- map(0x018, 0x01b).lrw32(NAME([this](offs_t offset){ return soft_intr; }), NAME([this](offs_t offset, u32 data){ soft_intr = data; timer_set(attotime::zero, TIMER_CHECK_IRQ); }));
- map(0x01c, 0x01f).lw32([this](u32 data){ soft_intr &= ~data; }, "soft_intr_clear");
- map(0x020, 0x020).lrw8(NAME([this](offs_t offset){ return protection; }), NAME([this](offs_t offset, u8 data){ protection = data & 1; })).umask32(0x000000ff);
- map(0x024, 0x025).lrw8(NAME([this](offs_t offset){ return sw_priority_mask; }), NAME([this](offs_t offset, u16 data){ sw_priority_mask = data; })).umask32(0x0000ffff);
- map(0x028, 0x028).lrw8(NAME([this](offs_t offset){ return daisy_priority; }), NAME([this](offs_t offset, u8 data){ daisy_priority = data & 0xf; })).umask32(0x000000ff);
- map(0x100, 0x17f).lrw32(NAME([this](offs_t offset){ return vectaddr[(offset & 0x7c) >> 2]; }), NAME([this](offs_t offset, u32 data){ vectaddr[(offset & 0x7c) >> 2] = data; }));
- map(0x200, 0x27f).lrw8(NAME([this](offs_t offset){ return vectprio[(offset & 0x7c) >> 2]; }), NAME([this](offs_t offset, u32 data){ vectprio[(offset & 0x7c) >> 2] = data & 0xf; }));
- map(0xf00, 0xf03).lrw32(NAME([this](offs_t offset){ return vicaddress; }), NAME([this](offs_t offset, u32 data){ vectaddr[(offset & 0x7c) >> 2] = data; }));
+ protection = BIT(data, 0);
+}
+
+u32 vic_pl190_device::cur_vect_addr_r()
+{
+ if (!machine().side_effects_disabled())
+ update_vector();
+
+ return vicaddress;
+}
+
+void vic_pl190_device::cur_vect_addr_w(u32 data)
+{
+ priority_mask = ~0;
+ priority = ~0;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+u32 vic_pl190_device::def_vect_addr_r()
+{
+ return defaddress;
+}
+
+void vic_pl190_device::def_vect_addr_w(u32 data)
+{
+ defaddress = data;
+}
+
+u32 vic_pl190_device::vect_addr_r(offs_t offset)
+{
+ return vectaddr[offset];
+}
+
+void vic_pl190_device::vect_addr_w(offs_t offset, u32 data)
+{
+ vectaddr[offset] = data;
+}
+
+u32 vic_pl190_device::vect_ctl_r(offs_t offset)
+{
+ return vectctl[offset];
+}
+
+void vic_pl190_device::vect_ctl_w(offs_t offset, u32 data)
+{
+ vectctl[offset] = data;
+}
+
+void vic_pl190_device::update_vector()
+{
+ u32 intrs = (raw_intr | soft_intr) & intr_en & ~intr_select;
+ u32 newmask = 0;
+
+ for (u8 i = 0; i < std::min(priority, num_vectors); i++)
+ {
+ u8 irq = vectctl[i] & 0x1f;
+
+ if (!BIT(vectctl[i], 5))
+ {
+ // vector is disabled
+ continue;
+ }
+ else if (BIT(intrs, irq))
+ {
+ // this interrupt is enabled and pending
+ // take it and update priority_mask to only allow higher priority interrupts
+ priority_mask = newmask;
+ priority = i;
+ vicaddress = vectaddr[i];
+ return;
+ }
+ else
+ {
+ // interrupt isn't pending, but it's higher priority
+ // allow it to be taken later
+ newmask |= (1 << irq);
+ }
+ }
+
+ // no vectored interrupt taken, use the default
+ priority_mask = ~0;
+ priority = ~0;
+ vicaddress = defaddress;
+}
+
+void vic_pl190_device::map(address_map &map)
+{
+ map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r));
+ map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r));
+ map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r));
+ map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w));
+ map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w));
+ map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w));
+ map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w));
+ map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w));
+ map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff);
+ map(0x030, 0x033).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w));
+ map(0x034, 0x037).rw(FUNC(vic_pl190_device::def_vect_addr_r), FUNC(vic_pl190_device::def_vect_addr_w));
+ map(0x100, 0x13f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w));
+ map(0x200, 0x23f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w));
map(0xfe0, 0xfe0).lr8([this](offs_t offset){ return periph_id[0]; }, "periph_id0").umask32(0x000000ff);
map(0xfe4, 0xfe4).lr8([this](offs_t offset){ return periph_id[1]; }, "periph_id1").umask32(0x000000ff);
map(0xfe8, 0xfe8).lr8([this](offs_t offset){ return periph_id[2]; }, "periph_id2").umask32(0x000000ff);
@@ -66,65 +219,191 @@ void vic_pl192_device::map(address_map &map)
map(0xffc, 0xffc).lr8([this](offs_t offset){ return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff);
}
-device_memory_interface::space_config_vector vic_pl192_device::memory_space_config() const
+device_memory_interface::space_config_vector vic_pl190_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(0, &m_mmio_config)
};
}
-void vic_pl192_device::device_resolve_objects()
+void vic_pl190_device::device_resolve_objects()
{
// resolve callbacks
m_out_irq_func.resolve_safe();
m_out_fiq_func.resolve_safe();
}
-void vic_pl192_device::device_start()
+void vic_pl190_device::device_start()
{
save_item(NAME(raw_intr));
save_item(NAME(intr_select));
save_item(NAME(intr_en));
save_item(NAME(soft_intr));
save_item(NAME(vectaddr));
+ save_item(NAME(defaddress));
save_item(NAME(vicaddress));
+ save_item(NAME(priority_mask));
+ save_item(NAME(priority));
save_item(NAME(protection));
- save_item(NAME(sw_priority_mask));
- save_item(NAME(daisy_priority));
- save_item(NAME(vectprio));
}
-void vic_pl192_device::device_reset()
+void vic_pl190_device::device_reset()
{
- raw_intr = intr_select = intr_en = soft_intr = vicaddress = protection = 0;
- sw_priority_mask = 0xffff;
- daisy_priority = 0xf;
+ raw_intr = intr_select = intr_en = soft_intr = 0;
+ defaddress = vicaddress = protection = 0;
- for(int i = 0; i < 32; i++)
- {
- vectaddr[i] = 0;
- }
+ priority_mask = ~0;
+ priority = ~0;
for(int i = 0; i < 32; i++)
{
- vectprio[i] = 0xf;
+ vectaddr[i] = 0;
+ vectctl[i] = 0;
}
}
-DEFINE_DEVICE_TYPE(PL192_VIC, vic_pl192_device, "vic_pl192", "ARM PL192 VIC")
-
-vic_pl192_device::vic_pl192_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+vic_pl190_device::vic_pl190_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_memory_interface(mconfig, *this)
+ , num_vectors(16)
+ , periph_id{0x92, 0x11, 0x04, 0x00}
+ , pcell_id{0x0d, 0xf0, 0x05, 0xb1}
, m_mmio_config("mmio", ENDIANNESS_LITTLE, 32, 32, 0)
, m_out_irq_func(*this)
, m_out_fiq_func(*this)
- , periph_id{0x92, 0x11, 0x04, 0x00}
- , pcell_id{0x0d, 0xf0, 0x05, 0xb1}
{
}
+vic_pl190_device::vic_pl190_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vic_pl190_device(mconfig, PL190_VIC, tag, owner, clock)
+{
+}
+
+
+
+
+void vic_upd800468_device::int_clear_w(u32 data)
+{
+ raw_intr &= ~data;
+ timer_set(attotime::zero, TIMER_CHECK_IRQ);
+}
+
+void vic_upd800468_device::map(address_map &map)
+{
+ vic_pl190_device::map(map);
+
+ map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w));
+ map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w));
+ map(0x2c8, 0x2cb).w(FUNC(vic_upd800468_device::int_clear_w));
+}
+
+vic_upd800468_device::vic_upd800468_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vic_pl190_device(mconfig, UPD800468_VIC, tag, owner, clock)
+{
+ num_vectors = 32;
+}
+
+
+
+
+u16 vic_pl192_device::sw_priority_r()
+{
+ return sw_priority_mask;
+}
+
+void vic_pl192_device::sw_priority_w(u16 data)
+{
+ sw_priority_mask = data;
+}
+
+u8 vic_pl192_device::daisy_priority_r()
+{
+ return daisy_priority;
+}
+
+void vic_pl192_device::daisy_priority_w(u8 data)
+{
+ daisy_priority = data & 0xf;
+}
+
+void vic_pl192_device::update_vector()
+{
+ u32 intrs = (raw_intr | soft_intr) & intr_en & ~intr_select;
+ u32 newmask = 0;
+
+ // see if there's a higher priority active interrupt to take
+ for (u8 i = 0; i < num_vectors; i++)
+ {
+ u8 new_prio = vectctl[i] & 0xf;
+ if (BIT(sw_priority_mask, new_prio) && BIT(intrs, i) && new_prio < priority)
+ {
+ // this interrupt is enabled and pending, take it
+ priority = new_prio;
+ vicaddress = vectaddr[i];
+ }
+ }
+
+ // update priority_mask to only allow higher priority interrupts
+ for (u8 i = 0; i < num_vectors; i++)
+ {
+ u8 new_prio = vectctl[i] & 0xf;
+ if (BIT(sw_priority_mask, new_prio) && new_prio < priority)
+ {
+ newmask |= (1 << i);
+ }
+ }
+ priority_mask = newmask;
+}
+
+void vic_pl192_device::map(address_map &map)
+{
+ map(0x000, 0x003).r(FUNC(vic_pl190_device::irq_status_r));
+ map(0x004, 0x007).r(FUNC(vic_pl190_device::fiq_status_r));
+ map(0x008, 0x00b).r(FUNC(vic_pl190_device::raw_intr_r));
+ map(0x00c, 0x00f).rw(FUNC(vic_pl190_device::int_select_r), FUNC(vic_pl190_device::int_select_w));
+ map(0x010, 0x013).rw(FUNC(vic_pl190_device::int_enable_r), FUNC(vic_pl190_device::int_enable_w));
+ map(0x014, 0x017).w(FUNC(vic_pl190_device::int_en_clear_w));
+ map(0x018, 0x01b).rw(FUNC(vic_pl190_device::soft_int_r), FUNC(vic_pl190_device::soft_int_w));
+ map(0x01c, 0x01f).w(FUNC(vic_pl190_device::soft_int_clear_w));
+ map(0x020, 0x020).rw(FUNC(vic_pl190_device::protection_r), FUNC(vic_pl190_device::protection_w)).umask32(0x000000ff);
+ map(0x024, 0x025).rw(FUNC(vic_pl192_device::sw_priority_r), FUNC(vic_pl192_device::sw_priority_w)).umask32(0x0000ffff);
+ map(0x028, 0x028).rw(FUNC(vic_pl192_device::daisy_priority_r), FUNC(vic_pl192_device::daisy_priority_w)).umask32(0x000000ff);
+ map(0x100, 0x17f).rw(FUNC(vic_pl190_device::vect_addr_r), FUNC(vic_pl190_device::vect_addr_w));
+ map(0x200, 0x27f).rw(FUNC(vic_pl190_device::vect_ctl_r), FUNC(vic_pl190_device::vect_ctl_w));
+ map(0xf00, 0xf03).rw(FUNC(vic_pl190_device::cur_vect_addr_r), FUNC(vic_pl190_device::cur_vect_addr_w));
+ map(0xfe0, 0xfe0).lr8([this](offs_t offset) { return periph_id[0]; }, "periph_id0").umask32(0x000000ff);
+ map(0xfe4, 0xfe4).lr8([this](offs_t offset) { return periph_id[1]; }, "periph_id1").umask32(0x000000ff);
+ map(0xfe8, 0xfe8).lr8([this](offs_t offset) { return periph_id[2]; }, "periph_id2").umask32(0x000000ff);
+ map(0xfec, 0xfec).lr8([this](offs_t offset) { return periph_id[3]; }, "periph_id3").umask32(0x000000ff);
+ map(0xff0, 0xff0).lr8([this](offs_t offset) { return pcell_id[0]; }, "pcell_id0").umask32(0x000000ff);
+ map(0xff4, 0xff4).lr8([this](offs_t offset) { return pcell_id[1]; }, "pcell_id1").umask32(0x000000ff);
+ map(0xff8, 0xff8).lr8([this](offs_t offset) { return pcell_id[2]; }, "pcell_id2").umask32(0x000000ff);
+ map(0xffc, 0xffc).lr8([this](offs_t offset) { return pcell_id[3]; }, "pcell_id3").umask32(0x000000ff);
+}
+
+void vic_pl192_device::device_start()
+{
+ vic_pl190_device::device_start();
+
+ save_item(NAME(sw_priority_mask));
+ save_item(NAME(daisy_priority));
+}
+
+void vic_pl192_device::device_reset()
+{
+ vic_pl190_device::device_start();
+
+ sw_priority_mask = 0xffff;
+ daisy_priority = 0xf;
+
+ for (int i = 0; i < 32; i++)
+ {
+ vectctl[i] = 0xf;
+ }
+}
+
vic_pl192_device::vic_pl192_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vic_pl192_device(mconfig, PL192_VIC, tag, owner, clock)
+ : vic_pl190_device(mconfig, PL192_VIC, tag, owner, clock)
{
+ num_vectors = 32;
}
diff --git a/src/devices/machine/vic_pl192.h b/src/devices/machine/vic_pl192.h
index 9936b369fb6..cb07a8854d5 100644
--- a/src/devices/machine/vic_pl192.h
+++ b/src/devices/machine/vic_pl192.h
@@ -1,26 +1,70 @@
// license:BSD-3-Clause
-// copyright-holders:Melissa Goad
+// copyright-holders:Devin Acker, Melissa Goad
-// ARM PrimeCell PL192 VIC emulation
+// ARM PrimeCell PL910/PL192 VIC emulation
#ifndef MAME_MACHINE_VIC_PL192_H
#define MAME_MACHINE_VIC_PL192_H
-class vic_pl192_device : public device_t, public device_memory_interface
+class vic_pl190_device : public device_t, public device_memory_interface
{
public:
- vic_pl192_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
+ vic_pl190_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
auto out_irq_cb() { return m_out_irq_func.bind(); }
auto out_fiq_cb() { return m_out_fiq_func.bind(); }
template<unsigned IRQ>
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { set_irq_line(IRQ, state); }
+ DECLARE_WRITE_LINE_MEMBER(irq_w) { set_irq_line(IRQ, state); }
void map(address_map &map);
+ u32 irq_status_r();
+ u32 fiq_status_r();
+ u32 raw_intr_r();
+
+ u32 int_select_r();
+ void int_select_w(u32 data);
+
+ u32 int_enable_r();
+ void int_enable_w(u32 data);
+ void int_en_clear_w(u32 data);
+
+ u32 soft_int_r();
+ void soft_int_w(u32 data);
+ void soft_int_clear_w(u32 data);
+
+ u8 protection_r();
+ void protection_w(u8 data);
+
+ u32 cur_vect_addr_r();
+ void cur_vect_addr_w(u32 data);
+
+ u32 def_vect_addr_r();
+ void def_vect_addr_w(u32 data);
+
+ u32 vect_addr_r(offs_t offset);
+ void vect_addr_w(offs_t offset, u32 data);
+
+ u32 vect_ctl_r(offs_t offset);
+ void vect_ctl_w(offs_t offset, u32 data);
+
protected:
- vic_pl192_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ static constexpr device_timer_id TIMER_CHECK_IRQ = 0;
+
+ vic_pl190_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void update_vector();
+
+ u8 num_vectors; // number of available vectored interrupts
+
+ u32 raw_intr, intr_select, intr_en, soft_intr;
+ u32 vectaddr[32], vectctl[32], defaddress, vicaddress;
+ int protection;
+
+ u32 priority_mask; // mask for interrupts which can take priority over the current one
+ u8 priority; // priority level of the current interrupt, if any
+ u8 periph_id[4], pcell_id[4];
// device-level overrides
virtual void device_resolve_objects() override;
@@ -31,21 +75,52 @@ protected:
virtual space_config_vector memory_space_config() const override;
private:
- static constexpr device_timer_id TIMER_CHECK_IRQ = 0;
-
void set_irq_line(int irq, int state);
address_space_config m_mmio_config;
devcb_write_line m_out_irq_func;
devcb_write_line m_out_fiq_func;
- u32 raw_intr, intr_select, intr_en, soft_intr, vectaddr[32], vicaddress;
- int protection;
+};
+
+class vic_upd800468_device : public vic_pl190_device
+{
+public:
+ vic_upd800468_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
+
+ void map(address_map &map);
+
+ void int_clear_w(u32 data);
+};
+
+class vic_pl192_device : public vic_pl190_device
+{
+public:
+ vic_pl192_device(const machine_config &mconfig, const char* tag, device_t *owner, uint32_t clock = 0);
+
+ void map(address_map &map);
+
+ u16 sw_priority_r();
+ void sw_priority_w(u16 data);
+
+ u8 daisy_priority_r();
+ void daisy_priority_w(u8 data);
+
+protected:
+
+ virtual void update_vector() override;
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
u16 sw_priority_mask;
- u8 daisy_priority, vectprio[32];
- u8 periph_id[4], pcell_id[4];
+ u8 daisy_priority;
};
+DECLARE_DEVICE_TYPE(PL190_VIC, vic_pl190_device)
+DECLARE_DEVICE_TYPE(UPD800468_VIC, vic_upd800468_device)
DECLARE_DEVICE_TYPE(PL192_VIC, vic_pl192_device)
#endif // MAME_MACHINE_VIC_PL192_H
diff --git a/src/mame/drivers/ctk2000.cpp b/src/mame/drivers/ctk2000.cpp
new file mode 100644
index 00000000000..64aba38114c
--- /dev/null
+++ b/src/mame/drivers/ctk2000.cpp
@@ -0,0 +1,300 @@
+// license:BSD-3-Clause
+// copyright-holders:Devin Acker
+/*
+ Casio CTK-2000 keyboard (and related models)
+
+ - CTK-2000 (2008)
+ Basic 61-key model
+ - CTK-3000
+ Adds velocity-sensitive keys and pitch wheel
+ - CTK-2100 (2009)
+ More flexible sampling feature, lesson buttons double as voice/drum pads
+ (based on CTK-2000, not 3000)
+
+ Main board (M800-MDA1):
+
+ IC1: CPU (NEC uPD800468)
+ Custom chip (ARM-based), built in peripheral controllers & sound generator
+
+ LSI2: 16Mbit ROM (OKI MR27T1602L)
+
+ Console PCB (M800-CNA):
+
+ IC401: LCD controller (Sitronix ST7066U-0A, HD44780 compatible)
+
+ CTK-2000 service manual with schematics, pinouts, etc.:
+ https://www.manualslib.com/manual/933451/Casio-Ctk-2000.html
+
+ */
+
+#include "emu.h"
+
+#include "cpu/arm7/upd800468.h"
+#include "video/hd44780.h"
+#include "emupal.h"
+#include "screen.h"
+
+namespace {
+
+class ctk2000_state : public driver_device
+{
+public:
+ ctk2000_state(machine_config const &mconfig, device_type type, char const *tag)
+ : driver_device(mconfig, type, tag)
+ , m_maincpu(*this, "maincpu")
+ , m_lcdc(*this, "lcdc")
+ {
+ }
+
+ void ctk2000(machine_config &config);
+
+ DECLARE_CUSTOM_INPUT_MEMBER(lcd_r) { return m_lcdc->db_r() >> 4; }
+ DECLARE_WRITE_LINE_MEMBER(lcd_w) { m_lcdc->db_w(state << 4); }
+
+ DECLARE_WRITE_LINE_MEMBER(apo_w);
+
+private:
+ void ctk2000_map(address_map &map);
+
+ virtual void driver_start() override;
+ virtual void driver_reset() override;
+
+ HD44780_PIXEL_UPDATE(lcd_update);
+ void palette_init(palette_device &palette);
+
+ required_device<upd800468_device> m_maincpu;
+ required_device<hd44780_device> m_lcdc;
+};
+
+WRITE_LINE_MEMBER(ctk2000_state::apo_w)
+{
+ logerror("apo_w: %x\n", state);
+ /* TODO: when 0, this should turn off the LCD, speakers, etc. */
+}
+
+HD44780_PIXEL_UPDATE(ctk2000_state::lcd_update)
+{
+ if (x < 6 && y < 8 && line < 2 && pos < 8)
+ bitmap.pix(line * 8 + y, pos * 6 + x) = state;
+}
+
+void ctk2000_state::palette_init(palette_device &palette)
+{
+ palette.set_pen_color(0, rgb_t(255, 255, 255));
+ palette.set_pen_color(1, rgb_t(0, 0, 0));
+}
+
+void ctk2000_state::ctk2000_map(address_map &map)
+{
+ // ROM is based at 0x18000000, but needs to be mirrored to the beginning of memory in order to boot
+ map(0x00000000, 0x001fffff).rom().mirror(0x18e00000);
+}
+
+void ctk2000_state::driver_start()
+{
+}
+
+void ctk2000_state::driver_reset()
+{
+}
+
+void ctk2000_state::ctk2000(machine_config &config)
+{
+ // CPU
+ UPD800468(config, m_maincpu, 48'000'000);
+ m_maincpu->set_addrmap(AS_PROGRAM, &ctk2000_state::ctk2000_map);
+ m_maincpu->port_in_cb<2>().set_ioport("P2_R");
+ m_maincpu->port_out_cb<2>().set_ioport("P2_W");
+ m_maincpu->port_out_cb<3>().set_ioport("P3");
+ // ADCs 0, 5, 6, 7 are connected to the mic input
+ // ADC 4 is connected to the pitch wheel (for ctk3000)
+ m_maincpu->adc_cb<1>().set_ioport("AIN1");
+ m_maincpu->adc_cb<2>().set_ioport("AIN2");
+ m_maincpu->adc_cb<3>().set_ioport("AIN3");
+
+ // LCD
+ HD44780(config, m_lcdc, 0);
+ m_lcdc->set_lcd_size(2, 8);
+ m_lcdc->set_pixel_update_cb(FUNC(ctk2000_state::lcd_update));
+
+ // screen (for testing only)
+ // TODO: the actual LCD with custom segments
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
+ screen.set_refresh_hz(60);
+ screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
+ screen.set_screen_update("lcdc", FUNC(hd44780_device::screen_update));
+ screen.set_size(6 * 8, 8 * 2);
+ screen.set_visarea_full();
+ screen.set_palette("palette");
+
+ PALETTE(config, "palette", FUNC(ctk2000_state::palette_init), 2);
+}
+
+INPUT_PORTS_START(ctk2100)
+ PORT_START("maincpu:kbd:FI0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2#")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2#")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E2")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2#")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2")
+
+ PORT_START("maincpu:kbd:FI1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2#")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2#")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B2")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3#")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3#")
+
+ PORT_START("maincpu:kbd:FI2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3#")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3#")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3#")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3")
+
+ PORT_START("maincpu:kbd:FI3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4#")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4#")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E4")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4#")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4")
+
+ PORT_START("maincpu:kbd:FI4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4#")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4#")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B4")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5#")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5#")
+
+ PORT_START("maincpu:kbd:FI5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5#")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5#")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5#")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5")
+
+ PORT_START("maincpu:kbd:FI6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6#")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6#")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E6")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6#")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6")
+
+ PORT_START("maincpu:kbd:FI7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6#")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6#")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B6")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7")
+ PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("maincpu:kbd:FI8")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("maincpu:kbd:FI9")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD)
+
+ PORT_START("maincpu:kbd:FI10")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad +") PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 5 / Auto")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Synchro / Ending / Pause")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Accomp On/Off / Chord / Part Select")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Sampling")
+
+ PORT_START("maincpu:kbd:KI0")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("maincpu:kbd:KI1")
+ // "song bank" and "tone" seem to be swapped in the schematic
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Song Bank")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tone")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Up")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Set Select / Music Challenge")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 4 / Next")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Play / Stop")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Metronome")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Intro / Repeat")
+
+ PORT_START("maincpu:kbd:KI2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rhythm")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Down")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 2 / Watch")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 3 / Remember")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 1 / Listen")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Normal / Fill In / Rewind")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Function")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Variation / Fill In / Fast Forward")
+
+ PORT_START("P2_R")
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk2000_state, lcd_r)
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("P2_W")
+ PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk2000_state, lcd_w)
+ PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, e_w)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk2000_state, apo_w)
+
+ PORT_START("P3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rw_w)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rs_w)
+ PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("AIN1")
+ PORT_BIT( 0x3ff, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Pedal")
+
+ PORT_START("AIN2")
+ PORT_CONFNAME( 0x3ff, 0x000, "Power Source" )
+ PORT_CONFSETTING( 0x000, "AC Adapter" )
+ PORT_CONFSETTING( 0x3ff, "Battery" )
+
+ PORT_START("AIN3")
+ PORT_BIT( 0x3ff, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("AIN2", 0x3ff, EQUALS, 0)
+ PORT_CONFNAME( 0x3ff, 0x3ff, "Battery Level" ) PORT_CONDITION("AIN2", 0x3ff, NOTEQUALS, 0)
+ // values here are somewhat arbitrary - ctk2100 only checks if the value is above/below a certain threshold
+ PORT_CONFSETTING( 0x100, "Low" )
+ PORT_CONFSETTING( 0x3ff, "Normal" )
+
+INPUT_PORTS_END
+
+ROM_START(ctk2100)
+ ROM_REGION(0x200000, "maincpu", 0)
+ ROM_LOAD("ctk2100.ic2", 0x000000, 0x200000, CRC(daf62f81) SHA1(4edc76ea04b59090d02646d92f9fc635a43140e9))
+ROM_END
+
+} // anonymous namespace
+
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+SYST( 2009, ctk2100, 0, 0, ctk2000, ctk2100, ctk2000_state, empty_init, "Casio", "CTK-2100", MACHINE_NO_SOUND | MACHINE_NODEVICE_MICROPHONE | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/drivers/ctk551.cpp b/src/mame/drivers/ctk551.cpp
index 82f2c90128c..77b0859aab8 100644
--- a/src/mame/drivers/ctk551.cpp
+++ b/src/mame/drivers/ctk551.cpp
@@ -180,7 +180,7 @@ void ctk551_state::ctk551(machine_config &config)
}
INPUT_PORTS_START(ctk551)
- PORT_START("maincpu:kbd:KO0")
+ PORT_START("maincpu:kbd:FI0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2")
@@ -190,7 +190,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2")
- PORT_START("maincpu:kbd:KO1")
+ PORT_START("maincpu:kbd:FI1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2#")
@@ -200,7 +200,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3#")
- PORT_START("maincpu:kbd:KO2")
+ PORT_START("maincpu:kbd:FI2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3#")
@@ -210,7 +210,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3")
- PORT_START("maincpu:kbd:KO3")
+ PORT_START("maincpu:kbd:FI3")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4")
@@ -220,7 +220,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4")
- PORT_START("maincpu:kbd:KO4")
+ PORT_START("maincpu:kbd:FI4")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4#")
@@ -230,7 +230,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5#")
- PORT_START("maincpu:kbd:KO5")
+ PORT_START("maincpu:kbd:FI5")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5#")
@@ -240,7 +240,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5")
- PORT_START("maincpu:kbd:KO6")
+ PORT_START("maincpu:kbd:FI6")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6")
@@ -250,7 +250,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6")
- PORT_START("maincpu:kbd:KO7")
+ PORT_START("maincpu:kbd:FI7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6#")
@@ -258,7 +258,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7")
PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_START("maincpu:kbd:KO8")
+ PORT_START("maincpu:kbd:FI8")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD)
@@ -268,7 +268,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rhythm")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tone")
- PORT_START("maincpu:kbd:KO9")
+ PORT_START("maincpu:kbd:FI9")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD)
@@ -278,7 +278,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Transpose / Tune / MIDI")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Chord Book")
- PORT_START("maincpu:kbd:KO10")
+ PORT_START("maincpu:kbd:FI10")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD)
@@ -288,7 +288,7 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Start / Stop")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Sync / Fill In")
- PORT_START("maincpu:kbd:KO11")
+ PORT_START("maincpu:kbd:KI0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right Hand On/Off")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left Hand On/Off")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fast Forward")
@@ -298,10 +298,13 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Up")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Volume Up")
- PORT_START("maincpu:kbd:KO12")
+ PORT_START("maincpu:kbd:KI1")
PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, switch_r)
+ PORT_START("maincpu:kbd:KI2")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
+
PORT_START("maincpu:kbd:VELOCITY")
PORT_BIT( 0x7f, 0x7f, IPT_POSITIONAL ) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0)
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index feccd2dc9f5..f10c87b6eb6 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -207,6 +207,7 @@ crei680.cpp
crimson.cpp
crvision.cpp
ct486.cpp
+ctk2000.cpp
ctk551.cpp
cvicny.cpp
cxg_ch2001.cpp
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index 4108b35ef42..64610c3ba21 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -56,6 +56,7 @@ using util::BIT;
#include "cpu/g65816/g65816ds.h"
#include "cpu/gigatron/gigatrondasm.h"
#include "cpu/h6280/6280dasm.h"
+#include "cpu/h8/gt913d.h"
#include "cpu/h8/h8d.h"
#include "cpu/h8/h8hd.h"
#include "cpu/h8/h8s2000d.h"
@@ -423,6 +424,7 @@ static const dasm_table_entry dasm_table[] =
{ "fr", be, 0, []() -> util::disasm_interface * { return new fr_disassembler; } },
{ "g65816", le, 0, []() -> util::disasm_interface * { return new g65816_disassembler(&g65816_unidasm); } },
{ "gigatron", be, -1, []() -> util::disasm_interface * { return new gigatron_disassembler; } },
+ { "gt913", be, 0, []() -> util::disasm_interface * { return new gt913_disassembler; } },
{ "h6280", le, 0, []() -> util::disasm_interface * { return new h6280_disassembler; } },
{ "h8", be, 0, []() -> util::disasm_interface * { return new h8_disassembler; } },
{ "h8h", be, 0, []() -> util::disasm_interface * { return new h8h_disassembler; } },