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 |