summaryrefslogtreecommitdiff
path: root/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/tcc780x/cowond2/button-cowond2.c')
-rw-r--r--firmware/target/arm/tcc780x/cowond2/button-cowond2.c136
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
25static enum touchpad_mode current_mode = TOUCHPAD_POINT; 28static enum touchpad_mode current_mode = TOUCHPAD_POINT;
29
30static short last_x, last_y;
31static bool touch_available = false;
32
33static 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
26void touchpad_set_mode(enum touchpad_mode mode) 40void touchpad_set_mode(enum touchpad_mode mode)
27{ 41{
28 current_mode = mode; 42 current_mode = mode;
29} 43}
44
30enum touchpad_mode touchpad_get_mode(void) 45enum touchpad_mode touchpad_get_mode(void)
31{ 46{
32 return current_mode; 47 return current_mode;
33} 48}
34 49
50void button_set_touch_available(void)
51{
52 touch_available = true;
53}
54
55struct 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
62static struct touch_calibration_point topleft, bottomright;
63
64static 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
35void button_init_device(void) 90void 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
40bool button_hold(void) 112bool 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
45int button_read_device(void) 117int 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;