From 3c0b5b0ef2b33dc4d2e3218b198c0ceca257d0ab Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Fri, 8 May 2020 13:41:37 +0200 Subject: [PATCH] fp6000: Rewrite driver - Add and hook up interrupt controller and timer - Add keyboard support (HLE) - Clean up and improve graphics handling - Add initial cassette support (not working) - Add centronics printer support - Add beeper - More info to dip switches --- scripts/target/mame/mess.lua | 2 + src/mame/drivers/fp6000.cpp | 670 ++++++++++++++++++++------------ src/mame/machine/fp6000_kbd.cpp | 314 +++++++++++++++ src/mame/machine/fp6000_kbd.h | 65 ++++ 4 files changed, 810 insertions(+), 241 deletions(-) create mode 100644 src/mame/machine/fp6000_kbd.cpp create mode 100644 src/mame/machine/fp6000_kbd.h diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index b9e10d8c1ab..c871902fe45 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -1901,6 +1901,8 @@ files { MAME_DIR .. "src/mame/drivers/fp200.cpp", MAME_DIR .. "src/mame/drivers/fp1100.cpp", MAME_DIR .. "src/mame/drivers/fp6000.cpp", + MAME_DIR .. "src/mame/machine/fp6000_kbd.cpp", + MAME_DIR .. "src/mame/machine/fp6000_kbd.h", MAME_DIR .. "src/mame/drivers/ht6000.cpp", MAME_DIR .. "src/mame/drivers/pb1000.cpp", MAME_DIR .. "src/mame/drivers/pv1000.cpp", diff --git a/src/mame/drivers/fp6000.cpp b/src/mame/drivers/fp6000.cpp index 7c30866c595..8b771175d82 100644 --- a/src/mame/drivers/fp6000.cpp +++ b/src/mame/drivers/fp6000.cpp @@ -1,278 +1,282 @@ -// license:BSD-3-Clause -// copyright-holders:Angelo Salese +// license: BSD-3-Clause +// copyright-holders: Angelo Salese, Dirk Best /*************************************************************************** Casio FP-6000 - preliminary driver by Angelo Salese - TODO: - - keyboard; - - fdc / cmt; + - Fix cassette + - Floppy/HDD + - Printer - gvram color pen is a rather crude guess (the layer is monochrome on BASIC?); - everything else - Debug trick for the keyboard: - - bp 0xfc93e, ip+=2 then define al = ASCII code - ****************************************************************************/ #include "emu.h" #include "cpu/i86/i86.h" +#include "machine/pic8259.h" +#include "machine/pit8253.h" #include "video/mc6845.h" +#include "sound/spkrdev.h" +#include "bus/centronics/ctronics.h" +#include "machine/fp6000_kbd.h" +#include "imagedev/cassette.h" #include "emupal.h" #include "screen.h" +#include "speaker.h" +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + class fp6000_state : public driver_device { public: fp6000_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_gvram(*this, "gvram"), - m_vram(*this, "vram"), m_maincpu(*this, "maincpu"), + m_pic(*this, "pic"), + m_pit(*this, "pit"), m_crtc(*this, "crtc"), m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette") + m_palette(*this, "palette"), + m_speaker(*this, "speaker"), + m_cassette(*this, "cassette"), + m_centronics(*this, "centronics"), + m_gvram(*this, "gvram"), + m_vram(*this, "vram"), + m_pcg(*this, "pcg") { } void fp6000(machine_config &config); -private: - uint8_t *m_char_rom; - required_shared_ptr m_gvram; - required_shared_ptr m_vram; - uint8_t m_crtc_vreg[0x100],m_crtc_index; - - struct { - uint16_t cmd; - }m_key; - DECLARE_READ8_MEMBER(fp6000_pcg_r); - DECLARE_WRITE8_MEMBER(fp6000_pcg_w); - DECLARE_WRITE8_MEMBER(fp6000_6845_address_w); - DECLARE_WRITE8_MEMBER(fp6000_6845_data_w); - DECLARE_READ8_MEMBER(fp6000_key_r); - DECLARE_WRITE8_MEMBER(fp6000_key_w); - DECLARE_READ16_MEMBER(unk_r); - DECLARE_READ16_MEMBER(ex_board_r); - DECLARE_READ16_MEMBER(pit_r); +protected: virtual void machine_start() override; virtual void machine_reset() override; - virtual void video_start() override; - uint32_t screen_update_fp6000(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + +private: required_device m_maincpu; + required_device m_pic; + required_device m_pit; required_devicem_crtc; required_device m_gfxdecode; required_device m_palette; + required_device m_speaker; + required_device m_cassette; + required_device m_centronics; + + required_shared_ptr m_gvram; + required_shared_ptr m_vram; + required_shared_ptr m_pcg; + void fp6000_io(address_map &map); void fp6000_map(address_map &map); + + emu_timer *m_pit_timer; + void pit_timer0_w(int state); + TIMER_CALLBACK_MEMBER(pit_timer0_clear); + void pit_timer2_w(int state); + + uint8_t port_08_r(); + void port_08_w(uint8_t data); + uint8_t port_09_r(); + void port_09_w(uint8_t data); + void port_0a_w(uint8_t data); + uint8_t port_0b_r(); + void port_0b_w(uint8_t data); + uint8_t port_0c_r(); + void port_0c_w(uint8_t data); + uint8_t port_0d_r(); + void port_0d_w(uint8_t data); + uint8_t port_0e_r(); + uint8_t port_0f_r(); + void port_0f_w(uint8_t data); + + MC6845_UPDATE_ROW(crtc_update_row); + DECLARE_READ16_MEMBER(unk_r); + + void centronics_busy_w(int state) { m_centronics_busy = state; }; + void centronics_fault_w(int state) { m_centronics_fault = state; }; + void centronics_perror_w(int state) { m_centronics_perror = state; }; + + uint8_t m_port_0a; + + int m_centronics_busy; + int m_centronics_fault; + int m_centronics_perror; }; -void fp6000_state::video_start() -{ -} -#define mc6845_h_char_total (m_crtc_vreg[0]) -#define mc6845_h_display (m_crtc_vreg[1]) -#define mc6845_h_sync_pos (m_crtc_vreg[2]) -#define mc6845_sync_width (m_crtc_vreg[3]) -#define mc6845_v_char_total (m_crtc_vreg[4]) -#define mc6845_v_total_adj (m_crtc_vreg[5]) -#define mc6845_v_display (m_crtc_vreg[6]) -#define mc6845_v_sync_pos (m_crtc_vreg[7]) -#define mc6845_mode_ctrl (m_crtc_vreg[8]) -#define mc6845_tile_height (m_crtc_vreg[9]+1) -#define mc6845_cursor_y_start (m_crtc_vreg[0x0a]) -#define mc6845_cursor_y_end (m_crtc_vreg[0x0b]) -#define mc6845_start_addr (((m_crtc_vreg[0x0c]<<8) & 0x3f00) | (m_crtc_vreg[0x0d] & 0xff)) -#define mc6845_cursor_addr (((m_crtc_vreg[0x0e]<<8) & 0x3f00) | (m_crtc_vreg[0x0f] & 0xff)) -#define mc6845_light_pen_addr (((m_crtc_vreg[0x10]<<8) & 0x3f00) | (m_crtc_vreg[0x11] & 0xff)) -#define mc6845_update_addr (((m_crtc_vreg[0x12]<<8) & 0x3f00) | (m_crtc_vreg[0x13] & 0xff)) - - -uint32_t fp6000_state::screen_update_fp6000(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int x,y; - int xi,yi; - uint8_t *gfx_rom = memregion("pcg")->base(); - uint32_t count; - - count = 0; - - for(y=0;y<400;y++) - { - for(x=0;x<640/4;x++) - { - for(xi=0;xi<4;xi++) - { - int dot = (m_gvram[count] >> (12-xi*4)) & 0xf; - - if(y < 400 && x*4+xi < 640) /* TODO: safety check */ - bitmap.pix16(y, x*4+xi) = m_palette->pen(dot); - } - - count++; - } - } - - for(y=0;y> 8; - int pen; - - for(yi=0;yi> (7-xi) & 1) ? color : -1; - - if(pen != -1) - if(y*mc6845_tile_height < 400 && x*8+xi < 640) /* TODO: safety check */ - bitmap.pix16(y*mc6845_tile_height+yi, x*8+xi) = m_palette->pen(pen); - } - } - } - } - - /* quick and dirty way to do the cursor */ - for(yi=0;yipen(7); - } - } - } - - return 0; -} - -READ8_MEMBER(fp6000_state::fp6000_pcg_r) -{ - return m_char_rom[offset]; -} - -WRITE8_MEMBER(fp6000_state::fp6000_pcg_w) -{ - m_char_rom[offset] = data; - m_gfxdecode->gfx(0)->mark_dirty(offset >> 4); -} - -WRITE8_MEMBER(fp6000_state::fp6000_6845_address_w) -{ - m_crtc_index = data; - m_crtc->address_w(data); -} - -WRITE8_MEMBER(fp6000_state::fp6000_6845_data_w) -{ - m_crtc_vreg[m_crtc_index] = data; - m_crtc->register_w(data); -} +//************************************************************************** +// ADDRESS MAPS +//************************************************************************** void fp6000_state::fp6000_map(address_map &map) { map.unmap_value_high(); map(0x00000, 0xbffff).ram(); - map(0xc0000, 0xdffff).ram().share("gvram");//gvram + map(0xc0000, 0xdffff).ram().share("gvram"); map(0xe0000, 0xe0fff).ram().share("vram"); - map(0xe7000, 0xe7fff).rw(FUNC(fp6000_state::fp6000_pcg_r), FUNC(fp6000_state::fp6000_pcg_w)); + map(0xe7000, 0xe7fff).ram().share("pcg"); map(0xf0000, 0xfffff).rom().region("ipl", 0); } -/* Hack until I understand what UART is this one ... */ -READ8_MEMBER(fp6000_state::fp6000_key_r) -{ - if(offset) - { - switch(m_key.cmd) - { - case 0x7e15: return 3; - case 0x1b15: return 1; - case 0x2415: return 0; - default: printf("%04x\n",m_key.cmd); - } - return 0; - } - - return 0x40; -} - -WRITE8_MEMBER(fp6000_state::fp6000_key_w) -{ - if(offset) - m_key.cmd = (data & 0xff) | (m_key.cmd << 8); - else - m_key.cmd = (data << 8) | (m_key.cmd & 0xff); -} - -READ16_MEMBER(fp6000_state::unk_r) -{ - return 0x40; -} - -READ16_MEMBER(fp6000_state::ex_board_r) -{ - return 0xffff; -} - -READ16_MEMBER(fp6000_state::pit_r) -{ - return machine().rand(); -} - void fp6000_state::fp6000_io(address_map &map) { map.unmap_value_high(); - map(0x08, 0x09).r(FUNC(fp6000_state::ex_board_r)); // BIOS of some sort ... - map(0x0a, 0x0b).portr("DSW"); // installed RAM id? - map(0x10, 0x11).nopr(); - map(0x20, 0x23).rw(FUNC(fp6000_state::fp6000_key_r), FUNC(fp6000_state::fp6000_key_w)).umask16(0x00ff); - map(0x38, 0x39).r(FUNC(fp6000_state::pit_r)); // pit? - map(0x70, 0x70).w(FUNC(fp6000_state::fp6000_6845_address_w)); - map(0x72, 0x72).w(FUNC(fp6000_state::fp6000_6845_data_w)); + map(0x08, 0x08).r(FUNC(fp6000_state::port_08_r)); + map(0x08, 0x08).w(FUNC(fp6000_state::port_08_w)); + map(0x09, 0x09).r(FUNC(fp6000_state::port_09_r)); + map(0x09, 0x09).w(FUNC(fp6000_state::port_09_w)); + map(0x0a, 0x0a).lr8(NAME([this] () { return ioport("cpudsw")->read(); })); + map(0x0a, 0x0a).w(FUNC(fp6000_state::port_0a_w)); + map(0x0b, 0x0b).r(FUNC(fp6000_state::port_0b_r)); + map(0x0b, 0x0b).w(FUNC(fp6000_state::port_0b_w)); + map(0x0c, 0x0c).r(FUNC(fp6000_state::port_0c_r)); + map(0x0c, 0x0c).w(FUNC(fp6000_state::port_0c_w)); + map(0x0d, 0x0d).r(FUNC(fp6000_state::port_0d_r)); + map(0x0d, 0x0d).w(FUNC(fp6000_state::port_0d_w)); + map(0x0e, 0x0e).r(FUNC(fp6000_state::port_0e_r)); + map(0x0e, 0x0e).w("centronics_data_out", FUNC(output_latch_device::write)); + map(0x0f, 0x0f).r(FUNC(fp6000_state::port_0f_r)); + map(0x0f, 0x0f).w(FUNC(fp6000_state::port_0f_w)); + // 10-17 floppy? + map(0x14, 0x14).lr8(NAME([this] () { return ioport("floppydsw")->read(); })); + map(0x20, 0x23).rw("keyboard", FUNC(fp6000_kbd_device::read), FUNC(fp6000_kbd_device::write)).umask16(0x00ff); + map(0x30, 0x33).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff); + map(0x38, 0x3f).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff); + // 50-5f dma? + map(0x70, 0x70).w(m_crtc, FUNC(mc6845_device::address_w)); + map(0x72, 0x72).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w)); map(0x74, 0x75).r(FUNC(fp6000_state::unk_r)); //bit 6 busy flag } -/* Input ports */ + +//************************************************************************** +// INPUT PORT DEFINITIONS +//************************************************************************** + static INPUT_PORTS_START( fp6000 ) - PORT_START("DSW") - PORT_DIPNAME( 0x01, 0x00, "DSW" ) - PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x10, 0x00, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0xe0, 0x40, "Installed RAM banks" ) - PORT_DIPSETTING( 0xe0, "0" ) - PORT_DIPSETTING( 0xc0, "1" ) - PORT_DIPSETTING( 0xa0, "2" ) - PORT_DIPSETTING( 0x80, "3" ) - PORT_DIPSETTING( 0x60, "4" ) - PORT_DIPSETTING( 0x40, "5" ) - PORT_DIPSETTING( 0x20, "6 (INVALID)" ) //exceeds 768KB limit (writes to gvram et al) - PORT_DIPSETTING( 0x00, "7 (INVALID)" ) + PORT_START("cpudsw") + PORT_DIPNAME(0x1f, 0x1e, "Printer type") + PORT_DIPSETTING( 0x1f, "0") + PORT_DIPSETTING( 0x1e, "1") + PORT_DIPSETTING( 0x1d, "2") + PORT_DIPSETTING( 0x1c, "3") + PORT_DIPSETTING( 0x1b, "4") + PORT_DIPSETTING( 0x1a, "5") + PORT_DIPSETTING( 0x19, "6") + PORT_DIPSETTING( 0x18, "7") + PORT_DIPSETTING( 0x17, "8") + PORT_DIPSETTING( 0x16, "9") + PORT_DIPSETTING( 0x15, "10") + PORT_DIPSETTING( 0x14, "11") + PORT_DIPSETTING( 0x13, "12") + PORT_DIPSETTING( 0x12, "13") + PORT_DIPSETTING( 0x11, "14") + PORT_DIPSETTING( 0x10, "15") + PORT_DIPSETTING( 0x0f, "16") + PORT_DIPSETTING( 0x0e, "17") + PORT_DIPSETTING( 0x0d, "18") + PORT_DIPSETTING( 0x0c, "19") + PORT_DIPSETTING( 0x0b, "20") + PORT_DIPSETTING( 0x0a, "21") + PORT_DIPSETTING( 0x09, "22") + PORT_DIPSETTING( 0x08, "23") + PORT_DIPSETTING( 0x07, "24") + PORT_DIPSETTING( 0x06, "25") + PORT_DIPSETTING( 0x05, "26") + PORT_DIPSETTING( 0x04, "27") + PORT_DIPSETTING( 0x03, "28") + PORT_DIPSETTING( 0x02, "29") + PORT_DIPSETTING( 0x01, "30") + PORT_DIPSETTING( 0x00, "31") + PORT_DIPNAME(0xe0, 0x40, "Installed RAM banks") + PORT_DIPSETTING( 0xe0, "0") + PORT_DIPSETTING( 0xc0, "1") + PORT_DIPSETTING( 0xa0, "2") + PORT_DIPSETTING( 0x80, "3") + PORT_DIPSETTING( 0x60, "4") + PORT_DIPSETTING( 0x40, "5") + PORT_DIPSETTING( 0x20, "6 (INVALID)") // exceeds 768KB limit (writes to gvram et al) + PORT_DIPSETTING( 0x00, "7 (INVALID)") + + PORT_START("floppydsw") + PORT_DIPNAME(0x07, 0x07, "Floppy type?") + PORT_DIPSETTING( 0x07, DEF_STR( None )) + PORT_DIPSETTING( 0x06, "1") + PORT_DIPSETTING( 0x05, "2") + PORT_DIPSETTING( 0x04, "3") + PORT_DIPSETTING( 0x03, "4") + PORT_DIPSETTING( 0x02, "5") + PORT_DIPSETTING( 0x01, "6") + PORT_DIPSETTING( 0x00, "7") + PORT_DIPUNKNOWN(0x08, 0x08) + PORT_DIPUNKNOWN(0x10, 0x10) + PORT_DIPUNKNOWN(0x20, 0x20) + PORT_DIPUNKNOWN(0x40, 0x40) + PORT_DIPUNKNOWN(0x80, 0x80) INPUT_PORTS_END -static const gfx_layout fp6000_charlayout = + +//************************************************************************** +// VIDEO EMULATION +//************************************************************************** + +READ16_MEMBER(fp6000_state::unk_r) +{ + // 7------- + // -6------ ? + // --5----- + // ---4---- + // ----3--- + // -----2-- + // ------1- screen lines: 0=200, 1=400 + // -------0 + + return 0x40; +} + +MC6845_UPDATE_ROW( fp6000_state::crtc_update_row ) +{ + const pen_t *pen = m_palette->pens(); + uint8_t *pcg = reinterpret_cast(m_pcg.target()); + uint32_t *vram = reinterpret_cast(m_gvram.target()); + + for (int x = 0; x < x_count; x++) + { + // text mode + uint8_t code = (m_vram[ma + x] >> 0) & 0xff; + uint8_t color = (m_vram[ma + x] >> 8) & 0x0f; + uint8_t gfx = pcg[(code << 4) | ra]; + + // cursor? + if (x == cursor_x) + gfx = 0xff; + + // draw 8 pixels of the character + for (int i = 0; i < 8; i++) + bitmap.pix32(y, x * 8 + i) = BIT(gfx, 7 - i) ? pen[color] : 0; + + // graphics + uint32_t data = vram[(ma << 3) + (ra * x_count) + x]; + + // draw 8 gfx pixels + if ((data >> 12) & 0x0f) bitmap.pix32(y, x * 8 + 0) = pen[(data >> 12) & 0x0f]; + if ((data >> 8) & 0x0f) bitmap.pix32(y, x * 8 + 1) = pen[(data >> 8) & 0x0f]; + if ((data >> 4) & 0x0f) bitmap.pix32(y, x * 8 + 2) = pen[(data >> 4) & 0x0f]; + if ((data >> 0) & 0x0f) bitmap.pix32(y, x * 8 + 3) = pen[(data >> 0) & 0x0f]; + if ((data >> 28) & 0x0f) bitmap.pix32(y, x * 8 + 4) = pen[(data >> 28) & 0x0f]; + if ((data >> 24) & 0x0f) bitmap.pix32(y, x * 8 + 5) = pen[(data >> 24) & 0x0f]; + if ((data >> 20) & 0x0f) bitmap.pix32(y, x * 8 + 6) = pen[(data >> 20) & 0x0f]; + if ((data >> 16) & 0x0f) bitmap.pix32(y, x * 8 + 7) = pen[(data >> 16) & 0x0f]; + } +} + +static const gfx_layout charlayout = { 8, 16, RGN_FRAC(1,1), @@ -283,58 +287,242 @@ static const gfx_layout fp6000_charlayout = 8*16 }; -static GFXDECODE_START( gfx_fp6000 ) - GFXDECODE_ENTRY( "pcg", 0x0000, fp6000_charlayout, 0, 1 ) +static GFXDECODE_START( gfx ) + GFXDECODE_RAM("pcg", 0, charlayout, 0, 1) GFXDECODE_END +//************************************************************************** +// MACHINE EMULATION +//************************************************************************** + +// 7------- option rom available (1=no) +// -654---- unknown +// ----3--- cassette in +// -----21- unknown +// -------0 cassette motor + +uint8_t fp6000_state::port_08_r() +{ + uint8_t data = 0; + + data |= 0x80; // no option rom + data |= (m_cassette->input() > 0 ? 0x00 : 0x08); + + return data; +} + +void fp6000_state::port_08_w(uint8_t data) +{ + logerror("port_08 write %02x\n", data); + + m_cassette->change_state(BIT(data, 0) ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); +} + +uint8_t fp6000_state::port_09_r() +{ + logerror("port_09 read\n"); + return 0xff; +} + +void fp6000_state::port_09_w(uint8_t data) +{ + logerror("port_09 write %02x\n", data); +} + +void fp6000_state::port_0a_w(uint8_t data) +{ + // 7------- speaker/cassette output select + // -6543210 unknown + + logerror("port_0a write %02x\n", data); + + m_port_0a = data; +} + +uint8_t fp6000_state::port_0b_r() +{ + logerror("port_0b read\n"); + return 0xff; +} + +void fp6000_state::port_0b_w(uint8_t data) +{ + // printer control? + logerror("port_0b write %02x\n", data); + m_pic->ir7_w(1); // ? +} + +uint8_t fp6000_state::port_0c_r() +{ + logerror("port_0c read\n"); + return 0xff; +} + +void fp6000_state::port_0c_w(uint8_t data) +{ + // 7------- unknown + // -6------ pit timer2 gate? + // --543210 unknown + + logerror("port_0c write %02x\n", data); +} + +uint8_t fp6000_state::port_0d_r() +{ + logerror("port_0d read\n"); + return 0xff; +} + +void fp6000_state::port_0d_w(uint8_t data) +{ + // after writing printer data + logerror("port_0d write %02x\n", data); + + // ? + m_centronics->write_strobe(1); + m_centronics->write_strobe(0); +} + +uint8_t fp6000_state::port_0e_r() +{ + uint8_t data = 0; + + // 765----- unknown + // ---4321- printer status lines + // -------0 printer busy + + logerror("port_0e read\n"); + + data |= m_centronics_perror << 2; // guess + data |= m_centronics_fault << 1; // guess + data |= m_centronics_busy << 0; + + return data; +} + +uint8_t fp6000_state::port_0f_r() +{ + // read at end of timer interrupt routine, result discarded + return 0xff; +} + +void fp6000_state::port_0f_w(uint8_t data) +{ + logerror("port_0f write %02x\n", data); + m_pic->ir7_w(0); // ? +} + +void fp6000_state::pit_timer0_w(int state) +{ + // work around pit issue, it issues set and clear at the same time, + // leaving the pic no time to react + if (state) + m_pic->ir0_w(1); + else + m_pit_timer->adjust(attotime::from_hz(100000)); // timing? +} + +TIMER_CALLBACK_MEMBER(fp6000_state::pit_timer0_clear) +{ + m_pic->ir0_w(0); +} + +void fp6000_state::pit_timer2_w(int state) +{ + if (BIT(m_port_0a, 7)) + m_speaker->level_w(state); + else + m_cassette->output(state ? 1.0 : 0.0); +} + void fp6000_state::machine_start() { - m_char_rom = memregion("pcg")->base(); + m_pit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(fp6000_state::pit_timer0_clear), this)); } void fp6000_state::machine_reset() { } + +//************************************************************************** +// MACHINE DEFINTIONS +//************************************************************************** + void fp6000_state::fp6000(machine_config &config) { - /* basic machine hardware */ - I8086(config, m_maincpu, 16000000/2); + I8086(config, m_maincpu, 16000000 / 2); // 8 Mhz? m_maincpu->set_addrmap(AS_PROGRAM, &fp6000_state::fp6000_map); m_maincpu->set_addrmap(AS_IO, &fp6000_state::fp6000_io); + m_maincpu->set_irq_acknowledge_callback(m_pic, FUNC(pic8259_device::inta_cb)); - /* video hardware */ + PIC8259(config, m_pic, 0); + m_pic->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0); + + PIT8253(config, m_pit, 0); + m_pit->set_clk<0>(16000000 / 16); // 1 MHz + m_pit->out_handler<0>().set(FUNC(fp6000_state::pit_timer0_w)).invert(); + m_pit->set_clk<2>(16000000 / 16); // 1 MHz? + m_pit->out_handler<2>().set(FUNC(fp6000_state::pit_timer2_w)); + + // video hardware screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ - screen.set_size(640, 480); - screen.set_visarea_full(); - screen.set_screen_update(FUNC(fp6000_state::screen_update_fp6000)); - screen.set_palette(m_palette); + screen.set_raw(16000000, 1024, 0, 640, 272, 0, 200); // 16 MHz? + screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update)); - MC6845(config, m_crtc, 16000000/5); /* unknown variant, unknown clock, hand tuned to get ~60 fps */ + MC6845(config, m_crtc, 16000000 / 8); // unknown variant, 2 MHz? m_crtc->set_screen("screen"); m_crtc->set_show_border_area(false); m_crtc->set_char_width(8); + m_crtc->set_update_row_callback(FUNC(fp6000_state::crtc_update_row)); - PALETTE(config, m_palette).set_entries(8); + PALETTE(config, m_palette).set_entries(16); - GFXDECODE(config, m_gfxdecode, m_palette, gfx_fp6000); + GFXDECODE(config, m_gfxdecode, m_palette, gfx); + + // audio hardware + SPEAKER(config, "mono").front_center(); + + SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 0.50); + + // keyboard + fp6000_kbd_device &keyboard(FP6000_KBD(config, "keyboard")); + keyboard.int_handler().set(m_pic, FUNC(pic8259_device::ir1_w)); + + // cassette + CASSETTE(config, m_cassette); + m_cassette->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED); + m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05); + + // centronics printer + output_latch_device ¢ronics_data_out(OUTPUT_LATCH(config, "centronics_data_out")); + + CENTRONICS(config, m_centronics, centronics_devices, "printer"); + m_centronics->set_output_latch(centronics_data_out); + m_centronics->ack_handler().set(m_pic, FUNC(pic8259_device::ir7_w)).invert(); + m_centronics->busy_handler().set(FUNC(fp6000_state::centronics_busy_w)); + m_centronics->fault_handler().set(FUNC(fp6000_state::centronics_fault_w)); + m_centronics->perror_handler().set(FUNC(fp6000_state::centronics_perror_w)); } -/* ROM definition */ + +//************************************************************************** +// ROM DEFINITIONS +//************************************************************************** + ROM_START( fp6000 ) - ROM_REGION16_LE( 0x10000, "ipl", ROMREGION_ERASEFF ) - ROM_LOAD( "ipl.rom", 0x0000, 0x10000, CRC(c72fe40a) SHA1(0e4c60dc27f6c7f461c4bc382b81602b3327a7a4)) + ROM_REGION16_LE(0x10000, "ipl", 0) + ROM_LOAD("ipl.rom", 0x0000, 0x10000, CRC(c72fe40a) SHA1(0e4c60dc27f6c7f461c4bc382b81602b3327a7a4)) - ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF ) - ROM_LOAD( "mcu", 0x0000, 0x1000, NO_DUMP ) //unknown MCU type - - ROM_REGION( 0x10000, "pcg", ROMREGION_ERASE00 ) + ROM_REGION(0x1000, "mcu", 0) + ROM_LOAD("mcu", 0x0000, 0x1000, NO_DUMP) // unknown MCU type ROM_END -/* Driver */ -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1985, fp6000, 0, 0, fp6000, fp6000, fp6000_state, empty_init, "Casio", "FP-6000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +//************************************************************************** +// SYSTEM DRIVERS +//************************************************************************** + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1985, fp6000, 0, 0, fp6000, fp6000, fp6000_state, empty_init, "Casio", "FP-6000", MACHINE_NOT_WORKING ) diff --git a/src/mame/machine/fp6000_kbd.cpp b/src/mame/machine/fp6000_kbd.cpp new file mode 100644 index 00000000000..128a7b75a8c --- /dev/null +++ b/src/mame/machine/fp6000_kbd.cpp @@ -0,0 +1,314 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** + + Casio FP-6000 Keyboard + +***************************************************************************/ + +#include "emu.h" +#include "fp6000_kbd.h" +#include "machine/keyboard.ipp" + + +DEFINE_DEVICE_TYPE(FP6000_KBD, fp6000_kbd_device, "fp6000_kbd", "FP-6000 Keyboard") + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( keyboard ) + PORT_START("row_0") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 00 */ PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_NAME("Copy") + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 01 */ PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 02 */ PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 03 */ PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 04 */ PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 05 */ PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 06 */ PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 07 */ PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 08 */ PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 09 */ PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0a */ PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0b */ PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0c */ PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_NAME("Ins") + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0d */ PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_NAME("Del") + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0e */ PORT_CODE(KEYCODE_HOME) PORT_CHAR(0) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_NAME("Cls / Home") + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 0f */ PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("SLock / Break") + + PORT_START("row_1") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 10 */ PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 11 */ PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 12 */ PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 13 */ PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 14 */ PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 15 */ PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 16 */ PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 17 */ PORT_CODE(KEYCODE_0) PORT_CHAR('0') + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 18 */ PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 19 */ PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1a */ PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1b */ PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1c */ PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_NAME("\xe2\x86\x91 PgUp") + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1d */ PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_NAME("\xe2\x86\x92 PgRt") + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1e */ PORT_CODE(KEYCODE_END) PORT_CHAR(0) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_NAME("Clr / End") + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 1f */ PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) + + PORT_START("row_2") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 20 */ PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 21 */ PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 22 */ PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 23 */ PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 24 */ PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 25 */ PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 26 */ PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 27 */ PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 28 */ PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('@') PORT_CHAR('`') + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 29 */ PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') PORT_NAME("\xC2\xA5 |") // ¥ + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2a */ PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2b */ PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_NAME("\xe2\x86\x90 PgLt") + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2c */ PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_NAME("\xe2\x86\x93 PgDn") + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2d */ PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2e */ PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 2f */ PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) + + PORT_START("row_3") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 30 */ PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 31 */ PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 32 */ PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 33 */ PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 34 */ PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 35 */ PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 36 */ PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 37 */ PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 38 */ PORT_CODE(KEYCODE_COLON) PORT_CHAR(':') PORT_CHAR('*') + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 39 */ PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_UNUSED) /* 3a */ // ? + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 3b */ PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 3c */ PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 3d */ PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_UNUSED) /* 3e */ // ? + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 3f */ PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_NAME("Ctrl") + + PORT_START("row_4") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 40 */ PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 41 */ PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 42 */ PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 43 */ PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 44 */ PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 45 */ PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 46 */ PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 47 */ PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 48 */ PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CHAR('+') + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 49 */ PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_UNUSED) /* 4a */ // ? + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 4b */ PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 4c */ PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 4d */ PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 4e */ PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 4f */ PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_NAME("Alt") + + PORT_START("row_5") + PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 50 */ PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 51 */ PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') + PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 52 */ PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 53 */ PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') + PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 54 */ PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 55 */ PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') + PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 56 */ PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 57 */ PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') + PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 58 */ PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 59 */ PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR(0) PORT_CHAR('_') PORT_NAME(" _") + PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5a */ PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT)) PORT_NAME("Kana") + PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5b */ PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) + PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5c */ PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) + PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5d */ PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) + PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5e */ PORT_CODE(KEYCODE_COMMA_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) + PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) /* 5f */ PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_NAME("Caps") + + // codes 0x60 to 0x7f seem to be copies of other codes +INPUT_PORTS_END + +ioport_constructor fp6000_kbd_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( keyboard ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// fp6000_kbd_device - constructor +//------------------------------------------------- + +fp6000_kbd_device::fp6000_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, FP6000_KBD, tag, owner, clock), + device_matrix_keyboard_interface(mconfig, *this, "row_0", "row_1", "row_2", "row_3", "row_4", "row_5"), + m_int_handler(*this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void fp6000_kbd_device::device_start() +{ + // resolve callbacks + m_int_handler.resolve_safe(); + + // register for state saving + save_item(NAME(m_status)); + save_item(NAME(m_data)); +} + +//------------------------------------------------- +// device_start - device-specific reset +//------------------------------------------------- + +void fp6000_kbd_device::device_reset() +{ + reset_key_state(); + start_processing(attotime::from_hz(9600)); + typematic_stop(); + + m_status = 0x00; + m_data = 0x7f; +} + +//------------------------------------------------- +// read - external read from keyboard +//------------------------------------------------- + +uint8_t fp6000_kbd_device::read(offs_t offset) +{ + uint8_t data = 0xff; + + switch (offset) + { + case 0: + if (0) + logerror("Read data from keyboard: %02x\n", m_data); + + m_int_handler(0); + m_status &= ~STATUS_DATA_AVAILABLE; + data = m_data; + break; + + case 1: + if (0) + logerror("Read status from keyboard: %02x\n", m_status); + + data = m_status; + break; + } + + return data; +} + +//------------------------------------------------- +// write - external data to keyboard +//------------------------------------------------- + +void fp6000_kbd_device::write(offs_t offset, uint8_t data) +{ + switch (offset) + { + case 0: + logerror("Write data to keyboard: %02x\n", data); + + switch (data) + { + case 0x0f: + m_status &= ~STATUS_READY_FOR_DATA; + m_status |= STATUS_DATA_AVAILABLE; + m_data = 0x35; // or 0x40 + break; + } + + break; + + case 1: + logerror("Write command to keyboard: %02x\n", data); + + switch (data) + { + case 0x7e: + m_status |= STATUS_READY_FOR_DATA; + break; + } + + break; + } +} + +//------------------------------------------------- +// key_make - handle a key being pressed +//------------------------------------------------- + +void fp6000_kbd_device::key_make(uint8_t row, uint8_t column) +{ + uint8_t code = translate(row, column); + + if (code != 0x7f) + { + send_key(code); + + // no typematic for modifier keys + if (code != 0x3f && code != 0x4f && code != 0x50 && code != 0x5a && code != 0x5f) + typematic_start(row, column, attotime::from_msec(750), attotime::from_msec(50)); + } +} + +//------------------------------------------------- +// key_break - handle a key being released +//------------------------------------------------- + +void fp6000_kbd_device::key_break(uint8_t row, uint8_t column) +{ + if (typematic_is(row, column)) + typematic_stop(); + + uint8_t code = translate(row, column); + + if (code != 0x7f) + send_key(0x80 | code); +} + +//------------------------------------------------- +// key_repeat - handle a key being repeated +//------------------------------------------------- + +void fp6000_kbd_device::key_repeat(u8 row, u8 column) +{ + uint8_t code = translate(row, column); + send_key(code); +} + +//------------------------------------------------- +// translate - row and column to key code +//------------------------------------------------- + +uint8_t fp6000_kbd_device::translate(uint8_t row, uint8_t column) +{ + return row * 16 + column; +} + +//------------------------------------------------- +// send_key - send key code to host +//------------------------------------------------- + +void fp6000_kbd_device::send_key(uint8_t code) +{ + m_status |= STATUS_DATA_AVAILABLE; + m_data = code; + m_int_handler(1); +} diff --git a/src/mame/machine/fp6000_kbd.h b/src/mame/machine/fp6000_kbd.h new file mode 100644 index 00000000000..978a2b49e3f --- /dev/null +++ b/src/mame/machine/fp6000_kbd.h @@ -0,0 +1,65 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** + + Casio FP-6000 Keyboard + +***************************************************************************/ + +#ifndef MAME_MACHINE_FP6000_KBD_H +#define MAME_MACHINE_FP6000_KBD_H + +#pragma once + +#include "machine/keyboard.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> fp6000_kbd_device + +class fp6000_kbd_device : public device_t, protected device_matrix_keyboard_interface<6> +{ +public: + // construction/destruction + fp6000_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + // callbacks + auto int_handler() { return m_int_handler.bind(); } + + uint8_t read(offs_t offset); + void write(offs_t offset, uint8_t data); + +protected: + // device-level overrides + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_matrix_keyboard_interface overrides + virtual void key_make(uint8_t row, uint8_t column) override; + virtual void key_break(uint8_t row, uint8_t column) override; + virtual void key_repeat(uint8_t row, uint8_t column) override; + +private: + devcb_write_line m_int_handler; + + enum + { + STATUS_READY_FOR_DATA = 0x01, + STATUS_DATA_AVAILABLE = 0x02 + }; + + uint8_t translate(uint8_t row, uint8_t column); + void send_key(uint8_t code); + + uint8_t m_status; + uint8_t m_data; +}; + +// device type definition +DECLARE_DEVICE_TYPE(FP6000_KBD, fp6000_kbd_device) + +#endif // MAME_MACHINE_FP6000_KBD_H