[Contents] [Commodore] [New] [Search] [Home]

Commodore 1571 firmware
MFM Control

        .page  
	.subttl 'mfmcntrl.src'

;bit   7   -           test track
;bit   6   -           test sector
;bit   5   -           test write protect switch
;bit   4   -           motor on
;bit   3   -           seek to track
;bit   2   -           wait for motor up to speed
;bit   1   -           logical seek
;bit   0   -           error return

cmdinf   .byte  $00,$15,$00,$00,$00,$15,$00,$bc          
         .byte  $34,$de,$fe,$dc,$15,$15,$00     

cmdjmp   .word    cmdzer         ; reset
         .word    cmdone         ; bump
         .word    cmdtwo         ; wp status
         .word    cmdthr         ; setup for step
         .word    cmdfor         ; reserved
         .word    cmdfve         ; read address
         .word    seke		 ; seek physical
         .word    cmdsev         ; format track
         .word    cmdeig         ; format disk
         .word    cmdnin         ; read sector
         .word    cmdten         ; write sector
         .word    cmdele         ; verify
         .word    cmdtwv         ; verify format
         .word    cmdthi         ; create sector table
         .word    diskin	 ; is the disk home ?

cmdis    =  *-cmdjmp     
        .page    
prcmd   sei      
	pha		; save cmd
        tax      
        lda  cmdinf,x   ; get information
        sta  info        
	lda  dkmode
	ora  #$80	; mfm mode
	sta  dkmode

        asl  info       ; check track
        bcc  prc00       

        lda  cmdbuf+3
        sta  cmd_trk	; save track
prc00   asl  info       ; check sector
        bcc  prc01       

        lda  cmdbuf+4
        sta  sectr      ; save sector
prc01   asl  info       ; check wp for write jobs
        bcc  prc02       

        lda  dskcnt
        and  #$10
        bne  prc02       

	lda  switch	; set kill job switch
	ora  #%00001000
	sta  switch	; wp error
        ldx  #8          
	stx  ctl_dat

prc02   asl  info       ; motor on ?
        bcc  prc03       

        jsr  stmtr      ; start motor
prc03   asl  info       ; seek ?
        bcc  prc04      ; seek physical while motor is spinning

        jsr  seke       ; seek job
prc04   asl  info       ; wait for motor up to speed ?
        bcc  prc05       

        jsr  wtmtr      ; go and wait

; disk up to speed

prc05   jsr  sel_sid	; select 
	asl  info	; logical seek required ?
	bcc  prc06

	jsr  s_log	; seek by reading

; disk up to speed and on track

prc06   lda  #0          
        pla		; get jobs
        asl  a   
        tax      
        lda  cmdjmp,x   ; do indirect
        sta  temp        
        lda  cmdjmp+1,x          
        sta  temp+1      

	jsr  do_the_command

	jsr  trnoff	; motor off...

	ldx  mfmcmd
	cpx  #2
	php

	asl  info
	bcs  prc07
 
  	plp
	bcc  prc08

	jmp  exbad

prc07	plp		; restore status

prc08	rts

do_the_command	jmp  (temp)

	.page


;******************************************************

moton   php		; no irq's
	sei
	lda  dskcnt
	ora  #4
	sta  dskcnt
	plp		; retrieve status
	rts

;******************************************************

motoff  php		; no irq's
	sei
	lda  dskcnt
	and  #$ff-$04
	sta  dskcnt
	plp		; retrieve status
	rts

;******************************************************

led_on	php		; no irq's
	sei		
	lda  dskcnt	; turn on led
	ora  #8
	sta  dskcnt
	plp		; retrieve status
	rts

;******************************************************

led_off	php		; no irq's
	sei
	lda  dskcnt	; turn led off
	and  #$ff-$08
	sta  dskcnt
	plp		; retrieve status
	rts

;******************************************************

stmtr   php      
        sei      
        lda  drvst       
	bmi  2$		; accelerating ?

	and  #bit5+bit4
	beq  1$

        lda  #$20       ; disk up to speed
        sta  drvst
2$	plp
	rts

1$	plp
	sta  cdrive	; set drive
        jmp  turnon	; turn on motor
	nop
	nop
	nop
	nop
	nop
	nop

;******************************************************

wtmtr   php             ; wait for motor up to speed
        cli      
wtmtr1  lda  drvst       
        cmp  #$20       ; drv ready ?
        bne  wtmtr1      

        plp      
        rts      

;******************************************************

seke    php  		; wait for not busy
        cli             ; enable irqs for motor on timing
        lda  cmd_trk
        asl  a          ; half steps
        cmp  cur_trk	; correct track ?
        beq  sekrtn     ; br, yep

