Floppyspielereien Teil 6: Heftige Nachwehen

Eigentlich wollte ich ja nach dem fünften Teil dieses Kurses (im Novemberheft) in der Versenkung verschwinden. Doch Sie haben zu früh aufgeatmet: Der Floppykurs erfährt eine -wenn auch kurze - Fortsetzung. Häufig gestellte Leserfragen, die alle interessieren könnten, sollen einmal beantwortet werden, außerdem möchte ich noch zu dem einen oder anderen Thema einen Nachtrag bringen.

Frage 1: Kann ich die Anzahl der FATs im Bootsektor auch auf 1 abändern und so mehr Platz auf der Diskette schaffen?

In der ST-Computer 7/87 hatte ich noch spekuliert, daß dies wohl möglich sei. Mittlerweile haben Tests aber ergeben, daß GEMDOS auf andere FAT-Anzahlen als zwei nicht vorbereitet ist. Es ist und bleibt eben der Schwachpunkt im Betriebssystem des ST, das GEMDOS. An anderer Stelle in diesem Heft finden Sie im GEMDOS-Kurs von Alex Esser (sei gegrüßt!) mehr Informationen zu diesem leidigen Thema.

Frage 2: Welche Manipulationen sind mit den fiktiven Verzeichniseinträgen 7 und möglich?

Wahrscheinlich keine. Im Teil 2 des Floppykurses habe ich zwar erwähnt, daß diese beiden Einträge in jedem Unterverzeichnis automatisch gebildet werden und durch eine Verzeigerung die Orientierung im Ordnergestrüpp erleichtern können; doch hat sich auch hier herausgestellt, daß GEMDOS diese Einträge überhaupt nicht benutzt, um sich zurecht-zufmden. und sind nur beibehalten worden, um mit MSDOS-Disketten kompatibel zu bleiben (Hallo Alex!).

Frage 3: Welche Probleme gibt es beim Einsatz von HYPERFORMAT?

Nicht mehr viele. Ich hatte ja vor längerer Zeit gemutmaßt, daß eventuell verschiedene Controllerserien an recht merkwürdigen Toleranzen schuld sein könnten, die HYPERFORMAT zu schaffen machten. Mittlerweile ist HYPERFORMAT aber so sicher geworden, daß diese minimalen Schwankungen wohl nicht mehr den Ausschlag geben.

Weiterhin wichtig bleibt aber die Drehzahl Ihres Laufwerks. Sie muß im Bereich von 300 bis 302 Umdrehungen pro Minute liegen und nicht, wie früher erwähnt, im Bereich bis zu 304 Umdrehungen. Auf diese Zahl war ich verfallen, weil mir das Public-Domain-Programm SPEED .TOS immer 1.5 Umdrehungen zuviel anzeigte; das heißt, ein Laufwerk, das die Diskette 300mal pro Minute komplett herumwirbelt, hat laut SPEED .TOS 301.5 Umdrehungen. Mittlerweile habe ich mir meine eigenen Meßprogramme geschrieben, die ihren Dienst korrekt verrichten. Sollten Sie selbst SPEED.TOS verwenden, können Sie bei Drehzahlanzeigen bis 304 Umdrehungen noch ruhig bleiben; darüberhinaus wird es aber langsam brenzlig für HYPERFORMAT. Warum?

HYPERFORMAT benötigt in den jetzigen Versionen etwa 6250 Bytes auf einer Spur. Bei einer normalen Drehzahl hat man die auch, sogar etwa 50 bis 70 Bytes mehr (wenn auch der Hersteller des Floppycontrollers das nicht wahrhaben will). Dreht das Laufwerk aber zu schnell, wird der Platz enger; es kann dann passieren, daß der letzte Sektor auf der Spur nicht mehr komplett geschrieben werden kann.

Es kommt auch vor, daß sich bei zu fixen Laufwerken die Datenfelder der Sektoren etwas verbreitern und die nachfolgenden Lückenbytes überschreiben; geschieht das mehrmals, werden die Synchronisationsbytes des nachfolgenden Adreßfeldes angeknabbert, und die Katastrophe ist nicht mehr weit (Zähne fest zusammenbeißen, Hände in den Nacken, Atem anhalten und beten).

Um dies alles brauchen Sie sich aber meist keine Gedanken zu machen, weil die Laufwerke im Normalfall schon ab Werk richtig justiert sind. Nun ist aber bei ATARI eigentlich nichts normal, und deswegen gibt es immer wieder Laufwerke, die nicht genau genug eingestellt sind, was man aber selbst leicht nachholen kann. Bei der alten SF314 (Epson-Laufwerk, zu erkennen am lauten Röhren des Drehmotors und der kleinen Auswurftaste) geht man zum Beispiel folgendermaßen vor:

  1. Laufwerk aufschrauben (vorher alle Kabel weg)
  2. Anschlußplatine abziehen, Metallumhüllung des eigentlichen Laufwerks abschrauben.
  3. Laufwerk umdrehen; auf der Unterseite findet sich ein kleiner Trimmer mit der Bezeichnung VR01, der für die Geschwindigkeitsregelung zuständig ist.
  4. Anschlußplatine wieder ans Laufwerk stecken, Kabel installieren, Rechner und Laufwerk anschalten (keine Angst, es laufen nur 5V- und 12V-Leitungen durchs Laufwerk, das beeindruckt Ihren Herzschrittmacher nicht im geringsten), Meßprogramm für die Geschwindigkeit laden (siehe auch Listing 1 und die dazugehörige Dokumentation) und starten.
  5. Geschwindigkeit auf 300 Umdrehungen pro Minute einstellen (vorsichtig an VR01 drehen!).
  6. Alles wieder ausschalten und zusammenschrauben, leise vergnügt vor sich hin pfeifen, Rechner anschalten und alle Disketten auf HYPERFORMAT umformatieren.

Im Listing 1 und der zugehörigen Dokumentation finden Sie eine Routine, die Sie in den Extended Minimon (siehe ST-Computer 9/87 und 10/87) einbinden können. Sie mißt die aktuelle Drehzahl und errechnet auch einen Durchschnittswert.

Bei anderen Laufwerkstypen (selbst von den Original-ATARI-Laufwerken gibt es mindestens vier Versionen, von den Laufwerken im 1040 oder in den MegaSTs ganz zu schweigen) mag der Regler anders heißen und auch anders zu erreichen sein, das Prinzip bleibt dasselbe. Eine ausführliche Anleitung für einige ausgewählte Laufwerkstypen finden Sie in meinem Floppybuch, das dem nächst wohlfeil im Handel zu erstehen ist. Dort finden Sie übrigens nebst anderen Überraschungen auch eine neue Über-Giga-Version von HYPERFORMAT (V3.0).

Frage 4: Mein Laufwerk schlägt schon bei Spur 80 an; kann man das irgendwie ändern?

Man kann eventuell. Zu diesem Thema hat mich sogar einmal ein Leser angerufen, der sich etwas ausgedacht hatte. Er hatte irgendwelche mechanischen Begrenzungen in seinem Laufwerk einfach abgeschleift, was natürlich ein wenig hemdsärmlig ist. Aber es funktionierte dann doch so gut, daß er - Zitat - ”den Lesekopf so weit nach innen bewegen kann, bis er aus der Halterung fällt”. Auf diese Weise kann man einige innere Spuren (80 bis 85) noch zur Datenspeicherung nutzen und - per HYPERFORMAT - über 960000 Bytes auf eine Diskette quetschen. Ich möchte Ihnen davon abraten, höhere Spuren als Spur 85 zu benutzen, weil dort Ihre Daten wirklich nicht mehr sonderlich sicher wären. Leider habe ich nichts mehr von diesem mutigen Zeitgenossen gehört; er möge sich doch, falls er diese Zeilen hier liest, noch einmal bei mir melden. Danke.

MEA MAXIMAL* CULPA

So, und nun möchte ich mich für einige meiner Fehlgriffe im Floppykurs entschuldigen. Ein paar Details sind doch nicht so korrekt gewesen, wie ich sie nach bestem Wissen und Gewissen ausgeforscht und niedergeschrieben hatte. Zum Glück handelt es sich vergleichsweise um Kleinigkeiten.

In der ST-Computer 11/87 verhinderte beispielsweise ein dummer Tippfehler, daß Sie die wahre Codierung der Steprate in Controllerbefehlen erführen. Hier die korrigierte Tabelle (Tabelle 1):

Stepratenfeld Steprate
r1 r0
0 0 6ms
0 1 12ms
1 0 2ms
1 1 3ms

(Tabelle 1: Das Stepratenfeld in FDC-Befehlen, diesmal hoffentlich richtig abgetippt)

Im dritten Teil habe ich die Belegung der Adresse SFF8606 (DMAModus-Register) erläutert. Dieses Register ergibt -wenn man es liest - den aktuellen DMA-Status. In Bit 0 steht dann aber nicht, wie irrtümlich abgedruckt, eine 0, wenn kein DMA-Fehler aufgetreten ist, sondern eine 1.

Mein schlimmster Schnitzer aber - und das haben auch einige erkannt und mich je nach Temperament mehr oder weniger verärgert darauf hingewiesen - war die Darstellung der FATStruktur im ersten Teil des Floppykurses. Dort hatte ich folgenden Anfang einer FAT angegeben:

F7 FF FF 03 40 00 05 FF F0

Eine solche FAT kann unter TOS gar nicht existieren, die letzten beiden Bytes müßten eigentlich vertauscht sein. Schon damals hatte ich ja einen Hilferuf an Sie, verehrte Leserin, lieber Leser, abgesetzt, da ich selbst anfangs mit der FAT so meine Schwierigkeiten hatte. In der Zwischenzeit habe ich durch eigene Experimente und nicht zuletzt durch einige nette Zuschriften viel darüber gelernt und möchte das an dieser Stelle weitergeben.

FATsucht, Teil II

Auf der FAT ist die Belegung einer Diskette mit Dateien vermerkt. Dabei werden aber immer komplette Cluster belegt; das sind normalerweise zwei zusammenhängende Sektoren. Eine FAT könnte nun so anfangen:

F7 FF FF 03 40 00 05 F0 FF

Jedem Cluster werden in der FAT 12 Bit (!) zugewiesen, das sind drei Hexadezimalziffern. TOS und Brüderchen MS-DOS beginnen die Nummerierung ihrer Cluster erst mit 2, die fiktiven Cluster 0 und 1 sind reserviert. In der FAT stehen an ihrer Stelle, wie man oben sieht, einige mysteriöse Bytes, die in TOS keine Wirkung haben und deswegen auch Null sein können. Unter MSDOS ist das erste Byte das sogen an n te Media-Byte und entspricht seinem Pendant im Bootsektor (siehe Floppykurs Teil II). Daß hier beim ST seltsamerweise nach dem Formatieren im Desktop eine $F7 steht, ist ein Grund, warum man ST-Disketten auf MSDOS-Maschinen doch nicht so ohne weiteres lesen kann.

Prinzipiell ist die FAT einfach zu verstehen. Im Diskettenverzeichnis steht für jede Datei ein Zeiger auf den ersten Cluster, den diese Datei belegt (siehe dazu auch Floppykurs, Teil II, über das Inhaltsverzeichnis der Diskette). Diesen Zeiger verwendet TOS, um an die betreffende Stelle der Blockbelegungstabelle zu springen. Dort hat nämlich jeder Cluster auf der Diskette einen eigens für ihn reservierten Platz in der FAT: Cluster 2 bekommt Platz Nr. 2, Cluster 500 hat Platz 500.

Nehmen wir an, in der Directory steht als erster Cluster die ’2’. Im FAT-Eintrag für Cluster 2 steht eine weitere Clusternummer ’3’. Aha, denken wir uns, die Datei setzt sich also auch in Cluster 3 fort. Mit dieser Drei springen wir in den FAT-Eintrag für Cluster 3- Dort finden wir wieder einen Verweis auf eine andere Clusternummer (nicht unbedingt auf Cluster 4).

Irgendwann ist auch die längste Datei am Ende: Dies wird in der Regel durch die fiktiven Clusternummern $FF8-$FFF angezeigt. Ein Wert von $FF0 bis $FF7 in einem FAT-Eintrag bedeutet, daß der betroffene Cluster beschädigt ist, also nicht belegt werden kann. Außerdem bedeutet ein Wert 0 in einem FAT-Eintrag, daß der Cluster frei ist.

Während das noch recht einsichtig klingt, werden Sie jetzt in der Praxis Ihre Schwierigkeiten haben. Denn auch die FAT-Einträge werden im Intel-Format abgespeichert, das heißt, niedrigstwertiges Byte zuerst. Dadurch ergibt sich in einer FAT ein ziemlich undurchsichtiger Wust, nämlich in unserem Beispiel:

F7 FF FF 03 40 00 05 F0FF...
(Bytenr: 012345678...)

MS-DOS und auch TOS füllen nämlich 16-Bit-Zahlen, die auf der Diskette im INTEL-Format stehen, mit den 12-Bit-Einträgen auf. Um das zu verstehen, lassen Sie uns das Konzept der Über-Cluster einführen. Das sind ganz einfach immer drei Bytes in der FAT. Der erste Über-Cluster in unserer Beispiel-FAT wäre dann F7 FF FF und interessiert uns nicht, weil er ja nur für die fiktiven Cluster 0 und 1 benutzt wird. Der zweite Über-Cluster ist schon interessanter:

