summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-05-19 13:42:49 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2012-05-19 16:10:52 +0200
commit85d5c19347c1665b765708cdb67f1d996c7f7fa4 (patch)
tree14cc20dbd694e408ece18c7d9788c2a74cef042e
parent247e611f4945d048f280471d78b7b83a96b35454 (diff)
downloadrockbox-85d5c19347c1665b765708cdb67f1d996c7f7fa4.tar.gz
rockbox-85d5c19347c1665b765708cdb67f1d996c7f7fa4.zip
imx233: add touchscreen driver
Change-Id: I406076d110e33cdae871222191d82262fabcf16a
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/target/arm/imx233/touchscreen-imx233.c193
-rw-r--r--firmware/target/arm/imx233/touchscreen-imx233.h34
3 files changed, 230 insertions, 0 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index facf9777ef..c81ecf3294 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -518,6 +518,9 @@ target/arm/imx233/lradc-imx233.c
518target/arm/imx233/pwm-imx233.c 518target/arm/imx233/pwm-imx233.c
519target/arm/imx233/rtc-imx233.c 519target/arm/imx233/rtc-imx233.c
520target/arm/imx233/dcp-imx233.c 520target/arm/imx233/dcp-imx233.c
521# ifdef HAVE_TOUCHSCREEN
522target/arm/imx233/touchscreen-imx233.c
523# endif
521#ifndef BOOTLOADER 524#ifndef BOOTLOADER
522target/arm/imx233/debug-imx233.c 525target/arm/imx233/debug-imx233.c
523#endif 526#endif
diff --git a/firmware/target/arm/imx233/touchscreen-imx233.c b/firmware/target/arm/imx233/touchscreen-imx233.c
new file mode 100644
index 0000000000..f8cbf76896
--- /dev/null
+++ b/firmware/target/arm/imx233/touchscreen-imx233.c
@@ -0,0 +1,193 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#include "touchscreen-imx233.h"
25#include "stdlib.h"
26
27/* Description:
28 * the driver basically has 2 modes:
29 * - wait mode: use the hardware touch detect mechanism to wait for an edge
30 * - measurement mode: use pull up/down and adc to measure X/Y
31 * In measurement mode, we start by measuring X then Y then we check if
32 * the hardware still detect a touch. When no touch is detected anymore, we
33 * go back to wait mode.
34 * For each axis, we handle stabilization by repeatedly measuring the position
35 * until it is stable. We consider a set of measures stable when
36 * no measure is further away from the average than DEBOUNCE_THRESHOLD and
37 * we have at least SAMPLES_THRESHOLD measures. This avoids using magic
38 * timing constants specific to the touchscreen stabilization time and
39 * it is much more robust.
40 *
41 * Inspired by linux touchscreen driver for the stmp37xx.
42 */
43
44enum touch_state_t
45{
46 TOUCH_STATE_WAIT, /* wait for touch */
47 TOUCH_STATE_MEASURE_X, /* measure x */
48 TOUCH_STATE_MEASURE_Y, /* measure y */
49 TOUCH_STATE_VERIFY, /* verify touch */
50};
51
52#define DEBOUNCE_THRESHOLD 100
53#define SAMPLES_THRESHOLD 4
54
55static enum touch_state_t touch_state;
56static int touch_chan = -1;
57static int touch_delay = -1;
58static int touch_x, touch_y, nr_samples;
59/* once a touch is confirmed, the parameters are copied to these value for
60 * instant readout by button code. */
61static bool old_touch_detect = false;
62static int old_touch_x, old_touch_y;
63
64static void kick_measure(bool pull_x, bool pull_y, bool detect, int lradc_phys)
65{
66 /* setup measurement: x- pull down and x+ pull up */
67 imx233_lradc_setup_touch(pull_x, pull_y, pull_x, pull_y, detect);
68 imx233_lradc_enable_touch_detect_irq(false);
69 imx233_lradc_enable_channel_irq(touch_chan, true);
70 /* measure channel, no accumulation */
71 imx233_lradc_setup_channel(touch_chan, false, false, 0, lradc_phys);
72 /* use a delay */
73 imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 0, 0, 8);
74 imx233_lradc_kick_delay(touch_delay);
75}
76
77static void enter_state(enum touch_state_t state)
78{
79 touch_state = state;
80 switch(state)
81 {
82 case TOUCH_STATE_WAIT:
83 imx233_lradc_setup_touch(false, false, false, false, true);
84 imx233_lradc_enable_channel_irq(touch_chan, false);
85 imx233_lradc_enable_touch_detect_irq(true);
86 break;
87 case TOUCH_STATE_MEASURE_X:
88 kick_measure(true, false, false, HW_LRADC_CHANNEL_YPLUS);
89 break;
90 case TOUCH_STATE_MEASURE_Y:
91 kick_measure(false, true, false, HW_LRADC_CHANNEL_XPLUS);
92 break;
93 case TOUCH_STATE_VERIFY:
94 kick_measure(false, false, true, HW_LRADC_CHANNEL_YPLUS);
95 break;
96 }
97}
98
99static void process(void)
100{
101 int val;
102 switch(touch_state)
103 {
104 case TOUCH_STATE_WAIT:
105 /* a touch has happened, check if it's still valid */
106 if(imx233_lradc_read_touch_detect())
107 enter_state(TOUCH_STATE_MEASURE_X);
108 else
109 {
110 old_touch_detect = false;
111 /* clear detect interrupt */
112 imx233_lradc_clear_touch_detect_irq();
113 }
114 break;
115 case TOUCH_STATE_MEASURE_X:
116 /* read value */
117 val = imx233_lradc_read_channel(touch_chan);
118 /* if value is too far from average, restart */
119 if(nr_samples > 0 && abs(val - touch_x) > DEBOUNCE_THRESHOLD)
120 nr_samples = 0;
121 touch_x = (touch_x * nr_samples + val) / (nr_samples + 1);
122 nr_samples++;
123 /* if we have enough samples, measure Y */
124 if(nr_samples > SAMPLES_THRESHOLD)
125 enter_state(TOUCH_STATE_MEASURE_Y);
126 else
127 imx233_lradc_kick_delay(touch_delay);
128 break;
129 case TOUCH_STATE_MEASURE_Y:
130 /* read value */
131 val = imx233_lradc_read_channel(touch_chan);
132 /* if value is too far from average, restart */
133 if(nr_samples > 0 && abs(val - touch_y) > DEBOUNCE_THRESHOLD)
134 nr_samples = 0;
135 touch_y = (touch_y * nr_samples + val) / (nr_samples + 1);
136 nr_samples++;
137 /* if we have enough samples, verify touch */
138 if(nr_samples > SAMPLES_THRESHOLD)
139 enter_state(TOUCH_STATE_VERIFY);
140 else
141 imx233_lradc_kick_delay(touch_delay);
142 break;
143 case TOUCH_STATE_VERIFY:
144 if(imx233_lradc_read_touch_detect())
145 {
146 old_touch_detect = true;
147 old_touch_x = touch_x;
148 old_touch_y = touch_y;
149 enter_state(TOUCH_STATE_MEASURE_X);
150 }
151 else
152 {
153 old_touch_detect = false;
154 enter_state(TOUCH_STATE_WAIT);
155 }
156 break;
157 }
158}
159
160void INT_TOUCH_DETECT(void)
161{
162 process();
163}
164
165static void touch_channel_irq(int chan)
166{
167 (void) chan;
168 process();
169}
170
171void imx233_touchscreen_init(void)
172{
173 touch_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK);
174 touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK);
175 if(touch_chan < 0 || touch_delay < 0)
176 panicf("Cannot acquire channel and delays for touchscreen measurement");
177 imx233_touchscreen_enable(false);
178}
179
180void imx233_touchscreen_enable(bool enable)
181{
182 enter_state(TOUCH_STATE_WAIT);
183 imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq);
184 imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), enable);
185 imx233_icoll_enable_interrupt(INT_SRC_TOUCH_DETECT, enable);
186}
187
188bool imx233_touchscreen_get_touch(int *raw_x, int *raw_y)
189{
190 if(raw_x) *raw_x = old_touch_x;
191 if(raw_y) *raw_y = old_touch_y;
192 return old_touch_detect;
193}
diff --git a/firmware/target/arm/imx233/touchscreen-imx233.h b/firmware/target/arm/imx233/touchscreen-imx233.h
new file mode 100644
index 0000000000..7933b9063a
--- /dev/null
+++ b/firmware/target/arm/imx233/touchscreen-imx233.h
@@ -0,0 +1,34 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24#ifndef __TOUCHSCREEN_IMX233__
25#define __TOUCHSCREEN_IMX233__
26
27#include "lradc-imx233.h"
28
29void imx233_touchscreen_init(void);
30void imx233_touchscreen_enable(bool enable);
31/* returns true if there is a touch */
32bool imx233_touchscreen_get_touch(int *raw_x, int *raw_y);
33
34#endif /* __TOUCHSCREEN_IMX233__ */ \ No newline at end of file