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
