src/emu/machine/68681.c
| r9743 | r9744 | |
| 8 | 8 | #include "emu.h" |
| 9 | 9 | #include "68681.h" |
| 10 | 10 | |
| 11 | | #define VERBOSE 1 |
| 11 | #define VERBOSE |
| 12 | 12 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 13 | 13 | |
| 14 | 14 | static const char *const duart68681_reg_read_names[0x10] = |
| r9743 | r9744 | |
| 242 | 242 | |
| 243 | 243 | duart68681->ISR |= INT_COUNTER_READY; |
| 244 | 244 | duart68681_update_interrupts(duart68681); |
| 245 | |
| 246 | // if ((duart68681->OPCR & 0x0c)== 0x04) { |
| 247 | // duart68681->OPR ^= 0x08; |
| 248 | // if (duart68681->duart_config->output_port_write) |
| 249 | // duart68681->duart_config->output_port_write(duart68681->device, duart68681->OPR ^ 0xff); |
| 250 | // |
| 251 | // } |
| 245 | 252 | }; |
| 246 | 253 | |
| 247 | 254 | static void duart68681_write_MR(duart68681_state *duart68681, int ch, UINT8 data) |
| r9743 | r9744 | |
| 305 | 312 | static void duart68681_write_CR(duart68681_state *duart68681, int ch, UINT8 data) |
| 306 | 313 | { |
| 307 | 314 | duart68681->channel[ch].CR = data; |
| 308 | | if ( BIT(data,0) ) |
| 309 | | { |
| 310 | | duart68681->channel[ch].rx_enabled = 1; |
| 311 | | } |
| 312 | | if ( BIT(data,1) ) |
| 313 | | { |
| 314 | | duart68681->channel[ch].rx_enabled = 0; |
| 315 | | duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY; // datasheet explicitly says disabling rx does not affect the reciever ready line, which just indicates if the fifo has anything in it at all. |
| 316 | | } |
| 317 | 315 | |
| 318 | | if ( BIT(data,2) ) |
| 319 | | { |
| 320 | | duart68681->channel[ch].tx_enabled = 1; |
| 321 | | duart68681->channel[ch].tx_ready = 1; |
| 322 | | duart68681->channel[ch].SR |= STATUS_TRANSMITTER_READY; |
| 323 | | duart68681->channel[ch].SR |= STATUS_TRANSMITTER_EMPTY; |
| 324 | | } |
| 325 | | if ( BIT(data,3) ) |
| 326 | | { |
| 327 | | duart68681->channel[ch].tx_enabled = 0; |
| 328 | | duart68681->channel[ch].tx_ready = 0; |
| 329 | | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY; |
| 330 | | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_EMPTY; |
| 331 | | } |
| 332 | | |
| 333 | 316 | switch( (data >> 4) & 0x07 ) |
| 334 | 317 | { |
| 335 | 318 | case 0: /* No command */ |
| r9743 | r9744 | |
| 348 | 331 | case 3: /* Reset channel A transmitter */ |
| 349 | 332 | duart68681->channel[ch].tx_enabled = 0; |
| 350 | 333 | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY; |
| 334 | if (ch == 0) |
| 335 | duart68681->ISR &= ~INT_TXRDYA; |
| 336 | else |
| 337 | duart68681->ISR &= ~INT_TXRDYB; |
| 351 | 338 | timer_adjust_oneshot(duart68681->channel[ch].tx_timer, attotime_never, ch); |
| 352 | 339 | break; |
| 353 | 340 | case 4: /* Reset Error Status */ |
| r9743 | r9744 | |
| 369 | 356 | break; |
| 370 | 357 | } |
| 371 | 358 | duart68681_update_interrupts(duart68681); |
| 359 | |
| 360 | if (BIT(data, 0)) { |
| 361 | duart68681->channel[ch].rx_enabled = 1; |
| 362 | } |
| 363 | if (BIT(data, 1)) { |
| 364 | duart68681->channel[ch].rx_enabled = 0; |
| 365 | duart68681->channel[ch].SR &= ~STATUS_RECEIVER_READY; |
| 366 | } |
| 367 | |
| 368 | if (BIT(data, 2)) { |
| 369 | duart68681->channel[ch].tx_enabled = 1; |
| 370 | duart68681->channel[ch].tx_ready = 1; |
| 371 | duart68681->channel[ch].SR |= STATUS_TRANSMITTER_READY; |
| 372 | if (ch == 0) |
| 373 | duart68681->ISR |= INT_TXRDYA; |
| 374 | else |
| 375 | duart68681->ISR |= INT_TXRDYB; |
| 376 | } |
| 377 | if (BIT(data, 3)) { |
| 378 | duart68681->channel[ch].tx_enabled = 0; |
| 379 | duart68681->channel[ch].tx_ready = 0; |
| 380 | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY; |
| 381 | if (ch == 0) |
| 382 | duart68681->ISR &= ~INT_TXRDYA; |
| 383 | else |
| 384 | duart68681->ISR &= ~INT_TXRDYB; |
| 385 | } |
| 386 | |
| 372 | 387 | }; |
| 373 | 388 | |
| 374 | 389 | static UINT8 duart68681_read_rx_fifo(duart68681_state *duart68681, int ch) |
| r9743 | r9744 | |
| 422 | 437 | |
| 423 | 438 | duart68681->channel[ch].tx_data = data; |
| 424 | 439 | |
| 425 | | duart68681->channel[ch].tx_ready = 0; |
| 426 | | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY; |
| 440 | // tx_ready will stay on in local loopback mode |
| 441 | if ((duart68681->channel[ch].MR2 & 0xc0) != 0x80) { |
| 442 | duart68681->channel[ch].tx_ready = 0; |
| 443 | duart68681->channel[ch].SR &= ~STATUS_TRANSMITTER_READY; |
| 444 | } |
| 427 | 445 | |
| 428 | 446 | if (ch == 0) |
| 429 | 447 | duart68681->ISR &= ~INT_TXRDYA; |
src/emu/machine/8237dma.c
| r9743 | r9744 | |
| 103 | 103 | : device_t(_machine, config), |
| 104 | 104 | m_config(config) |
| 105 | 105 | { |
| 106 | | |
| 107 | 106 | } |
| 108 | 107 | |
| 109 | 108 | //------------------------------------------------- |
| r9743 | r9744 | |
| 141 | 140 | m_last_service_channel = 3; |
| 142 | 141 | |
| 143 | 142 | m_command = 0; |
| 143 | m_drq = 0; |
| 144 | 144 | m_mask = 0x00; |
| 145 | 145 | m_status = 0x0F; |
| 146 | 146 | m_hrq = 0; |
| r9743 | r9744 | |
| 312 | 312 | |
| 313 | 313 | timer_enable( m_timer, 1 ); |
| 314 | 314 | } |
| 315 | else if (m_command == 3 && (m_drq & 1)) |
| 316 | { |
| 317 | /* Memory-to-memory transfers */ |
| 318 | m_hlda = 1; |
| 319 | m_state = DMA8237_S0; |
| 320 | } |
| 315 | 321 | else |
| 316 | 322 | { |
| 317 | 323 | timer_enable( m_timer, 0 ); |
| r9743 | r9744 | |
| 440 | 446 | i8327_set_dack(-1); |
| 441 | 447 | break; |
| 442 | 448 | |
| 443 | | case DMA8237_S11: /* Output A8-A15 */ |
| 449 | case DMA8237_S11: /* Output A8-A15 */ |
| 450 | |
| 451 | // logerror("###### dma8237_timerproc %s: from %04x count=%x to %04x count=%x\n", tag(), |
| 452 | // m_chan[0].m_address, m_chan[0].m_count, |
| 453 | // m_chan[1].m_address, m_chan[1].m_count); |
| 454 | |
| 455 | // FIXME: this will copy bytes correct, but not 16 bit words |
| 456 | m_temporary_data = devcb_call_read8(&m_in_memr_func, m_chan[0].m_address); |
| 457 | devcb_call_write8(&m_out_memw_func, m_chan[1].m_address, m_temporary_data); |
| 458 | |
| 459 | m_service_channel = 0; |
| 460 | |
| 461 | /* Advance */ |
| 462 | i8237_advance(); |
| 463 | |
| 464 | // advance destination channel as well |
| 465 | m_chan[1].m_count--; |
| 466 | m_chan[1].m_address++; |
| 467 | |
| 468 | if (m_chan[0].m_count == 0xFFFF || m_chan[1].m_count == 0xFFFF) { |
| 469 | m_hrq = 0; |
| 470 | m_hlda = 0; |
| 471 | devcb_call_write_line(&m_out_hrq_func, m_hrq); |
| 472 | m_state = DMA8237_SI; |
| 473 | m_status |= 3; // set TC for channel 0 and 1 |
| 474 | m_drq &= ~3; // clear drq for channel 0 and 1 |
| 475 | |
| 476 | // logerror("!!! dma8237_timerproc DMA8237_S11 %s: m_drq=%x m_command=%x\n", tag(), m_drq, m_command); |
| 477 | } |
| 444 | 478 | break; |
| 445 | 479 | } |
| 446 | 480 | } |
| r9743 | r9744 | |
| 506 | 540 | { |
| 507 | 541 | offset &= 0x0F; |
| 508 | 542 | |
| 509 | | logerror("i8237_w: offset = %02x, data = %02x\n", offset, data ); |
| 543 | // logerror("i8237_w: offset = %02x, data = %02x\n", offset, data ); |
| 510 | 544 | |
| 511 | 545 | switch(offset) { |
| 512 | 546 | case 0: |
| r9743 | r9744 | |
| 611 | 645 | m_mask = 0x0f; |
| 612 | 646 | m_state = DMA8237_SI; |
| 613 | 647 | m_status &= 0xF0; |
| 648 | m_temp = 0; |
| 614 | 649 | break; |
| 615 | 650 | |
| 616 | 651 | case 14: |
| r9743 | r9744 | |
| 639 | 674 | } |
| 640 | 675 | |
| 641 | 676 | timer_enable( m_timer, ( m_command & 0x04 ) ? 0 : 1 ); |
| 677 | |
| 642 | 678 | } |
| 643 | 679 | |
| 644 | 680 | |
src/emu/machine/mc146818.c
| r9743 | r9744 | |
| 88 | 88 | // MACROS |
| 89 | 89 | //************************************************************************** |
| 90 | 90 | |
| 91 | #define USE_UTC 1 |
| 92 | |
| 91 | 93 | #define HOURS_24 (m_data[0xb]&2) |
| 92 | 94 | #define BCD_MODE !(m_data[0xb]&4) // book has other description! |
| 93 | | #define CENTURY m_data[50] |
| 95 | #define CENTURY m_data[100] |
| 94 | 96 | #define YEAR m_data[9] |
| 95 | 97 | #define MONTH m_data[8] |
| 96 | 98 | #define DAY m_data[7] |
| r9743 | r9744 | |
| 183 | 185 | { |
| 184 | 186 | m_last_refresh = timer_get_time(&m_machine); |
| 185 | 187 | emu_timer *timer = device_timer_alloc(*this); |
| 186 | | timer_adjust_periodic(timer, ATTOTIME_IN_HZ(1), 0, ATTOTIME_IN_HZ(1)); |
| 188 | if (m_config.m_type == mc146818_device_config::MC146818_UTC) { |
| 189 | // hack: for apollo we increase the update frequency to stay in sync with real time |
| 190 | timer_adjust_periodic(timer, ATTOTIME_IN_HZ(2), 0, ATTOTIME_IN_HZ(2)); |
| 191 | } else { |
| 192 | timer_adjust_periodic(timer, ATTOTIME_IN_HZ(1), 0, ATTOTIME_IN_HZ(1)); |
| 193 | } |
| 187 | 194 | set_base_datetime(); |
| 188 | 195 | } |
| 189 | 196 | |
| r9743 | r9744 | |
| 196 | 203 | { |
| 197 | 204 | int year/*, month*/; |
| 198 | 205 | |
| 206 | if (m_config.m_type == mc146818_device_config::MC146818_UTC) { |
| 207 | // hack: set correct real time even for overloaded emulation |
| 208 | // (at least for apollo) |
| 209 | static osd_ticks_t t0 = 0; |
| 210 | osd_ticks_t t1 = osd_ticks(); |
| 211 | int n_seconds; |
| 212 | |
| 213 | if (t0 == 0) { |
| 214 | t0 = t1; |
| 215 | } |
| 216 | |
| 217 | n_seconds = (t1 - t0) / osd_ticks_per_second(); |
| 218 | t0 = t1 - (t1 - t0) % osd_ticks_per_second(); |
| 219 | if (n_seconds <= 0) { |
| 220 | // we were called to early |
| 221 | return; |
| 222 | } |
| 223 | |
| 224 | m_data[0] += n_seconds; |
| 225 | } else { |
| 226 | m_data[0] += 1; |
| 227 | } |
| 228 | |
| 199 | 229 | if (BCD_MODE) |
| 200 | 230 | { |
| 201 | | m_data[0]=bcd_adjust(m_data[0]+1); |
| 231 | m_data[0]=bcd_adjust(m_data[0]/*+1*/); |
| 202 | 232 | if (m_data[0]>=0x60) |
| 203 | 233 | { |
| 204 | 234 | m_data[0]=0; |
| r9743 | r9744 | |
| 241 | 271 | } |
| 242 | 272 | else |
| 243 | 273 | { |
| 244 | | m_data[0]=m_data[0]+1; |
| 274 | /*m_data[0]=m_data[0]+1;*/ |
| 245 | 275 | if (m_data[0]>=60) |
| 246 | 276 | { |
| 247 | | m_data[0]=0; |
| 277 | m_data[0] -= 60; |
| 248 | 278 | m_data[2]=m_data[2]+1; |
| 249 | 279 | if (m_data[2]>=60) { |
| 250 | 280 | m_data[2]=0; |
| r9743 | r9744 | |
| 272 | 302 | } |
| 273 | 303 | } |
| 274 | 304 | } |
| 305 | |
| 306 | if (m_data[1] == m_data[0] && // |
| 307 | m_data[3] == m_data[2] && // |
| 308 | m_data[5] == m_data[4]) { |
| 309 | // set the alarm interrupt flag AF |
| 310 | m_data[0x0c] |= 0x20; |
| 311 | } else { |
| 312 | // clear the alarm interrupt flag AF |
| 313 | m_data[0x0c] &= ~0x20; |
| 314 | if ((m_data[0x0c] & 0x70) == 0) { |
| 315 | // clear IRQF |
| 316 | m_data[0x0c] &= ~0x80; |
| 317 | } |
| 318 | } |
| 319 | |
| 320 | // set the update-ended interrupt Flag UF |
| 321 | m_data[0x0c] |= 0x10; |
| 322 | |
| 323 | // set the interrupt request flag IRQF |
| 324 | // FIXME: should throw IRQ line as well |
| 325 | if ((m_data[0x0b] & m_data[0x0c] & 0x70) != 0) { |
| 326 | m_data[0x0c] |= 0x80; |
| 327 | } |
| 328 | |
| 275 | 329 | m_updated = true; /* clock has been updated */ |
| 276 | 330 | m_last_refresh = timer_get_time(&m_machine); |
| 277 | 331 | } |
| r9743 | r9744 | |
| 297 | 351 | void mc146818_device::nvram_read(mame_file &file) |
| 298 | 352 | { |
| 299 | 353 | mame_fread(&file, m_data, sizeof(m_data)); |
| 354 | set_base_datetime(); |
| 300 | 355 | } |
| 301 | 356 | |
| 302 | 357 | |
| r9743 | r9744 | |
| 330 | 385 | void mc146818_device::set_base_datetime() |
| 331 | 386 | { |
| 332 | 387 | system_time systime; |
| 388 | system_time::full_time current_time; |
| 333 | 389 | |
| 334 | 390 | m_machine.base_datetime(systime); |
| 335 | 391 | |
| 336 | | if (HOURS_24 || (systime.local_time.hour < 12)) |
| 337 | | m_data[4] = dec_2_local(systime.local_time.hour); |
| 392 | current_time = m_config.m_type == mc146818_device_config::MC146818_UTC ? systime.utc_time: systime.local_time; |
| 393 | |
| 394 | // temporary hack to go back 20 year (e.g. from 2010 -> 1990) |
| 395 | // current_time.year -= 20; |
| 396 | |
| 397 | // logerror("mc146818_set_base_datetime %02d/%02d/%02d %02d:%02d:%02d\n", |
| 398 | // current_time.year % 100, current_time.month + 1, current_time.mday, |
| 399 | // current_time.hour,current_time.minute, current_time.second); |
| 400 | |
| 401 | if (HOURS_24 || (current_time.hour < 12)) |
| 402 | m_data[4] = dec_2_local(current_time.hour); |
| 338 | 403 | else |
| 339 | | m_data[4] = dec_2_local(systime.local_time.hour - 12) | 0x80; |
| 404 | m_data[4] = dec_2_local(current_time.hour - 12) | 0x80; |
| 340 | 405 | |
| 341 | 406 | if (m_config.m_type != mc146818_device_config::MC146818_IGNORE_CENTURY) |
| 342 | | CENTURY = dec_2_local(systime.local_time.year /100); |
| 407 | CENTURY = dec_2_local(current_time.year /100); |
| 343 | 408 | |
| 344 | | m_data[0] = dec_2_local(systime.local_time.second); |
| 345 | | m_data[2] = dec_2_local(systime.local_time.minute); |
| 346 | | DAY = dec_2_local(systime.local_time.day); |
| 347 | | MONTH = dec_2_local(systime.local_time.month + 1); |
| 348 | | YEAR = dec_2_local(systime.local_time.year % 100); |
| 409 | m_data[0] = dec_2_local(current_time.second); |
| 410 | m_data[2] = dec_2_local(current_time.minute); |
| 411 | DAY = dec_2_local(current_time.mday); |
| 412 | MONTH = dec_2_local(current_time.month + 1); |
| 413 | YEAR = dec_2_local(current_time.year % 100); |
| 349 | 414 | |
| 350 | | WEEK_DAY = systime.local_time.weekday; |
| 351 | | if (systime.local_time.is_dst) |
| 415 | WEEK_DAY = current_time.weekday; |
| 416 | if (current_time.is_dst) |
| 352 | 417 | m_data[0xb] |= 1; |
| 353 | 418 | else |
| 354 | 419 | m_data[0xb] &= ~1; |
| r9743 | r9744 | |
| 380 | 445 | break; |
| 381 | 446 | |
| 382 | 447 | case 0xc: |
| 383 | | if (m_updated) /* the clock has been updated */ |
| 384 | | data = 0x10; |
| 385 | | else |
| 386 | | data = 0x00; |
| 448 | // if(m_updated) /* the clock has been updated */ |
| 449 | // data = 0x10; |
| 450 | // else |
| 451 | // data = 0x00; |
| 452 | // the unused bits b0 ... b3 are always read as 0 |
| 453 | data = m_data[m_index % MC146818_DATA_SIZE] & 0xf0; |
| 454 | // read 0x0c will clear all IRQ flags in register 0x0c |
| 455 | m_data[m_index % MC146818_DATA_SIZE] &= 0x0f; |
| 387 | 456 | break; |
| 388 | 457 | case 0xd: |
| 389 | 458 | /* battery ok */ |
| r9743 | r9744 | |
| 425 | 494 | m_updated = false; |
| 426 | 495 | m_data[m_index % MC146818_DATA_SIZE] = data; |
| 427 | 496 | break; |
| 497 | case 0x0c: |
| 498 | // register 0x0c is readonly |
| 499 | break; |
| 428 | 500 | default: |
| 429 | 501 | m_data[m_index % MC146818_DATA_SIZE] = data; |
| 430 | 502 | } |