diff options
Diffstat (limited to 'firmware/target/arm/tcc780x/cowond2/button-cowond2.c')
-rw-r--r-- | firmware/target/arm/tcc780x/cowond2/button-cowond2.c | 136 |
1 files changed, 132 insertions, 4 deletions
diff --git a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c index ea37893f40..c0672f1c3a 100644 --- a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c | |||
@@ -21,20 +21,92 @@ | |||
21 | #include "cpu.h" | 21 | #include "cpu.h" |
22 | #include "button.h" | 22 | #include "button.h" |
23 | #include "adc.h" | 23 | #include "adc.h" |
24 | #include "pcf50606.h" | ||
25 | |||
26 | #define TOUCH_MARGIN 8 | ||
24 | 27 | ||
25 | static enum touchpad_mode current_mode = TOUCHPAD_POINT; | 28 | static enum touchpad_mode current_mode = TOUCHPAD_POINT; |
29 | |||
30 | static short last_x, last_y; | ||
31 | static bool touch_available = false; | ||
32 | |||
33 | static int touchpad_buttons[3][3] = | ||
34 | { | ||
35 | {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT}, | ||
36 | {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT}, | ||
37 | {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT}, | ||
38 | }; | ||
39 | |||
26 | void touchpad_set_mode(enum touchpad_mode mode) | 40 | void touchpad_set_mode(enum touchpad_mode mode) |
27 | { | 41 | { |
28 | current_mode = mode; | 42 | current_mode = mode; |
29 | } | 43 | } |
44 | |||
30 | enum touchpad_mode touchpad_get_mode(void) | 45 | enum touchpad_mode touchpad_get_mode(void) |
31 | { | 46 | { |
32 | return current_mode; | 47 | return current_mode; |
33 | } | 48 | } |
34 | 49 | ||
50 | void button_set_touch_available(void) | ||
51 | { | ||
52 | touch_available = true; | ||
53 | } | ||
54 | |||
55 | struct touch_calibration_point { | ||
56 | short px_x; /* known pixel value */ | ||
57 | short px_y; | ||
58 | short val_x; /* touchpad value at the known pixel */ | ||
59 | short val_y; | ||
60 | }; | ||
61 | |||
62 | static struct touch_calibration_point topleft, bottomright; | ||
63 | |||
64 | static int touch_to_pixels(short val_x, short val_y) | ||
65 | { | ||
66 | short x,y; | ||
67 | |||
68 | x=val_x; | ||
69 | y=val_y; | ||
70 | |||
71 | x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x) | ||
72 | / (bottomright.val_x - topleft.val_x) + topleft.px_x; | ||
73 | |||
74 | y = (y-topleft.val_y)*(bottomright.px_y - topleft.px_y) | ||
75 | / (bottomright.val_y - topleft.val_y) + topleft.px_y; | ||
76 | |||
77 | if (x < 0) | ||
78 | x = 0; | ||
79 | else if (x>=LCD_WIDTH) | ||
80 | x=LCD_WIDTH-1; | ||
81 | |||
82 | if (y < 0) | ||
83 | y = 0; | ||
84 | else if (y>=LCD_HEIGHT) | ||
85 | y=LCD_HEIGHT-1; | ||
86 | |||
87 | return (x<<16)|y; | ||
88 | } | ||
89 | |||
35 | void button_init_device(void) | 90 | void button_init_device(void) |
36 | { | 91 | { |
37 | /* Nothing to do */ | 92 | /* Configure GPIOA 4 (POWER) and 8 (HOLD) for input */ |
93 | GPIOA_DIR &= ~0x110; | ||
94 | |||
95 | /* Configure GPIOB 4 (button pressed) for input */ | ||
96 | GPIOB_DIR &= ~0x10; | ||
97 | |||
98 | touch_available = false; | ||
99 | |||
100 | /* Arbitrary touchscreen calibration */ | ||
101 | topleft.px_x = 0; | ||
102 | topleft.px_y = 0; | ||
103 | topleft.val_x = 50; | ||
104 | topleft.val_y = 50; | ||
105 | |||
106 | bottomright.px_x = LCD_WIDTH; | ||
107 | bottomright.px_y = LCD_HEIGHT; | ||
108 | bottomright.val_x = 980; | ||
109 | bottomright.val_y = 980; | ||
38 | } | 110 | } |
39 | 111 | ||
40 | bool button_hold(void) | 112 | bool button_hold(void) |
@@ -42,10 +114,11 @@ bool button_hold(void) | |||
42 | return (GPIOA & 0x8) ? false : true; | 114 | return (GPIOA & 0x8) ? false : true; |
43 | } | 115 | } |
44 | 116 | ||
45 | int button_read_device(void) | 117 | int button_read_device(int *data) |
46 | { | 118 | { |
47 | int btn = BUTTON_NONE; | 119 | int btn = BUTTON_NONE; |
48 | int adc; | 120 | int adc; |
121 | *data = 0; | ||
49 | 122 | ||
50 | if (GPIOB & 0x4) | 123 | if (GPIOB & 0x4) |
51 | { | 124 | { |
@@ -69,8 +142,63 @@ int button_read_device(void) | |||
69 | } | 142 | } |
70 | } | 143 | } |
71 | 144 | ||
72 | /* TODO: Read 'fake' buttons based on touchscreen quadrants. | 145 | if (touch_available) |
73 | Question: How can I read from the PCF chip (I2C) in a tick task? */ | 146 | { |
147 | short x = 0, y = 0; | ||
148 | static long last_touch = 0; | ||
149 | bool send_touch = false; | ||
150 | |||
151 | int irq_level = disable_irq_save(); | ||
152 | if (pcf50606_read(PCF5060X_ADCC1) & 0x80) /* Pen down */ | ||
153 | { | ||
154 | unsigned char buf[3]; | ||
155 | pcf50606_write(PCF5060X_ADCC2, (0xE<<1) | 1); /* ADC start X+Y */ | ||
156 | pcf50606_read_multiple(PCF5060X_ADCS1, buf, 3); | ||
157 | pcf50606_write(PCF5060X_ADCC2, 0); /* ADC stop */ | ||
158 | |||
159 | x = (buf[0] << 2) | (buf[1] & 3); | ||
160 | y = (buf[2] << 2) | ((buf[1] & 0xC) >> 2); | ||
161 | |||
162 | if (TIME_BEFORE(last_touch + HZ/5, current_tick)) | ||
163 | { | ||
164 | if ((x > last_x + TOUCH_MARGIN) || | ||
165 | (x < last_x - TOUCH_MARGIN) || | ||
166 | (y > last_y + TOUCH_MARGIN) || | ||
167 | (y < last_y - TOUCH_MARGIN)) | ||
168 | { | ||
169 | send_touch = true; | ||
170 | } | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | send_touch = true; | ||
175 | } | ||
176 | } | ||
177 | restore_irq(irq_level); | ||
178 | |||
179 | if (send_touch) | ||
180 | { | ||
181 | last_x = x; | ||
182 | last_y = y; | ||
183 | *data = touch_to_pixels(x, y); | ||
184 | switch (current_mode) | ||
185 | { | ||
186 | case TOUCHPAD_POINT: | ||
187 | btn |= BUTTON_TOUCHPAD; | ||
188 | break; | ||
189 | case TOUCHPAD_BUTTON: | ||
190 | { | ||
191 | int px_x = (*data&0xffff0000)>>16; | ||
192 | int px_y = (*data&0x0000ffff); | ||
193 | btn |= touchpad_buttons[px_y/(LCD_HEIGHT/3)] | ||
194 | [px_x/(LCD_WIDTH/3)]; | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | last_touch = current_tick; | ||
200 | touch_available = false; | ||
201 | } | ||
74 | 202 | ||
75 | if (!(GPIOA & 0x4)) | 203 | if (!(GPIOA & 0x4)) |
76 | btn |= BUTTON_POWER; | 204 | btn |= BUTTON_POWER; |