imx233: rework touchscreen driver
The old driver didn't behave nicely because it waiting for stability which could never arrive on some gestures. The new one uses a fixed delay and averaging. Change-Id: I8ff80f373b6792e6d5fc3cfe41b709642e61c38b
This commit is contained in:
parent
0173f6edf5
commit
57bb7b2d27
1 changed files with 37 additions and 47 deletions
|
@ -46,28 +46,53 @@ enum touch_state_t
|
|||
TOUCH_STATE_VERIFY, /* verify touch */
|
||||
};
|
||||
|
||||
#define DEBOUNCE_THRESHOLD 100
|
||||
#define SAMPLES_THRESHOLD 4
|
||||
#define NR_SAMPLES 10
|
||||
#define DELAY 1
|
||||
|
||||
static enum touch_state_t touch_state;
|
||||
static int touch_chan = -1;
|
||||
static int touch_delay = -1;
|
||||
static int touch_x, touch_y, nr_samples;
|
||||
static int touch_x, touch_y;
|
||||
/* once a touch is confirmed, the parameters are copied to these value for
|
||||
* instant readout by button code. */
|
||||
static bool old_touch_detect = false;
|
||||
static int old_touch_x, old_touch_y;
|
||||
|
||||
static void kick_measure(bool pull_x, bool pull_y, bool detect, int lradc_phys)
|
||||
static void process(void);
|
||||
|
||||
void INT_TOUCH_DETECT(void)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
||||
static void touch_channel_irq(int chan)
|
||||
{
|
||||
imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(chan), false);
|
||||
imx233_lradc_enable_channel_irq(chan, false);
|
||||
process();
|
||||
}
|
||||
|
||||
static void kick_measure(bool pull_x, bool pull_y, bool detect, int src)
|
||||
{
|
||||
if(touch_chan >= 0)
|
||||
imx233_lradc_release_channel(touch_chan);
|
||||
touch_chan = imx233_lradc_acquire_channel(src, TIMEOUT_NOBLOCK);
|
||||
if(touch_chan < 0)
|
||||
panicf("touchscreen: cannot get adc channel");
|
||||
/* enable interrupt */
|
||||
imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq);
|
||||
imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), true);
|
||||
imx233_lradc_enable_channel_irq(touch_chan, true);
|
||||
/* setup measurement: x- pull down and x+ pull up */
|
||||
imx233_lradc_setup_touch(pull_x, pull_y, pull_x, pull_y, detect);
|
||||
imx233_lradc_enable_touch_detect_irq(false);
|
||||
imx233_lradc_enable_channel_irq(touch_chan, true);
|
||||
/* measure channel, no accumulation */
|
||||
imx233_lradc_setup_channel(touch_chan, false, false, 0, lradc_phys);
|
||||
imx233_lradc_setup_channel(touch_chan, false, true, NR_SAMPLES - 1, src);
|
||||
imx233_lradc_clear_channel(touch_chan);
|
||||
/* use a delay */
|
||||
imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 0, 0, 8);
|
||||
imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 1 << touch_delay,
|
||||
NR_SAMPLES -1, DELAY);
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
}
|
||||
|
||||
|
@ -78,7 +103,6 @@ static void enter_state(enum touch_state_t state)
|
|||
{
|
||||
case TOUCH_STATE_WAIT:
|
||||
imx233_lradc_setup_touch(false, false, false, false, true);
|
||||
imx233_lradc_enable_channel_irq(touch_chan, false);
|
||||
imx233_lradc_enable_touch_detect_irq(true);
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_X:
|
||||
|
@ -95,7 +119,6 @@ static void enter_state(enum touch_state_t state)
|
|||
|
||||
static void process(void)
|
||||
{
|
||||
int val;
|
||||
switch(touch_state)
|
||||
{
|
||||
case TOUCH_STATE_WAIT:
|
||||
|
@ -110,32 +133,12 @@ static void process(void)
|
|||
}
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_X:
|
||||
/* read value */
|
||||
val = imx233_lradc_read_channel(touch_chan);
|
||||
/* if value is too far from average, restart */
|
||||
if(nr_samples > 0 && abs(val - touch_x) > DEBOUNCE_THRESHOLD)
|
||||
nr_samples = 0;
|
||||
touch_x = (touch_x * nr_samples + val) / (nr_samples + 1);
|
||||
nr_samples++;
|
||||
/* if we have enough samples, measure Y */
|
||||
if(nr_samples > SAMPLES_THRESHOLD)
|
||||
enter_state(TOUCH_STATE_MEASURE_Y);
|
||||
else
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
touch_x = imx233_lradc_read_channel(touch_chan) / NR_SAMPLES;
|
||||
enter_state(TOUCH_STATE_MEASURE_Y);
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_Y:
|
||||
/* read value */
|
||||
val = imx233_lradc_read_channel(touch_chan);
|
||||
/* if value is too far from average, restart */
|
||||
if(nr_samples > 0 && abs(val - touch_y) > DEBOUNCE_THRESHOLD)
|
||||
nr_samples = 0;
|
||||
touch_y = (touch_y * nr_samples + val) / (nr_samples + 1);
|
||||
nr_samples++;
|
||||
/* if we have enough samples, verify touch */
|
||||
if(nr_samples > SAMPLES_THRESHOLD)
|
||||
touch_y = imx233_lradc_read_channel(touch_chan) / NR_SAMPLES;
|
||||
enter_state(TOUCH_STATE_VERIFY);
|
||||
else
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
break;
|
||||
case TOUCH_STATE_VERIFY:
|
||||
if(imx233_lradc_read_touch_detect())
|
||||
|
@ -154,31 +157,18 @@ static void process(void)
|
|||
}
|
||||
}
|
||||
|
||||
void INT_TOUCH_DETECT(void)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
||||
static void touch_channel_irq(int chan)
|
||||
{
|
||||
(void) chan;
|
||||
process();
|
||||
}
|
||||
|
||||
void imx233_touchscreen_init(void)
|
||||
{
|
||||
touch_chan = imx233_lradc_acquire_channel(LRADC_SRC_XPLUS, TIMEOUT_NOBLOCK);
|
||||
touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK);
|
||||
if(touch_chan < 0 || touch_delay < 0)
|
||||
if(touch_delay < 0)
|
||||
panicf("Cannot acquire channel and delays for touchscreen measurement");
|
||||
imx233_touchscreen_enable(false);
|
||||
}
|
||||
|
||||
void imx233_touchscreen_enable(bool enable)
|
||||
{
|
||||
enter_state(TOUCH_STATE_WAIT);
|
||||
imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq);
|
||||
imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), enable);
|
||||
if(enable)
|
||||
enter_state(TOUCH_STATE_WAIT);
|
||||
imx233_icoll_enable_interrupt(INT_SRC_TOUCH_DETECT, enable);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue