So sieht der Versuchsaufbau mit dem Teensy aus, ich konnte die Floppy direkt mit einem Steckbrett und ein paar Dingsdakabeln verdrahten, keine lästigen Spannungsteiler oder Levelshifter da der Teensy 3.2 direkt TTL Pegel auf den Eingängen frisst.
#define _redwc 2 //2 density select IN #define _index 3 //8 index OUT #define _drivesel 4 //12 drive select 1 IN #define _motor 5 //16 motor1 on IN #define _dir 6 //18 direction IN #define _step 7 //20 step IN #define _writedata 8 //22 write data IN #define _writeen 9 //24 write enable IN #define _track0 10 //26 track 0 OUT #define _wprot 11 //28 write protect OUT #define _readdata 22 //30 read data OUT (FTM0) #define _side 14 //32 head select IN #define _ready 15 //34 ready / disk change OUT
Die ganzen Floppy Pins gehen von oben nach unten an die Pins vom Teensy, bis auf die Read Data Leitung, die habe ich nach Studium des Datenblatt an GPIO 22 gelegt, dieser GPIO lässt sich nämlich als Input Capture Trigger für das FlexTimer Module 0 benutzen.
Der FTM0 ist ein 16 Bit Timer der mit maximal Bus Clock läuft, Bus Clock ist beim Teensy der halbe Coreclock, da ich auf 96 MHz takte sind das 48 MHz. Über den Prescaler halbiere ich den Takt nochmal auf 24 MHz, d.h. alle 41,6 Nanosekunden zählt der Timer einen Schritt hoch. Für den Eingang habe ich noch einen Filter im Timer eingestellt sodaß das Signal am Input Trigger für mindestens 12 Taktzyklen Busclock (250ns) stabil sein muss damit es erkannt wird. Wird nun über den GPIO 22, welches der Input Capture Trigger für FlexTimer Modul 0 ist, ein Flankenwechsel (in meinem Falle Falling Edge) detektiert findet folgendes statt:
- der Inhalt des Counters (FTM0_CNT) wird in ein extra Register (FTM0_C0V) kopiert
- der Interrupt Vector (ftm0_isr) des FTM0 wird angesprungen
- die von mir geschriebene Interruptroutine setzt den Counter auf Null
- der Inhalt des Registers FTM0_C0V wird ausgewertet wie lang die Transition dauerte, 4,6 oder 8 µs
- entsprechende schreibe ich in eine Puffervariable eine ’10‘, ‚100‘ oder ‚1000‘, ich benutze dafür ein Longword (32bit) in dem ich die Bits sammel und wenn ich 8 Bit oder mehr komplett habe schreibe ich sie in den Steambuffer.
- On the Fly prüfe ich ob das Longword den Inhalt 0xA4489448 enthält, das ist nämlich der Anfang des Syncwords eine Amiga Sektors und kann ensprechend dem Stream entsprechend ausrichten das genau ein Byte anfängt. Ebenso vermerke ich in einer Tabelle einen Pointer auf den Sektoranfang im Speicher, das macht das decodieren später einfacher.
- wenn der Streambuffer voll ist oder ich 11 Sektoren gefunden habe schalte ich die Interrupt Generierung aus.
- der Interrupt benötigt etwa 0,9 µs pro Transition, d.h. sie ist lange fertig bevor die nächste Transition kommt (4µs oder länger)
Währenddessen wartet meine Hauptroutine nur darauf das der Lesevorgang beendet ist und startet danach die decodierung des Tracks.
Der ganze Spass läuft mittlerweile recht zuverlässig, hat zwar bisher kaum Fehlerüberprüfungen aber spuckt erste brauchbare Ergebnisse aus:
Reading Track 0 Sectors start at: 172, 2067, 3155, 4243, 5331, 6419, 7507, 8595, 9683, 10771, 11859 Decode took 1631 Sectors found: 11 Errors found: 0 OK Format Type: 255 Track: 0 Sector: 0 NumSec2Gap: 3 Data Chk: 4410155 Header Chk: 0 44 4F 53 00 C0 20 0F 19 00 00 03 70 43 FA 00 18 4E AE FF A0 4A 80 67 0A 20 40 20 68 00 16 70 00 DOS.. .....pC...N...J.g. @ h..p. 4E 75 70 FF 60 FA 64 6F 73 2E 6C 69 62 72 61 72 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Nup.`.dos.library............... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
Oben sieht man den Bootsektor einer Amiga Diskette, in den ersten vier Bytes steht „DOS“,0 für eine normale Diskette, dann folgt eine kurze Assemblerroutine die über die dos.library den Boot der Disk startet.