diff --git a/readme.txt b/readme.txt index 8236382..0931201 100644 --- a/readme.txt +++ b/readme.txt @@ -43,7 +43,7 @@ Performance As currently implemented: -Sequential read: 930kb/sec Sequential write: 414kb/sec +Sequential read: 930kb/sec Sequential write: 900kb/sec Tested with a 16GB class 10 SD card, via the commands: diff --git a/software/SCSI2SD/SCSI2SD.cydsn/disk.c b/software/SCSI2SD/SCSI2SD.cydsn/disk.c index 427112c..20de53b 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/disk.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/disk.c @@ -117,7 +117,7 @@ static void doWrite(uint32 lba, uint32 blocks) transfer.currentBlock = 0; scsiDev.phase = DATA_OUT; scsiDev.dataLen = SCSI_BLOCK_SIZE; - + scsiDev.dataPtr = SCSI_BLOCK_SIZE; // TODO FIX scsiDiskPoll() sdPrepareWrite(); } } @@ -370,21 +370,19 @@ void scsiDiskPoll() else if (scsiDev.phase == DATA_OUT && transfer.currentBlock != transfer.blocks) { - if (scsiDev.dataPtr == SCSI_BLOCK_SIZE) + int writeOk = sdWriteSector(); + // TODO FIX scsiDiskPoll() scsiDev.dataPtr = 0; + transfer.currentBlock++; + if (transfer.currentBlock >= transfer.blocks) { - int writeOk = sdWriteSector(); + scsiDev.dataLen = 0; scsiDev.dataPtr = 0; - transfer.currentBlock++; - if (transfer.currentBlock >= transfer.blocks) - { - scsiDev.dataLen = 0; - scsiDev.phase = STATUS; - scsiDiskReset(); + scsiDev.phase = STATUS; + scsiDiskReset(); - if (writeOk) - { - sdCompleteWrite(); - } + if (writeOk) + { + sdCompleteWrite(); } } } diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.c b/software/SCSI2SD/SCSI2SD.cydsn/sd.c index 21a8ecc..a35ea6e 100755 --- a/software/SCSI2SD/SCSI2SD.cydsn/sd.c +++ b/software/SCSI2SD/SCSI2SD.cydsn/sd.c @@ -284,22 +284,61 @@ static void sdWaitWriteBusy() int sdWriteSector() { - int result, i, maxWait; + int prep, i, guard; + int result, maxWait; uint8 dataToken; + + // Don't do a bus settle delay if we're already in the correct phase. + if (transfer.currentBlock == 0) + { + scsiEnterPhase(DATA_OUT); + } // Wait for a previously-written sector to complete. sdWaitWriteBusy(); - sdSpiByte(0xFC); // MULTIPLE byte start token - for (i = 0; i < SCSI_BLOCK_SIZE; i++) - { - while(!(SDCard_ReadTxStatus() & SDCard_STS_TX_FIFO_NOT_FULL)) - {} - SDCard_WriteTxData(scsiDev.data[i]); - } - while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE)) {} - SDCard_ClearFIFO(); + + prep = 0; + i = 0; + guard = 0; + // This loop is critically important for performance. + // We stream data straight from the SCSI fifos into the SPIM component + // FIFO's. If the loop isn't fast enough, the transmit FIFO's will empty, + // and performance will suffer. Every clock cycle counts. + while (i < SCSI_BLOCK_SIZE) + { + uint8_t sdRxStatus = CY_GET_REG8(SDCard_RX_STATUS_PTR); + uint8_t scsiStatus = CY_GET_REG8(scsiTarget_StatusReg__STATUS_REG); + + // Read from the SCSI fifo if there is room to stream the byte to the + // SPIM fifos + // See sdReadSector for comment on guard (FIFO size is really 5) + if((guard - i < 4) && + (scsiStatus & 2)) // SCSI RX FIFO NOT EMPTY + { + uint8_t val = CY_GET_REG8(scsiTarget_datapath__F1_REG); + CY_SET_REG8(SDCard_TXDATA_PTR, val); + guard++; + } + + // Byte has been sent out the SPIM interface. + if (sdRxStatus & SDCard_STS_RX_FIFO_NOT_EMPTY) + { + CY_GET_REG8(SDCard_RXDATA_PTR); + ++i; + } + + if (prep < SCSI_BLOCK_SIZE && + (scsiStatus & 1) // SCSI TX FIFO NOT FULL + ) + { + // Trigger the SCSI component to read a byte + CY_SET_REG8(scsiTarget_datapath__F0_REG, 0xFF); + prep++; + } + } + sdSpiByte(0x00); // CRC sdSpiByte(0x00); // CRC