Spin off common ft6x06 code to a driver
Allows for the i2c boilerplate to be shared between the M3K and Shanling Q1 ports. M3K-specific quirks remain in button-fiiom3k. Change-Id: I8879b603cefc16416bb200f1c484ca916d935c6a
This commit is contained in:
parent
551c74da55
commit
d01f3192f2
5 changed files with 210 additions and 74 deletions
|
@ -1928,13 +1928,18 @@ target/hosted/sdl/filesystem-sdl.c
|
||||||
drivers/touchpad.c
|
drivers/touchpad.c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Hardware drivers */
|
||||||
|
#ifndef SIMULATOR
|
||||||
#ifdef HAVE_I2C_ASYNC
|
#ifdef HAVE_I2C_ASYNC
|
||||||
drivers/i2c-async.c
|
drivers/i2c-async.c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_AXP_PMU
|
#ifdef HAVE_AXP_PMU
|
||||||
drivers/axp-pmu.c
|
drivers/axp-pmu.c
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_FT6x06
|
||||||
|
drivers/ft6x06.c
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* firmware/kernel section */
|
/* firmware/kernel section */
|
||||||
#ifdef HAVE_CORELOCK_OBJECT
|
#ifdef HAVE_CORELOCK_OBJECT
|
||||||
|
|
115
firmware/drivers/ft6x06.c
Normal file
115
firmware/drivers/ft6x06.c
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Aidan MacDonald
|
||||||
|
*
|
||||||
|
* 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 "ft6x06.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "i2c-async.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct ft6x06_driver {
|
||||||
|
/* i2c bus data */
|
||||||
|
int i2c_cookie;
|
||||||
|
i2c_descriptor i2c_desc;
|
||||||
|
|
||||||
|
/* callback for touch events */
|
||||||
|
ft6x06_event_cb event_cb;
|
||||||
|
|
||||||
|
/* buffer for I2C transfers */
|
||||||
|
uint8_t raw_data[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ft6x06_driver ft_drv;
|
||||||
|
struct ft6x06_state ft6x06_state;
|
||||||
|
|
||||||
|
static void ft6x06_i2c_callback(int status, i2c_descriptor* desc)
|
||||||
|
{
|
||||||
|
(void)desc;
|
||||||
|
if(status != I2C_STATUS_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int evt = ft_drv.raw_data[1] >> 6;
|
||||||
|
int tx = ft_drv.raw_data[2] | ((ft_drv.raw_data[1] & 0xf) << 8);
|
||||||
|
int ty = ft_drv.raw_data[4] | ((ft_drv.raw_data[3] & 0xf) << 8);
|
||||||
|
|
||||||
|
ft6x06_state.event = evt;
|
||||||
|
#ifdef FT6x06_SWAP_AXES
|
||||||
|
ft6x06_state.pos_x = ty;
|
||||||
|
ft6x06_state.pos_y = tx;
|
||||||
|
#else
|
||||||
|
ft6x06_state.pos_x = tx;
|
||||||
|
ft6x06_state.pos_y = ty;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ft_drv.event_cb(evt, ft6x06_state.pos_x, ft6x06_state.pos_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ft6x06_dummy_event_cb(int evt, int tx, int ty)
|
||||||
|
{
|
||||||
|
(void)evt;
|
||||||
|
(void)tx;
|
||||||
|
(void)ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft6x06_init(void)
|
||||||
|
{
|
||||||
|
/* Initialize stuff */
|
||||||
|
memset(&ft_drv, 0, sizeof(ft_drv));
|
||||||
|
ft_drv.event_cb = ft6x06_dummy_event_cb;
|
||||||
|
|
||||||
|
ft6x06_state.event = FT6x06_EVT_NONE;
|
||||||
|
ft6x06_state.pos_x = 0;
|
||||||
|
ft6x06_state.pos_y = 0;
|
||||||
|
|
||||||
|
/* Reserve bus management cookie */
|
||||||
|
ft_drv.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1);
|
||||||
|
|
||||||
|
/* Prep an I2C descriptor to read touch data */
|
||||||
|
ft_drv.i2c_desc.slave_addr = FT6x06_ADDR;
|
||||||
|
ft_drv.i2c_desc.bus_cond = I2C_START | I2C_STOP;
|
||||||
|
ft_drv.i2c_desc.tran_mode = I2C_READ;
|
||||||
|
ft_drv.i2c_desc.buffer[0] = &ft_drv.raw_data[5];
|
||||||
|
ft_drv.i2c_desc.count[0] = 1;
|
||||||
|
ft_drv.i2c_desc.buffer[1] = &ft_drv.raw_data[0];
|
||||||
|
ft_drv.i2c_desc.count[1] = 5;
|
||||||
|
ft_drv.i2c_desc.callback = ft6x06_i2c_callback;
|
||||||
|
ft_drv.i2c_desc.arg = 0;
|
||||||
|
ft_drv.i2c_desc.next = NULL;
|
||||||
|
|
||||||
|
/* Set I2C register address */
|
||||||
|
ft_drv.raw_data[5] = 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft6x06_set_event_cb(ft6x06_event_cb cb)
|
||||||
|
{
|
||||||
|
ft_drv.event_cb = cb ? cb : ft6x06_dummy_event_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft6x06_enable(bool en)
|
||||||
|
{
|
||||||
|
i2c_reg_write1(FT6x06_BUS, FT6x06_ADDR, 0xa5, en ? 0 : 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ft6x06_irq_handler(void)
|
||||||
|
{
|
||||||
|
/* We don't care if this fails, there's not much we can do about it */
|
||||||
|
i2c_async_queue(FT6x06_BUS, TIMEOUT_NOBLOCK, I2C_Q_ONCE,
|
||||||
|
ft_drv.i2c_cookie, &ft_drv.i2c_desc);
|
||||||
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
/* Drivers */
|
/* Drivers */
|
||||||
#define HAVE_I2C_ASYNC
|
#define HAVE_I2C_ASYNC
|
||||||
|
#define HAVE_FT6x06
|
||||||
|
#define FT6x06_SWAP_AXES
|
||||||
|
|
||||||
/* Buffer for plugins and codecs. */
|
/* Buffer for plugins and codecs. */
|
||||||
#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
|
#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
|
||||||
|
|
50
firmware/export/ft6x06.h
Normal file
50
firmware/export/ft6x06.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Aidan MacDonald
|
||||||
|
*
|
||||||
|
* 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 __FT6x06_H__
|
||||||
|
#define __FT6x06_H__
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef void(*ft6x06_event_cb)(int, int, int);
|
||||||
|
|
||||||
|
struct ft6x06_state {
|
||||||
|
int event;
|
||||||
|
int pos_x;
|
||||||
|
int pos_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ft6x06_event {
|
||||||
|
FT6x06_EVT_NONE = -1,
|
||||||
|
FT6x06_EVT_PRESS = 0,
|
||||||
|
FT6x06_EVT_RELEASE = 1,
|
||||||
|
FT6x06_EVT_CONTACT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct ft6x06_state ft6x06_state;
|
||||||
|
|
||||||
|
void ft6x06_init(void);
|
||||||
|
void ft6x06_set_event_cb(ft6x06_event_cb fn);
|
||||||
|
void ft6x06_enable(bool en);
|
||||||
|
void ft6x06_irq_handler(void);
|
||||||
|
|
||||||
|
#endif /* __FT6x06_H__ */
|
|
@ -25,7 +25,9 @@
|
||||||
#include "powermgmt.h"
|
#include "powermgmt.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "axp-pmu.h"
|
#include "axp-pmu.h"
|
||||||
|
#include "ft6x06.h"
|
||||||
#include "gpio-x1000.h"
|
#include "gpio-x1000.h"
|
||||||
|
#include "irq-x1000.h"
|
||||||
#include "i2c-x1000.h"
|
#include "i2c-x1000.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -35,12 +37,6 @@
|
||||||
# include "font.h"
|
# include "font.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Touch event types */
|
|
||||||
#define EVENT_NONE (-1)
|
|
||||||
#define EVENT_PRESS 0
|
|
||||||
#define EVENT_RELEASE 1
|
|
||||||
#define EVENT_CONTACT 2
|
|
||||||
|
|
||||||
/* FSM states */
|
/* FSM states */
|
||||||
#define STATE_IDLE 0
|
#define STATE_IDLE 0
|
||||||
#define STATE_PRESS 1
|
#define STATE_PRESS 1
|
||||||
|
@ -66,17 +62,6 @@
|
||||||
/* Number of touch samples to smooth before reading */
|
/* Number of touch samples to smooth before reading */
|
||||||
#define TOUCH_SAMPLES 3
|
#define TOUCH_SAMPLES 3
|
||||||
|
|
||||||
static struct ft_driver {
|
|
||||||
int i2c_cookie;
|
|
||||||
i2c_descriptor i2c_desc;
|
|
||||||
uint8_t raw_data[6];
|
|
||||||
bool active;
|
|
||||||
|
|
||||||
/* Number of pixels squared which must be moved before
|
|
||||||
* a scrollbar pulse is generated */
|
|
||||||
int scroll_thresh_sqr;
|
|
||||||
} ftd;
|
|
||||||
|
|
||||||
static struct ft_state_machine {
|
static struct ft_state_machine {
|
||||||
/* Current button state, used by button_read_device() */
|
/* Current button state, used by button_read_device() */
|
||||||
int buttons;
|
int buttons;
|
||||||
|
@ -105,6 +90,12 @@ static struct ft_state_machine {
|
||||||
|
|
||||||
/* Current touch position */
|
/* Current touch position */
|
||||||
int cur_x, cur_y;
|
int cur_x, cur_y;
|
||||||
|
|
||||||
|
/* Motion threshold squared, in 'pixels', required to trigger scrolling */
|
||||||
|
int scroll_thresh_sqr;
|
||||||
|
|
||||||
|
/* Touchpad enabled state */
|
||||||
|
bool active;
|
||||||
} fsm;
|
} fsm;
|
||||||
|
|
||||||
/* coordinates below this are the left hand buttons,
|
/* coordinates below this are the left hand buttons,
|
||||||
|
@ -210,9 +201,9 @@ static void ft_start_report_or_scroll(void)
|
||||||
static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
{
|
{
|
||||||
/* Generate a release event automatically in case we missed it */
|
/* Generate a release event automatically in case we missed it */
|
||||||
if(evt == EVENT_NONE) {
|
if(evt == FT6x06_EVT_NONE) {
|
||||||
if(TICKS_SINCE(t, fsm.last_event_t) >= AUTORELEASE_TIME) {
|
if(TICKS_SINCE(t, fsm.last_event_t) >= AUTORELEASE_TIME) {
|
||||||
evt = EVENT_RELEASE;
|
evt = FT6x06_EVT_RELEASE;
|
||||||
tx = fsm.cur_x;
|
tx = fsm.cur_x;
|
||||||
ty = fsm.cur_y;
|
ty = fsm.cur_y;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +211,7 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
|
|
||||||
switch(fsm.state) {
|
switch(fsm.state) {
|
||||||
case STATE_IDLE: {
|
case STATE_IDLE: {
|
||||||
if(evt == EVENT_PRESS || evt == EVENT_CONTACT) {
|
if(evt == FT6x06_EVT_PRESS || evt == FT6x06_EVT_CONTACT) {
|
||||||
/* Move to REPORT or PRESS state */
|
/* Move to REPORT or PRESS state */
|
||||||
if(ft_accum_touch(t, tx, ty))
|
if(ft_accum_touch(t, tx, ty))
|
||||||
ft_start_report_or_scroll();
|
ft_start_report_or_scroll();
|
||||||
|
@ -230,10 +221,10 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case STATE_PRESS: {
|
case STATE_PRESS: {
|
||||||
if(evt == EVENT_RELEASE) {
|
if(evt == FT6x06_EVT_RELEASE) {
|
||||||
/* Ignore if the number of samples is too low */
|
/* Ignore if the number of samples is too low */
|
||||||
ft_go_idle();
|
ft_go_idle();
|
||||||
} else if(evt == EVENT_PRESS || evt == EVENT_CONTACT) {
|
} else if(evt == FT6x06_EVT_PRESS || evt == FT6x06_EVT_CONTACT) {
|
||||||
/* Accumulate the touch position in the filter */
|
/* Accumulate the touch position in the filter */
|
||||||
if(ft_accum_touch(t, tx, ty))
|
if(ft_accum_touch(t, tx, ty))
|
||||||
ft_start_report_or_scroll();
|
ft_start_report_or_scroll();
|
||||||
|
@ -241,14 +232,14 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case STATE_REPORT: {
|
case STATE_REPORT: {
|
||||||
if(evt == EVENT_RELEASE)
|
if(evt == FT6x06_EVT_RELEASE)
|
||||||
ft_go_idle();
|
ft_go_idle();
|
||||||
else if(evt == EVENT_PRESS || evt == EVENT_CONTACT)
|
else if(evt == FT6x06_EVT_PRESS || evt == FT6x06_EVT_CONTACT)
|
||||||
ft_accum_touch(t, tx, ty);
|
ft_accum_touch(t, tx, ty);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case STATE_SCROLL_PRESS: {
|
case STATE_SCROLL_PRESS: {
|
||||||
if(evt == EVENT_RELEASE) {
|
if(evt == FT6x06_EVT_RELEASE) {
|
||||||
/* This _should_ synthesize a button press.
|
/* This _should_ synthesize a button press.
|
||||||
*
|
*
|
||||||
* - ft_start_report() will set the button bit based on the
|
* - ft_start_report() will set the button bit based on the
|
||||||
|
@ -257,10 +248,10 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
*
|
*
|
||||||
* - The next button_read_device() will see the button bit
|
* - The next button_read_device() will see the button bit
|
||||||
* and report it back to Rockbox, then step the FSM with
|
* and report it back to Rockbox, then step the FSM with
|
||||||
* EVENT_NONE.
|
* FT6x06_EVT_NONE.
|
||||||
*
|
*
|
||||||
* - The EVENT_NONE stepping will eventually autogenerate a
|
* - The FT6x06_EVT_NONE stepping will eventually autogenerate
|
||||||
* RELEASE event and restore the button state back to 0
|
* a RELEASE event and restore the button state back to 0
|
||||||
*
|
*
|
||||||
* - There's a small logic hole in the REPORT state which
|
* - There's a small logic hole in the REPORT state which
|
||||||
* could cause it to miss an immediately repeated PRESS
|
* could cause it to miss an immediately repeated PRESS
|
||||||
|
@ -271,7 +262,7 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(evt == EVENT_PRESS || evt == EVENT_CONTACT)
|
if(evt == FT6x06_EVT_PRESS || evt == FT6x06_EVT_CONTACT)
|
||||||
ft_accum_touch(t, tx, ty);
|
ft_accum_touch(t, tx, ty);
|
||||||
|
|
||||||
int dx = fsm.cur_x - fsm.orig_x;
|
int dx = fsm.cur_x - fsm.orig_x;
|
||||||
|
@ -289,21 +280,21 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case STATE_SCROLLING: {
|
case STATE_SCROLLING: {
|
||||||
if(evt == EVENT_RELEASE) {
|
if(evt == FT6x06_EVT_RELEASE) {
|
||||||
ft_go_idle();
|
ft_go_idle();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(evt == EVENT_PRESS || evt == EVENT_CONTACT)
|
if(evt == FT6x06_EVT_PRESS || evt == FT6x06_EVT_CONTACT)
|
||||||
ft_accum_touch(t, tx, ty);
|
ft_accum_touch(t, tx, ty);
|
||||||
|
|
||||||
int dx = fsm.cur_x - fsm.orig_x;
|
int dx = fsm.cur_x - fsm.orig_x;
|
||||||
int dy = fsm.cur_y - fsm.orig_y;
|
int dy = fsm.cur_y - fsm.orig_y;
|
||||||
int dp = (dx*dx) + (dy*dy);
|
int dp = (dx*dx) + (dy*dy);
|
||||||
if(dp >= ftd.scroll_thresh_sqr) {
|
if(dp >= fsm.scroll_thresh_sqr) {
|
||||||
/* avoid generating events if we're supposed to be inactive...
|
/* avoid generating events if we're supposed to be inactive...
|
||||||
* should not be necessary but better to be safe. */
|
* should not be necessary but better to be safe. */
|
||||||
if(ftd.active) {
|
if(fsm.active) {
|
||||||
if(dy < 0) {
|
if(dy < 0) {
|
||||||
queue_post(&button_queue, BUTTON_SCROLL_BACK, 0);
|
queue_post(&button_queue, BUTTON_SCROLL_BACK, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -327,18 +318,8 @@ static void ft_step_state(uint32_t t, int evt, int tx, int ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ft_i2c_callback(int status, i2c_descriptor* desc)
|
static void ft_event_cb(int evt, int tx, int ty)
|
||||||
{
|
{
|
||||||
(void)desc;
|
|
||||||
if(status != I2C_STATUS_OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* The panel is oriented such that its X axis is vertical,
|
|
||||||
* so swap the axes for reporting */
|
|
||||||
int evt = ftd.raw_data[1] >> 6;
|
|
||||||
int ty = ftd.raw_data[2] | ((ftd.raw_data[1] & 0xf) << 8);
|
|
||||||
int tx = ftd.raw_data[4] | ((ftd.raw_data[3] & 0xf) << 8);
|
|
||||||
|
|
||||||
/* TODO: convert the touch positions to linear positions.
|
/* TODO: convert the touch positions to linear positions.
|
||||||
*
|
*
|
||||||
* Points reported by the touch controller are distorted and non-linear,
|
* Points reported by the touch controller are distorted and non-linear,
|
||||||
|
@ -346,36 +327,11 @@ static void ft_i2c_callback(int status, i2c_descriptor* desc)
|
||||||
* the middle of the touchpad than on the edges, so scrolling feels slow
|
* the middle of the touchpad than on the edges, so scrolling feels slow
|
||||||
* in the middle and faster near the edge.
|
* in the middle and faster near the edge.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ft_step_state(__ost_read32(), evt, tx, ty);
|
ft_step_state(__ost_read32(), evt, tx, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ft6x06 interrupt pin */
|
|
||||||
void GPIOB12(void)
|
|
||||||
{
|
|
||||||
/* We don't care if this fails */
|
|
||||||
i2c_async_queue(FT6x06_BUS, TIMEOUT_NOBLOCK, I2C_Q_ONCE,
|
|
||||||
ftd.i2c_cookie, &ftd.i2c_desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ft_init(void)
|
static void ft_init(void)
|
||||||
{
|
{
|
||||||
/* Initialize the driver state */
|
|
||||||
ftd.i2c_cookie = i2c_async_reserve_cookies(FT6x06_BUS, 1);
|
|
||||||
ftd.i2c_desc.slave_addr = FT6x06_ADDR;
|
|
||||||
ftd.i2c_desc.bus_cond = I2C_START | I2C_STOP;
|
|
||||||
ftd.i2c_desc.tran_mode = I2C_READ;
|
|
||||||
ftd.i2c_desc.buffer[0] = &ftd.raw_data[5];
|
|
||||||
ftd.i2c_desc.count[0] = 1;
|
|
||||||
ftd.i2c_desc.buffer[1] = &ftd.raw_data[0];
|
|
||||||
ftd.i2c_desc.count[1] = 5;
|
|
||||||
ftd.i2c_desc.callback = ft_i2c_callback;
|
|
||||||
ftd.i2c_desc.arg = 0;
|
|
||||||
ftd.i2c_desc.next = NULL;
|
|
||||||
ftd.raw_data[5] = 0x02;
|
|
||||||
ftd.active = true;
|
|
||||||
touchpad_set_sensitivity(DEFAULT_TOUCHPAD_SENSITIVITY_SETTING);
|
|
||||||
|
|
||||||
/* Initialize the state machine */
|
/* Initialize the state machine */
|
||||||
fsm.buttons = 0;
|
fsm.buttons = 0;
|
||||||
fsm.state = STATE_IDLE;
|
fsm.state = STATE_IDLE;
|
||||||
|
@ -385,16 +341,24 @@ static void ft_init(void)
|
||||||
fsm.sum_x = fsm.sum_y = 0;
|
fsm.sum_x = fsm.sum_y = 0;
|
||||||
fsm.orig_x = fsm.orig_y = 0;
|
fsm.orig_x = fsm.orig_y = 0;
|
||||||
fsm.cur_x = fsm.cur_y = 0;
|
fsm.cur_x = fsm.cur_y = 0;
|
||||||
|
fsm.active = true;
|
||||||
|
touchpad_set_sensitivity(DEFAULT_TOUCHPAD_SENSITIVITY_SETTING);
|
||||||
|
|
||||||
/* Bring up I2C bus */
|
/* Bring up I2C bus */
|
||||||
i2c_x1000_set_freq(FT6x06_BUS, I2C_FREQ_400K);
|
i2c_x1000_set_freq(FT6x06_BUS, I2C_FREQ_400K);
|
||||||
|
|
||||||
|
/* Driver init */
|
||||||
|
ft6x06_init();
|
||||||
|
ft6x06_set_event_cb(ft_event_cb);
|
||||||
|
|
||||||
/* Reset chip */
|
/* Reset chip */
|
||||||
gpio_set_level(GPIO_FT6x06_RESET, 0);
|
gpio_set_level(GPIO_FT6x06_RESET, 0);
|
||||||
mdelay(5);
|
mdelay(5);
|
||||||
gpio_set_level(GPIO_FT6x06_RESET, 1);
|
gpio_set_level(GPIO_FT6x06_RESET, 1);
|
||||||
|
|
||||||
/* Configure the interrupt pin */
|
/* Configure the interrupt pin */
|
||||||
|
system_set_irq_handler(GPIO_TO_IRQ(GPIO_FT6x06_INTERRUPT),
|
||||||
|
ft6x06_irq_handler);
|
||||||
gpio_set_function(GPIO_FT6x06_INTERRUPT, GPIOF_IRQ_EDGE(0));
|
gpio_set_function(GPIO_FT6x06_INTERRUPT, GPIOF_IRQ_EDGE(0));
|
||||||
gpio_enable_irq(GPIO_FT6x06_INTERRUPT);
|
gpio_enable_irq(GPIO_FT6x06_INTERRUPT);
|
||||||
}
|
}
|
||||||
|
@ -403,13 +367,13 @@ void touchpad_set_sensitivity(int level)
|
||||||
{
|
{
|
||||||
int pixels = 40;
|
int pixels = 40;
|
||||||
pixels -= level;
|
pixels -= level;
|
||||||
ftd.scroll_thresh_sqr = pixels * pixels;
|
fsm.scroll_thresh_sqr = pixels * pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void touchpad_enable_device(bool en)
|
void touchpad_enable_device(bool en)
|
||||||
{
|
{
|
||||||
i2c_reg_write1(FT6x06_BUS, FT6x06_ADDR, 0xa5, en ? 0 : 3);
|
ft6x06_enable(en);
|
||||||
ftd.active = en;
|
fsm.active = en;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Value of headphone detect register */
|
/* Value of headphone detect register */
|
||||||
|
@ -467,7 +431,7 @@ void button_init_device(void)
|
||||||
int button_read_device(void)
|
int button_read_device(void)
|
||||||
{
|
{
|
||||||
int r = fsm.buttons;
|
int r = fsm.buttons;
|
||||||
ft_step_state(__ost_read32(), EVENT_NONE, 0, 0);
|
ft_step_state(__ost_read32(), FT6x06_EVT_NONE, 0, 0);
|
||||||
|
|
||||||
/* Read GPIOs for physical buttons */
|
/* Read GPIOs for physical buttons */
|
||||||
uint32_t a = REG_GPIO_PIN(GPIO_A);
|
uint32_t a = REG_GPIO_PIN(GPIO_A);
|
||||||
|
|
Loading…
Reference in a new issue