trunk/src/mess/drivers/px4.c
| r26901 | r26902 | |
| 52 | 52 | #define ART_OE 0x10 // overrun error |
| 53 | 53 | #define ART_FE 0x20 // framing error |
| 54 | 54 | |
| 55 | | // art baud rates |
| 56 | | static const int transmit_rate[] = { 2112, 1536, 768, 384, 192, 96, 48, 24, 192, 3072, 12, 6, 1152 }; |
| 57 | | static const int receive_rate[] = { 2112, 1536, 768, 384, 192, 96, 48, 24, 3072, 192, 12, 6, 1152 }; |
| 58 | 55 | |
| 59 | | |
| 60 | 56 | //************************************************************************** |
| 61 | 57 | // MACROS |
| 62 | 58 | //************************************************************************** |
| 63 | 59 | |
| 64 | 60 | #define ART_TX_ENABLED (BIT(m_artcr, 0)) |
| 65 | 61 | #define ART_RX_ENABLED (BIT(m_artcr, 2)) |
| 62 | #define ART_BREAK (BIT(m_artcr, 3)) |
| 66 | 63 | |
| 67 | | #define ART_DATA (BIT(m_artmr, 2)) // number of data bits, 7 or 8 |
| 68 | | #define ART_PEN (BIT(m_artmr, 4)) // parity enabled |
| 69 | | #define ART_EVEN (BIT(m_artmr, 5)) // even or odd parity |
| 70 | | #define ART_STOP (BIT(m_artmr, 7)) // number of stop bits, 1 or 2 |
| 71 | 64 | |
| 72 | | |
| 73 | 65 | //************************************************************************** |
| 74 | 66 | // TYPE DEFINITIONS |
| 75 | 67 | //************************************************************************** |
| 76 | 68 | |
| 77 | | class px4_state : public driver_device |
| 69 | class px4_state : public driver_device, |
| 70 | public device_serial_interface |
| 78 | 71 | { |
| 79 | 72 | public: |
| 80 | | px4_state(const machine_config &mconfig, device_type type, const char *tag) |
| 81 | | : driver_device(mconfig, type, tag), |
| 82 | | m_z80(*this, "maincpu"), |
| 83 | | m_ram(*this, RAM_TAG), |
| 84 | | m_centronics(*this, "centronics"), |
| 85 | | m_ext_cas(*this, "extcas"), |
| 86 | | m_speaker(*this, "speaker"), |
| 87 | | m_sio(*this, "sio"), |
| 88 | | m_rs232(*this, "rs232") |
| 89 | | , |
| 90 | | m_maincpu(*this, "maincpu") { } |
| 73 | px4_state(const machine_config &mconfig, device_type type, const char *tag) : |
| 74 | driver_device(mconfig, type, tag), |
| 75 | device_serial_interface(mconfig, *this), |
| 76 | m_z80(*this, "maincpu"), |
| 77 | m_ram(*this, RAM_TAG), |
| 78 | m_centronics(*this, "centronics"), |
| 79 | m_ext_cas(*this, "extcas"), |
| 80 | m_ext_cas_timer(*this, "extcas_timer"), |
| 81 | m_speaker(*this, "speaker"), |
| 82 | m_sio(*this, "sio"), |
| 83 | m_rs232(*this, "rs232"), |
| 84 | m_isr(0), m_ier(0), m_str(0), m_sior(0xbf), |
| 85 | m_artdir(0xff), m_artdor(0xff), m_artsr(0), m_artcr(0), |
| 86 | m_swr(0), |
| 87 | m_one_sec_int_enabled(true), m_alarm_int_enabled(true), m_key_int_enabled(true), |
| 88 | m_ramdisk_address(0), |
| 89 | m_ear_last_state(0) |
| 90 | { } |
| 91 | 91 | |
| 92 | 92 | // internal devices |
| 93 | 93 | required_device<cpu_device> m_z80; |
| 94 | 94 | required_device<ram_device> m_ram; |
| 95 | 95 | required_device<centronics_device> m_centronics; |
| 96 | 96 | required_device<cassette_image_device> m_ext_cas; |
| 97 | required_device<timer_device> m_ext_cas_timer; |
| 97 | 98 | required_device<speaker_sound_device> m_speaker; |
| 98 | 99 | required_device<epson_sio_device> m_sio; |
| 99 | 100 | required_device<rs232_port_device> m_rs232; |
| r26901 | r26902 | |
| 123 | 124 | UINT8 m_artdir; |
| 124 | 125 | UINT8 m_artdor; |
| 125 | 126 | UINT8 m_artsr; |
| 126 | | UINT8 m_artmr; |
| 127 | 127 | UINT8 m_artcr; |
| 128 | 128 | UINT8 m_swr; |
| 129 | 129 | |
| r26901 | r26902 | |
| 143 | 143 | UINT8 *m_ramdisk; |
| 144 | 144 | |
| 145 | 145 | // external cassette/barcode reader |
| 146 | | emu_timer *m_ext_cas_timer; |
| 147 | 146 | int m_ear_last_state; |
| 148 | 147 | |
| 149 | 148 | void install_rom_capsule(address_space &space, int size, const char *region); |
| 150 | 149 | |
| 150 | // device_serial_interface overrides |
| 151 | virtual void tra_callback(); |
| 152 | virtual void tra_complete(); |
| 153 | virtual void rcv_callback(); |
| 154 | virtual void rcv_complete(); |
| 155 | virtual void input_callback(UINT8 state); |
| 156 | |
| 157 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 158 | |
| 159 | DECLARE_WRITE_LINE_MEMBER( serial_rx_w ); |
| 160 | DECLARE_WRITE_LINE_MEMBER( serial_dcd_w ); |
| 161 | DECLARE_WRITE_LINE_MEMBER( serial_dsr_w ); |
| 162 | DECLARE_WRITE_LINE_MEMBER( serial_cts_w ); |
| 163 | |
| 164 | int m_rs232_dcd; |
| 165 | int m_rs232_cts; |
| 166 | |
| 151 | 167 | DECLARE_READ8_MEMBER(px4_icrlc_r); |
| 152 | 168 | DECLARE_WRITE8_MEMBER(px4_ctrl1_w); |
| 153 | 169 | DECLARE_READ8_MEMBER(px4_icrhc_r); |
| r26901 | r26902 | |
| 187 | 203 | DECLARE_PALETTE_INIT(px4p); |
| 188 | 204 | UINT32 screen_update_px4(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 189 | 205 | DECLARE_INPUT_CHANGED_MEMBER(key_callback); |
| 190 | | TIMER_CALLBACK_MEMBER(ext_cassette_read); |
| 206 | TIMER_DEVICE_CALLBACK_MEMBER( ext_cassette_read ); |
| 191 | 207 | TIMER_CALLBACK_MEMBER(transmit_data); |
| 192 | 208 | TIMER_CALLBACK_MEMBER(receive_data); |
| 193 | 209 | TIMER_DEVICE_CALLBACK_MEMBER(frc_tick); |
| 194 | 210 | TIMER_DEVICE_CALLBACK_MEMBER(upd7508_1sec_callback); |
| 195 | | required_device<cpu_device> m_maincpu; |
| 196 | 211 | }; |
| 197 | 212 | |
| 198 | 213 | |
| r26901 | r26902 | |
| 222 | 237 | } |
| 223 | 238 | |
| 224 | 239 | // external cassette or barcode reader input |
| 225 | | TIMER_CALLBACK_MEMBER(px4_state::ext_cassette_read) |
| 240 | TIMER_DEVICE_CALLBACK_MEMBER( px4_state::ext_cassette_read ) |
| 226 | 241 | { |
| 227 | 242 | UINT8 result; |
| 228 | 243 | int trigger = 0; |
| r26901 | r26902 | |
| 260 | 275 | } |
| 261 | 276 | |
| 262 | 277 | // free running counter |
| 263 | | TIMER_DEVICE_CALLBACK_MEMBER(px4_state::frc_tick) |
| 278 | TIMER_DEVICE_CALLBACK_MEMBER( px4_state::frc_tick ) |
| 264 | 279 | { |
| 265 | 280 | m_frc_value++; |
| 266 | 281 | |
| r26901 | r26902 | |
| 272 | 287 | } |
| 273 | 288 | |
| 274 | 289 | // input capture register low command trigger |
| 275 | | READ8_MEMBER(px4_state::px4_icrlc_r) |
| 290 | READ8_MEMBER( px4_state::px4_icrlc_r ) |
| 276 | 291 | { |
| 277 | 292 | if (VERBOSE) |
| 278 | 293 | logerror("%s: px4_icrlc_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 284 | 299 | } |
| 285 | 300 | |
| 286 | 301 | // control register 1 |
| 287 | | WRITE8_MEMBER(px4_state::px4_ctrl1_w) |
| 302 | WRITE8_MEMBER( px4_state::px4_ctrl1_w ) |
| 288 | 303 | { |
| 289 | | int baud; |
| 304 | const int rcv_rates[] = { 110, 150, 300, 600, 1200, 2400, 4800, 9600, 75, 1200, 19200, 38400, 200 }; |
| 305 | const int tra_rates[] = { 110, 150, 300, 600, 1200, 2400, 4800, 9600, 1200, 75, 19200, 38400, 200 }; |
| 290 | 306 | |
| 291 | 307 | if (VERBOSE) |
| 292 | 308 | logerror("%s: px4_ctrl1_w (0x%02x)\n", machine().describe_context(), data); |
| 293 | 309 | |
| 294 | 310 | // baudrate generator |
| 295 | | baud = data >> 4; |
| 311 | int baud = data >> 4; |
| 296 | 312 | |
| 297 | 313 | if (baud <= 12) |
| 298 | 314 | { |
| 299 | | m_transmit_timer->adjust(attotime::zero, 0, attotime::from_hz(XTAL_7_3728MHz/2/transmit_rate[baud])); |
| 300 | | m_receive_timer->adjust(attotime::zero, 0, attotime::from_hz(XTAL_7_3728MHz/2/receive_rate[baud])); |
| 315 | if (VERBOSE) |
| 316 | logerror("rcv baud = %d, tra baud = %d\n", rcv_rates[baud], tra_rates[baud]); |
| 317 | |
| 318 | set_rcv_rate(rcv_rates[baud]); |
| 319 | set_tra_rate(tra_rates[baud]); |
| 301 | 320 | } |
| 302 | 321 | |
| 303 | 322 | m_ctrl1 = data; |
| 304 | 323 | } |
| 305 | 324 | |
| 306 | 325 | // input capture register high command trigger |
| 307 | | READ8_MEMBER(px4_state::px4_icrhc_r) |
| 326 | READ8_MEMBER( px4_state::px4_icrhc_r ) |
| 308 | 327 | { |
| 309 | 328 | if (VERBOSE) |
| 310 | 329 | logerror("%s: px4_icrhc_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 313 | 332 | } |
| 314 | 333 | |
| 315 | 334 | // command register |
| 316 | | WRITE8_MEMBER(px4_state::px4_cmdr_w) |
| 335 | WRITE8_MEMBER( px4_state::px4_cmdr_w ) |
| 317 | 336 | { |
| 318 | | if (VERBOSE) |
| 337 | if (0) |
| 319 | 338 | logerror("%s: px4_cmdr_w (0x%02x)\n", machine().describe_context(), data); |
| 320 | 339 | |
| 321 | 340 | // clear overflow interrupt? |
| r26901 | r26902 | |
| 327 | 346 | } |
| 328 | 347 | |
| 329 | 348 | // input capture register low barcode trigger |
| 330 | | READ8_MEMBER(px4_state::px4_icrlb_r) |
| 349 | READ8_MEMBER( px4_state::px4_icrlb_r ) |
| 331 | 350 | { |
| 332 | 351 | if (VERBOSE) |
| 333 | 352 | logerror("%s: px4_icrlb_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 336 | 355 | } |
| 337 | 356 | |
| 338 | 357 | // control register 2 |
| 339 | | WRITE8_MEMBER(px4_state::px4_ctrl2_w) |
| 358 | WRITE8_MEMBER( px4_state::px4_ctrl2_w ) |
| 340 | 359 | { |
| 341 | 360 | if (VERBOSE) |
| 342 | 361 | logerror("%s: px4_ctrl2_w (0x%02x)\n", machine().describe_context(), data); |
| r26901 | r26902 | |
| 358 | 377 | } |
| 359 | 378 | |
| 360 | 379 | // input capture register high barcode trigger |
| 361 | | READ8_MEMBER(px4_state::px4_icrhb_r) |
| 380 | READ8_MEMBER( px4_state::px4_icrhb_r ) |
| 362 | 381 | { |
| 363 | 382 | if (VERBOSE) |
| 364 | 383 | logerror("%s: px4_icrhb_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 371 | 390 | } |
| 372 | 391 | |
| 373 | 392 | // interrupt status register |
| 374 | | READ8_MEMBER(px4_state::px4_isr_r) |
| 393 | READ8_MEMBER( px4_state::px4_isr_r ) |
| 375 | 394 | { |
| 376 | 395 | if (VERBOSE) |
| 377 | 396 | logerror("%s: px4_isr_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 380 | 399 | } |
| 381 | 400 | |
| 382 | 401 | // interrupt enable register |
| 383 | | WRITE8_MEMBER(px4_state::px4_ier_w) |
| 402 | WRITE8_MEMBER( px4_state::px4_ier_w ) |
| 384 | 403 | { |
| 385 | | if (VERBOSE) |
| 404 | if (0) |
| 386 | 405 | logerror("%s: px4_ier_w (0x%02x)\n", machine().describe_context(), data); |
| 387 | 406 | |
| 388 | 407 | m_ier = data; |
| r26901 | r26902 | |
| 390 | 409 | } |
| 391 | 410 | |
| 392 | 411 | // status register |
| 393 | | READ8_MEMBER(px4_state::px4_str_r) |
| 412 | READ8_MEMBER( px4_state::px4_str_r ) |
| 394 | 413 | { |
| 395 | 414 | UINT8 result = 0; |
| 396 | 415 | |
| r26901 | r26902 | |
| 426 | 445 | } |
| 427 | 446 | |
| 428 | 447 | // bank register |
| 429 | | WRITE8_MEMBER(px4_state::px4_bankr_w) |
| 448 | WRITE8_MEMBER( px4_state::px4_bankr_w ) |
| 430 | 449 | { |
| 431 | 450 | address_space &space_program = m_z80->space(AS_PROGRAM); |
| 432 | 451 | |
| 433 | | if (VERBOSE) |
| 452 | if (0) |
| 434 | 453 | logerror("%s: px4_bankr_w (0x%02x)\n", machine().describe_context(), data); |
| 435 | 454 | |
| 436 | 455 | m_bankr = data; |
| r26901 | r26902 | |
| 464 | 483 | } |
| 465 | 484 | |
| 466 | 485 | // serial io register |
| 467 | | READ8_MEMBER(px4_state::px4_sior_r) |
| 486 | READ8_MEMBER( px4_state::px4_sior_r ) |
| 468 | 487 | { |
| 469 | | if (VERBOSE) |
| 488 | if (0) |
| 470 | 489 | logerror("%s: px4_sior_r 0x%02x\n", machine().describe_context(), m_sior); |
| 471 | 490 | |
| 472 | 491 | return m_sior; |
| 473 | 492 | } |
| 474 | 493 | |
| 475 | 494 | // serial io register |
| 476 | | WRITE8_MEMBER(px4_state::px4_sior_w) |
| 495 | WRITE8_MEMBER( px4_state::px4_sior_w ) |
| 477 | 496 | { |
| 478 | | if (VERBOSE) |
| 497 | if (0) |
| 479 | 498 | logerror("%s: px4_sior_w (0x%02x)\n", machine().describe_context(), data); |
| 480 | 499 | |
| 481 | 500 | m_sior = data; |
| r26901 | r26902 | |
| 603 | 622 | //************************************************************************** |
| 604 | 623 | |
| 605 | 624 | // vram start address register |
| 606 | | WRITE8_MEMBER(px4_state::px4_vadr_w) |
| 625 | WRITE8_MEMBER( px4_state::px4_vadr_w ) |
| 607 | 626 | { |
| 608 | 627 | if (VERBOSE) |
| 609 | 628 | logerror("%s: px4_vadr_w (0x%02x)\n", machine().describe_context(), data); |
| r26901 | r26902 | |
| 612 | 631 | } |
| 613 | 632 | |
| 614 | 633 | // y offset register |
| 615 | | WRITE8_MEMBER(px4_state::px4_yoff_w) |
| 634 | WRITE8_MEMBER( px4_state::px4_yoff_w ) |
| 616 | 635 | { |
| 617 | 636 | if (VERBOSE) |
| 618 | 637 | logerror("%s: px4_yoff_w (0x%02x)\n", machine().describe_context(), data); |
| r26901 | r26902 | |
| 621 | 640 | } |
| 622 | 641 | |
| 623 | 642 | // frame register |
| 624 | | WRITE8_MEMBER(px4_state::px4_fr_w) |
| 643 | WRITE8_MEMBER( px4_state::px4_fr_w ) |
| 625 | 644 | { |
| 626 | 645 | if (VERBOSE) |
| 627 | 646 | logerror("%s: px4_fr_w (0x%02x)\n", machine().describe_context(), data); |
| 628 | 647 | } |
| 629 | 648 | |
| 630 | 649 | // speed-up register |
| 631 | | WRITE8_MEMBER(px4_state::px4_spur_w) |
| 650 | WRITE8_MEMBER( px4_state::px4_spur_w ) |
| 632 | 651 | { |
| 633 | 652 | if (VERBOSE) |
| 634 | 653 | logerror("%s: px4_spur_w (0x%02x)\n", machine().describe_context(), data); |
| r26901 | r26902 | |
| 639 | 658 | // GAPNIO |
| 640 | 659 | //************************************************************************** |
| 641 | 660 | |
| 661 | WRITE_LINE_MEMBER( px4_state::serial_rx_w ) |
| 662 | { |
| 663 | // synchronize to the start bit |
| 664 | device_serial_interface::rx_w(state); |
| 665 | |
| 666 | // update line state |
| 667 | if (state) |
| 668 | input_callback(m_input_state | RX); |
| 669 | else |
| 670 | input_callback(m_input_state & ~RX); |
| 671 | } |
| 672 | |
| 673 | WRITE_LINE_MEMBER( px4_state::serial_dcd_w ) |
| 674 | { |
| 675 | m_rs232_dcd = state; |
| 676 | } |
| 677 | |
| 678 | WRITE_LINE_MEMBER( px4_state::serial_dsr_w ) |
| 679 | { |
| 680 | m_artsr |= !state << 7; |
| 681 | } |
| 682 | |
| 683 | WRITE_LINE_MEMBER( px4_state::serial_cts_w ) |
| 684 | { |
| 685 | m_rs232_cts = state; |
| 686 | } |
| 687 | |
| 688 | void px4_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 689 | { |
| 690 | device_serial_interface::device_timer(timer, id, param, ptr); |
| 691 | } |
| 692 | |
| 693 | void px4_state::tra_callback() |
| 694 | { |
| 695 | if (ART_TX_ENABLED) |
| 696 | { |
| 697 | if (ART_BREAK) |
| 698 | { |
| 699 | // transmit break |
| 700 | txd_w(0); |
| 701 | set_out_data_bit(0); |
| 702 | } |
| 703 | else |
| 704 | { |
| 705 | // transmit data |
| 706 | txd_w(transmit_register_get_data_bit()); |
| 707 | } |
| 708 | } |
| 709 | else |
| 710 | { |
| 711 | // transmit mark |
| 712 | txd_w(1); |
| 713 | set_out_data_bit(1); |
| 714 | } |
| 715 | } |
| 716 | |
| 717 | void px4_state::tra_complete() |
| 718 | { |
| 719 | if (m_artsr & ART_TXRDY) |
| 720 | { |
| 721 | // no more bytes, buffer now empty |
| 722 | m_artsr |= ART_TXEMPTY; |
| 723 | } |
| 724 | else |
| 725 | { |
| 726 | // transfer next byte |
| 727 | transmit_register_setup(m_artdor); |
| 728 | m_artsr |= ART_TXRDY; |
| 729 | } |
| 730 | } |
| 731 | |
| 732 | void px4_state::rcv_callback() |
| 733 | { |
| 734 | if (ART_RX_ENABLED) |
| 735 | { |
| 736 | // receive data |
| 737 | receive_register_update_bit(get_in_data_bit()); |
| 738 | } |
| 739 | } |
| 740 | |
| 741 | void px4_state::rcv_complete() |
| 742 | { |
| 743 | receive_register_extract(); |
| 744 | m_artdir = get_received_char(); |
| 745 | |
| 746 | // TODO: verify parity and framing |
| 747 | |
| 748 | // overrun? |
| 749 | if (m_artsr & ART_RXRDY) |
| 750 | m_artsr |= ART_OE; |
| 751 | |
| 752 | // set ready and signal interrupt |
| 753 | m_artsr |= ART_RXRDY; |
| 754 | m_isr |= INT1_ART; |
| 755 | gapnit_interrupt(); |
| 756 | } |
| 757 | |
| 758 | void px4_state::input_callback(UINT8 state) |
| 759 | { |
| 760 | m_input_state = state; |
| 761 | } |
| 762 | |
| 642 | 763 | // helper function to read from selected serial port |
| 643 | 764 | int px4_state::rxd_r() |
| 644 | 765 | { |
| 645 | 766 | if (BIT(m_swr, 3)) |
| 646 | 767 | // from rs232 |
| 647 | | return m_rs232->rx(); |
| 768 | return get_in_data_bit(); |
| 648 | 769 | else |
| 649 | 770 | if (BIT(m_swr, 2)) |
| 650 | 771 | // from sio |
| r26901 | r26902 | |
| 664 | 785 | if (BIT(m_swr, 3)) |
| 665 | 786 | // from rs232 |
| 666 | 787 | m_rs232->tx(data); |
| 667 | | // else from cartridge |
| 788 | // else to cartridge |
| 668 | 789 | } |
| 669 | 790 | |
| 670 | | TIMER_CALLBACK_MEMBER(px4_state::transmit_data) |
| 671 | | { |
| 672 | | if (ART_TX_ENABLED) |
| 673 | | { |
| 674 | | } |
| 675 | | } |
| 676 | | |
| 677 | | TIMER_CALLBACK_MEMBER(px4_state::receive_data) |
| 678 | | { |
| 679 | | if (ART_RX_ENABLED) |
| 680 | | { |
| 681 | | } |
| 682 | | } |
| 683 | | |
| 684 | 791 | // cartridge interface |
| 685 | | READ8_MEMBER(px4_state::px4_ctgif_r) |
| 792 | READ8_MEMBER( px4_state::px4_ctgif_r ) |
| 686 | 793 | { |
| 687 | 794 | if (VERBOSE) |
| 688 | 795 | logerror("%s: px4_ctgif_r @ 0x%02x\n", machine().describe_context(), offset); |
| 689 | 796 | |
| 690 | | return 0xff; |
| 797 | return 0x00; |
| 691 | 798 | } |
| 692 | 799 | |
| 693 | 800 | // cartridge interface |
| 694 | | WRITE8_MEMBER(px4_state::px4_ctgif_w) |
| 801 | WRITE8_MEMBER( px4_state::px4_ctgif_w ) |
| 695 | 802 | { |
| 696 | 803 | if (VERBOSE) |
| 697 | 804 | logerror("%s: px4_ctgif_w (0x%02x @ 0x%02x)\n", machine().describe_context(), data, offset); |
| 698 | 805 | } |
| 699 | 806 | |
| 700 | 807 | // art data input register |
| 701 | | READ8_MEMBER(px4_state::px4_artdir_r) |
| 808 | READ8_MEMBER( px4_state::px4_artdir_r ) |
| 702 | 809 | { |
| 703 | 810 | if (VERBOSE) |
| 704 | 811 | logerror("%s: px4_artdir_r\n", machine().describe_context()); |
| r26901 | r26902 | |
| 706 | 813 | // clear ready |
| 707 | 814 | m_artsr &= ~ART_RXRDY; |
| 708 | 815 | |
| 816 | // clear interrupt |
| 817 | m_isr &= ~INT1_ART; |
| 818 | gapnit_interrupt(); |
| 819 | |
| 709 | 820 | return m_artdir; |
| 710 | 821 | } |
| 711 | 822 | |
| 712 | 823 | // art data output register |
| 713 | | WRITE8_MEMBER(px4_state::px4_artdor_w) |
| 824 | WRITE8_MEMBER( px4_state::px4_artdor_w ) |
| 714 | 825 | { |
| 715 | 826 | if (VERBOSE) |
| 716 | 827 | logerror("%s: px4_artdor_w (0x%02x)\n", machine().describe_context(), data); |
| 717 | 828 | |
| 718 | | // clear ready |
| 719 | | m_artsr &= ~ART_TXRDY; |
| 829 | m_artdor = data; |
| 720 | 830 | |
| 721 | | m_artdor = data; |
| 831 | // new data to transmit? |
| 832 | if (ART_TX_ENABLED && is_transmit_register_empty()) |
| 833 | { |
| 834 | transmit_register_setup(m_artdor); |
| 835 | m_artsr |= ART_TXRDY; |
| 836 | } |
| 837 | else |
| 838 | { |
| 839 | // clear ready |
| 840 | m_artsr &= ~ART_TXRDY; |
| 841 | } |
| 722 | 842 | } |
| 723 | 843 | |
| 724 | 844 | // art status register |
| 725 | | READ8_MEMBER(px4_state::px4_artsr_r) |
| 845 | READ8_MEMBER( px4_state::px4_artsr_r ) |
| 726 | 846 | { |
| 727 | | UINT8 result = 0; |
| 847 | if (0) |
| 848 | logerror("%s: px4_artsr_r (%02x)\n", machine().describe_context(), m_artsr); |
| 728 | 849 | |
| 729 | | if (VERBOSE) |
| 730 | | logerror("%s: px4_artsr_r\n", machine().describe_context()); |
| 731 | | |
| 732 | | result |= m_rs232->dsr_r() << 7; |
| 733 | | |
| 734 | | return result | m_artsr; |
| 850 | return m_artsr; |
| 735 | 851 | } |
| 736 | 852 | |
| 737 | 853 | // art mode register |
| 738 | | WRITE8_MEMBER(px4_state::px4_artmr_w) |
| 854 | WRITE8_MEMBER( px4_state::px4_artmr_w ) |
| 739 | 855 | { |
| 856 | int data_bits = BIT(data, 2) ? 8 : 7; |
| 857 | int parity = BIT(data, 4) ? (BIT(data, 5) ? PARITY_EVEN : PARITY_ODD) : PARITY_NONE; |
| 858 | int stop_bits = BIT(data, 7) ? 2 : 1; |
| 859 | |
| 740 | 860 | if (VERBOSE) |
| 741 | | logerror("%s: px4_artmr_w (0x%02x)\n", machine().describe_context(), data); |
| 861 | logerror("%s: serial frame setup: %d-%d-%d\n", tag(), data_bits, stop_bits, parity); |
| 742 | 862 | |
| 743 | | m_artmr = data; |
| 863 | set_data_frame(data_bits, stop_bits, parity, false); |
| 744 | 864 | } |
| 745 | 865 | |
| 746 | 866 | // io status register |
| 747 | | READ8_MEMBER(px4_state::px4_iostr_r) |
| 867 | READ8_MEMBER( px4_state::px4_iostr_r ) |
| 748 | 868 | { |
| 749 | | UINT8 result = 0; |
| 869 | UINT8 data = 0; |
| 750 | 870 | |
| 751 | | if (VERBOSE) |
| 752 | | logerror("%s: px4_iostr_r\n", machine().describe_context()); |
| 753 | | |
| 754 | 871 | // centronics status |
| 755 | | result |= m_centronics->busy_r() << 0; |
| 756 | | result |= !m_centronics->pe_r() << 1; |
| 872 | data |= m_centronics->busy_r() << 0; |
| 873 | data |= !m_centronics->pe_r() << 1; |
| 757 | 874 | |
| 758 | 875 | // sio status |
| 759 | | result |= !m_sio->pin_r() << 2; |
| 876 | data |= !m_sio->pin_r() << 2; |
| 760 | 877 | |
| 761 | 878 | // serial data |
| 762 | | result |= rxd_r() << 3; |
| 879 | data |= rxd_r() << 3; |
| 763 | 880 | |
| 764 | 881 | // rs232 status |
| 765 | | result |= m_rs232->dcd_r() << 4; |
| 766 | | result |= m_rs232->cts_r() << 5; |
| 882 | data |= !m_rs232_dcd << 4; |
| 883 | data |= !m_rs232_cts << 5; |
| 767 | 884 | |
| 768 | | result |= 1 << 6; // bit 6, csel, cartridge option select signal, set to 'other mode' |
| 769 | | result |= 0 << 7; // bit 7, caud - audio input from cartridge |
| 885 | data |= 1 << 6; // bit 6, csel, cartridge option select signal |
| 886 | data |= 0 << 7; // bit 7, caud - audio input from cartridge |
| 770 | 887 | |
| 771 | | return result; |
| 888 | if (0) |
| 889 | logerror("%s: px4_iostr_r (%02x)\n", machine().describe_context(), data); |
| 890 | |
| 891 | logerror("%s: px4_iostr_r: rx = %d, dcd = %d, cts = %d\n", machine().describe_context(), BIT(data, 3), BIT(data, 4), BIT(data, 5)); |
| 892 | |
| 893 | return data; |
| 772 | 894 | } |
| 773 | 895 | |
| 774 | 896 | // art command register |
| 775 | | WRITE8_MEMBER(px4_state::px4_artcr_w) |
| 897 | WRITE8_MEMBER( px4_state::px4_artcr_w ) |
| 776 | 898 | { |
| 777 | 899 | if (VERBOSE) |
| 778 | 900 | logerror("%s: px4_artcr_w (0x%02x)\n", machine().describe_context(), data); |
| 779 | 901 | |
| 780 | 902 | m_artcr = data; |
| 781 | 903 | |
| 782 | | // bit 0, txe - transmit enable |
| 783 | | if (!ART_TX_ENABLED) |
| 784 | | txd_w(1); // force high when disabled |
| 785 | | |
| 786 | | // bit 3, sbrk - break output |
| 787 | | if (ART_TX_ENABLED && BIT(data, 3)) |
| 788 | | txd_w(0); // force low when enabled and transmit enabled |
| 789 | | |
| 790 | 904 | // error reset |
| 791 | 905 | if (BIT(data, 4)) |
| 792 | 906 | m_artsr &= ~(ART_PE | ART_OE | ART_FE); |
| 793 | 907 | |
| 794 | 908 | // rs232 |
| 795 | | m_rs232->dtr_w(BIT(data, 1)); |
| 796 | | m_rs232->rts_w(BIT(data, 5)); |
| 909 | m_rs232->dtr_w(!BIT(data, 1)); |
| 910 | m_rs232->rts_w(!BIT(data, 5)); |
| 797 | 911 | } |
| 798 | 912 | |
| 799 | 913 | // switch register |
| 800 | | WRITE8_MEMBER(px4_state::px4_swr_w) |
| 914 | WRITE8_MEMBER( px4_state::px4_swr_w ) |
| 801 | 915 | { |
| 802 | 916 | if (VERBOSE) |
| 803 | | logerror("%s: px4_swr_w (0x%02x)\n", machine().describe_context(), data); |
| 917 | { |
| 918 | const char *cart_mode[] = { "hs", "io", "db", "ot" }; |
| 919 | const char *ser_mode[] = { "cart sio / cart sio", "sio / sio", "rs232 / rs232", "rs232 / sio" }; |
| 920 | logerror("%s: px4_swr_w: cartridge mode: %s, serial mode: %s, audio: %s\n", machine().describe_context(), |
| 921 | cart_mode[data & 0x03], ser_mode[(data >> 2) & 0x03], BIT(data, 4) ? "on" : "off"); |
| 922 | } |
| 804 | 923 | |
| 805 | 924 | m_swr = data; |
| 806 | 925 | } |
| 807 | 926 | |
| 808 | 927 | // io control register |
| 809 | | WRITE8_MEMBER(px4_state::px4_ioctlr_w) |
| 928 | WRITE8_MEMBER( px4_state::px4_ioctlr_w ) |
| 810 | 929 | { |
| 811 | 930 | if (VERBOSE) |
| 812 | 931 | logerror("%s: px4_ioctlr_w (0x%02x)\n", machine().describe_context(), data); |
| r26901 | r26902 | |
| 830 | 949 | // 7508 RELATED |
| 831 | 950 | //************************************************************************** |
| 832 | 951 | |
| 833 | | TIMER_DEVICE_CALLBACK_MEMBER(px4_state::upd7508_1sec_callback) |
| 952 | TIMER_DEVICE_CALLBACK_MEMBER( px4_state::upd7508_1sec_callback ) |
| 834 | 953 | { |
| 835 | 954 | // adjust interrupt status |
| 836 | 955 | m_interrupt_status |= UPD7508_INT_ONE_SECOND; |
| r26901 | r26902 | |
| 843 | 962 | } |
| 844 | 963 | } |
| 845 | 964 | |
| 846 | | INPUT_CHANGED_MEMBER(px4_state::key_callback) |
| 965 | INPUT_CHANGED_MEMBER( px4_state::key_callback ) |
| 847 | 966 | { |
| 848 | 967 | UINT32 oldvalue = oldval * field.mask(), newvalue = newval * field.mask(); |
| 849 | 968 | UINT32 delta = oldvalue ^ newvalue; |
| r26901 | r26902 | |
| 887 | 1006 | // EXTERNAL RAM-DISK |
| 888 | 1007 | //************************************************************************** |
| 889 | 1008 | |
| 890 | | WRITE8_MEMBER(px4_state::px4_ramdisk_address_w) |
| 1009 | WRITE8_MEMBER( px4_state::px4_ramdisk_address_w ) |
| 891 | 1010 | { |
| 892 | 1011 | switch (offset) |
| 893 | 1012 | { |
| r26901 | r26902 | |
| 897 | 1016 | } |
| 898 | 1017 | } |
| 899 | 1018 | |
| 900 | | READ8_MEMBER(px4_state::px4_ramdisk_data_r) |
| 1019 | READ8_MEMBER( px4_state::px4_ramdisk_data_r ) |
| 901 | 1020 | { |
| 902 | 1021 | UINT8 ret = 0xff; |
| 903 | 1022 | |
| r26901 | r26902 | |
| 917 | 1036 | return ret; |
| 918 | 1037 | } |
| 919 | 1038 | |
| 920 | | WRITE8_MEMBER(px4_state::px4_ramdisk_data_w) |
| 1039 | WRITE8_MEMBER( px4_state::px4_ramdisk_data_w ) |
| 921 | 1040 | { |
| 922 | 1041 | if (m_ramdisk_address < 0x20000) |
| 923 | 1042 | m_ramdisk[m_ramdisk_address] = data; |
| r26901 | r26902 | |
| 925 | 1044 | m_ramdisk_address = (m_ramdisk_address & 0xffff00) | ((m_ramdisk_address & 0xff) + 1); |
| 926 | 1045 | } |
| 927 | 1046 | |
| 928 | | READ8_MEMBER(px4_state::px4_ramdisk_control_r) |
| 1047 | READ8_MEMBER( px4_state::px4_ramdisk_control_r ) |
| 929 | 1048 | { |
| 930 | 1049 | // bit 7 determines the presence of a ram-disk |
| 931 | 1050 | return 0x7f; |
| r26901 | r26902 | |
| 982 | 1101 | // DRIVER INIT |
| 983 | 1102 | //************************************************************************** |
| 984 | 1103 | |
| 985 | | DRIVER_INIT_MEMBER(px4_state,px4) |
| 1104 | DRIVER_INIT_MEMBER( px4_state, px4 ) |
| 986 | 1105 | { |
| 987 | | // init 7508 |
| 988 | | m_one_sec_int_enabled = true; |
| 989 | | m_key_int_enabled = true; |
| 990 | | m_alarm_int_enabled = true; |
| 991 | | |
| 992 | | // art |
| 993 | | m_receive_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(px4_state::receive_data), this)); |
| 994 | | m_transmit_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(px4_state::transmit_data), this)); |
| 995 | | |
| 996 | | // external cassette or barcode reader |
| 997 | | m_ext_cas_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(px4_state::ext_cassette_read), this)); |
| 998 | | m_ear_last_state = 0; |
| 999 | | |
| 1000 | 1106 | // map os rom and last half of memory |
| 1001 | 1107 | membank("bank1")->set_base(memregion("os")->base()); |
| 1002 | 1108 | membank("bank2")->set_base(m_ram->pointer() + 0x8000); |
| 1003 | 1109 | } |
| 1004 | 1110 | |
| 1005 | | DRIVER_INIT_MEMBER(px4_state, px4p) |
| 1111 | DRIVER_INIT_MEMBER( px4_state, px4p ) |
| 1006 | 1112 | { |
| 1007 | 1113 | DRIVER_INIT_CALL(px4); |
| 1008 | 1114 | |
| r26901 | r26902 | |
| 1013 | 1119 | void px4_state::machine_reset() |
| 1014 | 1120 | { |
| 1015 | 1121 | m_artsr = ART_TXRDY | ART_TXEMPTY; |
| 1122 | receive_register_reset(); |
| 1123 | transmit_register_reset(); |
| 1016 | 1124 | } |
| 1017 | 1125 | |
| 1018 | | MACHINE_START_MEMBER(px4_state, px4_ramdisk) |
| 1126 | MACHINE_START_MEMBER( px4_state, px4_ramdisk ) |
| 1019 | 1127 | { |
| 1020 | 1128 | machine().device<nvram_device>("nvram")->set_base(m_ramdisk, 0x20000); |
| 1021 | 1129 | } |
| 1022 | 1130 | |
| 1131 | |
| 1023 | 1132 | //************************************************************************** |
| 1024 | 1133 | // ADDRESS MAPS |
| 1025 | 1134 | //************************************************************************** |
| r26901 | r26902 | |
| 1080 | 1189 | PORT_START("dips") |
| 1081 | 1190 | |
| 1082 | 1191 | PORT_DIPNAME(0x0f, 0x0f, "Character set") |
| 1083 | | PORT_DIPLOCATION("PX-4 DIP:8,7,6,5") |
| 1192 | PORT_DIPLOCATION("DIP:8,7,6,5") |
| 1084 | 1193 | PORT_DIPSETTING(0x0f, "ASCII") |
| 1085 | 1194 | PORT_DIPSETTING(0x0e, "France") |
| 1086 | 1195 | PORT_DIPSETTING(0x0d, "Germany") |
| r26901 | r26902 | |
| 1285 | 1394 | |
| 1286 | 1395 | // external cassette |
| 1287 | 1396 | MCFG_CASSETTE_ADD("extcas", px4_cassette_interface) |
| 1397 | MCFG_TIMER_DRIVER_ADD("extcas_timer", px4_state, ext_cassette_read) |
| 1288 | 1398 | |
| 1289 | 1399 | // sio port |
| 1290 | 1400 | MCFG_EPSON_SIO_ADD("sio", NULL) |
| 1291 | 1401 | |
| 1292 | 1402 | // rs232 port |
| 1293 | 1403 | MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, NULL) |
| 1404 | MCFG_SERIAL_OUT_RX_HANDLER(WRITELINE(px4_state, serial_rx_w)) |
| 1405 | MCFG_RS232_OUT_DCD_HANDLER(WRITELINE(px4_state, serial_dcd_w)) |
| 1406 | MCFG_RS232_OUT_DSR_HANDLER(WRITELINE(px4_state, serial_dsr_w)) |
| 1407 | MCFG_RS232_OUT_CTS_HANDLER(WRITELINE(px4_state, serial_cts_w)) |
| 1294 | 1408 | |
| 1295 | 1409 | // rom capsules |
| 1296 | 1410 | MCFG_CARTSLOT_ADD("capsule1") |