summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/tcc780x/cowond2/button-cowond2.c
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2008-04-27 13:30:11 +0000
committerRob Purchase <shotofadds@rockbox.org>2008-04-27 13:30:11 +0000
commit18b004b330fe3009b840bfece3f1071395722cfb (patch)
tree7a8f9cfd80cdde14df5929d818487c4b6079db12 /firmware/target/arm/tcc780x/cowond2/button-cowond2.c
parentf79bc5643087413448d6ad03b2a28ebf310f89d0 (diff)
downloadrockbox-18b004b330fe3009b840bfece3f1071395722cfb.tar.gz
rockbox-18b004b330fe3009b840bfece3f1071395722cfb.zip
Enable 'touchscreen areas' on the D2, based on JdGordon's m:robe code. Disable the bootloader debug screen, as that stuff is all available from the Debug menu now.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17257 a1c6a512-1295-4272-9138-f99709370657
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 @@
#include "cpu.h"
#include "button.h"
#include "adc.h"
+#include "pcf50606.h"
+
+#define TOUCH_MARGIN 8
static enum touchpad_mode current_mode = TOUCHPAD_POINT;
+
+static short last_x, last_y;
+static bool touch_available = false;
+
+static int touchpad_buttons[3][3] =
+{
+ {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
+ {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
+ {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT},
+};
+
void touchpad_set_mode(enum touchpad_mode mode)
{
current_mode = mode;
}
+
enum touchpad_mode touchpad_get_mode(void)
{
return current_mode;
}
+void button_set_touch_available(void)
+{
+ touch_available = true;
+}
+
+struct touch_calibration_point {
+ short px_x; /* known pixel value */
+ short px_y;
+ short val_x; /* touchpad value at the known pixel */
+ short val_y;
+};
+
+static struct touch_calibration_point topleft, bottomright;
+
+static int touch_to_pixels(short val_x, short val_y)
+{
+ short x,y;
+
+ x=val_x;
+ y=val_y;
+
+ x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x)
+ / (bottomright.val_x - topleft.val_x) + topleft.px_x;
+
+ y = (y-topleft.val_y)*(bottomright.px_y - topleft.px_y)
+ / (bottomright.val_y - topleft.val_y) + topleft.px_y;
+
+ if (x < 0)
+ x = 0;
+ else if (x>=LCD_WIDTH)
+ x=LCD_WIDTH-1;
+
+ if (y < 0)
+ y = 0;
+ else if (y>=LCD_HEIGHT)
+ y=LCD_HEIGHT-1;
+
+ return (x<<16)|y;
+}
+
void button_init_device(void)
{
- /* Nothing to do */
+ /* Configure GPIOA 4 (POWER) and 8 (HOLD) for input */
+ GPIOA_DIR &= ~0x110;
+
+ /* Configure GPIOB 4 (button pressed) for input */
+ GPIOB_DIR &= ~0x10;
+
+ touch_available = false;
+
+ /* Arbitrary touchscreen calibration */
+ topleft.px_x = 0;
+ topleft.px_y = 0;
+ topleft.val_x = 50;
+ topleft.val_y = 50;
+
+ bottomright.px_x = LCD_WIDTH;
+ bottomright.px_y = LCD_HEIGHT;
+ bottomright.val_x = 980;
+ bottomright.val_y = 980;
}
bool button_hold(void)
@@ -42,10 +114,11 @@ bool button_hold(void)
return (GPIOA & 0x8) ? false : true;
}
-int button_read_device(void)
+int button_read_device(int *data)
{
int btn = BUTTON_NONE;
int adc;
+ *data = 0;
if (GPIOB & 0x4)
{
@@ -69,8 +142,63 @@ int button_read_device(void)
}
}
- /* TODO: Read 'fake' buttons based on touchscreen quadrants.
- Question: How can I read from the PCF chip (I2C) in a tick task? */
+ if (touch_available)
+ {
+ short x = 0, y = 0;
+ static long last_touch = 0;
+ bool send_touch = false;
+
+ int irq_level = disable_irq_save();
+ if (pcf50606_read(PCF5060X_ADCC1) & 0x80) /* Pen down */
+ {
+ unsigned char buf[3];
+ pcf50606_write(PCF5060X_ADCC2, (0xE<<1) | 1); /* ADC start X+Y */
+ pcf50606_read_multiple(PCF5060X_ADCS1, buf, 3);
+ pcf50606_write(PCF5060X_ADCC2, 0); /* ADC stop */
+
+ x = (buf[0] << 2) | (buf[1] & 3);
+ y = (buf[2] << 2) | ((buf[1] & 0xC) >> 2);
+
+ if (TIME_BEFORE(last_touch + HZ/5, current_tick))
+ {
+ if ((x > last_x + TOUCH_MARGIN) ||
+ (x < last_x - TOUCH_MARGIN) ||
+ (y > last_y + TOUCH_MARGIN) ||
+ (y < last_y - TOUCH_MARGIN))
+ {
+ send_touch = true;
+ }
+ }
+ else
+ {
+ send_touch = true;
+ }
+ }
+ restore_irq(irq_level);
+
+ if (send_touch)
+ {
+ last_x = x;
+ last_y = y;
+ *data = touch_to_pixels(x, y);
+ switch (current_mode)
+ {
+ case TOUCHPAD_POINT:
+ btn |= BUTTON_TOUCHPAD;
+ break;
+ case TOUCHPAD_BUTTON:
+ {
+ int px_x = (*data&0xffff0000)>>16;
+ int px_y = (*data&0x0000ffff);
+ btn |= touchpad_buttons[px_y/(LCD_HEIGHT/3)]
+ [px_x/(LCD_WIDTH/3)];
+ break;
+ }
+ }
+ }
+ last_touch = current_tick;
+ touch_available = false;
+ }
if (!(GPIOA & 0x4))
btn |= BUTTON_POWER;