237 lines
6.5 KiB
C
237 lines
6.5 KiB
C
#include "includes.h"
|
|
#include "asm/plcnt.h"
|
|
#include "asm/gpio.h"
|
|
|
|
|
|
static u8 port_index_mapping_talbe[PLCNT_KEY_CH_MAX] = {0};
|
|
static u32 touch_pre_value[PLCNT_KEY_CH_MAX] = {0};
|
|
static u32 touch_normal_value[PLCNT_KEY_CH_MAX] = {0};
|
|
|
|
#define TOUCH_VAL_CALIBRATE_CYCLE (200)//周期大约2秒
|
|
static u32 touch_calibrate_cnt[PLCNT_KEY_CH_MAX] = {0};
|
|
static u32 touch_calibrate_tmp_value[PLCNT_KEY_CH_MAX] = {0};
|
|
|
|
static u8 touch_state = 0;
|
|
|
|
|
|
static const struct touch_key_platform_data *user_data = NULL;
|
|
|
|
static JL_PORT_FLASH_TypeDef *PLCNT_IO_PORTx = NULL;
|
|
static u8 PLCNT_IO_xx;
|
|
|
|
void plcnt_io_out(struct touch_key_port *key)
|
|
{
|
|
if (key->port > IO_MAX_NUM) {
|
|
return;
|
|
} else if ((key->port / 16) == 0) {
|
|
PLCNT_IO_PORTx = JL_PORTA;
|
|
} else if ((key->port / 16) == 1) {
|
|
PLCNT_IO_PORTx = JL_PORTB;
|
|
}
|
|
PLCNT_IO_xx = key->port % 16;
|
|
PLCNT_IO_PORTx->DIE |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->PU &= ~BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->PD |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->OUT |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->DIR &= ~BIT(PLCNT_IO_xx);
|
|
}
|
|
|
|
void plcnt_io_in(struct touch_key_port *key)
|
|
{
|
|
if (key->port > IO_MAX_NUM) {
|
|
return;
|
|
} else if ((key->port / 16) == 0) {
|
|
PLCNT_IO_PORTx = JL_PORTA;
|
|
} else if ((key->port / 16) == 1) {
|
|
PLCNT_IO_PORTx = JL_PORTB;
|
|
}
|
|
PLCNT_IO_xx = key->port % 16;
|
|
PLCNT_IO_PORTx->DIE |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->PU &= ~BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->PD |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->OUT |= BIT(PLCNT_IO_xx);
|
|
PLCNT_IO_PORTx->DIR |= BIT(PLCNT_IO_xx);
|
|
}
|
|
|
|
void plcnt_iomc(struct touch_key_port *key)
|
|
{
|
|
//放电计数引脚选择intputchannel2
|
|
gpio_set_fun_input_port(key->port, PFI_GP_ICH6);
|
|
SFR(JL_IOMAP->CON1, 8, 4, 6);
|
|
}
|
|
|
|
static u32 key_or = 0;
|
|
void plcnt_flt(u32 cur_val, u32 ch)
|
|
{
|
|
/* printf("ch%d : %d\n", ch, cur_val); */
|
|
//简单滤波
|
|
if (touch_pre_value[ch] == 0) {
|
|
touch_pre_value[ch] = cur_val;
|
|
} else if (cur_val >= touch_pre_value[ch]) {
|
|
touch_pre_value[ch] = touch_pre_value[ch] + (u32)((cur_val - touch_pre_value[ch]) * 0.2f);
|
|
} else {
|
|
touch_pre_value[ch] = touch_pre_value[ch] - (u32)((touch_pre_value[ch] - cur_val) * 0.2f);
|
|
}
|
|
//处理滤波之后的值
|
|
if (touch_pre_value[ch] > (touch_normal_value[ch] + user_data->port_list[ch].press_delta)) {
|
|
key_or |= BIT(ch);
|
|
touch_calibrate_cnt[ch] = 0;
|
|
} else {
|
|
key_or &= ~BIT(ch);
|
|
touch_calibrate_cnt[ch] ++;
|
|
}
|
|
//定期标定常态下的基准值
|
|
if (touch_calibrate_cnt[ch] > TOUCH_VAL_CALIBRATE_CYCLE) {
|
|
touch_normal_value[ch] = touch_calibrate_tmp_value[ch] / 10;
|
|
touch_calibrate_tmp_value[ch] = 0;
|
|
touch_calibrate_cnt[ch] = 0;
|
|
} else if (touch_calibrate_cnt[ch] >= (TOUCH_VAL_CALIBRATE_CYCLE / 2)) {
|
|
if (touch_calibrate_cnt[ch] < ((TOUCH_VAL_CALIBRATE_CYCLE / 2) + 10)) {
|
|
touch_calibrate_tmp_value[ch] += touch_pre_value[ch];
|
|
}
|
|
} else {
|
|
touch_calibrate_tmp_value[ch] = 0;
|
|
}
|
|
}
|
|
|
|
void scan_capkey_async(void *priv)
|
|
{
|
|
if (!user_data) {
|
|
return;
|
|
}
|
|
static u8 cur_ch = 0;
|
|
static u32 new_val = 0;
|
|
static u32 old_val = 0;
|
|
|
|
u8 pre_ch = cur_ch - 1;
|
|
u8 net_ch = cur_ch + 1;
|
|
if (cur_ch == 0) {
|
|
pre_ch = user_data->num - 1;
|
|
}
|
|
if (net_ch >= user_data->num) {
|
|
net_ch = 0;
|
|
}
|
|
|
|
new_val = JL_PCNT->VAL;
|
|
u32 delta_val = 0;
|
|
if (new_val >= old_val) {
|
|
delta_val = new_val - old_val;
|
|
} else {
|
|
delta_val = (u32) - new_val + old_val;
|
|
}
|
|
plcnt_flt(delta_val, pre_ch);
|
|
old_val = JL_PCNT->VAL;
|
|
plcnt_iomc(&(user_data->port_list[cur_ch]));
|
|
plcnt_io_in(&(user_data->port_list[cur_ch]));
|
|
if (net_ch != cur_ch) {
|
|
plcnt_io_out(&(user_data->port_list[net_ch]));
|
|
}
|
|
cur_ch = net_ch;
|
|
}
|
|
|
|
void scan_capkey(void *priv)
|
|
{
|
|
if (!user_data) {
|
|
return;
|
|
}
|
|
for (u8 ch = 0; ch < user_data->num; ch ++) {
|
|
plcnt_io_out(&(user_data->port_list[ch]));
|
|
plcnt_iomc(&(user_data->port_list[ch]));
|
|
u32 tmp_val, start_val, end_val, delta_val = 0;
|
|
for (u8 i = 0; i < 5; i ++) {
|
|
delay(100);
|
|
start_val = JL_PCNT->VAL;
|
|
PLCNT_IO_PORTx->DIR |= BIT(PLCNT_IO_xx);
|
|
__asm__ volatile("csync");
|
|
while (PLCNT_IO_PORTx->IN & BIT(PLCNT_IO_xx));
|
|
end_val = JL_PCNT->VAL;
|
|
PLCNT_IO_PORTx->DIR &= ~BIT(PLCNT_IO_xx);
|
|
if (end_val > start_val) {
|
|
tmp_val = end_val - start_val;
|
|
} else {
|
|
tmp_val = (u32) - start_val + end_val;
|
|
}
|
|
delta_val += tmp_val;
|
|
}
|
|
delta_val = delta_val / 5;
|
|
/* printf("%d: %d\n", ch, delta_val); */
|
|
plcnt_flt(delta_val, ch);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
@brief 引脚放电计数模块初始化
|
|
*/
|
|
int plcnt_init(void *_data)
|
|
{
|
|
if (_data == NULL) {
|
|
return -1;
|
|
}
|
|
user_data = (const struct touch_key_platform_data *)_data;
|
|
|
|
if (user_data->num > PLCNT_KEY_CH_MAX) {
|
|
return -1;
|
|
}
|
|
|
|
for (u8 ch = 0; ch < user_data->num; ch ++) {
|
|
touch_normal_value[ch] = 0 - (2 * user_data->port_list[ch].press_delta);
|
|
}
|
|
|
|
for (u8 ch = 0; ch < user_data->num; ch ++) {
|
|
plcnt_iomc(&(user_data->port_list[ch]));
|
|
plcnt_io_out(&(user_data->port_list[ch]));
|
|
}
|
|
|
|
JL_PCNT->CON = 0;
|
|
JL_PCNT->CON |= (0b11 << 2); //选择PLL240M为时钟源
|
|
JL_PCNT->CON |= BIT(1); //引脚放电计数使能
|
|
|
|
/* sys_s_hi_timer_add(NULL, scan_capkey_async, 2); //2ms */
|
|
sys_s_hi_timer_add(NULL, scan_capkey, 10); //10ms
|
|
|
|
return 0;
|
|
}
|
|
|
|
static u8 key_filter(u8 key)
|
|
{
|
|
static u8 used_key = 0xff;
|
|
static u8 old_key;
|
|
static u8 key_counter;
|
|
|
|
if (old_key != key) {
|
|
key_counter = 0;
|
|
old_key = key;
|
|
} else {
|
|
key_counter++;
|
|
if (key_counter == 3) {
|
|
used_key = key;
|
|
}
|
|
}
|
|
return used_key;
|
|
}
|
|
|
|
u8 get_plcnt_value(void)
|
|
{
|
|
/* printf("%d %d %d\n", touch_pre_value[0], touch_pre_value[1], touch_pre_value[2]); */
|
|
static u8 pre_i = 0;
|
|
u8 key_num = 0xff;
|
|
if (key_or) {
|
|
if (key_or & BIT(pre_i)) {
|
|
key_num = pre_i;
|
|
} else {
|
|
for (u8 ch = 0; ch < user_data->num; ch ++) {
|
|
if (key_or & BIT(ch)) {
|
|
key_num = ch;
|
|
pre_i = ch;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/* printf("key_num : %d\n", key_num); */
|
|
}
|
|
return key_filter(key_num);
|
|
}
|
|
|