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›