trunk/src/mess/machine/victor9k_fdc.c
r241676 | r241677 | |
13 | 13 | |
14 | 14 | TODO: |
15 | 15 | |
16 | | - everything |
| 16 | - floppy format |
| 17 | - spindle speed |
| 18 | - stepper |
| 19 | - read PLL |
| 20 | - TACH0/1 |
| 21 | - write logic |
17 | 22 | |
18 | 23 | */ |
19 | 24 | |
r241676 | r241677 | |
147 | 152 | MCFG_DEVICE_ADD(M6522_4_TAG, VIA6522, XTAL_30MHz/30) |
148 | 153 | MCFG_VIA6522_WRITEPA_HANDLER(WRITE8(victor_9000_fdc_t, via4_pa_w)) |
149 | 154 | MCFG_VIA6522_WRITEPB_HANDLER(WRITE8(victor_9000_fdc_t, via4_pb_w)) |
150 | | MCFG_VIA6522_CA2_HANDLER(WRITELINE(victor_9000_fdc_t, mode_w)) |
| 155 | MCFG_VIA6522_CA2_HANDLER(WRITELINE(victor_9000_fdc_t, wrsync_w)) |
151 | 156 | MCFG_VIA6522_IRQ_HANDLER(WRITELINE(victor_9000_fdc_t, via4_irq_w)) |
152 | 157 | |
153 | 158 | MCFG_DEVICE_ADD(M6522_5_TAG, VIA6522, XTAL_30MHz/30) |
r241676 | r241677 | |
192 | 197 | victor_9000_fdc_t::victor_9000_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
193 | 198 | device_t(mconfig, VICTOR_9000_FDC, "Victor 9000 FDC", tag, owner, clock, "victor9k_fdc", __FILE__), |
194 | 199 | m_irq_cb(*this), |
| 200 | m_syn_cb(*this), |
| 201 | m_lbrdy_cb(*this), |
195 | 202 | m_maincpu(*this, I8048_TAG), |
196 | 203 | m_via4(*this, M6522_4_TAG), |
197 | 204 | m_via5(*this, M6522_5_TAG), |
r241676 | r241677 | |
210 | 217 | m_rdy1(0), |
211 | 218 | m_ds0(1), |
212 | 219 | m_ds1(1), |
213 | | m_lms(0), |
| 220 | m_l0ms(0), |
| 221 | m_l1ms(0), |
214 | 222 | m_st0(0), |
215 | 223 | m_st1(0), |
216 | 224 | m_stp0(0), |
217 | 225 | m_stp1(0), |
218 | 226 | m_drive(0), |
219 | 227 | m_side(0), |
220 | | m_brdy(1), |
221 | | m_sync(1), |
222 | | m_gcrerr(0), |
223 | 228 | m_via4_irq(CLEAR_LINE), |
224 | 229 | m_via5_irq(CLEAR_LINE), |
225 | | m_via6_irq(CLEAR_LINE) |
| 230 | m_via6_irq(CLEAR_LINE), |
| 231 | m_syn(0), |
| 232 | m_lbrdy(1) |
226 | 233 | { |
| 234 | cur_live.tm = attotime::never; |
| 235 | cur_live.state = IDLE; |
| 236 | cur_live.next_state = -1; |
| 237 | cur_live.write_position = 0; |
| 238 | cur_live.write_start_time = attotime::never; |
227 | 239 | } |
228 | 240 | |
229 | 241 | |
r241676 | r241677 | |
233 | 245 | |
234 | 246 | void victor_9000_fdc_t::device_start() |
235 | 247 | { |
| 248 | // allocate timer |
| 249 | t_gen = timer_alloc(TM_GEN); |
| 250 | t_tach0 = timer_alloc(TM_TACH0); |
| 251 | t_tach1 = timer_alloc(TM_TACH1); |
| 252 | |
236 | 253 | // state saving |
237 | 254 | save_item(NAME(m_da)); |
238 | 255 | save_item(NAME(m_da0)); |
r241676 | r241677 | |
245 | 262 | save_item(NAME(m_rdy1)); |
246 | 263 | save_item(NAME(m_ds0)); |
247 | 264 | save_item(NAME(m_ds1)); |
248 | | save_item(NAME(m_lms)); |
| 265 | save_item(NAME(m_l0ms)); |
| 266 | save_item(NAME(m_l1ms)); |
249 | 267 | save_item(NAME(m_st0)); |
250 | 268 | save_item(NAME(m_st1)); |
251 | 269 | save_item(NAME(m_stp0)); |
252 | 270 | save_item(NAME(m_stp1)); |
253 | 271 | save_item(NAME(m_drive)); |
254 | 272 | save_item(NAME(m_side)); |
255 | | save_item(NAME(m_brdy)); |
256 | | save_item(NAME(m_sync)); |
257 | | save_item(NAME(m_gcrerr)); |
| 273 | save_item(NAME(m_drw)); |
| 274 | save_item(NAME(m_erase)); |
258 | 275 | save_item(NAME(m_via4_irq)); |
259 | 276 | save_item(NAME(m_via5_irq)); |
260 | 277 | save_item(NAME(m_via6_irq)); |
| 278 | save_item(NAME(m_syn)); |
| 279 | save_item(NAME(m_lbrdy)); |
261 | 280 | } |
262 | 281 | |
263 | 282 | |
r241676 | r241677 | |
267 | 286 | |
268 | 287 | void victor_9000_fdc_t::device_reset() |
269 | 288 | { |
| 289 | live_abort(); |
| 290 | |
270 | 291 | // resolve callbacks |
271 | 292 | m_irq_cb.resolve_safe(); |
| 293 | m_syn_cb.resolve_safe(); |
| 294 | m_lbrdy_cb.resolve_safe(); |
272 | 295 | |
273 | 296 | // reset devices |
274 | 297 | m_via4->reset(); |
r241676 | r241677 | |
291 | 314 | |
292 | 315 | void victor_9000_fdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
293 | 316 | { |
| 317 | switch (id) |
| 318 | { |
| 319 | case TM_GEN: |
| 320 | live_sync(); |
| 321 | live_run(); |
| 322 | |
| 323 | case TM_TACH0: |
| 324 | // TODO |
| 325 | break; |
| 326 | |
| 327 | case TM_TACH1: |
| 328 | // TODO |
| 329 | break; |
| 330 | } |
294 | 331 | } |
295 | 332 | |
296 | 333 | |
r241676 | r241677 | |
315 | 352 | |
316 | 353 | */ |
317 | 354 | |
318 | | return m_lms; |
| 355 | return (m_l1ms << 4) | m_l0ms; |
319 | 356 | } |
320 | 357 | |
321 | 358 | |
r241676 | r241677 | |
370 | 407 | |
371 | 408 | */ |
372 | 409 | |
373 | | if (BIT(data, 0)) m_floppy0->mon_w(0); |
374 | | if (BIT(data, 1)) m_floppy0->mon_w(1); |
375 | | if (BIT(data, 2)) m_floppy1->mon_w(0); |
376 | | if (BIT(data, 3)) m_floppy1->mon_w(1); |
| 410 | bool sync = false; |
377 | 411 | |
| 412 | int mtr0 = m_mtr0; |
| 413 | if ((data & 0x03) == 0x01) mtr0 = 0; |
| 414 | if ((data & 0x03) == 0x02) mtr0 = 1; |
| 415 | if (m_mtr0 != mtr0) sync = true; |
| 416 | |
| 417 | int mtr1 = m_mtr1; |
| 418 | if ((data & 0x0c) == 0x04) mtr1 = 0; |
| 419 | if ((data & 0x0c) == 0x08) mtr1 = 1; |
| 420 | if (m_mtr1 != mtr1) sync = true; |
| 421 | |
378 | 422 | int sel0 = BIT(data, 5); |
| 423 | if (m_sel0 != sel0) sync = true; |
379 | 424 | |
380 | | if (m_sel0 && !sel0) |
| 425 | int sel1 = BIT(data, 4); |
| 426 | if (m_sel1 != sel1) sync = true; |
| 427 | |
| 428 | if (sync) |
381 | 429 | { |
382 | | m_da0 = m_da; |
383 | | //m_floppy0->set_rpm(); |
384 | | } |
| 430 | live_sync(); |
385 | 431 | |
386 | | m_sel0 = sel0; |
| 432 | m_mtr0 = mtr0; |
| 433 | m_mtr1 = mtr1; |
| 434 | m_sel0 = sel0; |
| 435 | m_sel1 = sel1; |
387 | 436 | |
388 | | int sel1 = BIT(data, 4); |
| 437 | if (LOG) logerror("%s MTR0 %u MTR1 %u SEL0 %u SEL1 %u\n", machine().time().as_string(), m_mtr0, m_mtr1, m_sel0, m_sel1); |
389 | 438 | |
390 | | if (m_sel1 && !sel1) |
391 | | { |
392 | | m_da1 = m_da; |
393 | | //m_floppy1->set_rpm(); |
| 439 | update_spindle_motor(); |
| 440 | checkpoint(); |
| 441 | |
| 442 | if (!m_mtr0 || !m_mtr1) { |
| 443 | if(cur_live.state == IDLE) { |
| 444 | live_start(); |
| 445 | } |
| 446 | } else { |
| 447 | live_abort(); |
| 448 | } |
| 449 | |
| 450 | live_run(); |
394 | 451 | } |
395 | | |
396 | | m_sel1 = sel1; |
397 | 452 | } |
398 | 453 | |
399 | 454 | |
r241676 | r241677 | |
417 | 472 | } |
418 | 473 | |
419 | 474 | |
| 475 | void victor_9000_fdc_t::update_stepper_motor(floppy_image_device *floppy, int stp, int old_st, int st) |
| 476 | { |
| 477 | // TODO |
| 478 | } |
| 479 | |
| 480 | void victor_9000_fdc_t::update_spindle_motor() |
| 481 | { |
| 482 | if (m_sel0) m_da0 = m_da; |
| 483 | m_floppy0->mon_w(m_mtr0); |
| 484 | m_floppy0->set_rpm(300); // TODO |
| 485 | t_tach0->adjust(attotime::never); // TODO |
| 486 | |
| 487 | if (m_sel1) m_da1 = m_da; |
| 488 | m_floppy1->mon_w(m_mtr1); |
| 489 | m_floppy1->set_rpm(300); // TODO |
| 490 | t_tach1->adjust(attotime::never); // TODO |
| 491 | } |
| 492 | |
| 493 | |
420 | 494 | //------------------------------------------------- |
421 | 495 | // da_w - |
422 | 496 | //------------------------------------------------- |
423 | 497 | |
424 | 498 | WRITE8_MEMBER( victor_9000_fdc_t::da_w ) |
425 | 499 | { |
426 | | m_da = data; |
| 500 | if (m_da != data) |
| 501 | { |
| 502 | live_sync(); |
| 503 | m_da = data; |
| 504 | update_spindle_motor(); |
| 505 | checkpoint(); |
| 506 | live_run(); |
| 507 | } |
427 | 508 | } |
428 | 509 | |
429 | 510 | WRITE8_MEMBER( victor_9000_fdc_t::via4_pa_w ) |
r241676 | r241677 | |
443 | 524 | |
444 | 525 | */ |
445 | 526 | |
446 | | m_lms = (m_lms & 0xf0) | (data & 0x0f); |
447 | | m_st0 = data >> 4; |
| 527 | m_l0ms = data & 0x0f; |
| 528 | |
| 529 | UINT8 st0 = data >> 4; |
| 530 | |
| 531 | if (m_st0 != st0) |
| 532 | { |
| 533 | live_sync(); |
| 534 | update_stepper_motor(m_floppy0, m_stp0, st0, m_st0); |
| 535 | m_st0 = st0; |
| 536 | checkpoint(); |
| 537 | live_run(); |
| 538 | } |
448 | 539 | } |
449 | 540 | |
450 | 541 | WRITE8_MEMBER( victor_9000_fdc_t::via4_pb_w ) |
r241676 | r241677 | |
464 | 555 | |
465 | 556 | */ |
466 | 557 | |
467 | | m_lms = (data << 4) | (m_lms & 0x0f); |
468 | | m_st1 = data >> 4; |
| 558 | m_l1ms = data & 0x0f; |
| 559 | |
| 560 | UINT8 st1 = data >> 4; |
| 561 | |
| 562 | if (m_st1 != st1) |
| 563 | { |
| 564 | live_sync(); |
| 565 | update_stepper_motor(m_floppy1, m_stp1, st1, m_st1); |
| 566 | m_st1 = st1; |
| 567 | checkpoint(); |
| 568 | live_run(); |
| 569 | } |
469 | 570 | } |
470 | 571 | |
471 | | WRITE_LINE_MEMBER( victor_9000_fdc_t::mode_w ) |
| 572 | WRITE_LINE_MEMBER( victor_9000_fdc_t::wrsync_w ) |
472 | 573 | { |
| 574 | if (m_wrsync != state) |
| 575 | { |
| 576 | live_sync(); |
| 577 | m_wrsync = state; |
| 578 | cur_live.wrsync = state; |
| 579 | checkpoint(); |
| 580 | live_run(); |
| 581 | } |
473 | 582 | } |
474 | 583 | |
475 | 584 | WRITE_LINE_MEMBER( victor_9000_fdc_t::via4_irq_w ) |
r241676 | r241677 | |
479 | 588 | m_irq_cb(m_via4_irq || m_via5_irq || m_via6_irq); |
480 | 589 | } |
481 | 590 | |
482 | | |
483 | 591 | READ8_MEMBER( victor_9000_fdc_t::via5_pa_r ) |
484 | 592 | { |
485 | 593 | /* |
r241676 | r241677 | |
497 | 605 | |
498 | 606 | */ |
499 | 607 | |
500 | | return 0; |
| 608 | UINT8 e = checkpoint_live.e; |
| 609 | UINT8 i = checkpoint_live.i; |
| 610 | |
| 611 | return BIT(e, 6) << 7 | BIT(i, 7) << 6 | BIT(e, 5) << 5 | BIT(e, 4) << 4 | BIT(e, 2) << 3 | BIT(i, 1) << 2 | (e & 0x03); |
501 | 612 | } |
502 | 613 | |
503 | 614 | WRITE8_MEMBER( victor_9000_fdc_t::via5_pb_w ) |
r241676 | r241677 | |
516 | 627 | PB7 WD7 |
517 | 628 | |
518 | 629 | */ |
| 630 | |
| 631 | if (m_wd != data) |
| 632 | { |
| 633 | live_sync(); |
| 634 | m_wd = data; |
| 635 | cur_live.wd = data; |
| 636 | checkpoint(); |
| 637 | live_run(); |
| 638 | } |
519 | 639 | } |
520 | 640 | |
521 | 641 | WRITE_LINE_MEMBER( victor_9000_fdc_t::via5_irq_w ) |
r241676 | r241677 | |
555 | 675 | data |= (m_drive ? m_floppy1->wpt_r() : m_floppy0->wpt_r()) << 6; |
556 | 676 | |
557 | 677 | // disk sync detect |
558 | | data |= m_sync << 7; |
| 678 | data |= checkpoint_live.sync << 7; |
559 | 679 | |
560 | 680 | return data; |
561 | 681 | } |
r241676 | r241677 | |
583 | 703 | // LED, drive B |
584 | 704 | output_set_led_value(LED_B, BIT(data, 2)); |
585 | 705 | |
| 706 | bool sync = false; |
| 707 | |
586 | 708 | // dual side select |
587 | | m_side = BIT(data, 4); |
| 709 | int side = BIT(data, 4); |
| 710 | if (m_side != side) sync = true; |
588 | 711 | |
589 | 712 | // select drive A/B |
590 | | m_drive = BIT(data, 5); |
| 713 | int drive = BIT(data, 5); |
| 714 | if (m_drive != drive) sync = true; |
| 715 | |
| 716 | if (sync) |
| 717 | { |
| 718 | live_sync(); |
| 719 | |
| 720 | m_side = side; |
| 721 | cur_live.side = side; |
| 722 | m_floppy0->ss_w(side); |
| 723 | m_floppy1->ss_w(side); |
| 724 | |
| 725 | m_drive = drive; |
| 726 | cur_live.drive = drive; |
| 727 | |
| 728 | checkpoint(); |
| 729 | live_run(); |
| 730 | } |
591 | 731 | } |
592 | 732 | |
593 | 733 | READ8_MEMBER( victor_9000_fdc_t::via6_pb_r ) |
r241676 | r241677 | |
648 | 788 | if (!BIT(data, 2)) |
649 | 789 | m_maincpu->reset(); |
650 | 790 | |
| 791 | bool sync = false; |
| 792 | |
651 | 793 | // stepper enable A |
652 | | m_stp0 = BIT(data, 6); |
| 794 | int stp0 = BIT(data, 6); |
| 795 | if (m_stp0 != stp0) sync = true; |
653 | 796 | |
654 | 797 | // stepper enable B |
655 | | m_stp1 = BIT(data, 7); |
| 798 | int stp1 = BIT(data, 7); |
| 799 | if (m_stp1 != stp1) sync = true; |
| 800 | |
| 801 | if (sync) |
| 802 | { |
| 803 | live_sync(); |
| 804 | |
| 805 | m_stp0 = stp0; |
| 806 | update_stepper_motor(m_floppy0, m_stp0, m_st0, m_st0); |
| 807 | |
| 808 | m_stp1 = stp1; |
| 809 | update_stepper_motor(m_floppy1, m_stp1, m_st1, m_st1); |
| 810 | |
| 811 | checkpoint(); |
| 812 | live_run(); |
| 813 | } |
656 | 814 | } |
657 | 815 | |
658 | 816 | WRITE_LINE_MEMBER( victor_9000_fdc_t::drw_w ) |
659 | 817 | { |
| 818 | if (m_drw != state) |
| 819 | { |
| 820 | live_sync(); |
| 821 | m_drw = cur_live.drw = state; |
| 822 | checkpoint(); |
| 823 | if (LOG) logerror("%s DRW %u\n", machine().time().as_string(), state); |
| 824 | if (state) { |
| 825 | stop_writing(machine().time()); |
| 826 | } else { |
| 827 | start_writing(machine().time()); |
| 828 | } |
| 829 | live_run(); |
| 830 | } |
660 | 831 | } |
661 | 832 | |
662 | 833 | WRITE_LINE_MEMBER( victor_9000_fdc_t::erase_w ) |
663 | 834 | { |
| 835 | if (m_erase != state) |
| 836 | { |
| 837 | live_sync(); |
| 838 | m_erase = cur_live.erase = state; |
| 839 | checkpoint(); |
| 840 | if (LOG) logerror("%s ERASE %u\n", machine().time().as_string(), state); |
| 841 | live_run(); |
| 842 | } |
664 | 843 | } |
665 | 844 | |
666 | 845 | WRITE_LINE_MEMBER( victor_9000_fdc_t::via6_irq_w ) |
r241676 | r241677 | |
669 | 848 | |
670 | 849 | m_irq_cb(m_via4_irq || m_via5_irq || m_via6_irq); |
671 | 850 | } |
| 851 | |
| 852 | READ8_MEMBER( victor_9000_fdc_t::cs7_r ) |
| 853 | { |
| 854 | if (!checkpoint_live.lbrdy) |
| 855 | { |
| 856 | live_sync(); |
| 857 | cur_live.lbrdy = 1; |
| 858 | m_lbrdy_cb(1); |
| 859 | checkpoint(); |
| 860 | live_run(); |
| 861 | } |
| 862 | |
| 863 | return m_via5->read(space, offset); |
| 864 | } |
| 865 | |
| 866 | WRITE8_MEMBER( victor_9000_fdc_t::cs7_w ) |
| 867 | { |
| 868 | if (!checkpoint_live.lbrdy) |
| 869 | { |
| 870 | live_sync(); |
| 871 | cur_live.lbrdy = 1; |
| 872 | m_lbrdy_cb(1); |
| 873 | checkpoint(); |
| 874 | live_run(); |
| 875 | } |
| 876 | |
| 877 | m_via5->write(space, offset, data); |
| 878 | } |
| 879 | |
| 880 | floppy_image_device* victor_9000_fdc_t::get_floppy() |
| 881 | { |
| 882 | return m_drive ? m_floppy1 : m_floppy0; |
| 883 | } |
| 884 | |
| 885 | void victor_9000_fdc_t::live_start() |
| 886 | { |
| 887 | cur_live.tm = machine().time(); |
| 888 | cur_live.state = RUNNING; |
| 889 | cur_live.next_state = -1; |
| 890 | |
| 891 | cur_live.shift_reg = 0; |
| 892 | cur_live.shift_reg_write = 0; |
| 893 | cur_live.bit_counter = 0; |
| 894 | |
| 895 | cur_live.drive = m_drive; |
| 896 | cur_live.side = m_side; |
| 897 | cur_live.drw = m_drw; |
| 898 | cur_live.wd = m_wd; |
| 899 | cur_live.wrsync = m_wrsync; |
| 900 | cur_live.erase = m_erase; |
| 901 | |
| 902 | checkpoint_live = cur_live; |
| 903 | |
| 904 | live_run(); |
| 905 | } |
| 906 | |
| 907 | void victor_9000_fdc_t::checkpoint() |
| 908 | { |
| 909 | get_next_edge(machine().time()); |
| 910 | checkpoint_live = cur_live; |
| 911 | } |
| 912 | |
| 913 | void victor_9000_fdc_t::rollback() |
| 914 | { |
| 915 | cur_live = checkpoint_live; |
| 916 | get_next_edge(cur_live.tm); |
| 917 | } |
| 918 | |
| 919 | void victor_9000_fdc_t::start_writing(const attotime &tm) |
| 920 | { |
| 921 | cur_live.write_start_time = tm; |
| 922 | cur_live.write_position = 0; |
| 923 | } |
| 924 | |
| 925 | void victor_9000_fdc_t::stop_writing(const attotime &tm) |
| 926 | { |
| 927 | commit(tm); |
| 928 | cur_live.write_start_time = attotime::never; |
| 929 | } |
| 930 | |
| 931 | bool victor_9000_fdc_t::write_next_bit(bool bit, const attotime &limit) |
| 932 | { |
| 933 | if(cur_live.write_start_time.is_never()) { |
| 934 | cur_live.write_start_time = cur_live.tm; |
| 935 | cur_live.write_position = 0; |
| 936 | } |
| 937 | |
| 938 | attotime etime = cur_live.tm + m_period; |
| 939 | if(etime > limit) |
| 940 | return true; |
| 941 | |
| 942 | if(bit && cur_live.write_position < ARRAY_LENGTH(cur_live.write_buffer)) |
| 943 | cur_live.write_buffer[cur_live.write_position++] = cur_live.tm; |
| 944 | |
| 945 | if (LOG) logerror("%s write bit %u (%u)\n", cur_live.tm.as_string(), cur_live.bit_counter, bit); |
| 946 | |
| 947 | return false; |
| 948 | } |
| 949 | |
| 950 | void victor_9000_fdc_t::commit(const attotime &tm) |
| 951 | { |
| 952 | if(cur_live.write_start_time.is_never() || tm == cur_live.write_start_time || !cur_live.write_position) |
| 953 | return; |
| 954 | |
| 955 | if (LOG) logerror("%s committing %u transitions since %s\n", tm.as_string(), cur_live.write_position, cur_live.write_start_time.as_string()); |
| 956 | |
| 957 | if(get_floppy()) |
| 958 | get_floppy()->write_flux(cur_live.write_start_time, tm, cur_live.write_position, cur_live.write_buffer); |
| 959 | |
| 960 | cur_live.write_start_time = tm; |
| 961 | cur_live.write_position = 0; |
| 962 | } |
| 963 | |
| 964 | void victor_9000_fdc_t::live_delay(int state) |
| 965 | { |
| 966 | cur_live.next_state = state; |
| 967 | if(cur_live.tm != machine().time()) |
| 968 | t_gen->adjust(cur_live.tm - machine().time()); |
| 969 | else |
| 970 | live_sync(); |
| 971 | } |
| 972 | |
| 973 | void victor_9000_fdc_t::live_sync() |
| 974 | { |
| 975 | if(!cur_live.tm.is_never()) { |
| 976 | if(cur_live.tm > machine().time()) { |
| 977 | rollback(); |
| 978 | live_run(machine().time()); |
| 979 | commit(cur_live.tm); |
| 980 | } else { |
| 981 | commit(cur_live.tm); |
| 982 | if(cur_live.next_state != -1) { |
| 983 | cur_live.state = cur_live.next_state; |
| 984 | cur_live.next_state = -1; |
| 985 | } |
| 986 | if(cur_live.state == IDLE) { |
| 987 | stop_writing(cur_live.tm); |
| 988 | cur_live.tm = attotime::never; |
| 989 | } |
| 990 | } |
| 991 | cur_live.next_state = -1; |
| 992 | checkpoint(); |
| 993 | } |
| 994 | } |
| 995 | |
| 996 | void victor_9000_fdc_t::live_abort() |
| 997 | { |
| 998 | if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) { |
| 999 | rollback(); |
| 1000 | live_run(machine().time()); |
| 1001 | } |
| 1002 | |
| 1003 | stop_writing(cur_live.tm); |
| 1004 | |
| 1005 | cur_live.tm = attotime::never; |
| 1006 | cur_live.state = IDLE; |
| 1007 | cur_live.next_state = -1; |
| 1008 | cur_live.write_position = 0; |
| 1009 | cur_live.write_start_time = attotime::never; |
| 1010 | |
| 1011 | cur_live.brdy = 1; |
| 1012 | cur_live.lbrdy = 1; |
| 1013 | cur_live.sync = 1; |
| 1014 | cur_live.gcr_err = 1; |
| 1015 | } |
| 1016 | |
| 1017 | void victor_9000_fdc_t::live_run(const attotime &limit) |
| 1018 | { |
| 1019 | if(cur_live.state == IDLE || cur_live.next_state != -1) |
| 1020 | return; |
| 1021 | |
| 1022 | for(;;) { |
| 1023 | switch(cur_live.state) { |
| 1024 | case RUNNING: { |
| 1025 | bool syncpoint = false; |
| 1026 | |
| 1027 | if (cur_live.tm > limit) |
| 1028 | return; |
| 1029 | |
| 1030 | // read bit |
| 1031 | int bit = get_next_bit(cur_live.tm, limit); |
| 1032 | if(bit < 0) |
| 1033 | return; |
| 1034 | |
| 1035 | cur_live.shift_reg <<= 1; |
| 1036 | cur_live.shift_reg |= bit; |
| 1037 | cur_live.shift_reg &= 0x3ff; |
| 1038 | |
| 1039 | // sync |
| 1040 | int sync = !(cur_live.shift_reg == 0x3ff); |
| 1041 | |
| 1042 | // bit counter |
| 1043 | if (!sync) { |
| 1044 | cur_live.bit_counter = 0; |
| 1045 | } else if (cur_live.sync) { |
| 1046 | cur_live.bit_counter++; |
| 1047 | if (cur_live.bit_counter == 10) { |
| 1048 | cur_live.bit_counter = 0; |
| 1049 | } |
| 1050 | } |
| 1051 | |
| 1052 | // GCR decoder |
| 1053 | if (cur_live.drw) { |
| 1054 | cur_live.i = cur_live.drw << 10 | cur_live.shift_reg; |
| 1055 | } else { |
| 1056 | cur_live.i = 0x300 | ((cur_live.wd & 0xf0) << 1) | cur_live.wrsync << 4 | (cur_live.wd & 0x0f); |
| 1057 | } |
| 1058 | |
| 1059 | cur_live.e = m_gcr_rom->base()[cur_live.i]; |
| 1060 | |
| 1061 | // byte ready |
| 1062 | int brdy = cur_live.bit_counter == 9; |
| 1063 | |
| 1064 | // GCR error |
| 1065 | int gcr_err = !(brdy || BIT(cur_live.e, 3)); |
| 1066 | |
| 1067 | if (brdy != cur_live.brdy) { |
| 1068 | if (LOG) logerror("%s BRDY %u\n", cur_live.tm.as_string(),brdy); |
| 1069 | cur_live.brdy = brdy; |
| 1070 | if (!brdy) cur_live.lbrdy = 0; |
| 1071 | syncpoint = true; |
| 1072 | } |
| 1073 | |
| 1074 | if (sync != cur_live.sync) { |
| 1075 | if (LOG) logerror("%s SYNC %u\n", cur_live.tm.as_string(),sync); |
| 1076 | cur_live.sync = sync; |
| 1077 | syncpoint = true; |
| 1078 | } |
| 1079 | |
| 1080 | if (gcr_err != cur_live.gcr_err) { |
| 1081 | if (LOG) logerror("%s GCR ERR %u\n", cur_live.tm.as_string(),gcr_err); |
| 1082 | cur_live.gcr_err = gcr_err; |
| 1083 | syncpoint = true; |
| 1084 | } |
| 1085 | |
| 1086 | if (syncpoint) { |
| 1087 | commit(cur_live.tm); |
| 1088 | |
| 1089 | cur_live.tm += m_period; |
| 1090 | live_delay(RUNNING_SYNCPOINT); |
| 1091 | return; |
| 1092 | } |
| 1093 | |
| 1094 | cur_live.tm += m_period; |
| 1095 | break; |
| 1096 | } |
| 1097 | |
| 1098 | case RUNNING_SYNCPOINT: { |
| 1099 | m_lbrdy_cb(cur_live.lbrdy); |
| 1100 | |
| 1101 | cur_live.state = RUNNING; |
| 1102 | checkpoint(); |
| 1103 | break; |
| 1104 | } |
| 1105 | } |
| 1106 | } |
| 1107 | } |
| 1108 | |
| 1109 | void victor_9000_fdc_t::get_next_edge(const attotime &when) |
| 1110 | { |
| 1111 | // TODO |
| 1112 | } |
| 1113 | |
| 1114 | int victor_9000_fdc_t::get_next_bit(attotime &tm, const attotime &limit) |
| 1115 | { |
| 1116 | return -1; // TODO |
| 1117 | } |
trunk/src/mess/machine/victor9k_fdc.h
r241676 | r241677 | |
29 | 29 | #define MCFG_VICTOR_9000_FDC_IRQ_CB(_write) \ |
30 | 30 | devcb = &victor_9000_fdc_t::set_irq_wr_callback(*device, DEVCB_##_write); |
31 | 31 | |
| 32 | #define MCFG_VICTOR_9000_FDC_SYN_CB(_write) \ |
| 33 | devcb = &victor_9000_fdc_t::set_syn_wr_callback(*device, DEVCB_##_write); |
32 | 34 | |
| 35 | #define MCFG_VICTOR_9000_FDC_LBRDY_CB(_write) \ |
| 36 | devcb = &victor_9000_fdc_t::set_lbrdy_wr_callback(*device, DEVCB_##_write); |
33 | 37 | |
| 38 | |
| 39 | |
34 | 40 | //************************************************************************** |
35 | 41 | // TYPE DEFINITIONS |
36 | 42 | //************************************************************************** |
r241676 | r241677 | |
44 | 50 | victor_9000_fdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
45 | 51 | |
46 | 52 | template<class _Object> static devcb_base &set_irq_wr_callback(device_t &device, _Object object) { return downcast<victor_9000_fdc_t &>(device).m_irq_cb.set_callback(object); } |
| 53 | template<class _Object> static devcb_base &set_syn_wr_callback(device_t &device, _Object object) { return downcast<victor_9000_fdc_t &>(device).m_syn_cb.set_callback(object); } |
| 54 | template<class _Object> static devcb_base &set_lbrdy_wr_callback(device_t &device, _Object object) { return downcast<victor_9000_fdc_t &>(device).m_lbrdy_cb.set_callback(object); } |
47 | 55 | |
48 | 56 | DECLARE_READ8_MEMBER( cs5_r ) { return m_via4->read(space, offset); } |
49 | | DECLARE_WRITE8_MEMBER( cs5_w ) { return m_via4->write(space, offset, data); } |
| 57 | DECLARE_WRITE8_MEMBER( cs5_w ) { m_via4->write(space, offset, data); } |
50 | 58 | DECLARE_READ8_MEMBER( cs6_r ) { return m_via6->read(space, offset); } |
51 | | DECLARE_WRITE8_MEMBER( cs6_w ) { return m_via6->write(space, offset, data); } |
52 | | DECLARE_READ8_MEMBER( cs7_r ) { return m_via5->read(space, offset); } |
53 | | DECLARE_WRITE8_MEMBER( cs7_w ) { return m_via5->write(space, offset, data); } |
| 59 | DECLARE_WRITE8_MEMBER( cs6_w ) { m_via6->write(space, offset, data); } |
| 60 | DECLARE_READ8_MEMBER( cs7_r ); |
| 61 | DECLARE_WRITE8_MEMBER( cs7_w ); |
54 | 62 | |
55 | 63 | DECLARE_FLOPPY_FORMATS( floppy_formats ); |
56 | 64 | |
r241676 | r241677 | |
63 | 71 | |
64 | 72 | DECLARE_WRITE8_MEMBER( via4_pa_w ); |
65 | 73 | DECLARE_WRITE8_MEMBER( via4_pb_w ); |
66 | | DECLARE_WRITE_LINE_MEMBER( mode_w ); |
| 74 | DECLARE_WRITE_LINE_MEMBER( wrsync_w ); |
67 | 75 | DECLARE_WRITE_LINE_MEMBER( via4_irq_w ); |
68 | 76 | |
69 | 77 | DECLARE_READ8_MEMBER( via5_pa_r ); |
r241676 | r241677 | |
91 | 99 | private: |
92 | 100 | enum |
93 | 101 | { |
| 102 | TM_GEN, |
| 103 | TM_TACH0, |
| 104 | TM_TACH1 |
| 105 | }; |
| 106 | |
| 107 | enum |
| 108 | { |
94 | 109 | LED_A = 0, |
95 | 110 | LED_B |
96 | 111 | }; |
97 | 112 | |
| 113 | enum { |
| 114 | IDLE, |
| 115 | RUNNING, |
| 116 | RUNNING_SYNCPOINT |
| 117 | }; |
| 118 | |
| 119 | struct live_info { |
| 120 | attotime tm; |
| 121 | int state, next_state; |
| 122 | |
| 123 | int drive; |
| 124 | int side; |
| 125 | int drw; |
| 126 | |
| 127 | // common |
| 128 | offs_t i; |
| 129 | UINT8 e; |
| 130 | |
| 131 | // read |
| 132 | attotime edge; |
| 133 | UINT16 shift_reg; |
| 134 | int bit_counter; |
| 135 | int brdy; |
| 136 | int lbrdy; |
| 137 | int sync; |
| 138 | int gcr_err; |
| 139 | |
| 140 | // write |
| 141 | UINT16 shift_reg_write; |
| 142 | attotime write_start_time; |
| 143 | attotime write_buffer[32]; |
| 144 | int write_position; |
| 145 | UINT8 wd; |
| 146 | int wrsync; |
| 147 | int syn; |
| 148 | int gcr_data; |
| 149 | int erase; |
| 150 | }; |
| 151 | |
98 | 152 | devcb_write_line m_irq_cb; |
| 153 | devcb_write_line m_syn_cb; |
| 154 | devcb_write_line m_lbrdy_cb; |
99 | 155 | |
100 | 156 | required_device<cpu_device> m_maincpu; |
101 | 157 | required_device<via6522_device> m_via4; |
r241676 | r241677 | |
105 | 161 | required_device<floppy_image_device> m_floppy1; |
106 | 162 | required_memory_region m_gcr_rom; |
107 | 163 | |
| 164 | void update_stepper_motor(floppy_image_device *floppy, int stp, int old_st, int st); |
| 165 | void update_spindle_motor(); |
| 166 | |
108 | 167 | void ready0_cb(floppy_image_device *, int device); |
109 | 168 | int load0_cb(floppy_image_device *device); |
110 | 169 | void unload0_cb(floppy_image_device *device); |
r241676 | r241677 | |
116 | 175 | UINT8 m_da; |
117 | 176 | UINT8 m_da0; |
118 | 177 | UINT8 m_da1; |
| 178 | int m_mtr0; |
| 179 | int m_mtr1; |
119 | 180 | int m_sel0; |
120 | 181 | int m_sel1; |
121 | 182 | int m_tach0; |
r241676 | r241677 | |
124 | 185 | int m_rdy1; |
125 | 186 | int m_ds0; |
126 | 187 | int m_ds1; |
127 | | UINT8 m_lms; /* motor speed */ |
128 | | int m_st0; /* stepper phase */ |
129 | | int m_st1; /* stepper phase */ |
130 | | int m_stp0; /* stepper enable */ |
131 | | int m_stp1; /* stepper enable */ |
132 | | int m_drive; /* selected drive */ |
133 | | int m_side; /* selected side */ |
134 | | int m_brdy; |
135 | | int m_sync; |
136 | | int m_gcrerr; |
| 188 | UINT8 m_l0ms; |
| 189 | UINT8 m_l1ms; |
| 190 | int m_st0; |
| 191 | int m_st1; |
| 192 | int m_stp0; |
| 193 | int m_stp1; |
| 194 | int m_drive; |
| 195 | int m_side; |
| 196 | int m_drw; |
| 197 | int m_erase; |
| 198 | UINT8 m_wd; |
| 199 | int m_wrsync; |
137 | 200 | |
138 | 201 | int m_via4_irq; |
139 | 202 | int m_via5_irq; |
140 | 203 | int m_via6_irq; |
| 204 | int m_syn; |
| 205 | int m_lbrdy; |
| 206 | |
| 207 | attotime m_period; |
| 208 | |
| 209 | live_info cur_live, checkpoint_live; |
| 210 | emu_timer *t_gen, *t_tach0, *t_tach1; |
| 211 | |
| 212 | floppy_image_device* get_floppy(); |
| 213 | void live_start(); |
| 214 | void checkpoint(); |
| 215 | void rollback(); |
| 216 | bool write_next_bit(bool bit, const attotime &limit); |
| 217 | void start_writing(const attotime &tm); |
| 218 | void commit(const attotime &tm); |
| 219 | void stop_writing(const attotime &tm); |
| 220 | void live_delay(int state); |
| 221 | void live_sync(); |
| 222 | void live_abort(); |
| 223 | void live_run(const attotime &limit = attotime::never); |
| 224 | void get_next_edge(const attotime &when); |
| 225 | int get_next_bit(attotime &tm, const attotime &limit); |
141 | 226 | }; |
142 | 227 | |
143 | 228 | |