0 3 4 0 00
+ +   +

Nun nehmen wir an, ein Directoryeintrag zeige auf den Clustereintrag Nummero 2, also auf den Anfang unseres zweiten Über-Clusters. Die mit ”T” gekennzeichneten Nibbles (halbe Hexzahlen sozusagen) gehören zum ersten Cluster des Über-Clusters; da wir Intel-Format vor uns haben, muß die Null aus dem zweiten Byte noch vor die ”03”, also: 003, und schon haben wir die Nummer des nächsten Folgeclusters. Diese 003 zeigt auf den Clustereintrag 3 in der FAT, und der ist im nicht markierten Bereich des obigen Über-Clusters zu finden. Mit diesen nicht gekennzeichneten Nibbles verfährt man ähnlich wie vorhin, auch hier rutscht der höherwertige Teil (”00”) nach vorne, so daß wir eine hübsche 004 erhalten.

Für diejenigen, die das Selbermachen lieben, ist noch wichtig herauszufinden, wo ein bestimmter Eintrag in der FAT steht, und wie man algorithmisch vorgeht. Dazu gibt es ein Kochrezept:

Man prüfe, ob die gesuchte Clusternummer gerade ist. Ist sie das, multipliziere man sie mit 1.5 und lese dann das Wort ab der errechneten Stelle. Also zum Beispiel für die Clusternummer 4:

4 ist gerade, mal 1.5 ergibt 6, also liest man ab Byte 6 der Bei-spiel-FAT das Wort $05F0. Das dreht man wegen des Intel-Formats um zu $F005 und ignoriert das oberste Nibble - ergibt $005.

Ungerade Clusternummern multipliziert man ebenfalls mit 1.5 und ignoriert den Nachkommaanteil. Beispiel: Clusternummer 3 mal 1.5 ergibt 4.5. Ohne Nachkommastellen also 4. Ab Byte 4 lesen wir das Wort $4000. Was kommt jetzt? Richtig, Byteschaufelei wegen Intel-Format und so (Ergebnis $0040). Von diesem Ergebnis fällt das unterste Nibble weg (entspricht einer Division durch 16 oder 4 Rechtsshifts): Macht $004.

Wenn Sie diesen Algorithmus nachvollziehen und mit dem Konzept der Über-Cluster vergleichen, -werden Sie feststellen, daß ein Über-Cluster immer an einem geraden Clustereintrag beginnt. Ist die Nummer des gesuchten Eintrags also gerade, greift man auf die mit ”+” markierten Nibbles zu, ansonsten auf die anderen. Genau dieses Verhalten bildet der Algorithmus nach.

Ich denke, damit sind Sie fürs erste genügend verwirrt. Das war jetzt aber wirklich der vorläufig letzte Teil des Floppykurses; ich möchte mich jetzt meiner Festplatte widmen. Mal sehen, ob sich da ähnlich viel herausholen läßt wie aus der Floppy und deren Controller. Keep hacking, Ihr

Listing 1:

' Minimon für den ST 
' Written 1987 by Claus Brod
'                 Am Felsenkeller 2 
'                 8772 Marktheidenfeld
'
' V.2.1 mit rudimentärer Registerroutine 
' V.2.2 Registerroutine korrigiert, zusätzliche Fileausgabe 
' V.2.3 mit Speedtest
'
Cls
Do
    Print
    Print "Minimon ST - (C) 1987 by Claus Brod"
    Print
    Repeat
        Print "Sektormonitor oder Trackmonitor oder Quit (S/T/Q)?"
        A$=Upper$(Input$(1))
    Until A$="S" Or A$="T" Or A$*"Q“
    Exit If A$="Q"
    If A$="S"
        @Sektormon
    Else
        @Trackmon
    Endif
Loop
End
'
'
Procedure Gibmirzeit 
    Alert 1,"Funktion noch nichtI implementiert.",1,"OK",A 
Return
'
' Prozedur Trackmon 
' initialisiert den Trackmonitor 
' zeigt in einer Schleife das Menü an, fragt auf Tastendruck ab 
' und verteilt auf die Unterroutinen
'
Procedure Trackmon 
    @Init_trackmon 
    Cls
    Prn%=0
    Richtung%=0
    Seite%=0
    Drive%=0
    Steprate%=1 ! 3ms Steprate
    R$=Chr$(27)+"p"
    O$=Chr$(27)+"q"
    @Rst ! auf Track 0 zurückfahren
    Do
        Print
        Print "************ TRACKMON (C) ***********"
        @Prntable
        Print R$;"0";O$;" Track 0, ";R$;"1";O$;"Step, ";R$;"2";O$;" Step-In, "; 
        Print R$;"3";O$;" Step-Out, ";R$;"4";O$;"Seek, ";R$;"5";O$;" Rd Sec, ";
        Print R$;"6";O$;" Wr Sec"
        Print R$;"7";O$;" Rd Adr. ";R$;"8";O$;"Rd Trk, ";R$;"9";O$;" Wr Trk, "; 
        Print R$;"A";O$;" IRQ, ";R$;"D";O$;"ump Buf. ";R$;"S";O$;"eite (";Seite%;
        Print "), ";R$;"P";O$;"rn (o":
        If Prn%=1 
            Print "n)"
        Else 
            If Prn%=0 
                Print "ff)"
            Else 
                Print "n file)"
            Endif 
        Endif
        Print R$;"R";O$;"egister, ";R$;"G";O$;"eschwindigkeit, ":R$;"Q";O$;"uit" 
        M$=Upper$(Input$(1))
        Exit If M$="Q"
        If M$="G"
            @Speed 
        Endif 
        If M$="S"
            Seite%=1-Seite% 
        Endif 
        If M$= "P"
            Inc Prn% 
            If Prn%>2 
                Prn%=0 
            Endif 
            If Prn%=2 
                Input "Filename";Fi$
            Endif
        Endif
        If M$="D"
            @Dump_buf 
        Endif 
        If M$="A"
            @Irq ! FOC unterbrechen
        Endif 
        If M$="R"
            @Register
        Endif
        If M$<="9" And M$>="0"
            On Val(M$)+1 Gosub Rst,Step,Step_in,Step_out,Seek,Rdsec,Wrsec,Rdadr 
            On Val(M$)-7 Gosub Rdtrk,Wrtrk 
        Endif 
    Loop 
Return
'
'
Procedure Init_trackmon 
    Print "Einen Moment, bitte!"
    Restore Locksley 
    @Readprog(1000)
    ' LOCKSLEY.S einlesen 
    Inter$=Prg$
    Inter=Varptr(Inter$)
    Opcode=Inter*3 
    Restore Select
    @Readprog(1000) ! Reserve für Erweiterung
    ' SELECT.S einlesen
    Sel$=Prg$
    Sel=Varptr(Sel$)
    Laufwerk=Sel+3
