þþ + EI =x =Pd!AšATARI 1050 DISK DRIVE O.S.An,X* ATARI 1050 DISK DRIVE OPERATING SYSTEMxX*‚7X* based on listings of Michael Pascher (Abbuc-Buch)ŒX* and W. Derks–X* X* RAM $0000 - $00FFª#X* TIMER,IO $0280 - $029F (6532)´X* memory used by ports:¾X* PORT A ($0280)È)X* bit 0 drive number readÒ)X* 1 " readÜ*X* 2 writeæ*X* 3 motor off writeð*X* 4 > track 20 writeú*X* 5 single density write)X* 6 IRQ floppy ? read)X* 7 data request floppy NAK readX*"X* PORT B ($0282),%X* bit 0 data out (to CPU) write6$X* 1 read@%X* 2 step motor phase 1 writeJ%X* 3 step motor phase 2 writeT%X* 4 step motor phase 3 write^%X* 5 step motor phase 4 writeh$X* 6 data in (from CPU) readr$X* 7 command (from CPU) read|X*†X* memory usageX*š'X* sector buffer from $0000 to $007F¤X*® †SEKBUF¸X*Â/X* buffer for address info after READ ADRESSÌ-X* TRACK, SIDE, SEKTOR, LENGTH, CRC1, CRC2ÖX*à †ATRACKzê „ASEK|ô „ALEN}þ …ACRC1~ …ACRC2X**X* buffer for command and sector number&X*0 †RDRIVE€: †RKOMNDD …RSEKL‚N …RSEKHƒXX*b …FDATA…l „FSNR‡v „FTNR‰€X*Š †MOTIML‹;timer for MOTOR ON” †MOTIMHŒž…TRACK;track #¨†SEKTORŽ;sector #²%…CSTAT;controller status shadow¼!†STATUS;floppy drive statusÆ…ERROR‘;error byteÐ…COUNT’;counterÚ ƒDIR“;step direction floppyä „FLAG”î1„HZ95•;aux byte for track/sector calculationø‡SEEKERR– †TRKERR— …KOMND˜;command 0 - 7…JUMPL™;jump vector  …JUMPHš*7…DSTAT›;drive status, to detect change of diskette4ˆMUSTERNRœ> „HZ9DH „HZ9EžR'…PHASEŸ;actual phase of step motor\ …FMERK f(†ERRADR£;error addr for floppy testp „HZA4¤z"†BUFFER¥;temp for floppy test„‡STEPCNT¯;step countŽ…STEPS°;steps to do˜8„SBUF±;write buffer and track count for floppy test¢ ƒDRA€;data register PORT A¬+„DDRA;data direction register PORT A¶ ƒDRB‚;data register PORT BÀ+„DDRBƒ;data direction register PORT BÊ…TIM64–;timer : 64Ô‡TIM1024—;timer : 1024Þ,†T1024IŸ;timer : 1024 INTERRUPT ENABLEè1†FCNTRL;control register floppy controllerò†TRKREG;track registerü†SEKREG;sector register†DATREG;data registerX*ð$X*.$X* masks for phases of step motor8X*B$†PHASE1 û;each time 1 phase on 0L ÷V ï` †PHASE4 ßjX*t W~X*ˆX* command table’X*œ‡READSEK R;read sector¦*‡WRITSEK P;write sector without verify°'‡WRVESEK W;write sector with verifyº S;status requestÄ !;format single densityÎ ";format enhanced density؇SPEZIAL #;specialâ(X* first byte in following data blockì4X* 0 or 1 second byte to FLAG for command $24ö3X* 2 second byte contains sector number>X* it will be tested if sector after sector 1 on =X* each track is less or equal to this sector #?X* 3 do 1 step, direction in second byte ($FF or 1)X* 4 floppy test(9X* the diskette is enhanced formatted, then29X* several tests are done. The test returns<%X* a 'C' or 'E' (error)F-X* 5 SEEK on track in second byteP$ $;send time for one rotation inZcX* first two bytes of block (if command $23 00 00) or send motor rpms (if command $23 00 01)d;X* The time is stored in first 2 bytes of the sectornX* send after the testxX*‚…DRVNR 3;drive numberŒ 2=4=1– ÿ;end of table  ªX*´"X* start of program after RESET¾X*ÈX* port init & hardware testÒ …START-Ü$>ÿ;reset stackæBðQ><;PORT A bit 2 - 5 outputú P„DDRAQ>8;set bits 3-5PƒDRAQƒDRA;read register"M><,R>8;check for written value6H„FAIL;no, FATAL ERROR@ Q>=;PORT B bit 0, 2-5 outputJ P„DDRBTQ>=;set all bits^PƒDRBhQƒDRB;read registerrM>=|R>=;check for written value†H„FAIL;no, FATAL ERRORQ>К-P†FCNTRL;force interrupt floppy controller¤$>®„DEL10;wait a little while¸ H„DEL1ÂQ†FCNTRL;controller ready?ÌM>ÖH„FAIL;no, FATAL ERRORà$Q>U;test sector & track registerê P†TRKREGô P†SEKREGþ$>„DEL20;some respite H„DEL2N†TRKREG;ok?&H„FAIL;no, FATAL ERROR0Q>U: N†SEKREGD!H„FAIL;also for track registerNQ>HXP†FCNTRL;HEAD LOAD & STEP INb $>(;delayl" †DELAY1;wait X * 71 cycles (?)vQ†FCNTRL;busy?€M>Š!F„FAIL;no, something is rotten”$>(ž †DELAY1;wait another time¨ Q†FCNTRL²M>;now it must by ok¼H„FAIL;otherwise it't wrongÆQ>ð;get checksum of PROMÐP†SEKBUF;start addressÚQ>ä P†SEKBUFî,ø?#†PCHECKO@†SEKBUF7;add PROM bytes 3 H†PCHECK #†SEKBUF;next page* H†PCHECK4L>;result must be zero> P†SEKBUFH$F…TSTOK;if so, everything is fineRX*\X* fatal error, breakfX*p„FAIL+;hardware defectzX*„#X* hardware test ok, do RAM testŽX*˜…TSTOK$>;write to RAM¢ †RAMTSTA¬ P†SEKBUF9¶2À H†RAMTSTʇRAMTST1A;read itÔR†SEKBUF9;and compareÞ H„FAILè0ò H‡RAMTST1üA &†RAMCLRP†SEKBUF9;write another time 2;to zero out H†RAMCLR$ X*. X* for now, init motor8 X*B $>;step motor phase 3L &…PHASEV Q†PHASE4;bitpattern of phase` MƒDRB;to PORT Bj PƒDRBt , †TMOTON;motor on?, otherwise start motor~ Q>;track 0ˆ P…TRACK’ % †SIREST;10 steps in, then restoreœ Q†FCNTRL;controller status¦ P…CSTAT;to RAM° M>€;drive ready?º H„DRDY;yesÄ - …IDENT;otherwise, init drive, density etcÎ X*Ø 2X* here loops the program if nothing else to doâ &X* wait for command or new disketteì X*ö „DRDY †DSKCHG;change of disk? , †TKOMND;command from CPU, if so -- do it QƒDRA;motor on? M> H„DRDY;no( $>;yes, delay2 „DEL30< H„DEL3F #†MOTIML;incr MOTOR ON timerP H„DRDYZ #†MOTIMH;also msbd H„DRDYn ( †MOTOFF;if timer expires, stop motorx !„DRDY;end of main loop‚ X*Œ !X* look for change of diskette– X*  †DSKCHGQ>€ª M†FCNTRL;controller bit ready´ >;still the same?¾ N…DSTAT;if notÈ H†NEWDSK;it's a changeÒ ':;for motor is turned on each changeÜ "†NEWDSK&…DSTAT;store new statusæ Að I†DIDENT;motor off?ú  †MOTOFF;no, turn it off !†UPDATE;update status X* (†DIDENT †TMOTON;identify new diskette" …IDENT, †UPDATEQ†FCNTRL;update status6 P…CSTAT@ :J X*T X* turn motor off^ X*h †MOTOFFQƒDRA;turn motor offr L>;via bit 3 of PORT A| PƒDRA† Q>< LƒDRBš "PƒDRB;all step motor phases off¤ Q†STATUS® $M>ï;indicate MOTOR OFF to STATUS¸ P†STATUS :Ì X*Ö X* turn motor onà X*ê …MOTONQƒDRA;turn motor onô M>÷þ PƒDRA $…PHASE;step motor in QƒDRB;right phase M†PHASE19& PƒDRB0 Q>;reset MOTOR ON timer: P†MOTIMHD P†MOTIMLN 'Q†STATUS;indicate MOTOR ON to STATUSX L>b P†STATUSl $>v , †DELAY2;give motor some time to speed up€ :Š X*” X* identify inserted diskettež X* single or enhanced density¨ X*² …IDENT ‡RESTORE¼ QƒDRAÆ M>ß;try enhancedÐ PƒDRAÚ  …RDADR;READ ADRESS commandä F†IDENT1;succesfull read?î  …RDADR;no, try againø F†IDENT1;ok QƒDRA;otherwise, try single N>  PƒDRA Q†STATUS;indicate single* M>4 P†STATUS> :H †IDENT1Q†STATUSR L>€;indicate enhanced\ P†STATUSf :p X*z X* turn motor on if not on„ X* & reset MOTOR ON timerŽ X*˜ †TMOTONQƒDRA¢ M>;already on?¬ F…ZF18A¶  …MOTON;no, turn it onÀ …ZF18AQ>Ê P†MOTIMLÔ P†MOTIMH;reset timerÞ :è X*ò $X* delay, (X) * 100 micro secondsü X*†DELAY1%>ƒD111HƒD11$0.484B H†DELAY1L:VX*`"X* delay, (X) * 10 millisecondsjX*t%†DELAY2&„SBUF;SBUF used as counter~ ƒD21%>ˆ '„SBUF’ ƒD22$>úœ †DELAY1¦ "„SBUF°HƒD22º "„SBUFÄHƒD21Î:ØX*â'X* delay, (X) * 5 + 12 micro secondsìX*ö †DELAY31 H†DELAY3 :X*)X* 10 steps to the middle, and restore(X*2†SIRESTQ> < ‡DOSTEPS;make the stepsFX*PX* restore on track 0ZX*d‡RESTORE …FORCE;force IRQn# …FORCE;interrupt floppy commandx"Q>ÿ;direction: from the middle‚PƒDIRŒQ>–P‡STEPCNT;no steps  P…STEPSª‡RESTOR1Q†FCNTRL;on track 0?´M>¾F‡RESTOR2;br if soÈ …HSTEP;make half a stepÒ!‡RESTOR1;until on track 0܇RESTOR2Q…PHASE;in phase 4?æR>ðF‡RESTOR3;br if soú …HSTEP;otherwise, go on&!‡RESTOR2;until on track 0, phase 4‡RESTOR3Q> P†TRKREG;reset track register"P‡STEPCNT;and step counter,$>È;20 milli seconds delay6 †DELAY1@:JX*TX* make half a step^AX* the step motor runs a cyclus of 4 phases, equal to 2 trackshX*r#…HSTEP ‡DOHSTEP;make half a step|# …FORCE;interrupt floppy command†$>d;10 ms delay !†DELAY1šX*¤X* do half a step®X*¸!‡DOHSTEP#‡STEPCNT;incr counter Q‡STEPCNTÌR>x;already 120 steps?Ö#E‡STEPERR;if so, something wrongàQƒDRA;motor on?êM>ôF„STEP;is so, alrightþ4‡STEPERR+;step error: motor off or too many steps„STEP$…PHASEQ†PHASE19;get mask for phaseN>ÿ;invert&?0*ƒDIR;get step direction:I…STEPM;for following phaseD2;step forwardN(>;cyclus done?X H…STEP1b$>;if so, do it againl F…STEP1v…STEPM0;step backward€I…STEP1;cyclus done?Š#$>;if so, do it again backward”…STEP1&…PHASE;save new phasežC;reset old phase¨LƒDRB²M†PHASE19;set new phase¼PƒDRBÆ:ÐX*ÚX* seek track number in 008DäX*î(„SEEK …FORCE;interrupt actual commandø Q…TRACK;get destination track; !S†TRKREG;subtract actual trackH‡DOSTEPS;already there? :;yes, done*X*4)X* make as many steps as value in accu>X*H!‡DOSTEPSG…DOST1;step backward?R$>;no, forward\ I‡DOSTEP1f…DOST1$>ÿ;backwardpN>ÿ;get two's complementz,„O>Ž'‡DOSTEP1T?;two times (2 phases/step)˜I‡DOSTEP2;br if ok¢. ‡RESTORE;otherwise too many steps: restore¬Q>€;indicate error¶ P†STATUSÀ:Ê"‡DOSTEP2P…STEPS;number of stepsÔ&ƒDIR;directionÞQ>è'P‡STEPCNT;reset count of error stepsò#‡DOSTEP3 …HSTEP;make half a stepü"…STEPS;all done?H‡DOSTEP3;no, continue*ƒDIR;backward step?G†CHKTRK;br if so$Q>ÿ;otherwise step backward.&P…STEPS;but first one step too much8%Q>;forward, so track will alwaysB$P‡STEPCNT;be encountered from theL …HSTEP;same directionVQ>ÿ`PƒDIRj …HSTEP;step backwardtQ>;reset error count~ P…STEPSˆ P‡STEPCNT’X*œ/X* set bit 4 of PORT A for tracks > track 20¦X*°†CHKTRKQ…TRACKº*P†TRKREG;actual track in track registerÄR>;greater then 20?Î D…KTR20;noØ&Q>;otherwise, set bit 4 of PORT AâLƒDRAìH…GTR20;br alwaysö#…KTR20Q>ï;reset bit 4 of PORT AMƒDRA;for track less then 20 …GTR20PƒDRA$>È" †DELAY1;20 ms delay after SEEK(X*2)X* force IRQ, interrupt floppy command<X*F%†DFORCE …FORCE;two times force IRQP …FORCEQ>ÐZP†FCNTRL;command force IRQd$>;short delayn …FORC10x H…FORC1‚Q>Œ…FORC2*†FCNTRL;wait until–H…FORC2;controller ready :ªX*´X* command from CPU?¾X*ȆTKOMNDQ>Ò!*ƒDRB;test bit 1 of PORT B ???Ü H…NOKOMæG…TKOM1;bit 7 of PORT B = 1?ð…NOKOM:;no command from CPUúX*X* link other partsX*>ŽD7:FLOPOS2.M65"I,>ŽD7:FLOPOS3.M656>ŽD7:FLOPOS4.M65@>ŽD7:FLOPOS5.M65JEI