KT24-1110_65E-HA-651B/cpu/br25/plcnt.c
2024-11-10 18:44:17 +08:00

285 lines
8.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "system/includes.h"
#include "asm/plcnt.h"
#define PLCNT_CTM_DEBUG 0
#if PLCNT_CTM_DEBUG
#define plcnt_ctm_debug(fmt, ...) printf("[PLCNT] "fmt, ##__VA_ARGS__)
#else
#define plcnt_ctm_debug(fmt, ...)
#endif
u8 g_touch_len; //触摸按键数
u8 bCapState; //电容充放电状态
u8 bCap_ch = 0; //触摸通道
u16 Touchkey_value_new = 0;
u16 Touchkey_value_old = 0;
sCTM_KEY_VAR ctm_key_value;
#define PLCNT_CLOCK_SEL(x) SFR(JL_PCNT->CON, 2, 2, x)
#define INPUT_CHANNLE2_SRC_SEL(x) SFR(JL_IOMAP->CON2, 16, 6, x)
static const struct touch_key_platform_data *user_data = NULL;
sCTM_KEY_VAR *ctm_key_var;
static u8 plcnt_channel2port(u8 chan)
{
return user_data->port_list[chan].port;
}
static void set_port_out_H(u8 chan)
{
gpio_direction_output(plcnt_channel2port(chan), 1);
}
static void set_port_pd(u8 chan)
{
gpio_set_pull_down(plcnt_channel2port(chan), 1);
}
static void set_port_die(u8 chan)
{
gpio_set_die(plcnt_channel2port(chan), 1);
}
static void set_port_in(u8 chan)
{
gpio_direction_input(plcnt_channel2port(chan)); //输入
}
static void set_touch_io(u8 chan)
{
INPUT_CHANNLE2_SRC_SEL(plcnt_channel2port(chan));
set_port_in(chan); //设置为输入
}
static void ctm_key_var_init(sCTM_KEY_VAR *ptr)
{
ctm_key_var = ptr;
}
static void ctm_irq(u16 ctm_res, u8 ch)
{
u16 temp_u16_0, temp_u16_1;
s16 temp_s16_0, temp_s16_1;
s32 temp_s32_0;
//..............................................................................................
//取计数值/通道判断
//..............................................................................................
if (ctm_key_var->touch_init_cnt[ch]) {
ctm_key_var->touch_init_cnt[ch]--;
// touch_cnt_buf[ch] = rvalue << FLT0CFG;
// touch_release_buf[ch] = (long)(rvalue) << FLT1CFG0;
ctm_key_var->touch_cnt_buf[ch] = (u32)ctm_res << ctm_key_var->FLT0CFG;
ctm_key_var->touch_release_buf[ch] = (u32)ctm_res << ctm_key_var->FLT1CFG0;
}
//..............................................................................................
//当前计数值去抖动滤波器
//..............................................................................................
temp_u16_0 = ctm_key_var->touch_cnt_buf[ch];
temp_u16_1 = temp_u16_0;
temp_u16_1 -= (temp_u16_1 >> ctm_key_var->FLT0CFG);
temp_u16_1 += ctm_res;//temp_u16_1 += rvalue;
ctm_key_var->touch_cnt_buf[ch] = temp_u16_1;
temp_u16_0 += temp_u16_1;
temp_u16_0 >>= (ctm_key_var->FLT0CFG + 1);
//..............................................................................................
//各通道按键释放计数值滤波器
//..............................................................................................
temp_s32_0 = ctm_key_var->touch_release_buf[ch];
temp_u16_1 = temp_s32_0 >> ctm_key_var->FLT1CFG0; //获得滤波器之后的按键释放值
temp_s16_0 = temp_u16_0 - temp_u16_1; //获得和本次检测值的差值,按下按键为负值,释放按键为正值
temp_s16_1 = temp_s16_0;
// if(ch == 1)
// {
// printf("ch%d: %d %d", (short)ch, temp_u16_0, temp_s16_1);
// }
if (ctm_key_var->touch_key_state & BIT(ch)) { //如果本通道按键目前是处于释放状态
if (temp_s16_1 >= 0) { //当前计数值大于低通值,放大后参与运算
if (temp_s16_1 < (ctm_key_var->FLT1CFG2 >> 3)) {
temp_s16_1 <<= 3; //放大后参与运算
} else {
temp_s16_1 = ctm_key_var->FLT1CFG2; //饱和,防止某些较大的正偏差导致错判
}
} else if (temp_s16_1 >= ctm_key_var->FLT1CFG1) { //当前计数值小于低通值不多,正常参与运算
} else { //当前计数值小于低通值很多,缩小后参与运算 (有符号数右移自动扩展符号位???)
temp_s16_1 >>= 3;
}
} else { //如果本通道按键目前是处于按下状态, 缓慢降低释放计数值
if (temp_s16_1 <= ctm_key_var->RELEASECFG1) {
temp_s16_1 >>= 3; //缩小后参与运算
} else {
temp_s16_1 = 0;
}
}
temp_s32_0 += (s32)temp_s16_1;
ctm_key_var->touch_release_buf[ch] = temp_s32_0;
//..............................................................................................
//按键按下与释放检测
//..............................................................................................
if (temp_s16_0 <= ctm_key_var->PRESSCFG) { //按键按下
ctm_key_var->touch_key_state &= ~BIT(ch);
} else if (temp_s16_0 >= ctm_key_var->RELEASECFG0) { //按键释放
ctm_key_var->touch_key_state |= BIT(ch);
}
}
static void scan_capkey(void *priv)
{
u16 temp;
u16 Touchkey_value_delta;
if (0 == g_touch_len) {
return;
}
if (bCapState == 0) {
bCapState = 1;
Touchkey_value_new = JL_PCNT->VAL; ///获取计数值
set_port_out_H(bCap_ch);//set output H
///////***wait IO steady for pulse counter
if (Touchkey_value_old > Touchkey_value_new) {
Touchkey_value_new += 0x10000;
}
Touchkey_value_delta = Touchkey_value_new - Touchkey_value_old;
//plcnt_ctm_debug("old: %x new: %x", Touchkey_value_old, Touchkey_value_new);
Touchkey_value_old = Touchkey_value_new; ///记录旧值
temp = 6800L - Touchkey_value_delta * user_data->change_gain; ///1变化增大倍数
/* if(bCap_ch == 0){ */
/* plcnt_ctm_debug("value: %x\n", Touchkey_value_delta); */
/* } */
//plcnt_ctm_debug("delta: %d, ch: %d", Touchkey_value_delta, bCap_ch);
/* if(bCap_ch == 0) */
/* { */
/* plcnt_ctm_debug("temp: %d\n", Touchkey_value_delta); */
/* } */
/*调用滤波算法*/
ctm_irq(temp, bCap_ch);
/*清除前一个通道状态锁定PLL CNT*/
//set_port_out(bCap_ch); //设为输出
/*切换通道开始充电PLL CNT 输入Mux 切换*/
bCap_ch++;
bCap_ch %= g_touch_len;
//bCap_ch = (bCap_ch >= g_touch_len) ? 0 : bCap_ch;
////////***make sure IO is steady (IO output high voltage) for pulse counter
set_port_out_H(bCap_ch);
//set_port_out(bCap_ch);
} else {
bCapState = 0;
set_touch_io(bCap_ch); //设为输入开始计数
}
}
//API:
u8 get_plcnt_value(void)
{
u8 key;
u8 i;
for (i = 0; i < g_touch_len; i++) {
if (!(ctm_key_value.touch_key_state & (u8)(BIT(i)))) {
break;
}
}
key = (i < g_touch_len) ? i : NO_KEY;
if (key != NO_KEY) {
//plcnt_ctm_debug("tch %x", key);
}
return key;
}
//API:
int plcnt_init(void *_data)
{
if (_data == NULL) {
return -1;
}
user_data = (const struct touch_key_platform_data *)_data;
ctm_key_var_init(&ctm_key_value);
memset((u8 *)&ctm_key_value, 0x0, sizeof(sCTM_KEY_VAR));
/*触摸按键参数配置*/
ctm_key_value.FLT0CFG = 0;
ctm_key_value.FLT1CFG0 = 7;
ctm_key_value.FLT1CFG1 = -80;
ctm_key_value.FLT1CFG2 = (-(-10)) << 7; //1280
///调节灵敏度的主要参数
/* ctm_key_value.PRESSCFG = -10; */
/* ctm_key_value.RELEASECFG0 = -50; */
/* ctm_key_value.RELEASECFG1 = -80;//-81; */
ctm_key_value.PRESSCFG = user_data->press_cfg;
ctm_key_value.RELEASECFG0 = user_data->release_cfg0;
ctm_key_value.RELEASECFG1 = user_data->release_cfg1;
memset((u8 *) & (ctm_key_value.touch_init_cnt[0]), 0x10, TOUCH_KEY_CH_MAX);
ctm_key_value.touch_key_state = 0xffff; //<按键默认释放
//初始化计数器配置:
PLCNT_CLOCK_SEL(user_data->clock);
JL_PCNT->CON |= BIT(1); //使能计数器
if (user_data->num > TOUCH_KEY_CH_MAX) {
printf("plcnt_ctm key num config err!!!");
return -1;
}
g_touch_len = user_data->num;
Touchkey_value_old = JL_PCNT->VAL; ///获取计数值
set_port_out_H(bCap_ch);
#if 1 //如果外部有下拉电阻,可不是用芯片内部下拉
for (u8 i = 0; i < g_touch_len; i++) {
set_port_pd(i);
set_port_die(i);
}
#endif
plcnt_ctm_debug("touch_key_init , plcnt_con = 0x%x, val = 0x%x", JL_PCNT->CON, JL_PCNT->VAL);
sys_s_hi_timer_add(NULL, scan_capkey, 2); //2ms
return 0;
}