Return
'
'
Procedure Select 
    Poke Laufwerk,Seite%+2 ! Laufwerk A, Seite "Seite%"
    Call Sel 
Return
Procedure Deselect 
    Poke Laufwerk,0 ! deselektieren
    Call Sel 
Return
'
Procedure Mach_schon(O%)
    @Select         ! Laufwerk selektieren
    Poke Opcode,O%
    Call Inter      ! Kommando ausführen
    @Deselect       ! Laufwerk abwählen
Return
'
Procedure Register
    ' se1+3:8 für lesen, 9 für schreiben, 10 für DMA-Status
    ' in sel+4 wird das Register übergeben 
    ' in sel+8 wird der Wert übergeben 
    Print R$;"Register";O$
    Print R$;"L";O$;"esen oder ";R$;"S";O$;"chreiben?"
    Repeat
        A$=Upper$(Input$(1))
    Until A$="L" Or A$="S"
    If A$="L"
        @Get_them_al1 
    Else 
        Op%=9
        Poke Se1+3,Op%
        Print "(1) Kommandoregister"
        Print "(2) Trackregister"
        Print "(3) FDC-Sektorregister"
        Print "(4) Datenregister"
        Print "(5) DMA-Sektorregister"
        Repeat
            A=Val(Input$(1))
        Until A>B And A<6 
        R%=(A-1)*2 
        If A=5 
            R%=16 
        Endif
        Dpoke Sel+4,128+R%
        If Op%=9
            Input "Neuer Wert für das Register";W% 
            Dpoke Sel+8,U%
        Endif 
        Call Sel
        Print "Opcode: $";Hex$(Peek(Sel+3))
        Print "Register: $";Hex$(Dpeek(Sel+4)) 
        Print "Wert: $";Hex$(Dpeek(Sel+8) And 255)
        Print
    Endif
Return
'
'
Procedure Get_them_all 
    Poke Sel+3.8 ! Register lesen
    Dpoke Sel+4,128+0 
    Call Sel
    Print "FDC-Statusregister: $";Hex$(Dpeek(Sel+8) And 255)
    Dpoke Sel+4,128+2 
    Call Sel
    Print "Trackregister:      $";Hex$(Dpeek(Sel+8) And 255)
    Dpoke Sel+4,128+4 
    Call Sel
    Print "FDC-Sektorregister: $";Hex$(Dpeek(Sel+8) And 255)
    Dpoke Sel+4,128+6 
    Call Sel
    Print "Datenregister:      $";Hex$(Dpeek(Sel+8) And 255)
    Dpoke Sel+4,128+16 
    Call Sel
    Print "DMA-Sektorregister: $";Hex$(Dpeek(Sel+8) And 255)
    Poke Sel+3,10       ! DMA-Status lesen
    Call Sel
    Print "DMA-Status:         $";Hex$(Dpeek(Sel+8) And 255)
Return
'
' Prozedur Rst
' fährt den Lesekopf auf Spur 0 zurück
'
Procedure Rst 
    Print R$;"Restore";O$
    Track%=0
    Richtung%=0
    @Mach_schon(0+Steprate%) ! Restore-Befehl 
Return
'
' Prozedur IRQ
' unterbricht den Floppycontroller bei der Arbeit
'
Procedure Speed 
    Local Dr,Lp%,Avr 
    @Irq 
    Cls
    Print At(5.2);"Drehzahlmessung"
    Print At(5.9);" Drehzahl : "
    Print At(5,11);"Durchschnitt : "
    Mfp%=&HFFFA01 
    Genau%=10 
    @Select 
    Dpoke Sel+2,9 
    Dpoke Sel+4,&H80 
    Dpoke Sel+8,&HD4 
    Call Sel
    Repeat ! Warte auf Index
    Until (Peek(Mfp%) And 32)=0 ! Dann Start ! 
    Repeat 
        Dpoke Sel+2,9 
        Dpoke Sel+4,&H80 
        Dpoke Sel+8,&HD4
        T2=Timer
        For T%=1 To Genau% 
            Call Sel 
            Repeat
            Until (Peek(Mfp%) And 32)=0 
            If Inkey$<>"" Or Mousek 
                T%=99 
            Endif 
        Next T%
        Exit If T%=100 
        Dr=120B0*Genau%/(Timer-T2)
        Print At(22,9);Using "###.###",Dr 
        Add Avr,Dr 
        Inc Lp%
        Print At(22,11);Using "###.###",Avr/Lp% 
    Until Inkey$<>"" Or Mousek 
    @Irq
    @Deselect 
Return
'
'
Procedure Irq 
    Print R$;"IRQ";O$
    @Mach_schon(208) ! IRQ-Befehl 
Return
'
' Prozedur Step
' fährt den Lesekopf einen Schritt in die eingeschlagene Richtung
'
Procedure Step
    Print R$;"Step";O$
    Track%=Track%+Richtung% 
    @Mach_schon(32+16+Steprate%) ! Step mit Track-Update
Return
'
' Prozedur Step_in
' fährt den Lesekopf einen Schritt nach innen
'
Procedure Step_in
    Print R$;"Step-in";O$
    Richtung%=l
    Track%=Track%+Richtung% 
    @Mach_schon(64+16+Steprate%) ! Step-in mit Update
Return
'
' Prozedur Step-out
' fährt den Kopf einen Schritt nach aupen
'
Procedure Step_out 
    Richtung%=-1 
    Print R$;"Step-out";O$
    Track%=Track%+Richtung% 
    @Mach_schon(96+16+Steprate%) ! Step-out mit Update
Return
'
' Prozedur Seek 
' fährt den Lesekopf auf die gewünschte Spur
'
Procedure Seek 
    Print R$;"Seek";O$
    Input "Zieltrack";Trk 
    If Trk>Track%
        Richtung%=1 
    Else 
        If Trk<Track%
            Richtung%=-1
        Endif
    Endif
    Track%=Trk
    Poke Inter+5,Trk ! Spurnummer abliefern 
    @Mach_schon(16+Steprate%) ! Seek-Befehl 
Return
'
' Prozedur Rdsec
' liest Sektor(en) auf aktuellem Track ein
'
Procedure Rdsec 
    Print R$;"Read sector";O$
    Input "Welcher Sektor";Sector% 
    Poke Inter+7,Sector% ! Sektornummer schreiben 
    Input "Wieviel Bytes";Laenge 
    Buf$=Space$(12*512)
    Dpoke Inter+8,laenge ! Länge der Übertragung
    Lpoke Inter+10,Varptr(Buf$) ! Pufferadresse
    @Mach_schon(128+16)  ! Read multiple sectors
