diff --git a/firmware/SOURCES b/firmware/SOURCES index db468335f2..2cb97a241b 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1256,12 +1256,14 @@ target/arm/tcc77x/iaudio7/audio-iaudio7.c drivers/nand_id.c drivers/pcf50606.c drivers/pcf50635.c +drivers/tsc200x.c target/arm/lcd-as-memframe.S target/arm/tcc780x/adc-tcc780x.c target/arm/tcc780x/system-tcc780x.c target/arm/tcc780x/kernel-tcc780x.c target/arm/tcc780x/sd-tcc780x.c target/arm/tcc780x/cowond2/button-cowond2.c +target/arm/tcc780x/cowond2/touchscreen-cowond2.c target/arm/tcc780x/cowond2/lcd-cowond2.c target/arm/tcc780x/cowond2/power-cowond2.c target/arm/tcc780x/cowond2/powermgmt-cowond2.c diff --git a/firmware/drivers/tsc200x.c b/firmware/drivers/tsc200x.c new file mode 100644 index 0000000000..4af8118d26 --- /dev/null +++ b/firmware/drivers/tsc200x.c @@ -0,0 +1,64 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Jonas Aaberg, Rob Purchase + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "tsc200x.h" +#include "cpu.h" +#include "i2c.h" + +#define TSC_SLAVE_ADDR 0x90 +#define TSC_REG_READ_X 0x80 +#define TSC_REG_READ_Y 0x90 + +#ifdef COWON_D2 +#define TSCPRES_GPIO GPIOC +#define TSCPRES_GPIO_DIR GPIOC_DIR +#define TSCPRES_BIT (1<<26) +#endif + +void tsc200x_init(void) +{ + /* Configure GPIOC 26 (TSC pressed) for input */ + TSCPRES_GPIO_DIR &= ~TSCPRES_BIT; +} + +bool tsc200x_is_pressed(void) +{ + return !(TSCPRES_GPIO & TSCPRES_BIT); +} + +bool tsc200x_read_coords(short* x, short* y) +{ + int rc = 0; + unsigned char x_val[2], y_val[2]; + + rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_Y, y_val, 2); + rc |= i2c_readmem(TSC_SLAVE_ADDR, TSC_REG_READ_X, x_val, 2); + + if (rc >= 0) + { + /* Keep the 10 most significant bits */ + *x = ((((short)x_val[0]) << 8) | x_val[1]) >> 6; + *y = ((((short)y_val[0]) << 8) | y_val[1]) >> 6; + return true; + } + + return false; +} diff --git a/firmware/export/tsc200x.h b/firmware/export/tsc200x.h new file mode 100644 index 0000000000..a2705a0553 --- /dev/null +++ b/firmware/export/tsc200x.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Rob Purchase + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _TSC200X_H +#define _TSC200X_H + +#include + +/* The TI TSC2003 and TSC2007 touchscreen controllers are largely compatible, + except the TSC2007 filters coordinates using a "median windowed average". */ + +void tsc200x_init(void); +bool tsc200x_is_pressed(void); +bool tsc200x_read_coords(short* x, short* y); + +#endif /* _TSC200X_H */ diff --git a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c index 30d81fa059..df2ea1f307 100644 --- a/firmware/target/arm/tcc780x/cowond2/button-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/button-cowond2.c @@ -23,94 +23,9 @@ #include "cpu.h" #include "button.h" #include "adc.h" -#include "pcf50606.h" #include "backlight.h" -#include "touchscreen.h" -#include "stdlib.h" - -#define NO_OF_TOUCH_DATA 5 - -static bool touch_available = false; -static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA]; - -/* comparator for qsort */ -static int short_cmp(const void *a, const void *b) -{ - return *(short*)a - *(short*)b; -} - -void button_read_touch() -{ - static long last_touch_interrupt = 0; - static int touch_data_index = 0; - - /* don't read the coordinates when hold is enabled */ - if (button_hold()) return; - - /* put the touchscreen into idle mode */ - pcf50606_write(PCF5060X_ADCC1, 0); - - if (TIME_AFTER(current_tick, last_touch_interrupt + 1)) - { - /* resets the index if the last touch could not be read 5 times */ - touch_data_index = 0; - } - - /* here the touch coordinates are read 5 times */ - /* they will be sorted and the middle one will be used */ - pcf50606_read_adc(PCF5060X_ADC_TSC_XY, - &x[touch_data_index], &y[touch_data_index]); - - touch_data_index++; - - if (touch_data_index > NO_OF_TOUCH_DATA - 1) - { - /* coordinates 5 times read */ - touch_available = true; - touch_data_index = 0; - } - else - { - /* put the touchscreen back into the interrupt mode */ - pcf50606_write(PCF5060X_ADCC1, 1); - } - last_touch_interrupt = current_tick; -} - -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; - - 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; -} +#include "touchscreen-target.h" +#include void button_init_device(void) { @@ -120,18 +35,7 @@ void button_init_device(void) /* 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; + touchscreen_init_device(); } bool button_hold(void) @@ -147,8 +51,6 @@ int button_read_device(int *data) static bool hold_button = false; bool hold_button_old; - static bool touch_hold = false; - static long last_touch = 0; *data = old_data; @@ -185,40 +87,7 @@ int button_read_device(int *data) } } - if (touch_available || touch_hold) - { - short x_touch, y_touch; - static short last_x = 0, last_y = 0; - - if (touch_hold) - { - /* get rid of very fast unintended double touches */ - x_touch = last_x; - y_touch = last_y; - } - else - { - /* sort the 5 data taken and use the median value */ - qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); - qsort(y, NO_OF_TOUCH_DATA, sizeof(short), 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); - } - - if (TIME_AFTER(current_tick, last_touch + 10)) - { - /* put the touchscreen back into interrupt mode */ - touch_hold = false; - pcf50606_write(PCF5060X_ADCC1, 1); - } + btn |= touchscreen_read_device(data, &old_data); if (!(GPIOA & 0x4)) btn |= BUTTON_POWER; diff --git a/firmware/target/arm/tcc780x/cowond2/button-target.h b/firmware/target/arm/tcc780x/cowond2/button-target.h index ce6e2884a9..7d3736fe67 100644 --- a/firmware/target/arm/tcc780x/cowond2/button-target.h +++ b/firmware/target/arm/tcc780x/cowond2/button-target.h @@ -30,7 +30,6 @@ bool button_hold(void); void button_init_device(void); int button_read_device(int *data); -void button_read_touch(void); /* Main unit's buttons */ #define BUTTON_POWER 0x00000001 diff --git a/firmware/target/arm/tcc780x/cowond2/power-cowond2.c b/firmware/target/arm/tcc780x/cowond2/power-cowond2.c index d5f4ec9768..dfd692ecab 100644 --- a/firmware/target/arm/tcc780x/cowond2/power-cowond2.c +++ b/firmware/target/arm/tcc780x/cowond2/power-cowond2.c @@ -25,6 +25,7 @@ #include "pcf50606.h" #include "pcf50635.h" #include "button-target.h" +#include "touchscreen-target.h" #include "tuner.h" #include "backlight-target.h" #include "powermgmt.h" @@ -101,7 +102,7 @@ void EXT3(void) if (data[2] & 0x08) { /* Touchscreen event, do something about it */ - button_read_touch(); + touchscreen_handle_device_irq(); } } #endif diff --git a/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c b/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c new file mode 100644 index 0000000000..d6483886ad --- /dev/null +++ b/firmware/target/arm/tcc780x/cowond2/touchscreen-cowond2.c @@ -0,0 +1,233 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Rob Purchase, Carsten Schreiter, Jonas Aaberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include "button.h" +#include "pcf50606.h" +#include "touchscreen.h" +#include "stdlib.h" +#include "power-target.h" +#include "tsc200x.h" + +#define NO_OF_TOUCH_DATA 5 + +static bool touch_available = false; + +static short x[NO_OF_TOUCH_DATA], y[NO_OF_TOUCH_DATA]; + +/* comparator for qsort */ +static int short_cmp(const void *a, const void *b) +{ + return *(short*)a - *(short*)b; +} + +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; + + 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; +} + +static int touchscreen_read_pcf50606(int *data, int *old_data) +{ + int btn = BUTTON_NONE; + static bool touch_hold = false; + static long last_touch = 0; + + if (touch_available || touch_hold) + { + short x_touch, y_touch; + static short last_x = 0, last_y = 0; + + if (touch_hold) + { + /* get rid of very fast unintended double touches */ + x_touch = last_x; + y_touch = last_y; + } + else + { + /* sort the 5 data taken and use the median value */ + qsort(x, NO_OF_TOUCH_DATA, sizeof(short), short_cmp); + qsort(y, NO_OF_TOUCH_DATA, sizeof(short), 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); + } + + if (TIME_AFTER(current_tick, last_touch + 10)) + { + /* put the touchscreen back into interrupt mode */ + touch_hold = false; + pcf50606_write(PCF5060X_ADCC1, 1); + } + + return btn; +} + +static int touchscreen_read_tsc200x(int *data, int *old_data) +{ + int btn = BUTTON_NONE; + short x_touch, y_touch; + + static long last_read = 0; + static int last_btn = BUTTON_NONE; + + /* Don't read hw every check button round. I2C is slow + * and man is even slower. */ + if (TIME_BEFORE(current_tick, last_read + 10)) + { + *data = *old_data; + return last_btn; + } + + if (tsc200x_is_pressed()) + { + if (tsc200x_read_coords(&x_touch, &y_touch)) + { + *old_data = *data = touch_to_pixels(x_touch, y_touch); + + btn = touchscreen_to_pixels((*data & 0xffff0000) >> 16, + (*data & 0x0000ffff), + data); + + last_btn = btn; + } + } + + last_read = current_tick; + + return btn; +} + +void touchscreen_init_device(void) +{ + touch_available = false; + + /* Arbitrary touchscreen calibration */ + topleft.px_x = 0; + topleft.px_y = 0; + + bottomright.px_x = LCD_WIDTH; + bottomright.px_y = LCD_HEIGHT; + + topleft.val_x = 50; + topleft.val_y = 50; + + bottomright.val_x = 980; + bottomright.val_y = 980; + + if (get_pmu_type() != PCF50606) + { + tsc200x_init(); + } +} + +void touchscreen_handle_device_irq(void) +{ + static long last_touch_interrupt = 0; + static int touch_data_index = 0; + + /* don't read the coordinates when hold is enabled */ + if (button_hold()) return; + + /* put the touchscreen into idle mode */ + pcf50606_write(PCF5060X_ADCC1, 0); + + if (TIME_AFTER(current_tick, last_touch_interrupt + 1)) + { + /* resets the index if the last touch could not be read 5 times */ + touch_data_index = 0; + } + + /* here the touch coordinates are read 5 times */ + /* they will be sorted and the middle one will be used */ + pcf50606_read_adc(PCF5060X_ADC_TSC_XY, + &x[touch_data_index], &y[touch_data_index]); + + touch_data_index++; + + if (touch_data_index > NO_OF_TOUCH_DATA - 1) + { + /* coordinates 5 times read */ + touch_available = true; + touch_data_index = 0; + } + else + { + /* put the touchscreen back into the interrupt mode */ + pcf50606_write(PCF5060X_ADCC1, 1); + } + last_touch_interrupt = current_tick; +} + + +int touchscreen_read_device(int *data, int *old_data) +{ + int btn; + + if (get_pmu_type() == PCF50606) + btn = touchscreen_read_pcf50606(data, old_data); + else + btn = touchscreen_read_tsc200x(data, old_data); + + return btn; +} diff --git a/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h b/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h new file mode 100644 index 0000000000..be18aed723 --- /dev/null +++ b/firmware/target/arm/tcc780x/cowond2/touchscreen-target.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2009 by Jonas Aaberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _TOUCHSCREEN_TARGET_H_ +#define _TOUCHSCREEN_TARGET_H_ + +#include "config.h" + +void touchscreen_init_device(void); +int touchscreen_read_device(int *data, int *old_data); +void touchscreen_handle_device_irq(void); + +#endif