seklop  lda  cmd_trk	; where
        asl  a   
        cmp  cur_trk
        beq  sekdun      

        bcs  sekup      ; hi or lo ?

sekdn   jsr  stout      ; step out
        jmp  seklop     ; next

sekup   jsr  stin       ; step in
        jmp  seklop     ; next also

sekdun  ldy  #$10	; settle
        jsr  xms        ; delay

sekrtn  plp      
        rts      

;******************************************************

stin    lda  cur_trk	; get current valuestep
	clc
	adc  #1
        jmp  stpfin     ; half step out

stout   ldy  #99	; wait for trk_00
1$	lda  pota1	; check for trk_00
	ror  a		; rotate into carry
	php		; save carry
	lda  pota1	; debounce it
	ror  a		; carry <=
	ror  a		; bit 7 <=
	plp		; retrieve carry
	and  #$80	; sclear sign bit
	bcc  3$		; on track zero

	bpl  2$		; carry set(off) & sign(on) exit

	bmi  4$		; bra

3$	bmi  2$		; carry clear(on) & sign(off) exit

4$	dey	
	bne  1$		; continue

	bcs  2$		; br, not track 00 ?

	lda  dskcnt	; phase 0
	and  #3
	bne  2$

	lda  #0		; trk zero
	sta  cur_trk	; current trk = 400
	rts

2$	lda  cur_trk	; get current half step
        sec
	sbc #1

stpfin  sta  cur_trk	; save
        and  #3         ; strip unused
        sta  temp        
	php		; no irq's
	sei
        lda  dskcnt
        and  #$fc       ; strip step bits
        ora  temp        
        sta  dskcnt
	plp		; retrieve status
        ldy  #$06	; 6 ms step time, 16 ms settle
        
xms     jsr  onems      ; delay 1 ms
        dey      
        bne  xms         

        rts      


;******************************************************

onems   ldx  #2
        lda  #$6f	; *** rom ds 85 ***, beta9 1 mS.
onems1  adc  #1          
        bne  onems1      

        dex      
        bne  onems1      

        rts      


;******************************************************


cvstat  WDTEST		; chk address
	lda  wdstat     ; retrieve status
        lsr  a   
        lsr  a   
        lsr  a   
        and  #3         ; check status
        tax      
        lda  mfmer,x     
	sta  mfmcmd
	tax
        rts      

;******************************************************

strtwd  pha		; save accum
	jsr  led_on	; act led on
	pla
	WDTEST		; chk address
	sta  wdstat	; send cmd to wd 1770
	lda  #1		; wait for busy
	WDTEST		; chk address
1$	bit  wdstat
	beq  1$

	jmp  jslower	; WD1770 bug ????


;******************************************************

waitdn  jsr  led_off	; act led off
	lda  #1		; wait for unbusy
	WDTEST		; chk address
1$	bit  wdstat
	bne  1$

	rts

	.page	

;******************************************************

sectnx  lda  minsek	
	sec
	sbc  #1
	sta  ctl_dat	; save min sector - 1
	lda  cmdbuf+4	; get original sector
	clc
	adc  cpmit	; next sector
	cmp  maxsek
	beq  2$		; equal to or

	bcc  2$		;          less than

	sbc  maxsek	; rap around
	clc	
	adc  ctl_dat	; add min now
2$	sta  cmdbuf+4	; next sector for controller
	rts

	.page

;******************************************************

sectcv	ldy  #0
	ldx  #0
	lda  cmdbuf+3   ; start at sector x
	and  #$3f	; delete mode bit & table bit
	sta  cmdbuf+3
	sta  minsek	; new min
	pha		; save ss
	lda  cmdbuf+7	; save ns
	pha
	inc  cmdbuf+4	; interleave + 1

sectop	lda  cmdbuf+3	; ss
	sta  cmdbuf+11,y ; table goes to cmdbuf+42
	inc  cmdbuf+3	; increment ss
	inx
	tya		; do addition
	clc
	adc  cmdbuf+4	; add interleave
	tay
	cpy  #32	; no more room
	bcs  bd_int

	cpy  cmdbuf+7	; ns
	bcc  secles	; < than

	bne  seclmo	; can't be equal until the end

	cpx  cmdbuf+7	; ns end ?
	beq  seclmo

bd_int  dec  cmdbuf+4	; restore
	pla
	sta  cmdbuf+7	; restore ns
	pla
	sta  cmdbuf+3	; restore ss

	sec
	rts		; bad exit

seclmo  tya
	sec
	sbc  cmdbuf+7	; ns
	tay

