Index: firmware/target/arm/tcc780x/cowond2/button-cowond2.c =================================================================== --- firmware/target/arm/tcc780x/cowond2/button-cowond2.c (revision 19934) +++ firmware/target/arm/tcc780x/cowond2/button-cowond2.c (working copy) @@ -1,4 +1,4 @@ -/*************************************************************************** +/**************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / @@ -17,7 +17,7 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - ****************************************************************************/ + ***************************************************************************/ #include "config.h" #include "cpu.h" @@ -30,7 +30,6 @@ static enum touchscreen_mode current_mode = TOUCHSCREEN_POINT; -static short last_x, last_y; static bool touch_available = false; static int touchscreen_buttons[3][3] = @@ -55,38 +54,15 @@ touch_available = true; } -struct touch_calibration_point { - short px_x; /* known pixel value */ - short px_y; - short val_x; /* touchscreen 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; + /* Empiric touchscreen calibration */ - x = (x-topleft.val_x)*(bottomright.px_x - topleft.px_x) - / (bottomright.val_x - topleft.val_x) + topleft.px_x; + x = val_x / 3.1; + y = val_y / 4.2; - 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; } @@ -94,22 +70,11 @@ { /* 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; + touch_available = false; } bool button_hold(void) @@ -121,8 +86,8 @@ { int btn = BUTTON_NONE; int adc; - *data = 0; - + *data = 0; + if (button_hold()) return BUTTON_NONE; if (GPIOB & 0x4) @@ -145,71 +110,124 @@ } else if (adc < 0x200) { btn |= BUTTON_MENU; } - } + } if (touch_available) { short x = 0, y = 0; + static long last_touch = 0; - bool send_touch = false; + /* Used for touchscreen input */ + int px_x, px_y; + /* Used for touchscreen errors compensation */ + static int last_px_x = -1, last_px_y = -1; + static int last_wrong_px_x = -1, last_wrong_px_y = -1; + 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); + + do { + buf[1] = pcf50606_read(PCF5060X_ADCS2); + } while (!(buf[1] & 0x80)); /* Busy wait cycle on ADCRDY flag */ + + buf[0] = pcf50606_read(PCF5060X_ADCS1); + buf[2] = pcf50606_read(PCF5060X_ADCS3); + 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; + *data = touch_to_pixels(x, y); + px_x = ((*data & 0xffff0000) >> 16) / (LCD_WIDTH / 3); + px_y = (*data & 0x0000ffff) / (LCD_HEIGHT / 3); + + if (last_px_x == -1 && + last_px_y == -1) { + + last_px_x = px_x; + last_px_y = px_y; + + } + + if (!TIME_BEFORE(last_touch + HZ / 8, current_tick)) { + /* Very fast Touchscreen presses are handled here */ + + if ((px_x == last_px_x) && (px_y == last_px_y)) { + last_wrong_px_x = -1; + last_wrong_px_y = -1; + + last_px_x = px_x; + last_px_y = px_y; } + + if(px_x != last_px_x) { /* Error on x compensation */ + if(px_x == last_wrong_px_x) { /* Not an error */ + last_wrong_px_x = -1; + last_px_x = px_x; + } + + else { + last_wrong_px_x = px_x; + px_x = last_px_x; /* Not sure if it's an error so we use the old value one more time */ + } + } + + if (px_y != last_px_y) { /* Error on y compensation */ + if (px_y == last_wrong_px_y) { /* Not an error, we can use the new value */ + last_wrong_px_y = -1; + last_px_y = px_y; + } + else { + last_wrong_px_y = px_y; + px_y = last_px_y; /* Not sure if it's an error so we use the old value one more time */ + } + } + + px_x = last_px_x; + px_y = last_px_y; + } - else - { - send_touch = true; - } - } - restore_irq(irq_level); - if (send_touch) - { - last_x = x; - last_y = y; - *data = touch_to_pixels(x, y); + last_px_x = px_x; + last_px_y = px_y; + switch (current_mode) { case TOUCHSCREEN_POINT: btn |= BUTTON_TOUCHSCREEN; break; case TOUCHSCREEN_BUTTON: - { - int px_x = (*data&0xffff0000)>>16; - int px_y = (*data&0x0000ffff); - btn |= touchscreen_buttons[px_y/(LCD_HEIGHT/3)] - [px_x/(LCD_WIDTH/3)]; + btn |= touchscreen_buttons[px_y][px_x]; break; - } } + } + last_touch = current_tick; touch_available = false; + + restore_irq(irq_level); + } if (!(GPIOA & 0x4)) btn |= BUTTON_POWER; - + if(btn & BUTTON_TOUCHSCREEN && !is_backlight_on(true)) - *data = 0; - + *data = 0; + + if(btn == (BUTTON_MENU|BUTTON_MINUS)) + touchscreen_set_mode((touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_POINT : TOUCHSCREEN_POINT)); /* a little tricky but it does the job well for now */ + + if(btn == (BUTTON_PLUS|BUTTON_MENU)) + touchscreen_set_mode((touchscreen_get_mode() == TOUCHSCREEN_BUTTON ? TOUCHSCREEN_BUTTON: TOUCHSCREEN_BUTTON)); /* a little tricky but it does the job well for now */ + return btn; } +