Return
'
' Prozedur Rdadr
' Liest Adreßfelder auf aktuellem Track ein
'
Procedure Rdadr 
    Print R$;"Read Adress";O$
    Input "Wieviele AdrePfelder";Laenge 
    Dpoke Inter+8,Laenge        ! Zahl der Adrepfelder
    Laenge=Laenge*6             ! 6 Byte pro AdrefSfeld 
    Buf$=Space$()512)
    Lpoke Inter+10,Varptr(Buf$) ! Pufferadresse Buf2$=Space$(180)
    Lpoke Inter+14,Varptr(Buf2$) ! Pufferadresse für Status
    @Mach_schon(192)            ! Rd-Address-Befehl 
Return
'
' Prozedur Wrsec 
' schreibt Sektor(en) auf aktuellen Track
'
Procedure Wrsec 
    Print R$;"Write sector";O$
    Input "Welcher Sektor";Sek 
    Poke Inter+7,Sek ! Sektornummer 
    Input "Wieviel Bytes";Laenge 
    Dpoke Inter+8,Laenge ! Länge der Übertragung
    Lpoke Inter+10,Varptr(Buf$) ! Pufferadresse
    @Mach_schon(168+16) ! Write multiple sectors
Return 
'
' Prozedur Rdtrk 
' Aktuellen Track einiesen
'
Procedure Rdtrk 
    Print R$;"Read Track";O$
    Buf$=Space$(8008)
    Lpoke Inter+10,Varptr(Buf$) ! Pufferadresse 
    Input "Wieviel Bytes":Laenge 
    Dpoke Inter+8,Laenge ! Länge der Übertragung 
    @Mach_schon(192+32) ! Read Track 
Return
'
' Prozedur Wrtrk 
' Einen Track formatieren
'
Procedure Wrtrk 
    Print R$;"Write Track";O$
    T$=Space$(8000)
    ' liest die Trackdaten ab dem Label Trackdaten ein 
    ' Format der Datazeilen:
    ' zu schreibendes Byte, danach Anzahl (nie oft soll dieses Byte geschrieben werden)
    ' "***.***" heit Schluß 
    Restore Trackdaten 
    Cn=1 
    Do
        Read B$,Z$
        @Hextodec(B$)
        B=S
        @Hextodec(Z$)
        Z=S
        Exit If B$="***"
        If Upper$(B$)="TRACK"
            B=Track%
        Endif
        If Upper$(B$)="SIDE"
            B=5eite%
        Endif
        For T=1 To Z 
            Print B
            Mid$(T$,Cn,1)=Chr$(B)
            Inc Cn 
        Next T 
    Loop 
    Print
    Lpoke Inter+10,Varptr(T$) ! Pufferadresse 
    Input "Wieviel Bytes";Laenge 
    Dpoke Inter+8,Laenge ! Länge der Übertragung
    @Mach_schon(15*16) ! Write Track
Return

' Prozedur Dump_buf 
' Gibt ersten oder zweiten Puffer aus 
' und erlaubt ihn zu edieren

Procedure Dump_buf 
    Repeat
        Print "Ersten oder zweiten Puffer ausgeben (1/2)?"
        Ch$=Input$(1)
    Until Ch$="1" Or Ch$="2"
    If Ch$="1"
        Sec$=Buf$
        @Dump(Laenge)
    Else
        Sec$=Buf2$
        @Dump(Len(Buf2$))
    Endif
    Print R$;"Edit (Y/N)?";O$ 
    A$=Upper$(Input$(1))
    If A$="Y"
        If Ch$="1"
            Sec$=Buf$
            @Edit
            Buf$=Sec$
        Else
            Sec$=Buf2$
            @Edit
            Buf2$=Sec$
        Endif 
    Endif 
Return
'
' Prozedur Prntable 
' Statusmeldung ausgeben
'
Procedure Prntable 
    Inter=Varptr(Inter$)
    Opcode=Inter+3
    Sel=Varptr(Sel$)
    Laufwerk=Sel+3
    Print "Opcode                       :";
    Dpeek(Inter+2);Tab(48);
    If Dpeek(Inter+30)=0 
        Print "Kein "; 
    Endif
    Print "Timeout!"
    Print "Track                        :";Track%;Tab(40); 
    Print "Sektor                       :";Dpeek(Inter+6)
    Print "Adresse des Puffers 1        :";Lpeek(Inter+10):Tab(40);
    Print "Adresse des Puffers 2        :";Lpeek(Inter+14)
    Print "FDC-Status                   :";Peek(Inter+19);Tab(40); 
    Print "DMA-Status                   :";Peek(Inter+21)
    Print "Startadresse DMA             :";Lpeek(Inter+22);Tab(40);
    Print "Endadresse DMA               :";Lpeek(Inter+26)
    Print "Gelesene/geschriebene Bytes  :";Dpeek(Inter+8)
Return
'
' Prozedur Readprog 
' Liest Programm aus Datazeilen ein
'
Procedure Readprog(L)
    Prg$=Space$(L)
    T=1
    Repeat 
        Read A$
        If A$<>"***"
            Mid$(Prg$,T,1)=Chr$(Val("&h"+A$)) 
        Endif 
        Inc T 
    Until A$="***"
Return
'
' Prozedur Hextodec 
' Wandelt A$ in Dezimal um (Ziel: S)
'
Procedure Hextodec(A$)
    S=0
    A$=Upper$(A$)
    For I=1 To Len(A$)
        A=Asc(Right$(A$,I))
        If A>64 
            A=A-7 
        Endif 
        A=A-48
        S=S+A*16^(I-1)
    Next I 
Return
'
'
' Sektormon: Kleiner Diskmon mit Standardfähigkeiten
'
Procedure Sektormon 
    Cls
    Prn%=8
    Status%=0
    Seite%=0
    Track%=0
    Sector%=1
    Drive%=8
    Sec$=Space$(512)
    R$=Chr$(27)+"p"
    O$=Chr$(27)+"q"
    @Lesen
    Do
        Print
        Print "**** Minimon (C) 1987 Claus Brod *** Status: ";Status%;" ****" 
        Print R$;"R";O$;"ead, ";R$;"W";O$;"rite, ";R$;"T";O$;"rk (";Track%;"), ";
        Print R$;"S";O$;"eite (";Seite%;"), Se";R$;"k";O$;"tor (";Sector%;"), ";
        Print R$;"E";O$;"dit, ";R$;"D";O$;"ump, ";R$;"P";O$;"rn (o";
        If Prn% 
            Print "n), "; 
        Else 
            Print "ff), "; 
        Endif
        Print "E";R$;"x";O$;"ec, ";R$;"Q";O$;"uit"
        M$=Upper$(Input$(1))
        If M$="X"
            @Exe 
        Endif 
        If M$="P"
            Prn%=1-Prn% 
        Endif 
        If M$="T"
            Input "Track";Track%
        Endif 
        If M$="S"
            Input "Seite";Seite% 
        Endif 
        If M$="K"
            Input "Sektor";Sector% 
        Endif 
        If M$="R" 
            @Lesen 
        Endif 
        If M$="W"
            @Schreiben 
        Endif 
        If M$="E"
            @Edit
        Endif 
        If M$="D"
            @Dump(512)
        Endif
        Exit If M$="Q"
    Loop
