mirror of
https://github.com/libretro/Mu.git
synced 2026-09-23 07:05:37 +00:00
More work on SD card interface
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user