diff --git a/parts/z80/sdc.asm b/parts/z80/sdc.asm index e172b60..69f9609 100644 --- a/parts/z80/sdc.asm +++ b/parts/z80/sdc.asm @@ -20,6 +20,18 @@ ; SDC_PORT_CSLOW: Port number to make CS low ; SDC_PORT_SPI: Port number to send/receive SPI data +; *** Consts *** +.equ SDC_BLKSIZE 512 + +; *** Variables *** +; Index of the sector currently contained in SDC_BUF +.equ SDC_SECTOR SDC_RAMSTART +; Whenever we read a sector, we read a whole block at once and we store it +; in memory. That's where it goes. +.equ SDC_BUF SDC_SECTOR+1 +.equ SDC_RAMEND SDC_BUF+SDC_BLKSIZE + +; *** Code *** ; Wake the SD card up. After power up, a SD card has to receive at least 74 ; dummy clocks with CS and DI high. We send 80. sdcWakeUp: @@ -199,7 +211,6 @@ sdcInitialize: or a ; cp 0 jr nz, .error ; Success! out of idle mode! - ; At this point, you are ready to read and write data. jr .success .error: @@ -213,3 +224,74 @@ sdcInitialize: pop de pop hl ret + +; Send a command to set block size to SDC_BLKSIZE to the SD card. +; Returns zero in A if a success, non-zero otherwise +sdcSetBlkSize: + push hl + push de + + ld a, 0b01010000 ; CMD16 + ld hl, 0 + ld de, SDC_BLKSIZE + call sdcCmdR1 + ; Since we're out of idle mode, we expect a 0 response + ; We need no further processing: A is already the correct value. + pop de + pop hl + ret + +; Read block index specified in A and place the contents in (SDC_BUF). +; Doesn't check CRC. +; Returns 0 in A if success, non-zero if error. +; Returns SDC_BUF in HL +sdcReadBlk: + push bc + + out (SDC_PORT_CSLOW), a + ld hl, 0 ; read single block at addr A + ld d, 0 + ld e, a + ld a, 0b01010001 ; CMD17 + call sdcCmd + or a ; cp 0 + jr nz, .error + + ; Command sent, no error, now let's wait for our data response. + ld b, 20 +.loop1: + call sdcWaitResp + ; 0xfe is the expected data token for CMD17 + cp 0xfe + jr z, .loop1end + cp 0xff + jr nz, .error + djnz .loop1 + jr .error ; timeout. error out +.loop1end: + ; We received our data token! + ; Data packets follow immediately, we have 512 of them to read + ld bc, SDC_BLKSIZE + ld hl, SDC_BUF +.loop2: + call sdcWaitResp + ld (hl), a + cpi ; a trick to inc HL and dec BC at the same time. + ; P/V indicates whether BC reached 0 + jp pe, .loop2 ; BC is not zero, loop + ; Read our 2 CRC bytes + call sdcWaitResp + call sdcWaitResp + ; success! + xor a + jr .end +.error: + ; try to preserve error code + or a ; cp 0 + jr nz, .end ; already non-zero + inc a ; zero, adjust +.end: + out (SDC_PORT_CSHIGH), a + ld hl, SDC_BUF + pop bc + ret diff --git a/recipes/rc2014/sdcard/glue.asm b/recipes/rc2014/sdcard/glue.asm index 5519c0e..3bd4f3c 100644 --- a/recipes/rc2014/sdcard/glue.asm +++ b/recipes/rc2014/sdcard/glue.asm @@ -17,6 +17,8 @@ jr init jp sdcCmd jp sdcCmdR1 jp sdcCmdR7 + jp sdcReadBlk + jp sdcSetBlkSize ; interrupt hook .fill 0x38-$ @@ -57,6 +59,7 @@ SHELL_RAMSTART .equ BLOCKDEV_RAMEND SHELL_EXTRA_CMD_COUNT .equ 0 #include "shell.asm" +.equ SDC_RAMSTART SHELL_RAMEND .equ SDC_PORT_CSHIGH 6 .equ SDC_PORT_CSLOW 5 .equ SDC_PORT_SPI 4 diff --git a/recipes/rc2014/sdcard/jumptable.inc b/recipes/rc2014/sdcard/jumptable.inc index 3e99328..b5b1ab5 100644 --- a/recipes/rc2014/sdcard/jumptable.inc +++ b/recipes/rc2014/sdcard/jumptable.inc @@ -6,4 +6,6 @@ JUMP_SDCWAITRESP .equ 0x0e JUMP_SDCCMD .equ 0x11 JUMP_SDCCMDR1 .equ 0x14 JUMP_SDCCMDR7 .equ 0x17 +JUMP_SDCREAD .equ 0x1a +JUMP_SDCSETBLKSIZE .equ 0x1d diff --git a/recipes/rc2014/sdcard/sdinit.asm b/recipes/rc2014/sdcard/sdinit.asm index 1442a92..6c6bec0 100644 --- a/recipes/rc2014/sdcard/sdinit.asm +++ b/recipes/rc2014/sdcard/sdinit.asm @@ -5,51 +5,30 @@ or a jp nz, .error - ; Alright, normally we should configure block size and all, but this is - ; too exciting and we'll play it dirty: we'll read just enough bytes - ; to fetch our "Hello World!" and print it and we'll leave the SD card - ; hanging. Yeah, I know, not very polite. - - - out (5), a - ld hl, sCmd + ld hl, sOk call JUMP_PRINTSTR - ld a, 0b01010001 ; CMD17 - ld hl, 0 ; read single block at addr 0 - ld de, 0 - call JUMP_SDCCMD - cp 0 - jr nz, .error - ld hl, sCmd - call JUMP_PRINTSTR - ; Command sent, no error, now let's wait for our data response. - ld b, 20 -.loop1: - call JUMP_SDCWAITRESP - ; 0xfe is the expected data token for CMD17 - cp 0xfe - jr z, .loop1end - cp 0xff - jr nz, .error - djnz .loop1 - jr .error + call JUMP_SDCSETBLKSIZE + or a + jp nz, .error -.loop1end: - ld hl, sGettingData + ld hl, sOk call JUMP_PRINTSTR - ; Data packets follow immediately - ld b, 12 ; size of "Hello World!" - ld hl, sDest ; sDest has null chars, we'll be alright - ; printing it. -.loop2: - call JUMP_SDCWAITRESP - ld (hl), a - inc hl - djnz .loop2 - out (6), a - ld hl, sDest + + ; read sector 0 + xor a + call JUMP_SDCREAD + or a + jp nz, .error + + push hl + ld hl, sOk call JUMP_PRINTSTR + pop hl + ; SDC buffer address is in HL + ; YOLO! print it! + call JUMP_PRINTSTR + ret .error: call JUMP_PRINTHEX @@ -57,14 +36,7 @@ call JUMP_PRINTSTR ret -sCmd: - .db "CMD", 0xa, 0xd, 0 -sGettingData: - .db "Data", 0xa, 0xd, 0 sOk: .db "Ok", 0xa, 0xd, 0 sErr: .db "Err", 0xa, 0xd, 0 - -sDest: - .fill 0x10