diff --git a/src/mess/drivers/rainbow.c b/src/mess/drivers/rainbow.c index c93ad4eff9e..f675364062b 100644 --- a/src/mess/drivers/rainbow.c +++ b/src/mess/drivers/rainbow.c @@ -1134,6 +1134,7 @@ void rainbow_state::update_kbd_irq() WRITE_LINE_MEMBER(rainbow_state::kbd_tx) { // printf("%02x to keyboard\n", state); + m_lk201->rx_w(state); } WRITE_LINE_MEMBER(rainbow_state::kbd_rxready_w) @@ -1277,7 +1278,7 @@ static MACHINE_CONFIG_START( rainbow, rainbow_state ) MCFG_SOFTWARE_LIST_ADD("flop_list","rainbow") MCFG_I8251_ADD("kbdser", i8251_intf) - MCFG_TIMER_DRIVER_ADD_PERIODIC("keyboard", rainbow_state, keyboard_tick, attotime::from_hz(4800)) + MCFG_TIMER_DRIVER_ADD_PERIODIC("keyboard", rainbow_state, keyboard_tick, attotime::from_hz(4800*16)) // 8251 is set to /16 on the clock input MCFG_LK201_ADD() MCFG_NVRAM_ADD_0FILL("nvram") diff --git a/src/mess/machine/dec_lk201.c b/src/mess/machine/dec_lk201.c index 1aa7749cd01..4aff8f347db 100644 --- a/src/mess/machine/dec_lk201.c +++ b/src/mess/machine/dec_lk201.c @@ -1,6 +1,6 @@ /* DEC LK-201 keyboard - Emulation by R. Belmont + Emulation by R. Belmont & M. Burke This is the later "cost-reduced" 6805 version; there's also an 8048 version. */ @@ -108,7 +108,65 @@ ________|D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 // MACROS / CONSTANTS //************************************************************************** -#define LK201_CPU_TAG "lk201" +#define LK201_CPU_TAG "lk201_cpu" +#define LK201_SPK_TAG "beeper" + +//------------------------------------------------- +// SERIAL COMMUNICATIONS INTERFACE +//------------------------------------------------- + +#define SCI_BAUD 0 // Baud rate register +#define BAUD_SCR 0x07 // SCI baud rate select +#define BAUD_SCP 0x30 // SCI prescaler select + +#define SCI_SCCR1 1 // Control register 1 +#define SCCR1_WAKE 0x08 // Wakeup method +#define SCCR1_M 0x10 // Character length +#define SCCR1_T8 0x40 // Transmit bit 8 +#define SCCR1_R8 0x80 // Receive bit 8 + +#define SCI_SCCR2 2 // Control register 2 +#define SCCR2_SBK 0x01 // Send break +#define SCCR2_RWU 0x02 // Receiver wakeup enable +#define SCCR2_RE 0x04 // Receiver enable +#define SCCR2_TE 0x08 // Transmitter enable +#define SCCR2_ILIE 0x10 // Idle line interrupt enable +#define SCCR2_RIE 0x20 // Receiver interrupt enable +#define SCCR2_TCIE 0x40 // Transmit complete interrupt enable +#define SCCR2_TIE 0x80 // Transmit interrupt enable + +#define SCI_SCSR 3 // Status register +#define SCSR_FE 0x02 // Receiver framing error +#define SCSR_NF 0x04 // Receiver noise +#define SCSR_OR 0x08 // Receiver overrun +#define SCSR_IDLE 0x10 // Receiver idle +#define SCSR_RDRF 0x20 // Receive data register full +#define SCSR_TC 0x40 // Transmit complete +#define SCSR_TDRE 0x80 // Transmit data register empty +#define SCSR_INT (SCSR_IDLE | SCSR_RDRF| \ + SCSR_TC | SCSR_TDRE) // Interrupt sources + +#define SCI_SCDR 4 // Data register + +//------------------------------------------------- +// SERIAL PERIPHERAL INTERFACE +//------------------------------------------------- + +#define SPI_SPCR 0 // Control register +#define SPCR_SPR 0x03 // SPI clock rate select +#define SPCR_CPHA 0x04 // Clock phase +#define SPCR_CPOL 0x08 // Clock polarity +#define SPCR_MSTR 0x10 // Master mode select +#define SPCR_DWOM 0x20 // Port D wire-or mode option +#define SPCR_SPE 0x40 // Serial peripheral system enable +#define SPCR_SPIE 0x80 // Serial peripheral interrupt enable + +#define SPI_SPSR 1 // Status register +#define SPSR_MODF 0x10 // Mode fault flag +#define SPSR_WCOL 0x40 // Write collision +#define SPSR_SPIF 0x80 // SPI transfer complete + +#define SPI_SPDR 2 // Data I/O Register //************************************************************************** // DEVICE DEFINITIONS @@ -141,6 +199,10 @@ ADDRESS_MAP_END static MACHINE_CONFIG_FRAGMENT( lk201 ) MCFG_CPU_ADD(LK201_CPU_TAG, M68HC05EG, 2000000) // actually 68HC05C4 MCFG_CPU_PROGRAM_MAP(lk201_map) + + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD(LK201_SPK_TAG, BEEP, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_CONFIG_END @@ -159,6 +221,202 @@ const rom_entry *lk201_device::device_rom_region() const return ROM_NAME( lk201 ); } +//------------------------------------------------- +// INPUT_PORTS( lk201 ) +//------------------------------------------------- + +INPUT_PORTS_START( lk201 ) + PORT_START("KBD0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) + + PORT_START("KBD1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Compose") PORT_CODE(KEYCODE_LALT) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) + + PORT_START("KBD2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("A") PORT_CODE(KEYCODE_A) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("1") PORT_CODE(KEYCODE_1) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Esc") PORT_CODE(KEYCODE_TILDE) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("<") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("X") PORT_CODE(KEYCODE_X) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("S") PORT_CODE(KEYCODE_S) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("W") PORT_CODE(KEYCODE_W) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Z") PORT_CODE(KEYCODE_2) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Hold Screen") PORT_CODE(KEYCODE_F1) + + PORT_START("KBD4") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("C") PORT_CODE(KEYCODE_C) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("D") PORT_CODE(KEYCODE_D) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("E") PORT_CODE(KEYCODE_E) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3") PORT_CODE(KEYCODE_3) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Setup") PORT_CODE(KEYCODE_F3) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Print Screen") PORT_CODE(KEYCODE_F2) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD5") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("V") PORT_CODE(KEYCODE_V) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F") PORT_CODE(KEYCODE_F) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("R") PORT_CODE(KEYCODE_R) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4") PORT_CODE(KEYCODE_4) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Break") PORT_CODE(KEYCODE_F5) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) + + PORT_START("KBD6") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("B") PORT_CODE(KEYCODE_B) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("G") PORT_CODE(KEYCODE_G) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("T") PORT_CODE(KEYCODE_T) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("5") PORT_CODE(KEYCODE_5) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Interrupt") PORT_CODE(KEYCODE_F6) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD7") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("N") PORT_CODE(KEYCODE_N) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("H") PORT_CODE(KEYCODE_H) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("6") PORT_CODE(KEYCODE_6) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Resume") PORT_CODE(KEYCODE_F7) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Cancel") PORT_CODE(KEYCODE_F8) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD8") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("M") PORT_CODE(KEYCODE_M) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("J") PORT_CODE(KEYCODE_J) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("U") PORT_CODE(KEYCODE_U) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("7") PORT_CODE(KEYCODE_7) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Exit") PORT_CODE(KEYCODE_F10) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Main Screen") PORT_CODE(KEYCODE_F9) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD9") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("K") PORT_CODE(KEYCODE_K) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("I") PORT_CODE(KEYCODE_I) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("8") PORT_CODE(KEYCODE_8) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F11") PORT_CODE(KEYCODE_F11) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD10") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L") PORT_CODE(KEYCODE_L) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("O") PORT_CODE(KEYCODE_O) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9") PORT_CODE(KEYCODE_9) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F13") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F12") PORT_CODE(KEYCODE_F12) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("KBD11") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("/") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(";") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) // FIXME - duplicate "Return" + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("P") PORT_CODE(KEYCODE_P) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0") PORT_CODE(KEYCODE_0) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Delete") PORT_CODE(KEYCODE_BACKSPACE) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Additional Options") + + PORT_START("KBD12") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("]") PORT_CODE(KEYCODE_CLOSEBRACE) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Select") PORT_CODE(KEYCODE_DEL) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Help") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Find") PORT_CODE(KEYCODE_INSERT) + + PORT_START("KBD13") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("[") PORT_CODE(KEYCODE_OPENBRACE) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Previous") PORT_CODE(KEYCODE_END) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Insert Here") PORT_CODE(KEYCODE_HOME) + + PORT_START("KBD14") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 0") PORT_CODE(KEYCODE_0_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 1") PORT_CODE(KEYCODE_1_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 4") PORT_CODE(KEYCODE_4_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 7") PORT_CODE(KEYCODE_7_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Remove") PORT_CODE(KEYCODE_PGUP) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Next") PORT_CODE(KEYCODE_PGDN) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_NUMLOCK) + + PORT_START("KBD15") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) // FIXME - duplicate "Num 0" + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 2") PORT_CODE(KEYCODE_2_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 5") PORT_CODE(KEYCODE_5_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 8") PORT_CODE(KEYCODE_8_PAD) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF2") PORT_CODE(KEYCODE_SLASH_PAD) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F17") + + PORT_START("KBD16") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 3") PORT_CODE(KEYCODE_3_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 6") PORT_CODE(KEYCODE_6_PAD) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num 9") PORT_CODE(KEYCODE_9_PAD) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF3") PORT_CODE(KEYCODE_ASTERISK) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F18") + + PORT_START("KBD17") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER_PAD) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num ,") PORT_CODE(KEYCODE_PLUS_PAD) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num -") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF4") PORT_CODE(KEYCODE_MINUS_PAD) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F20") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F19") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor lk201_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( lk201 ); +} + //************************************************************************** // LIVE DEVICE //************************************************************************** @@ -169,7 +427,27 @@ const rom_entry *lk201_device::device_rom_region() const lk201_device::lk201_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, LK201, "DEC LK201 keyboard", tag, owner, clock, "lk201", __FILE__), - m_maincpu(*this, LK201_CPU_TAG) + device_serial_interface(mconfig, *this), + m_maincpu(*this, LK201_CPU_TAG), + m_speaker(*this, LK201_SPK_TAG), + m_kbd0(*this, "KBD0"), + m_kbd1(*this, "KBD1"), + m_kbd2(*this, "KBD2"), + m_kbd3(*this, "KBD3"), + m_kbd4(*this, "KBD4"), + m_kbd5(*this, "KBD5"), + m_kbd6(*this, "KBD6"), + m_kbd7(*this, "KBD7"), + m_kbd8(*this, "KBD8"), + m_kbd9(*this, "KBD9"), + m_kbd10(*this, "KBD10"), + m_kbd11(*this, "KBD11"), + m_kbd12(*this, "KBD12"), + m_kbd13(*this, "KBD13"), + m_kbd14(*this, "KBD14"), + m_kbd15(*this, "KBD15"), + m_kbd16(*this, "KBD16"), + m_kbd17(*this, "KBD17") { } @@ -188,6 +466,59 @@ void lk201_device::device_start() void lk201_device::device_reset() { + set_rate(4800); + set_data_frame(8, 1, PARITY_NONE, false); + + sci_status = (SCSR_TC | SCSR_TDRE); + + spi_status = 0; + spi_data = 0; + + kbd_data = 0; + led_data = 0; + + transmit_register_reset(); + receive_register_reset(); +} + +void lk201_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + device_serial_interface::device_timer(timer, id, param, ptr); +} + +void lk201_device::rcv_complete() +{ + printf("lk201 got %02x\n", get_received_char()); + sci_status |= SCSR_RDRF; + update_interrupts(); + receive_register_extract(); +} + +void lk201_device::tra_complete() +{ + sci_status |= (SCSR_TC | SCSR_TDRE); + update_interrupts(); +} + +void lk201_device::tra_callback() +{ + transmit_register_send_bit(); +} + +void lk201_device::input_callback(UINT8 state) +{ +} + +void lk201_device::update_interrupts() +{ + if (sci_ctl2 & sci_status & SCSR_INT) + { + m_maincpu->set_input_line(M68HC05EG_INT_CPI, 1); + } + else + { + m_maincpu->set_input_line(M68HC05EG_INT_CPI, 0); + } } READ8_MEMBER( lk201_device::ddr_r ) @@ -197,7 +528,7 @@ READ8_MEMBER( lk201_device::ddr_r ) WRITE8_MEMBER( lk201_device::ddr_w ) { -// printf("%02x to PORT %c DDR (PC=%x)\n", data, 'A' + offset, m_maincpu->pc()); +// printf("%02x to PORT %c DDR (PC=%x)\n", data, 'A' + offset, m_maincpu->pc()); send_port(space, offset, ports[offset] & data); @@ -208,24 +539,12 @@ READ8_MEMBER( lk201_device::ports_r ) { UINT8 incoming = 0; - switch (offset) - { - case 0: // port A - break; - - case 1: // port B - break; - - case 2: // port C - break; - } - // apply data direction registers incoming &= (ddrs[offset] ^ 0xff); // add in ddr-masked version of port writes incoming |= (ports[offset] & ddrs[offset]); -// printf("PORT %c read = %02x (DDR = %02x latch = %02x) (PC=%x)\n", 'A' + offset, ports[offset], ddrs[offset], ports[offset], m_maincpu->pc()); +// printf("PORT %c read = %02x (DDR = %02x latch = %02x) (PC=%x)\n", 'A' + offset, ports[offset], ddrs[offset], ports[offset], m_maincpu->pc()); return incoming; } @@ -239,7 +558,7 @@ WRITE8_MEMBER( lk201_device::ports_w ) void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data) { -// printf("PORT %c write %02x (DDR = %02x) (PC=%x)\n", 'A' + offset, data, ddrs[offset], m_maincpu->pc()); +// printf("PORT %c write %02x (DDR = %02x) (PC=%x)\n", 'A' + offset, data, ddrs[offset], m_maincpu->pc()); switch (offset) { @@ -250,6 +569,37 @@ void lk201_device::send_port(address_space &space, UINT8 offset, UINT8 data) break; case 2: // port C + // Check for keyboard read strobe + if (((data & 0x40) == 0) && (ports[offset] & 0x40)) + { + if (ports[0] & 0x1) kbd_data = m_kbd0->read(); + if (ports[0] & 0x2) kbd_data = m_kbd1->read(); + if (ports[0] & 0x4) kbd_data = m_kbd2->read(); + if (ports[0] & 0x8) kbd_data = m_kbd3->read(); + if (ports[0] & 0x10) kbd_data = m_kbd4->read(); + if (ports[0] & 0x20) kbd_data = m_kbd5->read(); + if (ports[0] & 0x40) kbd_data = m_kbd6->read(); + if (ports[0] & 0x80) kbd_data = m_kbd7->read(); + if (ports[1] & 0x1) kbd_data = m_kbd8->read(); + if (ports[1] & 0x2) kbd_data = m_kbd9->read(); + if (ports[1] & 0x4) kbd_data = m_kbd10->read(); + if (ports[1] & 0x8) kbd_data = m_kbd11->read(); + if (ports[1] & 0x10) kbd_data = m_kbd12->read(); + if (ports[1] & 0x20) kbd_data = m_kbd13->read(); + if (ports[1] & 0x40) kbd_data = m_kbd14->read(); + if (ports[1] & 0x80) kbd_data = m_kbd15->read(); + if (ports[2] & 0x1) kbd_data = m_kbd16->read(); + if (ports[2] & 0x2) kbd_data = m_kbd17->read(); + } + // Check for LED update strobe + if (((data & 0x80) == 0) && (ports[offset] & 0x80)) + { + // Lower nibble contains the LED values (1 = on, 0 = off) + output_set_value("led_wait", (led_data & 0x1) == 0); + output_set_value("led_comp", (led_data & 0x2) == 0); + output_set_value("led_hold", (led_data & 0x4) == 0); + output_set_value("led_lock", (led_data & 0x8) == 0); + } break; } } @@ -260,24 +610,29 @@ READ8_MEMBER( lk201_device::sci_r ) switch (offset) { - case 0: // baud rate + case SCI_BAUD: // Baud rate break; - case 1: // control 1 + case SCI_SCCR1: // Control 1 break; - case 2: // control 2 + case SCI_SCCR2: // Control 2 + incoming = sci_ctl2; break; - case 3: // status - incoming |= 0x40; // indicate transmit ready + case SCI_SCSR: // Status + incoming = sci_status; break; - case 4: // data + case SCI_SCDR: // Data + incoming = get_received_char(); + sci_status &= ~SCSR_RDRF; + m_maincpu->set_input_line(M68HC05EG_INT_CPI, 0); + update_interrupts(); break; } -// printf("SCI read @ %x = %02x (PC=%x)\n", offset, incoming, m_maincpu->pc()); +// printf("SCI read @ %x = %02x (PC=%x)\n", offset, incoming, m_maincpu->pc()); return incoming; } @@ -286,23 +641,29 @@ WRITE8_MEMBER( lk201_device::sci_w ) { switch (offset) { - case 0: // baud rate + case SCI_BAUD: // Baud rate break; - case 1: // control 1 + case SCI_SCCR1: // Control 1 break; - case 2: // control 2 + case SCI_SCCR2: // Control 2 + sci_ctl2 = data; + update_interrupts(); break; - case 3: // status + case SCI_SCSR: // Status break; - case 4: // data + case SCI_SCDR: // Data + transmit_register_setup(data); + sci_status &= ~(SCSR_TC | SCSR_TDRE); + m_maincpu->set_input_line(M68HC05EG_INT_CPI, 0); + update_interrupts(); break; } -// printf("SCI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc()); +// printf("SCI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc()); } READ8_MEMBER( lk201_device::spi_r ) @@ -311,18 +672,20 @@ READ8_MEMBER( lk201_device::spi_r ) switch (offset) { - case 0: // control + case SPI_SPCR: // Control break; - case 1: // status - incoming |= 0x80; + case SPI_SPSR: // Status + incoming = spi_status; + spi_status &= ~SPSR_SPIF; break; - case 2: // data + case SPI_SPDR: // Data I/O + incoming = spi_data; break; } -// printf("SPI read @ %x = %02x (PC=%x)\n", offset, incoming, m_maincpu->pc()); +// printf("SPI read @ %x = %02x (PC=%x)\n", offset, incoming, m_maincpu->pc()); return incoming; } @@ -331,24 +694,30 @@ WRITE8_MEMBER( lk201_device::spi_w ) { switch (offset) { - case 0: // control + case SPI_SPCR: // Control break; - case 1: // status + case SPI_SPSR: // Status (read only) break; - case 2: // data + case SPI_SPDR: // Data I/O + spi_data = data; + + // Transfer only allowed if transfer complete flag has been acknowleged + if ((spi_status & SPSR_SPIF) == 0) + { + // Data out + led_data = data; + + // Data in + spi_data = kbd_data; + + // Indicate transfer complete + spi_status |= SPSR_SPIF; + } break; } -// printf("SPI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc()); +// printf("SPI %02x to %x (PC=%x)\n", data, offset, m_maincpu->pc()); } -/* - -SCI 01 to 4 (PC=24b) firmware ID -SCI 00 to 4 (PC=cb2) hardware jumpers ID (port C & 0x30) -SCI 00 to 4 (PC=cb2) self-test result OK -SCI 00 to 4 (PC=cb2) keycode if there was a self-test error - -*/ diff --git a/src/mess/machine/dec_lk201.h b/src/mess/machine/dec_lk201.h index 96f1c187cd8..fb3151d9c8e 100644 --- a/src/mess/machine/dec_lk201.h +++ b/src/mess/machine/dec_lk201.h @@ -4,6 +4,7 @@ #define __LK201_H__ #include "emu.h" +#include "sound/beep.h" //************************************************************************** // MACROS / CONSTANTS @@ -44,7 +45,7 @@ // ======================> lk201_device -class lk201_device : public device_t +class lk201_device : public device_t, public device_serial_interface { public: // construction/destruction @@ -61,18 +62,56 @@ public: protected: // device-level overrides - virtual void device_start(); - virtual void device_reset(); virtual machine_config_constructor device_mconfig_additions() const; virtual const rom_entry *device_rom_region() const; + virtual ioport_constructor device_input_ports() const; + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); - required_device m_maincpu; + // device_serial overrides + virtual void rcv_complete(); // Rx completed receiving byte + virtual void tra_complete(); // Tx completed sending byte + virtual void tra_callback(); // Tx send bit + void input_callback(UINT8 state); private: UINT8 ddrs[3]; UINT8 ports[3]; + UINT8 led_data; + UINT8 kbd_data; + + UINT8 sci_ctl2; + UINT8 sci_status; + UINT8 sci_data; + + UINT8 spi_status; + UINT8 spi_data; + + required_device m_maincpu; + required_device m_speaker; + + required_ioport m_kbd0; + required_ioport m_kbd1; + required_ioport m_kbd2; + required_ioport m_kbd3; + required_ioport m_kbd4; + required_ioport m_kbd5; + required_ioport m_kbd6; + required_ioport m_kbd7; + required_ioport m_kbd8; + required_ioport m_kbd9; + required_ioport m_kbd10; + required_ioport m_kbd11; + required_ioport m_kbd12; + required_ioport m_kbd13; + required_ioport m_kbd14; + required_ioport m_kbd15; + required_ioport m_kbd16; + required_ioport m_kbd17; void send_port(address_space &space, UINT8 offset, UINT8 data); + void update_interrupts(); }; // device type definition