ctk551.cpp: New working machines (#9929)

* New working machines:
---------------------------------------
Casio Celviano AP-10 [Devin Acker]
Casio CTK-601 [Devin Acker, Gabriel Miceli]
Casio GZ-70SP [Devin Acker]
This commit is contained in:
Devin Acker 2022-08-12 19:30:06 -04:00 committed by GitHub
parent fa6a393a32
commit 41e1c7d3a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1499 additions and 216 deletions

View File

@ -1,20 +1,21 @@
// license:BSD-3-Clause
// copyright-holders:Devin Acker
/***************************************************************************
Casio GT913
Casio GT913 (uPD913)
This chip powers several late-90s/early-2000s Casio keyboards.
It's based on the H8/300 instruction set, but with different encoding
for many opcodes, as well as:
- Dedicated bank switching instructions (20-bit external address bus)
- Dedicated bank switching instructions
(20-bit external address bus + 3 chip select outputs, can address a total of 4MB)
- Two timers, three 8-bit ports, two 8-bit ADCs
- Keyboard controller w/ key velocity detection
- MIDI UART
- 24-voice DPCM sound
Earlier and later Casio keyboard models contain "uPD912" and "uPD914" chips,
which are presumably similar.
Variants include the uPD912 and GT915/uPD915.
These were later succeeded by the uPD914.
***************************************************************************/
@ -28,12 +29,12 @@ gt913_device::gt913_device(const machine_config &mconfig, const char *tag, devic
h8_device(mconfig, GT913, tag, owner, clock, address_map_constructor(FUNC(gt913_device::map), this)),
device_mixer_interface(mconfig, *this, 2),
m_rom(*this, DEVICE_SELF),
m_bank(*this, "bank"),
data_config("data", ENDIANNESS_BIG, 16, 22, 0),
m_intc(*this, "intc"),
m_sound(*this, "gt_sound"),
m_kbd(*this, "kbd"),
m_io_hle(*this, "io_hle"),
m_sci(*this, "sci"),
m_sci(*this, "sci%u", 0),
m_port(*this, "port%u", 1)
{
has_hc = false;
@ -46,11 +47,10 @@ std::unique_ptr<util::disasm_interface> gt913_device::create_disassembler()
void gt913_device::map(address_map &map)
{
// map.unmap_value_high();
map(0x0000, 0x7fff).rom();
map(0x8000, 0xbfff).bankr("bank");
map(0xfac0, 0xffbf).ram(); // CTK-551 zeroes out this range at $0418
map(0x8000, 0xbfff).rw(FUNC(gt913_device::data_r), FUNC(gt913_device::data_w));
map(0xc000, 0xf7ff).rom();
map(0xfac0, 0xffbf).ram();
/* ffc0-ffcb: sound */
map(0xffc0, 0xffc5).rw(m_sound, FUNC(gt913_sound_device::data_r), FUNC(gt913_sound_device::data_w));
@ -66,11 +66,13 @@ void gt913_device::map(address_map &map)
map(0xffdc, 0xffdd).w(m_io_hle, FUNC(gt913_io_hle_device::timer_rate0_w));
map(0xffdf, 0xffdf).w(m_io_hle, FUNC(gt913_io_hle_device::timer_rate1_w));
/* ffe0-ffe3: serial */
/* ffe0-ffe7: serial */
map(0xffe0, 0xffe0).w(FUNC(gt913_device::uart_rate_w));
map(0xffe1, 0xffe1).w(m_sci, FUNC(h8_sci_device::tdr_w));
map(0xffe2, 0xffe2).rw(FUNC(gt913_device::uart_control_r), FUNC(gt913_device::uart_control_w));
map(0xffe3, 0xffe3).r(m_sci, FUNC(h8_sci_device::rdr_r));
map(0xffe1, 0xffe1).w(m_sci[0], FUNC(h8_sci_device::tdr_w));
map(0xffe2, 0xffe2).select(0x04).rw(FUNC(gt913_device::uart_control_r), FUNC(gt913_device::uart_control_w));
map(0xffe3, 0xffe3).r(m_sci[0], FUNC(h8_sci_device::rdr_r));
map(0xffe5, 0xffe5).w(m_sci[1], FUNC(h8_sci_device::tdr_w));
map(0xffe7, 0xffe7).r(m_sci[1], FUNC(h8_sci_device::rdr_r));
/* ffe9-ffea: ADC */
map(0xffe9, 0xffe9).rw(m_io_hle, FUNC(gt913_io_hle_device::adc_control_r), FUNC(gt913_io_hle_device::adc_control_w));
@ -78,14 +80,13 @@ void gt913_device::map(address_map &map)
/* fff0-fff5: I/O ports */
map(0xfff0, 0xfff0).rw(m_port[0], FUNC(h8_port_device::ddr_r), FUNC(h8_port_device::ddr_w));
map(0xfff1, 0xfff1).rw(m_port[1], FUNC(h8_port_device::ddr_r), FUNC(h8_port_device::ddr_w));
// port 2 DDR - ctk601 and gz70sp both seem to use only bit 0 to indicate either all inputs or all outputs
// map(0xfff1, 0xfff1).rw(m_port[1], FUNC(h8_port_device::ddr_r), FUNC(h8_port_device::ddr_w));
map(0xfff1, 0xfff1).lw8(NAME([this](uint8_t data) { m_port[1]->ddr_w(BIT(data, 0) ? 0xff : 0x00); }));
map(0xfff2, 0xfff2).rw(m_port[0], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
map(0xfff3, 0xfff3).rw(m_port[1], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
// likely port 3 - pins are shared with input matrix, ctk551 clears this register on boot and nothing else
// (specifically, the pins are also used for key velocity detection, so port 3 is probably used by very few models, if any at all)
map(0xfff4, 0xfff4).rw(m_port[2], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
// unknown - ctk551 sets/clears a few bits on boot and before going to sleep
// map(0xfff5, 0xfff5).noprw();
map(0xfff5, 0xfff5).rw(FUNC(gt913_device::syscr_r), FUNC(gt913_device::syscr_w));
}
void gt913_device::device_add_mconfig(machine_config &config)
@ -98,34 +99,126 @@ void gt913_device::device_add_mconfig(machine_config &config)
m_sound->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
GT913_KBD_HLE(config, m_kbd, 0);
m_kbd->irq_cb().set([this] (int val) { if (val) m_intc->internal_interrupt(5); });
m_kbd->irq_cb().set([this] (int val)
{
if (val)
m_intc->internal_interrupt(5);
else
m_intc->clear_interrupt(5);
});
GT913_IO_HLE(config, m_io_hle, "intc", 6, 7);
H8_SCI(config, m_sci, "intc", 8, 9, 10, 0);
H8_SCI(config, m_sci[0], "intc", 8, 9, 10, 0);
H8_SCI(config, m_sci[1], "intc", 11, 12, 13, 0);
H8_PORT(config, m_port[0], h8_device::PORT_1, 0xff, 0x00);
H8_PORT(config, m_port[1], h8_device::PORT_2, 0xff, 0x00);
H8_PORT(config, m_port[2], h8_device::PORT_3, 0xff, 0x00);
H8_PORT(config, m_port[0], h8_device::PORT_1, 0x00, 0x00);
H8_PORT(config, m_port[1], h8_device::PORT_2, 0x00, 0x00);
H8_PORT(config, m_port[2], h8_device::PORT_3, 0x00, 0x00);
}
void gt913_device::uart_rate_w(uint8_t data)
{
m_sci->brr_w(data >> 2);
// TODO: how is SCI1 baud rate actually selected?
// gz70sp writes 0x7e to ffe4 to select 31250 baud for MIDI, which doesn't seem right
m_sci[0]->brr_w(data >> 2);
m_sci[1]->brr_w(data >> 2);
}
void gt913_device::uart_control_w(uint8_t data)
void gt913_device::uart_control_w(offs_t offset, uint8_t data)
{
const unsigned num = BIT(offset, 2);
/*
upper 4 bits seem to correspond to the upper bits of SSR (Tx/Rx/error status)
lower 4 bits seem to correspond to the upper bits of SCR (Tx/Rx IRQ enable, Tx/Rx enable(?))
*/
m_sci->ssr_w(data & 0xf0);
m_sci->scr_w((data & 0x0f) << 4);
m_sci[num]->ssr_w(data & 0xf0);
m_sci[num]->scr_w((data & 0x0f) << 4);
}
uint8_t gt913_device::uart_control_r()
uint8_t gt913_device::uart_control_r(offs_t offset)
{
return (m_sci->ssr_r() & 0xf0) | (m_sci->scr_r() >> 4);
const unsigned num = BIT(offset, 2);
return (m_sci[num]->ssr_r() & 0xf0) | (m_sci[num]->scr_r() >> 4);
}
void gt913_device::syscr_w(uint8_t data)
{
if (BIT(m_syscr ^ data, 2))
// NMI active edge has changed
m_intc->set_input(INPUT_LINE_NMI, CLEAR_LINE);
m_syscr = data;
}
uint8_t gt913_device::syscr_r()
{
return m_syscr;
}
void gt913_device::data_w(offs_t offset, uint8_t data)
{
m_data.write_byte(offset | (m_banknum & 0xff) << 14, data);
}
uint8_t gt913_device::data_r(offs_t offset)
{
return m_data.read_byte(offset | (m_banknum & 0xff) << 14);
}
uint8_t gt913_device::read8ib(uint32_t adr)
{
if (BIT(m_syscr, 0))
// indirect bank disabled
return program.read_byte(adr);
else if ((IR[0] & 0x0070) == 0)
// indirect bank enabled, using bankh for r0
return m_data.read_byte(adr | ((m_banknum >> 6) << 16));
else
// indirect bank enabled, using bankl for other regs
return m_data.read_byte(adr | ((m_banknum & 0x3f) << 16));
}
void gt913_device::write8ib(uint32_t adr, uint8_t data)
{
if (BIT(m_syscr, 0))
// indirect bank disabled
program.write_byte(adr, data);
else if ((IR[0] & 0x0070) == 0)
// indirect bank enabled, using bankh for r0
m_data.write_byte(adr | ((m_banknum >> 6) << 16), data);
else
// indirect bank enabled, using bankl for other regs
m_data.write_byte(adr | ((m_banknum & 0x3f) << 16), data);
}
uint16_t gt913_device::read16ib(uint32_t adr)
{
adr &= ~1;
if (BIT(m_syscr, 0))
// indirect bank disabled
return program.read_word(adr);
else if ((IR[0] & 0x0070) == 0)
// indirect bank enabled, using bankh for r0
return m_data.read_word(adr | ((m_banknum >> 6) << 16));
else
// indirect bank enabled, using bankl for other regs
return m_data.read_word(adr | ((m_banknum & 0x3f) << 16));
}
void gt913_device::write16ib(uint32_t adr, uint16_t data)
{
adr &= ~1;
if (BIT(m_syscr, 0))
// indirect bank disabled
program.write_word(adr, data);
else if ((IR[0] & 0x0070) == 0)
// indirect bank enabled, using bankh for r0
m_data.write_word(adr | ((m_banknum >> 6) << 16), data);
else
// indirect bank enabled, using bankl for other regs
m_data.write_word(adr | ((m_banknum & 0x3f) << 16), data);
}
void gt913_device::irq_setup()
@ -150,23 +243,40 @@ void gt913_device::internal_update(uint64_t current_time)
{
uint64_t event_time = 0;
add_event(event_time, m_sci->internal_update(current_time));
add_event(event_time, m_sci[0]->internal_update(current_time));
add_event(event_time, m_sci[1]->internal_update(current_time));
recompute_bcount(event_time);
}
void gt913_device::execute_set_input(int inputnum, int state)
{
if (inputnum == INPUT_LINE_NMI)
{
if (BIT(m_syscr, 2))
state ^= ASSERT_LINE;
}
m_intc->set_input(inputnum, state);
}
device_memory_interface::space_config_vector gt913_device::memory_space_config() const
{
return space_config_vector{
std::make_pair(AS_PROGRAM, &program_config),
std::make_pair(AS_IO, &io_config),
std::make_pair(AS_DATA, &data_config)
};
}
void gt913_device::device_start()
{
h8_device::device_start();
m_bank->configure_entries(0, m_rom->bytes() >> 12, m_rom->base(), 1 << 12);
space(AS_DATA).specific(m_data);
save_item(NAME(m_banknum));
save_item(NAME(m_syscr));
}
void gt913_device::device_reset()
@ -174,6 +284,7 @@ void gt913_device::device_reset()
h8_device::device_reset();
m_banknum = 0;
m_syscr = 0;
}
#include "cpu/h8/gt913.hxx"

View File

@ -28,17 +28,30 @@ public:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
void uart_rate_w(uint8_t data);
void uart_control_w(uint8_t data);
uint8_t uart_control_r();
void uart_control_w(offs_t offset, uint8_t data);
uint8_t uart_control_r(offs_t offset);
void data_w(offs_t offset, uint8_t data);
uint8_t data_r(offs_t offset);
void syscr_w(uint8_t data);
uint8_t syscr_r();
protected:
/* indirect reads/writes with banking support */
uint8_t read8ib(uint32_t adr);
void write8ib(uint32_t adr, uint8_t data);
uint16_t read16ib(uint32_t adr);
void write16ib(uint32_t adr, uint16_t data);
virtual void update_irq_filter() override;
virtual void interrupt_taken() override;
virtual void internal_update(uint64_t current_time) override;
virtual void irq_setup() override;
virtual void execute_set_input(int inputnum, int state) override;
virtual space_config_vector memory_space_config() const override;
virtual void device_add_mconfig(machine_config &config) override;
void map(address_map &map);
@ -49,15 +62,27 @@ protected:
virtual void do_exec_partial() override;
#define O(o) void o ## _full(); void o ## _partial()
O(ldbank_imm2l_bankl); O(ldbank_imm4l_bankh); O(ldbank_r8l_bankl); O(ldbank_r8l_bankh);
O(ldc_imm6l_ccr);
O(ldbank_imm6l_bankl); O(ldbank_imm6l_bankh); O(ldbank_r8l_bankl); O(ldbank_r8l_bankh);
O(dispatch_6600); O(dispatch_7000); O(dispatch_7200);
O(jmp_abs22e);
O(mov_b_r16ih_r8l); O(mov_w_r16ih_r16l); O(mov_b_r16ph_r8l); O(mov_w_r16ph_r16l);
O(mov_b_r8l_r16ih); O(mov_w_r16l_r16ih); O(mov_b_r8l_pr16h); O(mov_w_r16l_pr16h);
O(mov_b_r16d16h_r8l); O(mov_w_r16d16h_r16l); O(mov_b_r8l_r16d16h); O(mov_w_r16l_r16d16h);
O(dispatch_6000); O(dispatch_6100); O(dispatch_6200); O(dispatch_6300);
O(dispatch_6400); O(dispatch_6500); O(dispatch_6600); O(dispatch_6700);
O(dispatch_7000); O(dispatch_7100); O(dispatch_7200); O(dispatch_7300);
O(dispatch_7400); O(dispatch_7500); O(dispatch_7600); O(dispatch_7700);
#undef O
required_memory_region m_rom;
required_memory_bank m_bank;
uint16_t m_banknum;
address_space_config data_config;
memory_access<32, 1, 0, ENDIANNESS_BIG>::specific m_data;
uint16_t m_banknum;
uint8_t m_syscr;
required_device<gt913_intc_device> m_intc;
@ -71,7 +96,7 @@ protected:
required_device<gt913_io_hle_device> m_io_hle;
/* serial port */
required_device<h8_sci_device> m_sci;
required_device_array<h8_sci_device, 2> m_sci;
/* 3x 8-bit I/O ports */
required_device_array<h8_port_device, 3> m_port;

View File

@ -9,30 +9,31 @@
0240 fff0 0 stc ccr r8l
0340 fff0 0 ldc r8l ccr
0380 fff0 0 ldbank r8l bankh g
TMP1 = r8_r(IR[0]);
m_banknum = (TMP1 << 2) | (m_banknum & 0x3);
m_bank->set_entry(m_banknum);
0380 fff0 0 ldbank r8l bankl g
TMP1 = r8_r(IR[0]) & 0x3f;
m_banknum = (m_banknum & 0xffc0) | TMP1;
prefetch();
03c0 fff0 0 ldbank r8l bankl g
TMP1 = r8_r(IR[0]);
m_banknum = (m_banknum & 0xfffc) | (TMP1 & 0x3);
m_bank->set_entry(m_banknum);
03c0 fff0 0 ldbank r8l bankh g
TMP1 = r8_r(IR[0]) & 0x3f;
m_banknum = (TMP1 << 6) | (m_banknum & 0x3f);
prefetch();
0400 ff00 0 orc imm8 ccr
0500 ff00 0 xorc imm8 ccr
0600 ff00 0 andc imm8 ccr
0780 fff0 0 ldbank imm4l bankh g
m_banknum = ((IR[0] & 0xf) << 2) | (m_banknum & 0x3);
m_bank->set_entry(m_banknum);
0740 ffc0 0 ldc imm6l ccr g
CCR = IR[0] & 0x3f;
update_irq_filter();
prefetch_noirq();
0780 ffc0 0 ldbank imm6l bankl g
m_banknum = (m_banknum & 0xffc0) | (IR[0] & 0x3f);
prefetch();
07c0 fff0 0 ldbank imm2l bankl g
m_banknum = (m_banknum & 0xfffc) | (IR[0] & 0x3);
m_bank->set_entry(m_banknum);
07c0 ffc0 0 ldbank imm6l bankh g
m_banknum = ((IR[0] & 0x3f) << 6) | (m_banknum & 0x3f);
prefetch();
0800 ff00 0 add.b r8h r8l
@ -101,34 +102,162 @@
5980 ffff 0 rte - -
5a00 ff8f 0 jmp r16h -
5a80 ffff 0 jmp abs16e -
5b00 ff00 0 jmp abs8i -
# TODO: how is this instruction actually supposed to work?
# gz70sp has an unused instance of it (probably used in whatever keyboard the ROM is based on)
# located where a 'sleep' instruction would normally be.
# the lower 22 bits of the address point to a lone 'sleep' instruction at the end of the ROM,
# but given the 16-bit program counter, it's not really clear what exactly is meant to happen.
# for now, just setting bankl/bankh and jumping into the bankswitched memory area should be ok
# (the NMI from the power switch will get things going afterwards).
5b80 ffc0 0 jmp abs22e - g
internal(1);
m_banknum = ((IR[0] & 0x3f) << 2) | (IR[1] >> 14);
PC = 0x8000 | (IR[1] & 0x3fff);
prefetch();
5c00 ff8f 0 jsr r16h -
5c80 ffff 0 jsr abs16e -
5e00 ff00 0 bsr rel8 -
5f00 fff0 0 mov.w imm16 r16l
66000000 ff00ff8f 0 btst imm3 r16ihh
60000000 ff8fff8f 0 bset imm3 r16ihh
61000000 ff8fff0f 0 bset r8h r16ihh
62000000 ff8fff8f 0 bclr imm3 r16ihh
63000000 ff8fff0f 0 bclr r8h r16ihh
64000000 ff8fff8f 0 bnot imm3 r16ihh
65000000 ff8fff0f 0 bnot r8h r16ihh
66000000 ff8fff8f 0 btst imm3 r16ihh
67000000 ff8fff0f 0 btst r8h r16ihh
6800 ff80 0 mov.b r16ih r8l g
prefetch_start();
internal(1);
TMP1 = read8ib(r16_r(IR[0] >> 4));
set_nzv8(TMP1);
r8_w(IR[0], TMP1);
prefetch_done();
6900 ff88 0 mov.w r16ih r16l g
prefetch_start();
internal(1);
TMP1 = read16ib(r16_r(IR[0] >> 4));
set_nzv16(TMP1);
r16_w(IR[0], TMP1);
prefetch_done();
6a00 ff80 0 mov.b r16ph r8l g
TMP2 = r16_r(IR[0] >> 4);
prefetch_start();
internal(2);
TMP1 = read8ib(TMP2);
TMP2 += 1;
r16_w(IR[0] >> 4, TMP2);
set_nzv8(TMP1);
r8_w(IR[0], TMP1);
prefetch_done();
6b00 ff88 0 mov.w r16ph r16l g
TMP2 = r16_r(IR[0] >> 4);
prefetch_start();
internal(2);
TMP1 = read16ib(TMP2);
TMP2 += 2;
r16_w(IR[0] >> 4, TMP2);
set_nzv16(TMP1);
r16_w(IR[0], TMP1);
prefetch_done();
6800 ff80 0 mov.b r16ih r8l
6900 ff88 0 mov.w r16ih r16l
6a00 ff80 0 mov.b r16ph r8l
6b00 ff88 0 mov.w r16ph r16l
6c00 fff0 0 mov.b abs16 r8l
6d00 fff0 0 mov.w abs16 r16l
6e00 ff80 0 mov.b r16d16h r8l
6f00 ff80 0 mov.w r16d16h r16l
6e00 ff80 0 mov.b r16d16h r8l g
prefetch_start();
TMP1 = uint16_t(r16_r(IR[0] >> 4) + IR[1]);
internal(1);
TMP2 = read8ib(TMP1);
set_nzv8(TMP2);
r8_w(IR[0], TMP2);
prefetch_done();
6f00 ff80 0 mov.w r16d16h r16l g
prefetch_start();
TMP1 = uint16_t(r16_r(IR[0] >> 4) + IR[1]);
internal(1);
TMP2 = read16ib(TMP1);
set_nzv16(TMP2);
r16_w(IR[0], TMP2);
prefetch_done();
70000000 ff00ff8f 0 bset imm3 abs8
71000000 ff00ff0f 0 bset r8h abs8
72000000 ff00ff8f 0 bclr imm3 abs8
73000000 ff00ff0f 0 bclr r8h abs8
74000000 ff00ff8f 0 bnot imm3 abs8
75000000 ff00ff0f 0 bnot r8h abs8
76000000 ff00ff8f 0 btst imm3 abs8
77000000 ff00ff0f 0 btst r8h abs8
7800 ff80 0 mov.b r8l r16ih g
prefetch_start();
TMP1 = r8_r(IR[0]);
set_nzv8(TMP1);
internal(1);
write8ib(r16_r(IR[0] >> 4), TMP1);
prefetch_done();
7900 ff88 0 mov.w r16l r16ih g
prefetch_start();
TMP1 = r16_r(IR[0]);
set_nzv16(TMP1);
internal(1);
write16ib(r16_r(IR[0] >> 4), TMP1);
prefetch_done();
7a00 ff80 0 mov.b r8l pr16h g
TMP1 = r8_r(IR[0]);
TMP2 = r16_r(IR[0] >> 4);
prefetch_start();
internal(1);
TMP2 -= 1;
r16_w(IR[0] >> 4, TMP2);
set_nzv8(TMP1);
internal(1);
write8ib(TMP2, TMP1);
prefetch_done();
7b00 ff88 0 mov.w r16l pr16h g
TMP1 = r16_r(IR[0]);
TMP2 = r16_r(IR[0] >> 4);
prefetch_start();
internal(1);
TMP2 -= 2;
r16_w(IR[0] >> 4, TMP2);
set_nzv16(TMP1);
internal(1);
write16ib(TMP2, TMP1);
prefetch_done();
7800 ff80 0 mov.b r8l r16ih
7900 ff88 0 mov.w r16l r16ih
7a00 ff80 0 mov.b r8l pr16h
7b00 ff88 0 mov.w r16l pr16h
7c00 fff0 0 mov.b r8l abs16
7d00 fff0 0 mov.w r16l abs16
7e00 ff80 0 mov.b r8l r16d16h
7f00 ff80 0 mov.w r16l r16d16h
7e00 ff80 0 mov.b r8l r16d16h g
prefetch_start();
TMP1 = uint16_t(r16_r(IR[0] >> 4) + IR[1]);
TMP2 = r8_r(IR[0]);
set_nzv8(TMP2);
internal(1);
write8ib(TMP1, TMP2);
prefetch_done();
7f00 ff80 0 mov.w r16l r16d16h g
prefetch_start();
TMP1 = uint16_t(r16_r(IR[0] >> 4) + IR[1]);
TMP2 = r16_r(IR[0]);
set_nzv16(TMP2);
internal(1);
write16ib(TMP1, TMP2);
prefetch_done();
8000 f000 0 add.b imm8 r8u
9000 f000 0 addx.b imm8 r8u

View File

@ -482,16 +482,16 @@ uint8_t h8_device::do_addx8(uint8_t v1, uint8_t v2)
uint8_t h8_device::do_subx8(uint8_t v1, uint8_t v2)
{
uint16_t res = v1 - v2 - (CCR & F_C ? 1 : 0);
CCR &= ~(F_N|F_V|F_Z|F_C);
CCR &= ~(F_N|F_V|F_C);
if (has_hc)
{
CCR &= ~F_H;
if (((v1 & 0xf) - (v2 & 0xf) - (CCR & F_C ? 1 : 0)) & 0x10)
CCR |= F_H;
}
if(!uint8_t(res))
CCR |= F_Z;
else if(int8_t(res) < 0)
if(uint8_t(res))
CCR &= ~F_Z;
if(int8_t(res) < 0)
CCR |= F_N;
if((v1^v2) & (v1^res) & 0x80)
CCR |= F_V;

View File

@ -12,11 +12,12 @@ h8_intc_device::h8_intc_device(const machine_config &mconfig, const char *tag, d
h8_intc_device(mconfig, H8_INTC, tag, owner, clock)
{
irq_vector_base = 4;
irq_vector_count = 8;
irq_vector_nmi = 3;
}
h8_intc_device::h8_intc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock), irq_vector_base(0), irq_vector_nmi(0),
device_t(mconfig, type, tag, owner, clock), irq_vector_base(0), irq_vector_count(0), irq_vector_nmi(0),
cpu(*this, DEVICE_SELF_OWNER), nmi_input(false), irq_input(0), ier(0), isr(0), iscr(0), icr_filter(0), ipr_filter(0)
{
}
@ -48,7 +49,7 @@ int h8_intc_device::interrupt_taken(int vector)
if(0)
logerror("taking internal interrupt %d\n", vector);
pending_irqs[vector >> 5] &= ~(1 << (vector & 31));
if(irq_vector_base >= 0 && vector >= irq_vector_base && vector < irq_vector_base + 8) {
if(vector >= irq_vector_base && vector < irq_vector_base + irq_vector_count) {
int irq = vector - irq_vector_base;
if(irq_type[irq] != IRQ_LEVEL || !(irq_input & (1 << irq)))
isr &= ~(1 << irq);
@ -160,10 +161,12 @@ void h8_intc_device::update_irq_types()
void h8_intc_device::update_irq_state()
{
if (irq_vector_base >= 0)
if (irq_vector_count > 0)
{
pending_irqs[0] &= ~(255 << irq_vector_base);
pending_irqs[0] |= (isr & ier) << irq_vector_base;
const unsigned mask = (1 << irq_vector_count) - 1;
pending_irqs[0] &= ~(mask << irq_vector_base);
pending_irqs[0] |= (isr & ier & mask) << irq_vector_base;
}
int cur_vector = 0;
@ -199,7 +202,8 @@ void h8_intc_device::get_priority(int vect, int &icr_pri, int &ipr_pri) const
gt913_intc_device::gt913_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
gt913_intc_device(mconfig, GT913_INTC, tag, owner, clock)
{
irq_vector_base = -1; // no external IRQs
irq_vector_base = 4;
irq_vector_count = 1;
irq_vector_nmi = 3;
}
@ -208,11 +212,25 @@ gt913_intc_device::gt913_intc_device(const machine_config &mconfig, device_type
{
}
void gt913_intc_device::device_reset()
{
h8_intc_device::device_reset();
ier = 0x01;
}
void gt913_intc_device::clear_interrupt(int vector)
{
pending_irqs[vector >> 5] &= ~(1 << (vector & 31));
update_irq_state();
}
h8h_intc_device::h8h_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
h8h_intc_device(mconfig, H8H_INTC, tag, owner, clock)
{
irq_vector_base = 12;
irq_vector_count = 8;
irq_vector_nmi = 7;
}
@ -339,6 +357,7 @@ h8s_intc_device::h8s_intc_device(const machine_config &mconfig, const char *tag,
h8h_intc_device(mconfig, H8S_INTC, tag, owner, clock)
{
irq_vector_base = 16;
irq_vector_count = 8;
irq_vector_nmi = 7;
}

View File

@ -36,6 +36,7 @@ protected:
enum { MAX_VECTORS = 256 };
int irq_vector_base;
int irq_vector_count;
int irq_vector_nmi;
required_device<h8_device> cpu;
@ -64,8 +65,11 @@ class gt913_intc_device : public h8_intc_device {
public:
gt913_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
void clear_interrupt(int vector);
protected:
gt913_intc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_reset() override;
};
class h8h_intc_device : public h8_intc_device {

View File

@ -179,6 +179,10 @@ void h8_disassembler::disassemble_am(std::ostream &stream, int am, offs_t pc, co
util::stream_format(stream, "h'%04x", opcodes.r16(pc+2));
break;
case DASM_abs22e:
util::stream_format(stream, "h'%06x", opcodes.r32(pc) & 0x3fffff);
break;
case DASM_abs24e:
util::stream_format(stream, "h'%06x", opcodes.r32(pc) & 0xffffff);
break;
@ -213,16 +217,12 @@ void h8_disassembler::disassemble_am(std::ostream &stream, int am, offs_t pc, co
util::stream_format(stream, "#%x", (opcode >> 4) & 3);
break;
case DASM_imm2l:
util::stream_format(stream, "#%x", opcode & 3);
break;
case DASM_imm3:
util::stream_format(stream, "#%x", (opcode >> 4) & 7);
break;
case DASM_imm4l:
util::stream_format(stream, "#%x", opcode & 15);
case DASM_imm6l:
util::stream_format(stream, "#%x", opcode & 0x3f);
break;
case DASM_imm8:

View File

@ -70,6 +70,7 @@ protected:
DASM_abs32, /* 32-bit address present at end of instruction */
DASM_abs8i, /* 8-bit indirect jump address present at +1 */
DASM_abs16e, /* 16-bit jump address present at +2 */
DASM_abs22e, /* 22-bit jump address present at +1 (GT913) */
DASM_abs24e, /* 24-bit jump address present at +1 */
DASM_rel8, /* 8-bit pc-relative jump address at +1, offset=2 */
@ -80,9 +81,8 @@ protected:
DASM_four, /* immediate value 4 */
DASM_imm2, /* 2-bit immediate in bits 4-5 (trapa) */
DASM_imm2l, /* 2-bit immediate in bits 0-1 (GT913) */
DASM_imm3, /* 3-bit immediate in bits 4-6 (bit selection */
DASM_imm4l, /* 4-bit immediate in bits 0-3 (GT913) */
DASM_imm6l, /* 6-bit immediate in bits 0-5 (GT913) */
DASM_imm8, /* 8-bit immediate at +1 */
DASM_imm16, /* 16-bit immediate at +2 */
DASM_imm32, /* 32-bit immediate at +2 */
@ -90,7 +90,7 @@ protected:
DASM_ccr, /* internal register ccr */
DASM_exr, /* internal register exr */
DASM_bankl, /* internal register bankl (GT913) */
DASM_bankh, /* internal register bankl (GT913) */
DASM_bankh, /* internal register bankh (GT913) */
DASM_macl, /* internal register macl */
DASM_mach /* internal register mach */
};

View File

@ -145,7 +145,7 @@ class Opcode:
if dtype == 0 and (am1 == "r16h" or am2 == "r16h"):
self.mask[len(self.mask) - 1] |= 0x80
extra_words = 0
if (am1 == "abs16" or am2 == "abs16" or am1 == "abs16e" or am1 == "abs24e") and self.skip == 0:
if (am1 == "abs16" or am2 == "abs16" or am1 == "abs16e" or am1 == "abs22e" or am1 == "abs24e") and self.skip == 0:
extra_words += 1
if (am1 == "abs32" or am2 == "abs32") and self.skip == 0:
extra_words += 2

View File

@ -44,6 +44,14 @@ const s8 gt913_sound_device::sample_7_to_8[128] =
-16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1
};
// based on SW-10 softsynth
const u16 gt913_sound_device::volume_ramp[17] =
{
0x0000, 0x00fa, 0x0231, 0x03b5, 0x0596, 0x07ee, 0x0ad8, 0x0e78,
0x12fa, 0x1897, 0x1f93, 0x2843, 0x3313, 0x4087, 0x5143, 0x6617,
0x8000
};
gt913_sound_device::gt913_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, GT913_SOUND, tag, owner, clock)
, device_sound_interface(mconfig, *this)
@ -77,10 +85,10 @@ void gt913_sound_device::device_start()
save_item(STRUCT_MEMBER(m_voices, m_sample_next));
save_item(STRUCT_MEMBER(m_voices, m_exp));
save_item(STRUCT_MEMBER(m_voices, m_volume_data));
save_item(STRUCT_MEMBER(m_voices, m_volume_current));
save_item(STRUCT_MEMBER(m_voices, m_volume_target));
save_item(STRUCT_MEMBER(m_voices, m_volume_rate));
save_item(STRUCT_MEMBER(m_voices, m_volume_end));
save_item(STRUCT_MEMBER(m_voices, m_balance));
save_item(STRUCT_MEMBER(m_voices, m_gain));
@ -102,12 +110,13 @@ void gt913_sound_device::sound_stream_update(sound_stream& stream, std::vector<r
for (auto& voice : m_voices)
{
update_envelope(voice);
if (voice.m_enable)
mix_sample(voice, left, right);
}
outputs[0].put_int_clamp(i, (left * m_gain) >> 26, 32678);
outputs[1].put_int_clamp(i, (right * m_gain) >> 26, 32768);
outputs[0].put_int_clamp(i, (left * m_gain) >> 27, 32678);
outputs[1].put_int_clamp(i, (right * m_gain) >> 27, 32768);
}
}
@ -120,13 +129,27 @@ void gt913_sound_device::mix_sample(voice_t& voice, s64& left, s64& right)
{
// update sample position
voice.m_addr_frac += voice.m_pitch;
while (voice.m_addr_frac >= (1 << 25))
while (voice.m_enable && voice.m_addr_frac >= (1 << 25))
{
voice.m_addr_frac -= (1 << 25);
update_sample(voice);
}
// update volume envelope
// interpolate, apply envelope + channel gain, and mix into output
const u8 step = (voice.m_addr_frac >> 22) & 7;
const u8 env = (voice.m_volume_current >> 27);
const u16 env_step = (voice.m_volume_current >> 16) & 0x7ff;
const u32 env_level = (u32)volume_ramp[env] + (((volume_ramp[env + 1] - volume_ramp[env]) * env_step) >> 11);
const s64 sample = ((s64)voice.m_sample + (voice.m_sample_next * step / 8)) * voice.m_gain * env_level;
left += sample * voice.m_balance[0];
right += sample * voice.m_balance[1];
}
void gt913_sound_device::update_envelope(voice_t& voice)
{
if (voice.m_volume_target > voice.m_volume_current
&& (voice.m_volume_target - voice.m_volume_current) > voice.m_volume_rate)
{
@ -141,37 +164,42 @@ void gt913_sound_device::mix_sample(voice_t& voice, s64& left, s64& right)
{
voice.m_volume_current = voice.m_volume_target;
}
// interpolate, apply envelope + channel gain, and mix into output
const u8 step = (voice.m_addr_frac >> 22) & 7;
const u8 env = (voice.m_volume_current >> 24);
/*
the current envelope level effects amplitude non-linearly, just apply the value twice
(this hardware family is branded as "A² (A-Square) Sound Source" in some of Casio's
promotional materials, possibly for this reason?)
*/
const s64 sample = ((s64)voice.m_sample + (voice.m_sample_next * step / 8)) * voice.m_gain * env * env;
left += sample * voice.m_balance[0];
right += sample * voice.m_balance[1];
}
void gt913_sound_device::update_sample(voice_t& voice)
{
voice.m_sample += voice.m_sample_next;
if (voice.m_addr_current == (voice.m_addr_loop | 1))
if (voice.m_addr_current >= voice.m_addr_end)
{
if (voice.m_addr_loop == voice.m_addr_end)
{
voice.m_enable = false;
return;
}
voice.m_addr_current = voice.m_addr_loop;
/*
The last 12 bytes of each sample are a table containing five sample and exponent value pairs
for the data words immediately after the loop point. The first pair corresponds to what the
sample and exponent value will be _after_ processing the first word after the loop,
sample and exponent value will be _after_ processing the first 16-bit word after the loop,
so once we've reached that point, use those values to reload the current sample and exponent
*/
const u32 addr_loop_data = (voice.m_addr_end + 1) & ~1;
voice.m_sample_next = read_word(addr_loop_data) - voice.m_sample;
voice.m_exp = read_word(addr_loop_data + 10) & 7;
if (!BIT(voice.m_addr_current, 0))
{
/*
the loop data represents the state after applying both samples in a 16-bit word,
so if we're looping to the first of the two samples, compensate for the second one
*/
const u16 word = read_word(voice.m_addr_current);
const s16 delta = sample_7_to_8[word >> 9];
voice.m_sample_next -= delta * (1 << voice.m_exp);
}
}
else
{
@ -192,18 +220,10 @@ void gt913_sound_device::update_sample(voice_t& voice)
{
delta = sample_7_to_8[word >> 9];
}
voice.m_sample_next = delta * (1 << voice.m_exp);
}
voice.m_addr_current++;
if (voice.m_addr_current == voice.m_addr_end)
{
voice.m_addr_current = voice.m_addr_loop;
if (voice.m_addr_loop == voice.m_addr_end)
voice.m_enable = false;
}
}
void gt913_sound_device::data_w(offs_t offset, u16 data)
@ -236,7 +256,7 @@ void gt913_sound_device::command_w(u16 data)
}
auto& voice = m_voices[voicenum];
if (voicecmd == 0x0008)
if (voicecmd == 0x0008) // voice data write commands
{
/*
sample start addresses seem to need to be word-aligned to decode properly
@ -245,19 +265,19 @@ void gt913_sound_device::command_w(u16 data)
may loop badly or even become noticeably detuned
TODO: is the LSB of start addresses supposed to indicate something else, then?
*/
voice.m_addr_start = (m_data[1] | (m_data[2] << 16)) & 0x1ffffe;
voice.m_addr_start = (m_data[1] | (m_data[2] << 16)) & 0x3ffffe;
}
else if (voicecmd == 0x0000)
{
voice.m_addr_end = (m_data[0] | (m_data[1] << 16)) & 0x1fffff;
voice.m_addr_end = (m_data[0] | (m_data[1] << 16)) & 0x3fffff;
}
else if (voicecmd == 0x2000)
{
voice.m_addr_loop = (m_data[0] | (m_data[1] << 16)) & 0x1fffff;
voice.m_addr_loop = (m_data[0] | (m_data[1] << 16)) & 0x3fffff;
}
else if (voicecmd == 0x200a)
{
/* TODO: what does bit 4 of data[2] do? ctk551 sets it unconditionally */
/* TODO: what does bit 3 of data[2] do? ctk551 sets it unconditionally */
voice.m_exp = m_data[2] & 7;
}
else if (voicecmd == 0x200b)
@ -267,11 +287,11 @@ void gt913_sound_device::command_w(u16 data)
{
voice.m_addr_current = voice.m_addr_start;
voice.m_addr_frac = 0;
voice.m_sample = 0;
voice.m_volume_current = 0;
voice.m_sample = voice.m_sample_next = 0;
}
voice.m_enable = enable;
voice.m_volume_end &= enable;
}
else if (voicecmd == 0x4004)
{
@ -296,55 +316,58 @@ void gt913_sound_device::command_w(u16 data)
}
else if (voicecmd == 0x6007)
{
logerror("voice %u volume %u rate %u\n", voicenum, (m_data[0] >> 8), m_data[0] & 0xff);
/*
only set a new volume level/rate if we haven't previously indicated the end of an envelope,
unless the new level also has the high bit set. otherwise, a timer irq may try to update the
normal envelope while other code is trying to force a note off
*/
const bool end = BIT(m_data[0], 15);
if (!voice.m_volume_end || end)
{
voice.m_volume_end = end;
// logerror("voice %u volume %u rate %u\n", voicenum, (m_data[0] >> 8), m_data[0] & 0xff);
voice.m_volume_target = (m_data[0] & 0x7f00) << 16;
/*
In addition to volume levels applying non-linearly, envelope rates
are also non-linear. Unfortunately, with the ctk-551's limited patch set and
lack of editing features, figuring out the correct behavior isn't easy.
This is essentially a rough estimate until a higher-end model (ctk-601 series, etc)
can be dumped and used for more detailed testing.
*/
const u8 x = m_data[0] & 0xff;
if (x >= 127)
voice.m_volume_rate = x << 21;
else if (x >= 63)
voice.m_volume_rate = x << 16;
else if (x >= 47)
voice.m_volume_rate = x << 14;
else if (x >= 31)
voice.m_volume_rate = x << 11;
else if (x >= 23)
voice.m_volume_rate = x << 9;
else if (x >= 15)
voice.m_volume_rate = x << 7;
else
voice.m_volume_rate = x << 5;
voice.m_volume_data = m_data[0];
voice.m_volume_target = (m_data[0] & 0x7f00) << 16;
// referenced from the SW-10 softsynth
u8 base = m_data[0] & 0xff;
u8 shift = base >> 5;
switch (shift)
{
case 0:
shift = base >> 2;
base &= 3;
break;
case 1:
shift = 8;
base &= 0x1f;
break;
default:
shift += 6;
base = (base & 0x1f) | 0x20;
break;
}
/*
this part is less certain - the overall rate needs adjusting based on
the sample rate difference between this and the softsynth.
it's probably not exact, but it sounds okay
*/
voice.m_volume_rate = (base * 3) << (shift + 5);
}
else if (voicecmd == 0x2028)
else if (voicecmd == 0x2028) // voice data read commands
{
/*
ctk551 issues this command and then reads the voice's current volume from data0
to determine if it's time to start the next part of the volume envelope or not.
data0 is used to determine if it's time to start the next part of the volume envelope or not
*/
m_data[0] = voice.m_enable ? (voice.m_volume_current >> 16) : 0;
m_data[0] = voice.m_volume_current >> 16;
/*
data1 is used to read consecutive output sample and detect zero crossings when
data1 is used to read consecutive output samples and detect zero crossings when
applying volume or expression changes to a MIDI channel
*/
m_data[1] = voice.m_sample;
}
else if (voicecmd == 0x6020)
{
/*
AP-10 sometimes issues this command, then clears the low byte of data0,
and then issues command 0x6007 with the result (to pause an envelope?)
*/
m_data[0] = voice.m_volume_data;
}
else
{
logerror("unknown sound write %04x (data: %04x %04x %04x)\n", data, m_data[0], m_data[1], m_data[2]);

View File

@ -51,6 +51,7 @@ private:
static const u8 exp_2_to_3[4];
static const s8 sample_7_to_8[128];
static const u16 volume_ramp[17];
struct voice_t
{
@ -66,15 +67,16 @@ private:
s16 m_sample, m_sample_next;
u8 m_exp;
u16 m_volume_data;
u32 m_volume_current, m_volume_target;
u32 m_volume_rate;
bool m_volume_end;
u8 m_balance[2];
u8 m_gain;
};
void mix_sample(voice_t& voice, s64& left, s64& right);
void update_envelope(voice_t& voice);
void update_sample(voice_t& voice);
voice_t m_voices[24];

View File

@ -1,10 +1,121 @@
// license:BSD-3-Clause
// copyright-holders:Devin Acker
/*
Casio CTK-551 keyboard (and related models)
Casio GT913-based keyboards and MIDI modules
Casio released several keyboard models with the same main board.
As usual, some of them were also rebranded by Radio Shack.
-------------------------------------------------------------------------------
Celviano AP-10 digital piano (1995)
Main board (JCM358-MA1M):
LSI301: CPU (Casio/NEC uPD912GF)
LSI302: DSP (Hitachi HG51B277FB)
LSI303: 8Mbit ROM (Macronix MX23C8100MC-12)
LSI304: 64kbit SRAM for CPU (Sanyo LC3564SM-85), battery backed
LSI305: 256kbit SRAM for DSP (Sanyo LC333832M-70)
LSI306: stereo DAC (NEC uPD6379GR)
X301: 24MHz crystal for CPU
X302: 16MHz ceramic for DSP
Service manual with schematics, pinouts, etc.:
https://revenant1.net/casio/manuals/upd91x/ap10.pdf
To access the test mode (not mentioned in the service manual):
Hold both pedals and "Transpose/Tune/MIDI" while turning on the keyboard, then release the button.
Afterwards, press one of these buttons:
- Transpose: LED test
- Effect: switch test (press all front panel buttons left to right)
- Piano: key test (press all keys left to right)
- E.Piano: ROM test
- Organ/Strings/Song: sound volume test
- Record/Start/Stop: stereo test
- Demo: MIDI loopback test
- Harpsichord: exit test mode
TODO: fix backup RAM getting re-initialized on every boot.
Depends on the power switch being implemented correctly - turning the power off
is supposed to trigger a NMI which updates the RAM checksum, but the NMI handler
always proceeds to fully start up the system as if the power is being turned on
-------------------------------------------------------------------------------
General MIDI modules (1996)
- GZ-30M
Basic model, small desktop module
No 5-pin MIDI jack, only mini-DIN for RS-232 or RS-422
- GZ-70SP
MIDI module built into a pair of speakers w/ karaoke mic input
Provides both standard MIDI and mini-DIN connectors
- WG-130
WaveBlaster-style PC daughterboard
WG-130 board:
LSI101: stereo DAC (NEC uPD6379GR)
LSI102: CPU (Casio GT913F)
LSI103: 16Mbit ROM (Casio GM16000N-C40)
LSI104: 64kbit SRAM (Sanyo LC3564SM-85)
LSI105: unpopulated, for DSP SRAM
LSI106: unpopulated, for DSP
X101: 30MHz crystal
X102: unpopulated, for DSP
All three of these apparently use the same mask ROM.
This ROM was also distributed as part of Casio's SW-10 softsynth for Windows,
which it released in early 1997 as part of the "LANA Lite" karaoke system.
http://web.archive.org/web/20011122112757/www.casio.co.jp/lanalite/LanaSw10.exe
The WG-130 (and possibly others) have unpopulated footprints for the same DSP
used in some keyboards (e.g. the CTK-601). The ROM does actually support
using the DSP if it's present, and responds to the same sysex message used to
enable reverb on the CTK-601 and similar models (F0 44 0E 09 0x F7).
Pulling CPU pin 53 (KI0/P24) low starts a ROM checksum test.
The result is indicated both by sound as well as output on pin 55 (KI2/P11).
More info and photos:
https://piano.tyonmage.com/casio/gz-30m.html
https://piano.tyonmage.com/casio/gz-70sp.html
http://www.yjfy.com/museum/sound/WG-130.htm
-------------------------------------------------------------------------------
CTK-601/611 / Concertmate 990 (1997)
Main board (JCM462-MA1M):
LSI1: CPU (Casio GT913F)
LSI2: DSP (Casio GD277F / Hitachi HG51B277FB)
LSI3: 16Mbit ROM (Macronix MX23C1610MC-12)
LSI4: 256kbit SRAM for CPU (Toshiba TC55257DFL-70L)
LSI5: 256kbit SRAM for DSP (same as LSI4)
LSI6: stereo DAC (NEC uPD6379GR)
X1: 30MHz crystal for CPU
X2: 20MHz ceramic for DSP
Display board (JCM462-LCD1M):
LSI401: LCD controller (Epson SED1278F2A)
Service manuals with schematics, pinouts, etc.:
https://revenant1.net/casio/manuals/upd91x/ctk601.pdf
https://revenant1.net/casio/manuals/upd91x/ctk611.pdf
To access the test mode (not mentioned in the service manual):
Hold the keypad 0 button while turning on the keyboard, then release the button.
"TST" will appear on the LCD. Afterwards, press one of these buttons:
- Keypad 0: switch test (press all front panel buttons in a specific order, generally left to right)
- Keypad 1: pedal and key test
- Keypad 2: ROM test
- Keypad 4/5/6: sound volume test
- Keypad 7/8: stereo test
- Keypad 9: MIDI loopback test
- Keypad +: power source test
- Cursor Left: LCD test (all segments at once)
- Cursor Right: LCD test (all segments individually)
- Cursor Down: power off
-------------------------------------------------------------------------------
CTK-551 (and related models)
- CTK-531, CTK-533 (1999)
Basic 61-key model
@ -13,24 +124,21 @@
- CTK-551, CTK-558, Radio Shack MD-1160 (2000)
Adds pitch wheel and different selection of demo songs
Main board (JCM456-MA1M):
Main board (JCM453-MA1M / JCM456-MA1M):
LSI1: CPU (Casio GT913F)
LSI2: 8Mbit ROM (OKI MSM538002E)
LSI3: LCD controller (HD44780 compatible)
May be either a Samsung KS0066U-10B or Epson SED1278F2A.
IC1: stereo DAC (NEC uPD6379GR)
X1: 30MHz ceramic
LSI1: CPU (Casio GT913F)
Custom chip based on H8/300 instruction set, built in peripheral controllers & sound generator
LSI2: 8Mbit ROM (OKI MSM538002E)
LSI3: LCD controller (HD44780 compatible)
May be either a Samsung KS0066U-10B or Epson SED1278F2A.
IC1: stereo DAC (NEC uPD6379GR)
CTK-541 service manual with schematics, pinouts, etc.:
https://revenant1.net/ctk541.pdf
Service manuals with schematics, pinouts, etc.:
https://revenant1.net/casio/manuals/upd91x/ctk531.pdf
https://revenant1.net/casio/manuals/upd91x/ctk541.pdf
To access the test mode (not mentioned in the service manual):
Hold the "Start/Stop" and keypad 0 buttons together when turning on the keyboard.
Afterwards, press one of these buttons:
"215dTEST" will appear on the LCD. Afterwards, press one of these buttons:
- Tone: LCD test (press repeatedly)
- Keypad 0: switch test (press all front panel buttons in a specific order, generally left to right)
- Keypad 1 or Rhythm: pedal and key test
@ -50,11 +158,14 @@
#include "bus/midi/midiinport.h"
#include "bus/midi/midioutport.h"
#include "cpu/h8/gt913.h"
#include "machine/nvram.h"
#include "video/hd44780.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "ap10.lh"
namespace {
class ctk551_state : public driver_device
@ -64,42 +175,102 @@ public:
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_lcdc(*this, "lcdc")
, m_inputs(*this, "IN%u", 0U)
, m_outputs(*this, "%02x.%d.%d", 0U, 0U, 0U)
, m_led_touch(*this, "led_touch")
, m_led_console(*this, "led_console_%d", 0U)
, m_led_power(*this, "led_power")
{
}
void ap10(machine_config& config);
void gz70sp(machine_config& config);
void ctk601(machine_config& config);
void ctk551(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); }
void init_ap10();
void init_gz70sp();
DECLARE_CUSTOM_INPUT_MEMBER(lcd_r) { return m_lcdc->db_r() >> 4; }
DECLARE_WRITE_LINE_MEMBER(lcd_w)
{
m_lcd_data = state << 4;
m_lcdc->db_w(m_lcd_data);
}
// some models have all 4 LCD bits wired to adjacent port bits, but some don't
// (and even those don't always have them wired the same way -
// in some cases they're not even all connected to the same port)
template <unsigned Bit>
DECLARE_CUSTOM_INPUT_MEMBER(lcd_bit_r) { return BIT(m_lcdc->db_r(), Bit); }
template <unsigned Bit>
DECLARE_WRITE_LINE_MEMBER(lcd_bit_w)
{
m_lcd_data = (m_lcd_data & ~(1 << Bit)) | (state << Bit);
m_lcdc->db_w(m_lcd_data);
}
// handle the 4-position mode switch
// some models treat this as 3 modes plus power off,
// while others have 4 modes and move power to a separate button instead
DECLARE_CUSTOM_INPUT_MEMBER(switch_r) { return m_switch; }
DECLARE_INPUT_CHANGED_MEMBER(switch_w);
DECLARE_INPUT_CHANGED_MEMBER(power_w);
DECLARE_INPUT_CHANGED_MEMBER(switch_power_w);
DECLARE_WRITE_LINE_MEMBER(inputs_w) { m_input_sel = state; }
DECLARE_CUSTOM_INPUT_MEMBER(inputs_r);
void dsp_data_w(uint8_t data);
void dsp_cmd_w(uint8_t cmd);
DECLARE_WRITE_LINE_MEMBER(led_touch_w) { m_led_touch = state; }
void led_console_w(uint8_t state);
DECLARE_WRITE_LINE_MEMBER(apo_w);
private:
void ap10_map(address_map& map);
void gz70sp_map(address_map& map);
void ctk601_map(address_map& map);
void ctk551_map(address_map& map);
void ap10_io_map(address_map& map);
void gz70sp_io_map(address_map& map);
void ctk551_io_map(address_map &map);
virtual void driver_start() override;
required_device<gt913_device> m_maincpu;
required_device<hd44780_device> m_lcdc;
optional_device<hd44780_device> m_lcdc;
optional_ioport_array<4> m_inputs;
output_finder<64, 8, 5> m_outputs;
output_finder<> m_led_touch;
output_finder<6> m_led_console;
output_finder<> m_led_power;
ioport_value m_switch{};
ioport_value m_input_sel{};
uint8_t m_lcd_data{};
uint32_t m_dsp_data{};
DECLARE_WRITE_LINE_MEMBER(render_w);
};
INPUT_CHANGED_MEMBER(ctk551_state::switch_w)
{
if (!oldval && newval)
m_switch = param;
}
INPUT_CHANGED_MEMBER(ctk551_state::power_w)
{
m_maincpu->set_input_line(INPUT_LINE_NMI, newval ? ASSERT_LINE : CLEAR_LINE);
}
INPUT_CHANGED_MEMBER(ctk551_state::switch_power_w)
{
if (!oldval && newval)
{
@ -112,12 +283,39 @@ INPUT_CHANGED_MEMBER(ctk551_state::switch_w)
}
}
CUSTOM_INPUT_MEMBER(ctk551_state::inputs_r)
{
uint8_t result = 0xff;
for (unsigned i = 0U; i < m_inputs.size(); i++)
if (!BIT(m_input_sel, i))
result &= m_inputs[i].read_safe(0xff);
return result;
}
void ctk551_state::dsp_data_w(uint8_t data)
{
m_dsp_data >>= 8;
m_dsp_data |= (data << 24);
}
void ctk551_state::dsp_cmd_w(uint8_t data)
{
logerror("dsp_cmd_w: addr = %02x, data = %08x\n", data, m_dsp_data);
}
void ctk551_state::led_console_w(uint8_t state)
{
for (unsigned i = 0; i < 6; i++)
m_led_console[i] = !BIT(state, i);
}
WRITE_LINE_MEMBER(ctk551_state::apo_w)
{
logerror("apo_w: %x\n", state);
/* auto power off - disable the LCD and speakers
the CPU will go to sleep until the power switch triggers a NMI */
if (!state)
if (!state && m_lcdc.found())
m_lcdc->reset();
m_led_power = state;
m_maincpu->set_output_gain(ALL_OUTPUTS, state ? 1.0 : 0.0);
@ -140,6 +338,56 @@ WRITE_LINE_MEMBER(ctk551_state::render_w)
}
}
void ctk551_state::ap10_map(address_map& map)
{
map(0x000000, 0x0fffff).rom().region("maincpu", 0).mirror(0x100000);
map(0x300000, 0x301fff).ram().share("nvram").mirror(0x07e000);
// TODO: DSP
map(0x380000, 0x380000).w(FUNC(ctk551_state::dsp_data_w));
map(0x380001, 0x380001).w(FUNC(ctk551_state::dsp_cmd_w));
map(0x380002, 0x380003).noprw();
map(0x380003, 0x380003).w(FUNC(ctk551_state::led_console_w));
}
void ctk551_state::gz70sp_map(address_map& map)
{
map(0x000000, 0x1fffff).rom().region("maincpu", 0);
map(0x300000, 0x301fff).ram().mirror(0x07e000);
map(0x380000, 0x380003).noprw(); // DSP is mapped here, but not actually present
}
void ctk551_state::ctk601_map(address_map& map)
{
map(0x000000, 0x1fffff).rom().region("maincpu", 0);
map(0x300000, 0x307fff).ram().mirror(0x078000);
// TODO: DSP
map(0x380000, 0x380000).w(FUNC(ctk551_state::dsp_data_w));
map(0x380001, 0x380001).w(FUNC(ctk551_state::dsp_cmd_w));
map(0x380002, 0x380003).noprw();
map(0x380002, 0x380003).portr("PB").portw("PA").umask16(0x00ff);
}
void ctk551_state::ctk551_map(address_map& map)
{
map(0x000000, 0x0fffff).rom().region("maincpu", 0).mirror(0x100000);
}
void ctk551_state::ap10_io_map(address_map& map)
{
map(h8_device::PORT_1, h8_device::PORT_1).portrw("P1").umask16(0x00ff);
map(h8_device::PORT_2, h8_device::PORT_3).noprw();
map(h8_device::ADC_0, h8_device::ADC_1).nopr();
}
void ctk551_state::gz70sp_io_map(address_map& map)
{
map(h8_device::PORT_1, h8_device::PORT_1).portrw("P1").umask16(0x00ff);
map(h8_device::PORT_2, h8_device::PORT_2).portrw("P2").umask16(0x00ff);
map(h8_device::PORT_3, h8_device::PORT_3).noprw();
map(h8_device::ADC_0, h8_device::ADC_1).nopr();
}
void ctk551_state::ctk551_io_map(address_map &map)
{
map(h8_device::PORT_1, h8_device::PORT_1).portr("P1_R").portw("P1_W").umask16(0x00ff);
@ -152,19 +400,106 @@ void ctk551_state::ctk551_io_map(address_map &map)
void ctk551_state::driver_start()
{
m_led_touch.resolve();
m_led_console.resolve();
m_led_power.resolve();
m_outputs.resolve();
m_switch = 0x2;
m_input_sel = 0xf;
save_item(NAME(m_switch));
save_item(NAME(m_input_sel));
save_item(NAME(m_lcd_data));
save_item(NAME(m_dsp_data));
}
void ctk551_state::ap10(machine_config& config)
{
// CPU
GT913(config, m_maincpu, 24_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_DATA, &ctk551_state::ap10_map);
m_maincpu->set_addrmap(AS_IO, &ctk551_state::ap10_io_map);
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
NVRAM(config, "nvram");
// TODO: DSP
// MIDI
auto& mdin(MIDI_PORT(config, "mdin"));
midiin_slot(mdin);
mdin.rxd_handler().set("maincpu:sci0", FUNC(h8_sci_device::rx_w));
auto& mdout(MIDI_PORT(config, "mdout"));
midiout_slot(mdout);
m_maincpu->subdevice<h8_sci_device>("sci0")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
config.set_default_layout(layout_ap10);
}
void ctk551_state::gz70sp(machine_config& config)
{
// CPU
GT913(config, m_maincpu, 30_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_DATA, &ctk551_state::gz70sp_map);
m_maincpu->set_addrmap(AS_IO, &ctk551_state::gz70sp_io_map);
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
// MIDI (sci0 for RS232/422, sci1 for standard MIDI)
auto& mdin(MIDI_PORT(config, "mdin"));
midiin_slot(mdin);
mdin.rxd_handler().set("maincpu:sci1", FUNC(h8_sci_device::rx_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
}
void ctk551_state::ctk601(machine_config& config)
{
// CPU
GT913(config, m_maincpu, 30_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_DATA, &ctk551_state::ctk601_map);
m_maincpu->set_addrmap(AS_IO, &ctk551_state::ctk551_io_map);
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
// TODO: DSP
// MIDI
auto& mdin(MIDI_PORT(config, "mdin"));
midiin_slot(mdin);
mdin.rxd_handler().set("maincpu:sci0", FUNC(h8_sci_device::rx_w));
auto& mdout(MIDI_PORT(config, "mdout"));
midiout_slot(mdout);
m_maincpu->subdevice<h8_sci_device>("sci0")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd));
// LCD
HD44780(config, m_lcdc, 0);
m_lcdc->set_lcd_size(2, 8);
auto& screen = SCREEN(config, "screen", SCREEN_TYPE_SVG);
screen.set_refresh_hz(60);
screen.set_size(1000, 424);
screen.set_visarea_full();
screen.screen_vblank().set(FUNC(ctk551_state::render_w));
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_switch = 0x8;
}
void ctk551_state::ctk551(machine_config &config)
{
// CPU
// 30MHz oscillator, divided down internally (otherwise the test mode's OK/NG sounds play at double speed)
GT913(config, m_maincpu, 30'000'000 / 2);
m_maincpu->set_addrmap(AS_DATA, &ctk551_state::ctk551_map);
m_maincpu->set_addrmap(AS_IO, &ctk551_state::ctk551_io_map);
m_maincpu->add_route(0, "lspeaker", 1.0);
m_maincpu->add_route(1, "rspeaker", 1.0);
@ -172,11 +507,11 @@ void ctk551_state::ctk551(machine_config &config)
// MIDI
auto &mdin(MIDI_PORT(config, "mdin"));
midiin_slot(mdin);
mdin.rxd_handler().set("maincpu:sci", FUNC(h8_sci_device::rx_w));
mdin.rxd_handler().set("maincpu:sci0", FUNC(h8_sci_device::rx_w));
auto &mdout(MIDI_PORT(config, "mdout"));
midiout_slot(mdout);
m_maincpu->subdevice<h8_sci_device>("sci")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd));
m_maincpu->subdevice<h8_sci_device>("sci0")->tx_handler().set(mdout, FUNC(midi_port_device::write_txd));
// LCD
HD44780(config, m_lcdc, 0);
@ -190,9 +525,189 @@ void ctk551_state::ctk551(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
m_switch = 0x2;
}
INPUT_PORTS_START(ctk551)
INPUT_PORTS_START(ap10)
PORT_START("maincpu:kbd:FI0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A0")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A0#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B0")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C1")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C1#")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D1")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D1#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E1")
PORT_START("maincpu:kbd:FI1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F1")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F1#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G1")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G1#")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A1")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A1#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B1")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2")
PORT_START("maincpu:kbd:FI2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2#")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E2")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2#")
PORT_START("maincpu:kbd:FI3")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B2")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3#")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3")
PORT_START("maincpu:kbd:FI4")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3#")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4")
PORT_START("maincpu:kbd:FI5")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4#")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E4")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4#")
PORT_START("maincpu:kbd:FI6")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B4")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5#")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5")
PORT_START("maincpu:kbd:FI7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5#")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6")
PORT_START("maincpu:kbd:FI8")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6#")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D6#")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E6")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F6#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G6#")
PORT_START("maincpu:kbd:FI9")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A6#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B6")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C7#")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D7")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D7#")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E7")
PORT_START("maincpu:kbd:FI10")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F7")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F7#")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G7")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G7#")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A7")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A7#")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B7")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C8")
PORT_START("maincpu:kbd:KI0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Transpose / Tune / MIDI") PORT_CODE(KEYCODE_1)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Digital Effect") PORT_CODE(KEYCODE_2)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Piano") PORT_CODE(KEYCODE_3)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("E. Piano") PORT_CODE(KEYCODE_4)
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("maincpu:kbd:KI1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Harpsichord") PORT_CODE(KEYCODE_5)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Pipe Organ") PORT_CODE(KEYCODE_6)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Strings") PORT_CODE(KEYCODE_7)
PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("maincpu:kbd:KI2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Song") PORT_CODE(KEYCODE_8)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Record") PORT_CODE(KEYCODE_9)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Start / Stop") PORT_CODE(KEYCODE_0)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Demo") PORT_CODE(KEYCODE_MINUS)
PORT_BIT( 0xf0, 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)
PORT_START("P1")
PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, apo_w)
PORT_BIT( 0x38, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Damper Pedal")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Soft/Sostenuto Pedal")
INPUT_PORTS_END
INPUT_PORTS_START(gz70sp)
PORT_START("maincpu:kbd:FI0")
PORT_START("maincpu:kbd:FI1")
PORT_START("maincpu:kbd:FI2")
PORT_START("maincpu:kbd:FI3")
PORT_START("maincpu:kbd:FI4")
PORT_START("maincpu:kbd:FI5")
PORT_START("maincpu:kbd:FI6")
PORT_START("maincpu:kbd:FI7")
PORT_START("maincpu:kbd:FI8")
PORT_START("maincpu:kbd:FI9")
PORT_START("maincpu:kbd:FI10")
PORT_START("maincpu:kbd:KI0")
PORT_START("maincpu:kbd:KI1")
PORT_START("maincpu:kbd:KI2")
PORT_START("P1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) // test mode output (1 = in progress / OK, 0 = error)
PORT_BIT( 0xfc, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("P2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POWER_ON ) PORT_NAME("Demo") PORT_TOGGLE
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
/*
this is actually a serial mode switch for the mini-DIN connector
PORT_CONFNAME( 0x0e, 0x0e, "Connection to Host" )
PORT_CONFSETTING( 0x06, "PC 1 (RS-232, 31250 baud)" )
PORT_CONFSETTING( 0x0a, "PC 2 (RS-232, 38400 baud)" )
PORT_CONFSETTING( 0x0c, "Mac (RS-422, 31250 baud)" )
PORT_CONFSETTING( 0x0e, "MIDI" )
*/
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("ROM Test")
PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
INPUT_PORTS_START(base_61key)
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#")
@ -270,16 +785,144 @@ INPUT_PORTS_START(ctk551)
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 )
INPUT_PORTS_END
INPUT_PORTS_START(ctk601)
PORT_INCLUDE(base_61key)
PORT_START("maincpu:kbd:FI8")
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("maincpu:kbd:FI9")
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("maincpu:kbd:FI10")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 3")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 1")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Pitch Bend Down")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Cursor Down / Enter")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad +") PORT_CODE(KEYCODE_PLUS_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone")
PORT_START("maincpu:kbd:KI0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 4")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 2")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Pitch Bend Up")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Start / Stop")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm")
PORT_START("maincpu:kbd:KI1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 5")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Step")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tempo Down")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Cursor Right")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Demo")
PORT_START("maincpu:kbd:KI2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Drum Pad 6")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Memory")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tempo Up")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Cursor Left")
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 1") PORT_CODE(KEYCODE_1_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Transpose / Tune / MIDI")
PORT_START("maincpu:kbd:VELOCITY")
PORT_BIT( 0x7f, 0x7f, IPT_POSITIONAL ) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0)
PORT_START("P1_R")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, lcd_bit_r<4>)
PORT_BIT( 0x06, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, lcd_bit_r<5>)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, lcd_bit_r<6>)
PORT_BIT( 0x60, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, lcd_bit_r<7>)
PORT_START("P1_W")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, lcd_bit_w<4>)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, apo_w)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, lcd_bit_w<5>)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, lcd_bit_w<6>)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) // DSP reset
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, lcd_bit_w<7>)
PORT_START("P2")
PORT_BIT( 0x07, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, e_w)
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_START("AN0")
PORT_CONFNAME( 0xff, 0x00, "Power Source" )
PORT_CONFSETTING( 0x00, "AC Adapter" )
PORT_CONFSETTING( 0xff, "Battery" )
PORT_START("AN1")
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
// DSP ports
PORT_START("PA")
PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(ctk551_state, inputs_w)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rs_w)
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", hd44780_device, rw_w)
PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("PB")
PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, inputs_r)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Pedal")
PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("SWITCH")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Full Range Chord)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x1)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Fingered)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x2)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Casio Chord)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x4)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Normal)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x8)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_NAME("Power") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, power_w, 0)
PORT_START("IN0")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(ctk551_state, switch_r)
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Intro")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Normal / Fill In")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Synchro / Ending")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Variation / Fill In")
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Touch Response")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Free Session")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Layer")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Split")
PORT_START("IN3")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Reverb")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Accomp Volume")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Synth")
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYPAD ) PORT_NAME("Mixer")
INPUT_PORTS_END
INPUT_PORTS_START(ctk551)
PORT_INCLUDE(base_61key)
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)
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("Touch Response")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Song Bank")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rhythm")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tone")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Touch Response")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Song Bank")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rhythm")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tone")
PORT_START("maincpu:kbd:FI9")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
@ -287,29 +930,29 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Accomp Volume")
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_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Accomp Volume")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Transpose / Tune / MIDI")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Chord Book")
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)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Play / Pause")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rewind")
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_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Play / Pause")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Rewind")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Start / Stop")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Sync / Fill In")
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")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Stop")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Down")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Volume Down")
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_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Right Hand On/Off")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Left Hand On/Off")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Fast Forward")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Stop")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tempo Down")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Volume Down")
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Tempo Up")
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Volume Up")
PORT_START("maincpu:kbd:KI1")
PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED )
@ -322,10 +965,10 @@ INPUT_PORTS_START(ctk551)
PORT_BIT( 0x7f, 0x7f, IPT_POSITIONAL ) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0)
PORT_START("SWITCH")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Power Off") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x1)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Normal") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x2)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Casio Chord") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x4)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fingered") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_w, 0x8)
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Power Off") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_power_w, 0x1)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Normal)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_power_w, 0x2)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Casio Chord)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_power_w, 0x4)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mode (Fingered)") PORT_CHANGED_MEMBER(DEVICE_SELF, ctk551_state, switch_power_w, 0x8)
PORT_START("P1_R")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
@ -353,19 +996,59 @@ INPUT_PORTS_START(ctk551)
PORT_START("AN1")
PORT_BIT( 0xff, 0x7f, IPT_PADDLE ) PORT_NAME("Pitch Wheel") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(0x00, 0xff)
INPUT_PORTS_END
ROM_START(ap10)
ROM_REGION(0x100000, "maincpu", 0)
ROM_LOAD16_WORD_SWAP("ap10.lsi303", 0x000000, 0x100000, CRC(39caa214) SHA1(3b484628c1e6f0ad7c11e2ec7eff664294f9ec83)) // MX23C8100MC-12CA27
ROM_END
ROM_START(gz70sp)
ROM_REGION(0x200000, "maincpu", 0)
ROM_LOAD("romsxgm.bin", 0x000000, 0x200000, CRC(c392cf89) SHA1(93ebe213ea7a085c67d88974ed39ac3e9bf8059b)) // from the SW-10 softsynth
ROM_END
ROM_START(ctk601)
ROM_REGION(0x200000, "maincpu", 0)
ROM_LOAD16_WORD_SWAP("ctk601.lsi3", 0x000000, 0x200000, CRC(23ae6ab1) SHA1(c1a8a1b9af19888360b56587c58602c26ad5029e)) // MX23C1610MC-12CA62
ROM_REGION(366949, "screen", 0)
ROM_LOAD("ctk601.svg", 0, 366949, CRC(7596bb55) SHA1(73f999675158e41b96ab9d2ee31edd19b8ab3e0e))
ROM_END
ROM_START(ctk551)
ROM_REGION(0x100000, "maincpu", 0)
ROM_LOAD16_WORD_SWAP("ctk551.lsi2", 0x000000, 0x100000, CRC(66fc34cd) SHA1(47e9559edc106132f8a83462ed17a6c5c3872157)) // MSM538002E-T6
ROM_REGION(285279, "screen", 0)
ROM_LOAD("ctk551lcd.svg", 0, 285279, CRC(1bb5da03) SHA1(a0cf22c6577c4ff0119ee7bb4ba8b487e23872d4))
ROM_END
void ctk551_state::init_ap10()
{
uint16_t* rom = (uint16_t*)memregion("maincpu")->base();
for (uint32_t addr = 0; addr < 0x80000; addr++)
rom[addr] = bitswap(rom[addr], 15, 14, 13, 10, 11, 12, 9, 8, 7, 6, 2, 3, 4, 5, 1, 0);
}
void ctk551_state::init_gz70sp()
{
/*
the version of this ROM bundled with the SW-10 softsynth has little endian samples, so byteswap them
(and stop at the end of sample data, not the end of the whole ROM, otherwise the ROM test fails)
*/
uint16_t* rom = (uint16_t*)memregion("maincpu")->base();
for (uint32_t addr = 0x2f000 >> 1; addr < 0x1fe8c2 >> 1; addr++)
rom[addr] = swapendian_int16(rom[addr]);
}
} // anonymous namespace
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
SYST( 2000, ctk551, 0, 0, ctk551, ctk551, ctk551_state, empty_init, "Casio", "CTK-551", MACHINE_SUPPORTS_SAVE )
// models with MACHINE_IMPERFECT_SOUND are missing DSP emulation
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
SYST( 1995, ap10, 0, 0, ap10, ap10, ctk551_state, init_ap10, "Casio", "Celviano AP-10", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK | MACHINE_IMPERFECT_SOUND)
SYST( 1996, gz70sp, 0, 0, gz70sp, gz70sp, ctk551_state, init_gz70sp, "Casio", "GZ-70SP", MACHINE_SUPPORTS_SAVE )
SYST( 1997, ctk601, 0, 0, ctk601, ctk601, ctk551_state, empty_init, "Casio", "CTK-601", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_SOUND)
SYST( 2000, ctk551, 0, 0, ctk551, ctk551, ctk551_state, empty_init, "Casio", "CTK-551", MACHINE_SUPPORTS_SAVE )