secles	cpx  cmdbuf+7	; ns
	bne  sectop

	stx  cpmsek	; ns
	dex
	txa
	clc
	adc  minsek	; find max
	sta  maxsek	; new max
	cmp  minsek	; better be less than max
	bcc  bd_int	; bad starting sector

	pla
	sta  cmdbuf+7	; restore ns
	pla
	sta  cmdbuf+3	; restore ss
	dec  cmdbuf+4	; restore

	clc		; ok exit
	rts        


;******************************************************


verfmt	lda  mfmcmd
	pha		; save current logical track

	ldy  #0
	sty  mfmhdr	; init index into sector table
ver_fm	ldy  mfmhdr	; get current index
	lda  cmdbuf+11,y
	sta  wdsec	; setup sector for wd 1770
	jsr  cmdtwv	; verify
	ldx  mfmcmd	; get error
	cpx  #2
	bcs  ver_00

	inc  mfmhdr	; next entry in sector table
	ldy  mfmhdr
	cpy  cmdbuf+7	; check with ns
	bne  ver_fm	; done ?

	clc
	.byte  skip1	
ver_00	sec
	pla
	sta  mfmcmd	; restore track address
no_trk	rts


;******************************************************

chcsee	lda  cmdsiz
	cmp  #7		; next track parameter given ?
	bcc  no_trk

	lda  cmdbuf+6	; get nt
	sta  cmd_trk
	jmp  seke


;******************************************************


s_log	lda  mfmcmd	; save command
	pha
	jsr  cmdfiv	; where are we?
	ldx  mfmcmd	; status ok?
	cpx  #2
	bcc  1$		; see if we are there...

	jsr  cmdone	; restore to trk_00
	jsr  cmdfiv	; where are we.. better be track 00
	ldx  mfmcmd	; status ok?
	cpx  #2
	bcs  2$		; on error leave on track 00

1$	lda  cmd_trk	; we there yet ?
	asl  a
	cmp  cur_trk	; are we on ?
	beq  2$

	jsr  seke	; find it...should be there now...hope?

2$	pla
	sta  mfmcmd	; restore command	
	rts


;******************************************************


sel_sid php		; no irq's
	sei
	lda  switch
	and  #%00010000 ; check side
	cmp  #%00010000	; sclr carry
	jsr  set_side	; setw
	plp		; retrieve status
	rts

;******************************************************

maxmin	ldy  cpmsek	; get ns
	dey		; one less
	lda  #255	; as small as min can get
minim	cmp  cmdbuf+11,y
	bcc  no_min	; br, no change

	lda  cmdbuf+11,y
no_min	dey
	bpl  minim

	sta  minsek	; save min

	ldy  cpmsek	
	dey		; one less
	lda  #0		; as small as max can get
maxim	cmp  cmdbuf+11,y
	bcs  no_max	; br, no change

	lda  cmdbuf+11,y
no_max	dey
	bpl  maxim

	sta  maxsek	; save max
	rts

;******************************************************

fn_int	ldx  cpmsek	; location of min
	ldy  #0		; start in beginning
fn_000	lda  cmdbuf+11,y	
	cmp  minsek
	beq  fn_001	; min ?

	iny
	cpy  cpmsek
	bne  fn_000	

fn_001  sty  ctl_cmd	; save index
	lda  minsek	; get min
	clc	
	adc  #1		; add one to it
	sta  ctl_dat	; save min + 1

	ldx  #255	; interleave at zero
fnlook	lda  cmdbuf+11,y
	cmp  ctl_dat	; find min + 1 ?
	beq  fn_002

	inx		; cpmit = cpmit + 1
	iny	
	cpy  cpmsek	; index here ?
	bne  fnlook

	ldy  #0		; rap around
	beq  fnlook 	; bra

fn_002	rts		; return with hard interleave in .x


;******************************************************


diskin  lda  temp
	pha		; save temp
	php		; save status
	sei		; no irq's
	lda  wdtrk	; where are we ?
	sta  wddat	; here we are..
	lda  #$18
	jsr  strtwd	; seek cmd
	jsr  waitdn	; fin ?
	ldx  #0
	ldy  #128	; wait a little more than a revolution
	WDTEST		; chk address
	lda  wdstat	; get start status
	and  #2
	sta  temp	; save current status
	WDTEST		; chk address
1$	lda  wdstat	; get current status
	and  #2
	cmp  temp	; same go on
	beq  2$

	plp		; retrieve status	
	jmp  4$		; finish up ok disk inserted

2$	dex	
	bne  1$

	dey
	bne  1$		; timout ?

	plp		; retrieve status
	sec		; exit no index sensor toggling
	.byte skip1
4$	clc		; ok
	pla
	sta  temp	; restore temp
	rts

[Contents] [Commodore] [New] [Search] [Home]
This page has been created by Sami Rautiainen.
Read the small print. Last updated August 27, 1998.