MODULE_CARD

;	--------------------------------------------------------
;	MMC access
;	--------------------------------------------------------
;	written by TNT/Beyond Force
;
;	use as you wish, but don't claim you wrote it yourself


GO_IDLE_STATE		= $40	; CMD0
SEND_OP_COND		= $41	; CMD1
SET_BLOCKLEN		= $50	; CMD16
READ_SINGLE_BLOCK	= $51	; CMD17
WRITE_BLOCK		= $58	; CMD24
CRC_ON_OFF		= $7b	; CMD59


	MAC	select
	lda	#~2
	and	$df11
	sta	$df11
	ENDM

	MAC	deselect
	lda	#2
	ora	$df11
	sta	$df11
	ENDM


;	reset card
	subroutine
ResetCard

 lda	#6
 sta	bg

	lda	$df11
	and	#$bb		; 250kHz, write trigger
	ora	#2		; deselect
	sta	$df11

	lda	#0		; try 256 times
	sta	tmp

.reset1	ldx	#20		; 160 bits
	ldy	#$ff
	lda	#1
.reset2	sty	$df10
	bit	$df12
	bne	*-3
	dex
	bne	.reset2

;	!! should select and wait be in other order?

	asl
	jsr	WaitRast

	select				; into SPI mode during CMD0

	ldx	#7			; CMD0 (GO_IDLE_STATE)
	lda	#1
.reset3	ldy	ResetCmd.dat,x
	sty	$df10
	bit	$df12
	bne	*-3
	dex
	bpl	.reset3

	and	$df10			; !! "cmp; beq"?
	bne	.resetx
	
	inc	tmp
	bne	.reset1
	sec
	rts

.resetx
 if 0
 	deselect
	lda	#2
	jsr	WaitRast
	select

	lda	#1
 endif

;	idle -> ready

 ldx	#$0e
 stx	bg

.ready1	ldx	#7			; CMD1 (SEND_OP_COND)
.ready2	ldy	ReadyCmd.dat,x
	sty	$df10
	bit	$df12
	bne	*-3
	dex
	bpl	.ready2

.ready3	stx	$df10
	bit	$df12
	bne	*-3
	ldy	$df10
	iny
	beq	.ready3			; $FF - wait
	dey
	bne	.ready1			; not $00 - resend CMD1

	lda	#4			; 8MHz
	ora	$df11
	sta	$df11

	clc
	rts

;	send read command
	subroutine
SendRdCmd
	lda	#READ_SINGLE_BLOCK
	sta	cmd+5
	lda	#0		; pos = sec * $0200
	sta	cmd+1
	lda	sec
	asl
	sta	cmd+2
	lda	sec+1
	rol
	sta	cmd+3
	lda	sec+2
	rol
	sta	cmd+4
	lda	#$ff
	sta	cmd+0

	ldayi	cmd

;	drop thru !

;	send command at AY
	subroutine
SendCmdAY
	stay	cmdPtr

;	lda	#1
;	bit	$df12
;	bne	*-3

	deselect

	ldy	#$ff
	sty	$df10

;	lda	#1
;	bit	$df12
;	bne	*-3

;	lda	$df11
	and	#~2			; select card
	sta	$df11

	ldy	#5
.1	lda	(cmdPtr),y
	sta	$df10
	dey
	bpl	.1

.2	sty	$df10
	lda	$df10
	cmp	#$ff
	beq	.2
	rts

	subroutine
WaitForData
	ldy	#0
.1	ldx	#$ff
	stx	$df10
	dex
	cpx	$df10
	beq	.2
	iny
	cpy	#$ff
	bcc	.1
	lda	#0
	jsr	Dbg
	jsr	ResetCard
	lda	var_BORDERCOLOR
	sta	bg
	jsr	SendRdCmd
	jmp	WaitForData
.2	clc
	rts


	subroutine
ReadBufSector			; read [sec] to buffer, point bufptr to it
	ldayi	b

ReadSectorToAY
	stay	bufptr

;	read single [sec] to [bufptr]

	subroutine
ReadSector
	jsr	Progress

	jsr	SendRdCmd
	jsr	WaitForData

	rtrigger
	ldx	#1
	ldy	#0
.1	lda	$df10
	sta	(bufptr),y
	iny
	bne	.1
	inc	bufptr+1
	dex
	bpl	.1
	wtrigger

	dec	bufptr+1
	dec	bufptr+1

.2	clc
	rts

;	fat sector in memory has low/high bytes deinterleaved

	subroutine
ReadFATSector

	lda	sec
	cmp	FATSecInMem
	beq	.x
	sta	FATSecInMem

	jsr	Progress

	jsr	SendRdCmd
	jsr	WaitForData

	rtrigger
	ldy	#0
.1	lda	$df10			; <cluster to one page
	sta	fatlo,y
	lda	$df10			; >cluster to another
	sta	fathi,y
	iny
	bne	.1
	wtrigger

.x	clc
	rts


;	--------------------------------------------------------

	subroutine
WaitForCard
	lda	#$20			; Flash jumper
	ldy	#$27
	ldx	#0
	jsr	.wait

	lda	#$08			; card inserted
	ldy	#$22
	ldx	#40

.wait	sta	tmp
	sty	tmp+1

	and	$df12
	beq	.x

	lda	bg
	pha

	ldy	#0
.1	lda	.dat,x
	sta	$0400,y
	inx
	iny
	cpy	#40
	bne	.1

.2	lda	tmp+1
	ldx	#4
.3	cmp	#$80
	rol
	dex
	bne	.3
	sta	tmp+1
	ora	#$80			; no IRQ restart
	sta	bg

	lda	#4
	jsr	WaitRast
	lda	$df12
	and	tmp
	bne	.2

	pla
	sta	bg

	lda	#25
	jsr	WaitRast

.x	rts

.dat	dc.b	"      *** REMOVE FLASH JUMPER ***       "
	dc.b	"V0.4            INSERT CARD             "

ResetCmd.dat
	HEX	FF 95 00000000 40 FF	; GO_IDLE_STATE / -> idle
ReadyCmd.dat
	HEX	FF FF 00000000 41 FF	; SEND_OP_COND -> R3 / idle -> ready

MODULE_CARD_END