Return
'
' Sektor einlesen
'
Procedure Lesen 
    Buffer%=Varptr(Sec$)
    Status%=Xbios(8,L:Buffer%, L:0, Drive%, Sector%, Track%, Seite%, 1)
Return
'
'
' Sektor schreiben
'
Procedure Schreiben 
    Buffer%=Varptr(Sec$) 
    Status%=Xbios(9,L:Buffer%,L:B,Drive%,Sector%,Track%,Seite%,1)
Return
'
'
' Sektorpuffer ausgeben
'
Procedure Dump(L)
    If Prn%=0 
        Open "O",#1,"con:"
    Else
        If Prn%=1 
            Open "0",#1,"prn:"
        Else 
            Open "0",#1,Fi$
        Endif
    Endif
    Print #1,"Track: ";Track%;" Sektor: ";Sector%;" Seite: ";Seite%
    For T=1 To L Step 16 
        A$=Str$(T-1)
        While Len(A$)<3 
            A$="0"+A$
        Wend
        D$="     "
        Print #1,A$;D$;
        For I=0 To 15
            V$=Mid$(Sec$,T+I,1)
            A$=Hex$(Asc(O$))
            If V$<" " Or V$>"z"
                V$=" "
            Endif
            Print #1,Right$("0"+A$,2)
            D$=D$+V$
        Next I 
        Print #1,D$
        A$=Inkey$
        If A$=" "
            A=Inp(2)
        Endif
        Exit If A$>"" And A$<>" "
    Next T 
    Close #1 
Return
'
'
' Byte ändern 
'
Procedure Edit
    Input "Byte Nr.";Byte%
    Print "Alter Wert ist: ";Asc(Mid$(Sec$, Byte%+1,1))
    Input "Neuer Wert in dezimal oder ASCII";Wert$
    Wert%=Val(Wert$)
    If Wert%=0 And Left$(Wert$,1)<>"0" 
        Wert%=Asc(Wert$)
    Endif
    Mid$(Sec$,Byte%+1,1)=Chr$(Wert%)
Return
'
'
' anderes Programm ausführen
'
Procedure Exe 
    Fileselect "*.*","",Sel$
    If Exist(Sel$)<>0 
        S=Fre(0)
        Reserve 50000 
        Showm
        Exec 0,Sel$,"",""
        Reserve S-1000 
    Endif 
Return
'
'
' Datawüste mit den Oaten für LOCKSLEY und 
' SELECT sowie ein paar Trackdaten
'
Locksley:
Data 60,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
Data 0,B,0,0,0,0,48,E7,FF,FE,42,80,61,0,1,36 
Data 45,FA,FF,EE,24,80,3C,3A,FF,CA,45,FA,FF,E8,34,BC
Data 0,0,45,FA,FF,DA,34,BC,0,0,50,F9,0,0,4,3E 
Data 61,0,1,1E,51,F9,0,0,4,3E,45,FA,FF,C4,20, 12
Data 61,0,1,2,4C,DF,7F,FF,4E,75,32,3C,0,1E,61,A
Data 33,C7,0,FF,86,4,32,3C,0,1E,51,C9,FF,FE,4E,75
Data 2E,30,0,4,0,0,8,39,0,5,0,FF,FA,1,67,60 
Data 53,87,67,40,45,FA,FF,8E,4A,52,67,EA,45,FA,FF,70
Data 15,79,0,FF,86,9,0,1,15,79,0,FF,86,B,0,2 
Data 15,79,0,FF,86,D,0,3,20,3A,FF,54,B0,BA,FF,5C
Data 6D,C4,1E,3C,0,D0,61,0,0,EC,45,FA,FF,58,34,BC
Data 0,0,60,1C,61,1A,1E,3C,0,D0,61,0,0,08,45,FA
Data FF,3E,34,BC,0,1,45,FA,FF,3C,34,BC,0,0,4E,75
Data 30,39,0,FF,86,4,45,FA,FF,1A,34,80,4E,75,30,39
Data 0,FF,86,6,45,FA,FF,E,34,80,42,41,12,39,0,FF
Data 86,9,E1,89,12,39,0,FF,86,B,E1,89,12,39,0,FF
Data 86,D,45,FA,FE,F6,24,81,92,BA,FE,EC,45,FA,FE,DA
Data 34,81,4E,75,45,FA,FE,E0,24,87,13,C7,0,FF,86,D
Data E0,8F,13,C7,0,FF,86,B,E0,8F,13,C7,0,FF,86,9
Data 2E,3A,FE,C4,42,80,30,3A,FE,B0,0E,80,45,FA,FE,BC
Data 24,87,4E,75,2F,0,3F,3C,0,20,4E,41,5C,8F,4E,75
Data 3E,6,3A,6,8,6,0,7,66,10,CC,3C,0,F0,BC,3C 
Data 0,10,67,0,1,64,66,0,1,50,8,6,0,6,66,A 
Data 8,6,0,5,67,2A,66,0,0,F4,CC,3C,0,F0,BC,3C 
Data 0,C0,67,0,1,66,BC,3C,0,E0,67,6A,BC,3C,0,F0
Data 67,0,0,9E,61,0,FE,B4,32,3C,0,FA,60,0,FE,BC
Data 2E,3A,FE,48,61,0,FF,6E,45,FA,FE,5A,34,BC,0,1
Data 33,FC,0,90,0,FF,86,6,33,FC,1,90,0,FF,86,6
Data 33,FC,0,90,0,FF,86,6,3E,3C,8,E,61,8,FE,7C
Data 33,FC,0,84,0,FF,86,6,3E,3A,FE,C,61,0,FE,6C
Data 33,FC,0,80,0,FF,86,6,3E,5,61,0,FE,5E,61,0
Data FE,70,60,0,FE,EA,2E,3A,FD,F2,61,0,FF,18,45,FA
Data FE,4,34,BC,0,1,33,FC,0,90,0,FF,86,6,33,FC
Data 1,90,0,FF,86,6,33,FC,0,90,0,FF,86,6,3E,3C
Data 0,E,61,0,FE,26,33,FC,0,80,0,FF,86,6,60,B8
Data 2E,3A,FD,B8,61,0,FE,0E,45,FA,FD,CA,34,BC,0,1
Data 33,FC,1,90,0,FF,86,6,33,FC,0,90,0,FF,86,6
Data 33,FC,1,90,0,FF,86,6,3E,3C,0,E,61,0,F0,EC
Data 33,FC,1,80,0,FF,86,6,60,0,FF,7E,2E,3A,FD,7C
Data 61,6,FE,A2,45,FA,F0,8E,34,BC,8,1,33,FC,1,90
Data 0,FF,86,6,33,FC,0,90,0,FF,86,6,33,FC,1,90
Data 0,FF,86,6,3E,3C,0,E,61,0,FD,B0,33,FC,1,84
Data 0,FF,86,6,3E,3A,FD,40,61,0,FD,A0,33,FC,1,80
Data 0,FF,86,6,60,0,FF,32,33,FC,8,80,8,FF,86,6
Data 61,0,F0,88,60,0,FD,9A,33,FC,0,86,0,FF,86,6
Data 3E,3A,FD,12,61,0,FD,74,33,FC,0,88,0,FF,86,6
Data 3E,5,61,0,F0,66,60,0,FD,78,2E,3A,FC,FE,26,7A
Data FC,FE,61,0,FE,20,33,FC,0,90,8,FF,86,6,33,FC
Data 1,90,0,FF,86,6,33,FC,0,90,0,FF,86,6,3E,3C
Data 0,1,61,0,FD,36,33,FC,0,80,0,FF,86,6,34,3A
Data FC,C8,3E,5,61,0,FD,24,61,0,FD,36,32,3A,FC,C4
Data 36,C1,51,CA,FF,EE,60,8,FD,A6,0,0
Data ***
'
Select:
Data 60,E,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Data 48,E7,FF,FE,42,80,61,6A,45,FA,FF,F2,24,80,50,F9
Data 0,0,4,3E,3E,3A,FF,0C,66,14,33,FC,0,80,0,FF
Data 86,6,32,39,0,FF,86,4,8,1,0,7,66,F4,C,7
Data 0,8,6C,5C,A,7,0,7,CE,3C,0,7,40,E7,0,7C
Data 7,0,13,FC,0,E,0,FF,88,0,10,39,0,FF,88,0
Data C0,3C,0,F8,8E,0,13,C7,0,FF,88,2,51,F9,0,0
Data 4,3E,46,DF,45,FA,FF,96,20,12,61,6,4C,DF,7F,FF
Data 4E,75,2F,0,3F,3C,0,20,4E,41,5C,8F,4E,75,51,C9
Data FF,FE,4E,75,2F,A,3F,3C,0,9,4E,41,5C,8F,4E,75
Data C,7,0,8,67,14,C,7,0,9,67,20,C,7,0,A
Data 67,52,45,FA,0,68,61,DC,60,BA,33,FA,FF,48,0,FF
Data 86,6,61,1C,45,FA,FF,42,34,80,60,A8,3E,3A FF 3A
Data CE,7C,0,FF,33,FA,FF,2E,0,FF,86,6,61,14,60,94
Data 32,3C,8,1E,61,A8,30,39,0,FF,86,4,32,3C,0,1E
Data 60,9C,32,3C,0,1E,61,96,33,C7,0,FF,86,4,32,3C
Data 0,1E,60,8A,33,FC,8,90,0,FF,86,6,30,39,0,FF
Data 86,6,45,FA,FE,F4,34,80,60,0,FF,5A,52,6F,75,74
Data 69,6E,65,20,6E,6F,63,68,28,6E,69,63,68,74,20,69
Data 6D,70,6C,65,6D,65,6E,74,69,65,72,74,2E,D,A,0
Data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 
Data ***

