mirror of
https://github.com/libretro/Mu.git
synced 2026-09-22 22:56:12 +00:00
Doesnt get as far anymore but is more accurate
This commit is contained in:
@@ -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){
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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]();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
564
src/tsc2101.c
564
src/tsc2101.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user