eris2010

Documentation: http://frombelow.net/projects/eris2010/
Clone: git clone https://git.frombelow.net/eris2010.git
Log | Files | Refs | README | LICENSE

sd.asm (5352B)


      1 ;;; Copyright 2021 Gerd Beuster (gerd@frombelow.net). This is free
      2 ;;; software under the GNU GPL v3 license or any later version. See
      3 ;;; COPYING in the root directory for details.
      4 
      5 ;; -----------------------------------
      6 ;;; 
      7 ;;; SD card communication interface
      8 ;;; 
      9 ;;; -----------------------------------
     10 
     11 
     12 sd .namespace
     13 
     14 .section zero_page
     15 data:	.word ?
     16 	;; type does not need to be on the zero page.
     17 type:	.byte ?		; $05 = SD; $c1 = SDHC
     18 	;; Everything beyond these reserved variables available to
     19 	;; programs in RAM.
     20 .send zero_page
     21 
     22 .section rom
     23 	
     24 send_cmd:
     25 	.block
     26 	ldy #$00
     27 cmd_bytes_loop:
     28 	lda (sd.data),y
     29 	jsr via.spi_set
     30 	iny
     31 	cpy #$06
     32 	bne cmd_bytes_loop
     33 	lda #$ff		; Finalize transmission
     34 	jsr via.spi_set		; with dummy byte
     35 	rts
     36 	.bend
     37 
     38 
     39 print_block:
     40 	.block
     41 	ldx #$02
     42 	ldy #$00
     43 loop:
     44 	phx
     45 	phy
     46 	lda (sd.data),y
     47 	jsr io.puth
     48 	#io.PRINTS " "
     49 	ply
     50 	plx
     51 	iny
     52 	bne loop
     53 	#mem.ADD_WORD sd.data, $0100
     54 	dex
     55 	bne loop
     56 	#io.PRINTNL
     57 	#mem.SUB_WORD sd.data, $0200
     58 	rts
     59 	.bend
     60 	
     61 read_block:
     62 	;; Read a block of data
     63 	;; Block number is passed via stack.
     64 	.block
     65 	jsr ds.create_stack_frame
     66 	#ds.PUSH $04		; Local variable (32 bit block number)
     67 .if DEBUG	
     68 	#io.PRINTSNL "Sending CMD17"
     69 .endif
     70 	lda #$51		; CMD17 (READ_SINGLE_BLOCK)
     71 	jsr via.spi_set
     72 .if DEBUG
     73 	ldy #$00
     74 	lda (ds.frame_ptr),y
     75 	jsr io.puth
     76 	ldy #$01
     77 	lda (ds.frame_ptr),y
     78 	jsr io.puth
     79 	ldy #$02
     80 	lda (ds.frame_ptr),y
     81 	jsr io.puth
     82 	ldy #$03
     83 	lda (ds.frame_ptr),y
     84 	jsr io.puth
     85 .endif
     86 	jsr send_block_number
     87 	lda #$01		; Dummy CRC
     88 	jsr via.spi_set
     89 	jsr via.spi_get
     90 	cmp #$00
     91 	beq wait_for_start_token
     92 	jmp read_failed
     93 wait_for_start_token:	
     94 	jsr via.spi_get_nonblocking
     95 	cmp #$ff
     96 	beq wait_for_start_token
     97 	cmp #$fe
     98 	beq read_ok
     99 	jmp read_failed
    100 read_ok:	
    101 	ldx #$02
    102 	ldy #$00
    103 loop:	
    104 	phx
    105 	phy
    106 	jsr via.spi_get_nonblocking
    107 	ply
    108 	plx
    109 	sta (sd.data),y
    110 	iny
    111 	bne loop
    112 .if DEBUG
    113 	pha
    114 	phx
    115 	phy
    116 	#io.PRINTSNL "Got half block!"
    117 	ply
    118 	plx
    119 	pla
    120 .endif
    121 	#mem.ADD_WORD sd.data, $0100	; Second half of block
    122 	dex
    123 	bne loop
    124 	#mem.SUB_WORD sd.data, $0200	; Restore pointer
    125 	#sd.RECEIVE $2	; Get CRC
    126 	jsr ds.delete_stack_frame
    127 	clc
    128 	rts
    129 read_failed:
    130 	#io.PRINTSNL "Error reading SD card!"
    131 	sec
    132 	jsr ds.delete_stack_frame
    133 	rts
    134 	.bend
    135 
    136 send_block_number:
    137 	.block
    138 	lda sd.type	; Old cards expect the position
    139 	cmp #$05		; as bytes, not blocks
    140 	beq old_card
    141 	#ds.lda_LOCAL 0		; Block number
    142 	jsr via.spi_set
    143 	#ds.lda_LOCAL 1
    144 	jsr via.spi_set
    145 	#ds.lda_LOCAL 2
    146 	jsr via.spi_set
    147 	#ds.lda_LOCAL 3
    148 	jsr via.spi_set
    149 	rts
    150 old_card:
    151 	#ds.lda_LOCAL 3
    152 	asl a
    153 	#ds.sta_LOCAL 3
    154 	#ds.lda_LOCAL 2
    155 	rol a
    156 	#ds.sta_LOCAL 2
    157 	#ds.lda_LOCAL 1
    158 	rol a
    159 	jsr via.spi_set
    160 	#ds.lda_LOCAL 2
    161 	jsr via.spi_set
    162 	#ds.lda_LOCAL 3
    163 	jsr via.spi_set
    164 	lda #$00
    165 	jsr via.spi_set
    166 	rts
    167 	.bend
    168 	
    169 write_block:
    170 	;; Write block at data to card.
    171 	;; Block number is passed via stack.
    172 	.block
    173 	jsr ds.create_stack_frame
    174 	#ds.PUSH $04		; Local variable (32 bit block number)
    175 .if DEBUG	
    176 	#io.PRINTSNL "Sending CMD24"
    177 .endif
    178 	lda #$58		; CMD24 (WRITE_BLOCK)
    179 	jsr via.spi_set
    180 	jsr send_block_number
    181 	lda #$01		; Dummy CRC
    182 	jsr via.spi_set
    183 	lda #$ff
    184 	jsr via.spi_set		; Dummy byte
    185 	#sd.RECEIVE $1
    186 	;; Send start token
    187 	lda #$fe
    188 	jsr via.spi_set
    189 	;; Send data
    190 	ldx #$02
    191 	ldy #$00
    192 write_loop:
    193 	phx
    194 	phy
    195 	lda (sd.data),y
    196 	jsr via.spi_set
    197 	ply
    198 	plx
    199 	iny
    200 	cpy #$00
    201 	bne write_loop
    202 	#mem.ADD_WORD sd.data, $0100	; Second half of block
    203 	dex
    204 	cpx #$00
    205 	bne write_loop
    206 	#mem.SUB_WORD sd.data, $0200	; Restore pointer
    207 	;; Wait for write operation to complete
    208 	#sd.RECEIVE $1
    209 	cmp #$e5
    210 	bne error_writing
    211 wait_loop:
    212 	#sd.RECEIVE $1
    213 	beq wait_loop
    214 	jsr ds.delete_stack_frame
    215 	clc
    216 	rts
    217 error_writing:
    218 	#io.PRINTSNL "Error writing to SD card!"
    219 	jsr ds.delete_stack_frame
    220 	sec
    221 	rts
    222 	.bend
    223 
    224 close:
    225 	#mem.SET_BITS via.ra, #via.CS
    226 	rts
    227 
    228 open:
    229 	.block
    230 .if DEBUG	
    231 	#io.PRINTSNL "Initializing SD Card"
    232 .endif
    233 	;; Configure ports for in- and output
    234 	#mem.SET_BITS via.ddra, #(via.CS | via.SCK | via.MOSI)
    235 	#mem.CLEAR_BITS via.ddra, #via.MISO
    236 	ldy #$10		; Error counter
    237 	phy
    238 start_init:	
    239 	;; Card power on sequence:
    240 	;; Keep CS high, toggle clock for at least 74 cycles.
    241 	#mem.SET_BITS via.ra, #(via.CS | via.MOSI)
    242 	;; Wait for 80 clock pulses
    243 	ldx #160
    244 boot_wait_loop:
    245 	#mem.TOGGLE_BITS via.ra, #via.SCK
    246 	dex
    247 	bne boot_wait_loop
    248 	#mem.CLEAR_BITS via.ra, #(via.CS|via.MOSI|via.SCK)
    249 	#sd.SEND_CMD [$40, $00, $00, $00, $00, $95] ; CMD0
    250 	#sd.RECEIVE $1
    251 	cmp #$01		; Should be $01 (In idle state).
    252 	beq cont
    253 	ply
    254 	dey
    255 	phy
    256 	beq failed_init
    257 	jmp start_init		; If not, start over.
    258 failed_init:
    259 	ply
    260 	#io.PRINTSNL "Error initializing SD card!"
    261 	sec
    262 	rts
    263 cont:
    264 	;; Card is in SPI mode
    265 	ply
    266 	#sd.SEND_CMD [$48, $00, $00, $01, $aa, $87] ; CMD8
    267 	#sd.RECEIVE $1
    268 	#sd.SEND_CMD [$45, $00, $00, $00, $00, $5b] ; CMD5
    269 	#sd.RECEIVE $1 ; $05 = SD; $c1 = SDHC
    270 	sta sd.type
    271 	#sd.SEND_CMD [$7b, $00, $00, $00, $00, $83] ; CMD59
    272 	#sd.RECEIVE $1 ; should be $01
    273 	;; Send ACMD41 until card is initialized
    274 	ldy #$10		; Fail counter
    275 	phy
    276 wait_for_card_initialized:
    277 	#sd.SEND_CMD [$77, $00, $00, $00, $00, $65] ; CMD55
    278 	#sd.RECEIVE $1 ; should be $01
    279 	#sd.SEND_CMD [$69, $40, $00, $00, $00, $95] ; ACMD41 (v1 & v2 card)
    280 	#sd.RECEIVE $1 ; $01 if busy, $00 if ready (initialized)
    281 	cmp #$00
    282 	beq initialized
    283 	ply
    284 	dey
    285 	phy
    286 	bne cont2		; More tries?
    287 cont2:	
    288 	jmp wait_for_card_initialized
    289 initialized:
    290 	ply
    291 	#sd.SEND_CMD [$50, $00, $00, $02, $00, $15] ; CMD16
    292 	#sd.RECEIVE $1
    293 	clc
    294 	rts
    295 	.bend
    296 
    297 .send rom
    298 .endn