summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 15:34:54 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 15:34:54 +0200
commit57bb7b2d2704166b5d4dd307d3ae8d8ae99afbbd (patch)
tree20dd540c994744341c1a88b614699fb414b55f99
parent0173f6edf58c3ee377cd2d6a10540787cb847524 (diff)
downloadrockbox-57bb7b2d2704166b5d4dd307d3ae8d8ae99afbbd.tar.gz
rockbox-57bb7b2d2704166b5d4dd307d3ae8d8ae99afbbd.zip
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
-rw-r--r--firmware/target/arm/imx233/touchscreen-imx233.c84
1 files 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
46 TOUCH_STATE_VERIFY, /* verify touch */ 46 TOUCH_STATE_VERIFY, /* verify touch */
47}; 47};
48 48
49#define DEBOUNCE_THRESHOLD 100 49#define NR_SAMPLES 10
50#define SAMPLES_THRESHOLD 4 50#define DELAY 1
51 51
52static enum touch_state_t touch_state; 52static enum touch_state_t touch_state;
53static int touch_chan = -1; 53static int touch_chan = -1;
54static int touch_delay = -1; 54static int touch_delay = -1;
55static int touch_x, touch_y, nr_samples; 55static int touch_x, touch_y;
56/* once a touch is confirmed, the parameters are copied to these value for 56/* once a touch is confirmed, the parameters are copied to these value for
57 * instant readout by button code. */ 57 * instant readout by button code. */
58static bool old_touch_detect = false; 58static bool old_touch_detect = false;
59static int old_touch_x, old_touch_y; 59static int old_touch_x, old_touch_y;
60 60
61static void kick_measure(bool pull_x, bool pull_y, bool detect, int lradc_phys) 61static void process(void);
62
63void INT_TOUCH_DETECT(void)
64{
65 process();
66}
67
68static void touch_channel_irq(int chan)
62{ 69{
70 imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(chan), false);
71 imx233_lradc_enable_channel_irq(chan, false);
72 process();
73}
74
75static void kick_measure(bool pull_x, bool pull_y, bool detect, int src)
76{
77 if(touch_chan >= 0)
78 imx233_lradc_release_channel(touch_chan);
79 touch_chan = imx233_lradc_acquire_channel(src, TIMEOUT_NOBLOCK);
80 if(touch_chan < 0)
81 panicf("touchscreen: cannot get adc channel");
82 /* enable interrupt */
83 imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq);
84 imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), true);
85 imx233_lradc_enable_channel_irq(touch_chan, true);
63 /* setup measurement: x- pull down and x+ pull up */ 86 /* setup measurement: x- pull down and x+ pull up */
64 imx233_lradc_setup_touch(pull_x, pull_y, pull_x, pull_y, detect); 87 imx233_lradc_setup_touch(pull_x, pull_y, pull_x, pull_y, detect);
65 imx233_lradc_enable_touch_detect_irq(false); 88 imx233_lradc_enable_touch_detect_irq(false);
66 imx233_lradc_enable_channel_irq(touch_chan, true); 89 imx233_lradc_enable_channel_irq(touch_chan, true);
67 /* measure channel, no accumulation */ 90 /* measure channel, no accumulation */
68 imx233_lradc_setup_channel(touch_chan, false, false, 0, lradc_phys); 91 imx233_lradc_setup_channel(touch_chan, false, true, NR_SAMPLES - 1, src);
92 imx233_lradc_clear_channel(touch_chan);
69 /* use a delay */ 93 /* use a delay */
70 imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 0, 0, 8); 94 imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 1 << touch_delay,
95 NR_SAMPLES -1, DELAY);
71 imx233_lradc_kick_delay(touch_delay); 96 imx233_lradc_kick_delay(touch_delay);
72} 97}
73 98
@@ -78,7 +103,6 @@ static void enter_state(enum touch_state_t state)
78 { 103 {
79 case TOUCH_STATE_WAIT: 104 case TOUCH_STATE_WAIT:
80 imx233_lradc_setup_touch(false, false, false, false, true); 105 imx233_lradc_setup_touch(false, false, false, false, true);
81 imx233_lradc_enable_channel_irq(touch_chan, false);
82 imx233_lradc_enable_touch_detect_irq(true); 106 imx233_lradc_enable_touch_detect_irq(true);
83 break; 107 break;
84 case TOUCH_STATE_MEASURE_X: 108 case TOUCH_STATE_MEASURE_X:
@@ -95,7 +119,6 @@ static void enter_state(enum touch_state_t state)
95 119
96static void process(void) 120static void process(void)
97{ 121{
98 int val;
99 switch(touch_state) 122 switch(touch_state)
100 { 123 {
101 case TOUCH_STATE_WAIT: 124 case TOUCH_STATE_WAIT:
@@ -110,32 +133,12 @@ static void process(void)
110 } 133 }
111 break; 134 break;
112 case TOUCH_STATE_MEASURE_X: 135 case TOUCH_STATE_MEASURE_X:
113 /* read value */ 136 touch_x = imx233_lradc_read_channel(touch_chan) / NR_SAMPLES;
114 val = imx233_lradc_read_channel(touch_chan); 137 enter_state(TOUCH_STATE_MEASURE_Y);
115 /* if value is too far from average, restart */
116 if(nr_samples > 0 && abs(val - touch_x) > DEBOUNCE_THRESHOLD)
117 nr_samples = 0;
118 touch_x = (touch_x * nr_samples + val) / (nr_samples + 1);
119 nr_samples++;
120 /* if we have enough samples, measure Y */
121 if(nr_samples > SAMPLES_THRESHOLD)
122 enter_state(TOUCH_STATE_MEASURE_Y);
123 else
124 imx233_lradc_kick_delay(touch_delay);
125 break; 138 break;
126 case TOUCH_STATE_MEASURE_Y: 139 case TOUCH_STATE_MEASURE_Y:
127 /* read value */ 140 touch_y = imx233_lradc_read_channel(touch_chan) / NR_SAMPLES;
128 val = imx233_lradc_read_channel(touch_chan);
129 /* if value is too far from average, restart */
130 if(nr_samples > 0 && abs(val - touch_y) > DEBOUNCE_THRESHOLD)
131 nr_samples = 0;
132 touch_y = (touch_y * nr_samples + val) / (nr_samples + 1);
133 nr_samples++;
134 /* if we have enough samples, verify touch */
135 if(nr_samples > SAMPLES_THRESHOLD)
136 enter_state(TOUCH_STATE_VERIFY); 141 enter_state(TOUCH_STATE_VERIFY);
137 else
138 imx233_lradc_kick_delay(touch_delay);
139 break; 142 break;
140 case TOUCH_STATE_VERIFY: 143 case TOUCH_STATE_VERIFY:
141 if(imx233_lradc_read_touch_detect()) 144 if(imx233_lradc_read_touch_detect())
@@ -154,31 +157,18 @@ static void process(void)
154 } 157 }
155} 158}
156 159
157void INT_TOUCH_DETECT(void)
158{
159 process();
160}
161
162static void touch_channel_irq(int chan)
163{
164 (void) chan;
165 process();
166}
167
168void imx233_touchscreen_init(void) 160void imx233_touchscreen_init(void)
169{ 161{
170 touch_chan = imx233_lradc_acquire_channel(LRADC_SRC_XPLUS, TIMEOUT_NOBLOCK);
171 touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK); 162 touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK);
172 if(touch_chan < 0 || touch_delay < 0) 163 if(touch_delay < 0)
173 panicf("Cannot acquire channel and delays for touchscreen measurement"); 164 panicf("Cannot acquire channel and delays for touchscreen measurement");
174 imx233_touchscreen_enable(false); 165 imx233_touchscreen_enable(false);
175} 166}
176 167
177void imx233_touchscreen_enable(bool enable) 168void imx233_touchscreen_enable(bool enable)
178{ 169{
179 enter_state(TOUCH_STATE_WAIT); 170 if(enable)
180 imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq); 171 enter_state(TOUCH_STATE_WAIT);
181 imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), enable);
182 imx233_icoll_enable_interrupt(INT_SRC_TOUCH_DETECT, enable); 172 imx233_icoll_enable_interrupt(INT_SRC_TOUCH_DETECT, enable);
183} 173}
184 174