Hi,
I'm working on a touchscreen driver for a LM3S9B95 Stellaris.
I have an ADC sample sequence set up and I am able to read data out of the adc channels.
But the data does not seem to be of high enough resolution to convert to XY screen coordinates.
The touchscreen is a TTW4028001 on a 320X240 pixels LCD.
The data I'm getting from the ADC channel 11 (ADC_CTL_CH11), when I press the screen, is ranging from 0 to 30 for the Y. Which correlates to the 240 pixels width, on the bottom of the screen. And from 0 to 20 on the top of the screen. Which are quite promising results although quite low resolution of course.
The real problem lies in the reading of the ADC channel 10 (ADC_CTL_CH10), for the X values. That is constant around 43, when I press the screen it goes down by 5 to 38 at maximum.
This is with the reference voltage set to 1 volt external, connected at pin B6. With internal or external 3V, the resolution of the readings go down significantly.
Right now I'm using processor triggered interrupts, fired from a loop with interval. Eventually when I can make sensible readings this will be changed to timer based interrupts.
Another issue for me is getting valid conversion parameters to get valid XY coordinates. Like g_plParmSet in the touchscreen example driver for dk-lm3s9d96, touch.c. I don't know how to produce these values for my touchscreen, no clues in the datasheet.
If anyone can shed some light here, it would be greatly appreciated
Here is my code:
#define TS_ADC_PERIPH_B SYSCTL_PERIPH_GPIOB // the adc pins
#define TS_ADC_PERIPH_E SYSCTL_PERIPH_GPIOE // the drive pins
#define TS_ADC_BASE GPIO_PORTB_BASE
#define TS_DRIVE_BASE GPIO_PORTE_BASE
#define TS_X_ADC_PIN GPIO_PIN_4
#define TS_X_DRIVE_PIN GPIO_PIN_0
#define TS_Y_DRIVE_PIN GPIO_PIN_1
#define TS_Y_ADC_PIN GPIO_PIN_5
#define ADC_CTL_CH_XP ADC_CTL_CH10
#define ADC_CTL_CH_YP ADC_CTL_CH11
// from touch.c in the dk-lm3s9d96 example
const long g_plParmSet[7] =
{ -864, // M0
-79200, // M1
70274016, // M2
-85088, // M3
1056, // M4
80992576, // M5
199452, // M6
};
void ts_Init()
{
SysCtlPeripheralEnable (SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable (TS_ADC_PERIPH_B);
SysCtlPeripheralEnable (TS_ADC_PERIPH_E);
GPIOPinTypeADC(TS_ADC_BASE, TS_X_ADC_PIN | TS_Y_ADC_PIN);
GPIOPinTypeADC(GPIO_PORTB_BASE, GPIO_PIN_6);
ADCSequenceDisable(ADC0_BASE, 1);
ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_1V); // yields best results
//ADCReferenceSet(ADC0_BASE, ADC_REF_INT);
//ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V);
//ADCHardwareOversampleConfigure(ADC0_BASE, 4);
ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0);
ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH_XP);
ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH_YP | ADC_CTL_IE | ADC_CTL_END);
ADCIntRegister(ADC0_BASE, 1, ts_IntHandler);
ADCIntEnable(ADC0_BASE, 1);
ADCSequenceEnable(ADC0_BASE, 1);
GPIOPinWrite (TS_DRIVE_BASE, TS_X_DRIVE_PIN, TS_X_DRIVE_PIN);
GPIOPinWrite (TS_DRIVE_BASE, TS_Y_DRIVE_PIN, 0);
// Changing high low on the pins seems to have no effect
/*GPIOPinWrite (TS_ADC_BASE, TS_Y_ADC_PIN, 0);
GPIOPinWrite (TS_DRIVE_BASE, TS_X_DRIVE_PIN, TS_X_DRIVE_PIN);
GPIOPinWrite (TS_ADC_BASE, TS_X_ADC_PIN, 0);
GPIOPinWrite (TS_DRIVE_BASE, TS_Y_DRIVE_PIN, 0);*/
}
void ts_IntHandler(void)
{
unsigned long adc_buffer[4]; // Sequence 1 has a FIFO of 4 entries
ADCIntClear(ADC0_BASE, 1);
ADCSequenceDataGet(ADC0_BASE, 1, adc_buffer);
tRectangle sRect;
sRect.sXMin = ((GrContextDpyWidthGet(&g_sContext)) / 2) - 75;
sRect.sYMin = ((GrContextDpyHeightGet(&g_sContext)) / 2) - 40;
sRect.sXMax = ((GrContextDpyWidthGet(&g_sContext)) / 2) + 75;
sRect.sYMax = ((GrContextDpyHeightGet(&g_sContext)) / 2) + 40;
GrContextForegroundSet(&g_sContext, ClrBlack);
GrRectFill(&g_sContext, &sRect);
char buf[16];
GrContextForegroundSet(&g_sContext, ClrWhite);
// adc_buffer[0] (x) is constant at 43, when screen press about 5 down to 38 max
// adc_buffer[1] (y) has a range of 0 to 30
usprintf(buf, "%d", adc_buffer[0]);
GrStringDrawCentered(&g_sContext, buf, -1, GrContextDpyWidthGet(&g_sContext) / 2 - 40, ((GrContextDpyHeightGet(&g_sContext)) / 2) - 25, 0);
usprintf(buf, "%d", adc_buffer[1]);
GrStringDrawCentered(&g_sContext, buf, -1, GrContextDpyWidthGet(&g_sContext) / 2 + 40, ((GrContextDpyHeightGet(&g_sContext)) / 2) - 25, 0);
}
// main.cpp
int main(void)
{
SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ);
IntMasterEnable ();
...
// Here the touchscreen init and interrupt loop
ts_Init();
while (1)
{
ADCProcessorTrigger(ADC0_BASE, 1);
DelayMs(500);
}
}