diff options
author | Rob Purchase <shotofadds@rockbox.org> | 2008-04-27 13:30:11 +0000 |
---|---|---|
committer | Rob Purchase <shotofadds@rockbox.org> | 2008-04-27 13:30:11 +0000 |
commit | 18b004b330fe3009b840bfece3f1071395722cfb (patch) | |
tree | 7a8f9cfd80cdde14df5929d818487c4b6079db12 /firmware/target/arm/tcc780x/cowond2/button-cowond2.c | |
parent | f79bc5643087413448d6ad03b2a28ebf310f89d0 (diff) | |
download | rockbox-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.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 @@ #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; |