Trackdaten: 
Data 4E,2 
' Trackvorspann
'
Data 00,2 
' Sektorvorspann 
Data F5,3,FE,1 
' Syncbytes und Adreßmarke 
Data Track,1,Side,1,1,1,3,1,F7,1 
' Sektorvorspann und Checksumme 
Data 4E,14,0,A 
' Lückenbytes 
Data F5,3,FB,1 
' Syncbytes und Datenmarke 
Data CB,400,F7,1 
' Sektordaten und Checksumme 
Data 4E,18 
' Lückenbytes
'
Data 00,2 
' Sektorvorspann 
Data F5,3,FE,1 
' Syncbytes und Adreßmarke 
Data Track,1,Side,1,2,1,0,1,F7,1 
' Sektorheader (Sektor mit 128 Bytes) und Checksumme 
Data 4E,14,0,A 
' Lückenbytes 
Data F5,3,FB,1 
' Syncs und Datenmarke 
Data CB,40,F7,1 
' Sektordaten (unvollständig) und Checksumme 
Data 4E,10 
' Lückenbytes
'
Data 00,2 
' Sektorvorspann 
Data F5,3,FE,1
Data Track,1,Side,1,3,1,2,1,F7,1 
' normaler 512-Byte-Sektor 
Data 4E,14,0,A 
Data F5,3,FB,1 
Data CB,200 
' Sektordaten 
Data F7,1,4E,10
'
Data 00,2 
' Sektorvorspann 
Data FS,3,FE,1
Data Track,1,Side,1,4,1,4,1,F7,1 
' Sektor mit der Größenangabe '4'
Data 4E,14,0,A 
Data F5,3,FB,1 
Data 02,200 
' Sektordaten des zweiten Sektors Nr. 3 
Data F7,1,4E,10
'
Data 4E,200 
' Tracknachspann 
Data ***,***

Auf Touren gebracht - Noch eine Erweiterung zum Minimon

In den letzten beiden Folgen haben Sie ja schon miterlebt, daß der MINIMON sich ganz gut dazu eignet, selbstgebastelte Erweiterungen anzulügen. Um die Routine in Listing 1 einzubinden, müssen Sie nur das Menü des Trackmon-Teils etwas erweitern (einen Vorschlag dazu finden Sie ebenfalls im Listing). Die Routine mißt die Drehzahl des selektierten Laufwerks und gibt sie auf dem Schirm aus. Ein Tastendruck bricht die Messung ab.

Wie funktioniert die Routine? Das Programm schickt jeweils FORCE-IRQ-Befehle (siehe Floppykurs, Teil 5) an den Controller, deren Bit 2 gesetzt ist. Dadurch wird bei jedem Indeximpuls ein Interrupt ausgelöst. Dieser Interrupt wird dem MFP68901 im ST durchgemeldet. Der legt daraufhin Bit 5 seines GPIP-Registers (SFFFAOl) auf Low-Pegel (löscht es also). Auf solche Low-Pegel wartet das Programm; nach 10 Indeximpulsen wird die Zeit gemessen. die das Laufwerk dafür gebraucht hat. Aus dieser Zeit kann man durch eine einfache Formel errechnen, wieviele Umdrehungen das Laufwerk hat.

Die Formel sollte ich vielleicht erklären. Sie lautet:

(1) Drehzahl = 12000 * Genau% / (Zeit für Genau% Umdrehungen in 200stel Sekunden)

