imx233: add touchscreen driver
Change-Id: I406076d110e33cdae871222191d82262fabcf16a
This commit is contained in:
parent
247e611f49
commit
85d5c19347
3 changed files with 230 additions and 0 deletions
|
@ -518,6 +518,9 @@ target/arm/imx233/lradc-imx233.c
|
|||
target/arm/imx233/pwm-imx233.c
|
||||
target/arm/imx233/rtc-imx233.c
|
||||
target/arm/imx233/dcp-imx233.c
|
||||
# ifdef HAVE_TOUCHSCREEN
|
||||
target/arm/imx233/touchscreen-imx233.c
|
||||
# endif
|
||||
#ifndef BOOTLOADER
|
||||
target/arm/imx233/debug-imx233.c
|
||||
#endif
|
||||
|
|
193
firmware/target/arm/imx233/touchscreen-imx233.c
Normal file
193
firmware/target/arm/imx233/touchscreen-imx233.c
Normal file
|
@ -0,0 +1,193 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 by Amaury Pouly
|
||||
*
|
||||
* Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
|
||||
* and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
|
||||
*
|
||||
* 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 "touchscreen-imx233.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
/* Description:
|
||||
* the driver basically has 2 modes:
|
||||
* - wait mode: use the hardware touch detect mechanism to wait for an edge
|
||||
* - measurement mode: use pull up/down and adc to measure X/Y
|
||||
* In measurement mode, we start by measuring X then Y then we check if
|
||||
* the hardware still detect a touch. When no touch is detected anymore, we
|
||||
* go back to wait mode.
|
||||
* For each axis, we handle stabilization by repeatedly measuring the position
|
||||
* until it is stable. We consider a set of measures stable when
|
||||
* no measure is further away from the average than DEBOUNCE_THRESHOLD and
|
||||
* we have at least SAMPLES_THRESHOLD measures. This avoids using magic
|
||||
* timing constants specific to the touchscreen stabilization time and
|
||||
* it is much more robust.
|
||||
*
|
||||
* Inspired by linux touchscreen driver for the stmp37xx.
|
||||
*/
|
||||
|
||||
enum touch_state_t
|
||||
{
|
||||
TOUCH_STATE_WAIT, /* wait for touch */
|
||||
TOUCH_STATE_MEASURE_X, /* measure x */
|
||||
TOUCH_STATE_MEASURE_Y, /* measure y */
|
||||
TOUCH_STATE_VERIFY, /* verify touch */
|
||||
};
|
||||
|
||||
#define DEBOUNCE_THRESHOLD 100
|
||||
#define SAMPLES_THRESHOLD 4
|
||||
|
||||
static enum touch_state_t touch_state;
|
||||
static int touch_chan = -1;
|
||||
static int touch_delay = -1;
|
||||
static int touch_x, touch_y, nr_samples;
|
||||
/* once a touch is confirmed, the parameters are copied to these value for
|
||||
* instant readout by button code. */
|
||||
static bool old_touch_detect = false;
|
||||
static int old_touch_x, old_touch_y;
|
||||
|
||||
static void kick_measure(bool pull_x, bool pull_y, bool detect, int lradc_phys)
|
||||
{
|
||||
/* setup measurement: x- pull down and x+ pull up */
|
||||
imx233_lradc_setup_touch(pull_x, pull_y, pull_x, pull_y, detect);
|
||||
imx233_lradc_enable_touch_detect_irq(false);
|
||||
imx233_lradc_enable_channel_irq(touch_chan, true);
|
||||
/* measure channel, no accumulation */
|
||||
imx233_lradc_setup_channel(touch_chan, false, false, 0, lradc_phys);
|
||||
/* use a delay */
|
||||
imx233_lradc_setup_delay(touch_delay, 1 << touch_chan, 0, 0, 8);
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
}
|
||||
|
||||
static void enter_state(enum touch_state_t state)
|
||||
{
|
||||
touch_state = state;
|
||||
switch(state)
|
||||
{
|
||||
case TOUCH_STATE_WAIT:
|
||||
imx233_lradc_setup_touch(false, false, false, false, true);
|
||||
imx233_lradc_enable_channel_irq(touch_chan, false);
|
||||
imx233_lradc_enable_touch_detect_irq(true);
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_X:
|
||||
kick_measure(true, false, false, HW_LRADC_CHANNEL_YPLUS);
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_Y:
|
||||
kick_measure(false, true, false, HW_LRADC_CHANNEL_XPLUS);
|
||||
break;
|
||||
case TOUCH_STATE_VERIFY:
|
||||
kick_measure(false, false, true, HW_LRADC_CHANNEL_YPLUS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void process(void)
|
||||
{
|
||||
int val;
|
||||
switch(touch_state)
|
||||
{
|
||||
case TOUCH_STATE_WAIT:
|
||||
/* a touch has happened, check if it's still valid */
|
||||
if(imx233_lradc_read_touch_detect())
|
||||
enter_state(TOUCH_STATE_MEASURE_X);
|
||||
else
|
||||
{
|
||||
old_touch_detect = false;
|
||||
/* clear detect interrupt */
|
||||
imx233_lradc_clear_touch_detect_irq();
|
||||
}
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_X:
|
||||
/* read value */
|
||||
val = imx233_lradc_read_channel(touch_chan);
|
||||
/* if value is too far from average, restart */
|
||||
if(nr_samples > 0 && abs(val - touch_x) > DEBOUNCE_THRESHOLD)
|
||||
nr_samples = 0;
|
||||
touch_x = (touch_x * nr_samples + val) / (nr_samples + 1);
|
||||
nr_samples++;
|
||||
/* if we have enough samples, measure Y */
|
||||
if(nr_samples > SAMPLES_THRESHOLD)
|
||||
enter_state(TOUCH_STATE_MEASURE_Y);
|
||||
else
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
break;
|
||||
case TOUCH_STATE_MEASURE_Y:
|
||||
/* read value */
|
||||
val = imx233_lradc_read_channel(touch_chan);
|
||||
/* if value is too far from average, restart */
|
||||
if(nr_samples > 0 && abs(val - touch_y) > DEBOUNCE_THRESHOLD)
|
||||
nr_samples = 0;
|
||||
touch_y = (touch_y * nr_samples + val) / (nr_samples + 1);
|
||||
nr_samples++;
|
||||
/* if we have enough samples, verify touch */
|
||||
if(nr_samples > SAMPLES_THRESHOLD)
|
||||
enter_state(TOUCH_STATE_VERIFY);
|
||||
else
|
||||
imx233_lradc_kick_delay(touch_delay);
|
||||
break;
|
||||
case TOUCH_STATE_VERIFY:
|
||||
if(imx233_lradc_read_touch_detect())
|
||||
{
|
||||
old_touch_detect = true;
|
||||
old_touch_x = touch_x;
|
||||
old_touch_y = touch_y;
|
||||
enter_state(TOUCH_STATE_MEASURE_X);
|
||||
}
|
||||
else
|
||||
{
|
||||
old_touch_detect = false;
|
||||
enter_state(TOUCH_STATE_WAIT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void INT_TOUCH_DETECT(void)
|
||||
{
|
||||
process();
|
||||
}
|
||||
|
||||
static void touch_channel_irq(int chan)
|
||||
{
|
||||
(void) chan;
|
||||
process();
|
||||
}
|
||||
|
||||
void imx233_touchscreen_init(void)
|
||||
{
|
||||
touch_chan = imx233_lradc_acquire_channel(TIMEOUT_NOBLOCK);
|
||||
touch_delay = imx233_lradc_acquire_delay(TIMEOUT_NOBLOCK);
|
||||
if(touch_chan < 0 || touch_delay < 0)
|
||||
panicf("Cannot acquire channel and delays for touchscreen measurement");
|
||||
imx233_touchscreen_enable(false);
|
||||
}
|
||||
|
||||
void imx233_touchscreen_enable(bool enable)
|
||||
{
|
||||
enter_state(TOUCH_STATE_WAIT);
|
||||
imx233_lradc_set_channel_irq_callback(touch_chan, &touch_channel_irq);
|
||||
imx233_icoll_enable_interrupt(INT_SRC_LRADC_CHx(touch_chan), enable);
|
||||
imx233_icoll_enable_interrupt(INT_SRC_TOUCH_DETECT, enable);
|
||||
}
|
||||
|
||||
bool imx233_touchscreen_get_touch(int *raw_x, int *raw_y)
|
||||
{
|
||||
if(raw_x) *raw_x = old_touch_x;
|
||||
if(raw_y) *raw_y = old_touch_y;
|
||||
return old_touch_detect;
|
||||
}
|
34
firmware/target/arm/imx233/touchscreen-imx233.h
Normal file
34
firmware/target/arm/imx233/touchscreen-imx233.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2012 by Amaury Pouly
|
||||
*
|
||||
* Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
|
||||
* and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
|
||||
*
|
||||
* 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_IMX233__
|
||||
#define __TOUCHSCREEN_IMX233__
|
||||
|
||||
#include "lradc-imx233.h"
|
||||
|
||||
void imx233_touchscreen_init(void);
|
||||
void imx233_touchscreen_enable(bool enable);
|
||||
/* returns true if there is a touch */
|
||||
bool imx233_touchscreen_get_touch(int *raw_x, int *raw_y);
|
||||
|
||||
#endif /* __TOUCHSCREEN_IMX233__ */
|
Loading…
Reference in a new issue