From 57bb7b2d2704166b5d4dd307d3ae8d8ae99afbbd Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Tue, 18 Jun 2013 15:34:54 +0200 Subject: 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 --- firmware/target/arm/imx233/touchscreen-imx233.c | 84 +++++++++++-------------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/firmware/target/arm/imx233/touchscreen-imx233.c b/firmware/target/arm/imx233/touchscreen-imx233.c index e76d7a49e3..c4d2f4d726 100644 --- a/firmware/target/arm/imx233/touchscreen-imx233.c +++ b/firmware/target/arm/imx233/touchscreen-imx233.c @@ -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); } -- cgit v1.2.3