Versuchen wir uns dieser Formel schrittweise zu nähern. Bei Solldrehzahl - 300 Umdrehungen pro Minute - braucht das Laufwerk 0.2 s für eine Umdrehung. Das entspricht 40/200 Sekunden (diese Umrechnung brauchen wir gleich noch). Die tatsächliche Drehzahl ergibt sich nun aus dem Quotienten aus dieser Solldrehzeit und der wirklich gemessenen Zeit, multipliziert mit 300:

(2) Drehzahl = 300*Solldrehzeit/(gemessene Zeit)

Die Solldrehzeit ist (0.2 Sekunden * Genau%) = (40/200 Sekunden * Genau%). Setzt man das ein, ergibt sich:

(3) Drehzahl = 300* (40/ 200)Genau%/(gemessene Zeit) = 12000Genau% / ((gemessene Zeit)*200)

Damit sind wir schon ziemlich genau bei der ersten Formel angekommen. Den Faktor 200 im Nenner können wir uns schenken, weil im GFABASIC-Programm die Zeit eh schon in 200stel Sekunden (über die TIMER Variable) gemessen wird. Damit steht genau die Formel (1) vor uns.

Die Messung ist hinreichend genau, in der abgedruckten Version liegt der Meßfehler bei maximal +/-0.7 Umdrehungen. Mit dem Parameter Genauso können Sie - falls Sie so pingelig sind - die Exaktheit verbessern. Für HYPERFORMAT-Disketten sind Umdrehungsgeschwindigkeiten von 300 bis 302 Upm optimal.

Nach dem Anlaufen der Routine sollten Sie eine Weile warten, bis sich die Drehzahl stabilisiert hat. Probieren Sie doch mal, was passiert, wenn Sie Ihr Laufwerk während des Drehzahltests drehen und schütteln (aber nicht übertreiben).

Trackmon mit eingebauter Speed-Routine

Listing

' Diese Anpassung der Routine Trackmon soll Ihnen ver-
' deutlichen, wie man die SPEED-Routine in den EX-
' TENDED MINIMON einbauen könnte.

Procedure Trackmon 
    @Init_trackmon
    Cls
    Prn%=0
    Richtung%=0
    Seite%=0
    Drve%=0
    Steprate%=1
    R$=Chr$(27)+"p"
    O$=Chr$(27)+"q"
    @Rst    ! auf Track 0 zurückfahren
    Do
        Print
        Print "*************** TRACKMON (C) 1987 Claus Brod ****************"
        @Prntable
        Print R$;"0";O$;" Track 0, ";R$;"1";O$;" Step, ";R$;"2";O$;" Step-In, ";
        Print R$;"3";O$;" Step-Out, ";R$;"4";O$;" Seek, ";RS; "5'* jOS;" RdSec,
        Print RS;"6";OS;" Wr Sec"
        Print R$;"7";OS;" Rd Adr, RS;"8";O$;" Rd Trk, **;R$;"9" ;O$f WrTrk, “j 
        Print R$;"A";O$;" IRQ, ";R$;"0";O$;"ump Buf, ;RS;"S";O$;"eite (";Seite%;
        Print "), ";R$;"P";O$;"rn (o";
        If Prn%=1 
            Print "n)"
        Else
            If Prn%=0 
                Print 
            Else 
                Print "n file)"
            Endif
        Endif
        '
        '
        ' ............. Die folgende Zeile ist neu!!!
        Print R$;"R";O$;"egister, ";R$;"G";O$;‘eschwindigkeit,";R$;
        Print "Q";O$;"uit"
        ' ...............weiter wie gewohnt
        '
        M$=Upper$(Input$(1))
        Exit If M$="Q“
        '
        ' Jetzt wieder etwas Neues!!! 
        If M$="G"
            @Speed
        Endif
        ' ab jetzt wieder kalter Kaffee
        '
        If M$="S"
            Seite%=1-Seite%
        Endif 
        If M$="P"
            Inc Prn% 
            If Prn%>2 
                Prn%=0 
            Endif 
            If Prn%=2 
                Input "Filename";Fi$
            Endif
        Endif 
        If M$="D"
            @Dump_buf 
        Endif 
        If M$="A"
            @Irq ! FDC unterbrechen
        Endif 
        If M$="R"
            @Register
        Endif
        If M$<="9" And M$>="8"
            On Val(M$)+1 Gosub Rst,Step,Step_in,Step_out,Seek,Rdsec,Wrsec,Rdadr 
            On Val(M$)-7 Gosub Rdtrk,Wrtrk 
        Endif 
    Loop 
Return
'
Hier folgt jetzt die eigentliche Meßroutine SPEED.
'
' Speed-Routine; mißt die Drehzahl eines Laufwerks 
Procedure Speed 
    Local Dr,Lp%,Avr 
    @Irq
    ' FDC in definierten Zustand 
    '
    Cls
    Print At(5,2);"Drehzahlmessung“
    Print At(5.9);"   Drehzahl : "
    Print At(5,11);"Durchschnitt : "
    Mfp%=&HFFFA01
    ' Hier meldet der MFP den FDC-Interrupt beim Indeximpuls
    '
    Genau%=10
    ' Genauigkeitsfaktor, je höher, desto länger wird gemessen
    '
    @Select
    ' Laufwerk selektieren 
    Dpoke Sel+2,9 
    Dpoke Sel+4,&H88 
    Dpoke Sel+8,&HD4 
    Call Sel
    ' INDEX-IRQ ($04) an den FDC schicken 
    ' (erweiterte LOCKSLEY-Routine wird benötigt, siehe ST 11/87)
    '
    Repeat                      ! Warte auf Index
    Until (Peek(Mfp%) And 32)=0 ! Dann Start !!
    Repeat 
        Dpoke Sel+2,9 
        Dpoke Sei+4.&H80 
        Dpoke Sel+8,&HD4
        ' Parameterfeld der Select-Routine vorbereiten
        '
        T2=Timer
        For T%=1 To Genau% 
            Call Sel 
            Repeat
            Until (Peek(Mfp%) And 32)=0 
            If Inkey$<>"" Or Mousek 
                T%=99 
            Endif 
        Next T%
        ' Zeit für Genau% Umdrehungen messen 
        ' Abbruch durch Taste oder Mausklick 
        Exit If T%=100 
        Dr=12080*Genau%/(Timer-T2)
        ' Formel für Drehzahl, siehe Artikel)
        Print At(22,9);Using "###.###",Dr
        Add Avr,Dr
        Print At(22,11);Using "###.###",Avr/Lp%
    Until Inkey$<>"" Or Mousek 
    @Irq
    @Deselect
Return

Claus Brod
Aus: ST-Computer 01 / 1988, Seite 72

Links

Copyright-Bestimmungen: siehe Über diese Seite