284
src/mame/layout/ap10.lay Normal file
View File

@ -0,0 +1,284 @@
<?xml version="1.0"?>
<!--
license:CC0
-->
<mamelayout version="2">
<!-- general grey backdrop -->
<element name="greyback">
<rect>
<bounds left="0" top="0" right="1" bottom="1" />
<color red="0.2" green="0.2" blue="0.2" />
</rect>
</element>
<!-- text elements -->
<element name="transpose"><text string="TRANSPOSE/" /></element>
<element name="tune_midi"><text string="TUNE/MIDI" /></element>
<element name="digital"><text string="DIGITAL" /></element>
<element name="effect"><text string="EFFECT" /></element>
<element name="chorus"><text string="CHORUS REVERB" align="1" /></element>
<element name="reverb2"><text string="REVERB 2" align="1" /></element>
<element name="reverb1"><text string="REVERB 1" align="1" /></element>
<element name="tone"><text string="TONE" /></element>
<element name="piano"><text string="PIANO" /></element>
<element name="epiano"><text string="E.PIANO" /></element>
<element name="harpsi"><text string="HARPSI" /></element>
<element name="chord"><text string="CHORD" /></element>
<element name="pipe"><text string="PIPE" /></element>
<element name="organ"><text string="ORGAN" /></element>
<element name="strings"><text string="STRINGS" /></element>
<element name="song"><text string="SONG" /></element>
<element name="songa"><text string="SONG A" /></element>
<element name="songb"><text string="SONG B" /></element>
<element name="record"><text string="RECORD" /></element>
<element name="start"><text string="START/" /></element>
<element name="stop"><text string="STOP" /></element>
<element name="demo"><text string="DEMO" /></element>
<element name="ap10"><text string="AP-10" /></element>
<!-- button primitives -->
<element name="button" defstate="0">
<disk><bounds x="0" y="0" width="21" height="21" /><color red="0.0" green="0.0" blue="0.0" /></disk>
<disk><bounds x="44" y="0" width="21" height="21" /><color red="0.0" green="0.0" blue="0.0" /></disk>
<rect><bounds x="11" y="0" width="43" height="21" /><color red="0.0" green="0.0" blue="0.0" /></rect>
<disk state="0"><bounds x="2" y="2" width="17" height="17" /><color red="0.3" green="0.3" blue="0.3" /></disk>
<disk state="0"><bounds x="46" y="2" width="17" height="17" /><color red="0.3" green="0.3" blue="0.3" /></disk>
<rect state="0"><bounds x="11" y="2" width="43" height="17" /><color red="0.3" green="0.3" blue="0.3" /></rect>
<disk state="1"><bounds x="2" y="2" width="17" height="17" /><color red="0.5" green="0.5" blue="0.5" /></disk>
<disk state="1"><bounds x="46" y="2" width="17" height="17" /><color red="0.5" green="0.5" blue="0.5" /></disk>
<rect state="1"><bounds x="11" y="2" width="43" height="17" /><color red="0.5" green="0.5" blue="0.5" /></rect>
</element>
<!-- LED primitive -->
<element name="led" defstate="0">
<disk state="0"><color red="0.4" green="0.3" blue="0.3" /></disk>
<disk state="1"><color red="1.0" green="0.1" blue="0.1" /></disk>
</element>
<!-- keyboard primitives -->
<element name="keyfill"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
<element name="whitekey" defstate="0">
<rect state="0"><bounds x="0" y="0" width="45" height="504" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="0" y="0" width="45" height="504" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-a0" defstate="0">
<rect state="0"><bounds x="0" y="0" width="66" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="0" y="0" width="66" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-l" defstate="0">
<rect state="0"><bounds x="0" y="0" width="45" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="0" y="0" width="45" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-m" defstate="0">
<rect state="0"><bounds x="13" y="0" width="53" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="13" y="0" width="53" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-lm" defstate="0">
<rect state="0"><bounds x="10" y="0" width="44" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="10" y="0" width="44" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-rm" defstate="0">
<rect state="0"><bounds x="22" y="0" width="44" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="22" y="0" width="44" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="whitekey-r" defstate="0">
<rect state="0"><bounds x="34" y="0" width="45" height="332" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="0"><bounds x="0" y="332" width="79" height="172" /><color red="1.0" green="1.0" blue="1.0" /></rect>
<rect state="1"><bounds x="34" y="0" width="45" height="332" /><color red="0.9" green="0.9" blue="0.9" /></rect>
<rect state="1"><bounds x="0" y="332" width="79" height="172" /><color red="0.9" green="0.9" blue="0.9" /></rect>
</element>
<element name="blackkey" defstate="0">
<rect state="0"><bounds x="0" y="0" width="44" height="324" /><color red="0.0" green="0.0" blue="0.0" /></rect>
<rect state="0"><bounds x="4" y="0" width="36" height="320" /><color red="0.1" green="0.1" blue="0.1" /></rect>
<rect state="1"><bounds x="0" y="0" width="44" height="324" /><color red="0.1" green="0.1" blue="0.1" /></rect>
<rect state="1"><bounds x="4" y="0" width="36" height="320" /><color red="0.1" green="0.1" blue="0.1" /></rect>
</element>
<!-- button group -->
<group name="buttons">
<bounds x="0" y="0" width="4428" height="300" />
<element ref="transpose"><bounds xc="80" y="40" width="200" height="40"/></element>
<element ref="tune_midi"><bounds xc="80" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI0" inputmask="0x1"><bounds xc="80" y="128" width="160" height="48"/></element>
<element ref="digital"><bounds xc="280" y="40" width="180" height="40"/></element>
<element ref="effect"><bounds xc="280" y="80" width="180" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI0" inputmask="0x2"><bounds xc="280" y="128" width="160" height="48"/></element>
<element ref="led" name="led_console_0"><bounds xc="400" y="00" width="40" height="40" /></element>
<element ref="chorus"><bounds x="440" y="0" width="300" height="40"/></element>
<element ref="led" name="led_console_1"><bounds xc="400" y="64" width="40" height="40" /></element>
<element ref="reverb2"><bounds x="440" y="64" width="300" height="40"/></element>
<element ref="led" name="led_console_2"><bounds xc="400" y="128" width="40" height="40" /></element>
<element ref="reverb1"><bounds x="440" y="128" width="300" height="40"/></element>
<element ref="piano"><bounds xc="880" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI0" inputmask="0x4"><bounds xc="880" y="128" width="160" height="48"/></element>
<element ref="epiano"><bounds xc="1080" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI0" inputmask="0x8"><bounds xc="1080" y="128" width="160" height="48"/></element>
<element ref="harpsi"><bounds xc="1280" y="40" width="200" height="40"/></element>
<element ref="chord"><bounds xc="1280" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI1" inputmask="0x1"><bounds xc="1280" y="128" width="160" height="48"/></element>
<element ref="pipe"><bounds xc="1480" y="40" width="200" height="40"/></element>
<element ref="organ"><bounds xc="1480" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI1" inputmask="0x2"><bounds xc="1480" y="128" width="160" height="48"/></element>
<element ref="strings"><bounds xc="1680" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI1" inputmask="0x4"><bounds xc="1680" y="128" width="160" height="48"/></element>
<element ref="led" name="led_console_3"><bounds xc="1980" y="28" width="40" height="40" /></element>
<element ref="songa"><bounds xc="2080" y="28" width="200" height="40"/></element>
<element ref="led" name="led_console_4"><bounds xc="1980" y="80" width="40" height="40" /></element>
<element ref="songb"><bounds xc="2080" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI2" inputmask="0x1"><bounds xc="2080" y="128" width="160" height="48"/></element>
<element ref="led" name="led_console_5"><bounds xc="2280" y="28" width="40" height="40" /></element>
<element ref="record"><bounds xc="2280" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI2" inputmask="0x2"><bounds xc="2280" y="128" width="160" height="48"/></element>
<element ref="start"><bounds xc="2480" y="40" width="200" height="40"/></element>
<element ref="stop"><bounds xc="2480" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI2" inputmask="0x4"><bounds xc="2480" y="128" width="160" height="48"/></element>
<element ref="demo"><bounds xc="2880" y="80" width="200" height="40"/></element>
<element ref="button" inputtag="maincpu:kbd:KI2" inputmask="0x8"><bounds xc="2880" y="128" width="160" height="48"/></element>
</group>
<!-- keyboard group -->
<group name="keyboard">
<element ref="keyfill"><bounds x="72" y="98" width="4284" height="524" /></element>
<!-- octave 0 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI0" inputmask="0x02"><bounds x="151" y="108" width="44" height="324" /></element>
<element ref="whitekey-a0" inputtag="maincpu:kbd:FI0" inputmask="0x01"><bounds x="82" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI0" inputmask="0x04"><bounds x="164" y="108" width="79" height="504" /></element>
<!-- octave 1 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI0" inputmask="0x10"><bounds x="294" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI0" inputmask="0x40"><bounds x="397" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI1" inputmask="0x02"><bounds x="537" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI1" inputmask="0x08"><bounds x="631" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI1" inputmask="0x20"><bounds x="725" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI0" inputmask="0x08"><bounds x="246" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI0" inputmask="0x20"><bounds x="328" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI0" inputmask="0x80"><bounds x="410" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI1" inputmask="0x01"><bounds x="492" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI1" inputmask="0x04"><bounds x="574" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI1" inputmask="0x10"><bounds x="656" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI1" inputmask="0x40"><bounds x="738" y="108" width="79" height="504" /></element>
<!-- octave 2 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI2" inputmask="0x01"><bounds x="868" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI2" inputmask="0x04"><bounds x="971" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI2" inputmask="0x20"><bounds x="1111" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI2" inputmask="0x80"><bounds x="1205" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI3" inputmask="0x02"><bounds x="1299" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI1" inputmask="0x80"><bounds x="820" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI2" inputmask="0x02"><bounds x="902" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI2" inputmask="0x08"><bounds x="984" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI2" inputmask="0x10"><bounds x="1066" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI2" inputmask="0x40"><bounds x="1148" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI3" inputmask="0x01"><bounds x="1230" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI3" inputmask="0x04"><bounds x="1312" y="108" width="79" height="504" /></element>
<!-- octave 3 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI3" inputmask="0x10"><bounds x="1442" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI3" inputmask="0x40"><bounds x="1545" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI4" inputmask="0x02"><bounds x="1685" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI4" inputmask="0x08"><bounds x="1779" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI4" inputmask="0x20"><bounds x="1873" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI3" inputmask="0x08"><bounds x="1394" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI3" inputmask="0x20"><bounds x="1476" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI3" inputmask="0x80"><bounds x="1558" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI4" inputmask="0x01"><bounds x="1640" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI4" inputmask="0x04"><bounds x="1722" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI4" inputmask="0x10"><bounds x="1804" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI4" inputmask="0x40"><bounds x="1886" y="108" width="79" height="504" /></element>
<!-- octave 4 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI5" inputmask="0x01"><bounds x="2016" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI5" inputmask="0x04"><bounds x="2119" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI5" inputmask="0x20"><bounds x="2259" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI5" inputmask="0x80"><bounds x="2353" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI6" inputmask="0x02"><bounds x="2447" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI4" inputmask="0x80"><bounds x="1968" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI5" inputmask="0x02"><bounds x="2050" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI5" inputmask="0x08"><bounds x="2132" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI5" inputmask="0x10"><bounds x="2214" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI5" inputmask="0x40"><bounds x="2296" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI6" inputmask="0x01"><bounds x="2378" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI6" inputmask="0x04"><bounds x="2460" y="108" width="79" height="504" /></element>
<!-- octave 5 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI6" inputmask="0x10"><bounds x="2590" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI6" inputmask="0x40"><bounds x="2693" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI7" inputmask="0x02"><bounds x="2833" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI7" inputmask="0x08"><bounds x="2927" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI7" inputmask="0x20"><bounds x="3021" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI6" inputmask="0x08"><bounds x="2542" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI6" inputmask="0x20"><bounds x="2624" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI6" inputmask="0x80"><bounds x="2706" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI7" inputmask="0x01"><bounds x="2788" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI7" inputmask="0x04"><bounds x="2870" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI7" inputmask="0x10"><bounds x="2952" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI7" inputmask="0x40"><bounds x="3034" y="108" width="79" height="504" /></element>
<!-- octave 6 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI8" inputmask="0x01"><bounds x="3164" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI8" inputmask="0x04"><bounds x="3267" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI8" inputmask="0x20"><bounds x="3407" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI8" inputmask="0x80"><bounds x="3501" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI9" inputmask="0x02"><bounds x="3595" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI7" inputmask="0x80"><bounds x="3116" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI8" inputmask="0x02"><bounds x="3198" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI8" inputmask="0x08"><bounds x="3280" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI8" inputmask="0x10"><bounds x="3362" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI8" inputmask="0x40"><bounds x="3444" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI9" inputmask="0x01"><bounds x="3526" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI9" inputmask="0x04"><bounds x="3608" y="108" width="79" height="504" /></element>
<!-- octave 7 -->
<element ref="blackkey" inputtag="maincpu:kbd:FI9" inputmask="0x10"><bounds x="3738" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI9" inputmask="0x40"><bounds x="3841" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI10" inputmask="0x02"><bounds x="3981" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI10" inputmask="0x08"><bounds x="4075" y="108" width="44" height="324" /></element>
<element ref="blackkey" inputtag="maincpu:kbd:FI10" inputmask="0x20"><bounds x="4169" y="108" width="44" height="324" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI9" inputmask="0x08"><bounds x="3690" y="108" width="79" height="504" /></element>
<element ref="whitekey-m" inputtag="maincpu:kbd:FI9" inputmask="0x20"><bounds x="3772" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI9" inputmask="0x80"><bounds x="3854" y="108" width="79" height="504" /></element>
<element ref="whitekey-l" inputtag="maincpu:kbd:FI10" inputmask="0x01"><bounds x="3936" y="108" width="79" height="504" /></element>
<element ref="whitekey-lm" inputtag="maincpu:kbd:FI10" inputmask="0x04"><bounds x="4018" y="108" width="79" height="504" /></element>
<element ref="whitekey-rm" inputtag="maincpu:kbd:FI10" inputmask="0x10"><bounds x="4100" y="108" width="79" height="504" /></element>
<element ref="whitekey-r" inputtag="maincpu:kbd:FI10" inputmask="0x40"><bounds x="4182" y="108" width="79" height="504" /></element>
<!-- final key -->
<element ref="whitekey" inputtag="maincpu:kbd:FI10" inputmask="0x80"><bounds x="4264" y="108" width="79" height="504" /></element>
</group>
<view name="Keyboard">
<!-- overall background -->
<element ref="greyback"><bounds x="0" y="0" width="4428" height="824" /></element>
<!-- buttons -->
<group ref="buttons"><bounds x="725" y="80" width="4428" height="300" /></group>
<!-- keyboard -->
<group ref="keyboard"><bounds x="72" y="294" width="4284" height="524" /></group>
</view>
</mamelayout>

View File

@ -11661,7 +11661,10 @@ ct486 // 1993? 486 with CS4031
megatrix
@source:casio/ctk551.cpp
ap10 //
ctk551 //
ctk601 //
gz70sp //
@source:casio/ctk2000.cpp
ctk2100 //