src/mame/machine/archimds.c
| r8873 | r8874 | |
| 31 | 31 | #include "sound/dac.h" |
| 32 | 32 | #include "includes/archimds.h" |
| 33 | 33 | #include "machine/i2cmem.h" |
| 34 | #include "debugger.h" |
| 34 | 35 | |
| 35 | 36 | #ifdef MESS |
| 36 | 37 | #include "machine/wd17xx.h" |
| r8873 | r8874 | |
| 139 | 140 | |
| 140 | 141 | vidc_sndcur++; |
| 141 | 142 | |
| 142 | | if (vidc_sndcur >= vidc_sndend-vidc_sndstart) |
| 143 | if (vidc_sndcur >= (vidc_sndend-vidc_sndstart)+0x10) |
| 143 | 144 | { |
| 144 | 145 | vidc_sndcur = 0; |
| 145 | 146 | archimedes_request_irq_b(machine, ARCHIMEDES_IRQB_SOUND_EMPTY); |
| r8873 | r8874 | |
| 156 | 157 | { |
| 157 | 158 | double freq; |
| 158 | 159 | |
| 159 | | if(ioc_timercnt[tmr] != 0) // FIXME: dmdtouch does a divide by zero? |
| 160 | switch(tmr) |
| 160 | 161 | { |
| 161 | | freq = 2000000.0 / (double)ioc_timercnt[tmr]; |
| 162 | | // logerror("IOC: starting timer %d, %d ticks, freq %f Hz\n", tmr, ioc_timercnt[tmr], freq); |
| 163 | | timer_adjust_oneshot(timer[tmr], ATTOTIME_IN_HZ(freq), tmr); |
| 162 | case 0: |
| 163 | case 1: |
| 164 | timer_adjust_oneshot(timer[tmr], ATTOTIME_IN_USEC(ioc_timercnt[tmr]/8), tmr); // TODO: ARM timings are quite off there, it should be latch and not latch/8 |
| 165 | break; |
| 166 | case 2: |
| 167 | freq = 1000000.0 / (double)(ioc_timercnt[tmr]+1); |
| 168 | timer_adjust_oneshot(timer[tmr], ATTOTIME_IN_HZ(freq), tmr); |
| 169 | break; |
| 170 | case 3: |
| 171 | freq = 1000000.0 / (double)((ioc_timercnt[tmr]+1)*16); |
| 172 | timer_adjust_oneshot(timer[tmr], ATTOTIME_IN_HZ(freq), tmr); |
| 173 | break; |
| 164 | 174 | } |
| 165 | 175 | } |
| 166 | 176 | |
| r8873 | r8874 | |
| 198 | 208 | ioc_regs[IRQ_STATUS_A] = 0x10 | 0x80; //set up POR (Power On Reset) and Force IRQ at start-up |
| 199 | 209 | ioc_regs[IRQ_STATUS_B] = 0x02; //set up IL[1] On |
| 200 | 210 | ioc_regs[FIQ_STATUS] = 0x80; //set up Force FIQ |
| 211 | ioc_regs[CONTROL] = 0xff; |
| 201 | 212 | } |
| 202 | 213 | |
| 203 | 214 | void archimedes_init(running_machine *machine) |
| r8873 | r8874 | |
| 365 | 376 | if(IOC_LOG) |
| 366 | 377 | logerror("IOC: R %s = %02x (PC=%x) %02x\n", ioc_regnames[offset&0x1f], ioc_regs[offset&0x1f], cpu_get_pc( space->cpu ),offset & 0x1f); |
| 367 | 378 | |
| 379 | if((offset & 0x1f) >= 0x40/4) |
| 380 | printf("IOC: R %s = %02x (PC=%x) %02x\n", ioc_regnames[offset&0x1f], ioc_regs[offset&0x1f], cpu_get_pc( space->cpu ),offset & 0x1f); |
| 381 | |
| 368 | 382 | switch (offset & 0x1f) |
| 369 | 383 | { |
| 370 | 384 | case CONTROL: |
| r8873 | r8874 | |
| 381 | 395 | return (flyback) | (ioc_regs[CONTROL] & 0x7c) | (i2c_clk<<1) | i2c_data; |
| 382 | 396 | } |
| 383 | 397 | |
| 384 | | case 1: // keyboard read |
| 398 | case KART: // keyboard read |
| 385 | 399 | archimedes_request_irq_b(space->machine, ARCHIMEDES_IRQB_KBD_XMIT_EMPTY); |
| 386 | 400 | break; |
| 387 | 401 | |
| r8873 | r8874 | |
| 412 | 426 | case FIQ_MASK: |
| 413 | 427 | return (ioc_regs[FIQ_MASK]); |
| 414 | 428 | |
| 415 | | case 16: // timer 0 read |
| 416 | | return ioc_timerout[0]&0xff; |
| 417 | | case 17: |
| 418 | | return (ioc_timerout[0]>>8)&0xff; |
| 419 | | case 20: // timer 1 read |
| 420 | | return ioc_timerout[1]&0xff; |
| 421 | | case 21: |
| 422 | | return (ioc_timerout[1]>>8)&0xff; |
| 423 | | case 24: // timer 2 read |
| 424 | | return ioc_timerout[2]&0xff; |
| 425 | | case 25: |
| 426 | | return (ioc_timerout[2]>>8)&0xff; |
| 427 | | case 28: // timer 3 read |
| 428 | | return ioc_timerout[3]&0xff; |
| 429 | | case 29: |
| 430 | | return (ioc_timerout[3]>>8)&0xff; |
| 429 | case T0_LATCH_LO: return ioc_timerout[0]&0xff; |
| 430 | case T0_LATCH_HI: return (ioc_timerout[0]>>8)&0xff; |
| 431 | |
| 432 | case T1_LATCH_LO: return ioc_timerout[1]&0xff; |
| 433 | case T1_LATCH_HI: return (ioc_timerout[1]>>8)&0xff; |
| 434 | |
| 435 | case T2_LATCH_LO: return ioc_timerout[2]&0xff; |
| 436 | case T2_LATCH_HI: return (ioc_timerout[2]>>8)&0xff; |
| 437 | |
| 438 | case T3_LATCH_LO: return ioc_timerout[3]&0xff; |
| 439 | case T3_LATCH_HI: return (ioc_timerout[3]>>8)&0xff; |
| 431 | 440 | default: |
| 432 | 441 | if(!IOC_LOG) |
| 433 | 442 | logerror("IOC: R %s = %02x (PC=%x) %02x\n", ioc_regnames[offset&0x1f], ioc_regs[offset&0x1f], cpu_get_pc( space->cpu ),offset & 0x1f); |
| r8873 | r8874 | |
| 443 | 452 | if(IOC_LOG) |
| 444 | 453 | logerror("IOC: W %02x @ reg %s (PC=%x)\n", data&0xff, ioc_regnames[offset&0x1f], cpu_get_pc( space->cpu )); |
| 445 | 454 | |
| 455 | if((offset & 0x1f) >= 0x40/4) |
| 456 | printf("IOC: W %02x @ reg %s (PC=%x)\n", data&0xff, ioc_regnames[offset&0x1f], cpu_get_pc( space->cpu )); |
| 457 | |
| 458 | |
| 446 | 459 | switch (offset&0x1f) |
| 447 | 460 | { |
| 448 | | case 0: // I2C bus control |
| 461 | case CONTROL: // I2C bus control |
| 449 | 462 | //logerror("IOC I2C: CLK %d DAT %d\n", (data>>1)&1, data&1); |
| 450 | 463 | i2cmem_sda_write(space->machine->device("i2cmem"), data & 0x01); |
| 451 | 464 | i2cmem_scl_write(space->machine->device("i2cmem"), (data & 0x02) >> 1); |
| 452 | 465 | i2c_clk = (data & 2) >> 1; |
| 453 | 466 | break; |
| 454 | 467 | |
| 455 | | case 1: |
| 468 | case KART: |
| 456 | 469 | #if 0 |
| 457 | 470 | if(data == 0x0d) |
| 458 | 471 | printf("\n"); |
| r8873 | r8874 | |
| 470 | 483 | if(data & 0x08) //set up the VBLANK timer |
| 471 | 484 | timer_adjust_oneshot(vbl_timer, space->machine->primary_screen->time_until_pos(vidc_regs[0xb4]), 0); |
| 472 | 485 | |
| 473 | | //printf("MASKA: %02x\n",data); |
| 474 | 486 | break; |
| 475 | 487 | |
| 476 | | case IRQ_MASK_B: |
| 477 | | ioc_regs[IRQ_MASK_B] = data & 0xff; |
| 478 | | |
| 479 | | //printf("MASKB: %02x\n",data); |
| 480 | | break; |
| 481 | | |
| 482 | 488 | case FIQ_MASK: |
| 483 | 489 | ioc_regs[FIQ_MASK] = data & 0xff; |
| 484 | 490 | |
| 485 | 491 | if(data & 0x80) //force a FIRQ |
| 486 | 492 | archimedes_request_fiq(space->machine,ARCHIMEDES_FIQ_FORCE); |
| 487 | 493 | |
| 488 | | //printf("FMASK: %02x\n",data); |
| 489 | | |
| 490 | 494 | break; |
| 491 | 495 | |
| 492 | 496 | case IRQ_REQUEST_A: // IRQ clear A |
| 493 | 497 | ioc_regs[IRQ_STATUS_A] &= ~(data&0xff); |
| 494 | 498 | |
| 495 | 499 | // if that did it, clear the IRQ |
| 496 | | if (ioc_regs[IRQ_STATUS_A] == 0) |
| 500 | //if (ioc_regs[IRQ_STATUS_A] == 0) |
| 497 | 501 | { |
| 498 | | printf("IRQ clear A\n"); |
| 502 | //printf("IRQ clear A\n"); |
| 499 | 503 | cputag_set_input_line(space->machine, "maincpu", ARM_IRQ_LINE, CLEAR_LINE); |
| 500 | 504 | } |
| 501 | 505 | break; |
| 502 | 506 | |
| 503 | | case 16: |
| 504 | | case 17: |
| 507 | case T0_LATCH_LO: |
| 508 | case T0_LATCH_HI: |
| 505 | 509 | ioc_regs[offset&0x1f] = data & 0xff; |
| 506 | 510 | break; |
| 507 | 511 | |
| 508 | | case 20: |
| 509 | | case 21: |
| 512 | case T1_LATCH_LO: |
| 513 | case T1_LATCH_HI: |
| 510 | 514 | ioc_regs[offset&0x1f] = data & 0xff; |
| 511 | 515 | break; |
| 512 | 516 | |
| 513 | | case 24: |
| 514 | | case 25: |
| 517 | case T2_LATCH_LO: |
| 518 | case T2_LATCH_HI: |
| 515 | 519 | ioc_regs[offset&0x1f] = data & 0xff; |
| 516 | 520 | break; |
| 517 | 521 | |
| 518 | | case 28: |
| 519 | | case 29: |
| 522 | case T3_LATCH_LO: |
| 523 | case T3_LATCH_HI: |
| 520 | 524 | ioc_regs[offset&0x1f] = data & 0xff; |
| 521 | 525 | break; |
| 522 | 526 | |
| 523 | | case 19: // Timer 0 latch |
| 527 | case T0_LATCH: // Timer 0 latch |
| 524 | 528 | latch_timer_cnt(0); |
| 525 | 529 | break; |
| 526 | 530 | |
| 527 | | case 23: // Timer 1 latch |
| 531 | case T1_LATCH: // Timer 1 latch |
| 528 | 532 | latch_timer_cnt(1); |
| 529 | 533 | break; |
| 530 | 534 | |
| 531 | | case 27: // Timer 2 latch |
| 535 | case T2_LATCH: // Timer 2 latch |
| 532 | 536 | latch_timer_cnt(2); |
| 533 | 537 | break; |
| 534 | 538 | |
| 535 | | case 31: // Timer 3 latch |
| 539 | case T3_LATCH: // Timer 3 latch |
| 536 | 540 | latch_timer_cnt(3); |
| 537 | 541 | break; |
| 538 | 542 | |
| 539 | | case 18: // Timer 0 start |
| 540 | | ioc_timercnt[0] = ioc_regs[17]<<8 | ioc_regs[16]; |
| 543 | case T0_GO: // Timer 0 start |
| 544 | ioc_timercnt[0] = ioc_regs[T0_LATCH_HI]<<8 | ioc_regs[T0_LATCH_LO]; |
| 541 | 545 | a310_set_timer(0); |
| 542 | 546 | break; |
| 543 | 547 | |
| 544 | | case 22: // Timer 1 start |
| 545 | | ioc_timercnt[1] = ioc_regs[21]<<8 | ioc_regs[20]; |
| 548 | case T1_GO: // Timer 1 start |
| 549 | ioc_timercnt[1] = ioc_regs[T1_LATCH_HI]<<8 | ioc_regs[T1_LATCH_LO]; |
| 546 | 550 | a310_set_timer(1); |
| 547 | 551 | break; |
| 548 | 552 | |
| 549 | | case 26: // Timer 2 start |
| 550 | | ioc_timercnt[2] = ioc_regs[25]<<8 | ioc_regs[24]; |
| 553 | case T2_GO: // Timer 2 start |
| 554 | ioc_timercnt[2] = ioc_regs[T2_LATCH_HI]<<8 | ioc_regs[T2_LATCH_LO]; |
| 551 | 555 | a310_set_timer(2); |
| 552 | 556 | break; |
| 553 | 557 | |
| 554 | | case 30: // Timer 3 start |
| 555 | | ioc_timercnt[3] = ioc_regs[29]<<8 | ioc_regs[28]; |
| 558 | case T3_GO: // Timer 3 start |
| 559 | ioc_timercnt[3] = ioc_regs[T3_LATCH_HI]<<8 | ioc_regs[T3_LATCH_LO]; |
| 556 | 560 | a310_set_timer(3); |
| 557 | 561 | break; |
| 558 | 562 | |
| r8873 | r8874 | |
| 855 | 859 | break; |
| 856 | 860 | |
| 857 | 861 | case 4: /* sound start */ |
| 858 | | //logerror("MEMC: VIDSNDSTART %08x\n",data); |
| 862 | //logerror("MEMC: SNDSTART %08x\n",data); |
| 859 | 863 | vidc_sndstart = 0x2000000 | ((data>>2)&0x7fff)*16; |
| 864 | ioc_regs[IRQ_STATUS_B] &= ~ARCHIMEDES_IRQB_SOUND_EMPTY; |
| 860 | 865 | break; |
| 861 | 866 | |
| 862 | 867 | case 5: /* sound end */ |
| 863 | | //logerror("MEMC: VIDSNDEND %08x\n",data); |
| 868 | //logerror("MEMC: SNDEND %08x\n",data); |
| 864 | 869 | vidc_sndend = 0x2000000 | ((data>>2)&0x7fff)*16; |
| 870 | archimedes_request_irq_b(space->machine, ARCHIMEDES_IRQB_SOUND_EMPTY); |
| 865 | 871 | break; |
| 866 | 872 | |
| 867 | 873 | case 7: /* Control */ |