Files
99_7018_lmx/cpu/br28/lp_touch_key.c

1596 lines
55 KiB
C
Raw Normal View History

2025-10-29 13:10:02 +08:00
#include "includes.h"
#include "asm/power/p11.h"
#include "asm/power/p33.h"
#include "asm/lp_touch_key_tool.h"
#include "asm/lp_touch_key_alog.h"
#include "device/key_driver.h"
#include "key_event_deal.h"
#include "app_config.h"
#include "asm/lp_touch_key_api.h"
#include "asm/charge.h"
#define LOG_TAG_CONST LP_KEY
#define LOG_TAG "[LP_KEY]"
/* #define LOG_ERROR_ENABLE */
/* #define LOG_DEBUG_ENABLE */
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_LP_TOUCH_KEY_ENABLE
#define CTMU_CHECK_LONG_CLICK_BY_RES 1
/*************************************************************************************************************************
lp_touch_key driver
*************************************************************************************************************************/
#define LP_TOUCH_KEY_TIMER_MAGIC_NUM 0xFFFF
struct ctmu_key _ctmu_key = {
.slide_dir = TOUCH_KEY_EVENT_MAX,
.click_cnt = {0, 0, 0, 0, 0},
.last_key = {CTMU_KEY_NULL, CTMU_KEY_NULL, CTMU_KEY_NULL, CTMU_KEY_NULL, CTMU_KEY_NULL},
.short_timer = {LP_TOUCH_KEY_TIMER_MAGIC_NUM, LP_TOUCH_KEY_TIMER_MAGIC_NUM, LP_TOUCH_KEY_TIMER_MAGIC_NUM, LP_TOUCH_KEY_TIMER_MAGIC_NUM, LP_TOUCH_KEY_TIMER_MAGIC_NUM},
};
#define __this (&_ctmu_key)
static volatile u8 is_lpkey_active = 0;
extern void lp_touch_key_send_cmd(enum CTMU_M2P_CMD cmd);
//======================================================//
// 内置触摸灵敏度表, 由内置触摸灵敏度调试工具生成 //
// 请将该表替换sdk中lp_touch_key.c中同名的参数表 //
//======================================================//
const static struct ch_adjust_table ch_sensitivity_table[] = {
/* cfg0 cfg1 cfg2 */
//ch0 PB0
{ 109, 131, 4318}, // level 0
{ 109, 131, 3982}, // level 1
{ 109, 131, 3646}, // level 2
{ 109, 131, 3310}, // level 3
{ 109, 131, 2974}, // level 4
{ 109, 131, 2638}, // level 5
{ 109, 131, 2303}, // level 6
{ 109, 131, 1967}, // level 7
{ 109, 131, 1631}, // level 8
{ 109, 131, 1295}, // level 9
//ch1 PB1
{ 10, 15, 126}, // level 0
{ 10, 15, 117}, // level 1
{ 10, 15, 107}, // level 2
{ 10, 15, 97}, // level 3
{ 10, 15, 87}, // level 4
{ 10, 15, 77}, // level 5
{ 10, 15, 67}, // level 6
{ 10, 15, 57}, // level 7
{ 10, 15, 47}, // level 8
{ 10, 15, 38}, // level 9
//ch2 PB2
{ 10, 15, 152}, // level 0
{ 10, 15, 140}, // level 1
{ 10, 15, 128}, // level 2
{ 10, 15, 116}, // level 3
{ 10, 15, 104}, // level 4
{ 10, 15, 92}, // level 5
{ 10, 15, 81}, // level 6
{ 10, 15, 69}, // level 7
{ 10, 15, 57}, // level 8
{ 10, 15, 45}, // level 9
//ch3 PB4
{ 10, 15, 152}, // level 0
{ 10, 15, 140}, // level 1
{ 10, 15, 128}, // level 2
{ 10, 15, 116}, // level 3
{ 10, 15, 104}, // level 4
{ 10, 15, 92}, // level 5
{ 10, 15, 81}, // level 6
{ 10, 15, 69}, // level 7
{ 10, 15, 57}, // level 8
{ 10, 15, 45}, // level 9
//ch4 PB5
{ 109, 131, 4318}, // level 0
{ 109, 131, 3982}, // level 1
{ 109, 131, 3646}, // level 2
{ 109, 131, 3310}, // level 3
{ 109, 131, 2974}, // level 4
{ 109, 131, 2638}, // level 5
{ 109, 131, 2303}, // level 6
{ 109, 131, 1967}, // level 7
{ 109, 131, 1631}, // level 8
{ 109, 131, 1295}, // level 9
};
#define LPCTMU_VH_LEVEL 3 // 上限电压档位
#define LPCTMU_VL_LEVEL 0 // 下限电压档位
#define LPCTMU_CUR_LEVEL 7 // 充放电电流档位
static const u8 lpctmu_ana_vh_table[4] = {
LPCTMU_VH_065V,
LPCTMU_VH_070V,
LPCTMU_VH_075V,
LPCTMU_VH_080V,
};
static const u8 lpctmu_ana_vl_table[4] = {
LPCTMU_VL_020V,
LPCTMU_VL_025V,
LPCTMU_VL_030V,
LPCTMU_VL_035V,
};
static const u8 lpctmu_ana_cur_table[8] = {
LPCTMU_ISEL_036UA,
LPCTMU_ISEL_072UA,
LPCTMU_ISEL_108UA,
LPCTMU_ISEL_144UA,
LPCTMU_ISEL_180UA,
LPCTMU_ISEL_216UA,
LPCTMU_ISEL_252UA,
LPCTMU_ISEL_288UA
};
u8 get_lpctmu_ana_level(void)
{
return ((lpctmu_ana_vh_table[LPCTMU_VH_LEVEL]) | \
(lpctmu_ana_vl_table[LPCTMU_VL_LEVEL]) | \
(lpctmu_ana_cur_table[LPCTMU_CUR_LEVEL]));
}
struct lp_touch_key_alog_cfg {
u16 ready_flag;
u16 range;
s32 sigma;
};
static struct lp_touch_key_alog_cfg alog_cfg[5];
static u32 alog_sta_cnt[5];
static u8 ch_range_sensity[5] = {7, 7, 7, 7, 7};
static u16 save_alog_cfg_timeout[5] = {0, 0, 0, 0, 0};
static u16 ctmu_res_scan_time_add = 0;
#define TOUCH_RANGE_MIN 50
#define TOUCH_RANGE_MAX 500
#define CTMU_RES_BUF_SIZE 15
static u16 ctmu_res_buf[5][CTMU_RES_BUF_SIZE];
static u16 ctmu_res_buf_in[5] = {0, 0, 0, 0, 0};
static u16 falling_res_avg[5] = {0, 0, 0, 0, 0};
static u16 long_event_res_avg[5] = {0, 0, 0, 0, 0};
static const u8 _ch_priv[5] = {0, 1, 2, 3, 4};
int __attribute__((weak)) lp_touch_key_event_remap(struct sys_event *e)
{
return true;
}
static void __ctmu_notify_key_event(struct sys_event *event, u8 ch)
{
#if CFG_DISABLE_KEY_EVENT
return;
#endif
event->type = SYS_KEY_EVENT;
event->u.key.type = KEY_DRIVER_TYPE_CTMU_TOUCH; //区分按键类型
event->arg = (void *)DEVICE_EVENT_FROM_KEY;
if (__this->key_ch_msg_lock) {//锁住期间不能发消息
return;
}
#if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
if (lp_touch_key_online_debug_key_event_handle(ch, event)) {
return;
}
#endif /* #if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE */
if (lp_touch_key_event_remap(event)) {
sys_event_notify(event);
}
}
__attribute__((weak)) u8 remap_ctmu_short_click_event(u8 ch, u8 click_cnt, u8 event)
{
return event;
}
#if (TCFG_LP_SLIDE_KEY_ENABLE && (!TCFG_LP_SLIDE_KEY_SHORT_DISTANCE))
u8 __attribute__((weak)) ctmu_slide_direction_handle(u8 cur_ch, u8 pre_ch)
{
if ((cur_ch == 0xff) || (pre_ch == 0xff)) {
return TOUCH_KEY_EVENT_MAX;
}
u8 dir_case = (pre_ch << 4) | (cur_ch & 0xf);
log_debug("ctmu_touch_key_slide_direction = 0x%x : %x -> %x\n", dir_case, pre_ch, cur_ch);
switch (dir_case) {
case 0x12: //方向 1 -> 2
case 0x23: //方向 2 -> 3
case 0x13: //方向 1 -> 3
return TOUCH_KEY_EVENT_SLIDE_UP;
break;
case 0x32: //方向 3 -> 2
case 0x21: //方向 2 -> 1
case 0x31: //方向 3 -> 1
return TOUCH_KEY_EVENT_SLIDE_DOWN;
break;
}
return TOUCH_KEY_EVENT_MAX;
}
#endif
static void __ctmu_short_click_time_out_handle(void *priv)
{
u8 ch = *((u8 *)priv);
struct sys_event e;
switch (__this->click_cnt[ch]) {
case 0:
return;
break;
case 1:
e.u.key.event = KEY_EVENT_CLICK;
break;
case 2:
e.u.key.event = KEY_EVENT_DOUBLE_CLICK;
break;
case 3:
e.u.key.event = KEY_EVENT_TRIPLE_CLICK;
break;
case 4:
e.u.key.event = KEY_EVENT_FOURTH_CLICK;
break;
case 5:
e.u.key.event = KEY_EVENT_FIRTH_CLICK;
break;
default:
e.u.key.event = KEY_EVENT_USER;
break;
}
e.u.key.event = remap_ctmu_short_click_event(ch, __this->click_cnt[ch], e.u.key.event);
e.u.key.value = __this->config->ch[ch].key_value;
#if (TCFG_LP_SLIDE_KEY_ENABLE && (!TCFG_LP_SLIDE_KEY_SHORT_DISTANCE))
if (__this->slide_dir < TOUCH_KEY_EVENT_MAX) {
e.u.key.event = __this->slide_dir;
e.u.key.value = __this->config->slide_mode_key_value;
__this->slide_dir = ctmu_slide_direction_handle(0xff, 0xff);
}
#endif
log_debug("notify key%d short event, cnt: %d", ch, __this->click_cnt[ch]);
__ctmu_notify_key_event(&e, ch);
__this->short_timer[ch] = LP_TOUCH_KEY_TIMER_MAGIC_NUM;
__this->last_key[ch] = CTMU_KEY_NULL;
__this->click_cnt[ch] = 0;
}
static void ctmu_short_click_handle(u8 ch)
{
static u8 pre_ch = 0xff;
__this->slide_dir = TOUCH_KEY_EVENT_MAX;
__this->last_key[ch] = CTMU_KEY_SHORT_CLICK;
if (__this->short_timer[ch] == LP_TOUCH_KEY_TIMER_MAGIC_NUM) {
#if (TCFG_LP_SLIDE_KEY_ENABLE && (!TCFG_LP_SLIDE_KEY_SHORT_DISTANCE))
if (__this->config->slide_mode_en) {
if ((pre_ch != 0xff) && (pre_ch != ch) && (__this->click_cnt[pre_ch] == 1)) {
usr_timeout_del(__this->short_timer[pre_ch]);
__this->short_timer[pre_ch] = LP_TOUCH_KEY_TIMER_MAGIC_NUM;
__this->click_cnt[pre_ch] = 0;
__this->last_key[pre_ch] = CTMU_KEY_NULL;
__this->slide_dir = ctmu_slide_direction_handle(ch, pre_ch);
}
pre_ch = ch;
}
#endif
__this->click_cnt[ch] = 1;
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
__this->short_timer[ch] = usr_timeout_add((void *)&_ch_priv[ch], __ctmu_short_click_time_out_handle, CTMU_SHORT_CLICK_DELAY_TIME + 150, 1);
#else
__this->short_timer[ch] = usr_timeout_add((void *)&_ch_priv[ch], __ctmu_short_click_time_out_handle, CTMU_SHORT_CLICK_DELAY_TIME, 1);
#endif
} else {
__this->click_cnt[ch]++;
usr_timer_modify(__this->short_timer[ch], CTMU_SHORT_CLICK_DELAY_TIME);
}
}
static void ctmu_raise_click_handle(u8 ch)
{
struct sys_event e = {0};
if (__this->last_key[ch] >= CTMU_KEY_LONG_CLICK) {
e.u.key.event = KEY_EVENT_UP;
e.u.key.value = __this->config->ch[ch].key_value;
__ctmu_notify_key_event(&e, ch);
__this->last_key[ch] = CTMU_KEY_NULL;
log_debug("notify key HOLD UP event");
} else {
ctmu_short_click_handle(ch);
}
}
static void ctmu_long_click_handle(u8 ch)
{
__this->last_key[ch] = CTMU_KEY_LONG_CLICK;
struct sys_event e;
e.u.key.event = KEY_EVENT_LONG;
e.u.key.value = __this->config->ch[ch].key_value;
__ctmu_notify_key_event(&e, ch);
}
static void ctmu_hold_click_handle(u8 ch)
{
__this->last_key[ch] = CTMU_KEY_HOLD_CLICK;
struct sys_event e;
e.u.key.event = KEY_EVENT_HOLD;
e.u.key.value = __this->config->ch[ch].key_value;
__ctmu_notify_key_event(&e, ch);
}
#if TCFG_LP_EARTCH_KEY_ENABLE
__attribute__((weak))
void ear_lptouch_update_state(u8 state)
{
return;
}
static void __ctmu_ear_in_timeout_handle(void *priv)
{
#if CFG_DISABLE_INEAR_EVENT
return;
#endif
if (__this->config->ch[__this->config->eartch_ch].key_value == 0xFF) {
//使用外部自定义流程
if (__this->eartch_last_state == EAR_IN) {
ear_lptouch_update_state(0);
} else {
ear_lptouch_update_state(1);
}
return;
}
#if TCFG_EARTCH_EVENT_HANDLE_ENABLE
u8 state;
if (__this->eartch_last_state == EAR_IN) {
state = EARTCH_STATE_IN;
} else if (__this->eartch_last_state == EAR_OUT) {
state = EARTCH_STATE_OUT;
} else {
return;
}
eartch_state_update(state);
#endif /* #if TCFG_EARTCH_EVENT_HANDLE_ENABLE */
}
static void __ctmu_key_unlock_timeout_handle(void *priv)
{
__this->key_ch_msg_lock = false;
__this->key_ch_msg_lock_timer = 0;
}
static void ctmu_eartch_event_handle(u8 eartch_state)
{
__this->eartch_last_state = eartch_state;
#if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
struct sys_event event;
if (eartch_state == EAR_IN) {
event.u.key.event = 10;
} else if (eartch_state == EAR_OUT) {
event.u.key.event = 11;
}
if (lp_touch_key_online_debug_key_event_handle(__this->config->eartch_ch, &event)) {
return;
}
#endif /* #if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE */
__this->key_ch_msg_lock = true;
if (__this->key_ch_msg_lock_timer == 0) {
__this->key_ch_msg_lock_timer = sys_hi_timeout_add(NULL, __ctmu_key_unlock_timeout_handle, ERATCH_KEY_MSG_LOCK_TIME);
} else {
sys_hi_timer_modify(__this->key_ch_msg_lock_timer, ERATCH_KEY_MSG_LOCK_TIME);
}
__ctmu_ear_in_timeout_handle(NULL);
}
#endif
/*************************************************************************************************************************
lp_touch_key driver
*************************************************************************************************************************/
#if CTMU_CHECK_LONG_CLICK_BY_RES
static void lp_touch_key_ctmu_res_buf_clear(u8 ch)
{
ctmu_res_buf_in[ch] = 0;
for (u8 i = 0; i < CTMU_RES_BUF_SIZE; i ++) {
ctmu_res_buf[ch][i] = 0;
}
}
static void lp_touch_key_ctmu_res_all_buf_clear(void)
{
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
lp_touch_key_ctmu_res_buf_clear(ch);
}
}
static u32 lp_touch_key_ctmu_res_buf_avg(u8 ch)
{
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
u32 res_sum = 0;
u8 j = 0;
u8 cnt = ctmu_res_buf_in[ch];
for (u8 i = 0; i < (CTMU_RES_BUF_SIZE - 5); i ++) {
if (ctmu_res_buf[ch][cnt]) {
res_sum += ctmu_res_buf[ch][cnt];
j ++;
} else {
return 0;
}
cnt ++;
if (cnt >= CTMU_RES_BUF_SIZE) {
cnt = 0;
}
}
if (res_sum) {
return (res_sum / j);
}
#endif
return 0;
}
static u8 lp_touch_key_check_long_click_by_ctmu_res(u8 ch)
{
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
long_event_res_avg[ch] = lp_touch_key_ctmu_res_buf_avg(ch);
log_debug("long_event_res_avg: %d\n", long_event_res_avg[ch]);
if ((falling_res_avg[ch] < 2000) || \
(falling_res_avg[ch] > 20000) || \
(long_event_res_avg[ch] < 2000) || \
(long_event_res_avg[ch] > 20000)) {
} else {
u16 cfg2 = (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8) << 8) | M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8);
u16 diff = (falling_res_avg[ch] > long_event_res_avg[ch]) ? (falling_res_avg[ch] - long_event_res_avg[ch]) : (long_event_res_avg[ch] - falling_res_avg[ch]);
if (diff < (cfg2 / 2)) {
log_debug("long event return ! diff: %d < cfg2/2: %d\n", diff, (cfg2 / 2));
//复位算法
lp_touch_key_send_cmd(CTMU_M2P_RESET_ALGO);
return 1;
}
}
#endif
return 0;
}
#endif
u8 lp_touch_key_alog_range_display(u8 *display_buf)
{
if (__this->init == 0) {
return 0;
}
u8 tmp_buf[32], i = 0;
memset(tmp_buf, 0, sizeof(tmp_buf));
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
u16 range = alog_cfg[ch].range % 1000;
tmp_buf[0 + i * 4] = (range / 100) + '0';
tmp_buf[1 + i * 4] = ((range % 100) / 10) + '0';
tmp_buf[2 + i * 4] = (range % 10) + '0';
tmp_buf[3 + i * 4] = ' ';
i ++;
}
}
if (i) {
display_buf[0] = i * 4 + 1;
display_buf[1] = 0x01;
memcpy((u8 *)&display_buf[2], tmp_buf, i * 4);
printf_buf(display_buf, i * 4 + 2);
return (display_buf[0] + 1);
}
return 0;
}
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
void lp_touch_key_save_alog_cfg(void *priv)
{
u8 ch = *((u8 *)priv);
int ret = syscfg_write(VM_LP_TOUCH_KEY0_ALOG_CFG + ch, (void *)&alog_cfg[ch], sizeof(struct lp_touch_key_alog_cfg));
if (ret != sizeof(struct lp_touch_key_alog_cfg)) {
log_info("write vm alog cfg ready flag error !\n");
}
save_alog_cfg_timeout[ch] = 0;
}
void lp_touch_key_ctmu_cfg2_check_update(u8 ch, u16 cfg2_new)
{
u16 cfg0 = (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0H + ch * 8) << 8) | M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0L + ch * 8);
u16 cfg2_old = (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8) << 8) | M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8);
if ((cfg2_old != cfg2_new) && (cfg2_new > (3 * cfg0))) {
printf("ctmu ch%d cfg2_old = %d cfg2_new = %d\n", ch, cfg2_old, cfg2_new);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8) = cfg2_new & 0xff;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8) = (cfg2_new >> 8) & 0xff;
u16 cfg1 = (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1H + ch * 8) << 8) | (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1L + ch * 8));
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0L + ch * 8) = cfg1 & 0xff;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0H + ch * 8) = (cfg1 >> 8) & 0xff;
}
}
static void lp_touch_key_ctmu_res_scan(void *priv)
{
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
if (__this->config->eartch_en && (__this->config->eartch_ch == ch)) {
} else {
u16 ctmu_res0;
u16 ctmu_res1;
__read_res:
ctmu_res0 = (P2M_MESSAGE_ACCESS(P2M_MASSAGE_CTMU_CH0_H_RES + ch * 2) << 8) | P2M_MESSAGE_ACCESS(P2M_MASSAGE_CTMU_CH0_L_RES + ch * 2);
delay(100);
ctmu_res1 = (P2M_MESSAGE_ACCESS(P2M_MASSAGE_CTMU_CH0_H_RES + ch * 2) << 8) | P2M_MESSAGE_ACCESS(P2M_MASSAGE_CTMU_CH0_L_RES + ch * 2);
if (ctmu_res0 != ctmu_res1) {
goto __read_res;
}
#if 1
if ((ctmu_res0 < 2000) || (ctmu_res0 > 20000)) {
continue;
}
#if CTMU_CHECK_LONG_CLICK_BY_RES
ctmu_res_buf[ch][ctmu_res_buf_in[ch]] = ctmu_res0;
ctmu_res_buf_in[ch] ++;
if (ctmu_res_buf_in[ch] >= CTMU_RES_BUF_SIZE) {
ctmu_res_buf_in[ch] = 0;
}
#endif
if (alog_cfg[ch].ready_flag == 0) {
continue;
}
if (alog_sta_cnt[ch] < 50) {
alog_sta_cnt[ch] ++;
continue;
}
TouchAlgo_Update(ch, ctmu_res0);
u8 range_valid = 0;
u16 touch_range = TouchAlgo_GetRange(ch, (u8 *)&range_valid);
s32 touch_sigma = TouchAlgo_GetSigma(ch);
/* printf("ch%d res:%d range:%d val:%d sigma:%d\n", ch, ctmu_res0, touch_range, range_valid, touch_sigma); */
if ((range_valid) && (touch_range > TOUCH_RANGE_MIN) && (touch_range < TOUCH_RANGE_MAX)) {
if (touch_range != alog_cfg[ch].range) {
u16 cfg2_new = touch_range * (10 - ch_range_sensity[ch]) / 10;
lp_touch_key_ctmu_cfg2_check_update(ch, cfg2_new);
alog_cfg[ch].range = touch_range;
alog_cfg[ch].sigma = touch_sigma;
if (save_alog_cfg_timeout[ch] == 0) {
save_alog_cfg_timeout[ch] = sys_timeout_add((void *)&_ch_priv[ch], lp_touch_key_save_alog_cfg, 1);
}
}
} else if ((range_valid) && (touch_range >= TOUCH_RANGE_MAX)) {
TouchAlgo_SetRange(ch, alog_cfg[ch].range);
}
#endif
}
}
}
}
void lp_touch_key_alog_ready_flag_check_and_set(void)
{
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
if (__this->config->eartch_en && (__this->config->eartch_ch == ch)) {
} else {
alog_cfg[ch].ready_flag = 0;
syscfg_read(VM_LP_TOUCH_KEY0_ALOG_CFG + ch, (void *)&alog_cfg[ch], sizeof(struct lp_touch_key_alog_cfg));
if (alog_cfg[ch].ready_flag == 0) {
alog_cfg[ch].ready_flag = 1;
lp_touch_key_save_alog_cfg((void *)&ch);
}
}
}
}
}
#endif
static void ctmu_port_init(u8 port)
{
gpio_set_die(port, 0);
gpio_set_dieh(port, 0);
gpio_set_direction(port, 1);
gpio_set_pull_down(port, 0);
gpio_set_pull_up(port, 0);
}
u8 p11_wakeup_query(void)
{
return is_wakeup_source(PWR_WK_REASON_P11);
};
void lp_touch_key_send_cmd(enum CTMU_M2P_CMD cmd)
{
M2P_CTMU_CMD = cmd;
P11_M2P_INT_SET = BIT(M2P_CTMU_INDEX);
}
#define IO_RESET_PORTB_01 18
void lp_touch_key_init(const struct lp_touch_key_platform_data *config)
{
log_info("%s >>>>", __func__);
ASSERT(config && (__this->init == 0));
__this->config = config;
u8 pinr_io;
if (P33_CON_GET(P3_PINR_CON) & BIT(0)) {
pinr_io = P33_CON_GET(P3_PORT_SEL0);
if (pinr_io == IO_RESET_PORTB_01) {
P33_CON_SET(P3_PINR_CON, 0, 8, 0);
P33_CON_SET(P3_PINR_CON1, 0, 8, 0x16);
P33_CON_SET(P3_PINR_CON1, 0, 1, 1);
log_info("reset pin change: old: %d, P3_PINR_CON1 = 0x%x", pinr_io, P33_CON_GET(P3_PINR_CON1));
}
}
u8 ch_enable = 0;
u8 ch_wakeup_en = 0;
u8 ch_debug = 0;
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
ch_enable |= BIT(ch);
if (__this->config->ch[ch].wakeup_enable) {
ch_wakeup_en |= BIT(ch);
}
if (CFG_CHx_DEBUG_ENABLE & BIT(ch)) {
ch_debug |= BIT(ch);
}
}
}
if (p11_wakeup_query() == 0 || get_charge_online_flag() || (!(ch_wakeup_en)) || (is_ldo5v_wakeup())) {
for (u32 m2p_addr = 0x18; m2p_addr < 0x56; m2p_addr ++) {
M2P_MESSAGE_ACCESS(m2p_addr) = 0;
}
for (u32 p2m_addr = 0x10; p2m_addr < 0x24; p2m_addr ++) {
P2M_MESSAGE_ACCESS(p2m_addr) = 0;
}
}
M2P_CTMU_MSG = 0;
M2P_CTMU_CH_CFG = 0;
M2P_CTMU_TIME_BASE = CTMU_SAMPLE_RATE_PRD;
M2P_CTMU_LONG_TIMEL = (CTMU_LONG_KEY_DELAY_TIME & 0xFF);
M2P_CTMU_LONG_TIMEH = ((CTMU_LONG_KEY_DELAY_TIME >> 8) & 0xFF);
M2P_CTMU_HOLD_TIMEL = (CTMU_HOLD_CLICK_DELAY_TIME & 0xFF);
M2P_CTMU_HOLD_TIMEH = ((CTMU_HOLD_CLICK_DELAY_TIME >> 8) & 0xFF);
M2P_CTMU_SOFTOFF_LONG_TIMEL = (CFG_M2P_CTMU_SOFTOFF_LONG_TIME & 0xFF);
M2P_CTMU_SOFTOFF_LONG_TIMEH = ((CFG_M2P_CTMU_SOFTOFF_LONG_TIME >> 8) & 0xFF);
#if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_L = 0;
M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_H = 0;
#else
M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_L = (CTMU_RESET_TIME_CONFIG & 0xFF);
M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_H = ((CTMU_RESET_TIME_CONFIG >> 8) & 0xFF);
#endif
log_info("M2P_CTMU_LONG_TIMEL = 0x%x", M2P_CTMU_LONG_TIMEL);
log_info("M2P_CTMU_LONG_TIMEH = 0x%x", M2P_CTMU_LONG_TIMEH);
log_info("M2P_CTMU_HOLD_TIMEL = 0x%x", M2P_CTMU_HOLD_TIMEL);
log_info("M2P_CTMU_HOLD_TIMEH = 0x%x", M2P_CTMU_HOLD_TIMEH);
log_info("M2P_CTMU_SOFTOFF_LONG_TIMEL = 0x%x", M2P_CTMU_SOFTOFF_LONG_TIMEL);
log_info("M2P_CTMU_SOFTOFF_LONG_TIMEH = 0x%x", M2P_CTMU_SOFTOFF_LONG_TIMEH);
log_info("M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_L = 0x%x", M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_L);
log_info("M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_H = 0x%x", M2P_CTMU_LONG_PRESS_RESET_TIME_VALUE_H);
M2P_CTMU_CH_ENABLE = ch_enable;
M2P_CTMU_CH_WAKEUP_EN = ch_wakeup_en;
M2P_CTMU_CH_DEBUG = ch_debug;
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
u8 ch_sensity = __this->config->ch[ch].sensitivity;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0L + ch * 8) = ((ch_sensitivity_table[ch_sensity + ch * 10].cfg0) & 0xFF);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0H + ch * 8) = (((ch_sensitivity_table[ch_sensity + ch * 10].cfg0) >> 8) & 0xFF);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1L + ch * 8) = ((ch_sensitivity_table[ch_sensity + ch * 10].cfg1) & 0xFF);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1H + ch * 8) = (((ch_sensitivity_table[ch_sensity + ch * 10].cfg1) >> 8) & 0xFF);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8) = ((ch_sensitivity_table[ch_sensity + ch * 10].cfg2) & 0xFF);
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8) = (((ch_sensitivity_table[ch_sensity + ch * 10].cfg2) >> 8) & 0xFF);
log_info("M2P_CTMU_CH%d_CFG0L = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0L + ch * 8));
log_info("M2P_CTMU_CH%d_CFG0H = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0H + ch * 8));
log_info("M2P_CTMU_CH%d_CFG1L = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1L + ch * 8));
log_info("M2P_CTMU_CH%d_CFG1H = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1H + ch * 8));
log_info("M2P_CTMU_CH%d_CFG2L = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8));
log_info("M2P_CTMU_CH%d_CFG2H = 0x%x", ch, M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8));
ctmu_port_init(__this->config->ch[ch].port);
#if TCFG_LP_EARTCH_KEY_ENABLE
if (__this->config->eartch_en && (__this->config->eartch_ch == ch)) {
M2P_CTMU_CH_CFG |= BIT(1);
M2P_CTMU_EARTCH_CH = (__this->config->eartch_ref_ch << 4) | (__this->config->eartch_ch & 0xf);
#if (TCFG_EARTCH_EVENT_HANDLE_ENABLE && TCFG_LP_EARTCH_KEY_ENABLE)
extern int eartch_event_deal_init(void);
eartch_event_deal_init();
#endif
u16 trim_value;
int ret = syscfg_read(LP_KEY_EARTCH_TRIM_VALUE, &trim_value, sizeof(trim_value));
__this->eartch_trim_flag = 0;
__this->eartch_inear_ok = 0;
__this->eartch_trim_value = 0;
if (ret > 0) {
__this->eartch_inear_ok = 1;
__this->eartch_trim_value = trim_value;
log_info("eartch_trim_value = %d", __this->eartch_trim_value);
M2P_CTMU_EARTCH_TRIM_VALUE_L = (__this->eartch_trim_value & 0xFF);
M2P_CTMU_EARTCH_TRIM_VALUE_H = ((__this->eartch_trim_value >> 8) & 0xFF);
} else {
//没有trim的情况下用不了
M2P_CTMU_EARTCH_TRIM_VALUE_L = (10000 & 0xFF);
M2P_CTMU_EARTCH_TRIM_VALUE_H = ((10000 >> 8) & 0xFF);
}
//软件触摸灵敏度调试
M2P_CTMU_INEAR_VALUE_L = __this->config->eartch_soft_inear_val & 0xFF;
M2P_CTMU_INEAR_VALUE_H = __this->config->eartch_soft_inear_val >> 8;
M2P_CTMU_OUTEAR_VALUE_L = __this->config->eartch_soft_outear_val & 0xFF;
M2P_CTMU_OUTEAR_VALUE_H = __this->config->eartch_soft_outear_val >> 8;
} else
#endif
{
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
TouchAlgo_Init(ch, TOUCH_RANGE_MIN, TOUCH_RANGE_MAX);
alog_sta_cnt[ch] = 0;
ch_range_sensity[ch] = ch_sensity;
log_info("read vm alog cfg\n");
int ret = syscfg_read(VM_LP_TOUCH_KEY0_ALOG_CFG + ch, (void *)&alog_cfg[ch], sizeof(struct lp_touch_key_alog_cfg));
if ((ret == (sizeof(struct lp_touch_key_alog_cfg))) && (alog_cfg[ch].range > TOUCH_RANGE_MIN) && (alog_cfg[ch].range < TOUCH_RANGE_MAX)) {
log_info("vm read ch%d alog ready:%d sigma:%d range:%d\n", ch, alog_cfg[ch].ready_flag, alog_cfg[ch].sigma, alog_cfg[ch].range);
u16 cfg0 = (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0H + ch * 8) << 8) | (M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG0L + ch * 8));
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1L + ch * 8) = (cfg0 + 5) & 0xff;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG1H + ch * 8) = ((cfg0 + 5) >> 8) & 0xff;
u16 cfg2_new = alog_cfg[ch].range * (10 - ch_range_sensity[ch]) / 10;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2L + ch * 8) = cfg2_new & 0xff;
M2P_MESSAGE_ACCESS(M2P_MASSAGE_CTMU_CH0_CFG2H + ch * 8) = (cfg2_new >> 8) & 0xff;
TouchAlgo_SetSigma(ch, alog_cfg[ch].sigma);
TouchAlgo_SetRange(ch, alog_cfg[ch].range);
}
#endif
}
}
}
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
#if 1 //触摸算法要尽可能的在装完整机之后开始跑而这里是耳机生产流程中获取它第一次在舱内开机的时候在vm标记一个变量从此开始跑算法。
if (get_charge_online_flag()) {
log_info("check charge online!\n");
lp_touch_key_alog_ready_flag_check_and_set();//如果有其他好的位置,请将该函数移到那个位置执行。
}
#endif
if (ctmu_res_scan_time_add == 0) {
ctmu_res_scan_time_add = usr_timer_add(NULL, lp_touch_key_ctmu_res_scan, 20, 0);
}
#if CTMU_CHECK_LONG_CLICK_BY_RES
lp_touch_key_ctmu_res_all_buf_clear();
#endif
#endif
//CTMU 初始化命令
if (p11_wakeup_query() == 0 || get_charge_online_flag() || (!(ch_wakeup_en)) || (is_ldo5v_wakeup())) {
log_info("lp touch init by %d_%d_%d_%d\n", p11_wakeup_query(), get_charge_online_flag(), (!(ch_wakeup_en)), is_ldo5v_wakeup());
LPCTMU_ANA0_CONFIG(get_lpctmu_ana_level());
P2M_CTMU_WKUP_MSG &= (~(P2M_MESSAGE_INIT_MODE_FLAG));
} else {
P2M_CTMU_WKUP_MSG |= (P2M_MESSAGE_INIT_MODE_FLAG);
log_info("p11 wakeup, lp touch key continue work");
}
__this->softoff_mode = LP_TOUCH_SOFTOFF_MODE_ADVANCE;
log_info("M2P_CTMU_CH_ENABLE = 0x%x", M2P_CTMU_CH_ENABLE);
log_info("M2P_CTMU_CH_WAKEUP_EN = 0x%x", M2P_CTMU_CH_WAKEUP_EN);
log_info("M2P_CTMU_CH_CFG = 0x%x", M2P_CTMU_CH_CFG);
log_info("M2P_CTMU_EARTCH_CH = 0x%x", M2P_CTMU_EARTCH_CH);
lp_touch_key_send_cmd(CTMU_M2P_INIT);
#if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
lp_touch_key_online_debug_init();
#endif /* #if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE */
__this->init = 1;
}
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
/******************************双通道滑动触摸识别的基础原理***********************************
1.
chx __________________________________________
chx ___________ __________
|_______>180________|
2.
chx ___________ __________
|_______>180________|
chx _______ <30 <30 ______
|___________________________|
3.
chx ___________ __________
|_______>180________|
chx _______ <30 >30 __
|_______________________________|
4.
chx ___________ __________
|_______>180________|
chx ___ >30 <30 ______
|_______________________________|
5.
chx ___________ __________
|_______>180________|
chx ___ >30 >30 __
|___________________________________|
6.
chx ___________ ______
|_______________________|
chx _______ <30 >180 _<30______
|_______________________|
7.
chx ___________ __________
|_______________|
chx _______ <30 <180 _<30__________
|_______________|
8.t <
chx ___________ __________
|_______________|
chx ___ >30 t _<30__________
|___________________|
9.t <
chx ___________ ______
|___________________|
chx ___ >30 t __>30_________
|___________________|
10.t <
chx ___________ ______
|___________________|
chx _______ <30 t __>30_________
|_______________|
*****************************************************************************/
enum falling_order_type {
FALLING_NULL,
FALLING_FIRST,
FALLING_SECOND,
};
enum raising_order_type {
RAISING_NULL,
RAISING_FIRST,
RAISING_SECOND,
};
enum time_interval_type {
LONG_TIME,
SHORT_TIME,
};
enum slide_key_type {
SHORT_CLICK = 1,
DOUBLE_CLICK,
TRIPLE_CLICK,
FOURTH_CLICK,
FIRTH_CLICK,
LONG_CLICK = 8,
LONG_HOLD_CLICK = 9,
LONG_UP_CLICK = 10,
SLIDE_UP = 0x12,
SLIDE_DOWN = 0x21,
};
static u8 falling_order[2] = {FALLING_NULL, FALLING_NULL};
static u8 raising_order[2] = {RAISING_NULL, RAISING_NULL};
static u8 falling_time_interval = 0;
static u8 raising_time_interval = 0;
static u8 last_key_type = 0;
#define FALLING_TIMEOUT_TIME 30 //两个按下边沿的时间间隔的阈值
static int falling_timeout_add = 0;
static void falling_timeout_handle(void *priv)
{
falling_timeout_add = 0;
}
#define RAISING_TIMEOUT_TIME 30 //两个抬起边沿的时间间隔的阈值
static int raising_timeout_add = 0;
static void raising_timeout_handle(void *priv)
{
raising_timeout_add = 0;
}
#define CLICK_IDLE_TIMEOUT_TIME 500 //如果该时间内,没有单击,那么该时间之后的第一次单击,识别为首次单击
static int click_idle_timeout_add = 0;
static void click_idle_timeout_handle(void *priv)
{
click_idle_timeout_add = 0;
}
#define FIRST_SHORT_CLICK_TIMEOUT_TIME 190 //只针对首次单击,要满足按够那么长时间。连击时,后面的单击没有该时间要求
static int first_short_click_timeout_add = 0;
static void first_short_click_timeout_handle(void *priv)
{
first_short_click_timeout_add = 0;
}
void __attribute__((weak)) send_keytone_event(void)
{
//可以在此处发送按键音的消息
/* struct sys_event e; */
/* e.u.key.event = 5; */
/* e.u.key.value = 3; */
/* __ctmu_notify_key_event(&e, 0); */
}
#define SEND_KEYTONE_TIMEOUT_TIME 250 //长按时的按键音,在按下后的多长时间要响
static u8 send_keytone_flag = 0;
static int send_keytone_timeout_add = 0;
static void send_keytone_timeout_handle(void *priv)
{
send_keytone_event();
send_keytone_timeout_add = 0;
send_keytone_flag = 1;
}
#define SLIDE_CLICK_TIMEOUT_TIME 500 //识别为滑动之后该时间内如果有case7.也要识别为滑动
#define FAST_SLIDE_CNT_MAX 4 //一来就连续那么多次的case7.,就会识别为一次滑动。
static u8 fast_slide_cnt = 0;
static u8 fast_slide_type = 0;
static int slide_click_timeout_add = 0;
void slide_click_timeout_handle(void *priv)
{
slide_click_timeout_add = 0;
}
static void check_channel_falling_info(u8 ch)
{
falling_order[ch] = FALLING_FIRST;
if (falling_order[!ch] == FALLING_FIRST) {
falling_order[ch] = FALLING_SECOND;
}
send_keytone_flag = 0;
if (send_keytone_timeout_add == 0) {
send_keytone_timeout_add = sys_hi_timeout_add(NULL, send_keytone_timeout_handle, SEND_KEYTONE_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(send_keytone_timeout_add, SEND_KEYTONE_TIMEOUT_TIME);
}
if ((last_key_type != SHORT_CLICK) || (click_idle_timeout_add == 0)) {
if (first_short_click_timeout_add == 0) {
first_short_click_timeout_add = sys_hi_timeout_add(NULL, first_short_click_timeout_handle, FIRST_SHORT_CLICK_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(first_short_click_timeout_add, FIRST_SHORT_CLICK_TIMEOUT_TIME);
}
}
if (falling_order[ch] == FALLING_FIRST) {
if (falling_timeout_add == 0) {
falling_timeout_add = sys_hi_timeout_add(NULL, falling_timeout_handle, FALLING_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(falling_timeout_add, FALLING_TIMEOUT_TIME);
}
falling_time_interval = SHORT_TIME;
} else if (falling_order[ch] == FALLING_SECOND) {
if (falling_timeout_add) {
sys_hi_timeout_del(falling_timeout_add);
falling_timeout_add = 0;
falling_time_interval = SHORT_TIME;
} else {
falling_time_interval = LONG_TIME;
}
}
}
static u8 check_channel_raising_info_and_key_type(u8 ch)
{
u8 key_type = 0;
fast_slide_type = 0;
if (falling_order[ch] == FALLING_NULL) {
return key_type;
}
raising_order[ch] = RAISING_FIRST;
if (raising_order[!ch] == RAISING_FIRST) {
raising_order[ch] = RAISING_SECOND;
}
if (falling_order[ch] > falling_order[!ch]) {
if (raising_order[ch] == RAISING_FIRST) {
key_type = SHORT_CLICK; //case 1~5.
} else {
if (falling_time_interval == SHORT_TIME) {
if (raising_timeout_add) {
sys_hi_timeout_del(raising_timeout_add);
raising_timeout_add = 0;
key_type = SHORT_CLICK; //case 6~7.
if (ch == 0) {
fast_slide_type = SLIDE_DOWN;
} else {
fast_slide_type = SLIDE_UP;
}
} else if (ch == 0) {
key_type = SLIDE_DOWN; //case 10.
} else {
key_type = SLIDE_UP; //case 10.
}
} else if (ch == 0) {
key_type = SLIDE_DOWN; //caee 8~9.
} else {
key_type = SLIDE_UP; //case 8~9.
}
}
} else {
if (raising_order[ch] == RAISING_FIRST) {
if (falling_time_interval == SHORT_TIME) {
if (raising_timeout_add == 0) {
raising_timeout_add = sys_hi_timeout_add(NULL, raising_timeout_handle, RAISING_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(raising_timeout_add, RAISING_TIMEOUT_TIME);
}
} else if (ch == 0) {
key_type = SLIDE_UP; //case 8~9.
} else {
key_type = SLIDE_DOWN; //case 8~9.
}
} else {
if (falling_time_interval == SHORT_TIME) {
if (raising_timeout_add) {
sys_hi_timeout_del(raising_timeout_add);
raising_timeout_add = 0;
key_type = SHORT_CLICK; //case 6~7
if (ch == 0) {
fast_slide_type = SLIDE_UP;
} else {
fast_slide_type = SLIDE_DOWN;
}
} else if (ch == 0) {
key_type = SLIDE_UP; //case 10.
} else {
key_type = SLIDE_DOWN; //case 10.
}
} else if (ch == 0) {
key_type = SLIDE_UP; //case 8~9.
} else {
key_type = SLIDE_DOWN; //case 8~9.
}
}
}
return key_type;
}
static u8 get_slide_event_ch(void)
{
u8 event_ch = 1;
for (u8 ch = 0; ch < LP_CTMU_CHANNEL_SIZE; ch ++) {
if (__this->config->ch[ch].enable) {
event_ch = ch;
break;
}
}
return event_ch;
}
static u8 check_slide_key_type(u8 event, u8 ch)
{
u8 key_type = 0;
u8 event_ch = get_slide_event_ch();
if (event == (CTMU_P2M_CH0_FALLING_EVENT + ch * 8)) {
if (ch == event_ch) {
check_channel_falling_info(0);
} else {
check_channel_falling_info(1);
}
} else if (event == (CTMU_P2M_CH0_RAISING_EVENT + ch * 8)) {
if (ch == event_ch) {
if ((last_key_type == LONG_CLICK) || (last_key_type == LONG_HOLD_CLICK)) {
key_type = LONG_UP_CLICK; //一定是长按抬起
} else {
key_type = check_channel_raising_info_and_key_type(0);
}
} else {
key_type = check_channel_raising_info_and_key_type(1);
}
} else if (event == (CTMU_P2M_CH0_LONG_KEY_EVENT + event_ch * 8)) {//长按只判断通道号小的那个按键
key_type = LONG_CLICK;
} else if (event == (CTMU_P2M_CH0_HOLD_KEY_EVENT + event_ch * 8)) {//长按只判断通道号小的那个按键
key_type = LONG_HOLD_CLICK;
}
if (key_type) {
falling_order[0] = FALLING_NULL;
falling_order[1] = FALLING_NULL;
raising_order[0] = RAISING_NULL;
raising_order[1] = RAISING_NULL;
falling_time_interval = 0;
last_key_type = key_type;
if (send_keytone_timeout_add) {
sys_hi_timeout_del(send_keytone_timeout_add);
send_keytone_timeout_add = 0;
}
if (key_type == SHORT_CLICK) { //case 6~7 的进一步处理
if (first_short_click_timeout_add) {
sys_hi_timeout_del(first_short_click_timeout_add);
first_short_click_timeout_add = 0;
if (slide_click_timeout_add) {
sys_hi_timeout_del(slide_click_timeout_add);
slide_click_timeout_add = 0;
if (fast_slide_type) {
key_type = fast_slide_type;
last_key_type = key_type;
} else {
key_type = 0xff;
last_key_type = key_type;
}
fast_slide_cnt = 0;
} else {
if (fast_slide_type) {
fast_slide_cnt ++;
if (fast_slide_cnt >= FAST_SLIDE_CNT_MAX) {
fast_slide_cnt = 0;
key_type = fast_slide_type;
last_key_type = key_type;
} else {
key_type = 0xff;
last_key_type = key_type;
}
} else {
fast_slide_cnt = 0;
key_type = 0xff;
last_key_type = key_type;
}
}
} else {
if (send_keytone_flag == 0) {
send_keytone_event();
}
if (slide_click_timeout_add) {
sys_hi_timeout_del(slide_click_timeout_add);
slide_click_timeout_add = 0;
}
fast_slide_cnt = 0;
}
if (click_idle_timeout_add == 0) {
click_idle_timeout_add = sys_hi_timeout_add(NULL, click_idle_timeout_handle, CLICK_IDLE_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(click_idle_timeout_add, CLICK_IDLE_TIMEOUT_TIME);
}
} else {
fast_slide_cnt = 0;
}
if ((key_type == SLIDE_UP) || (key_type == SLIDE_DOWN)) {
if (slide_click_timeout_add == 0) {
slide_click_timeout_add = sys_hi_timeout_add(NULL, slide_click_timeout_handle, SLIDE_CLICK_TIMEOUT_TIME);
} else {
sys_hi_timer_modify(slide_click_timeout_add, SLIDE_CLICK_TIMEOUT_TIME);
}
}
}
return key_type;
}
static void ctmu_send_slide_key_type_event(u8 key_type)
{
struct sys_event e;
u8 event_ch = get_slide_event_ch();
switch (key_type) {
case SHORT_CLICK: //单击
ctmu_short_click_handle(event_ch);
break;
case LONG_CLICK: //长按
#if CTMU_CHECK_LONG_CLICK_BY_RES
if (lp_touch_key_check_long_click_by_ctmu_res(event_ch)) {
last_key_type = 0;
return;
}
#endif
ctmu_long_click_handle(event_ch);
break;
case LONG_HOLD_CLICK: //长按保持
#if CTMU_CHECK_LONG_CLICK_BY_RES
if (lp_touch_key_check_long_click_by_ctmu_res(event_ch)) {
last_key_type = 0;
return;
}
#endif
ctmu_hold_click_handle(event_ch);
break;
case LONG_UP_CLICK: //长按抬起
ctmu_raise_click_handle(event_ch);
break;
case SLIDE_UP: //向上滑动
e.u.key.event = TOUCH_KEY_EVENT_SLIDE_UP;
e.u.key.value = __this->config->slide_mode_key_value;
printf("key.event = TOUCH_KEY_EVENT_SLIDE_UP\n");
printf("key.value = %d\n", e.u.key.value);
__ctmu_notify_key_event(&e, event_ch);
break;
case SLIDE_DOWN: //向下滑动
e.u.key.event = TOUCH_KEY_EVENT_SLIDE_DOWN;
e.u.key.value = __this->config->slide_mode_key_value;
printf("key.event = TOUCH_KEY_EVENT_SLIDE_DOWN\n");
printf("key.value = %d\n", e.u.key.value);
__ctmu_notify_key_event(&e, event_ch);
break;
default:
break;
}
}
#endif
u8 last_state = CTMU_P2M_EARTCH_OUT_EVENT;
void p33_ctmu_key_event_irq_handler()
{
u8 ret = 0;
u8 ctmu_event = P2M_CTMU_KEY_EVENT;
u8 ch_num = P2M_CTMU_KEY_CNT;
u16 ch_res = 0;
u16 chx_res[LP_CTMU_CHANNEL_SIZE];
#if TCFG_LP_EARTCH_KEY_ENABLE
if (testbox_get_key_action_test_flag(NULL)) {
if (__this->config->eartch_en && (__this->config->eartch_ch == ch_num)) {
ret = lp_touch_key_testbox_remote_test(ch_num, ctmu_event);
if (ret == true) {
return;
}
}
}
#endif
/* printf("ctmu_event = 0x%x\n", ctmu_event); */
switch (ctmu_event) {
case CTMU_P2M_CH0_RES_EVENT:
case CTMU_P2M_CH1_RES_EVENT:
case CTMU_P2M_CH2_RES_EVENT:
case CTMU_P2M_CH3_RES_EVENT:
case CTMU_P2M_CH4_RES_EVENT:
chx_res[0] = (P2M_CTMU_CH0_H_RES << 8) | P2M_CTMU_CH0_L_RES;
chx_res[1] = (P2M_CTMU_CH1_H_RES << 8) | P2M_CTMU_CH1_L_RES;
chx_res[2] = (P2M_CTMU_CH2_H_RES << 8) | P2M_CTMU_CH2_L_RES;
chx_res[3] = (P2M_CTMU_CH3_H_RES << 8) | P2M_CTMU_CH3_L_RES;
chx_res[4] = (P2M_CTMU_CH4_H_RES << 8) | P2M_CTMU_CH4_L_RES;
ch_res = chx_res[ch_num];
/* printf("ch%d_res: %d\n", ch_num, ch_res); */
#if TWS_BT_SEND_KEY_CH_RES_DATA_ENABLE
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
lpctmu_tws_send_res_data(BT_KEY_CH_RES_MSG,
chx_res[0],
chx_res[1],
chx_res[2],
chx_res[3],
chx_res[4]);
}
#endif
#if TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
lp_touch_key_online_debug_send(ch_num, ch_res);
#endif
#if TCFG_LP_EARTCH_KEY_ENABLE
if (__this->config->eartch_en && (__this->config->eartch_ch == ch_num)) {
u16 eartch_ch_res = chx_res[ch_num];
u16 eartch_ref_ch_res = chx_res[__this->config->eartch_ref_ch];
u16 eartch_iir = (P2M_CTMU_EARTCH_H_IIR_VALUE << 8) | P2M_CTMU_EARTCH_L_IIR_VALUE;
u16 eartch_trim = (P2M_CTMU_EARTCH_H_TRIM_VALUE << 8) | P2M_CTMU_EARTCH_L_TRIM_VALUE;
u16 eartch_diff = (P2M_CTMU_EARTCH_H_DIFF_VALUE << 8) | P2M_CTMU_EARTCH_L_DIFF_VALUE;
#if TWS_BT_SEND_EARTCH_RES_DATA_ENABLE
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
lpctmu_tws_send_res_data(BT_EARTCH_RES_MSG,
eartch_ch_res,
eartch_ref_ch_res,
eartch_iir,
eartch_trim,
eartch_diff);
}
#endif
#if !TCFG_LP_TOUCH_KEY_BT_TOOL_ENABLE
if (__this->eartch_trim_flag) {
if (__this->eartch_trim_value == 0) {
__this->eartch_trim_value = eartch_diff;
} else {
__this->eartch_trim_value = ((eartch_diff + __this->eartch_trim_value) >> 1);
}
if (__this->eartch_trim_flag++ > 20) {
__this->eartch_trim_flag = 0;
M2P_CTMU_CH_DEBUG &= ~BIT(ch_num);
int ret = syscfg_write(LP_KEY_EARTCH_TRIM_VALUE, &(__this->eartch_trim_value), sizeof(__this->eartch_trim_value));
log_info("write ret = %d", ret);
if (ret > 0) {
M2P_CTMU_EARTCH_TRIM_VALUE_L = (__this->eartch_trim_value & 0xFF);
M2P_CTMU_EARTCH_TRIM_VALUE_H = ((__this->eartch_trim_value >> 8) & 0xFF);
__this->eartch_inear_ok = 1;
#if TCFG_EARTCH_EVENT_HANDLE_ENABLE
eartch_state_update(EARTCH_STATE_TRIM_OK);
#endif
log_info("trim: %d\n", __this->eartch_inear_ok);
is_lpkey_active = 0;
} else {
__this->eartch_inear_ok = 0;
#if TCFG_EARTCH_EVENT_HANDLE_ENABLE
eartch_state_update(EARTCH_STATE_TRIM_ERR);
#endif
log_info("trim: %d\n", __this->eartch_inear_ok);
is_lpkey_active = 0;
}
}
log_debug("eartch ch trim value: %d, res = %d", __this->eartch_trim_value, eartch_diff);
}
#endif
if (P2M_CTMU_EARTCH_EVENT != last_state) {
last_state = P2M_CTMU_EARTCH_EVENT;
if (last_state == CTMU_P2M_EARTCH_IN_EVENT) {
printf("soft inear\n");
#if TWS_BT_SEND_EVENT_ENABLE
lpctmu_tws_send_event_data(EAR_IN, BT_EVENT_SW_MSG);
#endif
if (__this->eartch_inear_ok) {
ctmu_eartch_event_handle(EAR_IN);
}
} else if (last_state == CTMU_P2M_EARTCH_OUT_EVENT) {
printf("soft outear");
#if TWS_BT_SEND_EVENT_ENABLE
lpctmu_tws_send_event_data(EAR_OUT, BT_EVENT_SW_MSG);
#endif
if (__this->eartch_inear_ok) {
ctmu_eartch_event_handle(EAR_OUT);
}
}
}
}
#endif
break;
case CTMU_P2M_CH0_SHORT_KEY_EVENT:
case CTMU_P2M_CH1_SHORT_KEY_EVENT:
case CTMU_P2M_CH2_SHORT_KEY_EVENT:
case CTMU_P2M_CH3_SHORT_KEY_EVENT:
case CTMU_P2M_CH4_SHORT_KEY_EVENT:
log_debug("CH%d: SHORT click", ch_num);
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
#else
ctmu_short_click_handle(ch_num);
#endif
break;
case CTMU_P2M_CH0_LONG_KEY_EVENT:
case CTMU_P2M_CH1_LONG_KEY_EVENT:
case CTMU_P2M_CH2_LONG_KEY_EVENT:
case CTMU_P2M_CH3_LONG_KEY_EVENT:
case CTMU_P2M_CH4_LONG_KEY_EVENT:
log_debug("CH%d: LONG click", ch_num);
is_lpkey_active = 0;
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
#else
#if CTMU_CHECK_LONG_CLICK_BY_RES
if (lp_touch_key_check_long_click_by_ctmu_res(ch_num)) {
return;
}
#endif
ctmu_long_click_handle(ch_num);
#endif
break;
case CTMU_P2M_CH0_HOLD_KEY_EVENT:
case CTMU_P2M_CH1_HOLD_KEY_EVENT:
case CTMU_P2M_CH2_HOLD_KEY_EVENT:
case CTMU_P2M_CH3_HOLD_KEY_EVENT:
case CTMU_P2M_CH4_HOLD_KEY_EVENT:
log_debug("CH%d: HOLD click", ch_num);
is_lpkey_active = 0;
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
#else
#if CTMU_CHECK_LONG_CLICK_BY_RES
if (lp_touch_key_check_long_click_by_ctmu_res(ch_num)) {
return;
}
#endif
ctmu_hold_click_handle(ch_num);
#endif
break;
case CTMU_P2M_CH0_FALLING_EVENT:
case CTMU_P2M_CH1_FALLING_EVENT:
case CTMU_P2M_CH2_FALLING_EVENT:
case CTMU_P2M_CH3_FALLING_EVENT:
case CTMU_P2M_CH4_FALLING_EVENT:
log_debug("CH%d: FALLING", ch_num);
is_lpkey_active = 1;
#if CTMU_CHECK_LONG_CLICK_BY_RES
falling_res_avg[ch_num] = lp_touch_key_ctmu_res_buf_avg(ch_num);
log_debug("falling_res_avg: %d", falling_res_avg[ch_num]);
#endif
break;
case CTMU_P2M_CH0_RAISING_EVENT:
case CTMU_P2M_CH1_RAISING_EVENT:
case CTMU_P2M_CH2_RAISING_EVENT:
case CTMU_P2M_CH3_RAISING_EVENT:
case CTMU_P2M_CH4_RAISING_EVENT:
log_debug("CH%d: RAISING", ch_num);
is_lpkey_active = 0;
#if CTMU_CHECK_LONG_CLICK_BY_RES
lp_touch_key_ctmu_res_buf_clear(ch_num);
#endif
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
#else
ctmu_raise_click_handle(ch_num);
#endif
break;
case CTMU_P2M_EARTCH_IN_EVENT:
log_debug("CH%d: IN", ch_num);
break;
case CTMU_P2M_EARTCH_OUT_EVENT:
log_debug("CH%d: OUT", ch_num);
break;
default:
break;
}
#if (TCFG_LP_SLIDE_KEY_ENABLE && TCFG_LP_SLIDE_KEY_SHORT_DISTANCE)
u8 key_type = check_slide_key_type(ctmu_event, ch_num);
if (key_type) {
printf("CH%d: key_type = 0x%x\n", ch_num, key_type);
ctmu_send_slide_key_type_event(key_type);
}
#endif
}
u8 lp_touch_key_power_on_status()
{
extern u8 power_reset_flag;
u8 sfr = power_reset_flag;
u8 ret = 0;
log_debug("P3_RST_SRC = %x, P2M_CTMU_CTMU_WKUP_MSG = 0x%x", sfr, P2M_CTMU_WKUP_MSG);
if (P2M_CTMU_WKUP_MSG & P2M_MESSAGE_POWER_ON_FLAG) { //长按开机查询
if (P2M_CTMU_WKUP_MSG & (P2M_MESSAGE_KEY_ACTIVE_FLAG)) { //按键释放查询, 0:释放, 1: 触摸保持
ret = 1; //key active
}
}
return ret;
}
void lp_touch_key_disable(void)
{
log_debug("%s", __func__);
P2M_CTMU_WKUP_MSG &= (~(P2M_MESSAGE_SYNC_FLAG));
lp_touch_key_send_cmd(CTMU_M2P_DISABLE);
while (!(P2M_CTMU_WKUP_MSG & P2M_MESSAGE_SYNC_FLAG));
__this->softoff_mode = LP_TOUCH_SOFTOFF_MODE_LEGACY;
}
void lp_touch_key_enable(void)
{
log_debug("%s", __func__);
lp_touch_key_send_cmd(CTMU_M2P_ENABLE);
__this->softoff_mode = LP_TOUCH_SOFTOFF_MODE_ADVANCE;
}
void lp_touch_key_charge_mode_enter()
{
log_debug("%s", __func__);
#if (!LP_TOUCH_KEY_CHARGE_MODE_SW_DISABLE)
P2M_CTMU_WKUP_MSG &= (~(P2M_MESSAGE_SYNC_FLAG));
lp_touch_key_send_cmd(CTMU_M2P_CHARGE_ENTER_MODE);
while (!(P2M_CTMU_WKUP_MSG & P2M_MESSAGE_SYNC_FLAG));
__this->softoff_mode = LP_TOUCH_SOFTOFF_MODE_LEGACY;
#endif
}
void lp_touch_key_charge_mode_exit()
{
log_debug("%s", __func__);
P2M_CTMU_WKUP_MSG &= (~(P2M_MESSAGE_RESET_ALGO_FLAG));
lp_touch_key_send_cmd(CTMU_M2P_RESET_ALGO);
while (!(P2M_CTMU_WKUP_MSG & P2M_MESSAGE_RESET_ALGO_FLAG));
#if (!LP_TOUCH_KEY_CHARGE_MODE_SW_DISABLE)
lp_touch_key_send_cmd(CTMU_M2P_CHARGE_EXIT_MODE);
__this->softoff_mode = LP_TOUCH_SOFTOFF_MODE_ADVANCE;
#endif
}
//=============================================//
//NOTE: 该函数为进关机时被库里面回调
//在板级配置struct low_power_param power_param中变量lpctmu_en配置为TCFG_LP_TOUCH_KEY_ENABLE时:
//该函数在决定softoff进触摸模式还是普通模式:
// return 1: 进触摸模式关机(LP_TOUCH_SOFTOFF_MODE_ADVANCE);
// return 0: 进普通模式关机(触摸关闭)(LP_TOUCH_SOFTOFF_MODE_LEGACY);
//使用场景:
// 1)在充电舱外关机, 需要触摸开机, 进带触摸关机模式;
// 2)在充电舱内关机,可以关闭触摸模块, 进普通关机模式, 关机功耗进一步降低.
//=============================================//
u8 lp_touch_key_softoff_mode_query(void)
{
return __this->softoff_mode;
}
void set_lpkey_active(u8 set)
{
is_lpkey_active = set;
}
static u8 lpkey_idle_query(void)
{
return !is_lpkey_active;
}
REGISTER_LP_TARGET(key_lp_target) = {
.name = "lpkey",
.is_idle = lpkey_idle_query,
};
#endif