diff --git a/hwTestSuite/tools.c b/hwTestSuite/tools.c index 8db5084..46aa3d1 100644 --- a/hwTestSuite/tools.c +++ b/hwTestSuite/tools.c @@ -56,7 +56,6 @@ Err makeFile(uint8_t* data, uint32_t size, char* fileName){ uint16_t ads7846GetValue(uint8_t channel, Boolean referenceMode, Boolean mode8Bit){ uint8_t config = 0x80; uint16_t value; - volatile uint32_t wasteTime; if(mode8Bit) config |= 0x08; @@ -73,7 +72,7 @@ uint16_t ads7846GetValue(uint8_t channel, Boolean referenceMode, Boolean mode8Bi turnInterruptsOff(); - /*misc configs from HwrADC, ADS7846 dosent work without these*/ + /*ADS7846 chip select and SPI2 CLK,DIN,DOUT*/ writeArbitraryMemory8(HW_REG_ADDR(PGDATA), readArbitraryMemory8(HW_REG_ADDR(PGDATA)) & 0xFB); writeArbitraryMemory8(HW_REG_ADDR(PEDIR), readArbitraryMemory8(HW_REG_ADDR(PEDIR)) | 0x01); writeArbitraryMemory8(HW_REG_ADDR(PEDATA), readArbitraryMemory8(HW_REG_ADDR(PEDATA)) & 0xFE); @@ -87,11 +86,6 @@ uint16_t ads7846GetValue(uint8_t channel, Boolean referenceMode, Boolean mode8Bi writeArbitraryMemory16(HW_REG_ADDR(SPICONT2), 0x4304); while(readArbitraryMemory16(HW_REG_ADDR(SPICONT2)) & 0x0100); - /*wait for the conversion to settle*/ - wasteTime = 0; - while(wasteTime < 100) - wasteTime++; - /*send last 3 bits, wait 1 bit, get 8/12 bit result then pad the transfer to 16 bits*/ writeArbitraryMemory16(HW_REG_ADDR(SPIDATA2), config << 14); writeArbitraryMemory16(HW_REG_ADDR(SPICONT2), 0x430F); @@ -103,7 +97,7 @@ uint16_t ads7846GetValue(uint8_t channel, Boolean referenceMode, Boolean mode8Bi /*disable SPI2*/ writeArbitraryMemory16(HW_REG_ADDR(SPICONT2), 0xE000); - /*misc configs from HwrADC, ADS7846 dosent work without this*/ + /*ADS7846 chip select*/ writeArbitraryMemory8(HW_REG_ADDR(PGDATA), readArbitraryMemory8(HW_REG_ADDR(PGDATA)) | 0x04); turnInterruptsOn(); diff --git a/src/ads7846.c b/src/ads7846.c index 53471cd..f10ccef 100644 --- a/src/ads7846.c +++ b/src/ads7846.c @@ -11,6 +11,7 @@ static const uint16_t ads7846DockResistorValues[PORT_END] = {0xFFF/*none*/, 0x1E static uint8_t ads7846BitsToNextControl;//bits before starting a new control byte static uint8_t ads7846ControlByte; static uint16_t ads7846OutputValue; +static bool ads7846ChipSelect; static inline double ads7846RangeMap(double oldMin, double oldMax, double value, double newMin, double newMax){ @@ -31,12 +32,13 @@ void ads7846Reset(){ ads7846ControlByte = 0x00; ads7846PenIrqEnabled = true; ads7846OutputValue = 0x0000; + ads7846ChipSelect = false; } uint64_t ads7846StateSize(){ uint64_t size = 0; - size += sizeof(uint8_t) * 3; + size += sizeof(uint8_t) * 4; size += sizeof(uint16_t); return size; @@ -45,27 +47,41 @@ uint64_t ads7846StateSize(){ void ads7846SaveState(uint8_t* data){ uint64_t offset = 0; + writeStateValueBool(data + offset, ads7846PenIrqEnabled); + offset += sizeof(uint8_t); writeStateValueUint8(data + offset, ads7846BitsToNextControl); offset += sizeof(uint8_t); writeStateValueUint8(data + offset, ads7846ControlByte); offset += sizeof(uint8_t); - writeStateValueBool(data + offset, ads7846PenIrqEnabled); - offset += sizeof(uint8_t); writeStateValueUint16(data + offset, ads7846OutputValue); offset += sizeof(uint16_t); + writeStateValueBool(data + offset, ads7846ChipSelect); + offset += sizeof(uint8_t); } void ads7846LoadState(uint8_t* data){ uint64_t offset = 0; + ads7846PenIrqEnabled = readStateValueBool(data + offset); + offset += sizeof(uint8_t); ads7846BitsToNextControl = readStateValueUint8(data + offset); offset += sizeof(uint8_t); ads7846ControlByte = readStateValueUint8(data + offset); offset += sizeof(uint8_t); - ads7846PenIrqEnabled = readStateValueBool(data + offset); - offset += sizeof(uint8_t); ads7846OutputValue = readStateValueUint16(data + offset); offset += sizeof(uint16_t); + ads7846ChipSelect = readStateValueBool(data + offset); + offset += sizeof(uint8_t); +} + +void ads7846SetChipSelect(bool value){ + //reset the chip when disabled, chip is active when chip select is low + if(value && !ads7846ChipSelect){ + ads7846BitsToNextControl = 0; + ads7846ControlByte = 0x00; + ads7846PenIrqEnabled = true; + ads7846OutputValue = 0x0000; + } } bool ads7846ExchangeBit(bool bitIn){ diff --git a/src/ads7846.h b/src/ads7846.h index 815b25f..682d0fd 100644 --- a/src/ads7846.h +++ b/src/ads7846.h @@ -10,5 +10,6 @@ uint64_t ads7846StateSize(); void ads7846SaveState(uint8_t* data); void ads7846LoadState(uint8_t* data); +void ads7846SetChipSelect(bool value); bool ads7846ExchangeBit(bool bitIn); bool ads7846Busy(); diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index d6a846b..952533c 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -657,9 +657,9 @@ void setHwRegister8(uint32_t address, uint8_t value){ case PGSEL: case PGDIR: case PGDATA: - //port g also does SPI stuff, unemulated so far //write without the top 2 bits registerArrayWrite8(address, value & 0x3F); + updateAds7846ChipSelectStatus(); break; case PKSEL: @@ -924,7 +924,7 @@ void setHwRegister16(uint32_t address, uint16_t value){ case CSUGBA: if((value & 0xF777) != registerArrayRead16(CSUGBA)){ registerArrayWrite16(CSUGBA, value & 0xF777); - //refresh all chipselect address lines + //refresh all chip select address lines setCsgba(registerArrayRead16(CSGBA)); setCsgbb(registerArrayRead16(CSGBB)); setCsgbd(registerArrayRead16(CSGBD)); @@ -938,7 +938,7 @@ void setHwRegister16(uint32_t address, uint16_t value){ registerArrayWrite16(CSCTRL1, value & 0x7F55); if((value & 0x4055) != (oldCsctrl1 & 0x4055)){ - //something important changed, update all chipselects + //something important changed, update all chip selects //CSA is not dependent on CSCTRL1 setCsb(registerArrayRead16(CSB)); setCsd(registerArrayRead16(CSD)); @@ -1070,7 +1070,7 @@ void resetHwRegisters(){ spi1TxWritePosition = 0; memset(chips, 0x00, sizeof(chips)); - //all chipselects are disabled at boot and CSA0 is mapped to 0x00000000 and covers the entire address range until CSA is set enabled + //all chip selects are disabled at boot and CSA0 is mapped to 0x00000000 and covers the entire address range until CSA is set enabled chips[CHIP_A0_ROM].inBootMode = true; //default sizes @@ -1184,9 +1184,11 @@ void resetHwRegisters(){ //SDRAM control, unused since RAM refresh is unemulated registerArrayWrite16(SDCTRL, 0x003C); - //add register settings to misc I/O + //move register settings to other I/O updatePowerButtonLedStatus(); updateVibratorStatus(); + updateAds7846ChipSelectStatus(); + updateBacklightAmplifierStatus(); recalculateCpuSpeed(); } diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 590e2ad..395a64d 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -74,7 +74,7 @@ static inline void setCsa(uint16_t value){ chips[CHIP_A0_ROM].readOnly = value & 0x8000; chips[CHIP_A0_ROM].lineSize = 0x20000/*128kb*/ << (value >> 1 & 0x0007); - //CSA is now just a normal chipselect + //CSA is now just a normal chip select if(chips[CHIP_A0_ROM].enable && chips[CHIP_A0_ROM].inBootMode) chips[CHIP_A0_ROM].inBootMode = false; @@ -298,10 +298,6 @@ static inline void setSpiCont2(uint16_t value){ else clearIprIsrBit(INT_SPI2); - //this fixes all ADS7846 communication problems, maybe the power to the ADS7846 is cut when the transfer is over? - if(value & 0x0200 && !(oldSpiCont2 & 0x0200)) - ads7846Reset(); - //do a transfer if(value & oldSpiCont2 & 0x0200 && value & 0x0100){ //enabled and exchange set @@ -571,6 +567,10 @@ static inline void updateVibratorStatus(){ palmMisc.vibratorOn = getPortKValue() & 0x10; } +static inline void updateAds7846ChipSelectStatus(){ + ads7846SetChipSelect(getPortGValue() & 0x04); +} + static inline void updateBacklightAmplifierStatus(){ palmMisc.backlightLevel = (palmMisc.backlightLevel > 0) ? (1 + backlightAmplifierState()) : 0; } diff --git a/src/memoryAccess.c b/src/memoryAccess.c index 9dd2c95..0431e95 100644 --- a/src/memoryAccess.c +++ b/src/memoryAccess.c @@ -330,7 +330,7 @@ uint32_t m68k_read_disassembler_32(uint32_t address){return m68k_read_memory_32( static uint8_t getProperBankType(uint32_t bank){ if(BANK_IN_RANGE(bank, REG_START_ADDRESS, REG_SIZE) || ((bank & 0x00FF) == 0x00FF && registersAreXXFFMapped())){ - //registers have first priority, they cover 0xFFFFF000(and 0xXXFFF000 when DMAP enabled in SCR) even if a chipselect overlaps this area or CHIP_A0_ROM is in boot mode + //registers have first priority, they cover 0xFFFFF000(and 0xXXFFF000 when DMAP enabled in SCR) even if a chip select overlaps this area or CHIP_A0_ROM is in boot mode return CHIP_REGISTERS; } else if(chips[CHIP_A0_ROM].inBootMode || (chips[CHIP_A0_ROM].enable && BANK_IN_RANGE(bank, chips[CHIP_A0_ROM].start, chips[CHIP_A0_ROM].lineSize))){ diff --git a/unimplementedHardware.txt b/unimplementedHardware.txt index ac51b17..f732f9b 100644 --- a/unimplementedHardware.txt +++ b/unimplementedHardware.txt @@ -6,10 +6,8 @@ On hardware PDIRQEG seems not to actually work at all(CPUID:0x57000000) CPU I/O: Peripheral Control Register, audio ppm mixing selection and timer cascade mode -Port G SPI stuff Setting the battery dead bit(PDDATA 0x80) if the emulated battery percent gets too low(don't know how low this is, a test will be slow and painful with how big the battery is on my device) DRAMC write enable -pen input Port M Infrared shutdown (PMDATA 0x20) some undocumented I/O might be on port e and port j if a timer triggers more than once per CLK32(> 32768 times a second) it will lose any triggers after the first and get out of sync @@ -17,7 +15,6 @@ SPI1, probably the SD card since SD cards use SPI for data transfer SPITEST SSTATUS is undocumented and therefore unemulated may need to trigger an interrupt if a IMR masked interrupt becomes unmasked and its bit is still set in IPR 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) -port g data bit 2 may need to be 0 to access ADS7846 REFREQ clock frequency in RTCCTL should slow down the RTC when enabled Dont know if it possible to have the backlight on and the display off at the same time(theres no reason for it but it may be possible) SPI1 slave mode, should never be used @@ -42,14 +39,18 @@ SED1376: swivelview register ADS7846: -the ADS7846 is currently being reset every time the SPI is disabled and reenabled(I don't know if this actually occurs or this is just a hack that works really well) -verify chip select +verify chip select(no test has been done yet, put 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) -pulling chip select low when high state likely resets the ADS7846 bit stream(this is currently being done when the SPI bus is enabled) Fixed: +port g data bit 2 may need to be 0 to access ADS7846(it is) +pen input +pulling chip select low when high state likely resets the ADS7846 bit stream(this is currently being done when the SPI bus is enabled)(resetting on disable, that would make more sense because the chip needs to be read/written instantly once chip select is pulled low) +From ADS7846 datasheet:Chip Select Input. Controls conversion timing and enables the serial input/output register. (this means the chip timing is likely reset when cs goes low) +the ADS7846 is currently being reset every time the SPI is disabled and reenabled(happens when ADS7846 chip select is turned off, not on SPI enable) +Port G SPI stuff(ADS7846 chip select was on port g) Edge triggered IRQ* interrupt pins may actually read the value of the interrupt instead of the pin value(IRQ* reads the pin, INT* still hasn't been tested yet) ADS7846 channels are not implemented properly in the emulator(works now) ADS7846 Channels 3 and 4(they need to be scaled differently)(works now)