trunk/src/mess/drivers/ngen.c
| r242151 | r242152 | |
| 4 | 4 | |
| 5 | 5 | 10-11-14 - Skeleton driver |
| 6 | 6 | |
| 7 | Interrupts based on patents: |
| 8 | level 1 - SIO |
| 9 | level 3 - timer (from PIT, presumably channel 0? Patent says "channel 3") |
| 10 | level 4 - "interrupt detector" - keyboard, printer, RTC |
| 11 | level 7 - floppy/hard disk |
| 7 | 12 | */ |
| 8 | 13 | |
| 9 | 14 | #include "emu.h" |
| r242151 | r242152 | |
| 16 | 21 | #include "machine/pit8253.h" |
| 17 | 22 | #include "machine/z80dart.h" |
| 18 | 23 | #include "bus/rs232/rs232.h" |
| 24 | #include "machine/ngen_kb.h" |
| 25 | #include "machine/clock.h" |
| 19 | 26 | |
| 20 | 27 | class ngen_state : public driver_device |
| 21 | 28 | { |
| r242151 | r242152 | |
| 36 | 43 | DECLARE_WRITE_LINE_MEMBER(pit_out0_w); |
| 37 | 44 | DECLARE_WRITE_LINE_MEMBER(pit_out1_w); |
| 38 | 45 | DECLARE_WRITE_LINE_MEMBER(pit_out2_w); |
| 46 | DECLARE_WRITE_LINE_MEMBER(cpu_timer_w); |
| 47 | DECLARE_WRITE_LINE_MEMBER(timer_clk_out); |
| 39 | 48 | DECLARE_WRITE16_MEMBER(cpu_peripheral_cb); |
| 40 | 49 | DECLARE_WRITE16_MEMBER(peripheral_w); |
| 41 | 50 | DECLARE_READ16_MEMBER(peripheral_r); |
| 42 | 51 | DECLARE_WRITE16_MEMBER(port00_w); |
| 43 | 52 | DECLARE_READ16_MEMBER(port00_r); |
| 44 | 53 | DECLARE_WRITE_LINE_MEMBER(dma_hrq_changed); |
| 54 | DECLARE_WRITE_LINE_MEMBER(dma_eop_changed); |
| 45 | 55 | DECLARE_WRITE_LINE_MEMBER(dack0_w); |
| 46 | 56 | DECLARE_WRITE_LINE_MEMBER(dack1_w); |
| 47 | 57 | DECLARE_WRITE_LINE_MEMBER(dack2_w); |
| 48 | 58 | DECLARE_WRITE_LINE_MEMBER(dack3_w); |
| 49 | | DECLARE_READ8_MEMBER(dma_read_byte); |
| 50 | | DECLARE_WRITE8_MEMBER(dma_write_byte); |
| 59 | DECLARE_READ8_MEMBER(dma_read_word); |
| 60 | DECLARE_WRITE8_MEMBER(dma_write_word); |
| 51 | 61 | MC6845_UPDATE_ROW(crtc_update_row); |
| 62 | // TODO: sort out what devices use which channels |
| 63 | DECLARE_READ8_MEMBER( dma_0_dack_r ) { UINT16 ret = 0xffff; m_dma_high_byte = ret & 0xff00; return ret; } |
| 64 | DECLARE_READ8_MEMBER( dma_1_dack_r ) { UINT16 ret = 0xffff; m_dma_high_byte = ret & 0xff00; return ret; } |
| 65 | DECLARE_READ8_MEMBER( dma_2_dack_r ) { UINT16 ret = 0xffff; m_dma_high_byte = ret & 0xff00; return ret; } |
| 66 | DECLARE_READ8_MEMBER( dma_3_dack_r ) { UINT16 ret = 0xffff; m_dma_high_byte = ret & 0xff00; return ret; } |
| 67 | DECLARE_WRITE8_MEMBER( dma_0_dack_w ){ popmessage("IOW: data %02x",data); } |
| 68 | DECLARE_WRITE8_MEMBER( dma_1_dack_w ){ } |
| 69 | DECLARE_WRITE8_MEMBER( dma_2_dack_w ){ } |
| 70 | DECLARE_WRITE8_MEMBER( dma_3_dack_w ){ } |
| 52 | 71 | |
| 53 | 72 | protected: |
| 73 | virtual void machine_reset(); |
| 74 | |
| 54 | 75 | private: |
| 55 | 76 | required_device<cpu_device> m_maincpu; |
| 56 | 77 | required_device<mc6845_device> m_crtc; |
| r242151 | r242152 | |
| 71 | 92 | UINT16 m_periph141; |
| 72 | 93 | UINT8 m_dma_offset[4]; |
| 73 | 94 | INT8 m_dma_channel; |
| 95 | UINT16 m_dma_high_byte; |
| 96 | UINT16 m_control; |
| 74 | 97 | }; |
| 75 | 98 | |
| 76 | 99 | WRITE_LINE_MEMBER(ngen_state::pit_out0_w) |
| 77 | 100 | { |
| 78 | | //m_pic->ir0_w(state); |
| 79 | | logerror("80186 Timer 1 state %i\n",state); |
| 101 | m_pic->ir3_w(state); // Timer interrupt |
| 102 | popmessage("PIT Timer 0 state %i\n",state); |
| 80 | 103 | } |
| 81 | 104 | |
| 82 | 105 | WRITE_LINE_MEMBER(ngen_state::pit_out1_w) |
| 83 | 106 | { |
| 84 | | logerror("PIT Timer 1 state %i\n",state); |
| 107 | popmessage("PIT Timer 1 state %i\n",state); |
| 108 | m_iouart->rxcb_w(state); |
| 109 | m_iouart->txcb_w(state); // channels in the correct order? |
| 85 | 110 | } |
| 86 | 111 | |
| 87 | 112 | WRITE_LINE_MEMBER(ngen_state::pit_out2_w) |
| 88 | 113 | { |
| 89 | 114 | m_iouart->rxca_w(state); |
| 90 | | m_iouart->rxcb_w(state); |
| 91 | 115 | m_iouart->txca_w(state); |
| 92 | | m_iouart->txcb_w(state); |
| 116 | //logerror("PIT Timer 2 state %i\n",state); |
| 93 | 117 | } |
| 94 | 118 | |
| 119 | WRITE_LINE_MEMBER(ngen_state::cpu_timer_w) |
| 120 | { |
| 121 | logerror("80186 Timer 1 state %i\n",state); |
| 122 | } |
| 123 | |
| 124 | WRITE_LINE_MEMBER(ngen_state::timer_clk_out) |
| 125 | { |
| 126 | m_viduart->write_rxc(state); // Keyboard UART Rx/Tx clocks |
| 127 | m_viduart->write_txc(state); |
| 128 | } |
| 129 | |
| 95 | 130 | WRITE16_MEMBER(ngen_state::cpu_peripheral_cb) |
| 96 | 131 | { |
| 97 | 132 | UINT32 addr; |
| r242151 | r242152 | |
| 184 | 219 | m_crtc->register_w(space,0,data & 0xff); |
| 185 | 220 | break; |
| 186 | 221 | case 0x146: |
| 187 | | logerror("Video write offset 0x146 data %04x mask %04x\n",data,mem_mask); |
| 222 | if(mem_mask & 0x00ff) |
| 223 | m_viduart->data_w(space,0,data & 0xff); |
| 188 | 224 | break; |
| 189 | 225 | case 0x147: |
| 190 | | //logerror("Video write offset 0x147 data %04x mask %04x\n",data,mem_mask); |
| 226 | if(mem_mask & 0x00ff) |
| 227 | m_viduart->control_w(space,0,data & 0xff); |
| 191 | 228 | break; |
| 192 | 229 | case 0x1a0: // serial? |
| 193 | 230 | logerror("(PC=%06x) Serial(?) 0x1a0 write offset %04x data %04x mask %04x\n",m_maincpu->device_t::safe_pc(),offset,data,mem_mask); |
| r242151 | r242152 | |
| 257 | 294 | ret = m_crtc->register_r(space,0); |
| 258 | 295 | break; |
| 259 | 296 | case 0x146: |
| 297 | if(mem_mask & 0x00ff) |
| 298 | ret = m_viduart->data_r(space,0); |
| 260 | 299 | break; |
| 261 | | case 0x147: // definitely video related, maybe UART sending data to the monitor? |
| 262 | | // expects bit 0 to be set (Video ready signal?) |
| 263 | | ret = 0; |
| 264 | | ret |= 1; |
| 300 | case 0x147: // keyboard UART |
| 301 | // expects bit 0 to be set (UART transmit ready) |
| 302 | if(mem_mask & 0x00ff) |
| 303 | ret = m_viduart->status_r(space,0); |
| 265 | 304 | break; |
| 266 | | case 0x1a0: // status? |
| 267 | | ret = 0; |
| 268 | | ret |= 0x02; // end of DMA transfer? |
| 305 | case 0x1a0: // I/O control register? |
| 306 | ret = m_control; // end of DMA transfer? (maybe a per-channel EOP?) Add a '| 0x40' to force a serial I/O failure, so that the keyboard can be tested |
| 269 | 307 | break; |
| 270 | 308 | case 0x1b1: |
| 271 | 309 | ret = 0; |
| r242151 | r242152 | |
| 299 | 337 | m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE); |
| 300 | 338 | } |
| 301 | 339 | |
| 340 | WRITE_LINE_MEMBER( ngen_state::dma_eop_changed ) |
| 341 | { |
| 342 | if(m_dma_channel == 0) |
| 343 | { |
| 344 | if(state) |
| 345 | m_control |= 0x02; |
| 346 | else |
| 347 | m_control &= ~0x02; |
| 348 | } |
| 349 | } |
| 350 | |
| 302 | 351 | void ngen_state::set_dma_channel(int channel, int state) |
| 303 | 352 | { |
| 304 | 353 | if(!state) |
| r242151 | r242152 | |
| 312 | 361 | WRITE_LINE_MEMBER( ngen_state::dack2_w ) { set_dma_channel(2, state); } |
| 313 | 362 | WRITE_LINE_MEMBER( ngen_state::dack3_w ) { set_dma_channel(3, state); } |
| 314 | 363 | |
| 315 | | READ8_MEMBER(ngen_state::dma_read_byte) |
| 364 | READ8_MEMBER(ngen_state::dma_read_word) |
| 316 | 365 | { |
| 317 | 366 | address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space |
| 318 | | UINT8 result; |
| 367 | UINT16 result; |
| 319 | 368 | if(m_dma_channel == -1) |
| 320 | 369 | return 0xff; |
| 321 | | offs_t page_offset = (((offs_t) m_dma_offset[m_dma_channel]) << 16) & 0xFF0000; |
| 370 | offs_t page_offset = (((offs_t) m_dma_offset[m_dma_channel]) << 16) & 0xFE0000; |
| 322 | 371 | |
| 323 | | result = prog_space.read_byte(page_offset + offset); |
| 324 | | popmessage("DMA byte address %06x read %02x\n",page_offset+offset,result); |
| 325 | | return result; |
| 372 | result = prog_space.read_word(page_offset + (offset << 1)); |
| 373 | m_dma_high_byte = result & 0xFF00; |
| 374 | popmessage("DMA byte address %06x read %04x\n",page_offset+(offset<<1),result); |
| 375 | return result & 0xff; |
| 326 | 376 | } |
| 327 | 377 | |
| 328 | 378 | |
| 329 | | WRITE8_MEMBER(ngen_state::dma_write_byte) |
| 379 | WRITE8_MEMBER(ngen_state::dma_write_word) |
| 330 | 380 | { |
| 331 | 381 | address_space& prog_space = m_maincpu->space(AS_PROGRAM); // get the right address space |
| 332 | 382 | if(m_dma_channel == -1) |
| 333 | 383 | return; |
| 334 | | offs_t page_offset = (((offs_t) m_dma_offset[m_dma_channel]) << 16) & 0xFF0000; |
| 384 | offs_t page_offset = (((offs_t) m_dma_offset[m_dma_channel]) << 16) & 0xFE0000; |
| 335 | 385 | |
| 336 | | prog_space.write_byte(page_offset + offset, data); |
| 337 | | popmessage("DMA byte address %06x write %02x\n",page_offset+offset,data); |
| 386 | prog_space.write_word(page_offset + (offset << 1), data); |
| 387 | popmessage("DMA byte address %06x write %04x\n",page_offset+(offset<<1), m_dma_high_byte | data); |
| 338 | 388 | } |
| 339 | 389 | |
| 340 | 390 | |
| r242151 | r242152 | |
| 355 | 405 | } |
| 356 | 406 | } |
| 357 | 407 | |
| 408 | void ngen_state::machine_reset() |
| 409 | { |
| 410 | m_control = 0; |
| 411 | m_viduart->write_dsr(0); |
| 412 | m_viduart->write_cts(0); |
| 413 | } |
| 414 | |
| 358 | 415 | static ADDRESS_MAP_START( ngen_mem, AS_PROGRAM, 16, ngen_state ) |
| 359 | 416 | AM_RANGE(0x00000, 0xf7fff) AM_RAM |
| 360 | 417 | AM_RANGE(0xf8000, 0xf9fff) AM_RAM AM_SHARE("vram") |
| r242151 | r242152 | |
| 385 | 442 | static INPUT_PORTS_START( ngen ) |
| 386 | 443 | INPUT_PORTS_END |
| 387 | 444 | |
| 445 | static SLOT_INTERFACE_START(keyboard) |
| 446 | SLOT_INTERFACE("ngen", NGEN_KEYBOARD) |
| 447 | SLOT_INTERFACE_END |
| 448 | |
| 388 | 449 | static MACHINE_CONFIG_START( ngen, ngen_state ) |
| 389 | 450 | // basic machine hardware |
| 390 | 451 | MCFG_CPU_ADD("maincpu", I80186, XTAL_16MHz / 2) |
| 391 | 452 | MCFG_CPU_PROGRAM_MAP(ngen_mem) |
| 392 | 453 | MCFG_CPU_IO_MAP(ngen_io) |
| 393 | 454 | MCFG_80186_CHIP_SELECT_CB(WRITE16(ngen_state, cpu_peripheral_cb)) |
| 394 | | MCFG_80186_TMROUT1_HANDLER(WRITELINE(ngen_state, pit_out0_w)) |
| 455 | MCFG_80186_TMROUT1_HANDLER(WRITELINE(ngen_state, cpu_timer_w)) |
| 395 | 456 | |
| 396 | 457 | MCFG_PIC8259_ADD( "pic", INPUTLINE("maincpu", 0), VCC, NULL ) |
| 397 | 458 | |
| 398 | 459 | MCFG_DEVICE_ADD("pit", PIT8254, 0) |
| 399 | | MCFG_PIT8253_CLK0(XTAL_14_7456MHz/8) // correct? |
| 400 | | MCFG_PIT8253_OUT0_HANDLER(WRITELINE(ngen_state, pit_out0_w)) |
| 401 | | MCFG_PIT8253_CLK1(XTAL_14_7456MHz/8) |
| 402 | | MCFG_PIT8253_OUT1_HANDLER(WRITELINE(ngen_state, pit_out1_w)) |
| 403 | | MCFG_PIT8253_CLK2(XTAL_14_7456MHz/8) |
| 460 | MCFG_PIT8253_CLK0(78120/4) // 19.53kHz, /4 of the CPU timer output? |
| 461 | MCFG_PIT8253_OUT0_HANDLER(WRITELINE(ngen_state, pit_out0_w)) // RS232 channel B baud rate |
| 462 | MCFG_PIT8253_CLK1(XTAL_14_7456MHz/12) // correct? - based on patent |
| 463 | MCFG_PIT8253_OUT1_HANDLER(WRITELINE(ngen_state, pit_out1_w)) // RS232 channel A baud rate |
| 464 | MCFG_PIT8253_CLK2(XTAL_14_7456MHz/12) |
| 404 | 465 | MCFG_PIT8253_OUT2_HANDLER(WRITELINE(ngen_state, pit_out2_w)) |
| 405 | 466 | |
| 406 | 467 | MCFG_DEVICE_ADD("dmac", AM9517A, XTAL_14_7456MHz / 3) // NEC D8237A, divisor unknown |
| 407 | 468 | MCFG_I8237_OUT_HREQ_CB(WRITELINE(ngen_state, dma_hrq_changed)) |
| 408 | | MCFG_I8237_IN_MEMR_CB(READ8(ngen_state, dma_read_byte)) |
| 409 | | MCFG_I8237_OUT_MEMW_CB(WRITE8(ngen_state, dma_write_byte)) |
| 469 | MCFG_I8237_OUT_EOP_CB(WRITELINE(ngen_state, dma_eop_changed)) |
| 470 | MCFG_I8237_IN_MEMR_CB(READ8(ngen_state, dma_read_word)) // DMA is always 16-bit |
| 471 | MCFG_I8237_OUT_MEMW_CB(WRITE8(ngen_state, dma_write_word)) |
| 410 | 472 | MCFG_I8237_OUT_DACK_0_CB(WRITELINE(ngen_state, dack0_w)) |
| 411 | 473 | MCFG_I8237_OUT_DACK_1_CB(WRITELINE(ngen_state, dack1_w)) |
| 412 | 474 | MCFG_I8237_OUT_DACK_2_CB(WRITELINE(ngen_state, dack2_w)) |
| 413 | 475 | MCFG_I8237_OUT_DACK_3_CB(WRITELINE(ngen_state, dack3_w)) |
| 476 | MCFG_I8237_IN_IOR_0_CB(READ8(ngen_state, dma_0_dack_r)) |
| 477 | MCFG_I8237_IN_IOR_1_CB(READ8(ngen_state, dma_1_dack_r)) |
| 478 | MCFG_I8237_IN_IOR_2_CB(READ8(ngen_state, dma_2_dack_r)) |
| 479 | MCFG_I8237_IN_IOR_3_CB(READ8(ngen_state, dma_3_dack_r)) |
| 480 | MCFG_I8237_OUT_IOW_0_CB(WRITE8(ngen_state, dma_0_dack_w)) |
| 481 | MCFG_I8237_OUT_IOW_1_CB(WRITE8(ngen_state, dma_1_dack_w)) |
| 482 | MCFG_I8237_OUT_IOW_2_CB(WRITE8(ngen_state, dma_2_dack_w)) |
| 483 | MCFG_I8237_OUT_IOW_3_CB(WRITE8(ngen_state, dma_3_dack_w)) |
| 414 | 484 | |
| 415 | 485 | // I/O board |
| 416 | 486 | MCFG_UPD7201_ADD("iouart",0,0,0,0,0) // clocked by PIT channel 2? |
| r242151 | r242152 | |
| 447 | 517 | MCFG_MC6845_UPDATE_ROW_CB(ngen_state, crtc_update_row) |
| 448 | 518 | MCFG_VIDEO_SET_SCREEN("screen") |
| 449 | 519 | |
| 450 | | MCFG_DEVICE_ADD("videouart", I8251, 19980000 / 9) // divisor unknown |
| 520 | // keyboard UART (patent says i8251 is used for keyboard communications, it is located on the video board) |
| 521 | MCFG_DEVICE_ADD("videouart", I8251, 0) // main clock unknown, Rx/Tx clocks are 19.53kHz |
| 522 | MCFG_I8251_TXEMPTY_HANDLER(DEVWRITELINE("pic",pic8259_device,ir4_w)) |
| 523 | MCFG_I8251_TXD_HANDLER(DEVWRITELINE("keyboard", rs232_port_device, write_txd)) |
| 524 | MCFG_RS232_PORT_ADD("keyboard", keyboard, "ngen") |
| 525 | MCFG_RS232_RXD_HANDLER(DEVWRITELINE("videouart", i8251_device, write_rxd)) |
| 526 | |
| 527 | MCFG_DEVICE_ADD("refresh_clock", CLOCK, 19200*16) // should be 19530Hz |
| 528 | MCFG_CLOCK_SIGNAL_HANDLER(WRITELINE(ngen_state,timer_clk_out)) |
| 451 | 529 | |
| 452 | 530 | MACHINE_CONFIG_END |
| 453 | 531 | |
trunk/src/mess/machine/ngen_kb.c
| r0 | r242152 | |
| 1 | // Convergent NGEN keyboard device |
| 2 | |
| 3 | #include "ngen_kb.h" |
| 4 | |
| 5 | ngen_keyboard_device::ngen_keyboard_device(const machine_config& mconfig, const char* tag, device_t* owner, UINT32 clock) : |
| 6 | serial_keyboard_device(mconfig, NGEN_KEYBOARD, "NGEN Keyboard", tag, owner, 0, "ngen_keyboard", __FILE__), |
| 7 | m_keys_down(false) |
| 8 | { |
| 9 | } |
| 10 | |
| 11 | |
| 12 | void ngen_keyboard_device::write(UINT8 data) |
| 13 | { |
| 14 | // To be figured out |
| 15 | logerror("KB: received character %02x\n",data); |
| 16 | } |
| 17 | |
| 18 | UINT8 ngen_keyboard_device::row_number(UINT8 code) |
| 19 | { |
| 20 | if BIT(code,0) return 0; |
| 21 | if BIT(code,1) return 1; |
| 22 | if BIT(code,2) return 2; |
| 23 | if BIT(code,3) return 3; |
| 24 | if BIT(code,4) return 4; |
| 25 | if BIT(code,5) return 5; |
| 26 | if BIT(code,6) return 6; |
| 27 | if BIT(code,7) return 7; |
| 28 | return 0; |
| 29 | } |
| 30 | |
| 31 | UINT8 ngen_keyboard_device::keyboard_handler(UINT8 last_code, UINT8 *scan_line) |
| 32 | { |
| 33 | int i; |
| 34 | UINT8 code = 0; |
| 35 | UINT8 key_code = 0; |
| 36 | UINT8 retVal = 0; |
| 37 | UINT8 shift = BIT(m_io_kbdc->read(), 1); |
| 38 | UINT8 caps = BIT(m_io_kbdc->read(), 2); |
| 39 | UINT8 ctrl = BIT(m_io_kbdc->read(), 0); |
| 40 | i = *scan_line; |
| 41 | { |
| 42 | if (i == 0) code = m_io_kbd0->read(); |
| 43 | else |
| 44 | if (i == 1) code = m_io_kbd1->read(); |
| 45 | else |
| 46 | if (i == 2) code = m_io_kbd2->read(); |
| 47 | else |
| 48 | if (i == 3) code = m_io_kbd3->read(); |
| 49 | else |
| 50 | if (i == 4) code = m_io_kbd4->read(); |
| 51 | else |
| 52 | if (i == 5) code = m_io_kbd5->read(); |
| 53 | else |
| 54 | if (i == 6) code = m_io_kbd6->read(); |
| 55 | else |
| 56 | if (i == 7) code = m_io_kbd7->read(); |
| 57 | else |
| 58 | if (i == 8) code = m_io_kbd8->read(); |
| 59 | else |
| 60 | if (i == 9) code = m_io_kbd9->read(); |
| 61 | |
| 62 | if (code != 0) |
| 63 | { |
| 64 | if (i==0 && shift==0) { |
| 65 | key_code = 0x30 + row_number(code) + 8*i; // for numbers and some signs |
| 66 | } |
| 67 | if (i==0 && shift==1) { |
| 68 | key_code = 0x20 + row_number(code) + 8*i; // for shifted numbers |
| 69 | } |
| 70 | if (i==1 && shift==0) { |
| 71 | if (row_number(code) < 4) { |
| 72 | key_code = 0x30 + row_number(code) + 8*i; // for numbers and some signs |
| 73 | } else { |
| 74 | key_code = 0x20 + row_number(code) + 8*i; // for numbers and some signs |
| 75 | } |
| 76 | } |
| 77 | if (i==1 && shift==1) { |
| 78 | if (row_number(code) < 4) { |
| 79 | key_code = 0x20 + row_number(code) + 8*i; // for numbers and some signs |
| 80 | } else { |
| 81 | key_code = 0x30 + row_number(code) + 8*i; // for numbers and some signs |
| 82 | } |
| 83 | } |
| 84 | if (i>=2 && i<=4 && (shift ^ caps)==0 && ctrl==0) { |
| 85 | key_code = 0x60 + row_number(code) + (i-2)*8; // for small letters |
| 86 | } |
| 87 | if (i>=2 && i<=4 && (shift ^ caps)==1 && ctrl==0) { |
| 88 | key_code = 0x40 + row_number(code) + (i-2)*8; // for big letters |
| 89 | } |
| 90 | if (i>=2 && i<=5 && ctrl==1) { |
| 91 | key_code = 0x00 + row_number(code) + (i-2)*8; // for CTRL + letters |
| 92 | } |
| 93 | if (i==5 && shift==1 && ctrl==0) { |
| 94 | if (row_number(code)<7) { |
| 95 | if (row_number(code)<3) { |
| 96 | key_code = (caps ? 0x60 : 0x40) + row_number(code) + (i-2)*8; // for big letters |
| 97 | } else { |
| 98 | key_code = 0x60 + row_number(code) + (i-2)*8; // for upper symbols letters |
| 99 | } |
| 100 | } else { |
| 101 | key_code = 0x40 + row_number(code) + (i-2)*8; // for DEL it is switched |
| 102 | } |
| 103 | } |
| 104 | if (i==5 && shift==0 && ctrl==0) { |
| 105 | if (row_number(code)<7) { |
| 106 | if (row_number(code)<3) { |
| 107 | key_code = (caps ? 0x40 : 0x60) + row_number(code) + (i-2)*8; // for small letters |
| 108 | } else { |
| 109 | key_code = 0x40 + row_number(code) + (i-2)*8; // for lower symbols letters |
| 110 | } |
| 111 | } else { |
| 112 | key_code = 0x60 + row_number(code) + (i-2)*8; // for DEL it is switched |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | if (i==6) { |
| 117 | switch(row_number(code)) |
| 118 | { |
| 119 | /* case 0: key_code = 0x11; break; |
| 120 | case 1: key_code = 0x12; break; |
| 121 | case 2: key_code = 0x13; break; |
| 122 | case 3: key_code = 0x14; break;*/ |
| 123 | case 4: key_code = 0x20; break; // Space |
| 124 | case 5: key_code = 0x0A; break; // LineFeed |
| 125 | case 6: key_code = 0x09; break; // TAB |
| 126 | case 7: key_code = 0x0D; break; // Enter |
| 127 | } |
| 128 | } |
| 129 | if (i==7) |
| 130 | { |
| 131 | switch(row_number(code)) |
| 132 | { |
| 133 | case 0: key_code = 0x1B; break; // Escape |
| 134 | case 1: key_code = 0x08; break; // Backspace |
| 135 | } |
| 136 | } |
| 137 | else |
| 138 | if (i==8) |
| 139 | { |
| 140 | key_code = row_number(code)+0x81; |
| 141 | if (ctrl) key_code+=0x10; |
| 142 | if (shift) key_code+=0x20; |
| 143 | } |
| 144 | else |
| 145 | if (i==9) |
| 146 | { |
| 147 | key_code = row_number(code)+0x89; |
| 148 | if (ctrl) key_code+=0x10; |
| 149 | if (shift) key_code+=0x20; |
| 150 | } |
| 151 | m_keys_down = true; |
| 152 | retVal = key_code; |
| 153 | } |
| 154 | else |
| 155 | { |
| 156 | *scan_line += 1; |
| 157 | if (*scan_line==10) |
| 158 | *scan_line = 0; |
| 159 | if(m_keys_down) |
| 160 | { |
| 161 | retVal = 0xc0; |
| 162 | m_keys_down = false; |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | // TODO: add scan code 0xc0 (all keys up) |
| 167 | return retVal; |
| 168 | } |
| 169 | |
| 170 | static INPUT_PORTS_START( ngen_keyboard ) |
| 171 | PORT_INCLUDE(generic_keyboard) |
| 172 | |
| 173 | PORT_START("RS232_TXBAUD") |
| 174 | PORT_CONFNAME(0xff, RS232_BAUD_19200, "TX Baud") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, serial_keyboard_device, update_serial) |
| 175 | PORT_CONFSETTING( RS232_BAUD_19200, "19200") // TODO: Based on the RAM refresh timer (~78kHz) to be 19530Hz |
| 176 | |
| 177 | PORT_START("RS232_STARTBITS") |
| 178 | PORT_CONFNAME(0xff, RS232_STARTBITS_1, "Start Bits") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, serial_keyboard_device, update_serial) |
| 179 | PORT_CONFSETTING( RS232_STARTBITS_1, "1") |
| 180 | |
| 181 | PORT_START("RS232_DATABITS") |
| 182 | PORT_CONFNAME(0xff, RS232_DATABITS_8, "Data Bits") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, serial_keyboard_device, update_serial) |
| 183 | PORT_CONFSETTING( RS232_DATABITS_8, "8") |
| 184 | |
| 185 | PORT_START("RS232_PARITY") |
| 186 | PORT_CONFNAME(0xff, RS232_PARITY_NONE, "Parity") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, serial_keyboard_device, update_serial) |
| 187 | PORT_CONFSETTING( RS232_PARITY_NONE, "None") |
| 188 | |
| 189 | PORT_START("RS232_STOPBITS") |
| 190 | PORT_CONFNAME(0xff, RS232_STOPBITS_2, "Stop Bits") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, serial_keyboard_device, update_serial) |
| 191 | PORT_CONFSETTING( RS232_STOPBITS_2, "2") |
| 192 | INPUT_PORTS_END |
| 193 | |
| 194 | |
| 195 | ioport_constructor ngen_keyboard_device::device_input_ports() const |
| 196 | { |
| 197 | return INPUT_PORTS_NAME(ngen_keyboard); |
| 198 | } |
| 199 | |
| 200 | void ngen_keyboard_device::device_start() |
| 201 | { |
| 202 | serial_keyboard_device::device_start(); |
| 203 | set_rcv_rate(19200); |
| 204 | } |
| 205 | |
| 206 | void ngen_keyboard_device::device_reset() |
| 207 | { |
| 208 | serial_keyboard_device::device_reset(); |
| 209 | m_keys_down = false; |
| 210 | } |
| 211 | |
| 212 | void ngen_keyboard_device::rcv_complete() |
| 213 | { |
| 214 | receive_register_extract(); |
| 215 | write(get_received_char()); |
| 216 | } |
| 217 | |
| 218 | const device_type NGEN_KEYBOARD = &device_creator<ngen_keyboard_device>; |
| 219 | |