From ade71ae821d1bae16559d2ac7cc29a730b5eaac1 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Tue, 20 Nov 2018 16:32:54 -0800 Subject: [PATCH] More work on SD card interface --- src/hardwareRegisters.c | 25 +++++--- src/hardwareRegistersAccessors.c.h | 91 +++++++++++++++++++++--------- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index f1fe48c..f056397 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -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: diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index f7c02b8..94dabce 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -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); }