src/mess/drivers/gp32.c
| r6588 | r6589 | |
| 20 | 20 | #include "cpu/arm7/arm7core.h" |
| 21 | 21 | #include "machine/smartmed.h" |
| 22 | 22 | #include "includes/gp32.h" |
| 23 | | #include "sound/dmadac.h" |
| 23 | #include "sound/dac.h" |
| 24 | 24 | |
| 25 | #define CLOCK_MULTIPLIER 1 |
| 26 | |
| 25 | 27 | #define BIT(x,n) (((x)>>(n))&1) |
| 26 | 28 | #define BITS(x,m,n) (((x)>>(n))&((1<<((m)-(n)+1))-1)) |
| 27 | 29 | |
| r6588 | r6589 | |
| 200 | 202 | // MPLLCON |
| 201 | 203 | case 0x04 / 4 : |
| 202 | 204 | { |
| 203 | | cputag_set_clock( space->machine, "maincpu", s3c240x_get_fclk( MPLLCON)); |
| 205 | cputag_set_clock( space->machine, "maincpu", s3c240x_get_fclk( MPLLCON) * CLOCK_MULTIPLIER); |
| 204 | 206 | } |
| 205 | 207 | break; |
| 206 | 208 | } |
| r6588 | r6589 | |
| 417 | 419 | |
| 418 | 420 | // DMA |
| 419 | 421 | |
| 422 | static emu_timer *s3c240x_dma_timer[4]; |
| 420 | 423 | static UINT32 s3c240x_dma_regs[0x7c/4]; |
| 421 | 424 | |
| 422 | | static void s3c240x_dma_start( running_machine *machine, int dma) |
| 425 | static void s3c240x_dma_trigger( running_machine *machine, int dma) |
| 423 | 426 | { |
| 424 | | const address_space *space = cpu_get_address_space( cputag_get_cpu( machine, "maincpu"), ADDRESS_SPACE_PROGRAM); |
| 425 | | UINT32 addr_src, addr_dst, dsz, tsz, tc, reg; |
| 426 | | int i, inc_src, inc_dst; |
| 427 | | reg = dma << 3; |
| 428 | | inc_src = (s3c240x_dma_regs[reg+0] >> 29) & 1; |
| 429 | | addr_src = s3c240x_dma_regs[reg+0] & 0x1FFFFFFF; |
| 430 | | inc_dst = (s3c240x_dma_regs[reg+1] >> 29) & 1; |
| 431 | | addr_dst = s3c240x_dma_regs[reg+1] & 0x1FFFFFFF; |
| 432 | | tsz = (s3c240x_dma_regs[reg+2] >> 27) & 1; |
| 433 | | dsz = (s3c240x_dma_regs[reg+2] >> 20) & 3; |
| 434 | | tc = (s3c240x_dma_regs[reg+2] >> 0) & 0x000FFFFF; |
| 435 | | // logerror( "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d tsz %d dsz %d tc %d\n", dma, addr_src, inc_src, addr_dst, inc_dst, tsz, dsz, tc); |
| 436 | | // logerror( "DMA %d - copy %08X bytes from %08X (%s) to %08X (%s)\n", dma, tc << dsz, addr_src, inc_src ? "fix" : "inc", addr_dst, inc_dst ? "fix" : "inc"); |
| 437 | | for (i=0;i<tc;i++) |
| 427 | UINT32 *regs = &s3c240x_dma_regs[dma<<3]; |
| 428 | UINT32 curr_tc, curr_src, curr_dst; |
| 429 | const address_space *space = cputag_get_address_space( machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| 430 | int dsz, inc; |
| 431 | static UINT32 ch_int[] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3}; |
| 432 | // logerror( "DMA %d trigger\n", dma); |
| 433 | curr_tc = BITS( regs[3], 19, 0); |
| 434 | curr_src = BITS( regs[4], 28, 0); |
| 435 | curr_dst = BITS( regs[5], 28, 0); |
| 436 | dsz = BITS( regs[2], 21, 20); |
| 437 | // logerror( "DMA %d - curr_src %08X curr_dst %08X curr_tc %04X dsz %d\n", dma, curr_src, curr_dst, curr_tc, dsz); |
| 438 | switch (dsz) |
| 438 | 439 | { |
| 439 | | switch (dsz) |
| 440 | case 0 : memory_write_byte( space, curr_dst, memory_read_byte( space, curr_src)); break; |
| 441 | case 1 : memory_write_word( space, curr_dst, memory_read_word( space, curr_src)); break; |
| 442 | case 2 : memory_write_dword( space, curr_dst, memory_read_dword( space, curr_src)); break; |
| 443 | } |
| 444 | // update curr_src |
| 445 | inc = BIT( regs[0], 29); |
| 446 | if (!inc) |
| 447 | { |
| 448 | curr_src += (1 << dsz); |
| 449 | regs[4] = (regs[4] & ~0x1FFFFFFF) | curr_src; |
| 450 | } |
| 451 | // update curr_dst |
| 452 | inc = BIT( regs[1], 29); |
| 453 | if (!inc) |
| 454 | { |
| 455 | curr_dst += (1 << dsz); |
| 456 | regs[5] = (regs[5] & ~0x1FFFFFFF) | curr_dst; |
| 457 | } |
| 458 | // update curr_tc |
| 459 | curr_tc--; |
| 460 | regs[3] = (regs[3] & ~0x000FFFFF) | curr_tc; |
| 461 | // ... |
| 462 | if (curr_tc == 0) |
| 463 | { |
| 464 | int _int, reload; |
| 465 | reload = BIT( regs[2], 22); |
| 466 | if (!reload) |
| 440 | 467 | { |
| 441 | | case 0 : memory_write_byte( space, addr_dst, memory_read_byte( space, addr_src)); break; |
| 442 | | case 1 : memory_write_word( space, addr_dst, memory_read_word( space, addr_src)); break; |
| 443 | | case 2 : memory_write_dword( space, addr_dst, memory_read_dword( space, addr_src)); break; |
| 468 | regs[3] = (regs[3] & ~0x000FFFFF) | BITS( regs[2], 19, 0); |
| 469 | regs[4] = (regs[4] & ~0x1FFFFFFF) | BITS( regs[0], 28, 0); |
| 470 | regs[5] = (regs[5] & ~0x1FFFFFFF) | BITS( regs[1], 28, 0); |
| 444 | 471 | } |
| 445 | | if (!inc_src) addr_src += (1 << dsz); |
| 446 | | if (!inc_dst) addr_dst += (1 << dsz); |
| 472 | else |
| 473 | { |
| 474 | regs[6] &= ~(1 << 1); // clear on/off |
| 475 | } |
| 476 | _int = BIT( regs[2], 28); |
| 477 | if (_int) |
| 478 | { |
| 479 | // logerror( "DMA %d request irq\n", dma); |
| 480 | s3c240x_request_irq( machine, ch_int[dma]); |
| 481 | } |
| 447 | 482 | } |
| 448 | 483 | } |
| 449 | 484 | |
| 485 | static void s3c240x_dma_start( running_machine *machine, int dma) |
| 486 | { |
| 487 | UINT32 addr_src, addr_dst, tc; |
| 488 | UINT32 *regs = &s3c240x_dma_regs[dma<<3]; |
| 489 | // UINT32 dsz, tsz, reload; |
| 490 | // int inc_src, inc_dst, _int, servmode, swhw_sel, hwsrcsel; |
| 491 | // logerror( "DMA %d start\n", dma); |
| 492 | addr_src = BITS( regs[0], 28, 0); |
| 493 | addr_dst = BITS( regs[1], 28, 0); |
| 494 | tc = BITS( regs[2], 19, 0); |
| 495 | // inc_src = BIT( regs[0], 29); |
| 496 | // inc_dst = BIT( regs[1], 29); |
| 497 | // tsz = BIT( regs[2], 27); |
| 498 | // _int = BIT( regs[2], 28); |
| 499 | // servmode = BIT( regs[2], 26); |
| 500 | // hwsrcsel = BITS( regs[2], 25, 24); |
| 501 | // swhw_sel = BIT( regs[2], 23); |
| 502 | // reload = BIT( regs[2], 22); |
| 503 | // dsz = BITS( regs[2], 21, 20); |
| 504 | // logerror( "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d int %d tsz %d servmode %d hwsrcsel %d swhw_sel %d reload %d dsz %d tc %d\n", dma, addr_src, inc_src, addr_dst, inc_dst, _int, tsz, servmode, hwsrcsel, swhw_sel, reload, dsz, tc); |
| 505 | // logerror( "DMA %d - copy %08X bytes from %08X (%s) to %08X (%s)\n", dma, tc << dsz, addr_src, inc_src ? "fix" : "inc", addr_dst, inc_dst ? "fix" : "inc"); |
| 506 | regs[3] = (regs[3] & ~0x000FFFFF) | tc; |
| 507 | regs[4] = (regs[4] & ~0x1FFFFFFF) | addr_src; |
| 508 | regs[5] = (regs[5] & ~0x1FFFFFFF) | addr_dst; |
| 509 | } |
| 510 | |
| 511 | static void s3c240x_dma_stop( running_machine *machine, int dma) |
| 512 | { |
| 513 | // logerror( "DMA %d stop\n", dma); |
| 514 | } |
| 515 | |
| 516 | static void s3c240x_dma_recalc( running_machine *machine, int dma) |
| 517 | { |
| 518 | if (s3c240x_dma_regs[(dma<<3)+6] & 2) |
| 519 | { |
| 520 | s3c240x_dma_start( machine, dma); |
| 521 | } |
| 522 | else |
| 523 | { |
| 524 | s3c240x_dma_stop( machine, dma); |
| 525 | } |
| 526 | } |
| 527 | |
| 450 | 528 | static READ32_HANDLER( s3c240x_dma_r ) |
| 451 | 529 | { |
| 452 | 530 | UINT32 data = s3c240x_dma_regs[offset]; |
| r6588 | r6589 | |
| 456 | 534 | |
| 457 | 535 | static WRITE32_HANDLER( s3c240x_dma_w ) |
| 458 | 536 | { |
| 537 | UINT32 old_value = s3c240x_dma_regs[offset]; |
| 459 | 538 | // logerror( "(DMA) %08X <- %08X (PC %08X)\n", 0x14600000 + (offset << 2), data, cpu_get_pc( space->cpu)); |
| 460 | 539 | COMBINE_DATA(&s3c240x_dma_regs[offset]); |
| 461 | 540 | switch (offset) |
| 462 | 541 | { |
| 542 | // DCON0 |
| 543 | case 0x08 / 4 : |
| 544 | { |
| 545 | if (((data >> 22) & 1) != 0) // reload |
| 546 | { |
| 547 | s3c240x_dma_regs[0x18/4] &= ~(1 << 1); // clear on/off |
| 548 | } |
| 549 | } |
| 550 | break; |
| 463 | 551 | // DMASKTRIG0 |
| 464 | 552 | case 0x18 / 4 : |
| 465 | 553 | { |
| 466 | | if (data & 2) s3c240x_dma_start( space->machine, 0); |
| 554 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( space->machine, 0); |
| 467 | 555 | } |
| 468 | 556 | break; |
| 557 | // DCON1 |
| 558 | case 0x28 / 4 : |
| 559 | { |
| 560 | if (((data >> 22) & 1) != 0) // reload |
| 561 | { |
| 562 | s3c240x_dma_regs[0x38/4] &= ~(1 << 1); // clear on/off |
| 563 | } |
| 564 | } |
| 565 | break; |
| 469 | 566 | // DMASKTRIG1 |
| 470 | 567 | case 0x38 / 4 : |
| 471 | 568 | { |
| 472 | | if (data & 2) s3c240x_dma_start( space->machine, 1); |
| 569 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( space->machine, 1); |
| 473 | 570 | } |
| 474 | 571 | break; |
| 572 | // DCON2 |
| 573 | case 0x48 / 4 : |
| 574 | { |
| 575 | if (((data >> 22) & 1) != 0) // reload |
| 576 | { |
| 577 | s3c240x_dma_regs[0x58/4] &= ~(1 << 1); // clear on/off |
| 578 | } |
| 579 | } |
| 580 | break; |
| 475 | 581 | // DMASKTRIG2 |
| 476 | 582 | case 0x58 / 4 : |
| 477 | 583 | { |
| 478 | | if (data & 2) s3c240x_dma_start( space->machine, 2); |
| 584 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( space->machine, 2); |
| 479 | 585 | } |
| 480 | 586 | break; |
| 587 | // DCON3 |
| 588 | case 0x68 / 4 : |
| 589 | { |
| 590 | if (((data >> 22) & 1) != 0) // reload |
| 591 | { |
| 592 | s3c240x_dma_regs[0x78/4] &= ~(1 << 1); // clear on/off |
| 593 | } |
| 594 | } |
| 595 | break; |
| 481 | 596 | // DMASKTRIG3 |
| 482 | 597 | case 0x78 / 4 : |
| 483 | 598 | { |
| 484 | | if (data & 2) s3c240x_dma_start( space->machine, 3); |
| 599 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( space->machine, 3); |
| 485 | 600 | } |
| 486 | 601 | break; |
| 487 | 602 | } |
| 488 | 603 | } |
| 489 | 604 | |
| 605 | static TIMER_CALLBACK( s3c240x_dma_timer_exp ) |
| 606 | { |
| 607 | // int ch = param; |
| 608 | // logerror( "DMA %d timer callback\n", ch); |
| 609 | } |
| 610 | |
| 490 | 611 | // SMARTMEDIA |
| 491 | 612 | |
| 492 | 613 | static struct { |
| r6588 | r6589 | |
| 736 | 857 | i2s_write( space->machine, I2S_L3C, (data & 0x00000200) ? 1 : 0); |
| 737 | 858 | } |
| 738 | 859 | break; |
| 860 | /* |
| 861 | // PGDAT |
| 862 | case 0x48 / 4 : |
| 863 | { |
| 864 | int i2ssdo; |
| 865 | i2ssdo = BIT( data, 3); |
| 866 | } |
| 867 | break; |
| 868 | */ |
| 739 | 869 | } |
| 740 | 870 | } |
| 741 | 871 | |
| r6588 | r6589 | |
| 1048 | 1178 | |
| 1049 | 1179 | static emu_timer *s3c240x_iis_timer; |
| 1050 | 1180 | static UINT32 s3c240x_iis_regs[0x14/4]; |
| 1051 | | static INT16 s3c240x_iis_fifo[16/2]; |
| 1052 | | static INT16 s3c240x_iis_fifo_index = 0; |
| 1181 | static UINT16 s3c240x_iis_fifo[16/2]; |
| 1182 | static int s3c240x_iis_fifo_index = 0; |
| 1053 | 1183 | |
| 1054 | 1184 | static void s3c240x_iis_start( running_machine *machine) |
| 1055 | 1185 | { |
| 1056 | 1186 | const UINT32 codeclk_table[] = { 256, 384}; |
| 1057 | | const device_config *dmadac[2]; |
| 1058 | 1187 | double freq; |
| 1059 | 1188 | int prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk; |
| 1060 | 1189 | // logerror( "IIS start\n"); |
| r6588 | r6589 | |
| 1064 | 1193 | codeclk = BIT( s3c240x_iis_regs[1], 2); |
| 1065 | 1194 | freq = (double)(s3c240x_get_pclk( MPLLCON) / (prescaler_control_a + 1) / codeclk_table[codeclk]) * 2; // why do I have to multiply by two? |
| 1066 | 1195 | // logerror( "IIS - pclk %d psc_enable %d psc_a %d psc_b %d codeclk %d freq %f\n", s3c240x_get_pclk( MPLLCON), prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk_table[codeclk], freq); |
| 1067 | | dmadac[0] = devtag_get_device( machine, "dac1"); |
| 1068 | | dmadac[1] = devtag_get_device( machine, "dac2"); |
| 1069 | | dmadac_set_frequency( &dmadac[0], 2, freq); |
| 1070 | | dmadac_enable( &dmadac[0], 2, 1); |
| 1071 | 1196 | timer_adjust_periodic( s3c240x_iis_timer, ATTOTIME_IN_HZ( freq), 0, ATTOTIME_IN_HZ( freq)); |
| 1072 | 1197 | } |
| 1073 | 1198 | |
| 1074 | 1199 | static void s3c240x_iis_stop( running_machine *machine) |
| 1075 | 1200 | { |
| 1076 | | const device_config *dmadac[2]; |
| 1077 | 1201 | // logerror( "IIS stop\n"); |
| 1078 | 1202 | timer_adjust_oneshot( s3c240x_iis_timer, attotime_never, 0); |
| 1079 | | dmadac[0] = devtag_get_device( machine, "dac1"); |
| 1080 | | dmadac[1] = devtag_get_device( machine, "dac2"); |
| 1081 | | dmadac_enable( &dmadac[0], 2, 0); |
| 1082 | 1203 | } |
| 1083 | 1204 | |
| 1084 | 1205 | static void s3c240x_iis_recalc( running_machine *machine) |
| r6588 | r6589 | |
| 1126 | 1247 | } |
| 1127 | 1248 | if (s3c240x_iis_fifo_index == 2) |
| 1128 | 1249 | { |
| 1129 | | const device_config *dmadac[2]; |
| 1130 | | dmadac[0] = devtag_get_device( space->machine, "dac1"); |
| 1131 | | dmadac[1] = devtag_get_device( space->machine, "dac2"); |
| 1250 | const device_config *dac[2]; |
| 1251 | dac[0] = devtag_get_device( space->machine, "dac1"); |
| 1252 | dac[1] = devtag_get_device( space->machine, "dac2"); |
| 1132 | 1253 | s3c240x_iis_fifo_index = 0; |
| 1133 | | dmadac_transfer( &dmadac[0], 2, 1, 1, 1, s3c240x_iis_fifo); |
| 1254 | dac_signed_data_16_w( dac[0], s3c240x_iis_fifo[0] + 0x8000); |
| 1255 | dac_signed_data_16_w( dac[1], s3c240x_iis_fifo[1] + 0x8000); |
| 1134 | 1256 | } |
| 1135 | 1257 | } |
| 1136 | 1258 | break; |
| r6588 | r6589 | |
| 1139 | 1261 | |
| 1140 | 1262 | static TIMER_CALLBACK( s3c240x_iis_timer_exp ) |
| 1141 | 1263 | { |
| 1264 | UINT32 dcon; |
| 1265 | int hwsrcsel, swhwsel; |
| 1142 | 1266 | // logerror( "IIS timer callback\n"); |
| 1267 | dcon = s3c240x_dma_regs[0x48/4]; |
| 1268 | hwsrcsel = BITS( dcon, 25, 24); |
| 1269 | swhwsel = BIT( dcon, 23); |
| 1270 | if ((swhwsel == 1) && (hwsrcsel == 0)) |
| 1271 | { |
| 1272 | UINT32 dmasktrig; |
| 1273 | int on_off; |
| 1274 | dmasktrig = s3c240x_dma_regs[0x58/4]; |
| 1275 | on_off = BIT( dmasktrig, 1); |
| 1276 | if (on_off) |
| 1277 | { |
| 1278 | s3c240x_dma_trigger( machine, 2); |
| 1279 | } |
| 1280 | } |
| 1143 | 1281 | } |
| 1144 | 1282 | |
| 1145 | 1283 | // RTC |
| r6588 | r6589 | |
| 1210 | 1348 | s3c240x_pwm_timer[2] = timer_alloc(machine, s3c240x_pwm_timer_exp, (void *)(FPTR)2); |
| 1211 | 1349 | s3c240x_pwm_timer[3] = timer_alloc(machine, s3c240x_pwm_timer_exp, (void *)(FPTR)3); |
| 1212 | 1350 | s3c240x_pwm_timer[4] = timer_alloc(machine, s3c240x_pwm_timer_exp, (void *)(FPTR)4); |
| 1351 | s3c240x_dma_timer[0] = timer_alloc( machine, s3c240x_dma_timer_exp, (void *)(FPTR)0); |
| 1352 | s3c240x_dma_timer[1] = timer_alloc( machine, s3c240x_dma_timer_exp, (void *)(FPTR)1); |
| 1353 | s3c240x_dma_timer[2] = timer_alloc( machine, s3c240x_dma_timer_exp, (void *)(FPTR)2); |
| 1354 | s3c240x_dma_timer[3] = timer_alloc( machine, s3c240x_dma_timer_exp, (void *)(FPTR)3); |
| 1213 | 1355 | s3c240x_iic_timer = timer_alloc(machine, s3c240x_iic_timer_exp, (void *)(FPTR)0); |
| 1214 | 1356 | s3c240x_iis_timer = timer_alloc(machine, s3c240x_iis_timer_exp, (void *)(FPTR)0); |
| 1215 | 1357 | eeprom_data = auto_alloc_array( machine, UINT8, 0x2000); |
| r6588 | r6589 | |
| 1315 | 1457 | MDRV_MACHINE_RESET(gp32) |
| 1316 | 1458 | |
| 1317 | 1459 | MDRV_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 1318 | | MDRV_SOUND_ADD("dac1", DMADAC, 0) |
| 1460 | MDRV_SOUND_ADD("dac1", DAC, 0) |
| 1319 | 1461 | MDRV_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.0) |
| 1320 | | MDRV_SOUND_ADD("dac2", DMADAC, 0) |
| 1462 | MDRV_SOUND_ADD("dac2", DAC, 0) |
| 1321 | 1463 | MDRV_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.0) |
| 1322 | 1464 | |
| 1323 | 1465 | MDRV_NVRAM_HANDLER(gp32) |