Doesnt get as far anymore but is more accurate

This commit is contained in:
meepingsnesroms
2019-08-27 17:54:32 -07:00
parent e277ae8a3b
commit 12ed98e68b
6 changed files with 334 additions and 313 deletions

View File

@@ -96,7 +96,7 @@ void pxa260I2cWriteWord(uint32_t address, uint32_t value){
}
pxa260I2cUnitBusy = true;
pxa260TimingQueueEvent(PXA260_I2C_TRANSFER_DURATION, PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL);
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL, PXA260_I2C_TRANSFER_DURATION);
}
else{
//send
@@ -108,7 +108,7 @@ void pxa260I2cWriteWord(uint32_t address, uint32_t value){
tps65010I2cExchange((pxa260I2cBuffer & 1 << 7 - index) ? I2C_1 : I2C_0);
pxa260I2cUnitBusy = true;
pxa260TimingQueueEvent(PXA260_I2C_TRANSFER_DURATION, PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY);
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY, PXA260_I2C_TRANSFER_DURATION);
}
}
if(value & 0x0002){

View File

@@ -209,7 +209,7 @@ void pxa260SspWriteWord(uint32_t address, uint32_t value){
pxa260SspTxFifoWrite(value);
if(!pxa260SspTransfering){
pxa260SspTransfering = true;
pxa260TimingQueueEvent(PXA260_SSP_TRANSFER_DURATION, PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE);
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE, PXA260_SSP_TRANSFER_DURATION);
}
pxa260SspUpdateInterrupt();
return;
@@ -245,7 +245,7 @@ void pxa260SspTransferComplete(void){
//if still transmitting, need to enqueue next event
if(pxa260SspTxFifoEntrys() > 0)
pxa260TimingQueueEvent(PXA260_SSP_TRANSFER_DURATION, PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE);
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE, PXA260_SSP_TRANSFER_DURATION);
else
pxa260SspTransfering = false;

View File

@@ -2,6 +2,7 @@
#include <string.h>
#include <setjmp.h>
#include "../tsc2101.h"
#include "../armv5te/os/os.h"
#include "../armv5te/emu.h"
#include "../armv5te/cpu.h"
@@ -10,18 +11,21 @@
#include "pxa260Timing.h"
static int32_t pxa260TimingLeftoverCycles;
#define PXA260_TIMING_NEVER 0xFFFFFFFF
void (*pxa260TimingCallbacks[PXA260_TIMING_TOTAL_CALLBACKS])(void);
event_t pxa260TimingQueuedEvents[20];
static int32_t pxa260TimingLeftoverCycles;//doesnt need to go in save states
void (*pxa260TimingCallbacks[PXA260_TIMING_TOTAL_CALLBACKS])(void);
int32_t pxa260TimingQueuedEvents[PXA260_TIMING_TOTAL_CALLBACKS];
static int32_t pxa260TimingGetDurationUntilNextEvent(int32_t duration/*call with how long you want to run*/){
uint8_t index;
for(index = 0; index < sizeof(pxa260TimingQueuedEvents) / sizeof(event_t); index++)
if(pxa260TimingQueuedEvents[index].active && pxa260TimingQueuedEvents[index].wait < duration)
duration = pxa260TimingQueuedEvents[index].wait;
for(index = 0; index < PXA260_TIMING_TOTAL_CALLBACKS; index++)
if(pxa260TimingQueuedEvents[index] != PXA260_TIMING_NEVER && pxa260TimingQueuedEvents[index] < duration)
duration = pxa260TimingQueuedEvents[index];
return duration;
}
@@ -30,30 +34,27 @@ void pxa260TimingInit(void){
pxa260TimingCallbacks[PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY] = pxa260I2cTransmitEmpty;
pxa260TimingCallbacks[PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL] = pxa260I2cReceiveFull;
pxa260TimingCallbacks[PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE] = pxa260SspTransferComplete;
pxa260TimingCallbacks[PXA260_TIMING_CALLBACK_TSC2101_SCAN] = tsc2101Scan;
}
void pxa260TimingReset(void){
memset(pxa260TimingQueuedEvents, 0x00, sizeof(pxa260TimingQueuedEvents));
}
void pxa260TimingQueueEvent(int32_t wait, uint8_t callbackId){
uint8_t index;
for(index = 0; index < sizeof(pxa260TimingQueuedEvents) / sizeof(event_t); index++){
if(!pxa260TimingQueuedEvents[index].active){
//found empty slot, enqueue event
pxa260TimingQueuedEvents[index].wait = wait;
pxa260TimingQueuedEvents[index].callbackId = callbackId;
pxa260TimingQueuedEvents[index].active = true;
if(wait < -cycle_count_delta){
pxa260TimingLeftoverCycles = -cycle_count_delta - wait;
cycle_count_delta = -wait;
}
return;
}
}
for(index = 0; index < PXA260_TIMING_TOTAL_CALLBACKS; index++)
pxa260TimingQueuedEvents[index] = PXA260_TIMING_NEVER;
}
debugLog("Unable to find CPU event slot!!!");
void pxa260TimingTriggerEvent(uint8_t callbackId, int32_t wait){
pxa260TimingQueuedEvents[callbackId] = wait;
//dont need to check if in handler since cycle_count_delta is 0 or positive when in handlers are called
if(wait < -cycle_count_delta){
pxa260TimingLeftoverCycles = -cycle_count_delta - wait;
cycle_count_delta = -wait;
}
}
void pxa260TimingCancelEvent(uint8_t callbackId){
pxa260TimingQueuedEvents[callbackId] = PXA260_TIMING_NEVER;
}
void pxa260TimingRun(int32_t cycles){
@@ -104,13 +105,13 @@ void pxa260TimingRun(int32_t cycles){
addCycles -= pxa260TimingLeftoverCycles;
pxa260TimingLeftoverCycles = 0;
for(index = 0; index < sizeof(pxa260TimingQueuedEvents) / sizeof(event_t); index++){
if(pxa260TimingQueuedEvents[index].active){
pxa260TimingQueuedEvents[index].wait -= addCycles;
if(pxa260TimingQueuedEvents[index].wait <= 0){
for(index = 0; index < PXA260_TIMING_TOTAL_CALLBACKS; index++){
if(pxa260TimingQueuedEvents[index] != PXA260_TIMING_NEVER){
pxa260TimingQueuedEvents[index] -= addCycles;
if(pxa260TimingQueuedEvents[index] <= 0){
//execute event
pxa260TimingCallbacks[pxa260TimingQueuedEvents[index].callbackId]();
pxa260TimingQueuedEvents[index].active = false;
pxa260TimingQueuedEvents[index] = PXA260_TIMING_NEVER;//set to never before calling function because it may retrigger the event and we dont want the new one cleared
pxa260TimingCallbacks[index]();
}
}
}

View File

@@ -7,22 +7,18 @@ enum{
PXA260_TIMING_CALLBACK_I2C_TRANSMIT_EMPTY = 0,
PXA260_TIMING_CALLBACK_I2C_RECEIVE_FULL,
PXA260_TIMING_CALLBACK_SSP_TRANSFER_COMPLETE,
PXA260_TIMING_CALLBACK_TSC2101_SCAN,
PXA260_TIMING_TOTAL_CALLBACKS
};
typedef struct{
int32_t wait;
uint8_t callbackId;
bool active;
}event_t;
extern void (*pxa260TimingCallbacks[])(void);//saving a function pointer in a state is not portable and will crash even on the same system between program loads with ASLR
extern event_t pxa260TimingQueuedEvents[];
extern int32_t pxa260TimingQueuedEvents[];
void pxa260TimingInit(void);
void pxa260TimingReset(void);
void pxa260TimingQueueEvent(int32_t wait, uint8_t callbackId);
void pxa260TimingTriggerEvent(uint8_t callbackId, int32_t wait);
void pxa260TimingCancelEvent(uint8_t callbackId);
void pxa260TimingRun(int32_t cycles);//this runs the CPU
#endif

View File

@@ -3,6 +3,7 @@
#include <string.h>
#include "emulator.h"
#include "pxa260/pxa260Timing.h"
#include "tsc2101.h"
@@ -11,7 +12,7 @@
//TODO: single shot/continuos modes
//TODO: HCTLM is wrong
#define TSC2101_SCAN_DURATION 10000//in PXA260 opcodes//TODO: this may need to be calculated based on the timing params in the registers
#define TSC2101_REG_LOCATION(page, address) ((page) << 6 | (address))
enum{
@@ -173,7 +174,288 @@ static uint16_t tsc2101GetTemp2Value(void){
return 0x777 & tsc2101GetAnalogMask();
}
static void tsc2101Scan(void){
static void tsc2101ResetRegisters(void){
tsc2101HasNewData = 0x0000;
memset(tsc2101Registers, 0x00, sizeof(tsc2101Registers));
//TODO: need to add all the registers here
tsc2101Registers[TOUCH_CONTROL_STATUS] = 0x8000;
tsc2101Registers[TOUCH_CONTROL_REFERENCE] = 0x0002;
//currenly at register 0x5 of touch control
tsc2101RefreshInterrupt();
}
static uint16_t tsc2101RegisterRead(uint8_t page, uint8_t address){
uint8_t combinedRegisterNumber = TSC2101_REG_LOCATION(page, address);
switch(combinedRegisterNumber){
case TOUCH_CONTROL_TSC_ADC:
return tsc2101Registers[TOUCH_CONTROL_TSC_ADC] & 0x3FFF | palmInput.touchscreenTouched << 15 | 1 << 14/*TODO: this states the ADC is never busy*/;
case TOUCH_CONTROL_STATUS:{
uint16_t value = tsc2101Registers[TOUCH_CONTROL_STATUS] & 0xF000;
value |= !!(tsc2101HasNewData) << 10;
//TODO: not returning individual status bits yet
debugLog("TSC2101 read status register\n");
return value;
}
case TOUCH_CONTROL_BUFFER_MODE:
return tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] | (tsc2101BufferFifoEntrys() == 64) << 10 | (tsc2101BufferFifoEntrys() == 0) << 9;
case TOUCH_CONTROL_RESET_CONTROL_REGISTER:
return 0xFFFF;
//TOUCH_DATA_* registers are scaned, the values get copyed to the register when the result is generated
case TOUCH_DATA_X:
case TOUCH_DATA_Y:
case TOUCH_DATA_Z1:
case TOUCH_DATA_Z2:
case TOUCH_DATA_BAT:
case TOUCH_DATA_AUX1:
case TOUCH_DATA_AUX2:
case TOUCH_DATA_TEMP1:
case TOUCH_DATA_TEMP2:
tsc2101HasNewData &= ~(1 << combinedRegisterNumber);
return tsc2101Registers[combinedRegisterNumber];
default:
if(page == 3)
return tsc2101BufferFifoRead();
debugLog("Unimplemented TSC2101 register read, page:0x%01X, address:0x%02X\n", page, address);
return 0x0000;//TODO: this may need to be 0xFFFF
}
}
static void tsc2101RegisterWrite(uint8_t page, uint8_t address, uint16_t value){
uint8_t combinedRegisterNumber = TSC2101_REG_LOCATION(page, address);
switch(combinedRegisterNumber){
case TOUCH_CONTROL_TSC_ADC:
tsc2101Registers[TOUCH_CONTROL_TSC_ADC] = value;
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_TSC2101_SCAN, TSC2101_SCAN_DURATION);
return;
case TOUCH_CONTROL_STATUS:
tsc2101Registers[TOUCH_CONTROL_STATUS] = value & 0xC000;
tsc2101RefreshInterrupt();//interrupt type might have changed
return;
case TOUCH_CONTROL_BUFFER_MODE:
if((tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000) && !(value & 0x8000))
tsc2101BufferFifoFlush();
tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] = value & 0xF800;
tsc2101RefreshInterrupt();//need to refresh innterupt because the trigger level may have changed
return;
case TOUCH_CONTROL_REFERENCE:
//TODO: may need to divide the values by the referece voltage then multiply by 0xFFF
tsc2101Registers[TOUCH_CONTROL_REFERENCE] = value & 0x001F;
return;
case TOUCH_CONTROL_RESET_CONTROL_REGISTER:
if(value == 0xBB00)
tsc2101ResetRegisters();
return;
case TOUCH_CONTROL_CONFIGURATION:
//TODO: TOUCH_CONTROL_CONFIGURATION SWPDTD bit
debugLog("TSC2101 config register writes not fully implemented\n");
tsc2101Registers[TOUCH_CONTROL_CONFIGURATION] = value & 0x007F;
tsc2101RefreshInterrupt();
return;
case TOUCH_CONTROL_TEMPERATURE_MAX:
case TOUCH_CONTROL_TEMPERATURE_MIN:
case TOUCH_CONTROL_AUX1_MAX:
case TOUCH_CONTROL_AUX1_MIN:
case TOUCH_CONTROL_AUX2_MAX:
case TOUCH_CONTROL_AUX2_MIN:
tsc2101Registers[combinedRegisterNumber] = value & 0x1FFF;
tsc2101RefreshInterrupt();
return;
case TOUCH_CONTROL_MEASUREMENT_CONFIGURATION:
tsc2101Registers[TOUCH_CONTROL_MEASUREMENT_CONFIGURATION] = value & 0xFE04;
tsc2101RefreshInterrupt();
return;
case TOUCH_DATA_X:
case TOUCH_DATA_Y:
case TOUCH_DATA_Z1:
case TOUCH_DATA_Z2:
case TOUCH_DATA_BAT:
case TOUCH_DATA_AUX1:
case TOUCH_DATA_AUX2:
case TOUCH_DATA_TEMP1:
case TOUCH_DATA_TEMP2:
//invalid write, ignore
return;
case TOUCH_CONTROL_PROGRAMMABLE_DELAY:
//simple write, no actions needed
tsc2101Registers[combinedRegisterNumber] = value;
return;
default:
if(page == 3)
debugLog("TSC2101 attempted to write buffer register:0x%02X, value:0x%04X\n", address, value);
debugLog("Unimplemented TSC2101 register write, page:0x%01X, address:0x%02X, value:0x%04X\n", page, address, value);
return;
}
}
void tsc2101Reset(bool isBoot){
tsc2101BufferReadPosition = 0;
tsc2101BufferWritePosition = 0;
tsc2101CurrentWord = 0x0000;
tsc2101CurrentWordBitsRemaining = 16;
tsc2101CurrentPage = 0;
tsc2101CurrentRegister = 0;
tsc2101CommandFinished = false;
tsc2101Read = false;
pxa260TimingCancelEvent(PXA260_TIMING_CALLBACK_TSC2101_SCAN);
if(isBoot)
tsc2101ChipSelect = true;
tsc2101ResetRegisters();
}
uint32_t tsc2101StateSize(void){
}
void tsc2101SaveState(uint8_t* data){
}
void tsc2101LoadState(uint8_t* data){
}
void tsc2101SetChipSelect(bool value){
if(value && !tsc2101ChipSelect){
tsc2101CurrentWordBitsRemaining = 16;
tsc2101Read = false;
tsc2101CommandFinished = false;
tsc2101Registers[TOUCH_CONTROL_TSC_ADC] &= 0xC3FF;//TODO: treating this as "stop bit", may be wrong
pxa260TimingCancelEvent(PXA260_TIMING_CALLBACK_TSC2101_SCAN);
}
tsc2101ChipSelect = value;
}
bool tsc2101ExchangeBit(bool bit){
bool output = true;//TODO: SPI return value is usualy true but this is unverified
if(tsc2101ChipSelect)
return true;
if(!tsc2101Read){
tsc2101CurrentWord <<= 1;
tsc2101CurrentWord |= bit;
}
else{
output = !!(tsc2101CurrentWord & 0x8000);
tsc2101CurrentWord <<= 1;
}
tsc2101CurrentWordBitsRemaining--;
if(tsc2101CurrentWordBitsRemaining == 0){
if(!tsc2101CommandFinished){
//write command word
tsc2101CurrentPage = tsc2101CurrentWord >> 11 & 0x000F;
tsc2101CurrentRegister = tsc2101CurrentWord >> 5 & 0x003F;
tsc2101Read = !!(tsc2101CurrentWord & 0x8000);
tsc2101CommandFinished = true;
if(tsc2101Read){
//add first data word
tsc2101CurrentWord = tsc2101RegisterRead(tsc2101CurrentPage, tsc2101CurrentRegister);
tsc2101CurrentRegister++;
}
}
else if(!tsc2101Read){
//write data word
//debugLog("TSC2101 should write now!\n");
if(tsc2101CurrentRegister < 0x40){
tsc2101RegisterWrite(tsc2101CurrentPage, tsc2101CurrentRegister, tsc2101CurrentWord);
tsc2101CurrentRegister++;
}
}
else{
//read data word
if(tsc2101CurrentRegister < 0x40){
tsc2101CurrentWord = tsc2101RegisterRead(tsc2101CurrentPage, tsc2101CurrentRegister);
tsc2101CurrentRegister++;
}
else{
tsc2101CurrentWord = 0xFFFF;
}
}
tsc2101CurrentWordBitsRemaining = 16;
}
return output;
}
void tsc2101RefreshInterrupt(void){
debugLog("TSC2101 PINTDAV not fully implemented\n");
//check if PINTDAV is data or pen and data interrupt
if(tsc2101Registers[TOUCH_CONTROL_STATUS] >> 14 & 0x0003){
if(tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MAX] & 0x1000 && ((tsc2101Registers[TOUCH_CONTROL_MEASUREMENT_CONFIGURATION] & 0x8000) ? tsc2101Registers[TOUCH_DATA_TEMP2] : tsc2101Registers[TOUCH_DATA_TEMP1]) >= (tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MAX] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MIN] & 0x1000 && ((tsc2101Registers[TOUCH_CONTROL_MEASUREMENT_CONFIGURATION] & 0x8000) ? tsc2101Registers[TOUCH_DATA_TEMP2] : tsc2101Registers[TOUCH_DATA_TEMP1]) <= (tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MIN] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_AUX1_MAX] & 0x1000 && tsc2101Registers[TOUCH_DATA_AUX1] >= (tsc2101Registers[TOUCH_CONTROL_AUX1_MAX] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_AUX1_MIN] & 0x1000 && tsc2101Registers[TOUCH_DATA_AUX1] <= (tsc2101Registers[TOUCH_CONTROL_AUX1_MIN] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_AUX2_MAX] & 0x1000 && tsc2101Registers[TOUCH_DATA_AUX2] >= (tsc2101Registers[TOUCH_CONTROL_AUX2_MAX] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_AUX2_MIN] & 0x1000 && tsc2101Registers[TOUCH_DATA_AUX2] <= (tsc2101Registers[TOUCH_CONTROL_AUX2_MIN] & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000){
//buffer mode, check if data is in buffer
if(tsc2101BufferFifoEntrys() >= ((tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] >> 11 & 0x0007) + 1) * 8)
goto trigger;
}
else{
//register mode
if(tsc2101HasNewData)
goto trigger;
}
}
//TODO: ignoring touch detect power down
//check PINTDAV is pen or pen and data interrupt and pen is down
if((tsc2101Registers[TOUCH_CONTROL_STATUS] >> 14 & 0x0003) != 0x0001)
if(palmInput.touchscreenTouched)
goto trigger;
//TODO: set pin high
return;
trigger:
//TODO: set pin low
return;
}
void tsc2101Scan(void){
bool keepScanning = false;
switch(tsc2101Registers[TOUCH_CONTROL_TSC_ADC] >> 10 & 0x000F){
case 0x0:
//none
@@ -184,6 +466,7 @@ static void tsc2101Scan(void){
tsc2101Registers[TOUCH_DATA_X] = tsc2101GetXValue();
tsc2101Registers[TOUCH_DATA_Y] = tsc2101GetYValue();
tsc2101HasNewData |= 1 << TOUCH_DATA_X | 1 << TOUCH_DATA_Y;
keepScanning = true;
if(tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000){
tsc2101BufferFifoWrite(TOUCH_DATA_Y);
@@ -198,6 +481,7 @@ static void tsc2101Scan(void){
tsc2101Registers[TOUCH_DATA_Z1] = tsc2101GetZ1Value();
tsc2101Registers[TOUCH_DATA_Z2] = tsc2101GetZ2Value();
tsc2101HasNewData |= 1 << TOUCH_DATA_X | 1 << TOUCH_DATA_Y | 1 << TOUCH_DATA_Z1 | 1 << TOUCH_DATA_Z2;
keepScanning = true;
if(tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000){
tsc2101BufferFifoWrite(TOUCH_DATA_Y);
@@ -267,6 +551,7 @@ static void tsc2101Scan(void){
case 0x9:
//auto scan
//TODO: implement
//keepScanning = true;
debugLog("TSC2101 auto scan unimplemented\n");
break;
@@ -285,6 +570,7 @@ static void tsc2101Scan(void){
tsc2101Registers[TOUCH_DATA_AUX1] = tsc2101GetAux1Value();
tsc2101Registers[TOUCH_DATA_AUX2] = tsc2101GetAux2Value();
tsc2101HasNewData |= 1 << TOUCH_DATA_BAT | 1 << TOUCH_DATA_AUX1 | 1 << TOUCH_DATA_AUX2;
keepScanning = true;
if(tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000){
tsc2101BufferFifoWrite(TOUCH_DATA_BAT);
@@ -308,274 +594,10 @@ static void tsc2101Scan(void){
}
tsc2101RefreshInterrupt();
if(keepScanning)
pxa260TimingTriggerEvent(PXA260_TIMING_CALLBACK_TSC2101_SCAN, TSC2101_SCAN_DURATION);
else
tsc2101Registers[TOUCH_CONTROL_TSC_ADC] &= 0xC3FF;
}
static void tsc2101ResetRegisters(void){
tsc2101HasNewData = 0x0000;
memset(tsc2101Registers, 0x00, sizeof(tsc2101Registers));
//TODO: need to add all the registers here
tsc2101Registers[TOUCH_CONTROL_STATUS] = 0x8000;
tsc2101Registers[TOUCH_CONTROL_REFERENCE] = 0x0002;
tsc2101RefreshInterrupt();
}
static uint16_t tsc2101RegisterRead(uint8_t page, uint8_t address){
uint8_t combinedRegisterNumber = TSC2101_REG_LOCATION(page, address);
switch(combinedRegisterNumber){
case TOUCH_CONTROL_TSC_ADC:
return tsc2101Registers[TOUCH_CONTROL_TSC_ADC] & 0x3FFF | palmInput.touchscreenTouched << 15 | 1 << 14/*TODO: this states the ADC is never busy*/;
case TOUCH_CONTROL_STATUS:
//TODO: just always saying new data is available to avoid timing
debugLog("TSC2101 read status register\n");
return tsc2101Registers[TOUCH_CONTROL_STATUS] | 0x0FDE;
case TOUCH_CONTROL_BUFFER_MODE:
return tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] | (tsc2101BufferFifoEntrys() == 64) << 10 | (tsc2101BufferFifoEntrys() == 0) << 9;
case TOUCH_CONTROL_RESET_CONTROL_REGISTER:
return 0xFFFF;
//TOUCH_DATA_* registers are scaned, the values get copyed to the register when the result is generated
case TOUCH_DATA_X:
case TOUCH_DATA_Y:
case TOUCH_DATA_Z1:
case TOUCH_DATA_Z2:
case TOUCH_DATA_BAT:
case TOUCH_DATA_AUX1:
case TOUCH_DATA_AUX2:
case TOUCH_DATA_TEMP1:
case TOUCH_DATA_TEMP2:
tsc2101HasNewData &= ~(1 << combinedRegisterNumber);
return tsc2101Registers[combinedRegisterNumber];
default:
if(page == 3)
return tsc2101BufferFifoRead();
debugLog("Unimplemented TSC2101 register read, page:0x%01X, address:0x%02X\n", page, address);
return 0x0000;//TODO: this may need to be 0xFFFF
}
}
static void tsc2101RegisterWrite(uint8_t page, uint8_t address, uint16_t value){
uint8_t combinedRegisterNumber = TSC2101_REG_LOCATION(page, address);
switch(combinedRegisterNumber){
case TOUCH_CONTROL_TSC_ADC:
tsc2101Registers[TOUCH_CONTROL_TSC_ADC] = value;
tsc2101Scan();//TODO: this should probably be on a timer
return;
case TOUCH_CONTROL_REFERENCE:
//TODO: may need to divide the values by the referece voltage then multiply by 0xFFF
tsc2101Registers[TOUCH_CONTROL_REFERENCE] = value & 0x001F;
return;
case TOUCH_CONTROL_RESET_CONTROL_REGISTER:
if(value == 0xBB00)
tsc2101ResetRegisters();
return;
case TOUCH_CONTROL_CONFIGURATION:
//TODO: TOUCH_CONTROL_CONFIGURATION SWPDTD bit
debugLog("TSC2101 config register writes not fully implemented\n");
tsc2101Registers[TOUCH_CONTROL_CONFIGURATION] = value & 0x007F;
tsc2101RefreshInterrupt();
return;
case TOUCH_CONTROL_TEMPERATURE_MAX:
case TOUCH_CONTROL_TEMPERATURE_MIN:
case TOUCH_CONTROL_AUX1_MAX:
case TOUCH_CONTROL_AUX1_MIN:
case TOUCH_CONTROL_AUX2_MAX:
case TOUCH_CONTROL_AUX2_MIN:
tsc2101Registers[combinedRegisterNumber] = value & 0x1FFF;
tsc2101RefreshInterrupt();
return;
case TOUCH_CONTROL_MEASUREMENT_CONFIGURATION:
tsc2101Registers[TOUCH_CONTROL_MEASUREMENT_CONFIGURATION] = value & 0xFE04;
tsc2101RefreshInterrupt();
return;
case TOUCH_DATA_X:
case TOUCH_DATA_Y:
case TOUCH_DATA_Z1:
case TOUCH_DATA_Z2:
case TOUCH_DATA_BAT:
case TOUCH_DATA_AUX1:
case TOUCH_DATA_AUX2:
case TOUCH_DATA_TEMP1:
case TOUCH_DATA_TEMP2:
//invalid write, ignore
return;
case TOUCH_CONTROL_PROGRAMMABLE_DELAY:
//simple write, no actions needed
tsc2101Registers[combinedRegisterNumber] = value;
return;
default:
if(page == 3)
debugLog("TSC2101 attempted to write buffer register:0x%02X, value:0x%04X\n", address, value);
debugLog("Unimplemented TSC2101 register write, page:0x%01X, address:0x%02X, value:0x%04X\n", page, address, value);
return;
}
}
void tsc2101Reset(bool isBoot){
tsc2101BufferReadPosition = 0;
tsc2101BufferWritePosition = 0;
tsc2101CurrentWord = 0x0000;
tsc2101CurrentWordBitsRemaining = 16;
tsc2101CurrentPage = 0;
tsc2101CurrentRegister = 0;
tsc2101CommandFinished = false;
tsc2101Read = false;
if(isBoot)
tsc2101ChipSelect = true;
tsc2101ResetRegisters();
}
uint32_t tsc2101StateSize(void){
}
void tsc2101SaveState(uint8_t* data){
}
void tsc2101LoadState(uint8_t* data){
}
void tsc2101SetChipSelect(bool value){
//TODO: ADCSM references a "stop bit", this is likely when chip select goes high but I have no proof
//also dont know if the scan type value in the register is set to 0x0
if(value && !tsc2101ChipSelect){
tsc2101CurrentWordBitsRemaining = 16;
tsc2101Read = false;
tsc2101CommandFinished = false;
}
tsc2101ChipSelect = value;
}
bool tsc2101ExchangeBit(bool bit){
bool output = true;//TODO: SPI return value is usualy true but this is unverified
if(tsc2101ChipSelect)
return true;
if(!tsc2101Read){
tsc2101CurrentWord <<= 1;
tsc2101CurrentWord |= bit;
}
else{
output = !!(tsc2101CurrentWord & 0x8000);
tsc2101CurrentWord <<= 1;
}
tsc2101CurrentWordBitsRemaining--;
if(tsc2101CurrentWordBitsRemaining == 0){
if(!tsc2101CommandFinished){
//write command word
tsc2101CurrentPage = tsc2101CurrentWord >> 11 & 0x000F;
tsc2101CurrentRegister = tsc2101CurrentWord >> 5 & 0x003F;
tsc2101Read = !!(tsc2101CurrentWord & 0x8000);
tsc2101CommandFinished = true;
if(tsc2101Read){
//add first data word
tsc2101CurrentWord = tsc2101RegisterRead(tsc2101CurrentPage, tsc2101CurrentRegister);
tsc2101CurrentRegister++;
}
}
else if(!tsc2101Read){
//write data word
//debugLog("TSC2101 should write now!\n");
if(tsc2101CurrentRegister < 0x40){
tsc2101RegisterWrite(tsc2101CurrentPage, tsc2101CurrentRegister, tsc2101CurrentWord);
tsc2101CurrentRegister++;
}
}
else{
//read data word
if(tsc2101CurrentRegister < 0x40){
tsc2101CurrentWord = tsc2101RegisterRead(tsc2101CurrentPage, tsc2101CurrentRegister);
tsc2101CurrentRegister++;
}
else{
tsc2101CurrentWord = 0xFFFF;
}
}
tsc2101CurrentWordBitsRemaining = 16;
}
return output;
}
void tsc2101RefreshInterrupt(void){
debugLog("TSC2101 PINTDAV not fully implemented\n");
//check if PINTDAV is data or pen and data interrupt
if(tsc2101Registers[TOUCH_CONTROL_STATUS] >> 14 & 0x0003){
uint16_t aux1 = tsc2101Registers[TOUCH_DATA_AUX1];
uint16_t aux2 = tsc2101Registers[TOUCH_DATA_AUX2];
uint16_t temp1 = tsc2101Registers[TOUCH_DATA_TEMP1];
uint16_t temp2 = tsc2101Registers[TOUCH_DATA_TEMP2];
bool useTemp2 = !!(tsc2101Registers[TOUCH_CONTROL_MEASUREMENT_CONFIGURATION] & 0x8000);
uint16_t temperatureMax = tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MAX];
uint16_t temperatureMin = tsc2101Registers[TOUCH_CONTROL_TEMPERATURE_MIN];
uint16_t aux1Max = tsc2101Registers[TOUCH_CONTROL_AUX1_MAX];
uint16_t aux1Min = tsc2101Registers[TOUCH_CONTROL_AUX1_MIN];
uint16_t aux2Max = tsc2101Registers[TOUCH_CONTROL_AUX2_MAX];
uint16_t aux2Min = tsc2101Registers[TOUCH_CONTROL_AUX2_MIN];
if(temperatureMax & 0x1000 && (useTemp2 ? temp2 : temp1) >= (temperatureMax & 0xFFF))
goto trigger;
if(temperatureMin & 0x1000 && (useTemp2 ? temp2 : temp1) <= (temperatureMin & 0xFFF))
goto trigger;
if(aux1Max & 0x1000 && aux1 >= (aux1Max & 0xFFF))
goto trigger;
if(aux1Min & 0x1000 && aux1 <= (aux1Min & 0xFFF))
goto trigger;
if(aux2Max & 0x1000 && aux2 >= (aux2Max & 0xFFF))
goto trigger;
if(aux2Min & 0x1000 && aux2 <= (aux2Min & 0xFFF))
goto trigger;
if(tsc2101Registers[TOUCH_CONTROL_BUFFER_MODE] & 0x8000){
//buffer mode, check if data is in buffer
if(tsc2101BufferFifoEntrys() > 0)
goto trigger;
}
else{
//register mode
if(tsc2101HasNewData)
goto trigger;
}
}
//check PINTDAV is pen or pen and data interrupt and pen is down
if((tsc2101Registers[TOUCH_CONTROL_STATUS] >> 14 & 0x0003) != 0x0001)
if(palmInput.touchscreenTouched)
goto trigger;
//TODO: set pin high
return;
trigger:
//TODO: set pin low
return;
}

View File

@@ -14,4 +14,6 @@ bool tsc2101ExchangeBit(bool bit);
void tsc2101RefreshInterrupt(void);//called after touchscreen update to flush the values
//TODO: this chip seems to do audio output, need to add a 16bit optimized transfer function
void tsc2101Scan(void);
#endif