Zitat von markusC64PS: Ich gehe davon aus, dass die von Dir o. g. Zeiten für Double Density sind, für High bzw. extra density sind andere Zeiten anzunehmen.
101 -> 4 micro
1001 -> 6 micro
10001 -> 8 micro
Ja die Zeiten gelten für Double Density. Für HD jeweils die Hälfte. SD (FM) und DD (MFM) basieren auf der gleichen Hardware.
FM wird aktuell nicht emuliert. Der Controller unterstützt es zwar aber der entsprechende PIN zwingt den Controller im Rahmen der 1571/1581 permanent auf MFM.
<FM>
Clockbit ist immer 1.
Datenbit : 1 => FM : 11 [4 + 4 micro]
Datenbit : 0 => FM : 10 [4 + 4 micro]
ergibt 2 mögliche patterns im FM stream
<MFM>
Clockbit ist nur 1, wenn Daten Bit davor eine 0 ist
Datenbit : 1 => MFM : 01
Datenbit : 0 => MFM : 10 oder 00 (wenn Bit davor eine 1 ist)
ergibt 3 mögliche patterns, siehe Anfang des postings
Da niemals zwei Einsen direkt nebeneinander stehen, kann die Bit Zelle von 4 micro auf 2 reduziert werden ohne das Flusswechsel zu dicht nebeneinander stehen und erreicht somit eine Verdopplung der Datendichte von FM zu MFM.
Der MFM Controller prüft die Zeit zwischen 2 Flusswechseln.
Vergehen zwischen 2 Flusswechseln 3.4 - 4.4 micro wird es als MFM Folge 101 gewertet.
Vergehen zwischen 2 Flusswechseln 5.4 - 6.4 micro wird es als MFM Folge 1001 gewertet.
Vergehen zwischen 2 Flusswechseln 7.4 - 8.4 micro wird es als MFM Folge 10001 gewertet.
Alles darüber hinaus sind Weak Bits.
Zitat von markusC64Analog zum GCR müsste man daraus ja Sektorheader und Sektordaten extrahieren sowie Prüfsummen berechnen und prüfen... und im Idealfall (nein, eigentlich für ein universelles Tool notwendig) die Sektorgröße erkennen... kann ja verschieden groß sein. Was im Wesentlichen einer Formatbeschreibung des "Sektors" bedarf (also raw, nicht auf Nutzdatenebene).
Und ganz wichtig: Welche Fehler kann der in der 1570/1571/1581 eingesetzte Controller liefern... während ich alles andere eher allgemein für MFM behandeln möchte, muss man an der Stelle wohl doch auf konkrete Fehler zurückgehen - die U2+/U64 wird die bei der 1571 wohl nur durchschleusen, und Du hast ja die selbe G71 Erweiterung...
Ich würde das durch kurze Beschreibungen der 5 Lese/Schreib Kommandos beantworten. Fehler Status Beschreibungen sind mit enthalten.
typischer Aufbau eines Tracks
------------------------------------
Index Adreßmark (optional) -> Lücke (80x $4e), 12x $0, 3x $f6 ($C2 mit fehlendem Clock Bit), 1x $fc, 50x $4e
- jeweils pro Sektor -
ID Feld des Sektors -> 12x $0, 3x $f5 (A1 mit fehlendem Clock Bit), 1x $fe, Track, Seite, Sektor, Sektor Größe, CRC1, CRC2, 22x $4e
Daten Feld des Sektors -> 12x $0, 3x $f5 (A1 mit fehlendem Clock Bit), 1x $fb, SEKTOR DATEN, x $4e (Anzahl festgelegt beim Formatieren)
Sync Marks: A1 entspricht MFM: $4489, C2 entspricht $5224
<Write Track>
Beim Formatieren Kommando wird jedes übergebene Byte auch geschrieben und der CRC berechnet. Ausnahme sind die Bytes F5, F6 und F7.
Kommando startet Schreibvorgang bei nächster Index Hole und läuft bis die Index Hole ein zweites Mal erkannt wird.
F5
--
schreibt $A1 mit fehlendem Clockbit, so dass die MFM Folge LMLM entsteht. (hint: 101 => S, 1001 => M, 10001 => L)
initialisiert CRC zu 0xcdb4
F6
--
schreibt $C2 mit fehlendem Clockbit, so dass die MFM Folge SMLM entsteht.
initialisiert CRC NICHT.
dient zum Kennzeichnen des Index Adreßmarks, dieser muss beim Formatieren aber nicht zwingend gesetzt werden.
hint: dieses Muster ist nicht weise gewählt (Design Fehler) und kann auch in Sektor Daten vorkommen. Es ist aber nur ein Problem bei Verwendung des Read Track Kommandos.
Beim Read Sector Kommando wird der AM Detector innerhalb des Lesens von Sektor Daten deaktiviert.
F7
--
schreibt den bis dahin selbst berechneten CRC (2 bytes). Damit das Sinn macht, sollte vorher also ein F5 geschrieben worden sein, zwecks CRC Initialisierung.
F7 maskiert direkt folgende F5, F6 und F7 z.B:
F7 F5 -> schreibt 2 CRC bytes und dann F5, nicht A1 mit fehlendem Clock Bit
F7 F7 F7 -> schreibt 2 CRC bytes, dann zweimal F7
<Read oder Wtite Sektor>
--- für Read und Write gleichermaßen ---
Das Read Sektor Kommando sucht nach dem A1 Sync Mark mit fehlendem Clockbit. Das ergibt die MFM Folge: 0x4489
Außerdem weiß der Controller nun, das das nächste Bit ein Clock Bit sein muss.
Es müssen zwingend 3 A1 Bytes (mit fehlendem Clock Bit) in Folge sein, gefolgt von $fc, $fd, $fe oder $ff. Nun ist der Mark als ID Feld erkannt.
Im Anschluss folgen die Bytes für Track, Side, Sektor, Sektor Größe und CRC. Track u. Sektor Register werden mit dem gelesenen abgeglichen um zu schauen ob der gewünschte Sektor erreicht ist.
Jedes der 3 A1 initialisiert den CRC zu $cdb4. Der Controller cheatet hier. Ein CRC, initialisiert mit 0xFFFF gefolgt von 3x A1 ergibt den CRC $cdb4.
1x $fe, Spur, Seite, Sektor, Sektor Größe müssen dann den CRC ergeben, welcher in den nächsten 2 Bytes gelesen wird. Andernfalls wird der entsprechende Status 'CRC ERROR' gesetzt und der Controller
beginnt von vorne. Das Kommando läuft also weiter. Wenn 5 mal der Index Hole erreicht wurde, ist allerdings Schluss und das entsprechende Status Bit wird gesetzt. 'RECORD NOT FOUND'
--- Read ---
Nach erfolgreich erkanntem ID Feld für den angeforderten Track/Sektor muss der Controller innerhalb von 44 gelesenen Bytes das Datenfeld finden, ansonsten geht es zurück zum Anfang, bis 5 Index Holes erreicht sind.
Es müssen zwingend 3 A1 Bytes (mit fehlendem Clock Bit) in Folge sein, gefolgt von $f8, $f9, $fa oder $fb. Nun ist der Mark als Daten Feld erkannt.
$fa und $fb gelten als DAM (Data Adreß Mark)
$f8 und $f9 gelten als DDAM (Deleted Data Adreß Mark) -> Status Bit für Record Type wird gesetzt.
Wichtig: Nun wird der AM Detektor deaktiviert. Für $A1 wäre es nicht so schrecklich wichtig, da das pattern sowieso nicht durch Sektor Daten entstehen kann. $C2 jedoch
kommt ab und an vor und würde das nächste Bit als Clock Bit interpretieren und den Bit Counter mit 0 initialisieren. Folgende Bytes würden falsch eingelesen werden.
Nun fordert der Controller über ein Flag im Status Register die CPU auf das gelesene Byte abzuholen (Data Request). Sollte dies nicht passieren bis zum nächsten fertigen Byte
wird das Status Flag 'LOST' gesetzt aber das Kommando läuft weiter.
Im ID Feld steht die Sektor Größe. Ist die entsprechende Anzahl Bytes gelesen, werden die nächsten 2 gelesenen Bytes als CRC betrachtet und mit dem berechneten CRC verglichen.
Passt das nicht wird das Kommando beendet und das CRC Error Flag im Status Register gesetzt.
--- Write ---
liest 2 dummy Bytes, setzt Data Request Flag im Status Register, check nach weiteren 9 dummy Bytes ob CPU erstes Sektor Byte übergeben hat, wenn nicht setzt 'LOST' Flag im Status Register
und beendet Kommando. Nach weiteren 11 gelesenen dummy Bytes wird endlich das write gate aktiviert, schreibt 12x 0, 3x $A1 (mit fehlendem clockbit), 1x $F8 oder $FB, abhängig
von Bit 0 des Kommandos (DAM oder DDAM). Schreibt jetzt das bereits übergebene erste Sektor Byte und fordert nun entsprechend der Sektor Größe aus dem ID Feld über das
Status Flag 'Data Request' die CPU auf weitere nachzuschieben. Sollte die CPU es nicht rechtzeitig schaffen, wird das Status Flag 'LOST' gesetzt. Das Kommando läuft allerdings
weiter und schreibt eine 0. CRC wird für alle geschriebenen Bytes nach der Initialisierung ($F5) berechnet und am Sektor Ende ergänzt.
--- für Read und Write gleichermaßen ---
Wenn im Kommando das Bit für multiple Sektoren gesetzt ist, wird das Sektor Register um eins erhöht und der Prozess beginnt von vorne, Kommando läuft also weiter.
Sollte das Sektor Register nun den höchstmöglichen Sektor überschreiten, versucht er erfolglos im Rahmen von 5 index holes den Sektor zu finden und beendet das Kommando.
<Read Address>
stimmt mit der Suche des ID Feldes von Read/Write Sektor überein. Nur hierbei wird der Track und Sektor nicht mit den beiden Registern verglichen, sondern das nächste Sektor ID Feld gelesen.
Nachdem Sync Mark wird der AM Detektor abgeschalten und die folgenden 6 Bytes gelesen.
Track, Seite, Sektor, Sektor Größe, CRC1, CRC2. Für diese wird im Gegensatz zu Read Sector das Data Request Bit im Status Register gesetzt und erwartet, dass die CPU die
Daten abholt. Passiert das nicht, läuft das Kommando weiter, setzt jedoch das 'LOST' Flag.
Zudem wird der gelesene Track ins Sektor Register kopiert, zwecks späteren Vergleichen der CPU mit dem Track Register.
Type 1 Kommandos, welche dem Track Stepping dienen, aktualisieren das Track Register. Nun kann mittels diesem Kommando überprüft werden ob vom angenommenen Track im Register auch
tatsächlich gelesen wird. Die Pins für stepping und direction sind in der 157x nicht angeschlossen. Dennoch können Type 1 Kommandos verwendet werden, da beide Pins auf Output stehen. Der Controller
hat keine Ahnung, dass diese ins Leere führen.
CRC wird validiert und bei fehlender Übereinstimmung das entsprechende Status Bit gesetzt.
Das Kommando läuft endlos, wenn kein ID Feld erkannt wird und muss dann mittels einem Force Interrupt beendet werden.
<Read Track>
dient der Analyse. Läuft von Index Hole zu Index Hole, wie Write Track. Alles wird der CPU zur Verfügung gestellt. Wie immer gilt, dass bei nicht rechtzeitig abgeholtem Byte
der LOST Flag im Status Register markiert wird.
Doch Vorsicht der AM Detektor wird hierbei nicht abgeschalten. Jetzt kann es passieren, dass ein $C2 mit fehlendem Clock Bit einen Sync auslöst.
Der Controller wird dann das nächstes Bit als Clock Bit werten und den Bit Counter auf 0 setzen.
Das MFM pattern 0x5224 ($C2 mit fehlendem Clockbit) kann durchaus in Sektor Daten vorkommen.
CRC wird nicht berechnet und geprüft.
-------------------------
Fuzzy Bits
Diese sind noch interessant zu erwähnen, da sie nicht im Rahmen der GCR Hardware vorkommen.
Der Controller verwendet ein Inspection Window und verschiebt dessen Phase ständig in Abhängigkeit von Motor Schwankungen derart, dass der Flusswechsel mittig bleibt.
Was passiert nun aber wenn der Flusswechsel z.B. zwischen 4.5 und 5.3 micro liegt. Dieser Bereich ist nicht sicher und befindet sich nun am Rand des Inspection Windows.
Je nach Motor Schwankung detektiert der Controller den Flusswechsel in diesem oder nächsten Window. Entweder wird das MFM pattern 101 oder 1001 erkannt.
Natürlich ist der Controller rein digital und erzeugt keine Zufälle. Die Motor Schwankungen verursachen das indirekt.
Z.b. Dungeon Master auf dem Atari hat Flusswechsel Abstände von 5 micro. Der Controller liest mehrfach über den gleichen Bereich und die Software prüft ob die Werte
sich unterscheiden. Unterscheiden diese sich nicht, handelt es sich um eine Kopie. Der Controller kann keine Abstände von 5 micro schreiben.
Der Controller schreibt 4, 6 oder 8 micro (+/- 128 nano für write precompensation in den inneren Tracks) Das liegt noch gut in der Toleranz.
Auf 3.5 Zoll Disketten wird write precompensation in der Regel auf allen Tracks angewandt.
In der Emulation besteht aktuell der selbe Zufall beim Lesen zwischen 4.5 u. 5.3, entweder 101 oder 1001.
Noch besser wäre es den Zufall nahe 5 micro maximal werden zu lassen und an den Rändern minimal. 4.5 wird sicherlich in den meisten Fällen 101 liefern
und 5.3 in den meisten Fällen 1001
Write Precompensation
...