diff options
Diffstat (limited to 'src/mame/casio/ctk2000.cpp')
-rw-r--r-- | src/mame/casio/ctk2000.cpp | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/src/mame/casio/ctk2000.cpp b/src/mame/casio/ctk2000.cpp new file mode 100644 index 00000000000..d0320506527 --- /dev/null +++ b/src/mame/casio/ctk2000.cpp @@ -0,0 +1,300 @@ +// license:BSD-3-Clause +// copyright-holders:Devin Acker +/* + Casio CTK-2000 keyboard (and related models) + + - CTK-2000 (2008) + Basic 61-key model + - CTK-3000 + Adds velocity-sensitive keys and pitch wheel + - CTK-2100 (2009) + More flexible sampling feature, lesson buttons double as voice/drum pads + (based on CTK-2000, not 3000) + + Main board (M800-MDA1): + + IC1: CPU (NEC uPD800468) + Custom chip (ARM-based), built in peripheral controllers & sound generator + + LSI2: 16Mbit ROM (OKI MR27T1602L) + + Console PCB (M800-CNA): + + IC401: LCD controller (Sitronix ST7066U-0A, HD44780 compatible) + + CTK-2000 service manual with schematics, pinouts, etc.: + https://www.manualslib.com/manual/933451/Casio-Ctk-2000.html + + */ + +#include "emu.h" + +#include "cpu/arm7/upd800468.h" +#include "video/hd44780.h" +#include "emupal.h" +#include "screen.h" + +namespace { + +class ctk2000_state : public driver_device +{ +public: + ctk2000_state(machine_config const &mconfig, device_type type, char const *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_lcdc(*this, "lcdc") + { + } + + void ctk2000(machine_config &config); + + ioport_value lcd_r() { return m_lcdc->db_r() >> 4; } + void lcd_w(int state) { m_lcdc->db_w(state << 4); } + + void apo_w(int state); + +private: + void ctk2000_map(address_map &map) ATTR_COLD; + + virtual void driver_start() override; + virtual void driver_reset() override; + + HD44780_PIXEL_UPDATE(lcd_update); + void palette_init(palette_device &palette); + + required_device<upd800468_device> m_maincpu; + required_device<hd44780_device> m_lcdc; +}; + +void ctk2000_state::apo_w(int state) +{ + logerror("apo_w: %x\n", state); + /* TODO: when 0, this should turn off the LCD, speakers, etc. */ +} + +HD44780_PIXEL_UPDATE(ctk2000_state::lcd_update) +{ + if (x < 6 && y < 8 && line < 2 && pos < 8) + bitmap.pix(line * 8 + y, pos * 6 + x) = state; +} + +void ctk2000_state::palette_init(palette_device &palette) +{ + palette.set_pen_color(0, rgb_t(255, 255, 255)); + palette.set_pen_color(1, rgb_t(0, 0, 0)); +} + +void ctk2000_state::ctk2000_map(address_map &map) +{ + // ROM is based at 0x18000000, but needs to be mirrored to the beginning of memory in order to boot + map(0x00000000, 0x001fffff).rom().mirror(0x18e00000); +} + +void ctk2000_state::driver_start() +{ +} + +void ctk2000_state::driver_reset() +{ +} + +void ctk2000_state::ctk2000(machine_config &config) +{ + // CPU + UPD800468(config, m_maincpu, 48'000'000); + m_maincpu->set_addrmap(AS_PROGRAM, &ctk2000_state::ctk2000_map); + m_maincpu->port_in_cb<2>().set_ioport("P2_R"); + m_maincpu->port_out_cb<2>().set_ioport("P2_W"); + m_maincpu->port_out_cb<3>().set_ioport("P3"); + // ADCs 0, 5, 6, 7 are connected to the mic input + // ADC 4 is connected to the pitch wheel (for ctk3000) + m_maincpu->adc_cb<1>().set_ioport("AIN1"); + m_maincpu->adc_cb<2>().set_ioport("AIN2"); + m_maincpu->adc_cb<3>().set_ioport("AIN3"); + + // LCD + HD44780(config, m_lcdc, 270'000); // TODO: Wrong device type, should be ST7066U_0A; clock not measured, datasheet typical clock used + m_lcdc->set_lcd_size(2, 8); + m_lcdc->set_pixel_update_cb(FUNC(ctk2000_state::lcd_update)); + + // screen (for testing only) + // TODO: the actual LCD with custom segments + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); + screen.set_refresh_hz(60); + screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ + screen.set_screen_update("lcdc", FUNC(hd44780_device::screen_update)); + screen.set_size(6 * 8, 8 * 2); + screen.set_visarea_full(); + screen.set_palette("palette"); + + PALETTE(config, "palette", FUNC(ctk2000_state::palette_init), 2); +} + +INPUT_PORTS_START(ctk2100) + PORT_START("maincpu:kbd:FI0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C2 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_CS2 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_D2 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_DS2 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_E2 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_F2 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_FS2 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_G2 + + PORT_START("maincpu:kbd:FI1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_GS2 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_A2 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_AS2 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_B2 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C3 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_CS3 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_D3 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_DS3 + + PORT_START("maincpu:kbd:FI2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_E3 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_F3 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_FS3 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_G3 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_GS3 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_A3 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_AS3 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_B3 + + PORT_START("maincpu:kbd:FI3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C4 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_CS4 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_D4 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_DS4 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_E4 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_F4 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_FS4 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_G4 + + PORT_START("maincpu:kbd:FI4") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_GS4 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_A4 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_AS4 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_B4 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C5 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_CS5 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_D5 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_DS5 + + PORT_START("maincpu:kbd:FI5") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_E5 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_F5 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_FS5 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_G5 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_GS5 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_A5 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_AS5 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_B5 + + PORT_START("maincpu:kbd:FI6") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C6 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_CS6 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_D6 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_DS6 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_E6 + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_F6 + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_FS6 + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_G6 + + PORT_START("maincpu:kbd:FI7") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_GS6 + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_A6 + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_AS6 + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_B6 + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_GM_C7 + PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("maincpu:kbd:FI8") + PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("maincpu:kbd:FI9") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_MINUS_PAD) + + PORT_START("maincpu:kbd:FI10") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Keypad +") PORT_CODE(KEYCODE_PLUS_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 5 / Auto") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Synchro / Ending / Pause") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Accomp On/Off / Chord / Part Select") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Sampling") + + PORT_START("maincpu:kbd:KI0") + PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("maincpu:kbd:KI1") + // "song bank" and "tone" seem to be swapped in the schematic + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Song Bank") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tone") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Up") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Set Select / Music Challenge") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 4 / Next") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Play / Stop") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Metronome") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Intro / Repeat") + + PORT_START("maincpu:kbd:KI2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Rhythm") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Tempo Down") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 2 / Watch") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 3 / Remember") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Voice Pad 1 / Listen") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Normal / Fill In / Rewind") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Function") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Variation / Fill In / Fast Forward") + + PORT_START("P2_R") + PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(FUNC(ctk2000_state::lcd_r)) + PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("P2_W") + PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(FUNC(ctk2000_state::lcd_w)) + PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", FUNC(hd44780_device::e_w)) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(FUNC(ctk2000_state::apo_w)) + + PORT_START("P3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", FUNC(hd44780_device::rw_w)) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("lcdc", FUNC(hd44780_device::rs_w)) + PORT_BIT( 0xf8, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("AIN1") + PORT_BIT( 0x3ff, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Pedal") + + PORT_START("AIN2") + PORT_CONFNAME( 0x3ff, 0x000, "Power Source" ) + PORT_CONFSETTING( 0x000, "AC Adapter" ) + PORT_CONFSETTING( 0x3ff, "Battery" ) + + PORT_START("AIN3") + PORT_BIT( 0x3ff, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("AIN2", 0x3ff, EQUALS, 0) + PORT_CONFNAME( 0x3ff, 0x3ff, "Battery Level" ) PORT_CONDITION("AIN2", 0x3ff, NOTEQUALS, 0) + // values here are somewhat arbitrary - ctk2100 only checks if the value is above/below a certain threshold + PORT_CONFSETTING( 0x100, "Low" ) + PORT_CONFSETTING( 0x3ff, "Normal" ) + +INPUT_PORTS_END + +ROM_START(ctk2100) + ROM_REGION(0x200000, "maincpu", 0) + ROM_LOAD("ctk2100.ic2", 0x000000, 0x200000, CRC(daf62f81) SHA1(4edc76ea04b59090d02646d92f9fc635a43140e9)) +ROM_END + +} // anonymous namespace + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +SYST( 2009, ctk2100, 0, 0, ctk2000, ctk2100, ctk2000_state, empty_init, "Casio", "CTK-2100", MACHINE_NO_SOUND | MACHINE_NODEVICE_MICROPHONE | MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) |