ADS7846 chip select now resets ADS7846

And the long saga of glitchy touchscreen issues and failed solutions finally comes to an and, now to the far more complicated SPI protocol, an entire SD card.
This commit is contained in:
meepingsnesroms
2018-09-20 10:30:09 -07:00
parent 559a7b5818
commit 803cd95c5a
7 changed files with 44 additions and 30 deletions

View File

@@ -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();

View File

@@ -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){

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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))){

View File

@@ -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)