Also, adjust SD card recipe. Straightforward initialization and read!pull/10/head
@@ -131,3 +131,85 @@ sdcCmdR7: | |||
out (SDC_PORT_CSHIGH), a | |||
ret | |||
; Initialize a SD card. This should be called at least 1ms after the powering | |||
; up of the card. Sets result code in A. Zero means success, non-zero means | |||
; error. | |||
sdcInitialize: | |||
push hl | |||
push de | |||
push bc | |||
call sdcWakeUp | |||
; Call CMD0 and expect a 0x01 response (card idle) | |||
; This should be called multiple times. We're actually expected to. | |||
; Let's call this for a maximum of 10 times. | |||
ld b, 10 | |||
.loop1: | |||
ld a, 0b01000000 ; CMD0 | |||
ld hl, 0 | |||
ld de, 0 | |||
ld c, 0x95 | |||
call sdcCmdR1 | |||
cp 0x01 | |||
jp z, .cmd0ok | |||
djnz .loop1 | |||
; Nothing? error | |||
jr .error | |||
.cmd0ok: | |||
; Then comes the CMD8. We send it with a 0x01aa argument and expect | |||
; a 0x01aa argument back, along with a 0x01 R1 response. | |||
ld a, 0b01001000 ; CMD8 | |||
ld hl, 0 | |||
ld de, 0x01aa | |||
ld c, 0x87 | |||
call sdcCmdR7 | |||
cp 0x01 | |||
jr nz, .error | |||
xor a | |||
cp h ; H is zero | |||
jr nz, .error | |||
cp l ; L is zero | |||
jr nz, .error | |||
ld a, d | |||
cp 0x01 | |||
jp nz, .error | |||
ld a, e | |||
cp 0xaa | |||
jr nz, .error | |||
; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we | |||
; the card goes out of idle mode, that is, when it stops sending us | |||
; 0x01 response and send us 0x00 instead. Any other response means that | |||
; initialization failed. | |||
.loop2: | |||
ld a, 0b01110111 ; CMD55 | |||
ld hl, 0 | |||
ld de, 0 | |||
call sdcCmdR1 | |||
cp 0x01 | |||
jr nz, .error | |||
ld a, 0b01101001 ; CMD41 (0x40000000) | |||
ld hl, 0x4000 | |||
ld de, 0x0000 | |||
call sdcCmdR1 | |||
cp 0x01 | |||
jr z, .loop2 | |||
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: | |||
ld a, 0x01 | |||
jr .end | |||
.success: | |||
xor a | |||
.end: | |||
pop bc | |||
pop de | |||
pop hl | |||
ret |
@@ -11,7 +11,7 @@ jr init | |||
; Why not use this unused space between 0x02 and 0x28 for a jump table? | |||
jp printstr | |||
jp printHex | |||
jp sdcWakeUp | |||
jp sdcInitialize | |||
jp sdcSendRecv | |||
jp sdcWaitResp | |||
jp sdcCmd | |||
@@ -29,6 +29,8 @@ init: | |||
ld sp, hl | |||
im 1 | |||
call aciaInit | |||
xor a | |||
call blkSel | |||
call shellInit | |||
; TODO - block device creation | |||
@@ -43,9 +45,15 @@ ACIA_RAMSTART .equ RAMSTART | |||
.define STDIO_PUTC call aciaPutC | |||
STDIO_RAMSTART .equ ACIA_RAMEND | |||
#include "stdio.asm" | |||
SHELL_RAMSTART .equ STDIO_RAMEND | |||
.define SHELL_IO_GETC call aciaGetC | |||
.define SHELL_IO_PUTC call aciaPutC | |||
BLOCKDEV_RAMSTART .equ STDIO_RAMEND | |||
BLOCKDEV_COUNT .equ 1 | |||
#include "blockdev.asm" | |||
; List of devices | |||
.dw aciaGetC, aciaPutC, 0, 0 | |||
SHELL_RAMSTART .equ BLOCKDEV_RAMEND | |||
.define SHELL_IO_GETC call blkGetCW | |||
.define SHELL_IO_PUTC call blkPutC | |||
SHELL_EXTRA_CMD_COUNT .equ 0 | |||
#include "shell.asm" | |||
@@ -1,9 +1,9 @@ | |||
JUMP_PRINTSTR .equ 0x03 | |||
JUMP_PRINTHEX .equ 0x06 | |||
JUMP_SDCWAKEUP .equ 0x09 | |||
JUMP_SDCSENDRECV .equ 0x0c | |||
JUMP_SDCWAITRESP .equ 0x0f | |||
JUMP_SDCCMD .equ 0x12 | |||
JUMP_SDCCMDR1 .equ 0x15 | |||
JUMP_SDCCMDR7 .equ 0x18 | |||
JUMP_PRINTSTR .equ 0x02 | |||
JUMP_PRINTHEX .equ 0x05 | |||
JUMP_SDCINITALIZE .equ 0x08 | |||
JUMP_SDCSENDRECV .equ 0x0b | |||
JUMP_SDCWAITRESP .equ 0x0e | |||
JUMP_SDCCMD .equ 0x11 | |||
JUMP_SDCCMDR1 .equ 0x14 | |||
JUMP_SDCCMDR7 .equ 0x17 | |||
@@ -1,62 +1,9 @@ | |||
#include "jumptable.inc" | |||
.org 0x9000 | |||
call JUMP_SDCWAKEUP | |||
; We expect a 0x01 R1 response | |||
ld hl, sCmd | |||
call JUMP_PRINTSTR | |||
ld a, 0b01000000 ; CMD0 | |||
ld hl, 0 | |||
ld de, 0 | |||
ld c, 0x95 | |||
call JUMP_SDCCMDR1 | |||
cp 0x01 | |||
call JUMP_SDCINITALIZE | |||
or a | |||
jp nz, .error | |||
ld hl, sOk | |||
call JUMP_PRINTSTR | |||
; We expect a 0x01 R1 response followed by 0x0001aa R7 response | |||
ld hl, sCmd | |||
call JUMP_PRINTSTR | |||
ld a, 0b01001000 ; CMD8 | |||
ld hl, 0 | |||
ld de, 0x01aa | |||
ld c, 0x87 | |||
call JUMP_SDCCMDR7 | |||
ld a, d | |||
cp 0x01 | |||
jp nz, .error | |||
ld a, e | |||
cp 0xaa | |||
jr nz, .error | |||
ld hl, sOk | |||
call JUMP_PRINTSTR | |||
; Now we need to repeatedly run CMD55+CMD41 (0x40000000) until we | |||
; the card goes out of idle mode, that is, when it stops sending us | |||
; 0x01 response and send us 0x00 instead. Any other response means that | |||
; initialization failed. | |||
ld hl, sCmd | |||
call JUMP_PRINTSTR | |||
.loop1: | |||
ld a, 0b01110111 ; CMD55 | |||
ld hl, 0 | |||
ld de, 0 | |||
call JUMP_SDCCMDR1 | |||
cp 0x01 | |||
jr nz, .error | |||
ld a, 0b01101001 ; CMD41 (0x40000000) | |||
ld hl, 0x4000 | |||
ld de, 0x0000 | |||
call JUMP_SDCCMDR1 | |||
cp 0x01 | |||
jr z, .loop1 | |||
cp 0 | |||
jr nz, .error | |||
; Success! out of idle mode! | |||
ld hl, sOk | |||
call JUMP_PRINTSTR | |||
; 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 | |||
@@ -78,17 +25,17 @@ | |||
call JUMP_PRINTSTR | |||
; Command sent, no error, now let's wait for our data response. | |||
ld b, 20 | |||
.loop3: | |||
.loop1: | |||
call JUMP_SDCWAITRESP | |||
; 0xfe is the expected data token for CMD17 | |||
cp 0xfe | |||
jr z, .loop3end | |||
jr z, .loop1end | |||
cp 0xff | |||
jr nz, .error | |||
djnz .loop3 | |||
djnz .loop1 | |||
jr .error | |||
.loop3end: | |||
.loop1end: | |||
ld hl, sGettingData | |||
call JUMP_PRINTSTR | |||
; Data packets follow immediately | |||