10 .OPT NO LIST›20 .SET 2,120›30 .SET 4,80›0100 .TITLE "ATARI 1050 DISK DRIVE O.S."›0110 * ATARI 1050 DISK DRIVE OPERATING SYSTEM›0120 *›0130 * based on listings of Michael Pascher (Abbuc-Buch)›0140 * and W. Derks›0150 *›0160 * RAM $0000 - $00FF›0170 * TIMER,IO $0280 - $029F (6532)›0180 * memory used by ports:›0190 * PORT A ($0280)›0200 * bit 0 drive number read›0210 * 1 " read›0220 * 2 write›0230 * 3 motor off write›0240 * 4 > track 20 write›0250 * 5 single density write›0260 * 6 IRQ floppy ? read›0270 * 7 data request floppy NAK read›0280 *›0290 * PORT B ($0282)›0300 * bit 0 data out (to CPU) write›0310 * 1 read›0320 * 2 step motor phase 1 write›0330 * 3 step motor phase 2 write›0340 * 4 step motor phase 3 write›0350 * 5 step motor phase 4 write›0360 * 6 data in (from CPU) read›0370 * 7 command (from CPU) read›0380 *›0390 * memory usage›0400 *›0410 * sector buffer from $0000 to $007F›0420 *›0430 SEKBUF = $00›0440 *›0450 * buffer for address info after READ ADRESS›0460 * TRACK, SIDE, SEKTOR, LENGTH, CRC1, CRC2›0470 *›0480 ATRACK = $7A›0490 ASEK = $7C›0500 ALEN = $7D›0510 ACRC1 = $7E›0520 ACRC2 = $7F›0530 *›0540 * buffer for command and sector number›0550 *›0560 RDRIVE = $80›0570 RKOMND = $81›0580 RSEKL = $82›0590 RSEKH = $83›0600 *›0610 FDATA = $85›0620 FSNR = $87›0630 FTNR = $89›0640 *›0650 MOTIML = $8B timer for MOTOR ON›0660 MOTIMH = $8C›0670 TRACK = $8D track #›0680 SEKTOR = $8E sector #›0690 CSTAT = $8F controller status shadow›0700 STATUS = $90 floppy drive status›0710 ERROR = $91 error byte›0720 COUNT = $92 counter›0730 DIR = $93 step direction floppy›0740 FLAG = $94›0750 HZ95 = $95 aux byte for track/sector calculation›0760 SEEKERR = $96›0770 TRKERR = $97›0780 KOMND = $98 command 0 - 7›0790 JUMPL = $99 jump vector›0800 JUMPH = $9A›0810 DSTAT = $9B drive status, to detect change of diskette›0820 MUSTERNR = $9C›0830 HZ9D = $9D›0840 HZ9E = $9E›0850 PHASE = $9F actual phase of step motor›0860 FMERK = $A0›0870 ERRADR = $A3 error addr for floppy test›0880 HZA4 = $A4›0890 BUFFER = $A5 temp for floppy test›0900 STEPCNT = $AF step count›0910 STEPS = $B0 steps to do›0920 SBUF = $B1 write buffer and track count for floppy test›0930 DRA = $0280 data register PORT A›0940 DDRA = $0281 data direction register PORT A›0950 DRB = $0282 data register PORT B›0960 DDRB = $0283 data direction register PORT B›0970 TIM64 = $0296 timer : 64›0980 TIM1024 = $0297 timer : 1024›0990 T1024I = $029F timer : 1024 INTERRUPT ENABLE›1000 FCNTRL = $0400 control register floppy controller›1010 TRKREG = $0401 track register›1020 SEKREG = $0402 sector register›1030 DATREG = $0403 data register›1040 *›1050 *= $F000›1060 *›1070 * masks for phases of step motor›1080 *›1090 PHASE1 .BYTE $FB each time 1 phase on 0›1100 .BYTE $F7›1110 .BYTE $EF›1120 PHASE4 .BYTE $DF›1130 *›1140 .BYTE $57›1150 *›1160 * command table›1170 *›1180 READSEK .BYTE $52 read sector›1190 WRITSEK .BYTE $50 write sector without verify›1200 WRVESEK .BYTE $57 write sector with verify›1210 .BYTE $53 status request›1220 .BYTE $21 format single density›1230 .BYTE $22 format enhanced density›1240 SPEZIAL .BYTE $23 special›1250 * first byte in following data block›1260 * 0 or 1 second byte to FLAG for command $24›1270 * 2 second byte contains sector number›1280 * it will be tested if sector after sector 1 on›1290 * each track is less or equal to this sector #›1300 * 3 do 1 step, direction in second byte ($FF or 1)›1310 * 4 floppy test›1320 * the diskette is enhanced formatted, then›1330 * several tests are done. The test returns›1340 * a 'C' or 'E' (error)›1350 * 5 SEEK on track in second byte›1360 .BYTE $24 send time for one rotation in›1370 * first two bytes of block (if command $23 00 00) or send motor rpms (if command $23 00 01)›1380 * The time is stored in first 2 bytes of the sector›1390 * send after the test›1400 *›1410 DRVNR .BYTE $33 drive number›1420 .BYTE $32,$34,$31›1430 .BYTE $FF end of table›1440 .BYTE 0›1450 *›1460 * start of program after RESET›1470 *›1480 * port init & hardware test›1490 START CLD ›1500 LDX #$FF reset stack›1510 TXS ›1520 LDA #$3C PORT A bit 2 - 5 output›1530 STA DDRA›1540 LDA #$38 set bits 3-5›1550 STA DRA›1560 LDA DRA read register›1570 AND #$3C›1580 CMP #$38 check for written value›1590 BNE FAIL no, FATAL ERROR›1600 LDA #$3D PORT B bit 0, 2-5 output›1610 STA DDRB›1620 LDA #$3D set all bits›1630 STA DRB›1640 LDA DRB read register›1650 AND #$3D›1660 CMP #$3D check for written value›1670 BNE FAIL no, FATAL ERROR›1680 LDA #$D0›1690 STA FCNTRL force interrupt floppy controller›1700 LDX #$15›1710 DEL1 DEX wait a little while›1720 BNE DEL1›1730 LDA FCNTRL controller ready?›1740 AND #1›1750 BNE FAIL no, FATAL ERROR›1760 LDA #$55 test sector & track register›1770 STA TRKREG›1780 STA SEKREG›1790 LDX #$1E›1800 DEL2 DEX some respite›1810 BNE DEL2›1820 EOR TRKREG ok?›1830 BNE FAIL no, FATAL ERROR›1840 LDA #$55›1850 EOR SEKREG›1860 BNE FAIL also for track register›1870 LDA #$48›1880 STA FCNTRL HEAD LOAD & STEP IN›1890 LDX #$28 delay›1900 JSR DELAY1 wait X * 71 cycles (?)›1910 LDA FCNTRL busy?›1920 AND #1›1930 BEQ FAIL no, something is rotten›1940 LDX #$28›1950 JSR DELAY1 wait another time›1960 LDA FCNTRL›1970 AND #1 now it must by ok›1980 BNE FAIL otherwise it't wrong›1990 LDA #$F0 get checksum of PROM›2000 STA SEKBUF+1 start address›2010 LDA #0›2020 STA SEKBUF›2030 CLC ›2040 TAY ›2050 PCHECK ADC (SEKBUF),Y add PROM bytes›2060 INY ›2070 BNE PCHECK›2080 INC SEKBUF+1 next page›2090 BNE PCHECK›2100 ORA #0 result must be zero›2110 STA SEKBUF›2120 BEQ TSTOK if so, everything is fine›2130 *›2140 * fatal error, break›2150 *›2160 FAIL BRK hardware defect›2170 *›2180 * hardware test ok, do RAM test›2190 *›2200 TSTOK LDX #0 write to RAM›2210 RAMTST TXA ›2220 STA SEKBUF,X›2230 INX ›2240 BNE RAMTST›2250 RAMTST1 TXA read it›2260 CMP SEKBUF,X and compare›2270 BNE FAIL›2280 DEX ›2290 BNE RAMTST1›2300 TXA ›2310 RAMCLR STA SEKBUF,X write another time›2320 INX to zero out›2330 BNE RAMCLR›2340 *›2350 * for now, init motor›2360 *›2370 LDX #3 step motor phase 3›2380 STX PHASE›2390 LDA PHASE4 bitpattern of phase›2400 AND DRB to PORT B›2410 STA DRB›2420 JSR TMOTON motor on?, otherwise start motor›2430 LDA #0 track 0›2440 STA TRACK›2450 JSR SIREST 10 steps in, then restore›2460 LDA FCNTRL controller status›2470 STA CSTAT to RAM›2480 AND #$80 drive ready?›2490 BNE DRDY yes›2500 JSR IDENT otherwise, init drive, density etc›2510 *›2520 * here loops the program if nothing else to do›2530 * wait for command or new diskette›2540 *›2550 DRDY JSR DSKCHG change of disk?›2560 JSR TKOMND command from CPU, if so -- do it›2570 LDA DRA motor on?›2580 AND #8›2590 BNE DRDY no›2600 LDX #8 yes, delay›2610 DEL3 DEX ›2620 BNE DEL3›2630 INC MOTIML incr MOTOR ON timer›2640 BNE DRDY›2650 INC MOTIMH also msb›2660 BNE DRDY›2670 JSR MOTOFF if timer expires, stop motor›2680 JMP DRDY end of main loop›2690 *›2700 * look for change of diskette›2710 *›2720 DSKCHG LDA #$80›2730 AND FCNTRL controller bit ready›2740 TAX still the same?›2750 EOR DSTAT if not›2760 BNE NEWDSK it's a change›2770 RTS for motor is turned on each change›2780 NEWDSK STX DSTAT store new status›2790 TXA ›2800 BPL DIDENT motor off?›2810 JSR MOTOFF no, turn it off›2820 JMP UPDATE update status›2830 *›2840 DIDENT JSR TMOTON identify new diskette›2850 JSR IDENT›2860 UPDATE LDA FCNTRL update status›2870 STA CSTAT›2880 RTS ›2890 *›2900 * turn motor off›2910 *›2920 MOTOFF LDA DRA turn motor off›2930 ORA #8 via bit 3 of PORT A›2940 STA DRA›2950 LDA #$3C›2960 ORA DRB›2970 STA DRB all step motor phases off›2980 LDA STATUS›2990 AND #$EF indicate MOTOR OFF to STATUS›3000 STA STATUS›3010 RTS ›3020 *›3030 * turn motor on›3040 *›3050 MOTON LDA DRA turn motor on›3060 AND #$F7›3070 STA DRA›3080 LDX PHASE step motor in›3090 LDA DRB right phase›3100 AND PHASE1,X›3110 STA DRB›3120 LDA #0 reset MOTOR ON timer›3130 STA MOTIMH›3140 STA MOTIML›3150 LDA STATUS indicate MOTOR ON to STATUS›3160 ORA #$10›3170 STA STATUS›3180 LDX #5›3190 JSR DELAY2 give motor some time to speed up›3200 RTS ›3210 *›3220 * identify inserted diskette›3230 * single or enhanced density›3240 *›3250 IDENT JSR RESTORE›3260 LDA DRA›3270 AND #$DF try enhanced›3280 STA DRA›3290 JSR RDADR READ ADRESS command›3300 BEQ IDENT1 succesfull read?›3310 JSR RDADR no, try again›3320 BEQ IDENT1 ok›3330 LDA DRA otherwise, try single›3340 EOR #$20›3350 STA DRA›3360 LDA STATUS indicate single›3370 AND #$7F›3380 STA STATUS›3390 RTS ›3400 IDENT1 LDA STATUS›3410 ORA #$80 indicate enhanced›3420 STA STATUS›3430 RTS ›3440 *›3450 * turn motor on if not on›3460 * & reset MOTOR ON timer›3470 *›3480 TMOTON LDA DRA›3490 AND #8 already on?›3500 BEQ ZF18A›3510 JSR MOTON no, turn it on›3520 ZF18A LDA #0›3530 STA MOTIML›3540 STA MOTIMH reset timer›3550 RTS ›3560 *›3570 * delay, (X) * 100 micro seconds›3580 *›3590 DELAY1 LDY #$12›3600 D11 DEY ›3610 BNE D11›3620 DEX ›3630 NOP ›3640 NOP ›3650 BNE DELAY1›3660 RTS ›3670 *›3680 * delay, (X) * 10 milliseconds›3690 *›3700 DELAY2 STX SBUF SBUF used as counter›3710 D21 LDY #4›3720 STY SBUF+1›3730 D22 LDX #$FA›3740 JSR DELAY1›3750 DEC SBUF+1›3760 BNE D22›3770 DEC SBUF›3780 BNE D21›3790 RTS ›3800 *›3810 * delay, (X) * 5 + 12 micro seconds›3820 *›3830 DELAY3 DEY ›3840 BNE DELAY3›3850 RTS ›3860 *›3870 * 10 steps to the middle, and restore›3880 *›3890 SIREST LDA #10›3900 JSR DOSTEPS make the steps›3910 *›3920 * restore on track 0›3930 *›3940 RESTORE JSR FORCE force IRQ›3950 JSR FORCE interrupt floppy command›3960 LDA #$FF direction: from the middle›3970 STA DIR›3980 LDA #0›3990 STA STEPCNT no steps›4000 STA STEPS›4010 RESTOR1 LDA FCNTRL on track 0?›4020 AND #4›4030 BEQ RESTOR2 br if so›4040 JSR HSTEP make half a step›4050 JMP RESTOR1 until on track 0›4060 RESTOR2 LDA PHASE in phase 4?›4070 CMP #3›4080 BEQ RESTOR3 br if so›4090 JSR HSTEP otherwise, go on›4100 JMP RESTOR2 until on track 0, phase 4›4110 RESTOR3 LDA #0›4120 STA TRKREG reset track register›4130 STA STEPCNT and step counter›4140 LDX #$C8 20 milli seconds delay›4150 JSR DELAY1›4160 RTS ›4170 *›4180 * make half a step›4190 * the step motor runs a cyclus of 4 phases, equal to 2 tracks›4200 *›4210 HSTEP JSR DOHSTEP make half a step›4220 JSR FORCE interrupt floppy command›4230 LDX #$64 10 ms delay›4240 JMP DELAY1›4250 *›4260 * do half a step›4270 *›4280 DOHSTEP INC STEPCNT incr counter›4290 LDA STEPCNT›4300 CMP #$78 already 120 steps?›4310 BCS STEPERR if so, something wrong›4320 LDA DRA motor on?›4330 AND #8›4340 BEQ STEP is so, alright›4350 STEPERR BRK step error: motor off or too many steps›4360 STEP LDX PHASE›4370 LDA PHASE1,X get mask for phase›4380 EOR #$FF invert›4390 TAY ›4400 BIT DIR get step direction›4410 BPL STEPM for following phase›4420 INX step forward›4430 CPX #4 cyclus done?›4440 BNE STEP1›4450 LDX #0 if so, do it again›4460 BEQ STEP1›4470 STEPM DEX step backward›4480 BPL STEP1 cyclus done?›4490 LDX #3 if so, do it again backward›4500 STEP1 STX PHASE save new phase›4510 TYA reset old phase›4520 ORA DRB›4530 AND PHASE1,X set new phase›4540 STA DRB›4550 RTS ›4560 *›4570 * seek track number in 008D›4580 *›4590 SEEK JSR FORCE interrupt actual command›4600 LDA TRACK get destination track›4610 SEC ›4620 SBC TRKREG subtract actual track›4630 BNE DOSTEPS already there?›4640 RTS yes, done›4650 *›4660 * make as many steps as value in accu›4670 *›4680 DOSTEPS BMI DOST1 step backward?›4690 LDX #1 no, forward›4700 BPL DOSTEP1›4710 DOST1 LDX #$FF backward›4720 EOR #$FF get two's complement›4730 CLC ›4740 ADC #1›4750 DOSTEP1 ASL A two times (2 phases/step)›4760 BPL DOSTEP2 br if ok›4770 JSR RESTORE otherwise too many steps: restore›4780 LDA #$80 indicate error›4790 STA STATUS›4800 RTS ›4810 DOSTEP2 STA STEPS number of steps›4820 STX DIR direction›4830 LDA #0›4840 STA STEPCNT reset count of error steps›4850 DOSTEP3 JSR HSTEP make half a step›4860 DEC STEPS all done?›4870 BNE DOSTEP3 no, continue›4880 BIT DIR backward step?›4890 BMI CHKTRK br if so›4900 LDA #$FF otherwise step backward›4910 STA STEPS but first one step too much›4920 LDA #0 forward, so track will always›4930 STA STEPCNT be encountered from the›4940 JSR HSTEP same direction›4950 LDA #$FF›4960 STA DIR›4970 JSR HSTEP step backward›4980 LDA #0 reset error count›4990 STA STEPS›5000 STA STEPCNT›5010 *›5020 * set bit 4 of PORT A for tracks > track 20›5030 *›5040 CHKTRK LDA TRACK›5050 STA TRKREG actual track in track register›5060 CMP #20 greater then 20?›5070 BCC KTR20 no›5080 LDA #$10 otherwise, set bit 4 of PORT A›5090 ORA DRA›5100 BNE GTR20 br always›5110 KTR20 LDA #$EF reset bit 4 of PORT A›5120 AND DRA for track less then 20›5130 GTR20 STA DRA›5140 LDX #$C8›5150 JSR DELAY1 20 ms delay after SEEK›5160 *›5170 * force IRQ, interrupt floppy command›5180 *›5190 DFORCE JSR FORCE two times force IRQ›5200 FORCE LDA #$D0›5210 STA FCNTRL command force IRQ›5220 LDX #7 short delay›5230 FORC1 DEX ›5240 BNE FORC1›5250 LDA #0›5260 FORC2 BIT FCNTRL wait until›5270 BNE FORC2 controller ready›5280 RTS ›5290 *›5300 * command from CPU?›5310 *›5320 TKOMND LDA #2›5330 BIT DRB test bit 1 of PORT B ???›5340 BNE NOKOM›5350 BMI TKOM1 bit 7 of PORT B = 1?›5360 NOKOM RTS no command from CPU›5370 *›5380 * link other parts›5390 *›5400 .INCLUDE #D8:FLOPOS2.M65›5410 .OPT LIST›5420 .INCLUDE #D8:FLOPOS3.M65›5430 .INCLUDE #D8:FLOPOS4.M65›5440 .INCLUDE #D8:FLOPOS5.M65›5450 .OPT NO LIST›