More work on SD card interface

This commit is contained in:
meepingsnesroms
2018-11-20 16:32:54 -08:00
parent 59c5a1d4fb
commit ade71ae821
2 changed files with 80 additions and 36 deletions

View File

@@ -26,6 +26,7 @@ uint16_t spi1RxFifo[9];
uint16_t spi1TxFifo[9];
uint8_t spi1RxReadPosition;
uint8_t spi1RxWritePosition;
bool spi1RxOverflowed;//not in savestates yet!!!
uint8_t spi1TxReadPosition;
uint8_t spi1TxWritePosition;
int32_t pwm1ClocksToNextSample;
@@ -386,6 +387,12 @@ uint8_t getHwRegister8(uint32_t address){
debugLog("PWMCNT1 not implimented\n");
break;
//16 bit registers being read as 8 bit
case SPICONT1:
case SPICONT1 + 1:
case SPIINTCS:
case SPIINTCS + 1:
//basic non GPIO functions
case SCR:
case LCKCON:
@@ -464,10 +471,6 @@ uint16_t getHwRegister16(uint32_t address){
case PWMC1:
return getPwmc1();
case SPIINTCS:
debugLog("SPIINTCS read not implented yet\n");
return 0x0000;
case SPITEST:
//SSTATUS is unemulated because the datasheet has no descrption of how it works
return spi1RxFifoEntrys() << 4 | spi1TxFifoEntrys();
@@ -476,6 +479,8 @@ uint16_t getHwRegister16(uint32_t address){
return spi1RxFifoRead();
//32 bit registers accessed as 16 bit
case IDR:
case IDR + 2:
case IMR:
case IMR + 2:
case IPR:
@@ -508,6 +513,7 @@ uint16_t getHwRegister16(uint32_t address){
case TCTL1:
case TCTL2:
case SPICONT1:
case SPIINTCS:
case SPICONT2:
case SPIDATA2:
//simple read, no actions needed
@@ -786,8 +792,7 @@ void setHwRegister16(uint32_t address, uint16_t value){
break;
case ICR:
//missing bottom 7 bits
registerArrayWrite16(address, value & 0xFF80);
registerArrayWrite16(ICR, value & 0xFF80);
updateTouchState();
checkPortDInterrupts();//this calls checkInterrupts() so it doesnt need to be called above
break;
@@ -800,7 +805,7 @@ void setHwRegister16(uint32_t address, uint16_t value){
//somewhat unemulated
//missing bit 7 and 6
//debugLog("Set DRAMC, old value:0x%04X, new value:0x%04X, PC:0x%08X\n", registerArrayRead16(address), value, flx68000GetPc());
registerArrayWrite16(address, value & 0xFF3F);
registerArrayWrite16(DRAMC, value & 0xFF3F);
updateCsdAddressLines();//the EDO bit can disable SDRAM access
break;
@@ -812,7 +817,7 @@ void setHwRegister16(uint32_t address, uint16_t value){
case SDCTRL:
//missing bits 13, 9, 8 and 7
//debugLog("Set SDCTRL, old value:0x%04X, new value:0x%04X, PC:0x%08X\n", registerArrayRead16(address), value, flx68000GetPc());
registerArrayWrite16(address, value & 0xDC7F);
registerArrayWrite16(SDCTRL, value & 0xDC7F);
updateCsdAddressLines();
break;
@@ -918,7 +923,7 @@ void setHwRegister16(uint32_t address, uint16_t value){
break;
case SPIINTCS:
debugLog("SPIINTCS write not implented yet\n");
setSpiIntCs(value);
break;
case SPITEST:
@@ -927,6 +932,8 @@ void setHwRegister16(uint32_t address, uint16_t value){
case SPITXD:
spi1TxFifoWrite(value);
//check if SPI1 interrupt changed
setSpiIntCs(registerArrayRead16(SPIINTCS));
break;
case SPICONT2:

View File

@@ -18,9 +18,8 @@ static void registerArrayWrite8(uint32_t address, uint8_t value){BUFFER_WRITE_8(
static void registerArrayWrite16(uint32_t address, uint16_t value){BUFFER_WRITE_16(palmReg, address, 0xFFF, value);}
static void registerArrayWrite32(uint32_t address, uint32_t value){BUFFER_WRITE_32(palmReg, address, 0xFFF, value);}
//interrupt setters
//interrupt setters, used for setting an interrupt with masking by IMR and logging in IPR
static void setIprIsrBit(uint32_t interruptBit){
//allows for setting an interrupt with masking by IMR and logging in IPR
uint32_t newIpr = registerArrayRead32(IPR) | interruptBit;
registerArrayWrite32(IPR, newIpr);
registerArrayWrite32(ISR, newIpr & ~registerArrayRead32(IMR));
@@ -42,19 +41,24 @@ static uint8_t spi1RxFifoEntrys(void){
static uint16_t spi1RxFifoRead(void){
uint16_t value = spi1RxFifo[spi1RxReadPosition];
spi1RxReadPosition = (spi1RxReadPosition + 1) % 9;
if(spi1RxFifoEntrys() > 0)
spi1RxReadPosition = (spi1RxReadPosition + 1) % 9;
spi1RxOverflowed = false;
return value;
}
static void spi1RxFifoFlush(void){
spi1RxReadPosition = spi1RxWritePosition;
}
static void spi1RxFifoWrite(uint16_t value){
if(spi1RxFifoEntrys() < 8){
spi1RxWritePosition = (spi1RxWritePosition + 1) % 9;
spi1RxFifo[spi1RxWritePosition] = value;
}
else{
spi1RxOverflowed = true;
}
}
static void spi1RxFifoFlush(void){
spi1RxReadPosition = spi1RxWritePosition;
}
static uint8_t spi1TxFifoEntrys(void){
@@ -66,6 +70,7 @@ static uint8_t spi1TxFifoEntrys(void){
static uint16_t spi1TxFifoRead(void){
uint16_t value = spi1TxFifo[spi1TxReadPosition];
//dont need a safety check here, the emulator will always check that data is present before trying to access it
spi1TxReadPosition = (spi1TxReadPosition + 1) % 9;
return value;
}
@@ -318,11 +323,38 @@ static void setIlcr(uint16_t value){
registerArrayWrite16(ILCR, newIlcr);
}
static void setSpiIntCs(uint16_t value){
uint16_t oldSpiIntCs = registerArrayRead16(SPIINTCS);
uint16_t newSpiIntCs = value & 0xFF00;
uint8_t rxEntrys = spi1RxFifoEntrys();
uint8_t txEntrys = spi1TxFifoEntrys();
//newSpiIntCs |= spi1TxOverflowed << 7;//BO, slave mode not supported
newSpiIntCs |= spi1RxOverflowed << 6;//RO
newSpiIntCs |= (rxEntrys == 8) << 5;//RF
newSpiIntCs |= (rxEntrys >= 4) << 4;//RH
newSpiIntCs |= (rxEntrys > 0) << 3;//RR
newSpiIntCs |= (txEntrys == 8) << 2;//TF
newSpiIntCs |= (txEntrys >= 4) << 1;//TH
newSpiIntCs |= txEntrys == 0;//TE
//if interrupt state changed update interrupts too, top 8 bits are just the enable bits for the bottom 8
if(!!(newSpiIntCs >> 8 & newSpiIntCs) != !!(oldSpiIntCs >> 8 & oldSpiIntCs)){
if(newSpiIntCs >> 8 & newSpiIntCs)
setIprIsrBit(INT_SPI1);
else
clearIprIsrBit(INT_SPI1);
checkInterrupts();
}
registerArrayWrite16(SPIINTCS, newSpiIntCs);
}
static void setSpiCont1(uint16_t value){
//only master mode is implemented(even then only partially)!!!
uint16_t oldSpiCont1 = registerArrayRead16(SPICONT1);
debugLog("SPI1 write, old value:0x%04X, value:0x%04X\n", oldSpiCont1, value);
debugLog("SPICONT1 write, old value:0x%04X, value:0x%04X\n", oldSpiCont1, value);
//SPI1 disabled
if(oldSpiCont1 & 0x0200 && !(value & 0x2000)){
@@ -336,30 +368,35 @@ static void setSpiCont1(uint16_t value){
//do a transfer if enabled(this register write and last) and exchange set
if(value & oldSpiCont1 & 0x0200 && value & 0x0100){
uint16_t currentTxFifoEntry = spi1TxFifoRead();
uint16_t newRxFifoEntry = 0;
uint8_t bitCount = (value & 0x000F) + 1;
uint16_t startBit = 1 << (bitCount - 1);
uint8_t bits;
while(spi1TxFifoEntrys() > 0){
uint16_t currentTxFifoEntry = spi1TxFifoRead();
uint16_t newRxFifoEntry = 0x0000;
uint8_t bitCount = (value & 0x000F) + 1;
uint16_t startBit = 1 << (bitCount - 1);
uint8_t bits;
debugLog("SPI1 transfer, PC:0x%08X\n", flx68000GetPc());
debugLog("SPI1 transfer, PC:0x%08X\n", flx68000GetPc());
//The most significant bit is output when the CPU loads the transmitted data, 13.2.3 SPI 1 Phase and Polarity Configurations MC68VZ328UM.pdf
for(bits = 0; bits < bitCount; bits++){
newRxFifoEntry |= sdCardExchangeBit(!!(currentTxFifoEntry & startBit));
newRxFifoEntry <<= 1;
currentTxFifoEntry <<= 1;
//The most significant bit is output when the CPU loads the transmitted data, 13.2.3 SPI 1 Phase and Polarity Configurations MC68VZ328UM.pdf
for(bits = 0; bits < bitCount; bits++){
newRxFifoEntry |= sdCardExchangeBit(!!(currentTxFifoEntry & startBit));
newRxFifoEntry <<= 1;
currentTxFifoEntry <<= 1;
}
//add received data back to RX FIFO
spi1RxFifoWrite(newRxFifoEntry);
//overflow occured, remove 1 FIFO entry
//I do not currently know if the FIFO entry is removed from the back or front of the FIFO, going with the back for now
//if(spi1RxFifoEntrys() == 0)
// spi1RxFifoRead();
}
//since exact timing isnt implemented reads have to be done at the same time as writes
spi1RxFifoWrite(newRxFifoEntry);
//overflow occured, remove 1 FIFO entry
//I do not currently know if the FIFO entry is removed from the back or front of the FIFO, going with the back for now
//if(spi1RxFifoEntrys() == 0)
// spi1RxFifoRead();
}
//update SPIINTCS interrupt bits
setSpiIntCs(registerArrayRead16(SPIINTCS));
registerArrayWrite16(SPICONT1, value);
}