trunk/src/mess/drivers/gp32.c
| r20915 | r20916 | |
| 47 | 47 | #define BITS(x,m,n) (((x)>>(n))&((1<<((m)-(n)+1))-1)) |
| 48 | 48 | |
| 49 | 49 | |
| 50 | | static UINT32 s3c240x_get_fclk(gp32_state *state, int reg); |
| 51 | | static UINT32 s3c240x_get_hclk(gp32_state *state, int reg); |
| 52 | | static UINT32 s3c240x_get_pclk(gp32_state *state, int reg); |
| 53 | | |
| 54 | | static void s3c240x_dma_request_iis( running_machine &machine); |
| 55 | | static void s3c240x_dma_request_pwm( running_machine &machine); |
| 56 | | |
| 57 | 50 | // LCD CONTROLLER |
| 58 | 51 | |
| 59 | 52 | |
| r20915 | r20916 | |
| 73 | 66 | return MAKE_RGB( r | i, g | i, b | i); |
| 74 | 67 | } |
| 75 | 68 | |
| 76 | | static void s3c240x_lcd_dma_reload( running_machine &machine) |
| 69 | void gp32_state::s3c240x_lcd_dma_reload() |
| 77 | 70 | { |
| 78 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 79 | | state->m_s3c240x_lcd.vramaddr_cur = state->m_s3c240x_lcd_regs[5] << 1; |
| 80 | | state->m_s3c240x_lcd.vramaddr_max = ((state->m_s3c240x_lcd_regs[5] & 0xFFE00000) | state->m_s3c240x_lcd_regs[6]) << 1; |
| 81 | | state->m_s3c240x_lcd.offsize = BITS( state->m_s3c240x_lcd_regs[7], 21, 11); |
| 82 | | state->m_s3c240x_lcd.pagewidth_cur = 0; |
| 83 | | state->m_s3c240x_lcd.pagewidth_max = BITS( state->m_s3c240x_lcd_regs[7], 10, 0); |
| 84 | | verboselog( machine, 3, "LCD - vramaddr %08X %08X offsize %08X pagewidth %08X\n", state->m_s3c240x_lcd.vramaddr_cur, state->m_s3c240x_lcd.vramaddr_max, state->m_s3c240x_lcd.offsize, state->m_s3c240x_lcd.pagewidth_max); |
| 71 | m_s3c240x_lcd.vramaddr_cur = m_s3c240x_lcd_regs[5] << 1; |
| 72 | m_s3c240x_lcd.vramaddr_max = ((m_s3c240x_lcd_regs[5] & 0xFFE00000) | m_s3c240x_lcd_regs[6]) << 1; |
| 73 | m_s3c240x_lcd.offsize = BITS( m_s3c240x_lcd_regs[7], 21, 11); |
| 74 | m_s3c240x_lcd.pagewidth_cur = 0; |
| 75 | m_s3c240x_lcd.pagewidth_max = BITS( m_s3c240x_lcd_regs[7], 10, 0); |
| 76 | verboselog( machine(), 3, "LCD - vramaddr %08X %08X offsize %08X pagewidth %08X\n", m_s3c240x_lcd.vramaddr_cur, m_s3c240x_lcd.vramaddr_max, m_s3c240x_lcd.offsize, m_s3c240x_lcd.pagewidth_max); |
| 85 | 77 | } |
| 86 | 78 | |
| 87 | | static void s3c240x_lcd_dma_init( running_machine &machine) |
| 79 | void gp32_state::s3c240x_lcd_dma_init() |
| 88 | 80 | { |
| 89 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 90 | | s3c240x_lcd_dma_reload( machine); |
| 91 | | state->m_s3c240x_lcd.bppmode = BITS( state->m_s3c240x_lcd_regs[0], 4, 1); |
| 92 | | state->m_s3c240x_lcd.bswp = BIT( state->m_s3c240x_lcd_regs[4], 1); |
| 93 | | state->m_s3c240x_lcd.hwswp = BIT( state->m_s3c240x_lcd_regs[4], 0); |
| 94 | | state->m_s3c240x_lcd.lineval = BITS( state->m_s3c240x_lcd_regs[1], 23, 14); |
| 95 | | state->m_s3c240x_lcd.hozval = BITS( state->m_s3c240x_lcd_regs[2], 18, 8); |
| 81 | s3c240x_lcd_dma_reload(); |
| 82 | m_s3c240x_lcd.bppmode = BITS( m_s3c240x_lcd_regs[0], 4, 1); |
| 83 | m_s3c240x_lcd.bswp = BIT( m_s3c240x_lcd_regs[4], 1); |
| 84 | m_s3c240x_lcd.hwswp = BIT( m_s3c240x_lcd_regs[4], 0); |
| 85 | m_s3c240x_lcd.lineval = BITS( m_s3c240x_lcd_regs[1], 23, 14); |
| 86 | m_s3c240x_lcd.hozval = BITS( m_s3c240x_lcd_regs[2], 18, 8); |
| 96 | 87 | } |
| 97 | 88 | |
| 98 | 89 | static UINT32 s3c240x_lcd_dma_read( running_machine &machine) |
| r20915 | r20916 | |
| 266 | 257 | verboselog( machine(), 3, "LCD - vpos %d hpos %d\n", m_s3c240x_lcd.vpos, m_s3c240x_lcd.hpos); |
| 267 | 258 | if (m_s3c240x_lcd.vramaddr_cur >= m_s3c240x_lcd.vramaddr_max) |
| 268 | 259 | { |
| 269 | | s3c240x_lcd_dma_reload( machine()); |
| 260 | s3c240x_lcd_dma_reload(); |
| 270 | 261 | } |
| 271 | 262 | verboselog( machine(), 3, "LCD - vramaddr %08X\n", m_s3c240x_lcd.vramaddr_cur); |
| 272 | 263 | while (m_s3c240x_lcd.vramaddr_cur < m_s3c240x_lcd.vramaddr_max) |
| r20915 | r20916 | |
| 293 | 284 | UINT32 gp32_state::screen_update_gp32(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 294 | 285 | { |
| 295 | 286 | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
| 296 | | s3c240x_lcd_dma_init( machine()); |
| 287 | s3c240x_lcd_dma_init(); |
| 297 | 288 | return 0; |
| 298 | 289 | } |
| 299 | 290 | |
| r20915 | r20916 | |
| 315 | 306 | return data; |
| 316 | 307 | } |
| 317 | 308 | |
| 318 | | static void s3c240x_lcd_configure( running_machine &machine) |
| 309 | void gp32_state::s3c240x_lcd_configure() |
| 319 | 310 | { |
| 320 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 321 | | screen_device *screen = machine.primary_screen; |
| 311 | screen_device *screen = machine().primary_screen; |
| 322 | 312 | UINT32 vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk; |
| 323 | 313 | double framerate, vclk; |
| 324 | 314 | rectangle visarea; |
| 325 | | vspw = BITS( state->m_s3c240x_lcd_regs[1], 5, 0); |
| 326 | | vbpd = BITS( state->m_s3c240x_lcd_regs[1], 31, 24); |
| 327 | | lineval = BITS( state->m_s3c240x_lcd_regs[1], 23, 14); |
| 328 | | vfpd = BITS( state->m_s3c240x_lcd_regs[1], 13, 6); |
| 329 | | hspw = BITS( state->m_s3c240x_lcd_regs[3], 7, 0); |
| 330 | | hbpd = BITS( state->m_s3c240x_lcd_regs[2], 25, 19); |
| 331 | | hfpd = BITS( state->m_s3c240x_lcd_regs[2], 7, 0); |
| 332 | | hozval = BITS( state->m_s3c240x_lcd_regs[2], 18, 8); |
| 333 | | clkval = BITS( state->m_s3c240x_lcd_regs[0], 17, 8); |
| 334 | | hclk = s3c240x_get_hclk(state, MPLLCON); |
| 335 | | verboselog( machine, 3, "LCD - vspw %d vbpd %d lineval %d vfpd %d hspw %d hbpd %d hfpd %d hozval %d clkval %d hclk %d\n", vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk); |
| 315 | vspw = BITS( m_s3c240x_lcd_regs[1], 5, 0); |
| 316 | vbpd = BITS( m_s3c240x_lcd_regs[1], 31, 24); |
| 317 | lineval = BITS( m_s3c240x_lcd_regs[1], 23, 14); |
| 318 | vfpd = BITS( m_s3c240x_lcd_regs[1], 13, 6); |
| 319 | hspw = BITS( m_s3c240x_lcd_regs[3], 7, 0); |
| 320 | hbpd = BITS( m_s3c240x_lcd_regs[2], 25, 19); |
| 321 | hfpd = BITS( m_s3c240x_lcd_regs[2], 7, 0); |
| 322 | hozval = BITS( m_s3c240x_lcd_regs[2], 18, 8); |
| 323 | clkval = BITS( m_s3c240x_lcd_regs[0], 17, 8); |
| 324 | hclk = s3c240x_get_hclk(MPLLCON); |
| 325 | verboselog( machine(), 3, "LCD - vspw %d vbpd %d lineval %d vfpd %d hspw %d hbpd %d hfpd %d hozval %d clkval %d hclk %d\n", vspw, vbpd, lineval, vfpd, hspw, hbpd, hfpd, hozval, clkval, hclk); |
| 336 | 326 | vclk = (double)(hclk / ((clkval + 1) * 2)); |
| 337 | | verboselog( machine, 3, "LCD - vclk %f\n", vclk); |
| 327 | verboselog( machine(), 3, "LCD - vclk %f\n", vclk); |
| 338 | 328 | framerate = vclk / (((vspw + 1) + (vbpd + 1) + (lineval + 1) + (vfpd + 1)) * ((hspw + 1) + (hbpd + 1) + (hfpd + 1) + (hozval + 1))); |
| 339 | | verboselog( machine, 3, "LCD - framerate %f\n", framerate); |
| 329 | verboselog( machine(), 3, "LCD - framerate %f\n", framerate); |
| 340 | 330 | visarea.set(0, hozval, 0, lineval); |
| 341 | | verboselog( machine, 3, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y); |
| 331 | verboselog( machine(), 3, "LCD - visarea min_x %d min_y %d max_x %d max_y %d\n", visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y); |
| 342 | 332 | screen->configure(hozval + 1, lineval + 1, visarea, HZ_TO_ATTOSECONDS( framerate)); |
| 343 | 333 | } |
| 344 | 334 | |
| 345 | | static void s3c240x_lcd_start( running_machine &machine) |
| 335 | void gp32_state::s3c240x_lcd_start() |
| 346 | 336 | { |
| 347 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 348 | | screen_device *screen = machine.primary_screen; |
| 349 | | verboselog( machine, 1, "LCD start\n"); |
| 350 | | s3c240x_lcd_configure( machine); |
| 351 | | s3c240x_lcd_dma_init( machine); |
| 352 | | state->m_s3c240x_lcd_timer->adjust( screen->time_until_pos(0, 0)); |
| 337 | screen_device *screen = machine().primary_screen; |
| 338 | verboselog( machine(), 1, "LCD start\n"); |
| 339 | s3c240x_lcd_configure(); |
| 340 | s3c240x_lcd_dma_init(); |
| 341 | m_s3c240x_lcd_timer->adjust( screen->time_until_pos(0, 0)); |
| 353 | 342 | } |
| 354 | 343 | |
| 355 | | static void s3c240x_lcd_stop( running_machine &machine) |
| 344 | void gp32_state::s3c240x_lcd_stop() |
| 356 | 345 | { |
| 357 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 358 | | verboselog( machine, 1, "LCD stop\n"); |
| 359 | | state->m_s3c240x_lcd_timer->adjust( attotime::never); |
| 346 | verboselog( machine(), 1, "LCD stop\n"); |
| 347 | m_s3c240x_lcd_timer->adjust( attotime::never); |
| 360 | 348 | } |
| 361 | 349 | |
| 362 | | static void s3c240x_lcd_recalc( running_machine &machine) |
| 350 | void gp32_state::s3c240x_lcd_recalc() |
| 363 | 351 | { |
| 364 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 365 | | if (state->m_s3c240x_lcd_regs[0] & 1) |
| 352 | if (m_s3c240x_lcd_regs[0] & 1) |
| 366 | 353 | { |
| 367 | | s3c240x_lcd_start( machine); |
| 354 | s3c240x_lcd_start(); |
| 368 | 355 | } |
| 369 | 356 | else |
| 370 | 357 | { |
| 371 | | s3c240x_lcd_stop( machine); |
| 358 | s3c240x_lcd_stop(); |
| 372 | 359 | } |
| 373 | 360 | } |
| 374 | 361 | |
| r20915 | r20916 | |
| 384 | 371 | { |
| 385 | 372 | if ((old_value & 1) != (data & 1)) |
| 386 | 373 | { |
| 387 | | s3c240x_lcd_recalc( machine()); |
| 374 | s3c240x_lcd_recalc(); |
| 388 | 375 | } |
| 389 | 376 | } |
| 390 | 377 | break; |
| r20915 | r20916 | |
| 415 | 402 | // CLOCK & POWER MANAGEMENT |
| 416 | 403 | |
| 417 | 404 | |
| 418 | | static UINT32 s3c240x_get_fclk(gp32_state *state, int reg) |
| 405 | UINT32 gp32_state::s3c240x_get_fclk(int reg) |
| 419 | 406 | { |
| 420 | 407 | UINT32 data, mdiv, pdiv, sdiv; |
| 421 | | data = state->m_s3c240x_clkpow_regs[reg]; // MPLLCON or UPLLCON |
| 408 | data = m_s3c240x_clkpow_regs[reg]; // MPLLCON or UPLLCON |
| 422 | 409 | mdiv = BITS( data, 19, 12); |
| 423 | 410 | pdiv = BITS( data, 9, 4); |
| 424 | 411 | sdiv = BITS( data, 1, 0); |
| 425 | 412 | return (UINT32)((double)((mdiv + 8) * 12000000) / (double)((pdiv + 2) * (1 << sdiv))); |
| 426 | 413 | } |
| 427 | 414 | |
| 428 | | static UINT32 s3c240x_get_hclk(gp32_state *state, int reg) |
| 415 | UINT32 gp32_state::s3c240x_get_hclk(int reg) |
| 429 | 416 | { |
| 430 | | switch (state->m_s3c240x_clkpow_regs[5] & 0x3) // CLKDIVN |
| 417 | switch (m_s3c240x_clkpow_regs[5] & 0x3) // CLKDIVN |
| 431 | 418 | { |
| 432 | | case 0 : return s3c240x_get_fclk(state, reg) / 1; |
| 433 | | case 1 : return s3c240x_get_fclk(state, reg) / 1; |
| 434 | | case 2 : return s3c240x_get_fclk(state, reg) / 2; |
| 435 | | case 3 : return s3c240x_get_fclk(state, reg) / 2; |
| 419 | case 0 : return s3c240x_get_fclk(reg) / 1; |
| 420 | case 1 : return s3c240x_get_fclk(reg) / 1; |
| 421 | case 2 : return s3c240x_get_fclk(reg) / 2; |
| 422 | case 3 : return s3c240x_get_fclk(reg) / 2; |
| 436 | 423 | } |
| 437 | 424 | return 0; |
| 438 | 425 | } |
| 439 | 426 | |
| 440 | | static UINT32 s3c240x_get_pclk(gp32_state *state, int reg) |
| 427 | UINT32 gp32_state::s3c240x_get_pclk(int reg) |
| 441 | 428 | { |
| 442 | | switch (state->m_s3c240x_clkpow_regs[5] & 0x3) // CLKDIVN |
| 429 | switch (m_s3c240x_clkpow_regs[5] & 0x3) // CLKDIVN |
| 443 | 430 | { |
| 444 | | case 0 : return s3c240x_get_fclk(state, reg) / 1; |
| 445 | | case 1 : return s3c240x_get_fclk(state, reg) / 2; |
| 446 | | case 2 : return s3c240x_get_fclk(state, reg) / 2; |
| 447 | | case 3 : return s3c240x_get_fclk(state, reg) / 4; |
| 431 | case 0 : return s3c240x_get_fclk(reg) / 1; |
| 432 | case 1 : return s3c240x_get_fclk(reg) / 2; |
| 433 | case 2 : return s3c240x_get_fclk(reg) / 2; |
| 434 | case 3 : return s3c240x_get_fclk(reg) / 4; |
| 448 | 435 | } |
| 449 | 436 | return 0; |
| 450 | 437 | } |
| r20915 | r20916 | |
| 465 | 452 | // MPLLCON |
| 466 | 453 | case 0x04 / 4 : |
| 467 | 454 | { |
| 468 | | gp32_state *state = machine().driver_data<gp32_state>(); |
| 469 | | machine().device("maincpu")->set_unscaled_clock(s3c240x_get_fclk(state, MPLLCON) * CLOCK_MULTIPLIER); |
| 455 | m_maincpu->set_unscaled_clock(s3c240x_get_fclk(MPLLCON) * CLOCK_MULTIPLIER); |
| 470 | 456 | } |
| 471 | 457 | break; |
| 472 | 458 | } |
| r20915 | r20916 | |
| 475 | 461 | // INTERRUPT CONTROLLER |
| 476 | 462 | |
| 477 | 463 | |
| 478 | | static void s3c240x_check_pending_irq( running_machine &machine) |
| 464 | void gp32_state::s3c240x_check_pending_irq() |
| 479 | 465 | { |
| 480 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 481 | | if (state->m_s3c240x_irq_regs[0] != 0) |
| 466 | if (m_s3c240x_irq_regs[0] != 0) |
| 482 | 467 | { |
| 483 | 468 | UINT32 int_type = 0, temp; |
| 484 | | temp = state->m_s3c240x_irq_regs[0]; |
| 469 | temp = m_s3c240x_irq_regs[0]; |
| 485 | 470 | while (!(temp & 1)) |
| 486 | 471 | { |
| 487 | 472 | int_type++; |
| 488 | 473 | temp = temp >> 1; |
| 489 | 474 | } |
| 490 | | state->m_s3c240x_irq_regs[4] |= (1 << int_type); // INTPND |
| 491 | | state->m_s3c240x_irq_regs[5] = int_type; // INTOFFSET |
| 492 | | machine.device( "maincpu")->execute().set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); |
| 475 | m_s3c240x_irq_regs[4] |= (1 << int_type); // INTPND |
| 476 | m_s3c240x_irq_regs[5] = int_type; // INTOFFSET |
| 477 | m_maincpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); |
| 493 | 478 | } |
| 494 | 479 | else |
| 495 | 480 | { |
| 496 | | machine.device( "maincpu")->execute().set_input_line(ARM7_IRQ_LINE, CLEAR_LINE); |
| 481 | m_maincpu->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE); |
| 497 | 482 | } |
| 498 | 483 | } |
| 499 | 484 | |
| 500 | | static void s3c240x_request_irq( running_machine &machine, UINT32 int_type) |
| 485 | void gp32_state::s3c240x_request_irq(UINT32 int_type) |
| 501 | 486 | { |
| 502 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 503 | | verboselog( machine, 5, "request irq %d\n", int_type); |
| 504 | | if (state->m_s3c240x_irq_regs[0] == 0) |
| 487 | verboselog( machine(), 5, "request irq %d\n", int_type); |
| 488 | if (m_s3c240x_irq_regs[0] == 0) |
| 505 | 489 | { |
| 506 | | state->m_s3c240x_irq_regs[0] |= (1 << int_type); // SRCPND |
| 507 | | state->m_s3c240x_irq_regs[4] |= (1 << int_type); // INTPND |
| 508 | | state->m_s3c240x_irq_regs[5] = int_type; // INTOFFSET |
| 509 | | machine.device( "maincpu")->execute().set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); |
| 490 | m_s3c240x_irq_regs[0] |= (1 << int_type); // SRCPND |
| 491 | m_s3c240x_irq_regs[4] |= (1 << int_type); // INTPND |
| 492 | m_s3c240x_irq_regs[5] = int_type; // INTOFFSET |
| 493 | m_maincpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); |
| 510 | 494 | } |
| 511 | 495 | else |
| 512 | 496 | { |
| 513 | | state->m_s3c240x_irq_regs[0] |= (1 << int_type); // SRCPND |
| 514 | | s3c240x_check_pending_irq( machine); |
| 497 | m_s3c240x_irq_regs[0] |= (1 << int_type); // SRCPND |
| 498 | s3c240x_check_pending_irq(); |
| 515 | 499 | } |
| 516 | 500 | } |
| 517 | 501 | |
| r20915 | r20916 | |
| 534 | 518 | case 0x00 / 4 : |
| 535 | 519 | { |
| 536 | 520 | m_s3c240x_irq_regs[0] = (old_value & ~data); // clear only the bit positions of SRCPND corresponding to those set to one in the data |
| 537 | | s3c240x_check_pending_irq( machine()); |
| 521 | s3c240x_check_pending_irq(); |
| 538 | 522 | } |
| 539 | 523 | break; |
| 540 | 524 | // INTPND |
| r20915 | r20916 | |
| 580 | 564 | return data; |
| 581 | 565 | } |
| 582 | 566 | |
| 583 | | static void s3c240x_pwm_start( running_machine &machine, int timer) |
| 567 | void gp32_state::s3c240x_pwm_start(int timer) |
| 584 | 568 | { |
| 585 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 586 | 569 | static const int mux_table[] = { 2, 4, 8, 16 }; |
| 587 | 570 | static const int prescaler_shift[] = { 0, 0, 8, 8, 8 }; |
| 588 | 571 | static const int mux_shift[] = { 0, 4, 8, 12, 16 }; |
| 589 | 572 | static const int tcon_shift[] = { 0, 8, 12, 16, 20 }; |
| 590 | | const UINT32 *regs = &state->m_s3c240x_pwm_regs[3+timer*3]; |
| 573 | const UINT32 *regs = &m_s3c240x_pwm_regs[3+timer*3]; |
| 591 | 574 | UINT32 prescaler, mux, cnt, cmp, auto_reload; |
| 592 | 575 | double freq, hz; |
| 593 | | verboselog( machine, 1, "PWM %d start\n", timer); |
| 594 | | prescaler = (state->m_s3c240x_pwm_regs[0] >> prescaler_shift[timer]) & 0xFF; |
| 595 | | mux = (state->m_s3c240x_pwm_regs[1] >> mux_shift[timer]) & 0x0F; |
| 596 | | freq = s3c240x_get_pclk(state, MPLLCON) / (prescaler + 1) / mux_table[mux]; |
| 576 | verboselog( machine(), 1, "PWM %d start\n", timer); |
| 577 | prescaler = (m_s3c240x_pwm_regs[0] >> prescaler_shift[timer]) & 0xFF; |
| 578 | mux = (m_s3c240x_pwm_regs[1] >> mux_shift[timer]) & 0x0F; |
| 579 | freq = s3c240x_get_pclk(MPLLCON) / (prescaler + 1) / mux_table[mux]; |
| 597 | 580 | cnt = BITS( regs[0], 15, 0); |
| 598 | 581 | if (timer != 4) |
| 599 | 582 | { |
| 600 | 583 | cmp = BITS( regs[1], 15, 0); |
| 601 | | auto_reload = BIT( state->m_s3c240x_pwm_regs[2], tcon_shift[timer] + 3); |
| 584 | auto_reload = BIT( m_s3c240x_pwm_regs[2], tcon_shift[timer] + 3); |
| 602 | 585 | } |
| 603 | 586 | else |
| 604 | 587 | { |
| 605 | 588 | cmp = 0; |
| 606 | | auto_reload = BIT( state->m_s3c240x_pwm_regs[2], tcon_shift[timer] + 2); |
| 589 | auto_reload = BIT( m_s3c240x_pwm_regs[2], tcon_shift[timer] + 2); |
| 607 | 590 | } |
| 608 | 591 | hz = freq / (cnt - cmp + 1); |
| 609 | | verboselog( machine, 5, "PWM %d - FCLK=%d HCLK=%d PCLK=%d prescaler=%d div=%d freq=%f cnt=%d cmp=%d auto_reload=%d hz=%f\n", timer, s3c240x_get_fclk(state, MPLLCON), s3c240x_get_hclk(state, MPLLCON), s3c240x_get_pclk(state, MPLLCON), prescaler, mux_table[mux], freq, cnt, cmp, auto_reload, hz); |
| 592 | verboselog( machine(), 5, "PWM %d - FCLK=%d HCLK=%d PCLK=%d prescaler=%d div=%d freq=%f cnt=%d cmp=%d auto_reload=%d hz=%f\n", timer, s3c240x_get_fclk(MPLLCON), s3c240x_get_hclk(MPLLCON), s3c240x_get_pclk(MPLLCON), prescaler, mux_table[mux], freq, cnt, cmp, auto_reload, hz); |
| 610 | 593 | if (auto_reload) |
| 611 | 594 | { |
| 612 | | state->m_s3c240x_pwm_timer[timer]->adjust( attotime::from_hz( hz), timer, attotime::from_hz( hz)); |
| 595 | m_s3c240x_pwm_timer[timer]->adjust( attotime::from_hz( hz), timer, attotime::from_hz( hz)); |
| 613 | 596 | } |
| 614 | 597 | else |
| 615 | 598 | { |
| 616 | | state->m_s3c240x_pwm_timer[timer]->adjust( attotime::from_hz( hz), timer); |
| 599 | m_s3c240x_pwm_timer[timer]->adjust( attotime::from_hz( hz), timer); |
| 617 | 600 | } |
| 618 | 601 | } |
| 619 | 602 | |
| 620 | | static void s3c240x_pwm_stop( running_machine &machine, int timer) |
| 603 | void gp32_state::s3c240x_pwm_stop(int timer) |
| 621 | 604 | { |
| 622 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 623 | | verboselog( machine, 1, "PWM %d stop\n", timer); |
| 624 | | state->m_s3c240x_pwm_timer[timer]->adjust( attotime::never); |
| 605 | verboselog( machine(), 1, "PWM %d stop\n", timer); |
| 606 | m_s3c240x_pwm_timer[timer]->adjust( attotime::never); |
| 625 | 607 | } |
| 626 | 608 | |
| 627 | | static void s3c240x_pwm_recalc( running_machine &machine, int timer) |
| 609 | void gp32_state::s3c240x_pwm_recalc(int timer) |
| 628 | 610 | { |
| 629 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 630 | 611 | static const int tcon_shift[] = { 0, 8, 12, 16, 20 }; |
| 631 | | if (state->m_s3c240x_pwm_regs[2] & (1 << tcon_shift[timer])) |
| 612 | if (m_s3c240x_pwm_regs[2] & (1 << tcon_shift[timer])) |
| 632 | 613 | { |
| 633 | | s3c240x_pwm_start( machine, timer); |
| 614 | s3c240x_pwm_start(timer); |
| 634 | 615 | } |
| 635 | 616 | else |
| 636 | 617 | { |
| 637 | | s3c240x_pwm_stop( machine, timer); |
| 618 | s3c240x_pwm_stop(timer); |
| 638 | 619 | } |
| 639 | 620 | } |
| 640 | 621 | |
| r20915 | r20916 | |
| 650 | 631 | { |
| 651 | 632 | if ((data & 1) != (old_value & 1)) |
| 652 | 633 | { |
| 653 | | s3c240x_pwm_recalc( machine(), 0); |
| 634 | s3c240x_pwm_recalc(0); |
| 654 | 635 | } |
| 655 | 636 | if ((data & 0x100) != (old_value & 0x100)) |
| 656 | 637 | { |
| 657 | | s3c240x_pwm_recalc( machine(), 1); |
| 638 | s3c240x_pwm_recalc(1); |
| 658 | 639 | } |
| 659 | 640 | if ((data & 0x1000) != (old_value & 0x1000)) |
| 660 | 641 | { |
| 661 | | s3c240x_pwm_recalc( machine(), 2); |
| 642 | s3c240x_pwm_recalc(2); |
| 662 | 643 | } |
| 663 | 644 | if ((data & 0x10000) != (old_value & 0x10000)) |
| 664 | 645 | { |
| 665 | | s3c240x_pwm_recalc( machine(), 3); |
| 646 | s3c240x_pwm_recalc(3); |
| 666 | 647 | } |
| 667 | 648 | if ((data & 0x100000) != (old_value & 0x100000)) |
| 668 | 649 | { |
| 669 | | s3c240x_pwm_recalc( machine(), 4); |
| 650 | s3c240x_pwm_recalc(4); |
| 670 | 651 | } |
| 671 | 652 | } |
| 672 | 653 | } |
| r20915 | r20916 | |
| 679 | 660 | verboselog( machine(), 2, "PWM %d timer callback\n", ch); |
| 680 | 661 | if (BITS( m_s3c240x_pwm_regs[1], 23, 20) == (ch + 1)) |
| 681 | 662 | { |
| 682 | | s3c240x_dma_request_pwm( machine()); |
| 663 | s3c240x_dma_request_pwm(); |
| 683 | 664 | } |
| 684 | 665 | else |
| 685 | 666 | { |
| 686 | | s3c240x_request_irq( machine(), ch_int[ch]); |
| 667 | s3c240x_request_irq(ch_int[ch]); |
| 687 | 668 | } |
| 688 | 669 | } |
| 689 | 670 | |
| 690 | 671 | // DMA |
| 691 | 672 | |
| 692 | 673 | |
| 693 | | static void s3c240x_dma_reload( running_machine &machine, int dma) |
| 674 | void gp32_state::s3c240x_dma_reload(int dma) |
| 694 | 675 | { |
| 695 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 696 | | UINT32 *regs = &state->m_s3c240x_dma_regs[dma<<3]; |
| 676 | UINT32 *regs = &m_s3c240x_dma_regs[dma<<3]; |
| 697 | 677 | regs[3] = (regs[3] & ~0x000FFFFF) | BITS( regs[2], 19, 0); |
| 698 | 678 | regs[4] = (regs[4] & ~0x1FFFFFFF) | BITS( regs[0], 28, 0); |
| 699 | 679 | regs[5] = (regs[5] & ~0x1FFFFFFF) | BITS( regs[1], 28, 0); |
| 700 | 680 | } |
| 701 | 681 | |
| 702 | | static void s3c240x_dma_trigger( running_machine &machine, int dma) |
| 682 | void gp32_state::s3c240x_dma_trigger(int dma) |
| 703 | 683 | { |
| 704 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 705 | | UINT32 *regs = &state->m_s3c240x_dma_regs[dma<<3]; |
| 684 | UINT32 *regs = &m_s3c240x_dma_regs[dma<<3]; |
| 706 | 685 | UINT32 curr_tc, curr_src, curr_dst; |
| 707 | | address_space &space = machine.device( "maincpu")->memory().space( AS_PROGRAM); |
| 686 | address_space &space = m_maincpu->space( AS_PROGRAM); |
| 708 | 687 | int dsz, inc_src, inc_dst, servmode; |
| 709 | 688 | static const UINT32 ch_int[] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3 }; |
| 710 | | verboselog( machine, 5, "DMA %d trigger\n", dma); |
| 689 | verboselog( machine(), 5, "DMA %d trigger\n", dma); |
| 711 | 690 | curr_tc = BITS( regs[3], 19, 0); |
| 712 | 691 | curr_src = BITS( regs[4], 28, 0); |
| 713 | 692 | curr_dst = BITS( regs[5], 28, 0); |
| r20915 | r20916 | |
| 715 | 694 | servmode = BIT( regs[2], 26); |
| 716 | 695 | inc_src = BIT( regs[0], 29); |
| 717 | 696 | inc_dst = BIT( regs[1], 29); |
| 718 | | verboselog( machine, 5, "DMA %d - curr_src %08X curr_dst %08X curr_tc %d dsz %d\n", dma, curr_src, curr_dst, curr_tc, dsz); |
| 697 | verboselog( machine(), 5, "DMA %d - curr_src %08X curr_dst %08X curr_tc %d dsz %d\n", dma, curr_src, curr_dst, curr_tc, dsz); |
| 719 | 698 | while (curr_tc > 0) |
| 720 | 699 | { |
| 721 | 700 | curr_tc--; |
| r20915 | r20916 | |
| 742 | 721 | reload = BIT( regs[2], 22); |
| 743 | 722 | if (!reload) |
| 744 | 723 | { |
| 745 | | s3c240x_dma_reload( machine, dma); |
| 724 | s3c240x_dma_reload(dma); |
| 746 | 725 | } |
| 747 | 726 | else |
| 748 | 727 | { |
| r20915 | r20916 | |
| 751 | 730 | _int = BIT( regs[2], 28); |
| 752 | 731 | if (_int) |
| 753 | 732 | { |
| 754 | | s3c240x_request_irq( machine, ch_int[dma]); |
| 733 | s3c240x_request_irq(ch_int[dma]); |
| 755 | 734 | } |
| 756 | 735 | } |
| 757 | 736 | } |
| 758 | 737 | |
| 759 | | static void s3c240x_dma_request_iis( running_machine &machine) |
| 738 | void gp32_state::s3c240x_dma_request_iis() |
| 760 | 739 | { |
| 761 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 762 | | UINT32 *regs = &state->m_s3c240x_dma_regs[2<<3]; |
| 763 | | verboselog( machine, 5, "s3c240x_dma_request_iis\n"); |
| 740 | UINT32 *regs = &m_s3c240x_dma_regs[2<<3]; |
| 741 | verboselog( machine(), 5, "s3c240x_dma_request_iis\n"); |
| 764 | 742 | if ((BIT( regs[6], 1) != 0) && (BIT( regs[2], 23) != 0) && (BITS( regs[2], 25, 24) == 0)) |
| 765 | 743 | { |
| 766 | | s3c240x_dma_trigger( machine, 2); |
| 744 | s3c240x_dma_trigger(2); |
| 767 | 745 | } |
| 768 | 746 | } |
| 769 | 747 | |
| 770 | | static void s3c240x_dma_request_pwm( running_machine &machine) |
| 748 | void gp32_state::s3c240x_dma_request_pwm() |
| 771 | 749 | { |
| 772 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 773 | 750 | int i; |
| 774 | | verboselog( machine, 5, "s3c240x_dma_request_pwm\n"); |
| 751 | verboselog( machine(), 5, "s3c240x_dma_request_pwm\n"); |
| 775 | 752 | for (i = 0; i < 4; i++) |
| 776 | 753 | { |
| 777 | 754 | if (i != 1) |
| 778 | 755 | { |
| 779 | | UINT32 *regs = &state->m_s3c240x_dma_regs[i<<3]; |
| 756 | UINT32 *regs = &m_s3c240x_dma_regs[i<<3]; |
| 780 | 757 | if ((BIT( regs[6], 1) != 0) && (BIT( regs[2], 23) != 0) && (BITS( regs[2], 25, 24) == 3)) |
| 781 | 758 | { |
| 782 | | s3c240x_dma_trigger( machine, i); |
| 759 | s3c240x_dma_trigger(i); |
| 783 | 760 | } |
| 784 | 761 | } |
| 785 | 762 | } |
| 786 | 763 | } |
| 787 | 764 | |
| 788 | | static void s3c240x_dma_start( running_machine &machine, int dma) |
| 765 | void gp32_state::s3c240x_dma_start(int dma) |
| 789 | 766 | { |
| 790 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 791 | 767 | UINT32 addr_src, addr_dst, tc; |
| 792 | | UINT32 *regs = &state->m_s3c240x_dma_regs[dma<<3]; |
| 768 | UINT32 *regs = &m_s3c240x_dma_regs[dma<<3]; |
| 793 | 769 | UINT32 dsz, tsz, reload; |
| 794 | 770 | int inc_src, inc_dst, _int, servmode, swhwsel, hwsrcsel; |
| 795 | | verboselog( machine, 1, "DMA %d start\n", dma); |
| 771 | verboselog( machine(), 1, "DMA %d start\n", dma); |
| 796 | 772 | addr_src = BITS( regs[0], 28, 0); |
| 797 | 773 | addr_dst = BITS( regs[1], 28, 0); |
| 798 | 774 | tc = BITS( regs[2], 19, 0); |
| r20915 | r20916 | |
| 805 | 781 | swhwsel = BIT( regs[2], 23); |
| 806 | 782 | reload = BIT( regs[2], 22); |
| 807 | 783 | dsz = BITS( regs[2], 21, 20); |
| 808 | | verboselog( machine, 5, "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d int %d tsz %d servmode %d hwsrcsel %d swhwsel %d reload %d dsz %d tc %d\n", dma, addr_src, inc_src, addr_dst, inc_dst, _int, tsz, servmode, hwsrcsel, swhwsel, reload, dsz, tc); |
| 809 | | verboselog( machine, 5, "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"); |
| 810 | | s3c240x_dma_reload( machine, dma); |
| 784 | verboselog( machine(), 5, "DMA %d - addr_src %08X inc_src %d addr_dst %08X inc_dst %d int %d tsz %d servmode %d hwsrcsel %d swhwsel %d reload %d dsz %d tc %d\n", dma, addr_src, inc_src, addr_dst, inc_dst, _int, tsz, servmode, hwsrcsel, swhwsel, reload, dsz, tc); |
| 785 | verboselog( machine(), 5, "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"); |
| 786 | s3c240x_dma_reload(dma); |
| 811 | 787 | if (swhwsel == 0) |
| 812 | 788 | { |
| 813 | | s3c240x_dma_trigger( machine, dma); |
| 789 | s3c240x_dma_trigger(dma); |
| 814 | 790 | } |
| 815 | 791 | } |
| 816 | 792 | |
| 817 | | static void s3c240x_dma_stop( running_machine &machine, int dma) |
| 793 | void gp32_state::s3c240x_dma_stop(int dma) |
| 818 | 794 | { |
| 819 | | verboselog( machine, 1, "DMA %d stop\n", dma); |
| 795 | verboselog( machine(), 1, "DMA %d stop\n", dma); |
| 820 | 796 | } |
| 821 | 797 | |
| 822 | | static void s3c240x_dma_recalc( running_machine &machine, int dma) |
| 798 | void gp32_state::s3c240x_dma_recalc(int dma) |
| 823 | 799 | { |
| 824 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 825 | | if (state->m_s3c240x_dma_regs[(dma<<3)+6] & 2) |
| 800 | if (m_s3c240x_dma_regs[(dma<<3)+6] & 2) |
| 826 | 801 | { |
| 827 | | s3c240x_dma_start( machine, dma); |
| 802 | s3c240x_dma_start(dma); |
| 828 | 803 | } |
| 829 | 804 | else |
| 830 | 805 | { |
| 831 | | s3c240x_dma_stop( machine, dma); |
| 806 | s3c240x_dma_stop(dma); |
| 832 | 807 | } |
| 833 | 808 | } |
| 834 | 809 | |
| r20915 | r20916 | |
| 858 | 833 | // DMASKTRIG0 |
| 859 | 834 | case 0x18 / 4 : |
| 860 | 835 | { |
| 861 | | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( machine(), 0); |
| 836 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc(0); |
| 862 | 837 | } |
| 863 | 838 | break; |
| 864 | 839 | // DCON1 |
| r20915 | r20916 | |
| 873 | 848 | // DMASKTRIG1 |
| 874 | 849 | case 0x38 / 4 : |
| 875 | 850 | { |
| 876 | | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( machine(), 1); |
| 851 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc(1); |
| 877 | 852 | } |
| 878 | 853 | break; |
| 879 | 854 | // DCON2 |
| r20915 | r20916 | |
| 888 | 863 | // DMASKTRIG2 |
| 889 | 864 | case 0x58 / 4 : |
| 890 | 865 | { |
| 891 | | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( machine(), 2); |
| 866 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc(2); |
| 892 | 867 | } |
| 893 | 868 | break; |
| 894 | 869 | // DCON3 |
| r20915 | r20916 | |
| 903 | 878 | // DMASKTRIG3 |
| 904 | 879 | case 0x78 / 4 : |
| 905 | 880 | { |
| 906 | | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc( machine(), 3); |
| 881 | if ((old_value & 2) != (data & 2)) s3c240x_dma_recalc(3); |
| 907 | 882 | } |
| 908 | 883 | break; |
| 909 | 884 | } |
| r20915 | r20916 | |
| 1405 | 1380 | transmit_clock_value = (data >> 0) & 0xF; |
| 1406 | 1381 | tx_clock_source_selection = (data >> 6) & 1; |
| 1407 | 1382 | enable_interrupt = (data >> 5) & 1; |
| 1408 | | clock = (double)(s3c240x_get_pclk(state, MPLLCON) / div_table[tx_clock_source_selection] / (transmit_clock_value + 1)); |
| 1383 | clock = (double)(s3c240x_get_pclk(MPLLCON) / div_table[tx_clock_source_selection] / (transmit_clock_value + 1)); |
| 1409 | 1384 | #endif |
| 1410 | 1385 | interrupt_pending_flag = BIT( data, 4); |
| 1411 | 1386 | if (interrupt_pending_flag == 0) |
| r20915 | r20916 | |
| 1481 | 1456 | enable_interrupt = BIT( m_s3c240x_iic_regs[0], 5); |
| 1482 | 1457 | if (enable_interrupt) |
| 1483 | 1458 | { |
| 1484 | | s3c240x_request_irq( machine(), INT_IIC); |
| 1459 | s3c240x_request_irq(INT_IIC); |
| 1485 | 1460 | } |
| 1486 | 1461 | } |
| 1487 | 1462 | |
| 1488 | 1463 | // IIS |
| 1489 | 1464 | |
| 1490 | | static void s3c240x_iis_start( running_machine &machine) |
| 1465 | void gp32_state::s3c240x_iis_start() |
| 1491 | 1466 | { |
| 1492 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 1493 | 1467 | static const UINT32 codeclk_table[] = { 256, 384 }; |
| 1494 | 1468 | double freq; |
| 1495 | 1469 | int prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk; |
| 1496 | | verboselog( machine, 1, "IIS start\n"); |
| 1497 | | prescaler_enable = BIT( state->m_s3c240x_iis_regs[0], 1); |
| 1498 | | prescaler_control_a = BITS( state->m_s3c240x_iis_regs[2], 9, 5); |
| 1499 | | prescaler_control_b = BITS( state->m_s3c240x_iis_regs[2], 4, 0); |
| 1500 | | codeclk = BIT( state->m_s3c240x_iis_regs[1], 2); |
| 1501 | | freq = (double)(s3c240x_get_pclk(state, MPLLCON) / (prescaler_control_a + 1) / codeclk_table[codeclk]) * 2; // why do I have to multiply by two? |
| 1502 | | verboselog( machine, 5, "IIS - pclk %d psc_enable %d psc_a %d psc_b %d codeclk %d freq %f\n", s3c240x_get_pclk(state, MPLLCON), prescaler_enable, prescaler_control_a, prescaler_control_b, codeclk_table[codeclk], freq); |
| 1503 | | state->m_s3c240x_iis_timer->adjust( attotime::from_hz( freq), 0, attotime::from_hz( freq)); |
| 1470 | verboselog( machine(), 1, "IIS start\n"); |
| 1471 | prescaler_enable = BIT( m_s3c240x_iis_regs[0], 1); |
| 1472 | prescaler_control_a = BITS( m_s3c240x_iis_regs[2], 9, 5); |
| 1473 | prescaler_control_b = BITS( m_s3c240x_iis_regs[2], 4, 0); |
| 1474 | codeclk = BIT( m_s3c240x_iis_regs[1], 2); |
| 1475 | freq = (double)(s3c240x_get_pclk(MPLLCON) / (prescaler_control_a + 1) / codeclk_table[codeclk]) * 2; // why do I have to multiply by two? |
| 1476 | verboselog( machine(), 5, "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); |
| 1477 | m_s3c240x_iis_timer->adjust( attotime::from_hz( freq), 0, attotime::from_hz( freq)); |
| 1504 | 1478 | } |
| 1505 | 1479 | |
| 1506 | | static void s3c240x_iis_stop( running_machine &machine) |
| 1480 | void gp32_state::s3c240x_iis_stop() |
| 1507 | 1481 | { |
| 1508 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 1509 | | verboselog( machine, 1, "IIS stop\n"); |
| 1510 | | state->m_s3c240x_iis_timer->adjust( attotime::never); |
| 1482 | verboselog( machine(), 1, "IIS stop\n"); |
| 1483 | m_s3c240x_iis_timer->adjust( attotime::never); |
| 1511 | 1484 | } |
| 1512 | 1485 | |
| 1513 | | static void s3c240x_iis_recalc( running_machine &machine) |
| 1486 | void gp32_state::s3c240x_iis_recalc() |
| 1514 | 1487 | { |
| 1515 | | gp32_state *state = machine.driver_data<gp32_state>(); |
| 1516 | | if (state->m_s3c240x_iis_regs[0] & 1) |
| 1488 | if (m_s3c240x_iis_regs[0] & 1) |
| 1517 | 1489 | { |
| 1518 | | s3c240x_iis_start( machine); |
| 1490 | s3c240x_iis_start(); |
| 1519 | 1491 | } |
| 1520 | 1492 | else |
| 1521 | 1493 | { |
| 1522 | | s3c240x_iis_stop( machine); |
| 1494 | s3c240x_iis_stop(); |
| 1523 | 1495 | } |
| 1524 | 1496 | } |
| 1525 | 1497 | |
| r20915 | r20916 | |
| 1551 | 1523 | // IISCON |
| 1552 | 1524 | case 0x00 / 4 : |
| 1553 | 1525 | { |
| 1554 | | if ((old_value & 1) != (data & 1)) s3c240x_iis_recalc( machine()); |
| 1526 | if ((old_value & 1) != (data & 1)) s3c240x_iis_recalc(); |
| 1555 | 1527 | } |
| 1556 | 1528 | break; |
| 1557 | 1529 | // IISFIF |
| r20915 | r20916 | |
| 1582 | 1554 | TIMER_CALLBACK_MEMBER(gp32_state::s3c240x_iis_timer_exp) |
| 1583 | 1555 | { |
| 1584 | 1556 | verboselog( machine(), 2, "IIS timer callback\n"); |
| 1585 | | s3c240x_dma_request_iis( machine()); |
| 1557 | s3c240x_dma_request_iis(); |
| 1586 | 1558 | } |
| 1587 | 1559 | |
| 1588 | 1560 | // RTC |