diff --git a/VERSION b/VERSION index 3927117a..594546fb 100644 --- a/VERSION +++ b/VERSION @@ -2,5 +2,5 @@ PACKAGE=picsimlab MAINVER=0 MINORVER=9 VERSION=0.9.0 -DATE=230910 +DATE=230924 VERSION_STABLE=0.9.0 diff --git a/src/Makefile.JS b/src/Makefile.JS index ae2618fb..b5681ec0 100644 --- a/src/Makefile.JS +++ b/src/Makefile.JS @@ -15,25 +15,29 @@ execdir= ${prefix}/bin/ #lxrad automatic generated block start, don't edit below! override CXXFLAGS+= -D_ARCH_=\"Javascript\" -D_DATE_=\"${DATE}\" -override CXXFLAGS+= -O2 -flto=auto -#override CXXFLAGS+= -g4 --source-map-base -Werror +override CXXFLAGS+= -O2 +#override CXXFLAGS+= -fsanitize=address +#override CXXFLAGS+= -gsource-map override CXXFLAGS+= -DEXT_BROWSER -DNO_DEBUG -DNO_TOOLS \ -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s USE_SDL_GFX=2\ - -s SDL2_IMAGE_FORMATS='["png","bmp"]' -s USE_SDL_TTF=2 --preload-file assets \ + -s SDL2_IMAGE_FORMATS='["png","bmp"]' -s USE_SDL_TTF=2 \ -D_VERSION_=\"${VERSION}\" -Wall -D_SHARE_=\"/assets/share/\" -I../../LXRAD_SDL2/include/ \ -D_LIB_=\"../lib/picsimlab/\" \ -I../../picsim/include/ -I../../ucsim-0.6/picsimlab/ \ -I../../simavr/simavr/ -DEXT_BROWSER_EXAMPLES \ -I../teste/glib_js/target/include -I../teste/glib_js/target/include/glib-2.0 \ - -I../teste/glib_js/target/lib/glib-2.0/include #--preload-file home + -I../teste/glib_js/target/lib/glib-2.0/include -override CXXFLAGS+= --pre-js load.js -# -s "BINARYEN_TRAP_MODE='clamp'" +#override CXXFLAGS+= -s "BINARYEN_TRAP_MODE='clamp'" LINK= -s DEMANGLE_SUPPORT=0 -s SAFE_HEAP=0 -s ASSERTIONS=0 -s TOTAL_MEMORY=128MB \ -s EXPORTED_FUNCTIONS='["_main","_file_ready","_lxrad_scale_up","_lxrad_scale_down","_dirt_load","_SimRun","_SimStat"]' \ - -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' + -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' --pre-js load.js --preload-file assets + +#LINK+= --preload-file home +#LINK+= -s ALLOW_MEMORY_GROWTH + #CXXFLAGS+=-s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 #CXXFLAGS+=--emrun diff --git a/src/Makefile.JSMT b/src/Makefile.JSMT index bbf728d3..8852e6a5 100644 --- a/src/Makefile.JSMT +++ b/src/Makefile.JSMT @@ -16,9 +16,10 @@ execdir= ${prefix}/bin/ #-Werror override CXXFLAGS+= -D_ARCH_=\"Javascript_MT\" -D_DATE_=\"${DATE}\" -override CXXFLAGS+= -DEXT_BROWSER -DNO_DEBUG -DNO_TOOLS -O2 -flto=auto\ +override CXXFLAGS+= -s USE_PTHREADS=1 +override CXXFLAGS+= -DEXT_BROWSER -DNO_DEBUG -DNO_TOOLS -O2 \ -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s USE_SDL_GFX=2\ - -s SDL2_IMAGE_FORMATS='["png","bmp"]' -s USE_SDL_TTF=2 --preload-file assets \ + -s SDL2_IMAGE_FORMATS='["png","bmp"]' -s USE_SDL_TTF=2 \ -D_VERSION_=\"${VERSION}\" -Wall -D_SHARE_=\"/assets/share/\" -I../../LXRAD_SDL2/include/ \ -D_LIB_=\"../lib/picsimlab/\" \ -I../../picsim/include/ -I../../ucsim-0.6/picsimlab/ \ @@ -26,13 +27,11 @@ override CXXFLAGS+= -DEXT_BROWSER -DNO_DEBUG -DNO_TOOLS -O2 -flto=auto\ -I../teste/glib_js/target/include -I../teste/glib_js/target/include/glib-2.0 \ -I../teste/glib_js/target/lib/glib-2.0/include # --preload-file home -override CXXFLAGS+= --pre-js load.js # -s "BINARYEN_TRAP_MODE='clamp'" -override CXXFLAGS+= -s USE_PTHREADS=1 LINK= -s DEMANGLE_SUPPORT=0 -s SAFE_HEAP=0 -s ASSERTIONS=0 -s TOTAL_MEMORY=128MB -s WASM=1 -s PTHREAD_POOL_SIZE=1 \ -s EXPORTED_FUNCTIONS='["_main","_file_ready","_lxrad_scale_up","_lxrad_scale_down","_dirt_load","_SimRun","_SimStat"]' \ - -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' + -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' --pre-js load.js --preload-file assets #-s PROXY_TO_PTHREAD #CXXFLAGS+=--emrun diff --git a/src/devices/sdcard.cc b/src/devices/sdcard.cc index fe5f81a4..f0410706 100644 --- a/src/devices/sdcard.cc +++ b/src/devices/sdcard.cc @@ -39,6 +39,31 @@ } else \ printf +// Generator polynomial: G(x) = x7 + x3 + 1 +static unsigned char CRC7(const unsigned char* buffer, const unsigned int size) { + const unsigned char poly = 0x89; + unsigned char crc = 0; + for (unsigned i = 0; i < size; i++) { + crc ^= buffer[i]; + for (int j = 0; j < 8; j++) { + crc = (crc & 0x80) ? ((crc ^ poly) << 1) : (crc << 1); + } + } + return crc >> 1; +} + +// Generator polynomial: x^16 + x^12 + x^5 + 1 +static unsigned short CRC16(const unsigned char* buffer, unsigned int size) { + unsigned char x; + unsigned short crc = 0; + for (unsigned i = 0; i < size; i++) { + x = crc >> 8 ^ buffer[i]; + x ^= x >> 4; + crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x); + } + return crc; +} + void sdcard_rst(sdcard_t* sd) { bitbang_spi_rst(&sd->bb_spi); sd->cmd = 0; @@ -48,7 +73,11 @@ void sdcard_rst(sdcard_t* sd) { sd->ap_cmd = 0; sd->data_rc = 0; sd->data_wc = 0; - sd->multi = 0; + sd->multi_wr = 0; + sd->multi_rd = 0; + sd->crc_on = 0; + sd->R1 = 1; + sd->cmd_count = 0; dprintf("rst sdcard\n"); } @@ -76,10 +105,11 @@ void sdcard_set_card_present(sdcard_t* sd, unsigned char cp) { } } -static char buff[512]; +static unsigned char buff[512]; unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, unsigned char ss) { unsigned int offset = 0; + unsigned short crc16; if (!sd->card_present) { return 1; @@ -94,7 +124,8 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un sd->replyc = 0; sd->data_rc = 0; sd->data_wc = 0; - sd->multi = 0; + sd->multi_wr = 0; + sd->multi_rd = 0; return 1; } @@ -133,7 +164,7 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un sd->data_wc--; - if ((sd->multi) && (!sd->data_wc)) { + if ((sd->multi_wr) && (!sd->data_wc)) { sd->data_wc = 515; } } else { @@ -167,32 +198,92 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un case 48: // crc sd->crc = (sd->bb_spi.insr & 0xFF); dprintf("----------------------------------------\n"); - dprintf("sdcard cmd=0x%02X arg=0x%08lX CRC=0x%02X \n", sd->cmd, sd->arg, sd->crc); + dprintf("sdcard %s%i [0x%02X] arg=0x%08lX CRC=0x%02X \n", (sd->ap_cmd ? "ACMD" : "CMD"), + sd->cmd, sd->cmd, sd->arg, sd->crc); + + if (sd->cmd_count < 10) { + sd->cmd_count++; + sd->R1 = 1; // R1 |0|ParameterE|AddressE|EraseE|CRCE|IllegalC|EraseR|idle| + } else { + sd->R1 = 0; // R1 |0|ParameterE|AddressE|EraseE|CRCE|IllegalC|EraseR|idle| + } if (sd->ap_cmd) { switch (sd->cmd) { + case ACMD13: // SD_STATUS - Send the SD Status. + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = sd->R1; + sd->reply[1] = 0xFE; // start block + // SD status + memset(&sd->reply[2], 0, 64); + sd->reply[2] = 0x00; // DAT_BUS_WIDTH:2 SECURED_MODE:1 reserved:5 + sd->reply[3] = 0X00; // reserved + sd->reply[4] = 0x00; + sd->reply[5] = 0x00; + sd->reply[6] = 0x00; + sd->reply[7] = 0x00; + sd->reply[8] = 0x00; + sd->reply[9] = 0x28; + sd->reply[10] = 0x01; + sd->reply[11] = 0x10; + sd->reply[12] = 0x90; + sd->reply[13] = 0x00; + sd->reply[14] = 0x0B; + sd->reply[15] = 0x05; + // reserved 16-65 + sd->reply[66] = 0xbc; + sd->reply[67] = 0x65; + sd->replyc = 69; + dprintf("sdcard sd_status\n"); + break; case ACMD23: // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be // pre-erased before writing sd->bb_spi.outsr = 0xFF; // fill byte sd->replyc = 2; - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; dprintf("sdcard pre-erased %li\n", sd->arg); break; case ACMD41: // SD_SEND_OP_COMD - Sends host capacity support information and activates // the card's initialization process sd->bb_spi.outsr = 0xFF; // fill byte sd->replyc = 2; - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| - // sd->reply[1] = 0x00; - // sd->reply[2] = 0x00; - // sd->reply[3] = 0x00; - // sd->reply[4] = 0x00; + sd->reply[0] = sd->R1; dprintf("sdcard send_op_comd\n"); break; + case ACMD42: // SET_CLR_CARD_DETECT - Connect[1]/Disconnect[0] the 50KOhm pull-up + // resistor on CS (pin 1) of the card. The pull-up may be used for card + // detection. + sd->bb_spi.outsr = 0xFF; // fill byte + sd->replyc = 2; + sd->reply[0] = sd->R1; + dprintf("sdcard set_clr_card_detect\n"); + break; + case ACMD51: // SEND_SCR - Reads the SD Configuration Register (SCR). + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = sd->R1; + sd->reply[1] = 0xFE; // start block + // SCR + sd->reply[2] = 0x02; // SCR_STRUCTURE:4 SD_SPEC :4 + sd->reply[3] = 0X25; // DATA_STAT_AFTER_ERASE:1 SD_SECURITY:3 SD_BUS_WIDTHS:4 + sd->reply[4] = 0x80; // reserved + sd->reply[5] = 0x00; // reserved + sd->reply[6] = 0x00; // reserved for manufacturer usage + sd->reply[7] = 0x00; // reserved for manufacturer usage + sd->reply[8] = 0x00; // reserved for manufacturer usage + sd->reply[9] = 0x00; // reserved for manufacturer usage + sd->reply[10] = 0x4c; // crc16 + sd->reply[11] = 0xd7; + sd->replyc = 13; + dprintf("sdcard send_scr\n"); + break; default: - sd->bb_spi.bit = 0; - sd->bb_spi.byte = 0; - printf("sdcard command not implemented!!!\n"); + // sd->bb_spi.bit = 0; + // sd->bb_spi.byte = 0; + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = + 0x04 | sd->R1; // R1 |0|ParameterE|AddressE|EraseE|CRCE|IllegalC|EraseR|idle| + sd->replyc = 2; + printf("sdcard command ACMD%d not implemented!!!\n", sd->cmd); break; } sd->ap_cmd = 0; @@ -200,14 +291,22 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un switch (sd->cmd) { case CMD0: // GO_IDLE_STATE - init card in spi mode if CS low sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x01; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->R1 = 1; + sd->reply[0] = sd->R1; sd->replyc = 2; + sd->cmd_count = 0; dprintf("sdcard soft reset \n"); break; + case CMD1: // SEND_OP_COND + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = sd->R1; + sd->replyc = 2; + dprintf("sdcard send op cond %li\n", sd->arg); + break; case CMD8: // SEND_IF_COND - verify SD Memory Card interface operating condition. sd->bb_spi.outsr = 0xFF; // fill byte sd->replyc = 6; - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->reply[1] = 0x00; sd->reply[2] = 0x00; sd->reply[3] = 0x01; // voltage @@ -216,7 +315,7 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un break; case CMD9: // SEND_CSD - read the Card Specific Data (CSD register) sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->reply[1] = 0xFE; // start block // CSDV2 sd->reply[2] = 0x40; // csd_ver:2 reserved1:6 @@ -238,13 +337,16 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un sd->reply[15] = 0x40; // write_bl_len_low:2 write_partial:1 reserved6:5 sd->reply[16] = 0x00; // file_format_grp:1 perm_write_protect:1 copy:1 // tmp_write_protect:1 file_format:2 reserved7:2 - sd->reply[18] = 0x01; // crc:7 always1:1 - sd->replyc = 20; + sd->reply[17] = (CRC7(&sd->reply[2], 15) << 1) | 1; // crc:7 always1:1 + crc16 = (CRC16(&sd->reply[2], 16)); + sd->reply[18] = crc16 >> 8; + sd->reply[19] = crc16 & 0xFF; + sd->replyc = 21; dprintf("sdcard send CSD\n"); break; case CMD10: // SEND_CID - read the card identification information (CID register) sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->reply[1] = 0xFE; // start block // CID sd->reply[2] = 0x01; // Manufacturer ID @@ -262,27 +364,36 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un sd->reply[14] = 0x78; // psn sd->reply[15] = 0x00; // reserved:4 mdt_year_high:4 sd->reply[16] = 0x04; // mdt_year_low:4 mdt_month:4 - sd->reply[18] = 0x01; // crc:7 always1:1 - sd->replyc = 20; + sd->reply[17] = 0x03; // crc:7 always1:1 + sd->reply[18] = 0xfb; // crc16 + sd->reply[19] = 0x8b; + sd->replyc = 21; dprintf("sdcard send CID \n"); break; case CMD12: // STOP_TRANSMISSION - end multiple block read sequence sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; - sd->multi = 0; + sd->multi_wr = 0; + sd->multi_rd = 0; dprintf("sdcard stop transmission\n"); break; case CMD13: // SEND_STATUS - read the card status register sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->reply[1] = 0x00; // R2 sd->replyc = 3; dprintf("sdcard send status\n"); break; + case CMD16: // SET_BLOCKLEN - Sets a block length (in bytes) for all + sd->bb_spi.outsr = 0xFF; // following block commands + sd->reply[0] = sd->R1; + sd->replyc = 2; + dprintf("sdcard set blocklen %lu\n", sd->arg); + break; case CMD17: // READ_SINGLE_BLOCK - read a single data block from the card sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->reply[1] = 0xFE; // start block sd->replyc = 3; sd->data_rc = 512; @@ -291,9 +402,21 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un fread(buff, 512, 1, sd->fd); dprintf("sdcard reading block %li\n", sd->arg / 512); break; + case CMD18: // READ_MULTIPLE_BLOCK - read a multiple data blocks from the card + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = sd->R1; + sd->reply[1] = 0xFE; // start block + sd->replyc = 3; + sd->data_rc = 512; + sd->multi_rd = 1; + + fseek(sd->fd, sd->arg /* 512*/, SEEK_SET); + fread(buff, 512, 1, sd->fd); + dprintf("sdcard reading multiple blocks start at %li\n", sd->arg / 512); + break; case CMD24: // WRITE_BLOCK - write a single data block to the card sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; sd->data_wc = 515; // include 0xFE initial token and crc fseek(sd->fd, sd->arg /* 512*/, SEEK_SET); @@ -301,16 +424,16 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un break; case CMD25: // WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; sd->data_wc = 515; // include 0xFC initial token and crc - sd->multi = 1; + sd->multi_wr = 1; fseek(sd->fd, sd->arg /* 512*/, SEEK_SET); dprintf("sdcard writing multiple blocks start at %li\n", sd->arg / 512); break; case CMD32: // ERASE_WR_BLK_START - sets the address of the first block to be erased sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; sd->ebstart = sd->arg / 512; dprintf("sdcard erase block start %li\n", sd->ebstart); @@ -318,14 +441,14 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un case CMD33: // ERASE_WR_BLK_END - sets the address of the last block of the continuous // range to be erased sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; sd->ebend = sd->arg / 512; dprintf("sdcard erase block end %li\n", sd->ebend); break; case CMD38: // ERASE - erase all previously selected blocks sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; dprintf("sdcard erasing blocks %li to %li\n", sd->ebstart, sd->ebend); fseek(sd->fd, sd->ebstart, SEEK_SET); @@ -336,7 +459,7 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un break; case CMD55: // APP_CMD - escape for application specific command sd->bb_spi.outsr = 0xFF; // fill byte - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; sd->replyc = 2; sd->ap_cmd = 1; dprintf("sdcard app command\n"); @@ -344,7 +467,7 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un case CMD58: // READ_OCR - read the OCR register of a card sd->bb_spi.outsr = 0xFF; // fill byte sd->replyc = 6; - sd->reply[0] = 0x00; // R1 |0|idle|EraseR|IllegalC|CRCE|EraseE|AddressE|ParameterE| + sd->reply[0] = sd->R1; if (sd->disk_size >= 4194304L) { sd->reply[1] = 0xC1; // Busy:1 CCS:1 resrved:5 S18A:1 } else { @@ -355,13 +478,25 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un sd->reply[4] = 0x00; // reseved:8 dprintf("sdcard read OCR \n"); break; + case CMD59: // CRC_ON_OFF - enable or disable CRC checking + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = sd->R1; + sd->replyc = 2; + sd->crc_on = sd->arg & 0x01; + dprintf("sdcard CRC ON/OFF = %i\n", sd->crc_on); + break; default: - sd->bb_spi.bit = 0; - sd->bb_spi.byte = 0; - printf("sdcard command not implemented!!!\n"); + // sd->bb_spi.bit = 0; + // sd->bb_spi.byte = 0; + sd->bb_spi.outsr = 0xFF; // fill byte + sd->reply[0] = + 0x04 | sd->R1; // R1 |0|ParameterE|AddressE|EraseE|CRCE|IllegalC|EraseR|idle| + sd->replyc = 2; + printf("sdcard command CMD%d not implemented!!!\n", sd->cmd); break; } } + dprintf("Reply[0] = 0x%02X\n", sd->reply[0]); break; default: // data offset = ((sd->bb_spi.byte << 3) - 48) / 8; @@ -384,8 +519,28 @@ unsigned short sdcard_io(sdcard_t* sd, unsigned char mosi, unsigned char clk, un if (sd->data_rc) { sd->bb_spi.outsr = (sd->bb_spi.outsr & 0xFF00) | buff[512 - sd->data_rc]; sd->data_rc--; + if (!sd->data_rc) { + unsigned short crc16 = 0xFFFF; + if (sd->crc_on) { + crc16 = CRC16(buff, 512); + } + sd->bb_spi.byte = 6; + sd->reply[0] = crc16 >> 8; + sd->reply[1] = crc16 & 0xFF; + sd->replyc = 3; + + if (sd->multi_rd) { + sd->reply[2] = 0xFF; + sd->reply[3] = 0xFE; // start block + sd->replyc = 5; + sd->data_rc = 512; + sd->arg += 512; + fread(buff, 512, 1, sd->fd); + dprintf("sdcard reading next block at %li\n", sd->arg / 512); + } + } } else { - sd->bb_spi.outsr = (sd->bb_spi.outsr & 0xFF00) | 0; // crc + sd->bb_spi.outsr = (sd->bb_spi.outsr & 0xFF00) | crc16; // crc sd->bb_spi.bit = 0; sd->bb_spi.byte = 0; } diff --git a/src/devices/sdcard.h b/src/devices/sdcard.h index 1c3945b9..f840938f 100644 --- a/src/devices/sdcard.h +++ b/src/devices/sdcard.h @@ -31,6 +31,7 @@ // SD card commands #define CMD0 0X00 +#define CMD1 0X01 // no spi #define CMD2 0X02 /** ALL_SEND_CID - Asks any card to send the CID. */ // no spi #define CMD3 0X03 /** SEND_RELATIVE_ADDR - Ask the card to publish a new RCA. */ // #define CMD6 0X06 /** SWITCH_FUNC - Switch Function Command */ @@ -40,8 +41,9 @@ #define CMD10 0X0A #define CMD12 0X0C #define CMD13 0X0D +#define CMD16 0X10 #define CMD17 0X11 -// #define CMD18 0X12 /** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */ +#define CMD18 0X12 #define CMD24 0X18 #define CMD25 0X19 #define CMD32 0X20 @@ -49,13 +51,15 @@ #define CMD38 0X26 #define CMD55 0X37 #define CMD58 0X3A -// #define CMD59 0X3B /** CRC_ON_OFF - enable or disable CRC checking */ +#define CMD59 0X3B // no spi #define ACMD6 0X06 /** SET_BUS_WIDTH - Defines the data bus width for data transfer. */ -// #define ACMD13 0X0D /** SD_STATUS - Send the SD Status. */ +#define ACMD13 0X0D #define ACMD23 0X17 #define ACMD41 0X29 +#define ACMD42 0X2A +#define ACMD51 0X33 -#define MAX_REPLY 20 +#define MAX_REPLY 72 typedef struct { FILE* fd; @@ -69,10 +73,14 @@ typedef struct { unsigned char ap_cmd; unsigned short data_rc; unsigned short data_wc; - unsigned char multi; + unsigned char multi_rd; + unsigned char multi_wr; unsigned long disk_size; // in kb unsigned long ebstart; unsigned long ebend; + unsigned char R1; + unsigned char crc_on; + unsigned int cmd_count; // used for boot } sdcard_t; void sdcard_rst(sdcard_t* sd);