trunk/src/emu/bus/rs232/ser_mouse.h
| r32152 | r32153 | |
| 21 | 21 | |
| 22 | 22 | protected: |
| 23 | 23 | virtual void device_start(); |
| 24 | | virtual void device_reset(); |
| 25 | 24 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 26 | 25 | virtual void mouse_trans(int dx, int dy, int nb, int mbc) = 0; |
| 27 | 26 | virtual void set_frame() = 0; |
| r32152 | r32153 | |
| 30 | 29 | UINT8 unqueue_data() {UINT8 ret = m_queue[m_tail]; ++m_tail %= 256; return ret;} |
| 31 | 30 | virtual void tra_complete(); |
| 32 | 31 | virtual void tra_callback(); |
| 32 | void reset_mouse(); |
| 33 | |
| 34 | virtual WRITE_LINE_MEMBER(input_dtr); |
| 35 | virtual WRITE_LINE_MEMBER(input_rts); |
| 36 | int m_dtr; |
| 37 | int m_rts; |
| 38 | |
| 33 | 39 | private: |
| 34 | 40 | UINT8 m_queue[256]; |
| 35 | 41 | UINT8 m_head, m_tail, m_mb; |
| r32152 | r32153 | |
| 40 | 46 | required_ioport m_x; |
| 41 | 47 | required_ioport m_y; |
| 42 | 48 | required_ioport m_btn; |
| 49 | |
| 50 | void check_state() { set_mouse_enable(!m_dtr && !m_rts); } |
| 43 | 51 | }; |
| 44 | 52 | |
| 45 | 53 | class microsoft_mouse_device : public serial_mouse_device |
| 46 | 54 | { |
| 47 | 55 | public: |
| 48 | 56 | microsoft_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 49 | | virtual DECLARE_WRITE_LINE_MEMBER( input_dtr ) { m_dtr = state; check_state(); } |
| 50 | | virtual DECLARE_WRITE_LINE_MEMBER( input_rts ) { m_rts = state; check_state(); m_old_rts = state; } |
| 51 | 57 | |
| 52 | 58 | protected: |
| 59 | virtual WRITE_LINE_MEMBER(input_rts); |
| 60 | |
| 53 | 61 | virtual void set_frame() { set_data_frame(1, 7, PARITY_NONE, STOP_BITS_2); } |
| 54 | 62 | virtual void mouse_trans(int dx, int dy, int nb, int mbc); |
| 55 | | virtual void device_reset() {m_old_rts = 0; serial_mouse_device::device_reset();} |
| 56 | | |
| 57 | | private: |
| 58 | | void check_state(); |
| 59 | | int m_dtr; |
| 60 | | int m_rts; |
| 61 | | int m_old_rts; |
| 62 | 63 | }; |
| 63 | 64 | |
| 64 | 65 | extern const device_type MSFT_SERIAL_MOUSE; |
| r32152 | r32153 | |
| 67 | 68 | { |
| 68 | 69 | public: |
| 69 | 70 | mouse_systems_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 70 | | virtual DECLARE_WRITE_LINE_MEMBER( input_dtr ) { m_dtr = state; check_state(); } |
| 71 | | virtual DECLARE_WRITE_LINE_MEMBER( input_rts ) { m_rts = state; check_state(); } |
| 72 | 71 | |
| 73 | 72 | protected: |
| 74 | 73 | virtual void set_frame() { set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2); } |
| 75 | 74 | virtual void mouse_trans(int dx, int dy, int nb, int mbc); |
| 76 | | |
| 77 | | private: |
| 78 | | void check_state() { set_mouse_enable((m_dtr && m_rts)?true:false); } |
| 79 | | int m_dtr; |
| 80 | | int m_rts; |
| 81 | 75 | }; |
| 82 | 76 | |
| 83 | 77 | extern const device_type MSYSTEM_SERIAL_MOUSE; |
trunk/src/emu/bus/rs232/ser_mouse.c
| r32152 | r32153 | |
| 13 | 13 | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 14 | 14 | device_rs232_port_interface(mconfig, *this), |
| 15 | 15 | device_serial_interface(mconfig, *this), |
| 16 | m_dtr(1), |
| 17 | m_rts(1), |
| 16 | 18 | m_x(*this, "ser_mouse_x"), |
| 17 | 19 | m_y(*this, "ser_mouse_y"), |
| 18 | 20 | m_btn(*this, "ser_mouse_btn") |
| r32152 | r32153 | |
| 23 | 25 | |
| 24 | 26 | microsoft_mouse_device::microsoft_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 25 | 27 | : serial_mouse_device(mconfig, MSFT_SERIAL_MOUSE, "Microsoft Serial Mouse", tag, owner, clock, "microsoft_mouse", __FILE__) |
| 26 | | , m_dtr(0) |
| 27 | 28 | { |
| 28 | 29 | } |
| 29 | 30 | |
| r32152 | r32153 | |
| 40 | 41 | m_enabled = false; |
| 41 | 42 | set_frame(); |
| 42 | 43 | set_tra_rate(1200); |
| 44 | reset_mouse(); |
| 45 | |
| 46 | save_item(NAME(m_dtr)); |
| 47 | save_item(NAME(m_rts)); |
| 48 | save_item(NAME(m_queue)); |
| 49 | save_item(NAME(m_head)); |
| 50 | save_item(NAME(m_tail)); |
| 51 | save_item(NAME(m_mb)); |
| 52 | save_item(NAME(m_enabled)); |
| 43 | 53 | } |
| 44 | 54 | |
| 45 | | void serial_mouse_device::device_reset() |
| 55 | void serial_mouse_device::reset_mouse() |
| 46 | 56 | { |
| 47 | 57 | m_head = m_tail = 0; |
| 48 | 58 | output_rxd(1); |
| r32152 | r32153 | |
| 202 | 212 | |
| 203 | 213 | } |
| 204 | 214 | |
| 205 | | void microsoft_mouse_device::check_state() |
| 215 | |
| 216 | WRITE_LINE_MEMBER(serial_mouse_device::input_dtr) |
| 206 | 217 | { |
| 207 | | if (m_dtr && m_rts) |
| 218 | m_dtr = state; |
| 219 | check_state(); |
| 220 | } |
| 221 | |
| 222 | WRITE_LINE_MEMBER(serial_mouse_device::input_rts) |
| 223 | { |
| 224 | m_rts = state; |
| 225 | check_state(); |
| 226 | } |
| 227 | |
| 228 | WRITE_LINE_MEMBER(microsoft_mouse_device::input_rts) |
| 229 | { |
| 230 | if (!m_dtr && m_rts && !state) |
| 208 | 231 | { |
| 209 | | /* RTS toggled */ |
| 210 | | if (!m_old_rts && m_rts) |
| 211 | | { |
| 212 | | /* reset mouse */ |
| 213 | | serial_mouse_device::device_reset(); |
| 214 | | /* Identify as Microsoft 3 Button Mouse */ |
| 215 | | queue_data('M'); |
| 216 | | queue_data('3'); |
| 217 | | } |
| 218 | | /* start a timer to scan the mouse input */ |
| 219 | | set_mouse_enable(true); |
| 232 | reset_mouse(); |
| 233 | /* Identify as Microsoft 3 Button Mouse */ |
| 234 | queue_data('M'); |
| 235 | queue_data('3'); |
| 220 | 236 | } |
| 221 | | else |
| 222 | | set_mouse_enable(false); |
| 237 | |
| 238 | serial_mouse_device::input_rts(state); |
| 223 | 239 | } |
| 224 | 240 | |
| 225 | 241 | |
trunk/src/emu/machine/ins8250.c
| r32152 | r32153 | |
| 97 | 97 | m_out_rts_cb(*this), |
| 98 | 98 | m_out_int_cb(*this), |
| 99 | 99 | m_out_out1_cb(*this), |
| 100 | | m_out_out2_cb(*this) |
| 100 | m_out_out2_cb(*this), |
| 101 | m_rxd(1), |
| 102 | m_dcd(1), |
| 103 | m_dsr(1), |
| 104 | m_ri(1), |
| 105 | m_cts(1) |
| 101 | 106 | { |
| 102 | 107 | } |
| 103 | 108 | |
| r32152 | r32153 | |
| 212 | 217 | { |
| 213 | 218 | m_regs.thr = data; |
| 214 | 219 | m_regs.lsr &= ~0x20; |
| 215 | | if ( m_regs.mcr & 0x10 ) |
| 216 | | { |
| 217 | | m_regs.lsr |= 0x61; |
| 218 | | m_regs.rbr = data; |
| 219 | | trigger_int(COM_INT_PENDING_RECEIVED_DATA_AVAILABLE); |
| 220 | | } |
| 221 | | else |
| 222 | | { |
| 223 | | if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1)) |
| 224 | | push_tx(data); |
| 225 | | clear_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); |
| 226 | | if(m_regs.lsr & 0x40) |
| 227 | | tra_complete(); |
| 228 | | } |
| 220 | if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1)) |
| 221 | push_tx(data); |
| 222 | clear_int(COM_INT_PENDING_TRANSMITTER_HOLDING_REGISTER_EMPTY); |
| 223 | if(m_regs.lsr & 0x40) |
| 224 | tra_complete(); |
| 229 | 225 | } |
| 230 | 226 | break; |
| 231 | 227 | case 1: |
| r32152 | r32153 | |
| 289 | 285 | { |
| 290 | 286 | m_regs.mcr = data & 0x1f; |
| 291 | 287 | |
| 292 | | if ( m_regs.mcr & 0x10 ) /* loopback test */ |
| 288 | update_msr(); |
| 289 | |
| 290 | if (m_regs.mcr & 0x10) /* loopback test */ |
| 293 | 291 | { |
| 294 | | data = ( ( m_regs.mcr & 0x0c ) << 4 ) | ( ( m_regs.mcr & 0x01 ) << 5 ) | ( ( m_regs.mcr & 0x02 ) << 3 ); |
| 295 | | if ( ( m_regs.msr & 0x20 ) != ( data & 0x20 ) ) |
| 296 | | data |= 0x02; |
| 297 | | if ( ( m_regs.msr & 0x10 ) != ( data & 0x10 ) ) |
| 298 | | data |= 0x01; |
| 299 | | if ( ( m_regs.msr & 0x40 ) && ! ( data & 0x40 ) ) |
| 300 | | data |= 0x04; |
| 301 | | if ( ( m_regs.msr & 0x80 ) != ( data & 0x80 ) ) |
| 302 | | data |= 0x08; |
| 303 | | m_regs.msr = data; |
| 292 | m_out_tx_cb(1); |
| 293 | device_serial_interface::rx_w(m_txd); |
| 294 | m_out_dtr_cb(1); |
| 295 | m_out_rts_cb(1); |
| 296 | m_out_out1_cb(1); |
| 297 | m_out_out2_cb(1); |
| 304 | 298 | } |
| 305 | 299 | else |
| 306 | 300 | { |
| 307 | | m_out_dtr_cb((m_regs.mcr & 1) ? 1 : 0); |
| 308 | | m_out_rts_cb((m_regs.mcr & 2) ? 1 : 0); |
| 309 | | m_out_out1_cb((m_regs.mcr & 4) ? 1 : 0); |
| 310 | | m_out_out2_cb((m_regs.mcr & 8) ? 1 : 0); |
| 301 | m_out_tx_cb(m_txd); |
| 302 | device_serial_interface::rx_w(m_rxd); |
| 303 | m_out_dtr_cb((m_regs.mcr & 1) ? 0 : 1); |
| 304 | m_out_rts_cb((m_regs.mcr & 2) ? 0 : 1); |
| 305 | m_out_out1_cb((m_regs.mcr & 4) ? 0 : 1); |
| 306 | m_out_out2_cb((m_regs.mcr & 8) ? 0 : 1); |
| 311 | 307 | } |
| 312 | 308 | } |
| 313 | 309 | break; |
| r32152 | r32153 | |
| 327 | 323 | |
| 328 | 324 | break; |
| 329 | 325 | case 6: |
| 330 | | /* |
| 331 | | This register can be written, but if you write a 1 bit into any of |
| 332 | | bits 3 - 0, you could cause an interrupt if the appropriate IER bit |
| 333 | | is set. |
| 334 | | */ |
| 335 | | m_regs.msr = data; |
| 336 | | |
| 337 | | if ( m_regs.msr & 0x0f ) |
| 338 | | trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); |
| 326 | // modem status register is read only |
| 339 | 327 | break; |
| 340 | 328 | case 7: |
| 341 | 329 | m_regs.scr = data; |
| r32152 | r32153 | |
| 354 | 342 | data = (m_regs.dl & 0xff); |
| 355 | 343 | else |
| 356 | 344 | { |
| 357 | | if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1) && !(m_regs.mcr & 0x10)) |
| 345 | if((m_device_type >= TYPE_NS16550) && (m_regs.fcr & 1)) |
| 358 | 346 | m_regs.rbr = pop_rx(); |
| 359 | 347 | else |
| 360 | 348 | { |
| r32152 | r32153 | |
| 482 | 470 | |
| 483 | 471 | void ins8250_uart_device::tra_callback() |
| 484 | 472 | { |
| 485 | | m_out_tx_cb(transmit_register_get_data_bit()); |
| 473 | m_txd = transmit_register_get_data_bit(); |
| 474 | if (m_regs.mcr & 0x10) |
| 475 | { |
| 476 | device_serial_interface::rx_w(m_txd); |
| 477 | } |
| 478 | else |
| 479 | { |
| 480 | m_out_tx_cb(m_txd); |
| 481 | } |
| 486 | 482 | } |
| 487 | 483 | |
| 488 | | void ins8250_uart_device::update_msr(int bit, UINT8 state) |
| 484 | void ins8250_uart_device::update_msr() |
| 489 | 485 | { |
| 490 | | UINT8 mask = (1<<bit); |
| 491 | | if((m_regs.msr & mask) == (state<<bit)) |
| 492 | | return; |
| 493 | | m_regs.msr |= mask; |
| 494 | | m_regs.msr = (m_regs.msr & ~(mask << 4)) | (state<<(bit+4)); |
| 495 | | trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); |
| 486 | UINT8 data; |
| 487 | |
| 488 | if (m_regs.mcr & 0x10) |
| 489 | data = ((m_regs.mcr & 0x0c) << 4) | ((m_regs.mcr & 0x01) << 5) | ((m_regs.mcr & 0x02) << 3); |
| 490 | else |
| 491 | data = (!m_dcd << 7) | (!m_ri << 6) | (!m_dsr << 5) | (!m_cts << 4); |
| 492 | |
| 493 | int change = (m_regs.msr ^ data) >> 4; |
| 494 | |
| 495 | if (change) |
| 496 | { |
| 497 | m_regs.msr = data | (m_regs.msr & 0xf) | change; |
| 498 | |
| 499 | trigger_int(COM_INT_PENDING_MODEM_STATUS_REGISTER); |
| 500 | } |
| 496 | 501 | } |
| 497 | 502 | |
| 498 | 503 | WRITE_LINE_MEMBER(ins8250_uart_device::dcd_w) |
| 499 | 504 | { |
| 500 | | update_msr(3, (state ? 1 : 0)); |
| 505 | m_dcd = state; |
| 506 | update_msr(); |
| 501 | 507 | } |
| 502 | 508 | |
| 503 | 509 | WRITE_LINE_MEMBER(ins8250_uart_device::dsr_w) |
| 504 | 510 | { |
| 505 | | update_msr(1, (state ? 1 : 0)); |
| 511 | m_dsr = state; |
| 512 | update_msr(); |
| 506 | 513 | } |
| 507 | 514 | |
| 508 | 515 | WRITE_LINE_MEMBER(ins8250_uart_device::ri_w) |
| 509 | 516 | { |
| 510 | | update_msr(2, (state ? 1 : 0)); |
| 517 | m_ri = state; |
| 518 | update_msr(); |
| 511 | 519 | } |
| 512 | 520 | |
| 513 | 521 | WRITE_LINE_MEMBER(ins8250_uart_device::cts_w) |
| 514 | 522 | { |
| 515 | | update_msr(0, (state ? 1 : 0)); |
| 523 | m_cts = state; |
| 524 | update_msr(); |
| 516 | 525 | } |
| 517 | 526 | |
| 527 | WRITE_LINE_MEMBER(ins8250_uart_device::rx_w) |
| 528 | { |
| 529 | m_rxd = state; |
| 530 | |
| 531 | if (!(m_regs.mcr & 0x10)) |
| 532 | device_serial_interface::rx_w(m_rxd); |
| 533 | } |
| 534 | |
| 518 | 535 | void ins8250_uart_device::device_start() |
| 519 | 536 | { |
| 520 | 537 | m_out_tx_cb.resolve_safe(); |
| r32152 | r32153 | |
| 525 | 542 | m_out_out2_cb.resolve_safe(); |
| 526 | 543 | set_tra_rate(0); |
| 527 | 544 | set_rcv_rate(0); |
| 528 | | memset(&m_regs, 0x00, sizeof(m_regs)); |
| 529 | 545 | |
| 530 | 546 | device_serial_interface::register_save_state(machine().save(), name(), tag()); |
| 531 | 547 | save_item(NAME(m_regs.thr)); |
| r32152 | r32153 | |
| 540 | 556 | save_item(NAME(m_regs.msr)); |
| 541 | 557 | save_item(NAME(m_regs.scr)); |
| 542 | 558 | save_item(NAME(m_int_pending)); |
| 559 | save_item(NAME(m_txd)); |
| 560 | save_item(NAME(m_rxd)); |
| 561 | save_item(NAME(m_dcd)); |
| 562 | save_item(NAME(m_dsr)); |
| 563 | save_item(NAME(m_ri)); |
| 564 | save_item(NAME(m_cts)); |
| 543 | 565 | } |
| 544 | 566 | |
| 545 | 567 | void ins8250_uart_device::device_reset() |
| 546 | 568 | { |
| 547 | | memset(&m_regs, 0x00, sizeof(m_regs)); |
| 548 | 569 | m_regs.ier = 0; |
| 549 | 570 | m_regs.iir = 1; |
| 550 | 571 | m_regs.lcr = 0; |
| 551 | 572 | m_regs.mcr = 0; |
| 552 | 573 | m_regs.lsr = (1<<5) | (1<<6); |
| 574 | update_msr(); |
| 575 | m_regs.msr &= 0xf0; |
| 553 | 576 | m_int_pending = 0; |
| 554 | 577 | receive_register_reset(); |
| 555 | 578 | transmit_register_reset(); |
| 556 | | m_out_rts_cb(0); |
| 557 | | m_out_dtr_cb(0); |
| 558 | | m_out_out1_cb(0); |
| 559 | | m_out_out2_cb(0); |
| 579 | m_txd = 1; |
| 560 | 580 | m_out_tx_cb(1); |
| 581 | m_out_rts_cb(1); |
| 582 | m_out_dtr_cb(1); |
| 583 | m_out_out1_cb(1); |
| 584 | m_out_out2_cb(1); |
| 561 | 585 | } |
| 562 | 586 | |
| 563 | 587 | void ins8250_uart_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |