diff --git a/.gitattributes b/.gitattributes index 30990127d2a..f02f1415845 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8343,6 +8343,7 @@ src/mess/layout/fidelz80.lay svneol=native#text/xml src/mess/layout/gl3000s.lay svneol=native#text/xml src/mess/layout/glasgow.lay svneol=native#text/xml src/mess/layout/h8.lay svneol=native#text/xml +src/mess/layout/ie15.lay svneol=native#text/xml src/mess/layout/instruct.lay svneol=native#text/xml src/mess/layout/junior.lay svneol=native#text/xml src/mess/layout/k1003.lay svneol=native#text/xml @@ -8509,6 +8510,8 @@ src/mess/machine/genpc.c svneol=native#text/plain src/mess/machine/hec2hrp.c svneol=native#text/plain src/mess/machine/hecdisk2.c svneol=native#text/plain src/mess/machine/hp48.c svneol=native#text/plain +src/mess/machine/ie15_kbd.c svneol=native#text/plain +src/mess/machine/ie15_kbd.h svneol=native#text/plain src/mess/machine/intv.c svneol=native#text/plain src/mess/machine/isbc_215g.c svneol=native#text/plain src/mess/machine/isbc_215g.h svneol=native#text/plain diff --git a/src/mess/drivers/ie15.c b/src/mess/drivers/ie15.c index 6327ba59338..40ee1beee07 100644 --- a/src/mess/drivers/ie15.c +++ b/src/mess/drivers/ie15.c @@ -1,36 +1,38 @@ /*************************************************************************** - 15IE-00-013 Terminal + 15IE-00-013 Terminal - board images : http://asvcorp.ru/darch/hardware/pdp/fryazin-display/index.html + A serial (RS232 or current loop) green-screen terminal, mostly VT52 + compatible (no Hold Screen mode and no graphics character set). - 29/06/2012 Skeleton driver. - - A serial (RS232 or current loop) green-screen terminal, mostly VT52 compatible - (no Hold Screen mode and no graphics character set, but has Cyrillic characters). - The top line is a status line. + Alternate character set (selected by SO/SI chars) is Cyrillic. ****************************************************************************/ + #include "emu.h" + +#include "bus/rs232/rs232.h" #include "cpu/ie15/ie15.h" #include "imagedev/bitbngr.h" -#include "machine/keyboard.h" +#include "machine/ie15_kbd.h" #include "sound/beep.h" +#include "ie15.lh" #define SCREEN_PAGE (80*48) -#define IE_1 0x80 -#define IE_KB_ACK 1 +#define IE_TRUE 0x80 +#define IE_FALSE 0 #define IE15_TOTAL_HORZ 1000 -#define IE15_TOTAL_VERT 28*11 - #define IE15_DISP_HORZ 800 -#define IE15_DISP_VERT 25*11 +#define IE15_HORZ_START 200 -#define IE15_HORZ_START 100 +#define IE15_TOTAL_VERT 28*11 +#define IE15_DISP_VERT 25*11 #define IE15_VERT_START 2*11 +#define IE15_STATUSLINE 11 + #define VERBOSE_DBG 1 /* general debug messages */ @@ -44,36 +46,32 @@ } \ } while (0) -#if VERBOSE_DBG > 0 -#define LOOPBACK (m_io_keyboard->read() & 0x20) -#else -#define LOOPBACK (0) -#endif -#define BITBANGER_TAG "bitbanger" -#define KEYBOARD_TAG "keyboard" - -class ie15_state : public driver_device +class ie15_state : public driver_device, + public device_serial_interface { public: - ie15_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), + ie15_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + device_serial_interface(mconfig, *this), m_maincpu(*this, "maincpu"), m_beeper(*this, "beeper"), - m_bitbanger(*this, BITBANGER_TAG), - m_io_keyboard(*this, KEYBOARD_TAG) + m_rs232(*this, "rs232"), + m_io_keyboard(*this, "keyboard") { } virtual void machine_reset(); virtual void video_start(); - DECLARE_PALETTE_INIT(ie15); UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_hle(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - TIMER_DEVICE_CALLBACK_MEMBER(scanline_callback); - DECLARE_WRITE8_MEMBER(kbd_put); - static const bitbanger_config ie15_bitbanger_config; - TIMER_CALLBACK_MEMBER(serial_tx_callback); - emu_timer *m_serial_tx_timer; + TIMER_DEVICE_CALLBACK_MEMBER( scanline_callback ); + DECLARE_WRITE16_MEMBER( kbd_put ); + + DECLARE_WRITE_LINE_MEMBER( serial_rx_callback ); + virtual void rcv_complete(); + virtual void tra_callback(); + virtual void tra_complete(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); DECLARE_WRITE8_MEMBER( mem_w ); DECLARE_READ8_MEMBER( mem_r ); @@ -96,117 +94,116 @@ public: DECLARE_WRITE8_MEMBER( serial_w ); DECLARE_READ8_MEMBER( serial_rx_ready_r ); DECLARE_READ8_MEMBER( serial_r ); -#if 0 DECLARE_WRITE8_MEMBER( serial_speed_w ); -#endif private: TIMER_CALLBACK_MEMBER(ie15_beepoff); - UINT32 draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y); + void update_leds(); + UINT32 draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline); + rectangle m_tmpclip; bitmap_ind16 m_tmpbmp; + bitmap_ind16 m_offbmp; const UINT8 *m_p_chargen; UINT8 *m_p_videoram; - UINT8 m_beep; - UINT8 m_cursor; + UINT8 m_long_beep; + UINT8 m_kb_control; UINT8 m_kb_data; - UINT8 m_kb_flag; UINT8 m_kb_flag0; + UINT8 m_kb_flag; + UINT8 m_kb_ruslat; UINT8 m_latch; - UINT8 m_ruslat; - UINT8 m_serial_rx_bits; - UINT8 m_serial_rx_buffer; - UINT8 m_serial_rx_data; - UINT8 m_serial_tx_bits; - UINT8 m_serial_tx_data; - UINT8 m_statusline; - UINT8 m_video; - UINT32 m_videoptr; - UINT32 m_videoptr_2; + struct { + UINT8 cursor; + UINT8 enable; + UINT8 line25; + UINT32 ptr1; + UINT32 ptr2; + } m_video; - static void bitbanger_callback(running_machine &machine, UINT8 bit); - DECLARE_WRITE_LINE_MEMBER( serial_rx_callback ); + UINT8 m_serial_rx_ready; + UINT8 m_serial_tx_ready; protected: required_device m_maincpu; required_device m_beeper; - required_device m_bitbanger; + required_device m_rs232; required_ioport m_io_keyboard; }; READ8_MEMBER( ie15_state::mem_r ) { UINT8 ret; - ret = m_p_videoram[m_videoptr]; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE) + ret = m_p_videoram[m_video.ptr1]; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_video.ptr1 >= SCREEN_PAGE) { - DBG_LOG(2,"memory",("R @ %03x == %02x\n", m_videoptr, ret)); + DBG_LOG(2,"memory",("R @ %03x == %02x\n", m_video.ptr1, ret)); } - m_videoptr++; - m_videoptr &= 0xfff; + m_video.ptr1++; + m_video.ptr1 &= 0xfff; m_latch = 0; return ret; } WRITE8_MEMBER( ie15_state::mem_w ) { if ((m_latch ^= 1) == 0) { - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE) + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_video.ptr1 >= SCREEN_PAGE) { - DBG_LOG(2,"memory",("W @ %03x <- %02x\n", m_videoptr, data)); + DBG_LOG(2,"memory",("W @ %03x <- %02x\n", m_video.ptr1, data)); } - m_p_videoram[m_videoptr++] = data; - m_videoptr &= 0xfff; + m_p_videoram[m_video.ptr1++] = data; + m_video.ptr1 &= 0xfff; } } WRITE8_MEMBER( ie15_state::mem_addr_inc_w ) { if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(2,"memory",("++ %03x\n", m_videoptr)); + DBG_LOG(2,"memory",("++ %03x\n", m_video.ptr1)); } - m_videoptr++; - m_videoptr &= 0xfff; - if (m_video) - m_videoptr_2 = m_videoptr; + m_video.ptr1++; + m_video.ptr1 &= 0xfff; + if (m_video.enable) + m_video.ptr2 = m_video.ptr1; } WRITE8_MEMBER( ie15_state::mem_addr_dec_w ) { if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(2,"memory",("-- %03x\n", m_videoptr)); + DBG_LOG(2,"memory",("-- %03x\n", m_video.ptr1)); } - m_videoptr--; - m_videoptr &= 0xfff; - if (m_video) - m_videoptr_2 = m_videoptr; + m_video.ptr1--; + m_video.ptr1 &= 0xfff; + if (m_video.enable) + m_video.ptr2 = m_video.ptr1; } WRITE8_MEMBER( ie15_state::mem_addr_lo_w ) { - UINT16 tmp = m_videoptr; + UINT16 tmp = m_video.ptr1; tmp &= 0xff0; tmp |= ((data >> 4) & 0xf); if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(2,"memory",("lo %03x <- %02x = %03x\n", m_videoptr, data, tmp)); + DBG_LOG(2,"memory",("lo %03x <- %02x = %03x\n", m_video.ptr1, data, tmp)); } - m_videoptr = tmp; - if (m_video) - m_videoptr_2 = tmp; + m_video.ptr1 = tmp; + if (m_video.enable) + m_video.ptr2 = tmp; } WRITE8_MEMBER( ie15_state::mem_addr_hi_w ) { - UINT16 tmp = m_videoptr; + UINT16 tmp = m_video.ptr1; tmp &= 0xf; tmp |= (data << 4); if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(2,"memory",("hi %03x <- %02x = %03x\n", m_videoptr, data, tmp)); + DBG_LOG(2,"memory",("hi %03x <- %02x = %03x\n", m_video.ptr1, data, tmp)); } - m_videoptr = tmp; - if (m_video) - m_videoptr_2 = tmp; + m_video.ptr1 = tmp; + if (m_video.enable) + m_video.ptr2 = tmp; } TIMER_CALLBACK_MEMBER(ie15_state::ie15_beepoff) @@ -215,27 +212,29 @@ TIMER_CALLBACK_MEMBER(ie15_state::ie15_beepoff) } WRITE8_MEMBER( ie15_state::beep_w ) { - UINT16 length = (m_beep&128)?150:400; + UINT16 length = (m_long_beep & IE_TRUE) ? 150 : 400; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { - DBG_LOG(1,"beep",("(%s)\n", m_beep?"short":"long")); + DBG_LOG(1,"beep",("(%s)\n", m_long_beep ? "short" : "long")); } machine().scheduler().timer_set(attotime::from_msec(length), timer_expired_delegate(FUNC(ie15_state::ie15_beepoff),this)); machine().device("beeper")->set_state(1); } +/* keyboard */ + // active high READ8_MEMBER( ie15_state::kb_r ) { - DBG_LOG(2,"keyboard",("R %02X '%c'\n", m_kb_data, m_kb_data < 0x20?' ':m_kb_data)); + DBG_LOG(2,"keyboard",("R %02X '%c'\n", m_kb_data, m_kb_data < 0x20 ? ' ' : m_kb_data)); return m_kb_data; } // active low READ8_MEMBER( ie15_state::kb_ready_r ) { - m_kb_flag &= IE_1; + m_kb_flag &= IE_TRUE; if (m_kb_flag != m_kb_flag0) { - DBG_LOG(2,"keyboard",("? %c\n", m_kb_flag?'n':'y')); + DBG_LOG(2,"keyboard",("? %c\n", m_kb_flag ? 'n' : 'y')); m_kb_flag0 = m_kb_flag; } return m_kb_flag; @@ -244,136 +243,93 @@ READ8_MEMBER( ie15_state::kb_ready_r ) { // active low WRITE8_MEMBER( ie15_state::kb_ready_w ) { DBG_LOG(2,"keyboard",("clear ready\n")); - m_kb_flag = IE_1 | IE_KB_ACK; + m_kb_flag = IE_TRUE | IE_KB_ACK; } // active high; active = interpret controls, inactive = display controls READ8_MEMBER( ie15_state::kb_s_red_r ) { - return m_io_keyboard->read() & 0x01 ? IE_1 : 0; + return m_io_keyboard->read() & IE_KB_RED ? IE_TRUE : 0; } // active high; active = setup mode READ8_MEMBER( ie15_state::kb_s_sdv_r ) { - return m_io_keyboard->read() & 0x02 ? IE_1 : 0; + return m_kb_control & IE_KB_SDV ? IE_TRUE : 0; } -// active high, XXX stub +// active high; active = keypress detected on aux keypad READ8_MEMBER( ie15_state::kb_s_dk_r ) { - return 0; + return m_kb_control & IE_KB_DK ? IE_TRUE : 0; } // active low; active = full duplex, inactive = half duplex READ8_MEMBER( ie15_state::kb_s_dupl_r ) { - return m_io_keyboard->read() & 0x08 ? IE_1 : 0; + return m_io_keyboard->read() & IE_KB_DUP ? IE_TRUE : 0; } // active high; active = on-line, inactive = local editing READ8_MEMBER( ie15_state::kb_s_lin_r ) { - return m_io_keyboard->read() & 0x10 ? IE_1 : 0; + return m_io_keyboard->read() & IE_KB_LIN ? IE_TRUE : 0; +} + +/* serial port */ + +void ie15_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + device_serial_interface::device_timer(timer, id, param, ptr); +} + +WRITE_LINE_MEMBER( ie15_state::serial_rx_callback ) +{ + device_serial_interface::rx_w(state); +} + +void ie15_state::rcv_complete() +{ + receive_register_extract(); + m_serial_rx_ready = IE_FALSE; +} + +void ie15_state::tra_callback() +{ + UINT8 bit = transmit_register_get_data_bit(); + m_rs232->write_txd(bit); +} + +void ie15_state::tra_complete() +{ + m_serial_tx_ready = IE_TRUE; } // active low READ8_MEMBER( ie15_state::serial_rx_ready_r ) { - if (LOOPBACK) - return m_serial_tx_data ? 0 : IE_1; - else - return m_serial_rx_data ? 0 : IE_1; + return m_serial_rx_ready; } -// not called unless data is ready -READ8_MEMBER( ie15_state::serial_r ) { - UINT8 tmp; - - if (LOOPBACK) { - tmp = m_serial_tx_data; - m_serial_tx_data = 0; - } else { - tmp = m_serial_rx_data; - m_serial_rx_data = 0; - } - DBG_LOG(2,"serial",("R %02X '%c'\n", tmp, tmp < 0x20?' ':tmp)); - return tmp; -} - -/* - m_serial_rx_buffer incoming bits. - m_serial_rx_bits number of bits in _buffer. - m_serial_rx_data complete byte, ready to be read by host, or 0 if no data. -*/ - -WRITE_LINE_MEMBER( ie15_state::serial_rx_callback ) -{ - UINT8 tmp = m_serial_rx_bits; - - switch (m_serial_rx_bits) { - // wait for start bit (0) - case 10: - m_serial_rx_bits = 0; - case 0: - if (!state) { - m_serial_rx_bits++; - m_serial_rx_buffer = 0; - } - break; - // stuff incoming bits into byte buffer - case 1: case 2: case 3: case 4: - case 5: case 6: case 7: case 8: - m_serial_rx_buffer |= state << (m_serial_rx_bits-1); - m_serial_rx_bits++; - break; - // expecting stop bit (1) - case 9: - if (state && !m_serial_rx_data) { - m_serial_rx_data = m_serial_rx_buffer; - m_serial_rx_bits++; - } else - m_serial_rx_bits = 0; - break; - default: - // overflow - break; - } - DBG_LOG(2,"serial",("r %d bits %02d->%02d buffer %02X data %02X\n", - state, tmp, m_serial_rx_bits, m_serial_rx_buffer, m_serial_rx_data)); -} - -const bitbanger_config ie15_state::ie15_bitbanger_config = -{ - DEVCB_DRIVER_LINE_MEMBER(ie15_state, serial_rx_callback), /* callback */ - BITBANGER_PRINTER, /* default mode */ - BITBANGER_9600, /* default output baud */ - BITBANGER_0PERCENT /* default fine tune adjustment */ -}; - // active high READ8_MEMBER( ie15_state::serial_tx_ready_r ) { - return m_serial_tx_data ? 0 : IE_1; + return m_serial_tx_ready; +} + +// not called unless data are ready +READ8_MEMBER( ie15_state::serial_r ) { + UINT8 data; + + data = get_received_char(); + m_serial_rx_ready = IE_TRUE; + DBG_LOG(1,"serial",("R %02X '%c'\n", data, data < 0x20?' ':data)); + return data; } WRITE8_MEMBER( ie15_state::serial_w ) { - DBG_LOG(2,"serial",("W %02X '%c'\n", data, data < 0x20?' ':data)); - if (LOOPBACK) { - if (!m_serial_tx_data) - m_serial_tx_data = data; - } else { - /* 1 start bit */ - m_bitbanger->output(0); - /* 8 data bits, 1 stop bit, no parity */ - m_serial_tx_bits = 8; - m_serial_tx_data = data; - m_serial_tx_timer->adjust(attotime::from_hz(9600)); - } + DBG_LOG(1,"serial",("W %02X '%c'\n", data, data < 0x20?' ':data)); + + m_serial_tx_ready = IE_FALSE; + transmit_register_setup(data); } -TIMER_CALLBACK_MEMBER(ie15_state::serial_tx_callback) { - if (!m_serial_tx_bits) { - m_bitbanger->output(1); - m_serial_tx_data = 0; - } else { - m_bitbanger->output(BIT(m_serial_tx_data, 8-(m_serial_tx_bits--))); - m_serial_tx_timer->adjust(attotime::from_hz(9600)); - } +WRITE8_MEMBER( ie15_state::serial_speed_w ) { + return; } READ8_MEMBER( ie15_state::flag_r ) { @@ -391,7 +347,7 @@ READ8_MEMBER( ie15_state::flag_r ) { ret = !machine().first_screen()->vblank(); break; case 4: - ret = m_ruslat; + ret = m_kb_ruslat; break; default: break; @@ -407,24 +363,24 @@ WRITE8_MEMBER( ie15_state::flag_w ) { switch (offset) { case 0: - m_video = data; + m_video.enable = data; break; case 1: - m_cursor = data; + m_video.cursor = data; break; case 2: - m_beep = data; + m_long_beep = data; break; case 3: - m_statusline = data; + m_video.line25 = data; break; case 4: - m_ruslat = data; + m_kb_ruslat = data; break; default: break; } - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && !offset) { DBG_LOG(2,"flag",("%sset %d\n", data?"":"re", offset)); } @@ -449,7 +405,7 @@ static ADDRESS_MAP_START(ie15_io, AS_IO, 8, ie15_state) AM_RANGE(011, 011) AM_READ(kb_r) // 09h R: keyboard data [6.1.5.2] AM_RANGE(012, 012) AM_READ(kb_s_red_r) // 0Ah I: keyboard mode "RED" [6.1.5.2] AM_RANGE(013, 013) AM_READ(kb_ready_r) // 0Bh R: keyboard data ready [6.1.5.2] - AM_RANGE(014, 014) AM_READ(kb_s_sdv_r) AM_WRITENOP // 0Ch W: serial port speed [6.1.3.1], R: keyboard mode "SDV" [6.1.5.2] + AM_RANGE(014, 014) AM_READ(kb_s_sdv_r) AM_WRITE(serial_speed_w) // 0Ch W: serial port speed [6.1.3.1], R: keyboard mode "SDV" [6.1.5.2] AM_RANGE(015, 015) AM_READ(kb_s_dk_r) AM_WRITE(kb_ready_w) // 0Dh I: keyboard mode "DK" [6.1.5.2] AM_RANGE(016, 016) AM_READ(kb_s_dupl_r) // 0Eh I: keyboard mode "DUPL" [6.1.5.2] AM_RANGE(017, 017) AM_READ(kb_s_lin_r) // 0Fh I: keyboard mode "LIN" [6.1.5.2] @@ -460,131 +416,172 @@ ADDRESS_MAP_END /* Input ports */ static INPUT_PORTS_START( ie15 ) PORT_START("keyboard") - PORT_DIPNAME(0x01, 0x00, "RED mode") - PORT_DIPSETTING(0x00, "Off" ) - PORT_DIPSETTING(0x01, "On" ) - PORT_DIPNAME(0x02, 0x00, "SDV mode (Setup)") - PORT_DIPSETTING(0x00, "Off" ) - PORT_DIPSETTING(0x02, "On" ) - PORT_DIPNAME(0x08, 0x00, "DUPL mode") - PORT_DIPSETTING(0x00, "Off" ) - PORT_DIPSETTING(0x08, "On" ) - PORT_DIPNAME(0x10, 0x00, "LIN mode") - PORT_DIPSETTING(0x00, "Off" ) - PORT_DIPSETTING(0x10, "On" ) - PORT_DIPNAME(0x20, 0x00, "digital loopback") - PORT_DIPSETTING(0x00, "Off" ) - PORT_DIPSETTING(0x20, "On" ) + PORT_DIPNAME(IE_KB_RED, IE_KB_RED, "RED (Interpret controls)") + PORT_DIPSETTING(0x00, "Off") + PORT_DIPSETTING(IE_KB_RED, "On") + PORT_DIPNAME(IE_KB_DUP, IE_KB_DUP, "DUP (Full duplex)") + PORT_DIPSETTING(0x00, "Off") + PORT_DIPSETTING(IE_KB_DUP, "On") + PORT_DIPNAME(IE_KB_LIN, IE_KB_LIN, "LIN (Online)") + PORT_DIPSETTING(0x00, "Off") + PORT_DIPSETTING(IE_KB_LIN, "On") INPUT_PORTS_END -WRITE8_MEMBER( ie15_state::kbd_put ) +WRITE16_MEMBER( ie15_state::kbd_put ) { - DBG_LOG(2,"keyboard",("W %02X<-%02X '%c' %c\n", m_kb_data, data, data < 0x20?' ':data, m_kb_flag?'n':'y')); - if (m_kb_flag == IE_1) { - m_kb_data = data; + DBG_LOG(2,"keyboard",("W %02X<-%02X '%c' %02X (%c)\n", m_kb_data, data, 'x' /* data < 0x20 ? ' ' : (data & 255) */, + m_kb_flag, m_kb_flag ? 'n' : 'y')); + m_kb_control = (data >> 8) & 255; + // send new key only when firmware has processed previous one + if (m_kb_flag == IE_TRUE) { + m_kb_data = data & 255; m_kb_flag = 0; } } +static IE15_KEYBOARD_INTERFACE( keyboard_intf ) +{ + DEVCB_DRIVER_MEMBER16(ie15_state, kbd_put) +}; + void ie15_state::machine_reset() { - m_ruslat = m_beep = m_statusline = m_cursor = m_video = m_kb_data = m_kb_flag0 = 0; - m_serial_tx_data = m_serial_tx_bits = m_serial_rx_buffer = m_serial_rx_data = m_serial_rx_bits = 0; - m_kb_flag = IE_1; + memset(&m_video, 0, sizeof(m_video)); + m_kb_ruslat = m_long_beep = m_kb_control = m_kb_data = m_kb_flag0 = 0; + m_kb_flag = IE_TRUE; machine().device("beeper")->set_frequency(2400); machine().device("beeper")->set_state(0); - m_serial_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ie15_state::serial_tx_callback),this)); + m_serial_tx_ready = m_serial_rx_ready = IE_TRUE; + set_data_frame(1 /* start bits */, 8 /* data bits */, PARITY_NONE, STOP_BITS_1); + // device supports rates from 150 to 9600 baud but null_modem has hardcoded 9600 + set_tra_rate(9600); + set_rcv_rate(9600); } void ie15_state::video_start() { - m_p_chargen = machine().root_device().memregion("chargen")->base(); + m_p_chargen = memregion("chargen")->base(); m_p_videoram = memregion("video")->base(); - m_videoptr = m_videoptr_2 = m_latch = 0; + m_video.ptr1 = m_video.ptr2 = m_latch = 0; + m_tmpclip = rectangle(0, IE15_DISP_HORZ-1, 0, IE15_DISP_VERT-1); m_tmpbmp.allocate(IE15_DISP_HORZ, IE15_DISP_VERT); + m_offbmp.allocate(IE15_DISP_HORZ, 1); + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { + m_offbmp.fill(0); + } } -UINT32 ie15_state::draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y) +/* + Usable raster is 800 x 275 pixels (80 x 25 characters). 24 lines are + available to the user and 25th (topmost) line is the status line. + Status line, if enabled, displays current serial port speed, 16 setup + bits, and clock. There is no NVRAM, so setup bits are always 0 after + reset and clock starts counting at 0 XXX. + + No character attributes are available, but in 'display controls' mode + control characters stored in memory are shown as blinking chars. + + Character cell is 10 x 11; character generator provides 7 x 8 of that. + 3 extra horizontal pixels are always blank. Blinking cursor may be + displayed on 3 extra scan lines. + + On each scan line, video board draws 80 characters from any location + in video memory; this is used by firmware to provide instant scroll + and cursor, which is a character with code 0x7F stored in XXX. + + Video board output is controlled by + - control flag 0 "disable video": 0 == disable + - control flag 1 "cursor": 0 == if this scan line is one of extra 3, + enable video every 5 frames. + - control flag 3 "status line": 0 == current scan line is part of status line + - keyboard mode 'RED' ('display controls'): if character code is + less than 0x20 and RED is set, enable video every 5 frames; if RED is + unset, disable video. + + XXX 'dotted look' is caused by strobe at 2x pixel clock -- use HLSL for this. +*/ + +UINT32 ie15_state::draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline) { - UINT8 gfx,fg,bg,ra,blink,red; - UINT16 x,chr; + UINT8 gfx, fg, bg, ra, blink, red; + UINT16 x, chr; bg = 0; fg = 1; ra = scanline % 8; - blink = (machine().first_screen()->frame_number() % 10) >= 5; - red = m_io_keyboard->read() & 0x01; - - DBG_LOG(2,"draw_scanline", - ("addr %03x row %d-%d video %d\n", offset, y, scanline, m_video)); + blink = (machine().first_screen()->frame_number() % 10) > 4; + red = m_io_keyboard->read() & IE_KB_RED; for (x = offset; x < offset + 80; x++) { - if (m_video) { - chr = m_p_videoram[x] << 3; - gfx = m_p_chargen[chr | ra]; + chr = m_p_videoram[x] << 3; + gfx = m_p_chargen[chr | ra]; - /* - Cursor is a character with only 3 scan lines, and is - not shown if flag 1 is not active on this scan line. - It always blinks if shown. - - Control characters blink if RED mode is on and they - are not on status line; else they are blanked out. - */ - - if (scanline > 7 && (!m_cursor || blink)) + if (scanline > 7 && (!m_video.cursor || blink)) + gfx = 0; + else if (chr < (0x20<<3)) { + if (red && blink && m_video.line25) + gfx = m_p_chargen[chr | 0x200 | ra]; + else gfx = 0; - if (chr < (0x20<<3)) { - if (!y || !red || blink) - gfx = 0; - else - gfx = m_p_chargen[chr | 0x200 | ra]; - } - /* Display a scanline of a character */ - *p++ = BIT(gfx, 7) ? fg : bg; - *p++ = BIT(gfx, 6) ? fg : bg; - *p++ = BIT(gfx, 5) ? fg : bg; - *p++ = BIT(gfx, 4) ? fg : bg; - *p++ = BIT(gfx, 3) ? fg : bg; - *p++ = BIT(gfx, 2) ? fg : bg; - *p++ = BIT(gfx, 1) ? fg : bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - } else { - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; - *p++ = bg; } + + *p++ = BIT(gfx, 7) ? fg : bg; + *p++ = BIT(gfx, 6) ? fg : bg; + *p++ = BIT(gfx, 5) ? fg : bg; + *p++ = BIT(gfx, 4) ? fg : bg; + *p++ = BIT(gfx, 3) ? fg : bg; + *p++ = BIT(gfx, 2) ? fg : bg; + *p++ = BIT(gfx, 1) ? fg : bg; + *p++ = bg; + *p++ = bg; + *p++ = bg; } return 0; } +void ie15_state::update_leds() +{ + UINT8 data = m_io_keyboard->read(); + output_set_value("lat_led", m_kb_ruslat ^ 1); + output_set_value("nr_led", BIT(m_kb_control, IE_KB_NR_BIT) ^ 1); + output_set_value("pch_led", BIT(data, IE_KB_PCH_BIT) ^ 1); + output_set_value("dup_led", BIT(data, IE_KB_DUP_BIT) ^ 1); + output_set_value("lin_led", BIT(data, IE_KB_LIN_BIT) ^ 1); + output_set_value("red_led", BIT(data, IE_KB_RED_BIT) ^ 1); + output_set_value("sdv_led", BIT(m_kb_control, IE_KB_SDV_BIT) ^ 1); + output_set_value("prd_led", 1); // XXX +} + +/* + VBlank is active for 3 topmost on-screen rows and 1 at the bottom; however, control flag 3 overrides VBlank, + allowing status line to be switched on and off. +*/ TIMER_DEVICE_CALLBACK_MEMBER(ie15_state::scanline_callback) { UINT16 y = machine().first_screen()->vpos(); -// DBG_LOG(2,"scanline", -// ("addr %03x frame %lld x %04d y %03d\n", m_videoptr_2, machine().first_screen()->frame_number(), machine().first_screen()->hpos(), y)); - if (y>=IE15_VERT_START) { - y -= IE15_VERT_START; - if (y < IE15_DISP_VERT) { - draw_scanline(&m_tmpbmp.pix16(y), m_videoptr_2, y%11, y/11); - } + + DBG_LOG(3,"scanline_cb", + ("addr %03x frame %" I64FMT "d x %.4d y %.3d row %.2d e:c:s %d:%d:%d\n", + m_video.ptr2, machine().first_screen()->frame_number(), machine().first_screen()->hpos(), y, + y%11, m_video.enable, m_video.cursor, m_video.line25)); + + if (y < IE15_VERT_START) return; + y -= IE15_VERT_START; + if (y >= IE15_DISP_VERT) return; + + if (!m_video.enable || (y < IE15_STATUSLINE && m_video.line25)) { + copybitmap( m_tmpbmp, m_offbmp, 0, 0, 0, y, m_tmpclip ); + } else { + draw_scanline( &m_tmpbmp.pix16(y), m_video.ptr2, y%11 ); } } UINT32 ie15_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { - copybitmap( bitmap, m_tmpbmp, 0, 0, IE15_HORZ_START, IE15_VERT_START, cliprect ); + update_leds(); + copybitmap(bitmap, m_tmpbmp, 0, 0, IE15_HORZ_START, IE15_VERT_START, cliprect); return 0; } @@ -604,15 +601,9 @@ static const gfx_layout ie15_charlayout = }; static GFXDECODE_START( ie15 ) - GFXDECODE_ENTRY( "chargen", 0x0000, ie15_charlayout, 0, 1 ) + GFXDECODE_ENTRY("chargen", 0x0000, ie15_charlayout, 0, 1) GFXDECODE_END -PALETTE_INIT_MEMBER(ie15_state, ie15) -{ - palette.set_pen_color(0, rgb_t::black); // black - palette.set_pen_color(1, 0x00, 0xc0, 0x00); // green -} - static MACHINE_CONFIG_START( ie15, ie15_state ) /* Basic machine hardware */ MCFG_CPU_ADD("maincpu", IE15, XTAL_30_8MHz / 10) @@ -630,13 +621,17 @@ static MACHINE_CONFIG_START( ie15, ie15_state ) MCFG_SCREEN_PALETTE("palette") MCFG_GFXDECODE_ADD("gfxdecode", "palette", ie15) - MCFG_PALETTE_ADD("palette", 2) - MCFG_PALETTE_INIT_OWNER(ie15_state, ie15) + MCFG_PALETTE_ADD_MONOCHROME_GREEN("palette") + + MCFG_DEFAULT_LAYOUT( layout_ie15 ) /* Devices */ - MCFG_DEVICE_ADD(KEYBOARD_TAG, GENERIC_KEYBOARD, 0) - MCFG_GENERIC_KEYBOARD_CB(WRITE8(ie15_state, kbd_put)) - MCFG_BITBANGER_ADD(BITBANGER_TAG, ie15_state::ie15_bitbanger_config) + MCFG_IE15_KEYBOARD_ADD("keyboard", keyboard_intf) + + MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, NULL) + MCFG_RS232_RXD_HANDLER(WRITELINE(ie15_state, serial_rx_callback)) + MCFG_DEVICE_MODIFY("rs232") + MCFG_SLOT_DEFAULT_OPTION("null_modem") MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("beeper", BEEP, 0) diff --git a/src/mess/layout/ie15.lay b/src/mess/layout/ie15.lay new file mode 100644 index 00000000000..bbb21cbed10 --- /dev/null +++ b/src/mess/layout/ie15.lay @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mess/machine/ie15_kbd.c b/src/mess/machine/ie15_kbd.c new file mode 100644 index 00000000000..d72f398d24b --- /dev/null +++ b/src/mess/machine/ie15_kbd.c @@ -0,0 +1,334 @@ +/*************************************************************************** + + 15WWW-97-006 keyboard, normally used with 15IE-00-013. + Irisha can use it too. + +***************************************************************************/ + +#include "machine/ie15_kbd.h" + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + + +ie15_keyboard_device::ie15_keyboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source) + , m_io_kbd0(*this, "TERM_LINE0") + , m_io_kbd1(*this, "TERM_LINE1") + , m_io_kbd2(*this, "TERM_LINE2") + , m_io_kbd3(*this, "TERM_LINE3") + , m_io_kbdc(*this, "TERM_LINEC") +{ +} + +ie15_keyboard_device::ie15_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, IE15_KEYBOARD, "15WWW-97-006 Keyboard", tag, owner, clock, "ie15_keyboard", __FILE__) + , m_io_kbd0(*this, "TERM_LINE0") + , m_io_kbd1(*this, "TERM_LINE1") + , m_io_kbd2(*this, "TERM_LINE2") + , m_io_kbd3(*this, "TERM_LINE3") + , m_io_kbdc(*this, "TERM_LINEC") +{ +} + +UINT8 ie15_keyboard_device::row_number(UINT32 code) +{ + if BIT(code,0) return 0; + if BIT(code,1) return 1; + if BIT(code,2) return 2; + if BIT(code,3) return 3; + if BIT(code,4) return 4; + if BIT(code,5) return 5; + if BIT(code,6) return 6; + if BIT(code,7) return 7; + if BIT(code,8) return 8; + if BIT(code,9) return 9; + if BIT(code,10) return 10; + if BIT(code,11) return 11; + if BIT(code,12) return 12; + if BIT(code,13) return 13; + if BIT(code,14) return 14; + if BIT(code,15) return 15; + return 0; +} + +UINT16 ie15_keyboard_device::keyboard_handler(UINT16 last_code, UINT8 *scan_line) +{ + int i; + UINT32 code = 0; + UINT16 key_code = 0; + UINT16 retVal = 0; + UINT8 ctrl = BIT(m_io_kbdc->read(), 0); + UINT8 shift = BIT(m_io_kbdc->read(), 1); + + i = *scan_line; + { + if (i == 0) code = m_io_kbd0->read(); + else + if (i == 1) code = m_io_kbd1->read(); + else + if (i == 2) code = m_io_kbd2->read(); + else + if (i == 3) code = m_io_kbd3->read(); + + if (code != 0) + { + if (!m_ruslat) + i += 4; + if (shift) + i += 8; + i <<= 4; + if (code < 0x10000) { + key_code = m_rom [i + row_number(code)]; + } else { + key_code = m_rom [i + row_number(code >> 16)*2 + 256]; + } + if (ctrl) { + key_code &= 0x1f; + } + retVal = key_code; + } else { + *scan_line += 1; + if (*scan_line==4) { + *scan_line = 0; + } + } + } + + // setup mode toggle + if (BIT(m_io_kbdc->read(), 2)) { + retVal |= (IE_KB_SDV << 8); + } + // aux keyboard flag + if (code & 0xe0e000) { + retVal |= (IE_KB_DK << 8); + } + // shift + if (shift) { + retVal |= (IE_KB_NR << 8); + } + // SI/SO handling + if ((key_code & 127) == IE_KB_SI) { + m_ruslat = 0; + } + if ((key_code & 127) == IE_KB_SO) { + m_ruslat = 1; + } + + return retVal; +} + +void ie15_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + UINT16 new_code; + new_code = keyboard_handler(m_last_code, &m_scan_line); + if ((m_last_code != new_code) /* && (new_code) */) + send_key(new_code); + m_last_code = new_code; +} + +/*************************************************************************** + VIDEO HARDWARE +***************************************************************************/ + +ROM_START( ie15_keyboard ) + ROM_REGION( 0x200, "ie15kbd", 0 ) + ROM_LOAD( "15bbb.rt5", 0x000, 0x200, CRC(e6a4226e) SHA1(0ee46f5be1b01fa917a6d483bb51463106ae441f) ) +ROM_END + +const rom_entry *ie15_keyboard_device::device_rom_region() const +{ + return ROM_NAME( ie15_keyboard ); +} + +static MACHINE_CONFIG_FRAGMENT( ie15_keyboard ) +MACHINE_CONFIG_END + +machine_config_constructor ie15_keyboard_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME(ie15_keyboard); +} + +void ie15_keyboard_device::device_start() +{ + m_keyboard_func.resolve(m_keyboard_cb, *this); + m_timer = timer_alloc(); + m_rom = (UINT8*)memregion("ie15kbd")->base(); +} + +void ie15_keyboard_device::device_config_complete() +{ + const ie15_keyboard_interface *intf = reinterpret_cast(static_config()); + if(intf != NULL) + { + *static_cast(this) = *intf; + } + else + { + memset(&m_keyboard_cb, 0, sizeof(m_keyboard_cb)); + } +} + +void ie15_keyboard_device::device_reset() +{ + m_last_code = 0; + m_scan_line = 0; + m_ruslat = 0; + m_timer->adjust(attotime::from_hz(10000), 0, attotime::from_hz(10000)); +} + +/* +Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y10 Y11 Y12 Y13 Y14 Y15 Y16 Y17 Y18 Y19 Y20 Y21 Y22 Y23 Y24 +-- +;+ 1! 2" 3# 4$ 5% 6& 7' 8( 9) 0 -= 7 8 9 ??? ?? ??? ??? ??? f1 f2 f3 +?J ?C ?U ?K ?E ?N ?G ?[ ?] ?Z ?H :* 4 5 6 ?? ?? ??1 ?1 ??2 f4 f5 f6 +?F ?Y ?W ?A ?P ?R ?O ?L ?D ?V ?\ .> ?? 1 2 3 ??? ??? ??? f7 f8 f9 +?Q ?^ ?S ?M ?I ?T ?X ?B ?@ ,< /? _ SPC 0 , fA fB fC + +rom: + +00000000 3b 31 32 33 34 35 36 37 38 39 30 2d 00 37 38 39 |;1234567890-.789| rus + upper +00000010 6a 63 75 6b 65 6e 67 7b 7d 7a 68 3a 00 34 35 36 |jcukeng{}zh:.456| +00000020 66 79 77 61 70 72 6f 6c 64 76 7c 2e 7f 31 32 33 |fywaproldv|..123| +00000030 71 7e 73 6d 69 74 78 62 60 2c 2f 7f 20 30 30 2c |q~smitxb`,/. 00,| + +00000040 3b 31 32 33 34 35 36 37 38 39 30 2d 00 37 38 39 |;1234567890-.789| lat + upper +00000050 4a 43 55 4b 45 4e 47 5b 5d 5a 48 3a 00 34 35 36 |JCUKENG[]ZH:.456| +00000060 46 59 57 41 50 52 4f 4c 44 56 5c 2e 7f 31 32 33 |FYWAPROLDV\..123| +00000070 51 5e 53 4d 49 54 58 42 40 2c 2f 5f 20 30 30 2c |Q^SMITXB@,/_ 00,| + +00000080 2b 21 22 23 24 25 26 27 28 29 30 3d 00 37 38 39 |+!"#$%&'()0=.789| rus + lower +00000090 4a 43 55 4b 45 4e 47 5b 5d 5a 48 2a 00 34 35 36 |JCUKENG[]ZH*.456| +000000a0 46 59 57 41 50 52 4f 4c 44 56 5c 3e 7f 31 32 33 |FYWAPROLDV\>.123| +000000b0 51 5e 53 4d 49 54 58 42 40 3c 3f 5f 20 30 30 2c |Q^SMITXB@.123| +000000f0 71 7e 73 6d 69 74 78 62 60 3c 3f 7f 20 30 30 2c |q~smitxb`') + PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) + PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) + PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) + PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) + PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRD") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) + PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRM") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) + PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRS") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) + PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) + PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) + PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) + + PORT_START("TERM_LINE3") + PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') + PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') + PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') + PORT_BIT(0x000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') + PORT_BIT(0x000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') + PORT_BIT(0x000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') + PORT_BIT(0x000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') + PORT_BIT(0x000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') + PORT_BIT(0x000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) // PORT_CHAR('`') PORT_CHAR('@') // XXX + PORT_BIT(0x000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') + PORT_BIT(0x000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') + PORT_BIT(0x000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('_') // XXX + PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') + PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) + PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad ,") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) + PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Lat (SO)") PORT_CODE(KEYCODE_LALT) + PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Rus (SI)") PORT_CODE(KEYCODE_RALT) + PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PgDn") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) + PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Next SetUp") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) + PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PgUp") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) + + PORT_START("TERM_LINEC") + PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) +// PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) + PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SetUp") PORT_CODE(KEYCODE_RSHIFT) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) + PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SetUp") PORT_CODE(KEYCODE_PRTSCR) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) +INPUT_PORTS_END + +ioport_constructor ie15_keyboard_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ie15_keyboard); +} + +const device_type IE15_KEYBOARD = &device_creator; diff --git a/src/mess/machine/ie15_kbd.h b/src/mess/machine/ie15_kbd.h new file mode 100644 index 00000000000..6da5c8fa256 --- /dev/null +++ b/src/mess/machine/ie15_kbd.h @@ -0,0 +1,89 @@ +#ifndef __IE15_KEYBOARD_H__ +#define __IE15_KEYBOARD_H__ + +#include "emu.h" + +#define IE_KB_ACK 1 + +#define IE_KB_RED 0x01 +#define IE_KB_SDV 0x02 +#define IE_KB_DUP 0x08 +#define IE_KB_LIN 0x10 +#define IE_KB_DK 0x20 +#define IE_KB_PCH 0x40 +#define IE_KB_NR 0x80 + +#define IE_KB_RED_BIT 0 +#define IE_KB_SDV_BIT 1 +#define IE_KB_DUP_BIT 3 +#define IE_KB_LIN_BIT 4 +#define IE_KB_DK_BIT 5 +#define IE_KB_PCH_BIT 6 +#define IE_KB_NR_BIT 7 + +#define IE_KB_SI 0x0f +#define IE_KB_SO 0x0e + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +struct ie15_keyboard_interface +{ + devcb_write16 m_keyboard_cb; +}; + +#define IE15_KEYBOARD_INTERFACE(name) const ie15_keyboard_interface (name) = + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_IE15_KEYBOARD_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, IE15_KEYBOARD, 0) \ + MCFG_DEVICE_CONFIG(_intrf) + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +class ie15_keyboard_device : + public device_t, + public ie15_keyboard_interface +{ +public: + ie15_keyboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + ie15_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual ioport_constructor device_input_ports() const; + virtual machine_config_constructor device_mconfig_additions() const; + virtual const rom_entry *device_rom_region() const; + +protected: + required_ioport m_io_kbd0; + required_ioport m_io_kbd1; + required_ioport m_io_kbd2; + required_ioport m_io_kbd3; + required_ioport m_io_kbdc; + + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual void device_config_complete(); + virtual void send_key(UINT16 code) { m_keyboard_func(0, code); } + emu_timer *m_timer; + +private: + virtual UINT16 keyboard_handler(UINT16 last_code, UINT8 *scan_line); + UINT8 row_number(UINT32 code); + UINT16 m_last_code; + UINT8 m_scan_line; + UINT8 m_ruslat; + UINT8 *m_rom; + + devcb_resolved_write16 m_keyboard_func; +}; + +extern const device_type IE15_KEYBOARD; + +#endif /* __IE15_KEYBOARD_H__ */ diff --git a/src/mess/mess.mak b/src/mess/mess.mak index a4c545382c7..6337f5219f5 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -2063,7 +2063,7 @@ $(MESSOBJ)/skeleton.a: \ $(MESS_DRIVERS)/hunter2.o \ $(EMU_MACHINE)/nsc810.o \ $(MESS_DRIVERS)/ibm6580.o \ - $(MESS_DRIVERS)/ie15.o \ + $(MESS_DRIVERS)/ie15.o $(MESS_MACHINE)/ie15_kbd.o \ $(MESS_DRIVERS)/if800.o \ $(MESS_DRIVERS)/imsai.o \ $(MESS_DRIVERS)/indiana.o \ @@ -2232,6 +2232,7 @@ $(MESS_DRIVERS)/fidelz80.o: $(MESS_LAYOUT)/fidelz80.lh \ $(MESS_LAYOUT)/vsc.lh $(MESS_DRIVERS)/glasgow.o: $(MESS_LAYOUT)/glasgow.lh $(MESS_DRIVERS)/h8.o: $(MESS_LAYOUT)/h8.lh +$(MESS_DRIVERS)/ie15.o: $(MESS_LAYOUT)/ie15.lh $(MESS_DRIVERS)/instruct.o: $(MESS_LAYOUT)/instruct.lh $(MESS_DRIVERS)/k1003.o: $(MESS_LAYOUT)/k1003.lh $(MESS_DRIVERS)/kim1.o: $(MESS_LAYOUT)/kim1.lh