mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2025-04-19 01:16:56 +02:00
touch: plug into event system (+ refactoring)
* Interrupt now at level 15 so it can work in the input timer callback * Remember last raw/conv/dots and expose unstable API to use it via new include <gint/drivers/touch.h> * Put number of touches in the structures
This commit is contained in:
parent
4e20f7bc5b
commit
bc8b9863ae
12 changed files with 272 additions and 313 deletions
|
@ -256,7 +256,6 @@ set(SOURCES
|
||||||
# Touch-screen driver
|
# Touch-screen driver
|
||||||
src/touch/i2c.c
|
src/touch/i2c.c
|
||||||
src/touch/i2c_inth.c
|
src/touch/i2c_inth.c
|
||||||
src/touch/adconv.c
|
|
||||||
src/touch/touch.c
|
src/touch/touch.c
|
||||||
src/touch/driver.c
|
src/touch/driver.c
|
||||||
)
|
)
|
||||||
|
|
|
@ -254,6 +254,10 @@ void keydev_tick(keydev_t *d, uint us);
|
||||||
// Low-level API to read events from the device
|
// Low-level API to read events from the device
|
||||||
//---
|
//---
|
||||||
|
|
||||||
|
/* keydev_queue_event(): Add an event in a device's buffer
|
||||||
|
Returns false if the event cannot be pushed. */
|
||||||
|
bool keydev_queue_event(keydev_t *d, key_event_t ev);
|
||||||
|
|
||||||
/* keydev_unqueue_event(): Retrieve the next keyboard event in queue
|
/* keydev_unqueue_event(): Retrieve the next keyboard event in queue
|
||||||
|
|
||||||
This source provides the queued KEYEV_UP, KEYEV_DOWN and KEYEV_HOLD events
|
This source provides the queued KEYEV_UP, KEYEV_DOWN and KEYEV_HOLD events
|
||||||
|
|
70
include/gint/drivers/touch.h
Normal file
70
include/gint/drivers/touch.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
//---
|
||||||
|
// gint:drivers:touch - Internals of the touch driver
|
||||||
|
//---
|
||||||
|
|
||||||
|
#ifndef GINT_DRIVERS_TOUCH
|
||||||
|
#define GINT_DRIVERS_TOUCH
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gint/config.h>
|
||||||
|
#include <gint/defs/types.h>
|
||||||
|
#include <gint/keyboard.h>
|
||||||
|
|
||||||
|
#if GINT_HW_CP
|
||||||
|
|
||||||
|
/* Access to the latest data of each stage of the touch input sequence.
|
||||||
|
* First stage is the raw output of the 0x84 command from I2C.
|
||||||
|
* Second stage is the same data after adjusting resolution and bit formats,
|
||||||
|
then determining then number of touches based on multi-touch parameters.
|
||||||
|
* Third stage is converting to screen-space coordinates based on calibration
|
||||||
|
parameters. */
|
||||||
|
|
||||||
|
/* First stage: raw output of command 0x84. There may not be data at all if the
|
||||||
|
input port indicates there are no touches. */
|
||||||
|
struct _touch_adraw {
|
||||||
|
/* Response to command 0x84 */
|
||||||
|
u16 x1, y1, z1, gh;
|
||||||
|
u16 x2, y2, z2, dm;
|
||||||
|
/* Whether data is present (if false, everything is 0 and no touches) */
|
||||||
|
bool has_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Second stage: decoded form of command 0x84 output. */
|
||||||
|
struct _touch_adconv {
|
||||||
|
/* Number of touches (0, 1 or 2) */
|
||||||
|
int touches;
|
||||||
|
int x1, y1;
|
||||||
|
int x2, y2;
|
||||||
|
int z1, z2;
|
||||||
|
u16 gh, dm;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Third stage: screen-space dots information. */
|
||||||
|
struct _touch_addots {
|
||||||
|
/* Number of touches (0, 1 or 2) */
|
||||||
|
int touches;
|
||||||
|
/* Valid if touches >= 1 */
|
||||||
|
int x1, y1, z1;
|
||||||
|
/* Valid if touches >= 2 */
|
||||||
|
int x2, y2, z2;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Run a scanning round and return the next event. This function is not
|
||||||
|
reentrant and is already called by the input timer. Don't call it! */
|
||||||
|
key_event_t touch_scan(void);
|
||||||
|
|
||||||
|
/* Get the last captured data from any of the 3 stages. All pointers can be
|
||||||
|
NULL; fills the structures that are provided. */
|
||||||
|
void touch_get_last_scan(struct _touch_adraw *raw,
|
||||||
|
struct _touch_adconv *conv, struct _touch_addots *dots);
|
||||||
|
|
||||||
|
#endif /* GINT_HW_CP */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* GINT_DRIVERS_TOUCH */
|
|
@ -33,12 +33,8 @@ extern int touch_calib_get_os(touch_calibration_t *calib);
|
||||||
/* touch_calib_set() - set calibration information */
|
/* touch_calib_set() - set calibration information */
|
||||||
extern int touch_calib_set(touch_calibration_t *calib);
|
extern int touch_calib_set(touch_calibration_t *calib);
|
||||||
|
|
||||||
// low-level API
|
// TODO: Functions to query the immediate state of the touch display
|
||||||
|
// TODO| As per queue? Or real-time?
|
||||||
#include <gint/keyboard.h>
|
|
||||||
|
|
||||||
/* touch_next_event() - get the next touchscreen event */
|
|
||||||
extern key_event_t touch_next_event(void);
|
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
#endif /* GINT_HW_CP */
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,7 @@ static int standard_repeater(GUNUSED int key, GUNUSED int duration, int count)
|
||||||
// Driver event generation
|
// Driver event generation
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/* keydev_queue_push(): Add an event in a device's buffer
|
bool keydev_queue_event(keydev_t *d, key_event_t ev)
|
||||||
Returns false if the event cannot be pushed. */
|
|
||||||
bool keydev_queue_push(keydev_t *d, key_event_t ev)
|
|
||||||
{
|
{
|
||||||
if(d->async_filter && !d->async_filter(ev))
|
if(d->async_filter && !d->async_filter(ev))
|
||||||
return true;
|
return true;
|
||||||
|
@ -165,7 +163,7 @@ void keydev_process_state(keydev_t *d, uint8_t scan[12])
|
||||||
ev.col = col;
|
ev.col = col;
|
||||||
ev.key = keymatrix_to_keycode(row, col);
|
ev.key = keymatrix_to_keycode(row, col);
|
||||||
/* Update state only if the push succeeds */
|
/* Update state only if the push succeeds */
|
||||||
if((diff & mask) && keydev_queue_push(d, ev))
|
if((diff & mask) && keydev_queue_event(d, ev))
|
||||||
d->state_now[row] = mode
|
d->state_now[row] = mode
|
||||||
? d->state_now[row] | mask
|
? d->state_now[row] | mask
|
||||||
: d->state_now[row] & ~mask;
|
: d->state_now[row] & ~mask;
|
||||||
|
@ -221,7 +219,7 @@ void keydev_tick(keydev_t *d, uint us)
|
||||||
/* Generate the next repeat */
|
/* Generate the next repeat */
|
||||||
key_event_t repeat = keydev_repeat_event(d);
|
key_event_t repeat = keydev_repeat_event(d);
|
||||||
if(repeat.type != KEYEV_NONE)
|
if(repeat.type != KEYEV_NONE)
|
||||||
keydev_queue_push(d, repeat);
|
keydev_queue_event(d, repeat);
|
||||||
|
|
||||||
d->time++;
|
d->time++;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include <gint/drivers/iokbd.h>
|
#include <gint/drivers/iokbd.h>
|
||||||
#include <gint/hardware.h>
|
#include <gint/hardware.h>
|
||||||
|
|
||||||
|
#if GINT_HW_CP
|
||||||
|
#include <gint/drivers/touch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -71,6 +75,12 @@ int keysc_tick(void)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GINT_HW_CP
|
||||||
|
key_event_t ev = touch_scan();
|
||||||
|
if(ev.type != KEYEV_NONE)
|
||||||
|
keydev_queue_event(&keysc_dev, ev);
|
||||||
|
#endif
|
||||||
|
|
||||||
return TIMER_CONTINUE;
|
return TIMER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,166 +0,0 @@
|
||||||
//---
|
|
||||||
// gint:touch:adconv - 0x84 register data conversion
|
|
||||||
//---
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <gint/defs/util.h>
|
|
||||||
#include <gint/cpu.h>
|
|
||||||
#include <gint/config.h>
|
|
||||||
|
|
||||||
#if GINT_HW_CP
|
|
||||||
|
|
||||||
#include "./adconv.h"
|
|
||||||
#include "./i2c.h"
|
|
||||||
#include "./driver.h"
|
|
||||||
|
|
||||||
//---
|
|
||||||
// Internals
|
|
||||||
//---
|
|
||||||
|
|
||||||
/* __touch_drv_info - global driver information */
|
|
||||||
extern struct _touch_drv_info __touch_drv_info;
|
|
||||||
|
|
||||||
/* _adconv_check_dual() - check if it is dual or single */
|
|
||||||
static int _adconv_check_dual(
|
|
||||||
struct _touch_adconv *adconv,
|
|
||||||
struct _touch_adraw *adraw
|
|
||||||
) {
|
|
||||||
extern struct _touch_drv_info __touch_drv_info;
|
|
||||||
bool is_dual;
|
|
||||||
int x2;
|
|
||||||
int y2;
|
|
||||||
int z2;
|
|
||||||
int val;
|
|
||||||
|
|
||||||
cpu_atomic_start();
|
|
||||||
x2 = ((int)((uint)(adraw->x2) >> 6)) + ((adraw->x2 & 1) * -0x400);
|
|
||||||
y2 = ((int)((uint)(adraw->y2) >> 6)) + ((adraw->y2 & 1) * -0x400);
|
|
||||||
z2 = ((int)((uint)(adraw->z2) >> 4)) + ((adraw->z2 & 1) * -0x1000);
|
|
||||||
adconv->x2 = x2;
|
|
||||||
adconv->y2 = y2;
|
|
||||||
adconv->z2 = z2;
|
|
||||||
val = __touch_drv_info.calibration.dual_sensi_entry;
|
|
||||||
if (__touch_drv_info.adinfo.prev_is_dual)
|
|
||||||
val = __touch_drv_info.calibration.dual_sensi_leave;
|
|
||||||
is_dual = ((abs(z2) >= val) || (max(abs(x2),abs(y2)) >= val));
|
|
||||||
__touch_drv_info.adinfo.prev_is_dual = is_dual;
|
|
||||||
cpu_atomic_end();
|
|
||||||
return is_dual;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---
|
|
||||||
// Public
|
|
||||||
//---
|
|
||||||
|
|
||||||
/* touch_adconv_get_raw() - read 0x84 register using I2C */
|
|
||||||
int touch_adconv_get_raw(struct _touch_adraw *adraw)
|
|
||||||
{
|
|
||||||
volatile uint8_t *IO_PRDR = (void*)0xa405013c;
|
|
||||||
|
|
||||||
if (((*IO_PRDR) & 0x20) != 0)
|
|
||||||
{
|
|
||||||
adraw->x1 = 0;
|
|
||||||
adraw->y1 = 0;
|
|
||||||
adraw->z1 = 0;
|
|
||||||
adraw->x2 = 0;
|
|
||||||
adraw->y2 = 0;
|
|
||||||
adraw->z2 = 0;
|
|
||||||
adraw->gh = 0;
|
|
||||||
cpu_atomic_start();
|
|
||||||
__touch_drv_info.adinfo.prev_is_dual = false;
|
|
||||||
cpu_atomic_end();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
i2c_reg_read(0x84, adraw, 16);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* touch_adconv_convert() - perform the raw conversion */
|
|
||||||
int touch_adconv_get_conv(
|
|
||||||
struct _touch_adconv *adconv,
|
|
||||||
struct _touch_adraw *adraw,
|
|
||||||
int type
|
|
||||||
) {
|
|
||||||
if (type == 0)
|
|
||||||
return 0;
|
|
||||||
adconv->x1 = adraw->x1 >> 4;
|
|
||||||
adconv->y1 = adraw->y1 >> 4;
|
|
||||||
adconv->z1 = adraw->z1 >> 4;
|
|
||||||
adconv->gh = adraw->gh >> 4;
|
|
||||||
adconv->dm = adraw->dm >> 6;
|
|
||||||
if (_adconv_check_dual(adconv, adraw) == 0)
|
|
||||||
return 1;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* touch_adconv_get_dots() - generate dots information */
|
|
||||||
int touch_adconv_get_dots(
|
|
||||||
struct _touch_addots *dots,
|
|
||||||
struct _touch_adconv *adconv,
|
|
||||||
int type
|
|
||||||
) {
|
|
||||||
int x_div;
|
|
||||||
int x_base;
|
|
||||||
int y_div;
|
|
||||||
int y_base;
|
|
||||||
|
|
||||||
cpu_atomic_start();
|
|
||||||
x_div = __touch_drv_info.calibration.x_div;
|
|
||||||
x_base = __touch_drv_info.calibration.x_base;
|
|
||||||
y_div = __touch_drv_info.calibration.y_div;
|
|
||||||
y_base = __touch_drv_info.calibration.y_base;
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
dots->type = TS_DOTS_TYPE_OFF;
|
|
||||||
dots->x1 = 0;
|
|
||||||
dots->y1 = 0;
|
|
||||||
dots->z1 = 0;
|
|
||||||
dots->x2 = 0;
|
|
||||||
dots->y2 = 0;
|
|
||||||
dots->z2 = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
dots->type = TS_DOTS_TYPE_SINGLE;
|
|
||||||
dots->x1 = ((adconv->x1 - x_base) * 0x100) / x_div;
|
|
||||||
dots->y1 = ((adconv->y1 - y_base) * 0x100) / y_div;
|
|
||||||
dots->z1 = adconv->z1;
|
|
||||||
dots->x2 = 0;
|
|
||||||
dots->y2 = 0;
|
|
||||||
dots->z2 = 0;
|
|
||||||
break;
|
|
||||||
case 2: {
|
|
||||||
dots->type = TS_DOTS_TYPE_DUAL;
|
|
||||||
int xmin = ((adconv->x1 - x_base) * 0x100) / x_div;
|
|
||||||
int ymin = ((adconv->y1 - y_base) * 0x100) / y_div;
|
|
||||||
// x2 end-to-end: ~185 (changes along the height)
|
|
||||||
// y2 end-to-end: 470
|
|
||||||
// x2 *= 1.64
|
|
||||||
// y2 *= 0.96
|
|
||||||
int xmax = xmin + adconv->x2 * 0x1ba / 0x100;
|
|
||||||
int ymax = ymin + adconv->y2 * 0x11f / 0x100;
|
|
||||||
dots->z1 = adconv->z1;
|
|
||||||
dots->z2 = adconv->z2;
|
|
||||||
|
|
||||||
if(dots->z2 >= 0) {
|
|
||||||
dots->x1 = xmin;
|
|
||||||
dots->y1 = ymin;
|
|
||||||
dots->x2 = xmax;
|
|
||||||
dots->y2 = ymax;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dots->x1 = xmin;
|
|
||||||
dots->y1 = ymax;
|
|
||||||
dots->x2 = xmax;
|
|
||||||
dots->y2 = ymin;
|
|
||||||
}
|
|
||||||
dots->z1 = adconv->x2;
|
|
||||||
dots->z2 = adconv->y2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu_atomic_end();
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
|
|
@ -1,90 +0,0 @@
|
||||||
#ifndef GINT_TOUCH_ADCONV_H
|
|
||||||
#define GINT_TOUCH_ADCONV_H 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <gint/defs/types.h>
|
|
||||||
#include <gint/config.h>
|
|
||||||
|
|
||||||
#if GINT_HW_CP
|
|
||||||
|
|
||||||
//---
|
|
||||||
// Internals
|
|
||||||
//---
|
|
||||||
|
|
||||||
/* _touch_adraw - raw 0x84 register information */
|
|
||||||
struct _touch_adraw
|
|
||||||
{
|
|
||||||
uint16_t x1;
|
|
||||||
uint16_t y1;
|
|
||||||
uint16_t z1;
|
|
||||||
uint16_t gh;
|
|
||||||
uint16_t x2;
|
|
||||||
uint16_t y2;
|
|
||||||
uint16_t z2;
|
|
||||||
uint16_t dm;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* _touch_adconv - post-conversion raw 0x84 register information */
|
|
||||||
struct _touch_adconv
|
|
||||||
{
|
|
||||||
int x1;
|
|
||||||
int y1;
|
|
||||||
int x2;
|
|
||||||
int y2;
|
|
||||||
int z1;
|
|
||||||
int z2;
|
|
||||||
uint16_t gh;
|
|
||||||
uint16_t dm;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* _touch_addots_type - type of dots */
|
|
||||||
enum _touch_addots_type
|
|
||||||
{
|
|
||||||
TS_DOTS_TYPE_OFF = 0,
|
|
||||||
TS_DOTS_TYPE_SINGLE = 1,
|
|
||||||
TS_DOTS_TYPE_DUAL = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* _touch_addots - touchscreen dots information */
|
|
||||||
struct _touch_addots
|
|
||||||
{
|
|
||||||
enum _touch_addots_type type;
|
|
||||||
int x1;
|
|
||||||
int y1;
|
|
||||||
int z1;
|
|
||||||
int x2;
|
|
||||||
int y2;
|
|
||||||
int z2;
|
|
||||||
};
|
|
||||||
|
|
||||||
//---
|
|
||||||
// Public
|
|
||||||
//---
|
|
||||||
|
|
||||||
/* touch_adconv_get_raw() - read 0x84 register using I2C */
|
|
||||||
extern int touch_adconv_get_raw(struct _touch_adraw *adraw);
|
|
||||||
|
|
||||||
/* touch_adconv_get_conv() - perform the raw conversion */
|
|
||||||
extern int touch_adconv_get_conv(
|
|
||||||
struct _touch_adconv *adconv,
|
|
||||||
struct _touch_adraw *adraw,
|
|
||||||
int type
|
|
||||||
);
|
|
||||||
|
|
||||||
/* touch_adconv_get_dots() - generate dots information */
|
|
||||||
extern int touch_adconv_get_dots(
|
|
||||||
struct _touch_addots *dots,
|
|
||||||
struct _touch_adconv *adconv,
|
|
||||||
int type
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* GINT_TOUCH_ADCONV_H */
|
|
|
@ -109,6 +109,6 @@ gint_driver_t drv_touch = {
|
||||||
.funbind = _touch_funbind,
|
.funbind = _touch_funbind,
|
||||||
.state_size = sizeof(touch_state_t),
|
.state_size = sizeof(touch_state_t),
|
||||||
};
|
};
|
||||||
GINT_DECLARE_DRIVER(24, drv_touch);
|
GINT_DECLARE_DRIVER(22, drv_touch);
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
#endif /* GINT_HW_CP */
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <gint/config.h>
|
||||||
#include <gint/keyboard.h>
|
#include <gint/keyboard.h>
|
||||||
#include <gint/touch.h>
|
#include <gint/touch.h>
|
||||||
#include <gint/config.h>
|
#include <gint/drivers/touch.h>
|
||||||
|
|
||||||
#if GINT_HW_CP
|
#if GINT_HW_CP
|
||||||
|
|
||||||
|
@ -21,6 +22,20 @@ struct _touch_drv_info
|
||||||
} adinfo;
|
} adinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Gets raw data from I2C command 0x84. This function is *NOT REENTRANT* and
|
||||||
|
must have only one user (from the scheduled input tick). */
|
||||||
|
extern void touch_adconv_get_raw(struct _touch_adraw *adraw);
|
||||||
|
|
||||||
|
/* touch_adconv_get_conv() - perform the raw conversion */
|
||||||
|
extern void touch_adconv_get_conv(
|
||||||
|
struct _touch_adconv *adconv,
|
||||||
|
struct _touch_adraw *adraw);
|
||||||
|
|
||||||
|
/* touch_adconv_get_dots() - generate dots information */
|
||||||
|
extern void touch_adconv_get_dots(
|
||||||
|
struct _touch_addots *dots,
|
||||||
|
struct _touch_adconv *adconv);
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
#endif /* GINT_HW_CP */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -224,10 +224,10 @@ void i2c_configure(void)
|
||||||
__i2c_request.status = I2C_REQ_STATUS_FINISHED;
|
__i2c_request.status = I2C_REQ_STATUS_FINISHED;
|
||||||
|
|
||||||
// Enable interrupt
|
// Enable interrupt
|
||||||
intc_priority(INTC_I2C_AL, 1);
|
intc_priority(INTC_I2C_AL, 15);
|
||||||
intc_priority(INTC_I2C_TACK, 1);
|
intc_priority(INTC_I2C_TACK, 15);
|
||||||
intc_priority(INTC_I2C_WAIT, 1);
|
intc_priority(INTC_I2C_WAIT, 15);
|
||||||
intc_priority(INTC_I2C_DTE, 1);
|
intc_priority(INTC_I2C_DTE, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* i2c_unbind() - unbind from gint to casio */
|
/* i2c_unbind() - unbind from gint to casio */
|
||||||
|
|
|
@ -2,23 +2,139 @@
|
||||||
// gint:touch - touch driver (high-level)
|
// gint:touch - touch driver (high-level)
|
||||||
//----
|
//----
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <gint/config.h>
|
||||||
|
#include <gint/defs/util.h>
|
||||||
#include <gint/touch.h>
|
#include <gint/touch.h>
|
||||||
#include <gint/cpu.h>
|
#include <gint/cpu.h>
|
||||||
#include <gint/config.h>
|
|
||||||
|
|
||||||
#if GINT_HW_CP
|
#if GINT_HW_CP
|
||||||
|
|
||||||
#include "./i2c.h"
|
#include "./i2c.h"
|
||||||
#include "./adconv.h"
|
|
||||||
#include "./driver.h"
|
#include "./driver.h"
|
||||||
|
|
||||||
|
/* __touch_drv_info - internal driver information */
|
||||||
|
extern struct _touch_drv_info __touch_drv_info;
|
||||||
|
|
||||||
|
// TODO[touch]: Get rid of global last_cong by making raw -> conv stateless
|
||||||
|
static struct _touch_adraw last_raw;
|
||||||
|
static struct _touch_adconv last_conv;
|
||||||
|
static struct _touch_addots last_dots;
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Internals
|
// Internals
|
||||||
//---
|
//---
|
||||||
|
|
||||||
/* __touch_drv_info - internal driver information */
|
void touch_adconv_get_raw(struct _touch_adraw *adraw)
|
||||||
extern struct _touch_drv_info __touch_drv_info;
|
{
|
||||||
|
volatile uint8_t *IO_PRDR = (void*)0xa405013c;
|
||||||
|
memset(adraw, 0, sizeof *adraw);
|
||||||
|
|
||||||
|
if ((*IO_PRDR & 0x20) == 0) {
|
||||||
|
i2c_reg_read(0x84, adraw, 16);
|
||||||
|
adraw->has_data = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_adconv_get_conv(
|
||||||
|
struct _touch_adconv *adconv,
|
||||||
|
struct _touch_adraw *adraw)
|
||||||
|
{
|
||||||
|
if (!adraw->has_data) {
|
||||||
|
memset(adconv, 0, sizeof *adconv);
|
||||||
|
cpu_atomic_start();
|
||||||
|
__touch_drv_info.adinfo.prev_is_dual = false;
|
||||||
|
cpu_atomic_end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
adconv->x1 = adraw->x1 >> 4;
|
||||||
|
adconv->y1 = adraw->y1 >> 4;
|
||||||
|
adconv->z1 = adraw->z1 >> 4;
|
||||||
|
adconv->x2 = ((int)((uint)(adraw->x2) >> 6)) + ((adraw->x2 & 1) * -0x400);
|
||||||
|
adconv->y2 = ((int)((uint)(adraw->y2) >> 6)) + ((adraw->y2 & 1) * -0x400);
|
||||||
|
adconv->z2 = ((int)((uint)(adraw->z2) >> 4)) + ((adraw->z2 & 1) * -0x1000);
|
||||||
|
adconv->gh = adraw->gh >> 4;
|
||||||
|
adconv->dm = adraw->dm >> 6;
|
||||||
|
|
||||||
|
cpu_atomic_start();
|
||||||
|
int dual_threshold = __touch_drv_info.calibration.dual_sensi_entry;
|
||||||
|
if (__touch_drv_info.adinfo.prev_is_dual)
|
||||||
|
dual_threshold = __touch_drv_info.calibration.dual_sensi_leave;
|
||||||
|
bool is_dual = (abs(adconv->z2) >= dual_threshold ||
|
||||||
|
max(abs(adconv->x2), abs(adconv->y2)) >= dual_threshold);
|
||||||
|
__touch_drv_info.adinfo.prev_is_dual = is_dual;
|
||||||
|
cpu_atomic_end();
|
||||||
|
|
||||||
|
adconv->touches = is_dual ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_adconv_get_dots(
|
||||||
|
struct _touch_addots *dots,
|
||||||
|
struct _touch_adconv *adconv)
|
||||||
|
{
|
||||||
|
int x_div;
|
||||||
|
int x_base;
|
||||||
|
int y_div;
|
||||||
|
int y_base;
|
||||||
|
|
||||||
|
cpu_atomic_start();
|
||||||
|
x_div = __touch_drv_info.calibration.x_div;
|
||||||
|
x_base = __touch_drv_info.calibration.x_base;
|
||||||
|
y_div = __touch_drv_info.calibration.y_div;
|
||||||
|
y_base = __touch_drv_info.calibration.y_base;
|
||||||
|
cpu_atomic_end();
|
||||||
|
|
||||||
|
dots->touches = adconv->touches;
|
||||||
|
switch (adconv->touches)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
dots->x1 = 0;
|
||||||
|
dots->y1 = 0;
|
||||||
|
dots->z1 = 0;
|
||||||
|
dots->x2 = 0;
|
||||||
|
dots->y2 = 0;
|
||||||
|
dots->z2 = 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
dots->x1 = ((adconv->x1 - x_base) * 0x100) / x_div;
|
||||||
|
dots->y1 = ((adconv->y1 - y_base) * 0x100) / y_div;
|
||||||
|
dots->z1 = adconv->z1;
|
||||||
|
dots->x2 = 0;
|
||||||
|
dots->y2 = 0;
|
||||||
|
dots->z2 = 0;
|
||||||
|
break;
|
||||||
|
case 2: {
|
||||||
|
int xmin = ((adconv->x1 - x_base) * 0x100) / x_div;
|
||||||
|
int ymin = ((adconv->y1 - y_base) * 0x100) / y_div;
|
||||||
|
// x2 end-to-end: ~185 (changes along the height)
|
||||||
|
// y2 end-to-end: 470
|
||||||
|
// x2 *= 1.64
|
||||||
|
// y2 *= 0.96
|
||||||
|
int xmax = xmin + adconv->x2 * 0x1ba / 0x100;
|
||||||
|
int ymax = ymin + adconv->y2 * 0x11f / 0x100;
|
||||||
|
dots->z1 = adconv->z1;
|
||||||
|
dots->z2 = adconv->z2;
|
||||||
|
|
||||||
|
if(dots->z2 >= 0) {
|
||||||
|
dots->x1 = xmin;
|
||||||
|
dots->y1 = ymin;
|
||||||
|
dots->x2 = xmax;
|
||||||
|
dots->y2 = ymax;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dots->x1 = xmin;
|
||||||
|
dots->y1 = ymax;
|
||||||
|
dots->x2 = xmax;
|
||||||
|
dots->y2 = ymin;
|
||||||
|
}
|
||||||
|
dots->z1 = adconv->x2;
|
||||||
|
dots->z2 = adconv->y2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
// Public
|
// Public
|
||||||
|
@ -62,50 +178,57 @@ int touch_calib_set(touch_calibration_t *calib)
|
||||||
|
|
||||||
// low-level API
|
// low-level API
|
||||||
|
|
||||||
/* touch_next_event() - get the next touch event */
|
static key_event_t make_event(struct _touch_addots const *dots)
|
||||||
key_event_t touch_next_event(void)
|
|
||||||
{
|
{
|
||||||
struct _touch_adconv adconv;
|
|
||||||
struct _touch_addots addots;
|
|
||||||
struct _touch_adraw adraw;
|
|
||||||
key_event_t evt;
|
key_event_t evt;
|
||||||
int type;
|
|
||||||
|
|
||||||
evt.type = KEYEV_TOUCH_RELEASE;
|
|
||||||
type = touch_adconv_get_raw(&adraw);
|
|
||||||
if (type != 0)
|
|
||||||
{
|
|
||||||
type = touch_adconv_get_conv(&adconv, &adraw, type);
|
|
||||||
type = touch_adconv_get_dots(&addots, &adconv, type);
|
|
||||||
if (type == 1)
|
|
||||||
{
|
|
||||||
evt.type = KEYEV_TOUCH_DRAG;
|
|
||||||
evt.x = addots.x1;
|
|
||||||
evt.y = addots.y1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu_atomic_start();
|
|
||||||
if (evt.type == KEYEV_TOUCH_DRAG) {
|
|
||||||
if (
|
|
||||||
(__touch_drv_info.prev_evt.type == KEYEV_NONE) ||
|
|
||||||
(__touch_drv_info.prev_evt.type == KEYEV_TOUCH_RELEASE)
|
|
||||||
) {
|
|
||||||
evt.type = KEYEV_TOUCH_PRESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (evt.type == KEYEV_TOUCH_RELEASE) {
|
|
||||||
if (
|
|
||||||
(__touch_drv_info.prev_evt.type == KEYEV_NONE) ||
|
|
||||||
(__touch_drv_info.prev_evt.type == KEYEV_TOUCH_RELEASE)
|
|
||||||
) {
|
|
||||||
evt.type = KEYEV_NONE;
|
evt.type = KEYEV_NONE;
|
||||||
|
|
||||||
|
cpu_atomic_start();
|
||||||
|
int prev_type = __touch_drv_info.prev_evt.type;
|
||||||
|
int prev_x = __touch_drv_info.prev_evt.x;
|
||||||
|
int prev_y = __touch_drv_info.prev_evt.y;
|
||||||
|
|
||||||
|
// TODO: Handle dual touch here
|
||||||
|
if(dots->touches != 1) {
|
||||||
|
if(prev_type != KEYEV_TOUCH_RELEASE && prev_type != KEYEV_NONE)
|
||||||
|
evt.type = KEYEV_TOUCH_RELEASE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(prev_type == KEYEV_TOUCH_RELEASE || prev_type == KEYEV_NONE)
|
||||||
|
evt.type = KEYEV_TOUCH_PRESSED;
|
||||||
|
/* Don't emit successive DRAG events at the same location */
|
||||||
|
else if(dots->x1 != prev_x || dots->y1 != prev_y)
|
||||||
|
evt.type = KEYEV_TOUCH_DRAG;
|
||||||
|
|
||||||
|
if(evt.type != KEYEV_NONE) {
|
||||||
|
evt.x = dots->x1;
|
||||||
|
evt.y = dots->y1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
__touch_drv_info.prev_evt.type = evt.type;
|
|
||||||
__touch_drv_info.prev_evt.x = evt.x;
|
if(evt.type != KEYEV_NONE)
|
||||||
__touch_drv_info.prev_evt.y = evt.y;
|
__touch_drv_info.prev_evt = evt;
|
||||||
cpu_atomic_end();
|
cpu_atomic_end();
|
||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key_event_t touch_scan(void)
|
||||||
|
{
|
||||||
|
touch_adconv_get_raw(&last_raw);
|
||||||
|
touch_adconv_get_conv(&last_conv, &last_raw);
|
||||||
|
touch_adconv_get_dots(&last_dots, &last_conv);
|
||||||
|
return make_event(&last_dots);
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_get_last_scan(struct _touch_adraw *raw,
|
||||||
|
struct _touch_adconv *conv, struct _touch_addots *dots)
|
||||||
|
{
|
||||||
|
if(raw)
|
||||||
|
*raw = last_raw;
|
||||||
|
if(conv)
|
||||||
|
*conv = last_conv;
|
||||||
|
if(dots)
|
||||||
|
*dots = last_dots;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* GINT_HW_CP */
|
#endif /* GINT_HW_CP */
|
||||||
|
|
Loading…
Add table
Reference in a new issue