diff --git a/bugs/unimplementedHardware.txt b/bugs/unimplementedHardware.txt index d2859c5..163912d 100644 --- a/bugs/unimplementedHardware.txt +++ b/bugs/unimplementedHardware.txt @@ -11,7 +11,6 @@ Setting the battery dead bit(PDDATA 0x80) if the emulated battery percent gets t DRAMC write enable Port M Infrared shutdown (PMDATA 0x20) some undocumented I/O might be on port e and port j -SPI1(the SD card interface) SPITEST SSTATUS is undocumented and therefore unemulated When SPICLK2, SPITXD or SPIRXD on port e is disabled ADS7846 functions should respond appropriately(not transmitting or receiving or blocking both for the clock) REFREQ clock frequency in RTCCTL should slow down the RTC when enabled @@ -30,7 +29,6 @@ sound plays too long when the category's menu is selected on the home screen and ARM CPU state isn't saved Memory: -SD card can't be read or written to by Palm OS unknown if DRAM bit expanded address space is used for CSC when its not an extension of CSD there is conflicting information on whether the DRAM bit effects CSC, needs a test made the unemulated chip selects(CSB1, CSC0/1) privilege violation interrupts are not handled properly @@ -40,12 +38,16 @@ swivelview register ADS7846: verify chip select(no test has been done yet, but everything points to port g bit 2) -need to trigger a false PENIRQ interrupt on reading certain channels electrical noise on lines(conversions probably should have +-20 added to values)(probably no need for this, it works so theres no need to use less precise values) in the edge case that SPICLK2 is disabled while using ADS7846 and a 1 was the last bit shifted out 0s will still be shifted in need to to verify behavior of differential mode bit SD Card: +need to dump valid SCR +block length is fixed at 512 right now +data blocks won't work properly when CRC checks are enabled +the CRC of CSD and CID are invalid +SEND_SCR may not be sending in the proper format(the return data format was not specified in the spec I read) IRQ2 may actually be attached to the SD Card data out pin, triggering an interrupt when a 0 is received to process the return data need to test if Port J Pin 3(SD card chip select) is attached to Port D Pin 5(SD Card Status(IRQ2))(pinouts.ru says chip select and card detect are the same line) @@ -56,6 +58,9 @@ MakePalmBitmap: Fixed: +SPI1(the SD card interface)(SPI1 master mode seems fully implemented now) +SD card can't be read or written to by Palm OS(SPI transactions are going both ways now, some flash chip read commands are implemented too) +(ADS7846)need to trigger a false PENIRQ interrupt on reading certain channels(this is being done now) (MakePalmBitmap)the small icons are corrupt (MakePalmBitmap)the non 16 bpp large icons are corrupt need to test if Port J Pin 3(SD card chip select) is attached to Port D Pin 5(SD Card Status(IRQ2))(pinouts.ru says chip select and card detect are the same line)(IRQ2 doesnt change when SD card chip select is toggled regardless of wether the card is inserted) diff --git a/src/emulator.h b/src/emulator.h index 449d70a..eacdced 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -47,7 +47,9 @@ static void debugLog(char* str, ...){}; #define AUDIO_CLOCK_RATE 235929600//smallest amount of time a second can be split into:(2.0 * (14.0 * (255 + 1.0) + 15 + 1.0)) * 32768 == 235929600, used to convert the variable timing of SYSCLK and CLK32 to a fixed location in the current frame 0<->AUDIO_END_OF_FRAME #define AUDIO_SPEAKER_RANGE 0x6000//prevent hitting the top or bottom of the speaker when switching direction rapidly #define SD_CARD_RESPONSE_FIFO_SIZE 10000 -#define SD_CARD_NCR_BYTES 1 +#define SD_CARD_NCR_BYTES 1//how many 0xFF bytes come before the R1 response +#define SD_CARD_READ_DELAY_BYTES 1//how many 0xFF bytes come before the data packet +#define SD_CARD_WRITE_DELAY_BYTES 1 #define SAVE_STATE_VERSION 0 //system constants @@ -104,6 +106,8 @@ typedef struct{ typedef struct{ uint64_t command; uint8_t commandBitsRemaining; + uint8_t runningCommand;//not in savestates yet!! + uint64_t runningCommandState;//not in savestates yet!! uint8_t responseFifo[SD_CARD_RESPONSE_FIFO_SIZE];//not in savestates yet!! uint16_t responseReadPosition;//not in savestates yet!! int8_t responseReadPositionBit;//not in savestates yet!! diff --git a/src/sdCard.c b/src/sdCard.c index ea38f0f..8e217dd 100644 --- a/src/sdCard.c +++ b/src/sdCard.c @@ -6,6 +6,9 @@ #include "specs/sdCardCommandSpec.h" +#define SD_CARD_MAX_DATA_PACKET_SIZE (1 + 2048 + 2) + + static const uint8_t sdCardCrc7Table[256] = { 0x00,0x09,0x12,0x1B,0x24,0x2D,0x36,0x3F,0x48,0x41,0x5A,0x53,0x6C,0x65,0x7E,0x77, 0x19,0x10,0x0B,0x02,0x3D,0x34,0x2F,0x26,0x51,0x58,0x43,0x4A,0x75,0x7C,0x67,0x6E, @@ -28,7 +31,9 @@ static const uint8_t sdCardCrc7Table[256] = { //register data is from a "ULTRA SD HI-SPEED 1GB", thats actually the name of the card these IDs are from static const uint8_t sdCardCsd[16] = {0x00, 0x2F, 0x00, 0x32, 0x5F, 0x59, 0x83, 0xB8, 0x6D, 0xB7, 0xFF, 0x9F, 0x96, 0x40, 0x00, 0x00};//CRC7 is invalid here static const uint8_t sdCardCid[16] = {0x1D, 0x41, 0x44, 0x53, 0x44, 0x20, 0x20, 0x20, 0x10, 0xA0, 0x50, 0x33, 0xA4, 0x00, 0x81, 0x00};//CRC7 is invalid here -static const uint8_t sdCardScr[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};//need to dump this one +static const uint8_t sdCardScr[8] = {0x01, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};//dont know it this needs a CRC7 or not? +static const uint8_t sdCardDsr[2] = {0x04, 0x04}; +//static const uint8_t sdCardRca[2] = {0x??, 0x??};//not available in SPI mode static uint32_t sdCardGetOcr(void){ return palmSdCard.inIdleState << 31/*power up status*/ | 0 << 30/*card capacity status*/ | 0x01FF8000/*supported voltages*/; @@ -65,6 +70,8 @@ static bool sdCardCmdIsCrcValid(uint8_t command, uint32_t argument, uint8_t crc) void sdCardReset(void){ palmSdCard.command = UINT64_C(0x0000000000000000); palmSdCard.commandBitsRemaining = 48; + palmSdCard.runningCommand = 0x00; + palmSdCard.runningCommandState = UINT64_C(0x0000000000000000); memset(palmSdCard.responseFifo, 0x00, SD_CARD_RESPONSE_FIFO_SIZE); palmSdCard.responseReadPosition = 0; palmSdCard.responseWritePosition = 0; @@ -95,8 +102,31 @@ bool sdCardExchangeBit(bool bit){ //make sure SD is actually plugged in and chip select is low if(palmSdCard.flashChip.data && !palmSdCard.chipSelect){ + //get output value first outputValue = sdCardResponseFifoReadBit(); + //if running a continuous command check if it needs servicing + if(!palmSdCard.inIdleState){ + switch(palmSdCard.runningCommand){ + case READ_MULTIPLE_BLOCK: + if(sdCardResponseFifoByteEntrys() < palmSdCard.blockLength){ + //sdCardDoResponseDelay(1);//packets may have no delay in between + if(palmSdCard.runningCommandState * palmSdCard.blockLength < palmSdCard.flashChip.size){ + sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, palmSdCard.flashChip.data[palmSdCard.runningCommandState * palmSdCard.blockLength], palmSdCard.blockLength); + palmSdCard.runningCommandState++; + } + else{ + sdCardDoResponseErrorToken(ET_OUT_OF_RANGE); + palmSdCard.runningCommand = 0x00; + } + } + break; + + default: + break; + } + } + //route received bit as command or data if(palmSdCard.receivingCommand){ //receiving a command @@ -173,9 +203,16 @@ bool sdCardExchangeBit(bool bit){ break; case SET_BLOCKLEN: - if(!palmSdCard.inIdleState) - palmSdCard.blockLength = argument; - sdCardDoResponseR1(palmSdCard.inIdleState); + if(!palmSdCard.inIdleState){ + //eventually may want to support other block lengths + if(argument == 512) + sdCardDoResponseR1(palmSdCard.inIdleState); + else + sdCardDoResponseR1(PARAMETER_ERROR | palmSdCard.inIdleState); + } + else{ + sdCardDoResponseR1(palmSdCard.inIdleState); + } break; case APP_CMD: @@ -183,15 +220,14 @@ bool sdCardExchangeBit(bool bit){ sdCardDoResponseR1(palmSdCard.inIdleState); break; - case READ_SINGLE_BLOCK: + case STOP_TRANSMISSION: if(!palmSdCard.inIdleState){ - if(argument * palmSdCard.blockLength < palmSdCard.flashChip.size){ - sdCardDoResponseR1(palmSdCard.inIdleState); + if(palmSdCard.runningCommand == READ_MULTIPLE_BLOCK){ + palmSdCard.runningCommand = 0x00; + sdCardResponseFifoFlush(); sdCardDoResponseDelay(1); - sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, palmSdCard.flashChip.data[argument * palmSdCard.blockLength], palmSdCard.blockLength); - } - else{ - sdCardDoResponseR1(ADDRESS_ERROR | palmSdCard.inIdleState); + sdCardDoResponseR1(palmSdCard.inIdleState); + sdCardDoResponseBusy(1); } } else{ @@ -199,6 +235,32 @@ bool sdCardExchangeBit(bool bit){ } break; + case READ_SINGLE_BLOCK: + sdCardDoResponseR1(palmSdCard.inIdleState); + if(!palmSdCard.inIdleState){ + sdCardDoResponseDelay(1); + if(argument * palmSdCard.blockLength < palmSdCard.flashChip.size) + sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, palmSdCard.flashChip.data[argument * palmSdCard.blockLength], palmSdCard.blockLength); + else + sdCardDoResponseErrorToken(ET_OUT_OF_RANGE); + } + break; + + case READ_MULTIPLE_BLOCK: + sdCardDoResponseR1(palmSdCard.inIdleState); + if(!palmSdCard.inIdleState){ + sdCardDoResponseDelay(1); + if(argument * palmSdCard.blockLength < palmSdCard.flashChip.size){ + sdCardDoResponseDataPacket(DATA_TOKEN_DEFAULT, palmSdCard.flashChip.data[argument * palmSdCard.blockLength], palmSdCard.blockLength); + palmSdCard.runningCommand = READ_MULTIPLE_BLOCK; + palmSdCard.runningCommandState = argument + 1; + } + else{ + sdCardDoResponseErrorToken(ET_OUT_OF_RANGE); + } + } + break; + default: debugLog("SD unknown command: cmd:%d, arg:0x%08X, CRC:0x%02X\n", command, argument, crc); sdCardDoResponseR1(ILLEGAL_COMMAND | palmSdCard.inIdleState); diff --git a/src/sdCardAccessors.c.h b/src/sdCardAccessors.c.h index 4ed72dd..ea05e44 100644 --- a/src/sdCardAccessors.c.h +++ b/src/sdCardAccessors.c.h @@ -68,8 +68,18 @@ static void sdCardDoResponseDataPacket(uint8_t token, uint8_t* location, uint16_ sdCardResponseFifoWriteByte(crc16 & 0xFF); } +static void sdCardDoResponseErrorToken(uint8_t token){ + sdCardResponseFifoWriteByte(token); +} + static void sdCardDoResponseDelay(uint16_t bytes){ uint16_t index; for(index = 0; index < bytes; index++) sdCardResponseFifoWriteByte(0xFF); } + +static void sdCardDoResponseBusy(uint16_t bytes){ + uint16_t index; + for(index = 0; index < bytes; index++) + sdCardResponseFifoWriteByte(0x00); +} diff --git a/src/specs/sdCardCommandSpec.h b/src/specs/sdCardCommandSpec.h index 749b7b5..9e3f154 100644 --- a/src/specs/sdCardCommandSpec.h +++ b/src/specs/sdCardCommandSpec.h @@ -34,6 +34,13 @@ #define ADDRESS_ERROR 0x20 #define PARAMETER_ERROR 0x40 +/*Error Token Bits*/ +#define ET_ERROR 0x01 +#define ET_CC_ERROR 0x02 +#define ET_CARD_ECC_FAILED 0x04 +#define ET_OUT_OF_RANGE 0x08 +#define ET_CARD_IS_LOCKED 0x10 + /*Data Transfer Tokens*/ #define DATA_TOKEN_DEFAULT 0xFE #define DATA_TOKEN_CMD25 0xFC