Previous 199869 Revisions Next

r19167 Tuesday 27th November, 2012 at 16:53:30 UTC by O. Galibert
wd1772: Rename to wd_fdc [O. Galibert]
[src/emu]emu.mak
[src/emu/machine]wd1772.c wd1772.h wd_fdc.c wd_fdc.h
[src/mess/drivers]b2m.c einstein.c esq1.c esq5505.c ht68k.c mirage.c samcoupe.c
[src/mess/includes]atarist.h b2m.h bw2.h einstein.h samcoupe.h super6.h v1050.h xerox820.h
[src/mess/machine]adam_fdc.h b2m.c tvc_hbf.h

trunk/src/emu/emu.mak
r19166r19167
271271   $(EMUMACHINE)/upd7201.o      \
272272   $(EMUMACHINE)/upd765.o      \
273273   $(EMUMACHINE)/v3021.o      \
274   $(EMUMACHINE)/wd1772.o      \
275274   $(EMUMACHINE)/wd17xx.o      \
276275   $(EMUMACHINE)/wd33c93.o      \
276   $(EMUMACHINE)/wd_fdc.o      \
277277   $(EMUMACHINE)/x2212.o      \
278278   $(EMUMACHINE)/x76f041.o      \
279279   $(EMUMACHINE)/x76f100.o      \
trunk/src/emu/machine/wd1772.c
r19166r19167
1/***************************************************************************
2
3    Copyright Olivier Galibert
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions are
8    met:
9
10        * Redistributions of source code must retain the above copyright
11          notice, this list of conditions and the following disclaimer.
12        * Redistributions in binary form must reproduce the above copyright
13          notice, this list of conditions and the following disclaimer in
14          the documentation and/or other materials provided with the
15          distribution.
16        * Neither the name 'MAME' nor the names of its contributors may be
17          used to endorse or promote products derived from this software
18          without specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
21    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
24    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30    POSSIBILITY OF SUCH DAMAGE.
31
32****************************************************************************/
33
34#include "wd1772.h"
35
36#include "debugger.h"
37
38const device_type FD1771x = &device_creator<fd1771_t>;
39const device_type FD1793x = &device_creator<fd1793_t>;
40const device_type FD1797x = &device_creator<fd1797_t>;
41const device_type WD2793x = &device_creator<wd2793_t>;
42const device_type WD2797x = &device_creator<wd2797_t>;
43const device_type WD1770x = &device_creator<wd1770_t>;
44const device_type WD1772x = &device_creator<wd1772_t>;
45const device_type WD1773x = &device_creator<wd1773_t>;
46
47wd177x_t::wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
48   device_t(mconfig, type, name, tag, owner, clock)
49{
50}
51
52void wd177x_t::device_start()
53{
54   t_gen = timer_alloc(TM_GEN);
55   t_cmd = timer_alloc(TM_CMD);
56   t_track = timer_alloc(TM_TRACK);
57   t_sector = timer_alloc(TM_SECTOR);
58   dden = false;
59   floppy = 0;
60
61   save_item(NAME(status));
62   save_item(NAME(command));
63   save_item(NAME(main_state));
64   save_item(NAME(sub_state));
65   save_item(NAME(track));
66   save_item(NAME(sector));
67   save_item(NAME(intrq_cond));
68   save_item(NAME(cmd_buffer));
69   save_item(NAME(track_buffer));
70   save_item(NAME(sector_buffer));
71   save_item(NAME(counter));
72   save_item(NAME(status_type_1));
73   save_item(NAME(last_dir));
74}
75
76void wd177x_t::device_reset()
77{
78   command = 0x00;
79   main_state = IDLE;
80   sub_state = IDLE;
81   cur_live.state = IDLE;
82   track = 0x00;
83   sector = 0x00;
84   status = 0x00;
85   data = 0x00;
86   cmd_buffer = track_buffer = sector_buffer = -1;
87   counter = 0;
88   status_type_1 = true;
89   last_dir = 1;
90   intrq = false;
91   drq = false;
92   hld = false;
93   live_abort();
94}
95
96void wd177x_t::set_floppy(floppy_image_device *_floppy)
97{
98   if(floppy == _floppy)
99      return;
100
101   if(floppy) {
102      floppy->mon_w(1);
103      floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
104   }
105
106   floppy = _floppy;
107
108   if(floppy) {
109      if(has_motor())
110         floppy->mon_w(status & S_MON ? 0 : 1);
111      floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(wd177x_t::index_callback), this));
112   }
113}
114
115void wd177x_t::setup_intrq_cb(line_cb cb)
116{
117   intrq_cb = cb;
118}
119
120void wd177x_t::setup_drq_cb(line_cb cb)
121{
122   drq_cb = cb;
123}
124
125void wd177x_t::setup_hld_cb(line_cb cb)
126{
127   hld_cb = cb;
128}
129
130void wd177x_t::setup_enp_cb(line_cb cb)
131{
132   enp_cb = cb;
133}
134
135void wd177x_t::dden_w(bool _dden)
136{
137   dden = _dden;
138}
139
140astring wd177x_t::tts(attotime t)
141{
142   char buf[256];
143   int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
144   sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000);
145   return buf;
146}
147
148astring wd177x_t::ttsn()
149{
150   return tts(machine().time());
151}
152
153void wd177x_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
154{
155   live_sync();
156
157   switch(id) {
158   case TM_GEN: do_generic(); break;
159   case TM_CMD: do_cmd_w(); break;
160   case TM_TRACK: do_track_w(); break;
161   case TM_SECTOR: do_sector_w(); break;
162   }
163
164   general_continue();
165}
166
167void wd177x_t::command_end()
168{
169   main_state = sub_state = IDLE;
170   status &= ~S_BUSY;
171   intrq = true;
172   motor_timeout = 0;
173   if(!intrq_cb.isnull())
174      intrq_cb(intrq);
175}
176
177void wd177x_t::seek_start(int state)
178{
179   main_state = state;
180   status = (status & ~(S_CRC|S_RNF|S_SPIN)) | S_BUSY;
181   if(has_head_load()) {
182      // TODO get value from HLT callback
183      if (command & 8)
184         status |= S_HLD;
185      else
186         status &= ~S_HLD;
187   }
188   sub_state = has_motor() && !has_head_load() ? SPINUP : SPINUP_DONE;
189   status_type_1 = true;
190   seek_continue();
191}
192
193void wd177x_t::seek_continue()
194{
195   for(;;) {
196      switch(sub_state) {
197      case SPINUP:
198         if(!(status & S_MON)) {
199            spinup();
200            return;
201         }
202         if(!(command & 0x08))
203            status |= S_SPIN;
204         sub_state = SPINUP_DONE;
205         break;
206
207      case SPINUP_WAIT:
208         return;
209
210      case SPINUP_DONE:
211         if(main_state == RESTORE && floppy && !floppy->trk00_r())
212            sub_state = SEEK_DONE;
213
214         if(main_state == SEEK && track == data)
215            sub_state = SEEK_DONE;
216
217         if(sub_state == SPINUP_DONE) {
218            counter = 0;
219            sub_state = SEEK_MOVE;
220         }
221         break;
222
223      case SEEK_MOVE:
224         if(floppy) {
225            floppy->dir_w(last_dir);
226            floppy->stp_w(0);
227            floppy->stp_w(1);
228         }
229         // When stepping with update, the track register is updated before seeking.
230         // Important for the sam coupe format code.
231         if(main_state == STEP && (command & 0x10))
232            track += last_dir ? -1 : 1;
233         counter++;
234         sub_state = SEEK_WAIT_STEP_TIME;
235         delay_cycles(t_gen, step_time(command & 3));
236         return;
237
238      case SEEK_WAIT_STEP_TIME:
239         return;
240
241      case SEEK_WAIT_STEP_TIME_DONE: {
242         bool done = false;
243         switch(main_state) {
244         case RESTORE:
245            done = !floppy || !floppy->trk00_r();
246            break;
247         case SEEK:
248            track += last_dir ? -1 : 1;
249            done = track == data;
250            break;
251         case STEP:
252            done = true;
253            break;
254         }
255
256         if(done || counter == 255) {
257            if(main_state == RESTORE)
258               track = 0;
259
260            if(command & 0x04) {
261               sub_state = SEEK_WAIT_STABILIZATION_TIME;
262               delay_cycles(t_gen, 120000);
263               return;
264            } else
265               sub_state = SEEK_DONE;
266
267         } else
268            sub_state = SEEK_MOVE;
269
270         break;
271      }
272
273      case SEEK_WAIT_STABILIZATION_TIME:
274         return;
275
276      case SEEK_WAIT_STABILIZATION_TIME_DONE:
277         sub_state = SEEK_DONE;
278         break;
279
280      case SEEK_DONE:
281         if(command & 0x04) {
282            if(has_ready() && !is_ready()) {
283               status |= S_RNF;
284               command_end();
285               return;
286            }
287            sub_state = SCAN_ID;
288            counter = 0;
289            live_start(SEARCH_ADDRESS_MARK_HEADER);
290            return;
291         }
292         command_end();
293         return;
294
295      case SCAN_ID:
296         if(cur_live.idbuf[0] != track) {
297            live_start(SEARCH_ADDRESS_MARK_HEADER);
298            return;
299         }
300         if(cur_live.crc) {
301            status |= S_CRC;
302            live_start(SEARCH_ADDRESS_MARK_HEADER);
303            return;
304         }
305         command_end();
306         return;
307
308      case SCAN_ID_FAILED:
309         status |= S_RNF;
310         command_end();
311         return;
312
313      default:
314         logerror("%s: seek unknown sub-state %d\n", ttsn().cstr(), sub_state);
315         return;
316      }
317   }
318}
319
320bool wd177x_t::sector_matches() const
321{
322   if(cur_live.idbuf[0] != track || cur_live.idbuf[2] != sector)
323      return false;
324   if(!has_side_check() || (command & 2))
325      return true;
326   if(command & 8)
327      return cur_live.idbuf[1] & 1;
328   else
329      return !(cur_live.idbuf[1] & 1);
330}
331
332bool wd177x_t::is_ready()
333{
334   return (floppy && !floppy->ready_r());
335}
336
337void wd177x_t::read_sector_start()
338{
339   if(has_ready() && !is_ready())
340      command_end();
341
342   main_state = READ_SECTOR;
343   status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY;
344   drop_drq();
345   if (has_side_select() && floppy)
346      floppy->ss_w(BIT(command, 1));
347   sub_state = has_motor() && !has_head_load() ? SPINUP : SPINUP_DONE;
348   status_type_1 = false;
349   read_sector_continue();
350}
351
352void wd177x_t::read_sector_continue()
353{
354   for(;;) {
355      switch(sub_state) {
356      case SPINUP:
357         if(!(status & S_MON)) {
358            spinup();
359            return;
360         }
361         sub_state = SPINUP_DONE;
362         break;
363
364      case SPINUP_WAIT:
365         return;
366
367      case SPINUP_DONE:
368         if(command & 4) {
369            sub_state = SETTLE_WAIT;
370            delay_cycles(t_gen, settle_time());
371            return;
372         } else {
373            sub_state = SETTLE_DONE;
374            break;
375         }
376
377      case SETTLE_WAIT:
378         return;
379
380      case SETTLE_DONE:
381         sub_state = SCAN_ID;
382         counter = 0;
383         live_start(SEARCH_ADDRESS_MARK_HEADER);
384         return;
385
386      case SCAN_ID:
387         if(!sector_matches()) {
388            live_start(SEARCH_ADDRESS_MARK_HEADER);
389            return;
390         }
391         if(cur_live.crc) {
392            status |= S_CRC;
393            live_start(SEARCH_ADDRESS_MARK_HEADER);
394            return;
395         }
396         // TODO WD2795/7 alternate sector size
397         sector_size = 128 << (cur_live.idbuf[3] & 3);
398         sub_state = SECTOR_READ;
399         live_start(SEARCH_ADDRESS_MARK_DATA);
400         return;
401
402      case SCAN_ID_FAILED:
403         status |= S_RNF;
404         command_end();
405         return;
406
407      case SECTOR_READ:
408         if(cur_live.crc)
409            status |= S_CRC;
410
411         if(command & 0x10 && !(status & S_RNF)) {
412            sector++;
413            sub_state = SETTLE_DONE;
414         } else {
415            command_end();
416            return;
417         }
418         break;
419
420      default:
421         logerror("%s: read sector unknown sub-state %d\n", ttsn().cstr(), sub_state);
422         return;
423      }
424   }
425}
426
427void wd177x_t::read_track_start()
428{
429   if(has_ready() && !is_ready())
430      command_end();
431   
432   main_state = READ_TRACK;
433   status = (status & ~(S_LOST|S_RNF)) | S_BUSY;
434   drop_drq();
435   if (has_side_select() && floppy)
436      floppy->ss_w(BIT(command, 1));
437   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
438   status_type_1 = false;
439   read_track_continue();
440}
441
442void wd177x_t::read_track_continue()
443{
444   for(;;) {
445      switch(sub_state) {
446      case SPINUP:
447         if(!(status & S_MON)) {
448            spinup();
449            return;
450         }
451         sub_state = SPINUP_DONE;
452         break;
453
454      case SPINUP_WAIT:
455         return;
456
457      case SPINUP_DONE:
458         if(command & 4) {
459            sub_state = SETTLE_WAIT;
460            delay_cycles(t_gen, settle_time());
461            return;
462
463         } else {
464            sub_state = SETTLE_DONE;
465            break;
466         }
467
468      case SETTLE_WAIT:
469         return;
470
471      case SETTLE_DONE:
472         sub_state = WAIT_INDEX;
473         return;
474
475      case WAIT_INDEX:
476         return;
477
478      case WAIT_INDEX_DONE:
479         sub_state = TRACK_DONE;
480         live_start(READ_TRACK_DATA);
481         return;
482
483      case TRACK_DONE:
484         command_end();
485         return;
486
487      default:
488         logerror("%s: read track unknown sub-state %d\n", ttsn().cstr(), sub_state);
489         return;
490      }
491   }
492}
493
494void wd177x_t::read_id_start()
495{
496   if(has_ready() && !is_ready())
497      command_end();
498   
499   main_state = READ_ID;
500   status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY;
501   drop_drq();
502   if (has_side_select() && floppy)
503      floppy->ss_w(BIT(command, 1));
504   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
505   status_type_1 = false;
506   read_id_continue();
507}
508
509void wd177x_t::read_id_continue()
510{
511   for(;;) {
512      switch(sub_state) {
513      case SPINUP:
514         if(!(status & S_MON)) {
515            spinup();
516            return;
517         }
518         sub_state = SPINUP_DONE;
519         break;
520
521      case SPINUP_WAIT:
522         return;
523
524      case SPINUP_DONE:
525         if(command & 4) {
526            sub_state = SETTLE_WAIT;
527            delay_cycles(t_gen, settle_time());
528            return;
529         } else {
530            sub_state = SETTLE_DONE;
531            break;
532         }
533
534      case SETTLE_WAIT:
535         return;
536
537      case SETTLE_DONE:
538         sub_state = SCAN_ID;
539         counter = 0;
540         live_start(SEARCH_ADDRESS_MARK_HEADER);
541         return;
542
543      case SCAN_ID:
544         command_end();
545         return;
546
547      case SCAN_ID_FAILED:
548         status |= S_RNF;
549         command_end();
550         return;
551
552      default:
553         logerror("%s: read id unknown sub-state %d\n", ttsn().cstr(), sub_state);
554         return;
555      }
556   }
557}
558
559void wd177x_t::write_track_start()
560{
561   if(has_ready() && !is_ready())
562      command_end();
563   
564   main_state = WRITE_TRACK;
565   status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY;
566   drop_drq();
567   if (has_side_select() && floppy)
568      floppy->ss_w(BIT(command, 1));
569   sub_state = has_motor()  && !has_head_load() ? SPINUP : SPINUP_DONE;
570   status_type_1 = false;
571   write_track_continue();
572}
573
574void wd177x_t::write_track_continue()
575{
576   for(;;) {
577      switch(sub_state) {
578      case SPINUP:
579         if(!(status & S_MON)) {
580            spinup();
581            return;
582         }
583         sub_state = SPINUP_DONE;
584         break;
585
586      case SPINUP_WAIT:
587         return;
588
589      case SPINUP_DONE:
590         if(command & 4) {
591            sub_state = SETTLE_WAIT;
592            delay_cycles(t_gen, settle_time());
593            return;
594         } else {
595            sub_state = SETTLE_DONE;
596            break;
597         }
598
599      case SETTLE_WAIT:
600         return;
601
602      case SETTLE_DONE:
603         set_drq();
604         sub_state = DATA_LOAD_WAIT;
605         delay_cycles(t_gen, 768);
606         return;
607
608      case DATA_LOAD_WAIT:
609         return;
610
611      case DATA_LOAD_WAIT_DONE:
612         if(drq) {
613            status |= S_LOST;
614            command_end();
615            return;
616         }
617         sub_state = WAIT_INDEX;
618         break;
619
620      case WAIT_INDEX:
621         return;
622
623      case WAIT_INDEX_DONE:
624         sub_state = TRACK_DONE;
625         live_start(WRITE_TRACK_DATA);
626         cur_live.pll.start_writing(machine().time());
627         return;
628
629      case TRACK_DONE:
630         command_end();
631         return;
632
633      default:
634         logerror("%s: write track unknown sub-state %d\n", ttsn().cstr(), sub_state);
635         return;
636      }
637   }
638}
639
640
641void wd177x_t::write_sector_start()
642{
643   if(has_ready() && !is_ready())
644      command_end();
645   
646   main_state = WRITE_SECTOR;
647   status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY;
648   drop_drq();
649   if (has_side_select() && floppy)
650      floppy->ss_w(BIT(command, 1));
651   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
652   status_type_1 = false;
653   write_sector_continue();
654}
655
656void wd177x_t::write_sector_continue()
657{
658   for(;;) {
659      switch(sub_state) {
660      case SPINUP:
661         if(!(status & S_MON)) {
662            spinup();
663            return;
664         }
665         sub_state = SPINUP_DONE;
666         break;
667
668      case SPINUP_WAIT:
669         return;
670
671      case SPINUP_DONE:
672         if(command & 4) {
673            sub_state = SETTLE_WAIT;
674            delay_cycles(t_gen, settle_time());
675            return;
676         } else {
677            sub_state = SETTLE_DONE;
678            break;
679         }
680
681      case SETTLE_WAIT:
682         return;
683
684      case SETTLE_DONE:
685         sub_state = SCAN_ID;
686         counter = 0;
687         live_start(SEARCH_ADDRESS_MARK_HEADER);
688         return;
689
690      case SCAN_ID:
691         if(!sector_matches()) {
692            live_start(SEARCH_ADDRESS_MARK_HEADER);
693            return;
694         }
695         if(cur_live.crc) {
696            status |= S_CRC;
697            live_start(SEARCH_ADDRESS_MARK_HEADER);
698            return;
699         }
700         // TODO WD2795/7 alternate sector size
701         sector_size = 128 << (cur_live.idbuf[3] & 3);
702         sub_state = SECTOR_WRITE;
703         live_start(WRITE_SECTOR_PRE);
704         return;
705
706      case SCAN_ID_FAILED:
707         status |= S_RNF;
708         command_end();
709         return;
710
711      case SECTOR_WRITE:
712         if(command & 0x10) {
713            sector++;
714            sub_state = SPINUP_DONE;
715         } else {
716            command_end();
717            return;
718         }
719         break;
720
721      default:
722         logerror("%s: write sector unknown sub-state %d\n", ttsn().cstr(), sub_state);
723         return;
724      }
725   }
726}
727
728void wd177x_t::interrupt_start()
729{
730   if(status & S_BUSY) {
731      main_state = sub_state = cur_live.state = IDLE;
732      cur_live.tm = attotime::never;
733      status &= ~S_BUSY;
734      drop_drq();
735      motor_timeout = 0;
736   }
737   
738   if(!(command & 0x0f)) {
739      intrq_cond = 0;
740   } else {
741      intrq_cond = (intrq_cond & I_IMM) | (command & 0x07);
742   }
743
744   if(intrq_cond & I_IMM) {
745      intrq = true;
746      if(!intrq_cb.isnull())
747         intrq_cb(intrq);
748   }
749
750   if(command & 0x03) {
751      logerror("%s: unhandled interrupt generation (%02x)\n", ttsn().cstr(), command);
752   }
753}
754
755void wd177x_t::general_continue()
756{
757   if(cur_live.state != IDLE) {
758      live_run();
759      if(cur_live.state != IDLE)
760         return;
761   }
762
763   switch(main_state) {
764   case IDLE:
765      break;
766   case RESTORE: case SEEK: case STEP:
767      seek_continue();
768      break;
769   case READ_SECTOR:
770      read_sector_continue();
771      break;
772   case READ_TRACK:
773      read_track_continue();
774      break;
775   case READ_ID:
776      read_id_continue();
777      break;
778   case WRITE_TRACK:
779      write_track_continue();
780      break;
781   case WRITE_SECTOR:
782      write_sector_continue();
783      break;
784   default:
785      logerror("%s: general_continue on unknown main-state %d\n", ttsn().cstr(), main_state);
786      break;
787   }
788}
789
790void wd177x_t::do_generic()
791{
792   switch(sub_state) {
793   case IDLE:
794   case SCAN_ID:
795   case SECTOR_READ:
796      break;
797
798   case SETTLE_WAIT:
799      sub_state = SETTLE_DONE;
800      break;
801
802   case SEEK_WAIT_STEP_TIME:
803      sub_state = SEEK_WAIT_STEP_TIME_DONE;
804      break;
805
806   case SEEK_WAIT_STABILIZATION_TIME:
807      sub_state = SEEK_WAIT_STABILIZATION_TIME_DONE;
808      break;
809
810   case DATA_LOAD_WAIT:
811      sub_state = DATA_LOAD_WAIT_DONE;
812      break;
813
814   default:
815      if(cur_live.tm.is_never())
816         logerror("%s: do_generic on unknown sub-state %d\n", ttsn().cstr(), sub_state);
817      break;
818   }
819}
820
821void wd177x_t::do_cmd_w()
822{
823   //  fprintf(stderr, "%s: command %02x\n", ttsn().cstr(), cmd_buffer);
824
825   // Only available command when busy is interrupt
826   if(main_state != IDLE && (cmd_buffer & 0xf0) != 0xd0) {
827      cmd_buffer = -1;
828      return;
829   }
830   command = cmd_buffer;
831   cmd_buffer = -1;
832
833   switch(command & 0xf0) {
834   case 0x00: logerror("wd1772: restore\n"); last_dir = 1; seek_start(RESTORE); break;
835   case 0x10: logerror("wd1772: seek %d\n", data); last_dir = data > track ? 0 : 1; seek_start(SEEK); break;
836   case 0x20: case 0x30: logerror("wd1772: step\n"); seek_start(STEP); break;
837   case 0x40: case 0x50: logerror("wd1772: step +\n"); last_dir = 0; seek_start(STEP); break;
838   case 0x60: case 0x70: logerror("wd1772: step -\n"); last_dir = 1; seek_start(STEP); break;
839   case 0x80: case 0x90: logerror("wd1772: read sector%s %d, %d\n", command & 0x10 ? " multiple" : "", track, sector); read_sector_start(); break;
840   case 0xa0: case 0xb0: logerror("wd1772: write sector%s %d, %d\n", command & 0x10 ? " multiple" : "", track, sector); write_sector_start(); break;
841   case 0xc0: logerror("wd1772: read id\n"); read_id_start(); break;
842   case 0xd0: logerror("wd1772: interrupt\n"); interrupt_start(); break;
843   case 0xe0: logerror("wd1772: read track %d\n", track); read_track_start(); break;
844   case 0xf0: logerror("wd1772: write track %d\n", track); write_track_start(); break;
845   }
846}
847
848void wd177x_t::cmd_w(UINT8 val)
849{
850   logerror("wd1772 cmd: %02x\n", val);
851   
852   if(intrq && !(intrq_cond & I_IMM)) {
853      intrq = false;
854      if(!intrq_cb.isnull())
855         intrq_cb(intrq);
856   }
857
858   // No more than one write in flight
859   if(cmd_buffer != -1)
860      return;
861
862   cmd_buffer = val;
863
864   delay_cycles(t_cmd, dden ? 384 : 184);
865}
866
867UINT8 wd177x_t::status_r()
868{
869   if(intrq && !(intrq_cond & I_IMM)) {
870      intrq = false;
871      if(!intrq_cb.isnull())
872         intrq_cb(intrq);
873   }
874
875   if(main_state == IDLE || status_type_1) {
876      if(floppy && floppy->idx_r())
877         status |= S_IP;
878      else
879         status &= ~S_IP;
880   } else {
881      if(drq)
882         status |= S_DRQ;
883      else
884         status &= ~S_DRQ;
885   }
886
887   if(status_type_1) {
888      status &= ~(S_TR00|S_WP);
889      if(floppy) {
890         if(floppy->wpt_r())
891            status |= S_WP;
892         if(!floppy->trk00_r())
893            status |= S_TR00;
894      }
895   }
896
897   if(has_ready()) {
898      if(!is_ready())
899         status |= S_NRDY;
900      else
901         status &= ~S_NRDY;
902   }
903
904   return status;
905}
906
907void wd177x_t::do_track_w()
908{
909   track = track_buffer;
910   track_buffer = -1;
911}
912
913void wd177x_t::track_w(UINT8 val)
914{
915   // No more than one write in flight
916   if(track_buffer != -1)
917      return;
918
919   track_buffer = val;
920   delay_cycles(t_track, dden ? 256 : 128);
921}
922
923UINT8 wd177x_t::track_r()
924{
925   return track;
926}
927
928void wd177x_t::do_sector_w()
929{
930   sector = sector_buffer;
931   sector_buffer = -1;
932}
933
934void wd177x_t::sector_w(UINT8 val)
935{
936   // No more than one write in flight
937   if(sector_buffer != -1)
938      return;
939
940   sector_buffer = val;
941   delay_cycles(t_sector, dden ? 256 : 128);
942}
943
944UINT8 wd177x_t::sector_r()
945{
946   return sector;
947}
948
949void wd177x_t::data_w(UINT8 val)
950{
951   data = val;
952   drop_drq();
953}
954
955UINT8 wd177x_t::data_r()
956{
957   drop_drq();
958   return data;
959}
960
961void wd177x_t::gen_w(int reg, UINT8 val)
962{
963   switch(reg) {
964   case 0: cmd_w(val); break;
965   case 1: track_w(val); break;
966   case 2: sector_w(val); break;
967   case 3: data_w(val); break;
968   }
969}
970
971UINT8 wd177x_t::gen_r(int reg)
972{
973   switch(reg) {
974   case 0: return status_r(); break;
975   case 1: return track_r(); break;
976   case 2: return sector_r(); break;
977   case 3: return data_r(); break;
978   }
979   return 0xff;
980}
981
982void wd177x_t::delay_cycles(emu_timer *tm, int cycles)
983{
984   tm->adjust(clocks_to_attotime(cycles));
985}
986
987void wd177x_t::spinup()
988{
989   if(command & 0x08)
990      sub_state = SPINUP_DONE;
991   else {
992      sub_state = SPINUP_WAIT;
993      counter = 0;
994   }
995
996   status |= S_MON;
997   if(floppy)
998      floppy->mon_w(0);
999
1000}
1001
1002void wd177x_t::index_callback(floppy_image_device *floppy, int state)
1003{
1004   live_sync();
1005
1006   if(!state) {
1007      general_continue();
1008      return;
1009   }
1010
1011   if(intrq_cond & I_IDX) {
1012      intrq = true;
1013      if(!intrq_cb.isnull())
1014         intrq_cb(intrq);
1015   }
1016
1017   switch(sub_state) {
1018   case IDLE:
1019      if(has_motor()) {
1020         motor_timeout ++;
1021         if(motor_timeout >= 5) {
1022            status &= ~S_MON;
1023            if(floppy)
1024               floppy->mon_w(1);
1025         }
1026      }
1027      break;
1028
1029   case SPINUP:
1030      break;
1031
1032   case SPINUP_WAIT:
1033      counter++;
1034      if(counter == 6) {
1035         sub_state = SPINUP_DONE;
1036         if(status_type_1)
1037            status |= S_SPIN;
1038      }
1039      break;
1040
1041   case SPINUP_DONE:
1042   case SETTLE_WAIT:
1043   case SETTLE_DONE:
1044   case DATA_LOAD_WAIT:
1045   case DATA_LOAD_WAIT_DONE:
1046   case SEEK_MOVE:
1047   case SEEK_WAIT_STEP_TIME:
1048   case SEEK_WAIT_STEP_TIME_DONE:
1049   case SEEK_WAIT_STABILIZATION_TIME:
1050   case SEEK_WAIT_STABILIZATION_TIME_DONE:
1051   case SEEK_DONE:
1052   case WAIT_INDEX_DONE:
1053   case SCAN_ID_FAILED:
1054   case SECTOR_READ:
1055   case SECTOR_WRITE:
1056      break;
1057
1058   case SCAN_ID:
1059      counter++;
1060      if(counter == 5) {
1061         sub_state = SCAN_ID_FAILED;
1062         live_abort();
1063      }
1064      break;
1065
1066   case WAIT_INDEX:
1067      sub_state = WAIT_INDEX_DONE;
1068      break;
1069
1070   case TRACK_DONE:
1071      live_abort();
1072      break;
1073
1074   default:
1075      logerror("%s: Index pulse on unknown sub-state %d\n", ttsn().cstr(), sub_state);
1076      break;
1077   }
1078
1079   general_continue();
1080}
1081
1082bool wd177x_t::intrq_r()
1083{
1084   return intrq;
1085}
1086
1087bool wd177x_t::drq_r()
1088{
1089   return drq;
1090}
1091
1092bool wd177x_t::hld_r()
1093{
1094   return hld;
1095}
1096
1097void wd177x_t::hlt_w(bool state)
1098{
1099   hlt = state;
1100}
1101
1102bool wd177x_t::enp_r()
1103{
1104   return enp;
1105}
1106
1107void wd177x_t::live_start(int state)
1108{
1109   cur_live.tm = machine().time();
1110   cur_live.state = state;
1111   cur_live.next_state = -1;
1112   cur_live.shift_reg = 0;
1113   cur_live.crc = 0xffff;
1114   cur_live.bit_counter = 0;
1115   cur_live.data_separator_phase = false;
1116   cur_live.data_reg = 0;
1117   cur_live.previous_type = live_info::PT_NONE;
1118   cur_live.data_bit_context = false;
1119   cur_live.byte_counter = 0;
1120   cur_live.pll.reset(cur_live.tm);
1121   cur_live.pll.set_clock(clocks_to_attotime(1));
1122   checkpoint_live = cur_live;
1123
1124   live_run();
1125}
1126
1127void wd177x_t::checkpoint()
1128{
1129   cur_live.pll.commit(floppy, cur_live.tm);
1130   checkpoint_live = cur_live;
1131}
1132
1133void wd177x_t::rollback()
1134{
1135   cur_live = checkpoint_live;
1136}
1137
1138void wd177x_t::live_delay(int state)
1139{
1140   cur_live.next_state = state;
1141   t_gen->adjust(cur_live.tm - machine().time());
1142}
1143
1144void wd177x_t::live_sync()
1145{
1146   if(!cur_live.tm.is_never()) {
1147      if(cur_live.tm > machine().time()) {
1148         //          fprintf(stderr, "%s: Rolling back and replaying (%s)\n", ttsn().cstr(), tts(cur_live.tm).cstr());
1149         rollback();
1150         live_run(machine().time());
1151         cur_live.pll.commit(floppy, cur_live.tm);
1152      } else {
1153         //          fprintf(stderr, "%s: Committing (%s)\n", ttsn().cstr(), tts(cur_live.tm).cstr());
1154         cur_live.pll.commit(floppy, cur_live.tm);
1155         if(cur_live.next_state != -1) {
1156            cur_live.state = cur_live.next_state;
1157            cur_live.next_state = -1;
1158         }
1159         if(cur_live.state == IDLE) {
1160            cur_live.pll.stop_writing(floppy, cur_live.tm);
1161            cur_live.tm = attotime::never;
1162         }
1163      }
1164      cur_live.next_state = -1;
1165      checkpoint();
1166   }
1167}
1168
1169void wd177x_t::live_abort()
1170{
1171   if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
1172      rollback();
1173      live_run(machine().time());
1174   }
1175
1176   cur_live.pll.stop_writing(floppy, cur_live.tm);
1177   cur_live.tm = attotime::never;
1178   cur_live.state = IDLE;
1179   cur_live.next_state = -1;
1180}
1181
1182bool wd177x_t::read_one_bit(attotime limit)
1183{
1184   int bit = cur_live.pll.get_next_bit(cur_live.tm, floppy, limit);
1185   if(bit < 0)
1186      return true;
1187   cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
1188   cur_live.bit_counter++;
1189   if(cur_live.data_separator_phase) {
1190      cur_live.data_reg = (cur_live.data_reg << 1) | bit;
1191      if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
1192         cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
1193      else
1194         cur_live.crc = cur_live.crc << 1;
1195   }
1196   cur_live.data_separator_phase = !cur_live.data_separator_phase;
1197   return false;
1198}
1199
1200bool wd177x_t::write_one_bit(attotime limit)
1201{
1202   bool bit = cur_live.shift_reg & 0x8000;
1203   if(cur_live.pll.write_next_bit(bit, cur_live.tm, floppy, limit))
1204      return true;
1205   if(cur_live.bit_counter & 1) {
1206      if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
1207         cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
1208      else
1209         cur_live.crc = cur_live.crc << 1;
1210   }
1211   cur_live.shift_reg = cur_live.shift_reg << 1;
1212   cur_live.bit_counter--;
1213   return false;
1214}
1215
1216void wd177x_t::live_write_raw(UINT16 raw)
1217{
1218   //  logerror("write %04x %04x\n", raw, cur_live.crc);
1219   cur_live.shift_reg = raw;
1220   cur_live.data_bit_context = raw & 1;
1221}
1222
1223void wd177x_t::live_write_mfm(UINT8 mfm)
1224{
1225   bool context = cur_live.data_bit_context;
1226   UINT16 raw = 0;
1227   for(int i=0; i<8; i++) {
1228      bool bit = mfm & (0x80 >> i);
1229      if(!(bit || context))
1230         raw |= 0x8000 >> (2*i);
1231      if(bit)
1232         raw |= 0x4000 >> (2*i);
1233      context = bit;
1234   }
1235   cur_live.shift_reg = raw;
1236   cur_live.data_bit_context = context;
1237   //  logerror("write %02x   %04x %04x\n", mfm, cur_live.crc, raw);
1238}
1239
1240void wd177x_t::live_run(attotime limit)
1241{
1242   if(cur_live.state == IDLE || cur_live.next_state != -1)
1243      return;
1244
1245   if(limit == attotime::never) {
1246      if(floppy)
1247         limit = floppy->time_next_index();
1248      if(limit == attotime::never) {
1249         // Happens when there's no disk or if the wd is not
1250         // connected to a drive, hence no index pulse. Force a
1251         // sync from time to time in that case, so that the main
1252         // cpu timeout isn't too painful.  Avoids looping into
1253         // infinity looking for data too.
1254
1255         limit = machine().time() + attotime::from_msec(1);
1256         t_gen->adjust(attotime::from_msec(1));
1257      }
1258   }
1259
1260   //  fprintf(stderr, "%s: live_run(%s)\n", ttsn().cstr(), tts(limit).cstr());
1261
1262   for(;;) {
1263      switch(cur_live.state) {
1264      case SEARCH_ADDRESS_MARK_HEADER:
1265         if(read_one_bit(limit))
1266            return;
1267#if 0
1268         fprintf(stderr, "%s: shift = %04x data=%02x c=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1269               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1270               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1271               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1272               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1273               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1274               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1275               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1276               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1277               cur_live.bit_counter);
1278#endif
1279
1280         if(cur_live.shift_reg == 0x4489) {
1281            cur_live.crc = 0x443b;
1282            cur_live.data_separator_phase = false;
1283            cur_live.bit_counter = 0;
1284            cur_live.state = READ_HEADER_BLOCK_HEADER;
1285         }
1286         break;
1287
1288      case READ_HEADER_BLOCK_HEADER: {
1289         if(read_one_bit(limit))
1290            return;
1291#if 0
1292         fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1293               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1294               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1295               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1296               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1297               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1298               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1299               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1300               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1301               cur_live.bit_counter);
1302#endif
1303         if(cur_live.bit_counter & 15)
1304            break;
1305
1306         int slot = cur_live.bit_counter >> 4;
1307
1308         if(slot < 3) {
1309            if(cur_live.shift_reg != 0x4489)
1310               cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
1311            break;
1312         }
1313         if(cur_live.data_reg != 0xfe && cur_live.data_reg != 0xff) {
1314            cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
1315            break;
1316         }
1317
1318         cur_live.bit_counter = 0;
1319
1320         if(main_state == READ_ID)
1321            cur_live.state = READ_ID_BLOCK_TO_DMA;
1322         else
1323            cur_live.state = READ_ID_BLOCK_TO_LOCAL;
1324
1325         break;
1326      }
1327
1328      case READ_ID_BLOCK_TO_LOCAL: {
1329         if(read_one_bit(limit))
1330            return;
1331         if(cur_live.bit_counter & 15)
1332            break;
1333         int slot = (cur_live.bit_counter >> 4)-1;
1334         cur_live.idbuf[slot] = cur_live.data_reg;
1335         if(slot == 5) {
1336            live_delay(IDLE);
1337            return;
1338         }
1339         break;
1340      }
1341
1342      case READ_ID_BLOCK_TO_DMA: {
1343         if(read_one_bit(limit))
1344            return;
1345         if(cur_live.bit_counter & 15)
1346            break;
1347         live_delay(READ_ID_BLOCK_TO_DMA_BYTE);
1348         return;
1349      }
1350
1351      case READ_ID_BLOCK_TO_DMA_BYTE:
1352         data = cur_live.data_reg;
1353         if(cur_live.bit_counter == 16)
1354            sector = data;
1355         set_drq();
1356
1357         if(cur_live.bit_counter == 16*6) {
1358            // Already synchronous
1359            cur_live.state = IDLE;
1360            return;
1361         }
1362
1363         cur_live.state = READ_ID_BLOCK_TO_DMA;
1364         checkpoint();
1365         break;
1366
1367      case SEARCH_ADDRESS_MARK_DATA:
1368         if(read_one_bit(limit))
1369            return;
1370#if 0
1371         fprintf(stderr, "%s: shift = %04x data=%02x c=%d.%x\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1372               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1373               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1374               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1375               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1376               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1377               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1378               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1379               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1380               cur_live.bit_counter >> 4, cur_live.bit_counter & 15);
1381#endif
1382         if(cur_live.bit_counter > 43*16) {
1383            live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1384            return;
1385         }
1386
1387         if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg == 0x4489) {
1388            cur_live.crc = 0x443b;
1389            cur_live.data_separator_phase = false;
1390            cur_live.bit_counter = 0;
1391            cur_live.state = READ_DATA_BLOCK_HEADER;
1392         }
1393         break;
1394
1395      case READ_DATA_BLOCK_HEADER: {
1396         if(read_one_bit(limit))
1397            return;
1398#if 0
1399         fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1400               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1401               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1402               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1403               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1404               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1405               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1406               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1407               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1408               cur_live.bit_counter);
1409#endif
1410         if(cur_live.bit_counter & 15)
1411            break;
1412
1413         int slot = cur_live.bit_counter >> 4;
1414
1415         if(slot < 3) {
1416            if(cur_live.shift_reg != 0x4489) {
1417               live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1418               return;
1419            }
1420            break;
1421         }
1422         if((cur_live.data_reg & 0xfe) != 0xfa && (cur_live.data_reg & 0xfe) != 0xfc) {
1423            live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1424            return;
1425         }
1426
1427         cur_live.bit_counter = 0;
1428         cur_live.state = READ_SECTOR_DATA;
1429         break;
1430      }
1431
1432      case SEARCH_ADDRESS_MARK_DATA_FAILED:
1433         status |= S_RNF;
1434         cur_live.state = IDLE;
1435         return;
1436
1437      case READ_SECTOR_DATA: {
1438         if(read_one_bit(limit))
1439            return;
1440         if(cur_live.bit_counter & 15)
1441            break;
1442         int slot = (cur_live.bit_counter >> 4)-1;
1443         if(slot < sector_size) {
1444            // Sector data
1445            live_delay(READ_SECTOR_DATA_BYTE);
1446            return;
1447
1448         } else if(slot < sector_size+2) {
1449            // CRC
1450            if(slot == sector_size+1) {
1451               live_delay(IDLE);
1452               return;
1453            }
1454         }
1455
1456         break;
1457      }
1458
1459      case READ_SECTOR_DATA_BYTE:
1460         data = cur_live.data_reg;
1461         set_drq();
1462         cur_live.state = READ_SECTOR_DATA;
1463         checkpoint();
1464         break;
1465
1466      case READ_TRACK_DATA: {
1467         if(read_one_bit(limit))
1468            return;
1469         if(cur_live.bit_counter != 16
1470            && cur_live.shift_reg != 0x4489
1471            && cur_live.shift_reg != 0x5224)
1472            break;
1473
1474         // Incorrect, hmmm
1475         // Probably >2 + not just after a sync if <16
1476
1477         // Transitions 00..00 -> 4489.4489.4489 at varied syncs:
1478         //  0: 00.00.14.a1   1: ff.fe.c2.a1   2: 00.01.14.a1   3: ff.fc.c2.a1
1479         //  4: 00.02.14.a1   5: ff.f8.c2.a1   6: 00.05.14.a1   7: ff.f0.c2.a1
1480         //  8: 00.00.0a.a1   9: ff.ff.e1.a1  10: 00.00.14.a1  11: ff.ff.ce.a1
1481         // 12: 00.00.14.a1  13: ff.ff.c2.a1  14: 00.00.14.a1  15: ff.ff.c2.a1
1482
1483         bool output_byte = cur_live.bit_counter > 5;
1484
1485         cur_live.data_separator_phase = false;
1486         cur_live.bit_counter = 0;
1487
1488         if(output_byte) {
1489            live_delay(READ_TRACK_DATA_BYTE);
1490            return;
1491         }
1492
1493         break;
1494      }
1495
1496      case READ_TRACK_DATA_BYTE:
1497         data = cur_live.data_reg;
1498         set_drq();
1499         cur_live.state = READ_TRACK_DATA;
1500         checkpoint();
1501         break;
1502
1503      case WRITE_TRACK_DATA:
1504         if(drq) {
1505            status |= S_LOST;
1506            data = 0;
1507         }
1508
1509         switch(data) {
1510         case 0xf5:
1511            live_write_raw(0x4489);
1512            cur_live.crc = 0x968b; // Ensures that the crc is cdb4 after writing the byte
1513            cur_live.previous_type = live_info::PT_NONE;
1514            break;
1515         case 0xf6:
1516            cur_live.previous_type = live_info::PT_NONE;
1517            live_write_raw(0x5224);
1518            break;
1519         case 0xf7:
1520            if(cur_live.previous_type == live_info::PT_CRC_2) {
1521               cur_live.previous_type = live_info::PT_NONE;
1522               live_write_mfm(0xf7);
1523            } else {
1524               cur_live.previous_type = live_info::PT_CRC_1;
1525               live_write_mfm(cur_live.crc >> 8);
1526            }
1527            break;
1528         default:
1529            cur_live.previous_type = live_info::PT_NONE;
1530            live_write_mfm(data);
1531            break;
1532         }
1533         set_drq();
1534         cur_live.state = WRITE_BYTE;
1535         cur_live.bit_counter = 16;
1536         checkpoint();
1537         break;
1538
1539      case WRITE_BYTE:
1540         if(write_one_bit(limit))
1541            return;
1542         if(cur_live.bit_counter == 0) {
1543            live_delay(WRITE_BYTE_DONE);
1544            return;
1545         }
1546         break;
1547
1548      case WRITE_BYTE_DONE:
1549         switch(sub_state) {
1550         case TRACK_DONE:
1551            if(cur_live.previous_type == live_info::PT_CRC_1) {
1552               cur_live.previous_type = live_info::PT_CRC_2;
1553               live_write_mfm(cur_live.crc >> 8);
1554               cur_live.state = WRITE_BYTE;
1555               cur_live.bit_counter = 16;
1556               checkpoint();
1557            } else
1558               cur_live.state = WRITE_TRACK_DATA;
1559            break;
1560
1561         case SECTOR_WRITE:
1562            cur_live.state = WRITE_BYTE;
1563            cur_live.bit_counter = 16;
1564            cur_live.byte_counter++;
1565            if(cur_live.byte_counter <= 11)
1566               live_write_mfm(0x00);
1567            else if(cur_live.byte_counter == 12) {
1568               cur_live.crc = 0xffff;
1569               live_write_raw(0x4489);
1570            } else if(cur_live.byte_counter <= 14)
1571               live_write_raw(0x4489);
1572            else if(cur_live.byte_counter == 15)
1573               live_write_mfm(command & 1 ? 0xf8 : 0xfb);
1574            else if(cur_live.byte_counter <= sector_size + 16-2) {
1575               if(drq) {
1576                  status |= S_LOST;
1577                  data = 0;
1578               }
1579               live_write_mfm(data);
1580               set_drq();
1581            } else if(cur_live.byte_counter == sector_size + 16-1) {
1582               if(drq) {
1583                  status |= S_LOST;
1584                  data = 0;
1585               }
1586               live_write_mfm(data);
1587            } else if(cur_live.byte_counter <= sector_size + 16+1)
1588               live_write_mfm(cur_live.crc >> 8);
1589            else if(cur_live.byte_counter == sector_size + 16+2)
1590               // Is that correct?  It seems required (try ST formatting)
1591               live_write_mfm(0xff);
1592            else {
1593               cur_live.pll.stop_writing(floppy, cur_live.tm);
1594               cur_live.state = IDLE;
1595               return;
1596            }
1597
1598            checkpoint();
1599            break;
1600
1601         default:
1602            logerror("%s: Unknown sub state %d in WRITE_BYTE_DONE\n", tts(cur_live.tm).cstr(), sub_state);
1603            live_abort();
1604            return;
1605         }
1606         break;
1607
1608      case WRITE_SECTOR_PRE:
1609         if(read_one_bit(limit))
1610            return;
1611         if(cur_live.bit_counter != 16)
1612            break;
1613         live_delay(WRITE_SECTOR_PRE_BYTE);
1614         return;
1615
1616      case WRITE_SECTOR_PRE_BYTE:
1617         cur_live.state = WRITE_SECTOR_PRE;
1618         cur_live.byte_counter++;
1619         cur_live.bit_counter = 0;
1620         switch(cur_live.byte_counter) {
1621         case 2:
1622            set_drq();
1623            checkpoint();
1624            break;
1625         case 11:
1626            if(drq) {
1627               status |= S_LOST;
1628               cur_live.state = IDLE;
1629               return;
1630            }
1631            break;
1632         case 22:
1633            cur_live.state = WRITE_BYTE;
1634            cur_live.bit_counter = 16;
1635            cur_live.byte_counter = 0;
1636            cur_live.data_bit_context = cur_live.data_reg & 1;
1637            cur_live.pll.start_writing(cur_live.tm);
1638            live_write_mfm(0x00);
1639            break;
1640         }
1641         break;
1642
1643      default:
1644         logerror("%s: Unknown live state %d\n", tts(cur_live.tm).cstr(), cur_live.state);
1645         return;
1646      }
1647   }
1648}
1649
1650void wd177x_t::set_drq()
1651{
1652   if(drq)
1653      status |= S_LOST;
1654   else {
1655      drq = true;
1656      if(!drq_cb.isnull())
1657         drq_cb(true);
1658   }
1659}
1660
1661void wd177x_t::drop_drq()
1662{
1663   if(drq) {
1664      drq = false;
1665      if(!drq_cb.isnull())
1666         drq_cb(false);
1667   }
1668}
1669
1670void wd177x_t::pll_t::set_clock(attotime period)
1671{
1672   for(int i=0; i<42; i++)
1673      delays[i] = period*(i+1);
1674}
1675
1676void wd177x_t::pll_t::reset(attotime when)
1677{
1678   counter = 0;
1679   increment = 128;
1680   transition_time = 0xffff;
1681   history = 0x80;
1682   slot = 0;
1683   ctime = when;
1684   phase_add = 0x00;
1685   phase_sub = 0x00;
1686   freq_add  = 0x00;
1687   freq_sub  = 0x00;
1688   write_position = 0;
1689   write_start_time = attotime::never;
1690}
1691
1692int wd177x_t::pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit)
1693{
1694   attotime when = floppy ? floppy->get_next_transition(ctime) : attotime::never;
1695#if 0
1696   if(!when.is_never())
1697      fprintf(stderr, "transition_time=%s\n", tts(when).cstr());
1698#endif
1699
1700   for(;;) {
1701      //      fprintf(stderr, "slot=%2d, counter=%03x\n", slot, counter);
1702      attotime etime = ctime+delays[slot];
1703      //      fprintf(stderr, "etime=%s\n", tts(etime).cstr());
1704      if(etime > limit)
1705         return -1;
1706      if(transition_time == 0xffff && !when.is_never() && etime >= when)
1707         transition_time = counter;
1708      if(slot < 8) {
1709         UINT8 mask = 1 << slot;
1710         if(phase_add & mask)
1711            counter += 226;
1712         else if(phase_sub & mask)
1713            counter += 30;
1714         else
1715            counter += increment;
1716
1717         if((freq_add & mask) && increment < 140)
1718            increment++;
1719         else if((freq_sub & mask) && increment > 117)
1720            increment--;
1721      } else
1722         counter += increment;
1723
1724      slot++;
1725      tm = etime;
1726      if(counter & 0x800)
1727         break;
1728   }
1729   //  fprintf(stderr, "first transition, time=%03x, inc=%3d\n", transition_time, increment);
1730   int bit = transition_time != 0xffff;
1731
1732   if(transition_time != 0xffff) {
1733      static const UINT8 pha[8] = { 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 };
1734      static const UINT8 phs[8] = { 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf };
1735      static const UINT8 freqa[4][8] = {
1736         { 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 },
1737         { 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
1738         { 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
1739         { 0, 0, 0, 0, 0, 0, 0, 0 }
1740      };
1741      static const UINT8 freqs[4][8] = {
1742         { 0, 0, 0, 0, 0, 0, 0, 0 },
1743         { 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
1744         { 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
1745         { 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf },
1746      };
1747
1748      int cslot = transition_time >> 8;
1749      phase_add = pha[cslot];
1750      phase_sub = phs[cslot];
1751      int way = transition_time & 0x400 ? 1 : 0;
1752      if(history & 0x80)
1753         history = way ? 0x80 : 0x83;
1754      else if(history & 0x40)
1755         history = way ? history & 2 : (history & 2) | 1;
1756      freq_add = freqa[history & 3][cslot];
1757      freq_sub = freqs[history & 3][cslot];
1758      history = way ? (history >> 1) | 2 : history >> 1;
1759
1760   } else
1761      phase_add = phase_sub = freq_add = freq_sub = 0;
1762
1763   counter &= 0x7ff;
1764
1765   ctime = tm;
1766   transition_time = 0xffff;
1767   slot = 0;
1768
1769   return bit;
1770}
1771
1772void wd177x_t::pll_t::start_writing(attotime tm)
1773{
1774   write_start_time = tm;
1775   write_position = 0;
1776}
1777
1778void wd177x_t::pll_t::stop_writing(floppy_image_device *floppy, attotime tm)
1779{
1780   commit(floppy, tm);
1781   write_start_time = attotime::never;
1782}
1783
1784bool wd177x_t::pll_t::write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit)
1785{
1786   if(write_start_time.is_never()) {
1787      write_start_time = ctime;
1788      write_position = 0;
1789   }
1790
1791   for(;;) {
1792      attotime etime = ctime+delays[slot];
1793      if(etime > limit)
1794         return true;
1795      UINT16 pre_counter = counter;
1796      counter += increment;
1797      if(bit && !(pre_counter & 0x400) && (counter & 0x400))
1798         if(write_position < ARRAY_LENGTH(write_buffer))
1799            write_buffer[write_position++] = etime;
1800      slot++;
1801      tm = etime;
1802      if(counter & 0x800)
1803         break;
1804   }
1805
1806   counter &= 0x7ff;
1807
1808   ctime = tm;
1809   slot = 0;
1810
1811   return false;
1812}
1813
1814void wd177x_t::pll_t::commit(floppy_image_device *floppy, attotime tm)
1815{
1816   if(write_start_time.is_never() || tm == write_start_time)
1817      return;
1818
1819   if(floppy)
1820      floppy->write_flux(write_start_time, tm, write_position, write_buffer);
1821   write_start_time = tm;
1822   write_position = 0;
1823}
1824
1825int wd177x_t::step_time(int mode) const
1826{
1827   const static int step_times[4] = { 48000, 96000, 160000, 240000 };
1828   return step_times[mode];
1829}
1830
1831int wd177x_t::settle_time() const
1832{
1833   return 240000;
1834}
1835
1836bool wd177x_t::has_ready() const
1837{
1838   return false;
1839}
1840
1841bool wd177x_t::has_head_load() const
1842{
1843   return false;
1844}
1845
1846bool wd177x_t::has_side_check() const
1847{
1848   return false;
1849}
1850
1851bool wd177x_t::has_side_select() const
1852{
1853   return false;
1854}
1855
1856bool wd177x_t::has_sector_length_select() const
1857{
1858   return false;
1859}
1860
1861bool wd177x_t::has_precompensation() const
1862{
1863   return false;
1864}
1865
1866fd1771_t::fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1771x, "FD1771", tag, owner, clock)
1867{
1868}
1869
1870fd1793_t::fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1793x, "FD1793", tag, owner, clock)
1871{
1872}
1873
1874fd1797_t::fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1797x, "FD1797", tag, owner, clock)
1875{
1876}
1877
1878wd2793_t::wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD2793x, "WD2793", tag, owner, clock)
1879{
1880}
1881
1882wd2797_t::wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD2797x, "WD2797", tag, owner, clock)
1883{
1884}
1885
1886wd1770_t::wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1770x, "WD1770", tag, owner, clock)
1887{
1888}
1889
1890wd1772_t::wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1772x, "WD1772", tag, owner, clock)
1891{
1892}
1893
1894int wd1772_t::step_time(int mode) const
1895{
1896   const static int step_times[4] = { 48000, 96000, 16000, 24000 };
1897   return step_times[mode];
1898}
1899
1900int wd1772_t::settle_time() const
1901{
1902   return 120000;
1903}
1904
1905wd1773_t::wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1773x, "WD1773", tag, owner, clock)
1906{
1907}
trunk/src/emu/machine/wd1772.h
r19166r19167
1#ifndef WD1772_H
2#define WD1772_H
3
4#include "emu.h"
5#include "imagedev/floppy.h"
6
7#define MCFG_FD1771x_ADD(_tag, _clock)  \
8   MCFG_DEVICE_ADD(_tag, FD1771x, _clock)
9
10#define MCFG_FD1793x_ADD(_tag, _clock)  \
11   MCFG_DEVICE_ADD(_tag, FD1793x, _clock)
12
13#define MCFG_FD1797x_ADD(_tag, _clock)  \
14   MCFG_DEVICE_ADD(_tag, FD1797x, _clock)
15
16#define MCFG_WD2793x_ADD(_tag, _clock)  \
17   MCFG_DEVICE_ADD(_tag, WD2793x, _clock)
18
19#define MCFG_WD2797x_ADD(_tag, _clock)  \
20   MCFG_DEVICE_ADD(_tag, WD2797x, _clock)
21
22#define MCFG_WD1770x_ADD(_tag, _clock)  \
23   MCFG_DEVICE_ADD(_tag, WD1770x, _clock)
24
25#define MCFG_WD1772x_ADD(_tag, _clock)  \
26   MCFG_DEVICE_ADD(_tag, WD1772x, _clock)
27
28#define MCFG_WD1773x_ADD(_tag, _clock)  \
29   MCFG_DEVICE_ADD(_tag, WD1773x, _clock)
30
31class wd177x_t : public device_t {
32public:
33   typedef delegate<void (bool state)> line_cb;
34
35   wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
36
37   void dden_w(bool dden);
38   void set_floppy(floppy_image_device *floppy);
39   void setup_intrq_cb(line_cb cb);
40   void setup_drq_cb(line_cb cb);
41   void setup_hld_cb(line_cb cb);
42   void setup_enp_cb(line_cb cb);
43
44   void cmd_w(UINT8 val);
45   UINT8 status_r();
46   DECLARE_READ8_MEMBER( status_r ) { return status_r(); }
47   DECLARE_WRITE8_MEMBER( cmd_w ) { cmd_w(data); }
48
49   void track_w(UINT8 val);
50   UINT8 track_r();
51   DECLARE_READ8_MEMBER( track_r ) { return track_r(); }
52   DECLARE_WRITE8_MEMBER( track_w ) { track_w(data); }
53
54   void sector_w(UINT8 val);
55   UINT8 sector_r();
56   DECLARE_READ8_MEMBER( sector_r ) { return sector_r(); }
57   DECLARE_WRITE8_MEMBER( sector_w ) { sector_w(data); }
58
59   void data_w(UINT8 val);
60   UINT8 data_r();
61   DECLARE_READ8_MEMBER( data_r ) { return data_r(); }
62   DECLARE_WRITE8_MEMBER( data_w ) { data_w(data); }
63
64   void gen_w(int reg, UINT8 val);
65   UINT8 gen_r(int reg);
66   DECLARE_READ8_MEMBER( read ) { return gen_r(offset);}
67   DECLARE_WRITE8_MEMBER( write ) { gen_w(offset,data); }
68
69   bool intrq_r();
70   bool drq_r();
71
72   bool hld_r();
73   void hlt_w(bool state);
74
75   bool enp_r();
76
77protected:
78   virtual void device_start();
79   virtual void device_reset();
80   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
81
82   virtual bool has_ready() const;
83   virtual bool has_motor() const = 0;
84   virtual bool has_head_load() const;
85   virtual bool has_side_check() const;
86   virtual bool has_side_select() const;
87   virtual bool has_sector_length_select() const;
88   virtual bool has_precompensation() const;
89   virtual int step_time(int mode) const;
90   virtual int settle_time() const;
91
92private:
93   enum { TM_GEN, TM_CMD, TM_TRACK, TM_SECTOR };
94
95   //  State machine general behaviour:
96   //
97   //  There are three levels of state.
98   //
99   //  Main state is associated to (groups of) commands.  They're set
100   //  by a *_start() function below, and the associated _continue()
101   //  function can then be called at pretty much any time.
102   //
103   //  Sub state is the state of execution within a command.  The
104   //  principle is that the *_start() function selects the initial
105   //  substate, then the *_continue() function decides what to do,
106   //  possibly changing state.  Eventually it can:
107   //  - decide to wait for an event (timer, index)
108   //  - end the command with command_end()
109   //  - start a live state (see below)
110   //
111   //  In the first case, it must first switch to a waiting
112   //  sub-state, then return.  The waiting sub-state must just
113   //  return immediatly when *_continue is called.  Eventually the
114   //  event handler function will advance the state machine to
115   //  another sub-state, and things will continue synchronously.
116   //
117   //  On command end it's also supposed to return immediatly.
118   //
119   //  The last option is to switch to the next sub-state, start a
120   //  live state with live_start() then return.  The next sub-state
121   //  will only be called once the live state is finished.
122   //
123   //  Live states change continually depending on the disk contents
124   //  until the next externally discernable event is found.  They
125   //  are checkpointing, run until an event is found, then they wait
126   //  for it.  When an event eventually happen the the changes are
127   //  either committed or replayed until the sync event time.
128   //
129   //  The transition to IDLE is only done on a synced event.  Some
130   //  other transitions, such as activating drq, are also done after
131   //  syncing without exiting live mode.  Syncing in live mode is
132   //  done by calling live_delay() with the state to change to after
133   //  syncing.
134
135   enum {
136      // General "doing nothing" state
137      IDLE,
138
139      // Main states - the commands
140      RESTORE,
141      SEEK,
142      STEP,
143      READ_SECTOR,
144      READ_TRACK,
145      READ_ID,
146      WRITE_TRACK,
147      WRITE_SECTOR,
148
149      // Sub states
150
151      SPINUP,
152      SPINUP_WAIT,
153      SPINUP_DONE,
154
155      SETTLE_WAIT,
156      SETTLE_DONE,
157
158      DATA_LOAD_WAIT,
159      DATA_LOAD_WAIT_DONE,
160
161      SEEK_MOVE,
162      SEEK_WAIT_STEP_TIME,
163      SEEK_WAIT_STEP_TIME_DONE,
164      SEEK_WAIT_STABILIZATION_TIME,
165      SEEK_WAIT_STABILIZATION_TIME_DONE,
166      SEEK_DONE,
167
168      WAIT_INDEX,
169      WAIT_INDEX_DONE,
170
171      SCAN_ID,
172      SCAN_ID_FAILED,
173
174      SECTOR_READ,
175      SECTOR_WRITE,
176      TRACK_DONE,
177
178      // Live states
179
180      SEARCH_ADDRESS_MARK_HEADER,
181      READ_HEADER_BLOCK_HEADER,
182      READ_DATA_BLOCK_HEADER,
183      READ_ID_BLOCK_TO_LOCAL,
184      READ_ID_BLOCK_TO_DMA,
185      READ_ID_BLOCK_TO_DMA_BYTE,
186      SEARCH_ADDRESS_MARK_DATA,
187      SEARCH_ADDRESS_MARK_DATA_FAILED,
188      READ_SECTOR_DATA,
189      READ_SECTOR_DATA_BYTE,
190      READ_TRACK_DATA,
191      READ_TRACK_DATA_BYTE,
192      WRITE_TRACK_DATA,
193      WRITE_BYTE,
194      WRITE_BYTE_DONE,
195      WRITE_SECTOR_PRE,
196      WRITE_SECTOR_PRE_BYTE,
197   };
198
199   struct pll_t {
200      UINT16 counter;
201      UINT16 increment;
202      UINT16 transition_time;
203      UINT8 history;
204      UINT8 slot;
205      UINT8 phase_add, phase_sub, freq_add, freq_sub;
206      attotime ctime;
207
208      attotime delays[42];
209
210      attotime write_start_time;
211      attotime write_buffer[32];
212      int write_position;
213
214      void set_clock(attotime period);
215      void reset(attotime when);
216      int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
217      bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit);
218      void start_writing(attotime tm);
219      void commit(floppy_image_device *floppy, attotime tm);
220      void stop_writing(floppy_image_device *floppy, attotime tm);
221   };
222
223   struct live_info {
224      enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
225
226      attotime tm;
227      int state, next_state;
228      UINT16 shift_reg;
229      UINT16 crc;
230      int bit_counter, byte_counter, previous_type;
231      bool data_separator_phase, data_bit_context;
232      UINT8 data_reg;
233      UINT8 idbuf[6];
234      pll_t pll;
235   };
236
237   enum {
238      S_BUSY = 0x01,
239      S_DRQ  = 0x02,
240      S_IP   = 0x02,
241      S_TR00 = 0x04,
242      S_LOST = 0x04,
243      S_CRC  = 0x08,
244      S_RNF  = 0x10,
245      S_HLD  = 0x20,
246      S_SPIN = 0x20, // WD1770, WD1772
247      S_DDM  = 0x20,
248      S_WF   = 0x20, // WD1773
249      S_WP   = 0x40,
250      S_NRDY = 0x80,
251      S_MON  = 0x80  // WD1770, WD1772
252   };
253
254   enum {
255      I_RDY = 0x01,
256      I_NRDY = 0x02,
257      I_IDX = 0x04,
258      I_IMM = 0x08
259   };
260
261   floppy_image_device *floppy;
262
263   emu_timer *t_gen, *t_cmd, *t_track, *t_sector;
264
265   bool dden, status_type_1, intrq, drq, hld, hlt, enp;
266   int main_state, sub_state;
267   UINT8 command, track, sector, data, status, intrq_cond;
268   int last_dir;
269
270   int counter, motor_timeout, sector_size;
271
272   int cmd_buffer, track_buffer, sector_buffer;
273
274   live_info cur_live, checkpoint_live;
275   line_cb intrq_cb, drq_cb, hld_cb, enp_cb;
276
277   static astring tts(attotime t);
278   astring ttsn();
279
280   void delay_cycles(emu_timer *tm, int cycles);
281
282   // Device timer subfunctions
283   void do_cmd_w();
284   void do_track_w();
285   void do_sector_w();
286   void do_generic();
287
288
289   // Main-state handling functions
290   void seek_start(int state);
291   void seek_continue();
292
293   void read_sector_start();
294   void read_sector_continue();
295
296   void read_track_start();
297   void read_track_continue();
298
299   void read_id_start();
300   void read_id_continue();
301
302   void write_track_start();
303   void write_track_continue();
304
305   void write_sector_start();
306   void write_sector_continue();
307
308   void interrupt_start();
309
310   void general_continue();
311   void command_end();
312
313   void spinup();
314   void index_callback(floppy_image_device *floppy, int state);
315   bool sector_matches() const;
316   bool is_ready();
317
318   void live_start(int live_state);
319   void live_abort();
320   void checkpoint();
321   void rollback();
322   void live_delay(int state);
323   void live_sync();
324   void live_run(attotime limit = attotime::never);
325   bool read_one_bit(attotime limit);
326   bool write_one_bit(attotime limit);
327
328   void live_write_raw(UINT16 raw);
329   void live_write_mfm(UINT8 mfm);
330
331   void drop_drq();
332   void set_drq();
333};
334
335class fd1771_t : public wd177x_t {
336public:
337   fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
338
339protected:
340   virtual bool has_ready() const { return true; }
341   virtual bool has_motor() const { return false; }
342   virtual bool has_head_load() const { return true; }
343   virtual bool has_side_check() const { return true; }
344};
345
346class fd1793_t : public wd177x_t {
347public:
348   fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
349
350protected:
351   virtual bool has_ready() const { return true; }
352   virtual bool has_motor() const { return false; }
353   virtual bool has_head_load() const { return true; }
354   virtual bool has_side_check() const { return true; }
355};
356
357class fd1797_t : public wd177x_t {
358public:
359   fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
360
361protected:
362   virtual bool has_ready() const { return true; }
363   virtual bool has_motor() const { return false; }
364   virtual bool has_head_load() const { return true; }
365   virtual bool has_side_select() const { return true; }
366   virtual bool has_sector_length_select() const { return true; }
367};
368
369class wd2793_t : public wd177x_t {
370public:
371   wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
372
373protected:
374   virtual bool has_ready() const { return true; }
375   virtual bool has_motor() const { return false; }
376   virtual bool has_head_load() const { return true; }
377   virtual bool has_side_check() const { return true; }
378};
379
380class wd2797_t : public wd177x_t {
381public:
382   wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
383
384protected:
385   virtual bool has_ready() const { return true; }
386   virtual bool has_motor() const { return false; }
387   virtual bool has_head_load() const { return true; }
388   virtual bool has_side_select() const { return true; }
389   virtual bool has_sector_length_select() const { return true; }
390};
391
392class wd1770_t : public wd177x_t {
393public:
394   wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
395
396protected:
397   virtual bool has_motor() const { return true; }
398   virtual bool has_precompensation() const { return true; }
399};
400
401class wd1772_t : public wd177x_t {
402public:
403   wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
404
405protected:
406   virtual bool has_motor() const { return true; }
407   virtual bool has_precompensation() const { return true; }
408   virtual int step_time(int mode) const;
409   virtual int settle_time() const;
410};
411
412class wd1773_t : public wd177x_t {
413public:
414   wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
415
416protected:
417   virtual bool has_motor() const { return false; }
418   virtual bool has_head_load() const { return true; }
419   virtual bool has_side_check() const { return true; }
420};
421
422extern const device_type FD1771x;
423extern const device_type FD1793x;
424extern const device_type FD1797x;
425extern const device_type WD2793x;
426extern const device_type WD2797x;
427extern const device_type WD1770x;
428extern const device_type WD1772x;
429extern const device_type WD1773x;
430
431#endif
trunk/src/emu/machine/wd_fdc.c
r19166r19167
1/***************************************************************************
2
3    Copyright Olivier Galibert
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions are
8    met:
9
10        * Redistributions of source code must retain the above copyright
11          notice, this list of conditions and the following disclaimer.
12        * Redistributions in binary form must reproduce the above copyright
13          notice, this list of conditions and the following disclaimer in
14          the documentation and/or other materials provided with the
15          distribution.
16        * Neither the name 'MAME' nor the names of its contributors may be
17          used to endorse or promote products derived from this software
18          without specific prior written permission.
19
20    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
21    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
24    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30    POSSIBILITY OF SUCH DAMAGE.
31
32****************************************************************************/
33
34#include "wd_fdc.h"
35
36#include "debugger.h"
37
38const device_type FD1771x = &device_creator<fd1771_t>;
39const device_type FD1793x = &device_creator<fd1793_t>;
40const device_type FD1797x = &device_creator<fd1797_t>;
41const device_type WD2793x = &device_creator<wd2793_t>;
42const device_type WD2797x = &device_creator<wd2797_t>;
43const device_type WD1770x = &device_creator<wd1770_t>;
44const device_type WD1772x = &device_creator<wd1772_t>;
45const device_type WD1773x = &device_creator<wd1773_t>;
46
47wd177x_t::wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
48   device_t(mconfig, type, name, tag, owner, clock)
49{
50}
51
52void wd177x_t::device_start()
53{
54   t_gen = timer_alloc(TM_GEN);
55   t_cmd = timer_alloc(TM_CMD);
56   t_track = timer_alloc(TM_TRACK);
57   t_sector = timer_alloc(TM_SECTOR);
58   dden = false;
59   floppy = 0;
60
61   save_item(NAME(status));
62   save_item(NAME(command));
63   save_item(NAME(main_state));
64   save_item(NAME(sub_state));
65   save_item(NAME(track));
66   save_item(NAME(sector));
67   save_item(NAME(intrq_cond));
68   save_item(NAME(cmd_buffer));
69   save_item(NAME(track_buffer));
70   save_item(NAME(sector_buffer));
71   save_item(NAME(counter));
72   save_item(NAME(status_type_1));
73   save_item(NAME(last_dir));
74}
75
76void wd177x_t::device_reset()
77{
78   command = 0x00;
79   main_state = IDLE;
80   sub_state = IDLE;
81   cur_live.state = IDLE;
82   track = 0x00;
83   sector = 0x00;
84   status = 0x00;
85   data = 0x00;
86   cmd_buffer = track_buffer = sector_buffer = -1;
87   counter = 0;
88   status_type_1 = true;
89   last_dir = 1;
90   intrq = false;
91   drq = false;
92   hld = false;
93   live_abort();
94}
95
96void wd177x_t::set_floppy(floppy_image_device *_floppy)
97{
98   if(floppy == _floppy)
99      return;
100
101   if(floppy) {
102      floppy->mon_w(1);
103      floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
104   }
105
106   floppy = _floppy;
107
108   if(floppy) {
109      if(has_motor())
110         floppy->mon_w(status & S_MON ? 0 : 1);
111      floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(FUNC(wd177x_t::index_callback), this));
112   }
113}
114
115void wd177x_t::setup_intrq_cb(line_cb cb)
116{
117   intrq_cb = cb;
118}
119
120void wd177x_t::setup_drq_cb(line_cb cb)
121{
122   drq_cb = cb;
123}
124
125void wd177x_t::setup_hld_cb(line_cb cb)
126{
127   hld_cb = cb;
128}
129
130void wd177x_t::setup_enp_cb(line_cb cb)
131{
132   enp_cb = cb;
133}
134
135void wd177x_t::dden_w(bool _dden)
136{
137   dden = _dden;
138}
139
140astring wd177x_t::tts(attotime t)
141{
142   char buf[256];
143   int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND;
144   sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000);
145   return buf;
146}
147
148astring wd177x_t::ttsn()
149{
150   return tts(machine().time());
151}
152
153void wd177x_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
154{
155   live_sync();
156
157   switch(id) {
158   case TM_GEN: do_generic(); break;
159   case TM_CMD: do_cmd_w(); break;
160   case TM_TRACK: do_track_w(); break;
161   case TM_SECTOR: do_sector_w(); break;
162   }
163
164   general_continue();
165}
166
167void wd177x_t::command_end()
168{
169   main_state = sub_state = IDLE;
170   status &= ~S_BUSY;
171   intrq = true;
172   motor_timeout = 0;
173   if(!intrq_cb.isnull())
174      intrq_cb(intrq);
175}
176
177void wd177x_t::seek_start(int state)
178{
179   main_state = state;
180   status = (status & ~(S_CRC|S_RNF|S_SPIN)) | S_BUSY;
181   if(has_head_load()) {
182      // TODO get value from HLT callback
183      if (command & 8)
184         status |= S_HLD;
185      else
186         status &= ~S_HLD;
187   }
188   sub_state = has_motor() && !has_head_load() ? SPINUP : SPINUP_DONE;
189   status_type_1 = true;
190   seek_continue();
191}
192
193void wd177x_t::seek_continue()
194{
195   for(;;) {
196      switch(sub_state) {
197      case SPINUP:
198         if(!(status & S_MON)) {
199            spinup();
200            return;
201         }
202         if(!(command & 0x08))
203            status |= S_SPIN;
204         sub_state = SPINUP_DONE;
205         break;
206
207      case SPINUP_WAIT:
208         return;
209
210      case SPINUP_DONE:
211         if(main_state == RESTORE && floppy && !floppy->trk00_r())
212            sub_state = SEEK_DONE;
213
214         if(main_state == SEEK && track == data)
215            sub_state = SEEK_DONE;
216
217         if(sub_state == SPINUP_DONE) {
218            counter = 0;
219            sub_state = SEEK_MOVE;
220         }
221         break;
222
223      case SEEK_MOVE:
224         if(floppy) {
225            floppy->dir_w(last_dir);
226            floppy->stp_w(0);
227            floppy->stp_w(1);
228         }
229         // When stepping with update, the track register is updated before seeking.
230         // Important for the sam coupe format code.
231         if(main_state == STEP && (command & 0x10))
232            track += last_dir ? -1 : 1;
233         counter++;
234         sub_state = SEEK_WAIT_STEP_TIME;
235         delay_cycles(t_gen, step_time(command & 3));
236         return;
237
238      case SEEK_WAIT_STEP_TIME:
239         return;
240
241      case SEEK_WAIT_STEP_TIME_DONE: {
242         bool done = false;
243         switch(main_state) {
244         case RESTORE:
245            done = !floppy || !floppy->trk00_r();
246            break;
247         case SEEK:
248            track += last_dir ? -1 : 1;
249            done = track == data;
250            break;
251         case STEP:
252            done = true;
253            break;
254         }
255
256         if(done || counter == 255) {
257            if(main_state == RESTORE)
258               track = 0;
259
260            if(command & 0x04) {
261               sub_state = SEEK_WAIT_STABILIZATION_TIME;
262               delay_cycles(t_gen, 120000);
263               return;
264            } else
265               sub_state = SEEK_DONE;
266
267         } else
268            sub_state = SEEK_MOVE;
269
270         break;
271      }
272
273      case SEEK_WAIT_STABILIZATION_TIME:
274         return;
275
276      case SEEK_WAIT_STABILIZATION_TIME_DONE:
277         sub_state = SEEK_DONE;
278         break;
279
280      case SEEK_DONE:
281         if(command & 0x04) {
282            if(has_ready() && !is_ready()) {
283               status |= S_RNF;
284               command_end();
285               return;
286            }
287            sub_state = SCAN_ID;
288            counter = 0;
289            live_start(SEARCH_ADDRESS_MARK_HEADER);
290            return;
291         }
292         command_end();
293         return;
294
295      case SCAN_ID:
296         if(cur_live.idbuf[0] != track) {
297            live_start(SEARCH_ADDRESS_MARK_HEADER);
298            return;
299         }
300         if(cur_live.crc) {
301            status |= S_CRC;
302            live_start(SEARCH_ADDRESS_MARK_HEADER);
303            return;
304         }
305         command_end();
306         return;
307
308      case SCAN_ID_FAILED:
309         status |= S_RNF;
310         command_end();
311         return;
312
313      default:
314         logerror("%s: seek unknown sub-state %d\n", ttsn().cstr(), sub_state);
315         return;
316      }
317   }
318}
319
320bool wd177x_t::sector_matches() const
321{
322   if(cur_live.idbuf[0] != track || cur_live.idbuf[2] != sector)
323      return false;
324   if(!has_side_check() || (command & 2))
325      return true;
326   if(command & 8)
327      return cur_live.idbuf[1] & 1;
328   else
329      return !(cur_live.idbuf[1] & 1);
330}
331
332bool wd177x_t::is_ready()
333{
334   return (floppy && !floppy->ready_r());
335}
336
337void wd177x_t::read_sector_start()
338{
339   if(has_ready() && !is_ready())
340      command_end();
341
342   main_state = READ_SECTOR;
343   status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY;
344   drop_drq();
345   if (has_side_select() && floppy)
346      floppy->ss_w(BIT(command, 1));
347   sub_state = has_motor() && !has_head_load() ? SPINUP : SPINUP_DONE;
348   status_type_1 = false;
349   read_sector_continue();
350}
351
352void wd177x_t::read_sector_continue()
353{
354   for(;;) {
355      switch(sub_state) {
356      case SPINUP:
357         if(!(status & S_MON)) {
358            spinup();
359            return;
360         }
361         sub_state = SPINUP_DONE;
362         break;
363
364      case SPINUP_WAIT:
365         return;
366
367      case SPINUP_DONE:
368         if(command & 4) {
369            sub_state = SETTLE_WAIT;
370            delay_cycles(t_gen, settle_time());
371            return;
372         } else {
373            sub_state = SETTLE_DONE;
374            break;
375         }
376
377      case SETTLE_WAIT:
378         return;
379
380      case SETTLE_DONE:
381         sub_state = SCAN_ID;
382         counter = 0;
383         live_start(SEARCH_ADDRESS_MARK_HEADER);
384         return;
385
386      case SCAN_ID:
387         if(!sector_matches()) {
388            live_start(SEARCH_ADDRESS_MARK_HEADER);
389            return;
390         }
391         if(cur_live.crc) {
392            status |= S_CRC;
393            live_start(SEARCH_ADDRESS_MARK_HEADER);
394            return;
395         }
396         // TODO WD2795/7 alternate sector size
397         sector_size = 128 << (cur_live.idbuf[3] & 3);
398         sub_state = SECTOR_READ;
399         live_start(SEARCH_ADDRESS_MARK_DATA);
400         return;
401
402      case SCAN_ID_FAILED:
403         status |= S_RNF;
404         command_end();
405         return;
406
407      case SECTOR_READ:
408         if(cur_live.crc)
409            status |= S_CRC;
410
411         if(command & 0x10 && !(status & S_RNF)) {
412            sector++;
413            sub_state = SETTLE_DONE;
414         } else {
415            command_end();
416            return;
417         }
418         break;
419
420      default:
421         logerror("%s: read sector unknown sub-state %d\n", ttsn().cstr(), sub_state);
422         return;
423      }
424   }
425}
426
427void wd177x_t::read_track_start()
428{
429   if(has_ready() && !is_ready())
430      command_end();
431   
432   main_state = READ_TRACK;
433   status = (status & ~(S_LOST|S_RNF)) | S_BUSY;
434   drop_drq();
435   if (has_side_select() && floppy)
436      floppy->ss_w(BIT(command, 1));
437   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
438   status_type_1 = false;
439   read_track_continue();
440}
441
442void wd177x_t::read_track_continue()
443{
444   for(;;) {
445      switch(sub_state) {
446      case SPINUP:
447         if(!(status & S_MON)) {
448            spinup();
449            return;
450         }
451         sub_state = SPINUP_DONE;
452         break;
453
454      case SPINUP_WAIT:
455         return;
456
457      case SPINUP_DONE:
458         if(command & 4) {
459            sub_state = SETTLE_WAIT;
460            delay_cycles(t_gen, settle_time());
461            return;
462
463         } else {
464            sub_state = SETTLE_DONE;
465            break;
466         }
467
468      case SETTLE_WAIT:
469         return;
470
471      case SETTLE_DONE:
472         sub_state = WAIT_INDEX;
473         return;
474
475      case WAIT_INDEX:
476         return;
477
478      case WAIT_INDEX_DONE:
479         sub_state = TRACK_DONE;
480         live_start(READ_TRACK_DATA);
481         return;
482
483      case TRACK_DONE:
484         command_end();
485         return;
486
487      default:
488         logerror("%s: read track unknown sub-state %d\n", ttsn().cstr(), sub_state);
489         return;
490      }
491   }
492}
493
494void wd177x_t::read_id_start()
495{
496   if(has_ready() && !is_ready())
497      command_end();
498   
499   main_state = READ_ID;
500   status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY;
501   drop_drq();
502   if (has_side_select() && floppy)
503      floppy->ss_w(BIT(command, 1));
504   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
505   status_type_1 = false;
506   read_id_continue();
507}
508
509void wd177x_t::read_id_continue()
510{
511   for(;;) {
512      switch(sub_state) {
513      case SPINUP:
514         if(!(status & S_MON)) {
515            spinup();
516            return;
517         }
518         sub_state = SPINUP_DONE;
519         break;
520
521      case SPINUP_WAIT:
522         return;
523
524      case SPINUP_DONE:
525         if(command & 4) {
526            sub_state = SETTLE_WAIT;
527            delay_cycles(t_gen, settle_time());
528            return;
529         } else {
530            sub_state = SETTLE_DONE;
531            break;
532         }
533
534      case SETTLE_WAIT:
535         return;
536
537      case SETTLE_DONE:
538         sub_state = SCAN_ID;
539         counter = 0;
540         live_start(SEARCH_ADDRESS_MARK_HEADER);
541         return;
542
543      case SCAN_ID:
544         command_end();
545         return;
546
547      case SCAN_ID_FAILED:
548         status |= S_RNF;
549         command_end();
550         return;
551
552      default:
553         logerror("%s: read id unknown sub-state %d\n", ttsn().cstr(), sub_state);
554         return;
555      }
556   }
557}
558
559void wd177x_t::write_track_start()
560{
561   if(has_ready() && !is_ready())
562      command_end();
563   
564   main_state = WRITE_TRACK;
565   status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY;
566   drop_drq();
567   if (has_side_select() && floppy)
568      floppy->ss_w(BIT(command, 1));
569   sub_state = has_motor()  && !has_head_load() ? SPINUP : SPINUP_DONE;
570   status_type_1 = false;
571   write_track_continue();
572}
573
574void wd177x_t::write_track_continue()
575{
576   for(;;) {
577      switch(sub_state) {
578      case SPINUP:
579         if(!(status & S_MON)) {
580            spinup();
581            return;
582         }
583         sub_state = SPINUP_DONE;
584         break;
585
586      case SPINUP_WAIT:
587         return;
588
589      case SPINUP_DONE:
590         if(command & 4) {
591            sub_state = SETTLE_WAIT;
592            delay_cycles(t_gen, settle_time());
593            return;
594         } else {
595            sub_state = SETTLE_DONE;
596            break;
597         }
598
599      case SETTLE_WAIT:
600         return;
601
602      case SETTLE_DONE:
603         set_drq();
604         sub_state = DATA_LOAD_WAIT;
605         delay_cycles(t_gen, 768);
606         return;
607
608      case DATA_LOAD_WAIT:
609         return;
610
611      case DATA_LOAD_WAIT_DONE:
612         if(drq) {
613            status |= S_LOST;
614            command_end();
615            return;
616         }
617         sub_state = WAIT_INDEX;
618         break;
619
620      case WAIT_INDEX:
621         return;
622
623      case WAIT_INDEX_DONE:
624         sub_state = TRACK_DONE;
625         live_start(WRITE_TRACK_DATA);
626         cur_live.pll.start_writing(machine().time());
627         return;
628
629      case TRACK_DONE:
630         command_end();
631         return;
632
633      default:
634         logerror("%s: write track unknown sub-state %d\n", ttsn().cstr(), sub_state);
635         return;
636      }
637   }
638}
639
640
641void wd177x_t::write_sector_start()
642{
643   if(has_ready() && !is_ready())
644      command_end();
645   
646   main_state = WRITE_SECTOR;
647   status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY;
648   drop_drq();
649   if (has_side_select() && floppy)
650      floppy->ss_w(BIT(command, 1));
651   sub_state = has_motor() && !has_head_load()  ? SPINUP : SPINUP_DONE;
652   status_type_1 = false;
653   write_sector_continue();
654}
655
656void wd177x_t::write_sector_continue()
657{
658   for(;;) {
659      switch(sub_state) {
660      case SPINUP:
661         if(!(status & S_MON)) {
662            spinup();
663            return;
664         }
665         sub_state = SPINUP_DONE;
666         break;
667
668      case SPINUP_WAIT:
669         return;
670
671      case SPINUP_DONE:
672         if(command & 4) {
673            sub_state = SETTLE_WAIT;
674            delay_cycles(t_gen, settle_time());
675            return;
676         } else {
677            sub_state = SETTLE_DONE;
678            break;
679         }
680
681      case SETTLE_WAIT:
682         return;
683
684      case SETTLE_DONE:
685         sub_state = SCAN_ID;
686         counter = 0;
687         live_start(SEARCH_ADDRESS_MARK_HEADER);
688         return;
689
690      case SCAN_ID:
691         if(!sector_matches()) {
692            live_start(SEARCH_ADDRESS_MARK_HEADER);
693            return;
694         }
695         if(cur_live.crc) {
696            status |= S_CRC;
697            live_start(SEARCH_ADDRESS_MARK_HEADER);
698            return;
699         }
700         // TODO WD2795/7 alternate sector size
701         sector_size = 128 << (cur_live.idbuf[3] & 3);
702         sub_state = SECTOR_WRITE;
703         live_start(WRITE_SECTOR_PRE);
704         return;
705
706      case SCAN_ID_FAILED:
707         status |= S_RNF;
708         command_end();
709         return;
710
711      case SECTOR_WRITE:
712         if(command & 0x10) {
713            sector++;
714            sub_state = SPINUP_DONE;
715         } else {
716            command_end();
717            return;
718         }
719         break;
720
721      default:
722         logerror("%s: write sector unknown sub-state %d\n", ttsn().cstr(), sub_state);
723         return;
724      }
725   }
726}
727
728void wd177x_t::interrupt_start()
729{
730   if(status & S_BUSY) {
731      main_state = sub_state = cur_live.state = IDLE;
732      cur_live.tm = attotime::never;
733      status &= ~S_BUSY;
734      drop_drq();
735      motor_timeout = 0;
736   }
737   
738   if(!(command & 0x0f)) {
739      intrq_cond = 0;
740   } else {
741      intrq_cond = (intrq_cond & I_IMM) | (command & 0x07);
742   }
743
744   if(intrq_cond & I_IMM) {
745      intrq = true;
746      if(!intrq_cb.isnull())
747         intrq_cb(intrq);
748   }
749
750   if(command & 0x03) {
751      logerror("%s: unhandled interrupt generation (%02x)\n", ttsn().cstr(), command);
752   }
753}
754
755void wd177x_t::general_continue()
756{
757   if(cur_live.state != IDLE) {
758      live_run();
759      if(cur_live.state != IDLE)
760         return;
761   }
762
763   switch(main_state) {
764   case IDLE:
765      break;
766   case RESTORE: case SEEK: case STEP:
767      seek_continue();
768      break;
769   case READ_SECTOR:
770      read_sector_continue();
771      break;
772   case READ_TRACK:
773      read_track_continue();
774      break;
775   case READ_ID:
776      read_id_continue();
777      break;
778   case WRITE_TRACK:
779      write_track_continue();
780      break;
781   case WRITE_SECTOR:
782      write_sector_continue();
783      break;
784   default:
785      logerror("%s: general_continue on unknown main-state %d\n", ttsn().cstr(), main_state);
786      break;
787   }
788}
789
790void wd177x_t::do_generic()
791{
792   switch(sub_state) {
793   case IDLE:
794   case SCAN_ID:
795   case SECTOR_READ:
796      break;
797
798   case SETTLE_WAIT:
799      sub_state = SETTLE_DONE;
800      break;
801
802   case SEEK_WAIT_STEP_TIME:
803      sub_state = SEEK_WAIT_STEP_TIME_DONE;
804      break;
805
806   case SEEK_WAIT_STABILIZATION_TIME:
807      sub_state = SEEK_WAIT_STABILIZATION_TIME_DONE;
808      break;
809
810   case DATA_LOAD_WAIT:
811      sub_state = DATA_LOAD_WAIT_DONE;
812      break;
813
814   default:
815      if(cur_live.tm.is_never())
816         logerror("%s: do_generic on unknown sub-state %d\n", ttsn().cstr(), sub_state);
817      break;
818   }
819}
820
821void wd177x_t::do_cmd_w()
822{
823   //  fprintf(stderr, "%s: command %02x\n", ttsn().cstr(), cmd_buffer);
824
825   // Only available command when busy is interrupt
826   if(main_state != IDLE && (cmd_buffer & 0xf0) != 0xd0) {
827      cmd_buffer = -1;
828      return;
829   }
830   command = cmd_buffer;
831   cmd_buffer = -1;
832
833   switch(command & 0xf0) {
834   case 0x00: logerror("wd1772: restore\n"); last_dir = 1; seek_start(RESTORE); break;
835   case 0x10: logerror("wd1772: seek %d\n", data); last_dir = data > track ? 0 : 1; seek_start(SEEK); break;
836   case 0x20: case 0x30: logerror("wd1772: step\n"); seek_start(STEP); break;
837   case 0x40: case 0x50: logerror("wd1772: step +\n"); last_dir = 0; seek_start(STEP); break;
838   case 0x60: case 0x70: logerror("wd1772: step -\n"); last_dir = 1; seek_start(STEP); break;
839   case 0x80: case 0x90: logerror("wd1772: read sector%s %d, %d\n", command & 0x10 ? " multiple" : "", track, sector); read_sector_start(); break;
840   case 0xa0: case 0xb0: logerror("wd1772: write sector%s %d, %d\n", command & 0x10 ? " multiple" : "", track, sector); write_sector_start(); break;
841   case 0xc0: logerror("wd1772: read id\n"); read_id_start(); break;
842   case 0xd0: logerror("wd1772: interrupt\n"); interrupt_start(); break;
843   case 0xe0: logerror("wd1772: read track %d\n", track); read_track_start(); break;
844   case 0xf0: logerror("wd1772: write track %d\n", track); write_track_start(); break;
845   }
846}
847
848void wd177x_t::cmd_w(UINT8 val)
849{
850   logerror("wd1772 cmd: %02x\n", val);
851   
852   if(intrq && !(intrq_cond & I_IMM)) {
853      intrq = false;
854      if(!intrq_cb.isnull())
855         intrq_cb(intrq);
856   }
857
858   // No more than one write in flight
859   if(cmd_buffer != -1)
860      return;
861
862   cmd_buffer = val;
863
864   delay_cycles(t_cmd, dden ? 384 : 184);
865}
866
867UINT8 wd177x_t::status_r()
868{
869   if(intrq && !(intrq_cond & I_IMM)) {
870      intrq = false;
871      if(!intrq_cb.isnull())
872         intrq_cb(intrq);
873   }
874
875   if(main_state == IDLE || status_type_1) {
876      if(floppy && floppy->idx_r())
877         status |= S_IP;
878      else
879         status &= ~S_IP;
880   } else {
881      if(drq)
882         status |= S_DRQ;
883      else
884         status &= ~S_DRQ;
885   }
886
887   if(status_type_1) {
888      status &= ~(S_TR00|S_WP);
889      if(floppy) {
890         if(floppy->wpt_r())
891            status |= S_WP;
892         if(!floppy->trk00_r())
893            status |= S_TR00;
894      }
895   }
896
897   if(has_ready()) {
898      if(!is_ready())
899         status |= S_NRDY;
900      else
901         status &= ~S_NRDY;
902   }
903
904   return status;
905}
906
907void wd177x_t::do_track_w()
908{
909   track = track_buffer;
910   track_buffer = -1;
911}
912
913void wd177x_t::track_w(UINT8 val)
914{
915   // No more than one write in flight
916   if(track_buffer != -1)
917      return;
918
919   track_buffer = val;
920   delay_cycles(t_track, dden ? 256 : 128);
921}
922
923UINT8 wd177x_t::track_r()
924{
925   return track;
926}
927
928void wd177x_t::do_sector_w()
929{
930   sector = sector_buffer;
931   sector_buffer = -1;
932}
933
934void wd177x_t::sector_w(UINT8 val)
935{
936   // No more than one write in flight
937   if(sector_buffer != -1)
938      return;
939
940   sector_buffer = val;
941   delay_cycles(t_sector, dden ? 256 : 128);
942}
943
944UINT8 wd177x_t::sector_r()
945{
946   return sector;
947}
948
949void wd177x_t::data_w(UINT8 val)
950{
951   data = val;
952   drop_drq();
953}
954
955UINT8 wd177x_t::data_r()
956{
957   drop_drq();
958   return data;
959}
960
961void wd177x_t::gen_w(int reg, UINT8 val)
962{
963   switch(reg) {
964   case 0: cmd_w(val); break;
965   case 1: track_w(val); break;
966   case 2: sector_w(val); break;
967   case 3: data_w(val); break;
968   }
969}
970
971UINT8 wd177x_t::gen_r(int reg)
972{
973   switch(reg) {
974   case 0: return status_r(); break;
975   case 1: return track_r(); break;
976   case 2: return sector_r(); break;
977   case 3: return data_r(); break;
978   }
979   return 0xff;
980}
981
982void wd177x_t::delay_cycles(emu_timer *tm, int cycles)
983{
984   tm->adjust(clocks_to_attotime(cycles));
985}
986
987void wd177x_t::spinup()
988{
989   if(command & 0x08)
990      sub_state = SPINUP_DONE;
991   else {
992      sub_state = SPINUP_WAIT;
993      counter = 0;
994   }
995
996   status |= S_MON;
997   if(floppy)
998      floppy->mon_w(0);
999
1000}
1001
1002void wd177x_t::index_callback(floppy_image_device *floppy, int state)
1003{
1004   live_sync();
1005
1006   if(!state) {
1007      general_continue();
1008      return;
1009   }
1010
1011   if(intrq_cond & I_IDX) {
1012      intrq = true;
1013      if(!intrq_cb.isnull())
1014         intrq_cb(intrq);
1015   }
1016
1017   switch(sub_state) {
1018   case IDLE:
1019      if(has_motor()) {
1020         motor_timeout ++;
1021         if(motor_timeout >= 5) {
1022            status &= ~S_MON;
1023            if(floppy)
1024               floppy->mon_w(1);
1025         }
1026      }
1027      break;
1028
1029   case SPINUP:
1030      break;
1031
1032   case SPINUP_WAIT:
1033      counter++;
1034      if(counter == 6) {
1035         sub_state = SPINUP_DONE;
1036         if(status_type_1)
1037            status |= S_SPIN;
1038      }
1039      break;
1040
1041   case SPINUP_DONE:
1042   case SETTLE_WAIT:
1043   case SETTLE_DONE:
1044   case DATA_LOAD_WAIT:
1045   case DATA_LOAD_WAIT_DONE:
1046   case SEEK_MOVE:
1047   case SEEK_WAIT_STEP_TIME:
1048   case SEEK_WAIT_STEP_TIME_DONE:
1049   case SEEK_WAIT_STABILIZATION_TIME:
1050   case SEEK_WAIT_STABILIZATION_TIME_DONE:
1051   case SEEK_DONE:
1052   case WAIT_INDEX_DONE:
1053   case SCAN_ID_FAILED:
1054   case SECTOR_READ:
1055   case SECTOR_WRITE:
1056      break;
1057
1058   case SCAN_ID:
1059      counter++;
1060      if(counter == 5) {
1061         sub_state = SCAN_ID_FAILED;
1062         live_abort();
1063      }
1064      break;
1065
1066   case WAIT_INDEX:
1067      sub_state = WAIT_INDEX_DONE;
1068      break;
1069
1070   case TRACK_DONE:
1071      live_abort();
1072      break;
1073
1074   default:
1075      logerror("%s: Index pulse on unknown sub-state %d\n", ttsn().cstr(), sub_state);
1076      break;
1077   }
1078
1079   general_continue();
1080}
1081
1082bool wd177x_t::intrq_r()
1083{
1084   return intrq;
1085}
1086
1087bool wd177x_t::drq_r()
1088{
1089   return drq;
1090}
1091
1092bool wd177x_t::hld_r()
1093{
1094   return hld;
1095}
1096
1097void wd177x_t::hlt_w(bool state)
1098{
1099   hlt = state;
1100}
1101
1102bool wd177x_t::enp_r()
1103{
1104   return enp;
1105}
1106
1107void wd177x_t::live_start(int state)
1108{
1109   cur_live.tm = machine().time();
1110   cur_live.state = state;
1111   cur_live.next_state = -1;
1112   cur_live.shift_reg = 0;
1113   cur_live.crc = 0xffff;
1114   cur_live.bit_counter = 0;
1115   cur_live.data_separator_phase = false;
1116   cur_live.data_reg = 0;
1117   cur_live.previous_type = live_info::PT_NONE;
1118   cur_live.data_bit_context = false;
1119   cur_live.byte_counter = 0;
1120   cur_live.pll.reset(cur_live.tm);
1121   cur_live.pll.set_clock(clocks_to_attotime(1));
1122   checkpoint_live = cur_live;
1123
1124   live_run();
1125}
1126
1127void wd177x_t::checkpoint()
1128{
1129   cur_live.pll.commit(floppy, cur_live.tm);
1130   checkpoint_live = cur_live;
1131}
1132
1133void wd177x_t::rollback()
1134{
1135   cur_live = checkpoint_live;
1136}
1137
1138void wd177x_t::live_delay(int state)
1139{
1140   cur_live.next_state = state;
1141   t_gen->adjust(cur_live.tm - machine().time());
1142}
1143
1144void wd177x_t::live_sync()
1145{
1146   if(!cur_live.tm.is_never()) {
1147      if(cur_live.tm > machine().time()) {
1148         //          fprintf(stderr, "%s: Rolling back and replaying (%s)\n", ttsn().cstr(), tts(cur_live.tm).cstr());
1149         rollback();
1150         live_run(machine().time());
1151         cur_live.pll.commit(floppy, cur_live.tm);
1152      } else {
1153         //          fprintf(stderr, "%s: Committing (%s)\n", ttsn().cstr(), tts(cur_live.tm).cstr());
1154         cur_live.pll.commit(floppy, cur_live.tm);
1155         if(cur_live.next_state != -1) {
1156            cur_live.state = cur_live.next_state;
1157            cur_live.next_state = -1;
1158         }
1159         if(cur_live.state == IDLE) {
1160            cur_live.pll.stop_writing(floppy, cur_live.tm);
1161            cur_live.tm = attotime::never;
1162         }
1163      }
1164      cur_live.next_state = -1;
1165      checkpoint();
1166   }
1167}
1168
1169void wd177x_t::live_abort()
1170{
1171   if(!cur_live.tm.is_never() && cur_live.tm > machine().time()) {
1172      rollback();
1173      live_run(machine().time());
1174   }
1175
1176   cur_live.pll.stop_writing(floppy, cur_live.tm);
1177   cur_live.tm = attotime::never;
1178   cur_live.state = IDLE;
1179   cur_live.next_state = -1;
1180}
1181
1182bool wd177x_t::read_one_bit(attotime limit)
1183{
1184   int bit = cur_live.pll.get_next_bit(cur_live.tm, floppy, limit);
1185   if(bit < 0)
1186      return true;
1187   cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
1188   cur_live.bit_counter++;
1189   if(cur_live.data_separator_phase) {
1190      cur_live.data_reg = (cur_live.data_reg << 1) | bit;
1191      if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
1192         cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
1193      else
1194         cur_live.crc = cur_live.crc << 1;
1195   }
1196   cur_live.data_separator_phase = !cur_live.data_separator_phase;
1197   return false;
1198}
1199
1200bool wd177x_t::write_one_bit(attotime limit)
1201{
1202   bool bit = cur_live.shift_reg & 0x8000;
1203   if(cur_live.pll.write_next_bit(bit, cur_live.tm, floppy, limit))
1204      return true;
1205   if(cur_live.bit_counter & 1) {
1206      if((cur_live.crc ^ (bit ? 0x8000 : 0x0000)) & 0x8000)
1207         cur_live.crc = (cur_live.crc << 1) ^ 0x1021;
1208      else
1209         cur_live.crc = cur_live.crc << 1;
1210   }
1211   cur_live.shift_reg = cur_live.shift_reg << 1;
1212   cur_live.bit_counter--;
1213   return false;
1214}
1215
1216void wd177x_t::live_write_raw(UINT16 raw)
1217{
1218   //  logerror("write %04x %04x\n", raw, cur_live.crc);
1219   cur_live.shift_reg = raw;
1220   cur_live.data_bit_context = raw & 1;
1221}
1222
1223void wd177x_t::live_write_mfm(UINT8 mfm)
1224{
1225   bool context = cur_live.data_bit_context;
1226   UINT16 raw = 0;
1227   for(int i=0; i<8; i++) {
1228      bool bit = mfm & (0x80 >> i);
1229      if(!(bit || context))
1230         raw |= 0x8000 >> (2*i);
1231      if(bit)
1232         raw |= 0x4000 >> (2*i);
1233      context = bit;
1234   }
1235   cur_live.shift_reg = raw;
1236   cur_live.data_bit_context = context;
1237   //  logerror("write %02x   %04x %04x\n", mfm, cur_live.crc, raw);
1238}
1239
1240void wd177x_t::live_run(attotime limit)
1241{
1242   if(cur_live.state == IDLE || cur_live.next_state != -1)
1243      return;
1244
1245   if(limit == attotime::never) {
1246      if(floppy)
1247         limit = floppy->time_next_index();
1248      if(limit == attotime::never) {
1249         // Happens when there's no disk or if the wd is not
1250         // connected to a drive, hence no index pulse. Force a
1251         // sync from time to time in that case, so that the main
1252         // cpu timeout isn't too painful.  Avoids looping into
1253         // infinity looking for data too.
1254
1255         limit = machine().time() + attotime::from_msec(1);
1256         t_gen->adjust(attotime::from_msec(1));
1257      }
1258   }
1259
1260   //  fprintf(stderr, "%s: live_run(%s)\n", ttsn().cstr(), tts(limit).cstr());
1261
1262   for(;;) {
1263      switch(cur_live.state) {
1264      case SEARCH_ADDRESS_MARK_HEADER:
1265         if(read_one_bit(limit))
1266            return;
1267#if 0
1268         fprintf(stderr, "%s: shift = %04x data=%02x c=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1269               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1270               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1271               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1272               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1273               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1274               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1275               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1276               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1277               cur_live.bit_counter);
1278#endif
1279
1280         if(cur_live.shift_reg == 0x4489) {
1281            cur_live.crc = 0x443b;
1282            cur_live.data_separator_phase = false;
1283            cur_live.bit_counter = 0;
1284            cur_live.state = READ_HEADER_BLOCK_HEADER;
1285         }
1286         break;
1287
1288      case READ_HEADER_BLOCK_HEADER: {
1289         if(read_one_bit(limit))
1290            return;
1291#if 0
1292         fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1293               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1294               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1295               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1296               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1297               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1298               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1299               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1300               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1301               cur_live.bit_counter);
1302#endif
1303         if(cur_live.bit_counter & 15)
1304            break;
1305
1306         int slot = cur_live.bit_counter >> 4;
1307
1308         if(slot < 3) {
1309            if(cur_live.shift_reg != 0x4489)
1310               cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
1311            break;
1312         }
1313         if(cur_live.data_reg != 0xfe && cur_live.data_reg != 0xff) {
1314            cur_live.state = SEARCH_ADDRESS_MARK_HEADER;
1315            break;
1316         }
1317
1318         cur_live.bit_counter = 0;
1319
1320         if(main_state == READ_ID)
1321            cur_live.state = READ_ID_BLOCK_TO_DMA;
1322         else
1323            cur_live.state = READ_ID_BLOCK_TO_LOCAL;
1324
1325         break;
1326      }
1327
1328      case READ_ID_BLOCK_TO_LOCAL: {
1329         if(read_one_bit(limit))
1330            return;
1331         if(cur_live.bit_counter & 15)
1332            break;
1333         int slot = (cur_live.bit_counter >> 4)-1;
1334         cur_live.idbuf[slot] = cur_live.data_reg;
1335         if(slot == 5) {
1336            live_delay(IDLE);
1337            return;
1338         }
1339         break;
1340      }
1341
1342      case READ_ID_BLOCK_TO_DMA: {
1343         if(read_one_bit(limit))
1344            return;
1345         if(cur_live.bit_counter & 15)
1346            break;
1347         live_delay(READ_ID_BLOCK_TO_DMA_BYTE);
1348         return;
1349      }
1350
1351      case READ_ID_BLOCK_TO_DMA_BYTE:
1352         data = cur_live.data_reg;
1353         if(cur_live.bit_counter == 16)
1354            sector = data;
1355         set_drq();
1356
1357         if(cur_live.bit_counter == 16*6) {
1358            // Already synchronous
1359            cur_live.state = IDLE;
1360            return;
1361         }
1362
1363         cur_live.state = READ_ID_BLOCK_TO_DMA;
1364         checkpoint();
1365         break;
1366
1367      case SEARCH_ADDRESS_MARK_DATA:
1368         if(read_one_bit(limit))
1369            return;
1370#if 0
1371         fprintf(stderr, "%s: shift = %04x data=%02x c=%d.%x\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1372               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1373               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1374               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1375               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1376               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1377               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1378               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1379               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1380               cur_live.bit_counter >> 4, cur_live.bit_counter & 15);
1381#endif
1382         if(cur_live.bit_counter > 43*16) {
1383            live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1384            return;
1385         }
1386
1387         if(cur_live.bit_counter >= 28*16 && cur_live.shift_reg == 0x4489) {
1388            cur_live.crc = 0x443b;
1389            cur_live.data_separator_phase = false;
1390            cur_live.bit_counter = 0;
1391            cur_live.state = READ_DATA_BLOCK_HEADER;
1392         }
1393         break;
1394
1395      case READ_DATA_BLOCK_HEADER: {
1396         if(read_one_bit(limit))
1397            return;
1398#if 0
1399         fprintf(stderr, "%s: shift = %04x data=%02x counter=%d\n", tts(cur_live.tm).cstr(), cur_live.shift_reg,
1400               (cur_live.shift_reg & 0x4000 ? 0x80 : 0x00) |
1401               (cur_live.shift_reg & 0x1000 ? 0x40 : 0x00) |
1402               (cur_live.shift_reg & 0x0400 ? 0x20 : 0x00) |
1403               (cur_live.shift_reg & 0x0100 ? 0x10 : 0x00) |
1404               (cur_live.shift_reg & 0x0040 ? 0x08 : 0x00) |
1405               (cur_live.shift_reg & 0x0010 ? 0x04 : 0x00) |
1406               (cur_live.shift_reg & 0x0004 ? 0x02 : 0x00) |
1407               (cur_live.shift_reg & 0x0001 ? 0x01 : 0x00),
1408               cur_live.bit_counter);
1409#endif
1410         if(cur_live.bit_counter & 15)
1411            break;
1412
1413         int slot = cur_live.bit_counter >> 4;
1414
1415         if(slot < 3) {
1416            if(cur_live.shift_reg != 0x4489) {
1417               live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1418               return;
1419            }
1420            break;
1421         }
1422         if((cur_live.data_reg & 0xfe) != 0xfa && (cur_live.data_reg & 0xfe) != 0xfc) {
1423            live_delay(SEARCH_ADDRESS_MARK_DATA_FAILED);
1424            return;
1425         }
1426
1427         cur_live.bit_counter = 0;
1428         cur_live.state = READ_SECTOR_DATA;
1429         break;
1430      }
1431
1432      case SEARCH_ADDRESS_MARK_DATA_FAILED:
1433         status |= S_RNF;
1434         cur_live.state = IDLE;
1435         return;
1436
1437      case READ_SECTOR_DATA: {
1438         if(read_one_bit(limit))
1439            return;
1440         if(cur_live.bit_counter & 15)
1441            break;
1442         int slot = (cur_live.bit_counter >> 4)-1;
1443         if(slot < sector_size) {
1444            // Sector data
1445            live_delay(READ_SECTOR_DATA_BYTE);
1446            return;
1447
1448         } else if(slot < sector_size+2) {
1449            // CRC
1450            if(slot == sector_size+1) {
1451               live_delay(IDLE);
1452               return;
1453            }
1454         }
1455
1456         break;
1457      }
1458
1459      case READ_SECTOR_DATA_BYTE:
1460         data = cur_live.data_reg;
1461         set_drq();
1462         cur_live.state = READ_SECTOR_DATA;
1463         checkpoint();
1464         break;
1465
1466      case READ_TRACK_DATA: {
1467         if(read_one_bit(limit))
1468            return;
1469         if(cur_live.bit_counter != 16
1470            && cur_live.shift_reg != 0x4489
1471            && cur_live.shift_reg != 0x5224)
1472            break;
1473
1474         // Incorrect, hmmm
1475         // Probably >2 + not just after a sync if <16
1476
1477         // Transitions 00..00 -> 4489.4489.4489 at varied syncs:
1478         //  0: 00.00.14.a1   1: ff.fe.c2.a1   2: 00.01.14.a1   3: ff.fc.c2.a1
1479         //  4: 00.02.14.a1   5: ff.f8.c2.a1   6: 00.05.14.a1   7: ff.f0.c2.a1
1480         //  8: 00.00.0a.a1   9: ff.ff.e1.a1  10: 00.00.14.a1  11: ff.ff.ce.a1
1481         // 12: 00.00.14.a1  13: ff.ff.c2.a1  14: 00.00.14.a1  15: ff.ff.c2.a1
1482
1483         bool output_byte = cur_live.bit_counter > 5;
1484
1485         cur_live.data_separator_phase = false;
1486         cur_live.bit_counter = 0;
1487
1488         if(output_byte) {
1489            live_delay(READ_TRACK_DATA_BYTE);
1490            return;
1491         }
1492
1493         break;
1494      }
1495
1496      case READ_TRACK_DATA_BYTE:
1497         data = cur_live.data_reg;
1498         set_drq();
1499         cur_live.state = READ_TRACK_DATA;
1500         checkpoint();
1501         break;
1502
1503      case WRITE_TRACK_DATA:
1504         if(drq) {
1505            status |= S_LOST;
1506            data = 0;
1507         }
1508
1509         switch(data) {
1510         case 0xf5:
1511            live_write_raw(0x4489);
1512            cur_live.crc = 0x968b; // Ensures that the crc is cdb4 after writing the byte
1513            cur_live.previous_type = live_info::PT_NONE;
1514            break;
1515         case 0xf6:
1516            cur_live.previous_type = live_info::PT_NONE;
1517            live_write_raw(0x5224);
1518            break;
1519         case 0xf7:
1520            if(cur_live.previous_type == live_info::PT_CRC_2) {
1521               cur_live.previous_type = live_info::PT_NONE;
1522               live_write_mfm(0xf7);
1523            } else {
1524               cur_live.previous_type = live_info::PT_CRC_1;
1525               live_write_mfm(cur_live.crc >> 8);
1526            }
1527            break;
1528         default:
1529            cur_live.previous_type = live_info::PT_NONE;
1530            live_write_mfm(data);
1531            break;
1532         }
1533         set_drq();
1534         cur_live.state = WRITE_BYTE;
1535         cur_live.bit_counter = 16;
1536         checkpoint();
1537         break;
1538
1539      case WRITE_BYTE:
1540         if(write_one_bit(limit))
1541            return;
1542         if(cur_live.bit_counter == 0) {
1543            live_delay(WRITE_BYTE_DONE);
1544            return;
1545         }
1546         break;
1547
1548      case WRITE_BYTE_DONE:
1549         switch(sub_state) {
1550         case TRACK_DONE:
1551            if(cur_live.previous_type == live_info::PT_CRC_1) {
1552               cur_live.previous_type = live_info::PT_CRC_2;
1553               live_write_mfm(cur_live.crc >> 8);
1554               cur_live.state = WRITE_BYTE;
1555               cur_live.bit_counter = 16;
1556               checkpoint();
1557            } else
1558               cur_live.state = WRITE_TRACK_DATA;
1559            break;
1560
1561         case SECTOR_WRITE:
1562            cur_live.state = WRITE_BYTE;
1563            cur_live.bit_counter = 16;
1564            cur_live.byte_counter++;
1565            if(cur_live.byte_counter <= 11)
1566               live_write_mfm(0x00);
1567            else if(cur_live.byte_counter == 12) {
1568               cur_live.crc = 0xffff;
1569               live_write_raw(0x4489);
1570            } else if(cur_live.byte_counter <= 14)
1571               live_write_raw(0x4489);
1572            else if(cur_live.byte_counter == 15)
1573               live_write_mfm(command & 1 ? 0xf8 : 0xfb);
1574            else if(cur_live.byte_counter <= sector_size + 16-2) {
1575               if(drq) {
1576                  status |= S_LOST;
1577                  data = 0;
1578               }
1579               live_write_mfm(data);
1580               set_drq();
1581            } else if(cur_live.byte_counter == sector_size + 16-1) {
1582               if(drq) {
1583                  status |= S_LOST;
1584                  data = 0;
1585               }
1586               live_write_mfm(data);
1587            } else if(cur_live.byte_counter <= sector_size + 16+1)
1588               live_write_mfm(cur_live.crc >> 8);
1589            else if(cur_live.byte_counter == sector_size + 16+2)
1590               // Is that correct?  It seems required (try ST formatting)
1591               live_write_mfm(0xff);
1592            else {
1593               cur_live.pll.stop_writing(floppy, cur_live.tm);
1594               cur_live.state = IDLE;
1595               return;
1596            }
1597
1598            checkpoint();
1599            break;
1600
1601         default:
1602            logerror("%s: Unknown sub state %d in WRITE_BYTE_DONE\n", tts(cur_live.tm).cstr(), sub_state);
1603            live_abort();
1604            return;
1605         }
1606         break;
1607
1608      case WRITE_SECTOR_PRE:
1609         if(read_one_bit(limit))
1610            return;
1611         if(cur_live.bit_counter != 16)
1612            break;
1613         live_delay(WRITE_SECTOR_PRE_BYTE);
1614         return;
1615
1616      case WRITE_SECTOR_PRE_BYTE:
1617         cur_live.state = WRITE_SECTOR_PRE;
1618         cur_live.byte_counter++;
1619         cur_live.bit_counter = 0;
1620         switch(cur_live.byte_counter) {
1621         case 2:
1622            set_drq();
1623            checkpoint();
1624            break;
1625         case 11:
1626            if(drq) {
1627               status |= S_LOST;
1628               cur_live.state = IDLE;
1629               return;
1630            }
1631            break;
1632         case 22:
1633            cur_live.state = WRITE_BYTE;
1634            cur_live.bit_counter = 16;
1635            cur_live.byte_counter = 0;
1636            cur_live.data_bit_context = cur_live.data_reg & 1;
1637            cur_live.pll.start_writing(cur_live.tm);
1638            live_write_mfm(0x00);
1639            break;
1640         }
1641         break;
1642
1643      default:
1644         logerror("%s: Unknown live state %d\n", tts(cur_live.tm).cstr(), cur_live.state);
1645         return;
1646      }
1647   }
1648}
1649
1650void wd177x_t::set_drq()
1651{
1652   if(drq)
1653      status |= S_LOST;
1654   else {
1655      drq = true;
1656      if(!drq_cb.isnull())
1657         drq_cb(true);
1658   }
1659}
1660
1661void wd177x_t::drop_drq()
1662{
1663   if(drq) {
1664      drq = false;
1665      if(!drq_cb.isnull())
1666         drq_cb(false);
1667   }
1668}
1669
1670void wd177x_t::pll_t::set_clock(attotime period)
1671{
1672   for(int i=0; i<42; i++)
1673      delays[i] = period*(i+1);
1674}
1675
1676void wd177x_t::pll_t::reset(attotime when)
1677{
1678   counter = 0;
1679   increment = 128;
1680   transition_time = 0xffff;
1681   history = 0x80;
1682   slot = 0;
1683   ctime = when;
1684   phase_add = 0x00;
1685   phase_sub = 0x00;
1686   freq_add  = 0x00;
1687   freq_sub  = 0x00;
1688   write_position = 0;
1689   write_start_time = attotime::never;
1690}
1691
1692int wd177x_t::pll_t::get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit)
1693{
1694   attotime when = floppy ? floppy->get_next_transition(ctime) : attotime::never;
1695#if 0
1696   if(!when.is_never())
1697      fprintf(stderr, "transition_time=%s\n", tts(when).cstr());
1698#endif
1699
1700   for(;;) {
1701      //      fprintf(stderr, "slot=%2d, counter=%03x\n", slot, counter);
1702      attotime etime = ctime+delays[slot];
1703      //      fprintf(stderr, "etime=%s\n", tts(etime).cstr());
1704      if(etime > limit)
1705         return -1;
1706      if(transition_time == 0xffff && !when.is_never() && etime >= when)
1707         transition_time = counter;
1708      if(slot < 8) {
1709         UINT8 mask = 1 << slot;
1710         if(phase_add & mask)
1711            counter += 226;
1712         else if(phase_sub & mask)
1713            counter += 30;
1714         else
1715            counter += increment;
1716
1717         if((freq_add & mask) && increment < 140)
1718            increment++;
1719         else if((freq_sub & mask) && increment > 117)
1720            increment--;
1721      } else
1722         counter += increment;
1723
1724      slot++;
1725      tm = etime;
1726      if(counter & 0x800)
1727         break;
1728   }
1729   //  fprintf(stderr, "first transition, time=%03x, inc=%3d\n", transition_time, increment);
1730   int bit = transition_time != 0xffff;
1731
1732   if(transition_time != 0xffff) {
1733      static const UINT8 pha[8] = { 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 };
1734      static const UINT8 phs[8] = { 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf };
1735      static const UINT8 freqa[4][8] = {
1736         { 0xf, 0x7, 0x3, 0x1, 0, 0, 0, 0 },
1737         { 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
1738         { 0x7, 0x3, 0x1, 0, 0, 0, 0, 0 },
1739         { 0, 0, 0, 0, 0, 0, 0, 0 }
1740      };
1741      static const UINT8 freqs[4][8] = {
1742         { 0, 0, 0, 0, 0, 0, 0, 0 },
1743         { 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
1744         { 0, 0, 0, 0, 0, 0x1, 0x3, 0x7 },
1745         { 0, 0, 0, 0, 0x1, 0x3, 0x7, 0xf },
1746      };
1747
1748      int cslot = transition_time >> 8;
1749      phase_add = pha[cslot];
1750      phase_sub = phs[cslot];
1751      int way = transition_time & 0x400 ? 1 : 0;
1752      if(history & 0x80)
1753         history = way ? 0x80 : 0x83;
1754      else if(history & 0x40)
1755         history = way ? history & 2 : (history & 2) | 1;
1756      freq_add = freqa[history & 3][cslot];
1757      freq_sub = freqs[history & 3][cslot];
1758      history = way ? (history >> 1) | 2 : history >> 1;
1759
1760   } else
1761      phase_add = phase_sub = freq_add = freq_sub = 0;
1762
1763   counter &= 0x7ff;
1764
1765   ctime = tm;
1766   transition_time = 0xffff;
1767   slot = 0;
1768
1769   return bit;
1770}
1771
1772void wd177x_t::pll_t::start_writing(attotime tm)
1773{
1774   write_start_time = tm;
1775   write_position = 0;
1776}
1777
1778void wd177x_t::pll_t::stop_writing(floppy_image_device *floppy, attotime tm)
1779{
1780   commit(floppy, tm);
1781   write_start_time = attotime::never;
1782}
1783
1784bool wd177x_t::pll_t::write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit)
1785{
1786   if(write_start_time.is_never()) {
1787      write_start_time = ctime;
1788      write_position = 0;
1789   }
1790
1791   for(;;) {
1792      attotime etime = ctime+delays[slot];
1793      if(etime > limit)
1794         return true;
1795      UINT16 pre_counter = counter;
1796      counter += increment;
1797      if(bit && !(pre_counter & 0x400) && (counter & 0x400))
1798         if(write_position < ARRAY_LENGTH(write_buffer))
1799            write_buffer[write_position++] = etime;
1800      slot++;
1801      tm = etime;
1802      if(counter & 0x800)
1803         break;
1804   }
1805
1806   counter &= 0x7ff;
1807
1808   ctime = tm;
1809   slot = 0;
1810
1811   return false;
1812}
1813
1814void wd177x_t::pll_t::commit(floppy_image_device *floppy, attotime tm)
1815{
1816   if(write_start_time.is_never() || tm == write_start_time)
1817      return;
1818
1819   if(floppy)
1820      floppy->write_flux(write_start_time, tm, write_position, write_buffer);
1821   write_start_time = tm;
1822   write_position = 0;
1823}
1824
1825int wd177x_t::step_time(int mode) const
1826{
1827   const static int step_times[4] = { 48000, 96000, 160000, 240000 };
1828   return step_times[mode];
1829}
1830
1831int wd177x_t::settle_time() const
1832{
1833   return 240000;
1834}
1835
1836bool wd177x_t::has_ready() const
1837{
1838   return false;
1839}
1840
1841bool wd177x_t::has_head_load() const
1842{
1843   return false;
1844}
1845
1846bool wd177x_t::has_side_check() const
1847{
1848   return false;
1849}
1850
1851bool wd177x_t::has_side_select() const
1852{
1853   return false;
1854}
1855
1856bool wd177x_t::has_sector_length_select() const
1857{
1858   return false;
1859}
1860
1861bool wd177x_t::has_precompensation() const
1862{
1863   return false;
1864}
1865
1866fd1771_t::fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1771x, "FD1771", tag, owner, clock)
1867{
1868}
1869
1870fd1793_t::fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1793x, "FD1793", tag, owner, clock)
1871{
1872}
1873
1874fd1797_t::fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, FD1797x, "FD1797", tag, owner, clock)
1875{
1876}
1877
1878wd2793_t::wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD2793x, "WD2793", tag, owner, clock)
1879{
1880}
1881
1882wd2797_t::wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD2797x, "WD2797", tag, owner, clock)
1883{
1884}
1885
1886wd1770_t::wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1770x, "WD1770", tag, owner, clock)
1887{
1888}
1889
1890wd1772_t::wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1772x, "WD1772", tag, owner, clock)
1891{
1892}
1893
1894int wd1772_t::step_time(int mode) const
1895{
1896   const static int step_times[4] = { 48000, 96000, 16000, 24000 };
1897   return step_times[mode];
1898}
1899
1900int wd1772_t::settle_time() const
1901{
1902   return 120000;
1903}
1904
1905wd1773_t::wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd177x_t(mconfig, WD1773x, "WD1773", tag, owner, clock)
1906{
1907}
trunk/src/emu/machine/wd_fdc.h
r19166r19167
1#ifndef WD1772_H
2#define WD1772_H
3
4#include "emu.h"
5#include "imagedev/floppy.h"
6
7#define MCFG_FD1771x_ADD(_tag, _clock)  \
8   MCFG_DEVICE_ADD(_tag, FD1771x, _clock)
9
10#define MCFG_FD1793x_ADD(_tag, _clock)  \
11   MCFG_DEVICE_ADD(_tag, FD1793x, _clock)
12
13#define MCFG_FD1797x_ADD(_tag, _clock)  \
14   MCFG_DEVICE_ADD(_tag, FD1797x, _clock)
15
16#define MCFG_WD2793x_ADD(_tag, _clock)  \
17   MCFG_DEVICE_ADD(_tag, WD2793x, _clock)
18
19#define MCFG_WD2797x_ADD(_tag, _clock)  \
20   MCFG_DEVICE_ADD(_tag, WD2797x, _clock)
21
22#define MCFG_WD1770x_ADD(_tag, _clock)  \
23   MCFG_DEVICE_ADD(_tag, WD1770x, _clock)
24
25#define MCFG_WD1772x_ADD(_tag, _clock)  \
26   MCFG_DEVICE_ADD(_tag, WD1772x, _clock)
27
28#define MCFG_WD1773x_ADD(_tag, _clock)  \
29   MCFG_DEVICE_ADD(_tag, WD1773x, _clock)
30
31class wd177x_t : public device_t {
32public:
33   typedef delegate<void (bool state)> line_cb;
34
35   wd177x_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
36
37   void dden_w(bool dden);
38   void set_floppy(floppy_image_device *floppy);
39   void setup_intrq_cb(line_cb cb);
40   void setup_drq_cb(line_cb cb);
41   void setup_hld_cb(line_cb cb);
42   void setup_enp_cb(line_cb cb);
43
44   void cmd_w(UINT8 val);
45   UINT8 status_r();
46   DECLARE_READ8_MEMBER( status_r ) { return status_r(); }
47   DECLARE_WRITE8_MEMBER( cmd_w ) { cmd_w(data); }
48
49   void track_w(UINT8 val);
50   UINT8 track_r();
51   DECLARE_READ8_MEMBER( track_r ) { return track_r(); }
52   DECLARE_WRITE8_MEMBER( track_w ) { track_w(data); }
53
54   void sector_w(UINT8 val);
55   UINT8 sector_r();
56   DECLARE_READ8_MEMBER( sector_r ) { return sector_r(); }
57   DECLARE_WRITE8_MEMBER( sector_w ) { sector_w(data); }
58
59   void data_w(UINT8 val);
60   UINT8 data_r();
61   DECLARE_READ8_MEMBER( data_r ) { return data_r(); }
62   DECLARE_WRITE8_MEMBER( data_w ) { data_w(data); }
63
64   void gen_w(int reg, UINT8 val);
65   UINT8 gen_r(int reg);
66   DECLARE_READ8_MEMBER( read ) { return gen_r(offset);}
67   DECLARE_WRITE8_MEMBER( write ) { gen_w(offset,data); }
68
69   bool intrq_r();
70   bool drq_r();
71
72   bool hld_r();
73   void hlt_w(bool state);
74
75   bool enp_r();
76
77protected:
78   virtual void device_start();
79   virtual void device_reset();
80   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
81
82   virtual bool has_ready() const;
83   virtual bool has_motor() const = 0;
84   virtual bool has_head_load() const;
85   virtual bool has_side_check() const;
86   virtual bool has_side_select() const;
87   virtual bool has_sector_length_select() const;
88   virtual bool has_precompensation() const;
89   virtual int step_time(int mode) const;
90   virtual int settle_time() const;
91
92private:
93   enum { TM_GEN, TM_CMD, TM_TRACK, TM_SECTOR };
94
95   //  State machine general behaviour:
96   //
97   //  There are three levels of state.
98   //
99   //  Main state is associated to (groups of) commands.  They're set
100   //  by a *_start() function below, and the associated _continue()
101   //  function can then be called at pretty much any time.
102   //
103   //  Sub state is the state of execution within a command.  The
104   //  principle is that the *_start() function selects the initial
105   //  substate, then the *_continue() function decides what to do,
106   //  possibly changing state.  Eventually it can:
107   //  - decide to wait for an event (timer, index)
108   //  - end the command with command_end()
109   //  - start a live state (see below)
110   //
111   //  In the first case, it must first switch to a waiting
112   //  sub-state, then return.  The waiting sub-state must just
113   //  return immediatly when *_continue is called.  Eventually the
114   //  event handler function will advance the state machine to
115   //  another sub-state, and things will continue synchronously.
116   //
117   //  On command end it's also supposed to return immediatly.
118   //
119   //  The last option is to switch to the next sub-state, start a
120   //  live state with live_start() then return.  The next sub-state
121   //  will only be called once the live state is finished.
122   //
123   //  Live states change continually depending on the disk contents
124   //  until the next externally discernable event is found.  They
125   //  are checkpointing, run until an event is found, then they wait
126   //  for it.  When an event eventually happen the the changes are
127   //  either committed or replayed until the sync event time.
128   //
129   //  The transition to IDLE is only done on a synced event.  Some
130   //  other transitions, such as activating drq, are also done after
131   //  syncing without exiting live mode.  Syncing in live mode is
132   //  done by calling live_delay() with the state to change to after
133   //  syncing.
134
135   enum {
136      // General "doing nothing" state
137      IDLE,
138
139      // Main states - the commands
140      RESTORE,
141      SEEK,
142      STEP,
143      READ_SECTOR,
144      READ_TRACK,
145      READ_ID,
146      WRITE_TRACK,
147      WRITE_SECTOR,
148
149      // Sub states
150
151      SPINUP,
152      SPINUP_WAIT,
153      SPINUP_DONE,
154
155      SETTLE_WAIT,
156      SETTLE_DONE,
157
158      DATA_LOAD_WAIT,
159      DATA_LOAD_WAIT_DONE,
160
161      SEEK_MOVE,
162      SEEK_WAIT_STEP_TIME,
163      SEEK_WAIT_STEP_TIME_DONE,
164      SEEK_WAIT_STABILIZATION_TIME,
165      SEEK_WAIT_STABILIZATION_TIME_DONE,
166      SEEK_DONE,
167
168      WAIT_INDEX,
169      WAIT_INDEX_DONE,
170
171      SCAN_ID,
172      SCAN_ID_FAILED,
173
174      SECTOR_READ,
175      SECTOR_WRITE,
176      TRACK_DONE,
177
178      // Live states
179
180      SEARCH_ADDRESS_MARK_HEADER,
181      READ_HEADER_BLOCK_HEADER,
182      READ_DATA_BLOCK_HEADER,
183      READ_ID_BLOCK_TO_LOCAL,
184      READ_ID_BLOCK_TO_DMA,
185      READ_ID_BLOCK_TO_DMA_BYTE,
186      SEARCH_ADDRESS_MARK_DATA,
187      SEARCH_ADDRESS_MARK_DATA_FAILED,
188      READ_SECTOR_DATA,
189      READ_SECTOR_DATA_BYTE,
190      READ_TRACK_DATA,
191      READ_TRACK_DATA_BYTE,
192      WRITE_TRACK_DATA,
193      WRITE_BYTE,
194      WRITE_BYTE_DONE,
195      WRITE_SECTOR_PRE,
196      WRITE_SECTOR_PRE_BYTE,
197   };
198
199   struct pll_t {
200      UINT16 counter;
201      UINT16 increment;
202      UINT16 transition_time;
203      UINT8 history;
204      UINT8 slot;
205      UINT8 phase_add, phase_sub, freq_add, freq_sub;
206      attotime ctime;
207
208      attotime delays[42];
209
210      attotime write_start_time;
211      attotime write_buffer[32];
212      int write_position;
213
214      void set_clock(attotime period);
215      void reset(attotime when);
216      int get_next_bit(attotime &tm, floppy_image_device *floppy, attotime limit);
217      bool write_next_bit(bool bit, attotime &tm, floppy_image_device *floppy, attotime limit);
218      void start_writing(attotime tm);
219      void commit(floppy_image_device *floppy, attotime tm);
220      void stop_writing(floppy_image_device *floppy, attotime tm);
221   };
222
223   struct live_info {
224      enum { PT_NONE, PT_CRC_1, PT_CRC_2 };
225
226      attotime tm;
227      int state, next_state;
228      UINT16 shift_reg;
229      UINT16 crc;
230      int bit_counter, byte_counter, previous_type;
231      bool data_separator_phase, data_bit_context;
232      UINT8 data_reg;
233      UINT8 idbuf[6];
234      pll_t pll;
235   };
236
237   enum {
238      S_BUSY = 0x01,
239      S_DRQ  = 0x02,
240      S_IP   = 0x02,
241      S_TR00 = 0x04,
242      S_LOST = 0x04,
243      S_CRC  = 0x08,
244      S_RNF  = 0x10,
245      S_HLD  = 0x20,
246      S_SPIN = 0x20, // WD1770, WD1772
247      S_DDM  = 0x20,
248      S_WF   = 0x20, // WD1773
249      S_WP   = 0x40,
250      S_NRDY = 0x80,
251      S_MON  = 0x80  // WD1770, WD1772
252   };
253
254   enum {
255      I_RDY = 0x01,
256      I_NRDY = 0x02,
257      I_IDX = 0x04,
258      I_IMM = 0x08
259   };
260
261   floppy_image_device *floppy;
262
263   emu_timer *t_gen, *t_cmd, *t_track, *t_sector;
264
265   bool dden, status_type_1, intrq, drq, hld, hlt, enp;
266   int main_state, sub_state;
267   UINT8 command, track, sector, data, status, intrq_cond;
268   int last_dir;
269
270   int counter, motor_timeout, sector_size;
271
272   int cmd_buffer, track_buffer, sector_buffer;
273
274   live_info cur_live, checkpoint_live;
275   line_cb intrq_cb, drq_cb, hld_cb, enp_cb;
276
277   static astring tts(attotime t);
278   astring ttsn();
279
280   void delay_cycles(emu_timer *tm, int cycles);
281
282   // Device timer subfunctions
283   void do_cmd_w();
284   void do_track_w();
285   void do_sector_w();
286   void do_generic();
287
288
289   // Main-state handling functions
290   void seek_start(int state);
291   void seek_continue();
292
293   void read_sector_start();
294   void read_sector_continue();
295
296   void read_track_start();
297   void read_track_continue();
298
299   void read_id_start();
300   void read_id_continue();
301
302   void write_track_start();
303   void write_track_continue();
304
305   void write_sector_start();
306   void write_sector_continue();
307
308   void interrupt_start();
309
310   void general_continue();
311   void command_end();
312
313   void spinup();
314   void index_callback(floppy_image_device *floppy, int state);
315   bool sector_matches() const;
316   bool is_ready();
317
318   void live_start(int live_state);
319   void live_abort();
320   void checkpoint();
321   void rollback();
322   void live_delay(int state);
323   void live_sync();
324   void live_run(attotime limit = attotime::never);
325   bool read_one_bit(attotime limit);
326   bool write_one_bit(attotime limit);
327
328   void live_write_raw(UINT16 raw);
329   void live_write_mfm(UINT8 mfm);
330
331   void drop_drq();
332   void set_drq();
333};
334
335class fd1771_t : public wd177x_t {
336public:
337   fd1771_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
338
339protected:
340   virtual bool has_ready() const { return true; }
341   virtual bool has_motor() const { return false; }
342   virtual bool has_head_load() const { return true; }
343   virtual bool has_side_check() const { return true; }
344};
345
346class fd1793_t : public wd177x_t {
347public:
348   fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
349
350protected:
351   virtual bool has_ready() const { return true; }
352   virtual bool has_motor() const { return false; }
353   virtual bool has_head_load() const { return true; }
354   virtual bool has_side_check() const { return true; }
355};
356
357class fd1797_t : public wd177x_t {
358public:
359   fd1797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
360
361protected:
362   virtual bool has_ready() const { return true; }
363   virtual bool has_motor() const { return false; }
364   virtual bool has_head_load() const { return true; }
365   virtual bool has_side_select() const { return true; }
366   virtual bool has_sector_length_select() const { return true; }
367};
368
369class wd2793_t : public wd177x_t {
370public:
371   wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
372
373protected:
374   virtual bool has_ready() const { return true; }
375   virtual bool has_motor() const { return false; }
376   virtual bool has_head_load() const { return true; }
377   virtual bool has_side_check() const { return true; }
378};
379
380class wd2797_t : public wd177x_t {
381public:
382   wd2797_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
383
384protected:
385   virtual bool has_ready() const { return true; }
386   virtual bool has_motor() const { return false; }
387   virtual bool has_head_load() const { return true; }
388   virtual bool has_side_select() const { return true; }
389   virtual bool has_sector_length_select() const { return true; }
390};
391
392class wd1770_t : public wd177x_t {
393public:
394   wd1770_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
395
396protected:
397   virtual bool has_motor() const { return true; }
398   virtual bool has_precompensation() const { return true; }
399};
400
401class wd1772_t : public wd177x_t {
402public:
403   wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
404
405protected:
406   virtual bool has_motor() const { return true; }
407   virtual bool has_precompensation() const { return true; }
408   virtual int step_time(int mode) const;
409   virtual int settle_time() const;
410};
411
412class wd1773_t : public wd177x_t {
413public:
414   wd1773_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
415
416protected:
417   virtual bool has_motor() const { return false; }
418   virtual bool has_head_load() const { return true; }
419   virtual bool has_side_check() const { return true; }
420};
421
422extern const device_type FD1771x;
423extern const device_type FD1793x;
424extern const device_type FD1797x;
425extern const device_type WD2793x;
426extern const device_type WD2797x;
427extern const device_type WD1770x;
428extern const device_type WD1772x;
429extern const device_type WD1773x;
430
431#endif
trunk/src/mess/machine/tvc_hbf.h
r19166r19167
55
66#include "emu.h"
77#include "machine/tvcexp.h"
8#include "machine/wd1772.h"
8#include "machine/wd_fdc.h"
99#include "formats/tvc_dsk.h"
1010
1111
trunk/src/mess/machine/b2m.c
r19166r19167
1212#include "imagedev/cassette.h"
1313#include "machine/i8255.h"
1414#include "machine/pit8253.h"
15#include "machine/wd1772.h"
15#include "machine/wd_fdc.h"
1616#include "machine/pic8259.h"
1717#include "machine/i8251.h"
1818#include "includes/b2m.h"
trunk/src/mess/machine/adam_fdc.h
r19166r19167
1919#include "formats/mfi_dsk.h"
2020#include "imagedev/floppy.h"
2121#include "machine/adamnet.h"
22#include "machine/wd1772.h"
22#include "machine/wd_fdc.h"
2323
2424
2525
trunk/src/mess/includes/v1050.h
r19166r19167
2020#include "machine/scsicb.h"
2121#include "machine/scsihd.h"
2222#include "machine/v1050kb.h"
23#include "machine/wd1772.h"
23#include "machine/wd_fdc.h"
2424#include "video/mc6845.h"
2525
2626#define SCREEN_TAG            "screen"
trunk/src/mess/includes/b2m.h
r19166r19167
1010#include "machine/i8255.h"
1111#include "machine/pit8253.h"
1212#include "machine/pic8259.h"
13#include "machine/wd1772.h"
13#include "machine/wd_fdc.h"
1414#include "sound/speaker.h"
1515#include "sound/wave.h"
1616
trunk/src/mess/includes/super6.h
r19166r19167
1717#include "machine/z80pio.h"
1818#include "machine/ram.h"
1919#include "machine/terminal.h"
20#include "machine/wd1772.h"
20#include "machine/wd_fdc.h"
2121
2222#define Z80_TAG         "u30"
2323#define Z80CTC_TAG      "u20"
trunk/src/mess/includes/bw2.h
r19166r19167
1313#include "machine/pit8253.h"
1414#include "machine/ram.h"
1515#include "machine/serial.h"
16#include "machine/wd1772.h"
16#include "machine/wd_fdc.h"
1717#include "video/msm6255.h"
1818#include "rendlay.h"
1919
trunk/src/mess/includes/atarist.h
r19166r19167
1616#include "machine/mc68901.h"
1717#include "machine/rescap.h"
1818#include "machine/rp5c15.h"
19#include "machine/wd1772.h"
19#include "machine/wd_fdc.h"
2020#include "sound/ay8910.h"
2121#include "sound/lmc1992.h"
2222
trunk/src/mess/includes/einstein.h
r19166r19167
1010#include "video/mc6845.h"
1111#include "cpu/z80/z80daisy.h"
1212#include "imagedev/floppy.h"
13#include "machine/wd1772.h"
13#include "machine/wd_fdc.h"
1414#include "machine/z80ctc.h"
1515
1616/***************************************************************************
trunk/src/mess/includes/samcoupe.h
r19166r19167
1111#ifndef SAMCOUPE_H_
1212#define SAMCOUPE_H_
1313
14#include "machine/wd1772.h"
14#include "machine/wd_fdc.h"
1515
1616/* screen dimensions */
1717#define SAM_BLOCK         8
trunk/src/mess/includes/xerox820.h
r19166r19167
1111#include "machine/scsibus.h"
1212#include "machine/scsicb.h"
1313#include "machine/scsihd.h"
14#include "machine/wd1772.h"
14#include "machine/wd_fdc.h"
1515#include "machine/z80pio.h"
1616#include "machine/z80ctc.h"
1717#include "machine/z80dart.h"
trunk/src/mess/drivers/mirage.c
r19166r19167
6767#include "cpu/m6809/m6809.h"
6868#include "machine/6850acia.h"
6969#include "machine/6522via.h"
70#include "machine/wd1772.h"
70#include "machine/wd_fdc.h"
7171#include "formats/esq8_dsk.h"
7272#include "formats/mfi_dsk.h"
7373#include "formats/dfi_dsk.h"
trunk/src/mess/drivers/esq1.c
r19166r19167
115115#include "cpu/m6809/m6809.h"
116116#include "sound/es5503.h"
117117#include "machine/68681.h"
118#include "machine/wd1772.h"
118#include "machine/wd_fdc.h"
119119
120120#include "machine/esqvfd.h"
121121
trunk/src/mess/drivers/einstein.c
r19166r19167
6161#include "video/tms9928a.h"
6262#include "cpu/z80/z80.h"
6363#include "cpu/z80/z80daisy.h"
64#include "machine/wd1772.h"
64#include "machine/wd_fdc.h"
6565#include "formats/hxcmfm_dsk.h"
6666#include "formats/mfi_dsk.h"
6767#include "formats/dsk_dsk.h"
trunk/src/mess/drivers/samcoupe.c
r19166r19167
3434
3535/* components */
3636#include "cpu/z80/z80.h"
37#include "machine/wd1772.h"
37#include "machine/wd_fdc.h"
3838#include "machine/msm6242.h"
3939#include "machine/ctronics.h"
4040#include "sound/saa1099.h"
trunk/src/mess/drivers/ht68k.c
r19166r19167
2929#include "formats/hxcmfm_dsk.h"
3030#include "formats/mfi_dsk.h"
3131#include "imagedev/flopdrv.h"
32#include "machine/wd1772.h"
32#include "machine/wd_fdc.h"
3333#include "machine/terminal.h"
3434
3535
trunk/src/mess/drivers/esq5505.c
r19166r19167
9696#include "cpu/m68000/m68000.h"
9797#include "sound/es5506.h"
9898#include "machine/68681.h"
99#include "machine/wd1772.h"
99#include "machine/wd_fdc.h"
100100#include "machine/hd63450.h"    // compatible with MC68450, which is what these really have
101101#include "formats/esq16_dsk.h"
102102#include "formats/mfi_dsk.h"
trunk/src/mess/drivers/b2m.c
r19166r19167
1717#include "formats/hxcmfm_dsk.h"
1818#include "formats/mfi_dsk.h"
1919#include "imagedev/flopdrv.h"
20#include "machine/wd1772.h"
20#include "machine/wd_fdc.h"
2121#include "machine/ram.h"
2222#include "includes/b2m.h"
2323

Previous 199869 Revisions Next


© 1997-2024 The MAME Team