trunk/src/devices/machine/wozfdc.cpp
| r250320 | r250321 | |
| 76 | 76 | save_item(NAME(active)); |
| 77 | 77 | save_item(NAME(phases)); |
| 78 | 78 | save_item(NAME(external_io_select)); |
| 79 | | save_item(NAME(cur_lss.tm)); |
| 80 | | save_item(NAME(cur_lss.cycles)); |
| 81 | | save_item(NAME(cur_lss.data_reg)); |
| 82 | | save_item(NAME(cur_lss.address)); |
| 83 | | save_item(NAME(cur_lss.write_start_time)); |
| 84 | | // save_item(NAME(cur_lss.write_buffer)); |
| 85 | | save_item(NAME(cur_lss.write_position)); |
| 86 | | save_item(NAME(cur_lss.write_line_active)); |
| 87 | | save_item(NAME(predicted_lss.tm)); |
| 88 | | save_item(NAME(predicted_lss.cycles)); |
| 89 | | save_item(NAME(predicted_lss.data_reg)); |
| 90 | | save_item(NAME(predicted_lss.address)); |
| 91 | | save_item(NAME(predicted_lss.write_start_time)); |
| 92 | | // save_item(NAME(predicted_lss.write_buffer)); |
| 93 | | save_item(NAME(predicted_lss.write_position)); |
| 94 | | save_item(NAME(predicted_lss.write_line_active)); |
| 79 | save_item(NAME(cycles)); |
| 80 | save_item(NAME(data_reg)); |
| 81 | save_item(NAME(address)); |
| 82 | save_item(NAME(write_start_time)); |
| 83 | save_item(NAME(write_position)); |
| 84 | save_item(NAME(write_line_active)); |
| 95 | 85 | save_item(NAME(drvsel)); |
| 96 | 86 | save_item(NAME(enable1)); |
| 97 | 87 | } |
| r250320 | r250321 | |
| 104 | 94 | mode_write = false; |
| 105 | 95 | mode_load = false; |
| 106 | 96 | last_6502_write = 0x00; |
| 107 | | cur_lss.tm = machine().time(); |
| 108 | | cur_lss.cycles = time_to_cycles(cur_lss.tm); |
| 109 | | cur_lss.data_reg = 0x00; |
| 110 | | cur_lss.address = 0x00; |
| 111 | | cur_lss.write_start_time = attotime::never; |
| 112 | | cur_lss.write_position = 0; |
| 113 | | cur_lss.write_line_active = false; |
| 114 | | predicted_lss.tm = attotime::never; |
| 97 | cycles = time_to_cycles(machine().time()); |
| 98 | data_reg = 0x00; |
| 99 | address = 0x00; |
| 100 | write_start_time = attotime::never; |
| 101 | write_position = 0; |
| 102 | write_line_active = false; |
| 115 | 103 | external_io_select = false; |
| 104 | |
| 105 | // Just a timer to be sure that the lss is updated from time to |
| 106 | // time, so that there's no hiccup when it's talked to again. |
| 107 | timer->adjust(attotime::from_msec(10), 0, attotime::from_msec(10)); |
| 116 | 108 | } |
| 117 | 109 | |
| 118 | 110 | void wozfdc_device::a3_update_drive_sel() |
| r250320 | r250321 | |
| 152 | 144 | floppy->mon_w(true); |
| 153 | 145 | } |
| 154 | 146 | floppy = newflop; |
| 155 | | if(active) { |
| 147 | if(active) |
| 156 | 148 | floppy->mon_w(false); |
| 157 | | lss_predict(); |
| 158 | | } |
| 159 | 149 | } |
| 160 | 150 | } |
| 161 | 151 | |
| r250320 | r250321 | |
| 188 | 178 | floppy->mon_w(true); |
| 189 | 179 | active = MODE_IDLE; |
| 190 | 180 | } |
| 191 | | |
| 192 | | if(active) |
| 193 | | lss_predict(); |
| 194 | 181 | } |
| 195 | 182 | |
| 196 | 183 | /*------------------------------------------------- |
| r250320 | r250321 | |
| 201 | 188 | { |
| 202 | 189 | control(offset); |
| 203 | 190 | |
| 204 | | if(!(offset & 1)) |
| 205 | | return cur_lss.data_reg; |
| 191 | if(!(offset & 1)) { |
| 192 | lss_sync(); |
| 193 | return data_reg; |
| 194 | } |
| 206 | 195 | return 0xff; |
| 207 | 196 | } |
| 208 | 197 | |
| r250320 | r250321 | |
| 214 | 203 | WRITE8_MEMBER(wozfdc_device::write) |
| 215 | 204 | { |
| 216 | 205 | control(offset); |
| 206 | lss_sync(); |
| 217 | 207 | last_6502_write = data; |
| 218 | | lss_predict(); |
| 219 | 208 | } |
| 220 | 209 | |
| 221 | 210 | void wozfdc_device::phase(int ph, bool on) |
| r250320 | r250321 | |
| 235 | 224 | if(active) |
| 236 | 225 | lss_sync(); |
| 237 | 226 | phase(offset >> 1, offset & 1); |
| 238 | | if(active) |
| 239 | | lss_predict(); |
| 240 | 227 | |
| 241 | 228 | } else |
| 242 | 229 | switch(offset) { |
| r250320 | r250321 | |
| 262 | 249 | break; |
| 263 | 250 | } |
| 264 | 251 | break; |
| 265 | | case 0xa: |
| 252 | case 0xa: |
| 266 | 253 | external_io_select = false; |
| 267 | 254 | if(floppy != floppy0->get_device()) { |
| 268 | 255 | if(active) { |
| r250320 | r250321 | |
| 270 | 257 | floppy->mon_w(true); |
| 271 | 258 | } |
| 272 | 259 | floppy = floppy0->get_device(); |
| 273 | | if(active) { |
| 260 | if(active) |
| 274 | 261 | floppy->mon_w(false); |
| 275 | | lss_predict(); |
| 276 | | } |
| 277 | 262 | } |
| 278 | 263 | break; |
| 279 | 264 | case 0xb: |
| r250320 | r250321 | |
| 287 | 272 | floppy->mon_w(true); |
| 288 | 273 | } |
| 289 | 274 | floppy = floppy1->get_device(); |
| 290 | | if(active) { |
| 275 | if(active) |
| 291 | 276 | floppy->mon_w(false); |
| 292 | | lss_predict(); |
| 293 | | } |
| 294 | 277 | } |
| 295 | 278 | } |
| 296 | 279 | else |
| r250320 | r250321 | |
| 302 | 285 | if(mode_load) { |
| 303 | 286 | if(active) { |
| 304 | 287 | lss_sync(); |
| 305 | | cur_lss.address &= ~0x04; |
| 288 | address &= ~0x04; |
| 306 | 289 | } |
| 307 | 290 | mode_load = false; |
| 308 | | if(active) |
| 309 | | lss_predict(); |
| 310 | 291 | } |
| 311 | 292 | break; |
| 312 | 293 | case 0xd: |
| 313 | 294 | if(!mode_load) { |
| 314 | 295 | if(active) { |
| 315 | 296 | lss_sync(); |
| 316 | | cur_lss.address |= 0x04; |
| 297 | address |= 0x04; |
| 317 | 298 | } |
| 318 | 299 | mode_load = true; |
| 319 | | if(active) |
| 320 | | lss_predict(); |
| 321 | 300 | } |
| 322 | 301 | break; |
| 323 | 302 | case 0xe: |
| 324 | 303 | if(mode_write) { |
| 325 | 304 | if(active) { |
| 326 | 305 | lss_sync(); |
| 327 | | cur_lss.address &= ~0x08; |
| 306 | address &= ~0x08; |
| 328 | 307 | } |
| 329 | 308 | mode_write = false; |
| 330 | | if(active) |
| 331 | | lss_predict(); |
| 332 | 309 | } |
| 333 | 310 | break; |
| 334 | 311 | case 0xf: |
| 335 | 312 | if(!mode_write) { |
| 336 | 313 | if(active) { |
| 337 | 314 | lss_sync(); |
| 338 | | cur_lss.address |= 0x08; |
| 339 | | cur_lss.write_start_time = machine().time(); |
| 315 | address |= 0x08; |
| 316 | write_start_time = machine().time(); |
| 340 | 317 | if(floppy) |
| 341 | | floppy->set_write_splice(cur_lss.write_start_time); |
| 318 | floppy->set_write_splice(write_start_time); |
| 342 | 319 | } |
| 343 | 320 | mode_write = true; |
| 344 | | if(active) |
| 345 | | lss_predict(); |
| 346 | 321 | } |
| 347 | 322 | break; |
| 348 | 323 | } |
| r250320 | r250321 | |
| 365 | 340 | |
| 366 | 341 | void wozfdc_device::lss_start() |
| 367 | 342 | { |
| 368 | | cur_lss.tm = machine().time(); |
| 369 | | cur_lss.cycles = time_to_cycles(cur_lss.tm); |
| 370 | | cur_lss.data_reg = 0x00; |
| 371 | | cur_lss.address &= ~0x0e; |
| 372 | | cur_lss.write_position = 0; |
| 373 | | cur_lss.write_start_time = mode_write ? machine().time() : attotime::never; |
| 374 | | cur_lss.write_line_active = false; |
| 343 | cycles = time_to_cycles(machine().time()); |
| 344 | data_reg = 0x00; |
| 345 | address &= ~0x0e; |
| 346 | write_position = 0; |
| 347 | write_start_time = mode_write ? machine().time() : attotime::never; |
| 348 | write_line_active = false; |
| 375 | 349 | if(mode_write && floppy) |
| 376 | | floppy->set_write_splice(cur_lss.write_start_time); |
| 377 | | lss_predict(); |
| 350 | floppy->set_write_splice(write_start_time); |
| 378 | 351 | } |
| 379 | 352 | |
| 380 | | void wozfdc_device::lss_delay(UINT64 cycles, const attotime &tm, UINT8 data_reg, UINT8 address, bool write_line_active) |
| 381 | | { |
| 382 | | if(data_reg & 0x80) |
| 383 | | address |= 0x02; |
| 384 | | else |
| 385 | | address &= ~0x02; |
| 386 | | predicted_lss.cycles = cycles; |
| 387 | | predicted_lss.tm = tm; |
| 388 | | predicted_lss.data_reg = data_reg; |
| 389 | | predicted_lss.address = address; |
| 390 | | predicted_lss.write_line_active = write_line_active; |
| 391 | | attotime mtm = machine().time(); |
| 392 | | if(predicted_lss.tm > mtm) |
| 393 | | timer->adjust(predicted_lss.tm - mtm); |
| 394 | | } |
| 395 | | |
| 396 | | void wozfdc_device::lss_delay(UINT64 cycles, UINT8 data_reg, UINT8 address, bool write_line_active) |
| 397 | | { |
| 398 | | lss_delay(cycles, cycles_to_time(cycles), data_reg, address, write_line_active); |
| 399 | | } |
| 400 | | |
| 401 | | void wozfdc_device::commit_predicted() |
| 402 | | { |
| 403 | | cur_lss = predicted_lss; |
| 404 | | assert(!mode_write || (cur_lss.write_line_active && (cur_lss.address & 0x80)) || ((!cur_lss.write_line_active) && !(cur_lss.address & 0x80))); |
| 405 | | if(mode_write) { |
| 406 | | if(floppy) |
| 407 | | floppy->write_flux(cur_lss.write_start_time, cur_lss.tm, cur_lss.write_position, cur_lss.write_buffer); |
| 408 | | cur_lss.write_start_time = cur_lss.tm; |
| 409 | | cur_lss.write_position = 0; |
| 410 | | } |
| 411 | | |
| 412 | | predicted_lss.tm = attotime::never; |
| 413 | | } |
| 414 | | |
| 415 | 353 | void wozfdc_device::lss_sync() |
| 416 | 354 | { |
| 417 | | attotime tm = machine().time(); |
| 418 | | if(!predicted_lss.tm.is_never() && predicted_lss.tm <= tm) |
| 419 | | commit_predicted(); |
| 355 | if(!active) |
| 356 | return; |
| 420 | 357 | |
| 421 | | while(cur_lss.tm < tm) { |
| 422 | | lss_predict(tm); |
| 423 | | commit_predicted(); |
| 424 | | } |
| 425 | | } |
| 358 | attotime next_flux = floppy ? floppy->get_next_transition(cycles_to_time(cycles) - attotime::from_usec(1)) : attotime::never; |
| 426 | 359 | |
| 427 | | void wozfdc_device::lss_predict(attotime limit) |
| 428 | | { |
| 429 | | predicted_lss.write_start_time = cur_lss.write_start_time; |
| 430 | | predicted_lss.write_position = cur_lss.write_position; |
| 431 | | memcpy(predicted_lss.write_buffer, cur_lss.write_buffer, cur_lss.write_position * sizeof(attotime)); |
| 432 | | bool write_line_active = cur_lss.write_line_active; |
| 433 | | |
| 434 | | attotime next_flux = floppy ? floppy->get_next_transition(cur_lss.tm - attotime::from_usec(1)) : attotime::never; |
| 435 | | |
| 436 | | if(limit == attotime::never) |
| 437 | | limit = machine().time() + attotime::from_usec(50); |
| 438 | | |
| 439 | | UINT64 cycles = cur_lss.cycles; |
| 440 | | UINT64 cycles_limit = time_to_cycles(limit); |
| 360 | UINT64 cycles_limit = time_to_cycles(machine().time()); |
| 441 | 361 | UINT64 cycles_next_flux = next_flux != attotime::never ? time_to_cycles(next_flux) : UINT64(-1); |
| 442 | 362 | UINT64 cycles_next_flux_down = cycles_next_flux != UINT64(-1) ? cycles_next_flux+1 : UINT64(-1); |
| 443 | 363 | |
| 444 | | UINT8 address = cur_lss.address; |
| 445 | | UINT8 data_reg = cur_lss.data_reg; |
| 446 | | |
| 447 | 364 | if(cycles >= cycles_next_flux && cycles < cycles_next_flux_down) |
| 448 | 365 | address &= ~0x10; |
| 449 | 366 | else |
| r250320 | r250321 | |
| 463 | 380 | if((write_line_active && !(address & 0x80)) || |
| 464 | 381 | (!write_line_active && (address & 0x80))) { |
| 465 | 382 | write_line_active = !write_line_active; |
| 466 | | assert(predicted_lss.write_position != 32); |
| 467 | | predicted_lss.write_buffer[predicted_lss.write_position++] = cycles_to_time(cycles); |
| 383 | assert(write_position != 32); |
| 384 | write_buffer[write_position++] = cycles_to_time(cycles); |
| 468 | 385 | } |
| 469 | 386 | } |
| 470 | 387 | |
| 471 | 388 | address = (address & 0x1e) | (opcode & 0xc0) | ((opcode & 0x20) >> 5) | ((opcode & 0x10) << 1); |
| 472 | 389 | switch(opcode & 0x0f) { |
| 473 | 390 | case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: |
| 474 | | if(data_reg) { |
| 475 | | lss_delay(cycles+1, 0x00, address, write_line_active); |
| 476 | | return; |
| 477 | | } |
| 391 | data_reg = 0x00; |
| 478 | 392 | break; |
| 479 | 393 | case 0x8: case 0xc: |
| 480 | 394 | break; |
| 481 | 395 | case 0x9: |
| 482 | | lss_delay(cycles+1, data_reg << 1, address, write_line_active); |
| 483 | | return; |
| 396 | data_reg <<= 1; |
| 397 | break; |
| 484 | 398 | case 0xa: case 0xe: |
| 485 | | lss_delay(cycles+1, (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00), address, write_line_active); |
| 486 | | return; |
| 399 | data_reg = (data_reg >> 1) | (floppy && floppy->wpt_r() ? 0x80 : 0x00); |
| 400 | break; |
| 487 | 401 | case 0xb: case 0xf: |
| 488 | | lss_delay(cycles+1, last_6502_write, address, write_line_active); |
| 489 | | return; |
| 402 | data_reg = last_6502_write; |
| 403 | break; |
| 490 | 404 | case 0xd: |
| 491 | | lss_delay(cycles+1, (data_reg << 1) | 0x01, address, write_line_active); |
| 492 | | return; |
| 405 | data_reg = (data_reg << 1) | 0x01; |
| 406 | break; |
| 493 | 407 | } |
| 408 | if(data_reg & 0x80) |
| 409 | address |= 0x02; |
| 410 | else |
| 411 | address &= ~0x02; |
| 494 | 412 | cycles++; |
| 495 | 413 | } |
| 496 | 414 | |
| r250320 | r250321 | |
| 503 | 421 | cycles_next_flux_down = cycles_next_flux != UINT64(-1) ? cycles_next_flux+1 : UINT64(-1); |
| 504 | 422 | } |
| 505 | 423 | } |
| 506 | | |
| 507 | | lss_delay(cycles, limit, data_reg, address, write_line_active); |
| 508 | 424 | } |
| 509 | 425 | |
| 510 | 426 | // set the two images for the Disk II |