Index: firmware/target/arm/tcc780x/cowond2/button-cowond2.c =================================================================== --- firmware/target/arm/tcc780x/cowond2/button-cowond2.c (Revision 22826) +++ firmware/target/arm/tcc780x/cowond2/button-cowond2.c (Arbeitskopie) @@ -26,15 +26,65 @@ #include "pcf50606.h" #include "backlight.h" #include "touchscreen.h" +#include "stdlib.h" -#define TOUCH_MARGIN 8 +#define NO_OF_TOUCH_DATA 5 -static short last_x, last_y; static bool touch_available = false; +static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA]; -void button_set_touch_available(void) +static int cmp(const void *val_1, const void *val_2) { + if( *(int *)val_1 < *(int *)val_2 ) + return -1; + else if( *(int *)val_1 > *(int *)val_2) + return 1; + else + return 0; /* values are equal */ +} + +void button_set_touch_available() { - touch_available = true; + static long last_touch_interrupt = 0; + static int touch_data_index = 0; + + pcf50606_write(PCF5060X_ADCC1, (0x01) & 0); + /* put the touchscreen into the idle mode */ + unsigned char buf[3]; + + /* here the touch coordinates are read 5 times */ + /* they will be sorted and the middle one will be used */ + pcf50606_write(PCF5060X_ADCC2, (0xE<<1) | 1); /* ADC start X+Y */ + + do { + buf[1] = pcf50606_read(PCF5060X_ADCS2); + } while (!(buf[1] & 0x80)); /* Busy wait on ADCRDY flag */ + + buf[0] = pcf50606_read(PCF5060X_ADCS1); + buf[2] = pcf50606_read(PCF5060X_ADCS3); + + pcf50606_write(PCF5060X_ADCC2, 0); /* ADC stop */ + + if (current_tick > last_touch_interrupt + 1) + { /* resets the index if the last touch could not be read 5 times */ + touch_data_index = 0; + } + + x[touch_data_index] = (buf[0] << 2) | (buf[1] & 3); + y[touch_data_index] = (buf[2] << 2) | ((buf[1] & 0xC) >> 2); + + touch_data_index++; + + if (touch_data_index > NO_OF_TOUCH_DATA - 1) + { /* coordinates 5 timese read */ + touch_available = true; + touch_data_index = 0; + } + else + { + pcf50606_write(PCF5060X_ADCC1, (0x01) | 1); + /* put the touchscreen back into the interrupt mode */ + } + last_touch_interrupt = current_tick; } struct touch_calibration_point { @@ -107,7 +157,9 @@ static bool hold_button = false; bool hold_button_old; - + static bool touch_hold = false; + static long last_touch = 0; + *data = old_data; hold_button_old = hold_button; @@ -143,60 +195,37 @@ } } - if (touch_available) + if (touch_available || touch_hold) { - short x = 0, y = 0; - static long last_touch = 0; - bool send_touch = false; + short x_touch, y_touch; + static short last_x = 0, last_y = 0; - 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 */ - - do { - buf[1] = pcf50606_read(PCF5060X_ADCS2); - } while (!(buf[1] & 0x80)); /* Busy wait 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; - } - } - else - { - send_touch = true; - } + if (touch_hold) + { /* this is to get rid of very fast unintended double touches */ + x_touch = last_x; + y_touch = last_y; } - restore_irq(irq_level); - - if (send_touch) - { - last_x = x; - last_y = y; - old_data = *data = touch_to_pixels(x, y); - btn |= touchscreen_to_pixels((*data&0xffff0000)>>16, - (*data&0x0000ffff), - data); + else + { /* sort the 5 data taken and finally use the meridian */ + qsort(x, NO_OF_TOUCH_DATA, sizeof(short), cmp); + qsort(y, NO_OF_TOUCH_DATA, sizeof(short), cmp); + x_touch = last_x = x[(NO_OF_TOUCH_DATA - 1)/2]; + y_touch = last_y = y[(NO_OF_TOUCH_DATA - 1)/2]; + last_touch = current_tick; + touch_hold = true; + touch_available = false; } + old_data = *data = touch_to_pixels(x_touch, y_touch); + btn |= touchscreen_to_pixels((*data&0xffff0000)>>16, + (*data&0x0000ffff), + data); + } - last_touch = current_tick; - touch_available = false; + if (current_tick > last_touch + 10) + { + touch_hold = false; + pcf50606_write(PCF5060X_ADCC1, (0x01) | 1); + /* put the touchscreen back into the interrupt mode */ } if (!(GPIOA & 0x4)) Index: firmware/drivers/touchscreen.c =================================================================== --- firmware/drivers/touchscreen.c (Revision 22826) +++ firmware/drivers/touchscreen.c (Arbeitskopie) @@ -116,14 +116,38 @@ /* TODO: add jitter (and others) filter */ int touchscreen_to_pixels(int x, int y, int *data) { + #define BUTTON_MARGIN_X LCD_WIDTH * 0.05 + #define BUTTON_MARGIN_Y LCD_HEIGHT * 0.05 + x &= 0xFFFF; y &= 0xFFFF; map_pixels(&x, &y); if(current_mode == TOUCHSCREEN_BUTTON) - return touchscreen_buttons[y / (LCD_HEIGHT/3)] - [x / (LCD_WIDTH/3) ]; + { + int column = 0, row = 0; + + if (x < LCD_WIDTH/3 - BUTTON_MARGIN_X) + column = 0; + else if (x > LCD_WIDTH/3 + BUTTON_MARGIN_X && + x < 2*LCD_WIDTH/3 - BUTTON_MARGIN_X) + column = 1; + else if (x > 2*LCD_WIDTH/3 + BUTTON_MARGIN_X) + column = 2; + else + return BUTTON_NONE; + + if (y < LCD_HEIGHT/3 - BUTTON_MARGIN_Y) + row = 0; + else if (y > LCD_HEIGHT/3 + BUTTON_MARGIN_Y && + y < 2*LCD_HEIGHT/3 - BUTTON_MARGIN_Y) + row = 1; + else if (y > 2*LCD_HEIGHT/3 + BUTTON_MARGIN_Y) + row = 2; + else return BUTTON_NONE; + return touchscreen_buttons[row][column]; + } else { *data = (x << 16 | y);