diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2012-05-19 13:42:49 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2012-05-19 16:10:52 +0200 |
commit | 85d5c19347c1665b765708cdb67f1d996c7f7fa4 (patch) | |
tree | 14cc20dbd694e408ece18c7d9788c2a74cef042e | |
parent | 247e611f4945d048f280471d78b7b83a96b35454 (diff) | |
download | rockbox-85d5c19347c1665b765708cdb67f1d996c7f7fa4.tar.gz rockbox-85d5c19347c1665b765708cdb67f1d996c7f7fa4.zip |
imx233: add touchscreen driver
Change-Id: I406076d110e33cdae871222191d82262fabcf16a
-rw-r--r-- | firmware/SOURCES | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/touchscreen-imx233.c | 193 | ||||
-rw-r--r-- | firmware/target/arm/imx233/touchscreen-imx233.h | 34 |
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 | |||
518 | target/arm/imx233/pwm-imx233.c | 518 | target/arm/imx233/pwm-imx233.c |
519 | target/arm/imx233/rtc-imx233.c | 519 | target/arm/imx233/rtc-imx233.c |
520 | target/arm/imx233/dcp-imx233.c | 520 | target/arm/imx233/dcp-imx233.c |
521 | # ifdef HAVE_TOUCHSCREEN | ||
522 | target/arm/imx233/touchscreen-imx233.c | ||
523 | # endif | ||
521 | #ifndef BOOTLOADER | 524 | #ifndef BOOTLOADER |
522 | target/arm/imx233/debug-imx233.c | 525 | target/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 | |||
44 | enum 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 | |||
55 | static enum touch_state_t touch_state; | ||
56 | static int touch_chan = -1; | ||
57 | static int touch_delay = -1; | ||
58 | static 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. */ | ||
61 | static bool old_touch_detect = false; | ||
62 | static int old_touch_x, old_touch_y; | ||
63 | |||
64 | static 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 | |||
77 | static 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 | |||
99 | static 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 | |||
160 | void INT_TOUCH_DETECT(void) | ||
161 | { | ||
162 | process(); | ||
163 | } | ||
164 | |||
165 | static void touch_channel_irq(int chan) | ||
166 | { | ||
167 | (void) chan; | ||
168 | process(); | ||
169 | } | ||
170 | |||
171 | void 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 | |||
180 | void 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 | |||
188 | bool 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 | |||
29 | void imx233_touchscreen_init(void); | ||
30 | void imx233_touchscreen_enable(bool enable); | ||
31 | /* returns true if there is a touch */ | ||
32 | bool imx233_touchscreen_get_touch(int *raw_x, int *raw_y); | ||
33 | |||
34 | #endif /* __TOUCHSCREEN_IMX233__ */ \ No newline at end of file | ||