This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
+175
View File
@@ -0,0 +1,175 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adkey.data.bss")
#pragma data_seg(".adkey.data")
#pragma const_seg(".adkey.text.const")
#pragma code_seg(".adkey.text")
#endif
#include "key_driver.h"
#include "adkey.h"
#include "gpio.h"
#include "app_config.h"
#include "asm/power_interface.h"
#if TCFG_ADKEY_ENABLE
#define TCFG_ADKEY_LED_IO_REUSE 0
#define TCFG_ADKEY_IR_IO_REUSE 0
#define TCFG_ADKEY_LED_SPI_IO_REUSE 0
static const struct adkey_platform_data *__this = NULL;
//按键驱动扫描参数列表
struct key_driver_para adkey_scan_param = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_AD,
.filter_time = 2, //按键消抖延时;
.long_time = 75, //按键判定长按数量
.hold_time = (75 + 15), //按键判定HOLD数量
.click_delay_time = 20, //按键被抬起后等待连击延时数量
.scan_time = 10, //按键扫描频率, 单位: ms
};
u8 ad_get_key_value(void)
{
u8 i;
u16 ad_data;
if (!__this->enable) {
return NO_KEY;
}
/* ad_data = adc_get_voltage(__this->ad_channel); */
ad_data = adc_get_value(__this->ad_channel);
for (i = 0; i < CONFIG_ADKEY_MAX_NUM; i++) {
if ((ad_data <= __this->ad_value[i]) && (__this->ad_value[i] < 0xfffL)) {
return __this->key_value[i];
}
}
return NO_KEY;
}
__attribute__((weak))
const struct adkey_platform_data *get_adkey_platform_data()
{
return NULL;
}
int adkey_init(void)
{
__this = get_adkey_platform_data();
if (!__this) {
return -EINVAL;
}
if (!__this->enable) {
return KEY_NOT_SUPPORT;
}
adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC
#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE)
#else
if (__this->extern_up_en) {
gpio_set_mode(IO_PORT_SPILT(__this->adkey_pin), PORT_INPUT_FLOATING);
} else {
gpio_set_mode(IO_PORT_SPILT(__this->adkey_pin), PORT_INPUT_PULLUP_100K);
}
gpio_set_function(IO_PORT_SPILT(__this->adkey_pin), PORT_FUNC_GPADC);
#endif
if (__this->long_press_enable) {
gpio_longpress_pin0_reset_config(__this->adkey_pin, 0, __this->long_press_time, 1, PORT_INPUT_PULLUP_100K, 0);
}
return 0;
}
#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE)
#if TCFG_ADKEY_IR_IO_REUSE
static u8 ir_io_sus = 0;
extern u8 ir_io_suspend(void);
extern u8 ir_io_resume(void);
#endif
#if TCFG_ADKEY_LED_IO_REUSE
static u8 led_io_sus = 0;
extern u8 led_io_suspend(void);
extern u8 led_io_resume(void);
#endif
#if TCFG_ADKEY_LED_SPI_IO_REUSE
static u8 led_spi_sus = 0;
extern u8 led_spi_suspend(void);
extern u8 led_spi_resume(void);
#endif
u8 adc_io_reuse_enter(u32 ch)
{
if (ch == __this->ad_channel) {
#if TCFG_ADKEY_IR_IO_REUSE
if (ir_io_suspend()) {
return 1;
} else {
ir_io_sus = 1;
}
#endif
#if TCFG_ADKEY_LED_IO_REUSE
if (led_io_suspend()) {
return 1;
} else {
led_io_sus = 1;
}
#endif
#if TCFG_ADKEY_LED_SPI_IO_REUSE
if (led_spi_suspend()) {
return 1;
} else {
led_spi_sus = 1;
}
#endif
if (__this->extern_up_en) {
gpio_set_mode(IO_PORT_SPILT(__this->adkey_pin), PORT_HIGHZ);
} else {
gpio_set_mode(IO_PORT_SPILT(__this->adkey_pin), PORT_INPUT_PULLUP_10K);
gpio_set_function(IO_PORT_SPILT(__this->adkey_pin), PORT_FUNC_GPADC);
}
}
return 0;
}
u8 adc_io_reuse_exit(u32 ch)
{
if (ch == __this->ad_channel) {
#if TCFG_ADKEY_IR_IO_REUSE
if (ir_io_sus) {
ir_io_sus = 0;
ir_io_resume();
}
#endif
#if TCFG_ADKEY_LED_IO_REUSE
if (led_io_sus) {
led_io_sus = 0;
led_io_resume();
}
#endif
#if TCFG_ADKEY_LED_SPI_IO_REUSE
if (led_spi_sus) {
led_spi_sus = 0;
led_spi_resume();
}
#endif
}
return 0;
}
#endif
REGISTER_KEY_OPS(adkey) = {
.idle_query_en = 1,
.param = &adkey_scan_param,
.get_value = ad_get_key_value,
.key_init = adkey_init,
};
#endif /* #if TCFG_ADKEY_ENABLE */
+47
View File
@@ -0,0 +1,47 @@
#ifndef DEVICE_ADKEY_H
#define DEVICE_ADKEY_H
#include "typedef.h"
#include "gpadc.h"
#ifndef CONFIG_ADKEY_MAX_NUM
#define CONFIG_ADKEY_MAX_NUM 20
#endif
struct adkey_platform_data {
u8 enable;
u8 adkey_pin;
u8 extern_up_en; //是否用外部上拉,1:用外部上拉, 0:用内部上拉10K
u32 ad_channel;
u8 long_press_enable;
u8 long_press_time;
u16 ad_value[CONFIG_ADKEY_MAX_NUM];
u8 key_value[CONFIG_ADKEY_MAX_NUM];
};
struct adkey_rtcvdd_platform_data {
u8 enable;
u8 adkey_pin;
u8 adkey_num;
u32 ad_channel;
u32 extern_up_res_value; //是否用外部上拉,1:用外部上拉, 0:用内部上拉10K
u16 res_value[CONFIG_ADKEY_MAX_NUM]; //电阻值, 从 [大 --> 小] 配置
u8 key_value[CONFIG_ADKEY_MAX_NUM];
};
//ADKEY API:
int adkey_init(void);
u8 ad_get_key_value(void);
//RTCVDD ADKEY API:
int adkey_rtcvdd_init(void);
u8 adkey_rtcvdd_get_key_value(void);
bool is_adkey_press_down();
int get_adkey_io();
const struct adkey_platform_data *get_adkey_platform_data();
#endif
+258
View File
@@ -0,0 +1,258 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adkey_rtcvdd.data.bss")
#pragma data_seg(".adkey_rtcvdd.data")
#pragma const_seg(".adkey_rtcvdd.text.const")
#pragma code_seg(".adkey_rtcvdd.text")
#endif
#include "system/includes.h"
#include "key_driver.h"
#include "adkey.h"
#include "gpio.h"
#include "app_config.h"
#if TCFG_ADKEY_RTCVDD_ENABLE
#define ADKEY_RTCVDD_DEBUG 1
#if ADKEY_RTCVDD_DEBUG
#define adkey_rtcvdd_debug(fmt, ...) printf("[ADKEY_RTCVDD] "fmt, ##__VA_ARGS__)
#else
#define adkey_rtcvdd_debug(fmt, ...)
#endif
#define ADC_KEY_NUMBER 10
#define FULL_ADC 0x3ffL
#define ADC_FULL(x) (x)
#define ADC_VOLTAGE(x,y,z) ((x*y) / (y + z)) //x当前满幅电压,y分压电阻,z上拉电阻
#define ADC_ZERRO(x) (0)
u16 ad_rtcvdd_key_table[ADC_KEY_NUMBER + 1] = {0};
#define FULL_AD_VOLTAGE 0x3FFF
volatile u8 adkey_lock_cnt = 0;
static u8 rtcvdd_cnt = 10;
static u8 rtcvdd_full_cnt = 0xff;
u16 rtcvdd_full_value = FULL_AD_VOLTAGE;
u16 max_value = 0;
u16 min_value = 0xffff;
u32 total_value = 0;
static u8 check_rtcvdd_cnt = 0;
extern const struct adkey_platform_data adkey_data;
static const struct adkey_rtcvdd_platform_data *__this = NULL;
//按键驱动扫描参数列表
struct key_driver_para adkey_rtcvdd_scan_para = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_RTCVDD_AD,
.filter_time = 2, //按键消抖延时;
.long_time = 75, //按键判定长按数量
.hold_time = (75 + 15), //按键判定HOLD数量
.click_delay_time = 20, //按键被抬起后等待连击延时数量
.scan_time = 10, //按键扫描频率, 单位: ms
};
static void set_rtcvdd_table(u16 adc_rtcvdd)
{
u8 i;
u32 extern_up_res_value = __this->extern_up_res_value;
if (extern_up_res_value == 0) { //使用内部上拉
extern_up_res_value = 100;
}
for (i = 0; i < __this->adkey_num; i++) {
if (i == (__this->adkey_num - 1)) {
ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_FULL(adc_rtcvdd)) / 2;
//adkey_rtcvdd_debug("recvdd = %d, res_value[%d] = %d", adc_rtcvdd, i, __this->res_value[i]);
} else {
ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i + 1], extern_up_res_value)) / 2;
//adkey_rtcvdd_debug("res_value[%d] = %d, res_value[%d] = %d", i, __this->res_value[i], i + 1, __this->res_value[i+1]);
}
}
}
static void SET_ADKEY_LOCK_CNT(u8 cnt)
{
CPU_SR_ALLOC();
OS_ENTER_CRITICAL();
adkey_lock_cnt = cnt;
OS_EXIT_CRITICAL();
}
static u8 GET_ADKEY_LOCK_CNT(void)
{
u8 val;
CPU_SR_ALLOC();
OS_ENTER_CRITICAL();
val = adkey_lock_cnt;
OS_EXIT_CRITICAL();
return val;
}
static void POST_ADKEY_LOCK_CNT(void)
{
CPU_SR_ALLOC();
OS_ENTER_CRITICAL();
adkey_lock_cnt --;
OS_EXIT_CRITICAL();
}
/*----------------------------------------------------------------------------*/
/**@brief ad按键初始化
@param void
@param void
@return void
@note void ad_key0_init(void)
*/
/*----------------------------------------------------------------------------*/
int adkey_rtcvdd_init(void)
{
adkey_rtcvdd_debug("ad key init\n");
__this = &adkey_data;
if (!__this) {
return -EINVAL;
}
if (__this->extern_up_res_value == 0) { //使用内部上拉
gpio_set_pull_up(__this->adkey_pin, 1);
} else {
gpio_set_pull_up(__this->adkey_pin, 0);
}
gpio_set_mode(IO_PORT_SPILT(__this->adkey_pin), PORT_HIGHZ);
adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC
adc_add_sample_ch(AD_CH_RTCVDD);
set_rtcvdd_table(FULL_ADC);
return 0;
}
/*把cnt个值里的最大值和最小值去掉,求剩余cnt-2个数的平均值*/
static u16 rtcvdd_full_vaule_update(u16 value)
{
u16 full_value = FULL_ADC;
if (rtcvdd_full_cnt == 0xff) {
rtcvdd_full_cnt = 0;
SET_ADKEY_LOCK_CNT(50);
return value; //first time
} else {
rtcvdd_full_cnt ++;
if (value > max_value) {
max_value = value;
}
if (value < min_value) {
min_value = value;
}
total_value += value;
if (rtcvdd_full_cnt > 10 - 1) { //算10个数
full_value = (total_value - max_value - min_value) / (rtcvdd_full_cnt - 2);
rtcvdd_full_cnt = 0;
max_value = 0;
min_value = 0xffff;
total_value = 0;
} else {
return rtcvdd_full_value;
}
}
return full_value;
}
u8 get_rtcvdd_level(void)
{
u8 level = GET_RTCVDD_VOL();
return level;
}
void set_rtcvdd_level(u8 level)
{
if (level > 7 || level < 0) {
return;
}
RTCVDD_VOL_SEL(level);
}
/*检测到RTCVDD 比 VDDIO 高的时候自动把RTCVDD降一档*/
static u8 rtcvdd_auto_match_vddio_lev(u32 rtcvdd_value)
{
u8 rtcvdd_lev = 0;
if (rtcvdd_value >= FULL_ADC) { //trim rtcvdd < vddio
if (rtcvdd_cnt > 10) {
rtcvdd_cnt = 0;
rtcvdd_lev = get_rtcvdd_level();
if (rtcvdd_lev < 8) {
rtcvdd_lev++; //降一档
/* rtcvdd_lev--; //降一档 */
set_rtcvdd_level(rtcvdd_lev);
SET_ADKEY_LOCK_CNT(50);
return 1;
}
} else {
rtcvdd_cnt ++;
}
} else {
rtcvdd_cnt = 0;
rtcvdd_full_value = rtcvdd_full_vaule_update(rtcvdd_value);
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 获取ad按键值
@param void
@param void
@return key_number
@note tu8 adkey_rtcvdd_get_key_value(void)
*/
/*----------------------------------------------------------------------------*/
u8 adkey_rtcvdd_get_key_value(void)
{
u8 key_number, i;
u32 ad_value;
u16 rtcvdd_value = 0;
rtcvdd_value = 2 * adc_get_value(AD_CH_RTCVDD);
ad_value = adc_get_value(__this->ad_channel);
/* printf("rtcvdd_value = %d, ad_value = %d", rtcvdd_value, ad_value); */
if (rtcvdd_auto_match_vddio_lev(rtcvdd_value)) {
return NO_KEY;
}
if (GET_ADKEY_LOCK_CNT()) {
POST_ADKEY_LOCK_CNT();
return NO_KEY;
}
set_rtcvdd_table(rtcvdd_full_value);
for (i = 0; i < __this->adkey_num; i++) {
if (ad_value <= ad_rtcvdd_key_table[i] && (ad_rtcvdd_key_table[i] < 0x3FFL)) {
return __this->key_value[i];
}
}
return NO_KEY;
}
REGISTER_KEY_OPS(adkey_rtcvdd) = {
.param = &adkey_rtcvdd_scan_para,
.get_value = adkey_rtcvdd_get_key_value,
.key_init = adkey_rtcvdd_init,
};
#endif /* #if TCFG_ADKEY_RTCVDD_ENABLE */
@@ -0,0 +1,71 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".ctmu_touch_key.data.bss")
#pragma data_seg(".ctmu_touch_key.data")
#pragma const_seg(".ctmu_touch_key.text.const")
#pragma code_seg(".ctmu_touch_key.text")
#endif
#include "key_driver.h"
#include "app_config.h"
#if TCFG_CTMU_TOUCH_KEY_ENABLE
#include "asm/ctmu.h"
#define LOG_TAG_CONST CTMU
#define LOG_TAG "[ctmu]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
/* =========== 触摸键使用说明 ============= */
//1. 使用ctmu模块作计数;
extern const struct ctmu_touch_key_platform_data ctmu_touch_key_data;
static const struct ctmu_touch_key_platform_data *__this = NULL;
//按键驱动扫描参数列表
struct key_driver_para ctmu_touch_key_scan_para = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_CTMU_TOUCH,
.filter_time = 2, //按键消抖延时;
.long_time = 55, //按键判定长按数量
.hold_time = (55 + 15), //按键判定HOLD数量
.click_delay_time = 40, //按键被抬起后等待连击延时数量
.scan_time = 10, //按键扫描频率, 单位: ms
};
static u8 ctmu_touch_key_get_value(void)
{
u8 key = get_ctmu_value();
if (key != NO_KEY) {
log_debug("key = %d %x", key, __this->port_list[key].key_value);
return __this->port_list[key].key_value;
}
return NO_KEY;
}
int ctmu_touch_key_init(void)
{
__this = &ctmu_touch_key_data;
log_info("ctmu touch_key_init >>>> ");
return ctmu_init((void *)ctmu_touch_key_data);
}
REGISTER_KEY_OPS(ctmu_touch_key) = {
.param = &ctmu_touch_key_scan_para,
.get_value = ctmu_touch_key_get_value,
.key_init = ctmu_touch_key_init,
};
#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */
+274
View File
@@ -0,0 +1,274 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".iokey.data.bss")
#pragma data_seg(".iokey.data")
#pragma const_seg(".iokey.text.const")
#pragma code_seg(".iokey.text")
#endif
#include "app_config.h"
#if TCFG_IOKEY_ENABLE
#include "key_driver.h"
#include "iokey.h"
#include "gpio.h"
#include "asm/power_interface.h"
static const struct iokey_platform_data *__this = NULL;
#define MARK_BIT_VALUE(b, v) \
do { \
if ((v & (~BIT(7))) < 7) { \
b |= BIT(v & (~BIT(7))); \
} \
} while(0)
//按键驱动扫描参数列表
struct key_driver_para iokey_scan_para = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_IO,
#if MOUSE_KEY_SCAN_MODE
.filter_time = 2, //按键消抖延时;
.long_time = 5, //按键判定长按数量
.hold_time = (5 + 0), //按键判定HOLD数量
.scan_time = 5, //按键扫描频率, 单位: ms
#else
.filter_time = 4, //按键消抖延时;
.long_time = 75, //按键判定长按数量
.hold_time = (75 + 15), //按键判定HOLD数量
.scan_time = 10, //按键扫描频率, 单位: ms
#endif
.click_delay_time = 20, //按键被抬起后等待连击延时数量
};
static void key_io_pull_down_input(u8 key_io)
{
gpio_set_mode(IO_PORT_SPILT(key_io), PORT_INPUT_PULLDOWN_10K);
}
static void key_io_pull_up_input(u8 key_io)
{
gpio_set_mode(IO_PORT_SPILT(key_io), PORT_INPUT_PULLUP_10K);
}
static void key_io_output_high(u8 key_io)
{
gpio_set_mode(IO_PORT_SPILT(key_io), PORT_OUTPUT_HIGH);
/* gpio_set_pull_down(key_io, 0); */
/* gpio_set_pull_up(key_io, 0); */
}
static void key_io_output_low(u8 key_io)
{
gpio_set_mode(IO_PORT_SPILT(key_io), PORT_OUTPUT_LOW);
/* gpio_set_pull_down(key_io, 0); */
/* gpio_set_pull_up(key_io, 0); */
}
static int get_io_key_value(u8 key_io)
{
return gpio_read(key_io);
}
static void key_io_reset(void)
{
int i;
for (i = 0; i < __this->num; i++) {
switch (__this->port[i].connect_way) {
case ONE_PORT_TO_HIGH:
key_io_pull_down_input(__this->port[i].key_type.one_io.port);
break;
case ONE_PORT_TO_LOW:
#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE)
if (TCFG_MULTIPLEX_PORT != __this->port[i].key_type.one_io.port) {
key_io_pull_up_input(__this->port[i].key_type.one_io.port);
}
#else
key_io_pull_up_input(__this->port[i].key_type.one_io.port);
#endif
break;
case DOUBLE_PORT_TO_IO:
break;
default:
ASSERT(0, "IO KEY CONNECT ERR!!!");
break;
}
}
}
#if MULT_KEY_ENABLE
extern const struct key_remap_data iokey_remap_data;
static u8 iokey_value_remap(u8 bit_mark)
{
for (int i = 0; i < iokey_remap_data.remap_num; i++) {
if (iokey_remap_data.table[i].bit_value == bit_mark) {
return iokey_remap_data.table[i].remap_value;
}
}
return NO_KEY;
}
#endif
#if TCFG_IO_MULTIPLEX_WITH_SD == ENABLE
static u8 mult_key_value = 1;
extern u8 sd_io_suspend(u8 sdx, u8 sd_io);
extern u8 sd_io_resume(u8 sdx, u8 sd_io);
void sd_mult_io_detect(void *arg)
{
static u32 cnt = 0;
if (sd_io_suspend(1, 1) == 0) {
gpio_set_mode(IO_PORT_SPILT(TCFG_MULTIPLEX_PORT), PORT_OUTPUT_LOW);
udelay(10);
gpio_set_mode(IO_PORT_SPILT(TCFG_MULTIPLEX_PORT), PORT_INPUT_PULL_10K);
udelay(10);
mult_key_value = gpio_read(TCFG_MULTIPLEX_PORT);
sd_io_resume(1, 1);
}
}
#endif
__attribute__((weak)) u8 iokey_filter_hook(u8 io_state)
{
return 0;
}
u8 io_get_key_value(void)
{
int i;
u8 press_value = 0;
u8 read_value = 0;
u8 read_io;
u8 write_io;
u8 connect_way;
u8 ret_value = NO_KEY;
u8 bit_mark = 0;
if (!__this->enable) {
return NO_KEY;
}
//先扫描单IO接按键方式
for (i = 0; i < __this->num; i++) {
connect_way = __this->port[i].connect_way;
if (connect_way == ONE_PORT_TO_HIGH) {
press_value = 1;
} else if (connect_way == ONE_PORT_TO_LOW) {
press_value = 0;
} else {
continue;
}
read_io = __this->port[i].key_type.one_io.port;
#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE)
if (read_io == TCFG_MULTIPLEX_PORT) {
read_value = mult_key_value;
} else {
read_value = get_io_key_value(read_io);
}
#else
read_value = get_io_key_value(read_io);
#endif
if (iokey_filter_hook(read_value)) {
#ifdef TCFG_IOKEY_TIME_REDEFINE
extern struct key_driver_para iokey_scan_user_para;
iokey_scan_user_para.filter_cnt = 0;
iokey_scan_user_para.press_cnt = 0;
iokey_scan_user_para.click_delay_cnt = 0;
iokey_scan_user_para.last_key = NO_KEY;
#else
iokey_scan_para.filter_cnt = 0;
iokey_scan_para.press_cnt = 0;
iokey_scan_para.click_delay_cnt = 0;
iokey_scan_para.last_key = NO_KEY;
#endif
return NO_KEY;
}
if (read_value == press_value) {
ret_value = __this->port[i].key_value;
#if MULT_KEY_ENABLE
MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键
#else
goto _iokey_get_value_end;
#endif
}
}
//再扫描两个IO接按键方式, in_port: 上拉输入, out_port: 输出低
for (i = 0; i < __this->num; i++) {
connect_way = __this->port[i].connect_way;
if (connect_way == DOUBLE_PORT_TO_IO) {//标准双io
press_value = 0;
read_io = __this->port[i].key_type.two_io.in_port;
key_io_output_low(__this->port[i].key_type.two_io.out_port); //输出低
key_io_pull_up_input(read_io); //上拉
read_value = get_io_key_value(read_io);
key_io_reset(); //按键初始化为单IO检测状态
if (read_value == press_value) {
ret_value = __this->port[i].key_value;
#if MULT_KEY_ENABLE
MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键
#else
goto _iokey_get_value_end;
#endif
}
}
}
#if MULT_KEY_ENABLE
bit_mark = iokey_value_remap(bit_mark); //组合按键重新映射按键值
ret_value = (bit_mark != NO_KEY) ? bit_mark : ret_value;
#endif
_iokey_get_value_end:
return ret_value;
}
__attribute__((weak))
const struct iokey_platform_data *get_iokey_platform_data()
{
return NULL;
}
int iokey_init(void)
{
__this = get_iokey_platform_data();
if (__this == NULL) {
return -EINVAL;
}
if (!__this->enable) {
return KEY_NOT_SUPPORT;
}
key_io_reset();
if (__this->long_press_enable) {
gpio_longpress_pin0_reset_config(__this->long_press_port, __this->long_press_level, __this->long_press_time, 1, 1, 0);
}
return 0;
}
REGISTER_KEY_OPS(iokey) = {
.idle_query_en = 1,
.param = &iokey_scan_para,
.get_value = io_get_key_value,
.key_init = iokey_init,
};
#endif /* #if TCFG_IOKEY_ENABLE */
+62
View File
@@ -0,0 +1,62 @@
#ifndef DEVICE_IOKEY_H
#define DEVICE_IOKEY_H
#include "typedef.h"
#ifndef CONFIG_IOKEY_MAX_NUM
#define CONFIG_IOKEY_MAX_NUM 15
#endif
// enum key_connect_way {
// ONE_PORT_TO_LOW, //按键一个端口接低电平, 另一个端口接IO
// ONE_PORT_TO_HIGH, //按键一个端口接高电平, 另一个端口接IO
// DOUBLE_PORT_TO_IO, //按键两个端口接IO
// };
#define ONE_PORT_TO_LOW 0 //按键一个端口接低电平, 另一个端口接IO
#define ONE_PORT_TO_HIGH 1 //按键一个端口接高电平, 另一个端口接IO
#define DOUBLE_PORT_TO_IO 2 //按键两个端口接IO
#define CUST_DOUBLE_PORT_TO_IO 3
struct one_io_key {
u8 port;
};
struct two_io_key {
u8 in_port;
u8 out_port;
};
union key_type {
struct one_io_key one_io;
struct two_io_key two_io;
};
struct iokey_port {
union key_type key_type;
u8 connect_way;
u8 key_value;
};
struct iokey_platform_data {
u8 enable;
u8 num;
u8 long_press_enable;
u8 long_press_time;
u8 long_press_port;
u8 long_press_level;
const struct iokey_port *port;
};
//IOKEY API:
int iokey_init(void);
u8 io_get_key_value(void);
bool is_iokey_press_down();
int get_iokey_power_io();
const struct iokey_platform_data *get_iokey_platform_data();
#endif
+87
View File
@@ -0,0 +1,87 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".irkey.data.bss")
#pragma data_seg(".irkey.data")
#pragma const_seg(".irkey.text.const")
#pragma code_seg(".irkey.text")
#endif
#include "key_driver.h"
#include "irkey.h"
#include "gpio.h"
#include "asm/irflt.h"
#include "app_config.h"
#if TCFG_IRKEY_ENABLE
static const struct irkey_platform_data *__this = NULL;
//按键驱动扫描参数列表
struct key_driver_para irkey_scan_param = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_IR,
.filter_time = 2, //按键消抖延时;
.long_time = 75, //按键判定长按数量
.hold_time = (75 + 15), //按键判定HOLD数量
.click_delay_time = 20, //按键被抬起后等待连击延时数量
.scan_time = 10, //按键扫描频率, 单位: ms
};
u8 ir_get_key_value(void)
{
u8 tkey = 0xff;
u8 key_value = 0xff;
tkey = get_irflt_value();
if (tkey == 0xff) {
return tkey;
}
/* printf("ir tkey : 0x%02x", tkey); */
/* return 0xff; */
for (u8 i = 0; i < __this->num; i++) {
if (tkey == __this->IRff00_2_keynum[i].source_value) {
key_value = __this->IRff00_2_keynum[i].key_value;
break;
}
}
/* printf("ir key_value: %d\n", key_value); */
/* return 0xff; */
return key_value;
}
__attribute__((weak))
const struct irkey_platform_data *get_irkey_platform_data()
{
return NULL;
}
int irkey_init(void)
{
__this = get_irkey_platform_data();
if (__this == NULL) {
return -EINVAL;
}
if (!__this->enable) {
return KEY_NOT_SUPPORT;
}
printf("irkey_init ");
irflt_config(__this->port);
ir_timeout_set();
return 0;
}
REGISTER_KEY_OPS(irkey) = {
.idle_query_en = 1,
.param = &irkey_scan_param,
.get_value = ir_get_key_value,
.key_init = irkey_init,
};
#endif
+28
View File
@@ -0,0 +1,28 @@
#ifndef DEVICE_IRKEY_H
#define DEVICE_IRKEY_H
#include "typedef.h"
#ifndef CONFIG_IRKEY_MAX_NUM
#define CONFIG_IRKEY_MAX_NUM 35
#endif
struct ff00_2_keynum {
u8 source_value;
u8 key_value;
};
struct irkey_platform_data {
u8 enable;
u8 port;
u8 num;
struct ff00_2_keynum IRff00_2_keynum[CONFIG_IRKEY_MAX_NUM];
};
u8 ir_get_key_value(void);
int irkey_init(void);
int get_irkey_io();
#endif
+222
View File
@@ -0,0 +1,222 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".key_driver.data.bss")
#pragma data_seg(".key_driver.data")
#pragma const_seg(".key_driver.text.const")
#pragma code_seg(".key_driver.text")
#endif
#include "system/timer.h"
#include "asm/power_interface.h"
#include "key_driver.h"
#include "sdk_config.h"
#define LOG_TAG "[KEY]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#include "debug.h"
static volatile u8 g_is_key_active = 0; //按键是否活跃标志,判断是否可进低功耗
static volatile bool g_key_idle_query_en = false; //是否需要判断g_is_key_active的使能标志
__attribute__((weak))
void key_down_event_handler(u8 key_value)
{
}
/* --------------------------------------------------------------------------*/
/**
* @brief 按键扫描函数,扫描所有注册的按键驱动
*
* @param key_ops:按键操作句柄
*/
/* ----------------------------------------------------------------------------*/
static void key_driver_scan(void *key_ops)
{
struct key_driver_ops *key_handler = (struct key_driver_ops *)key_ops;
struct key_driver_para *scan_para = (struct key_driver_para *)key_handler->param;
u8 key_event = 0;
u8 cur_key_value = NO_KEY;
u8 key_value = 0;
struct key_event key = {0};
#if CONFIG_LVGL_UI_ENABLE
struct key_event key_click = {0};
#endif
key.init = 1;
//区分按键类型
key.type = scan_para->key_type;
cur_key_value = key_handler->get_value();
if (cur_key_value != NO_KEY) {
//35*10Ms
g_is_key_active = 35;
} else if (g_is_key_active) {
g_is_key_active --;
}
//===== 按键消抖处理
//当前按键值与上一次按键值如果不相等, 重新消抖处理, 注意filter_time != 0;
if (cur_key_value != scan_para->filter_value && scan_para->filter_time) {
//消抖次数清0, 重新开始消抖
scan_para->filter_cnt = 0;
//记录上一次的按键值
scan_para->filter_value = cur_key_value;
//第一次检测, 返回不做处理
return;
}
//当前按键值与上一次按键值相等, filter_cnt开始累加
if (scan_para->filter_cnt < scan_para->filter_time) {
scan_para->filter_cnt++;
return;
}
//===== 按键消抖结束, 开始判断按键类型(单击, 双击, 长按, 多击, HOLD, (长按/HOLD)抬起)
if (cur_key_value != scan_para->last_key) {
if (cur_key_value == NO_KEY) {
//cur_key = NO_KEY; last_key = valid_key -> 按键被抬起
if (scan_para->press_cnt >= scan_para->long_time) {
//长按/HOLD状态之后被按键抬起;
key_event = KEY_ACTION_UP;
key_value = scan_para->last_key;
goto __notify;
} else {
#if CONFIG_LVGL_UI_ENABLE
key_event = KEY_ACTION_UP;
key_value = scan_para->last_key;
scan_para->click_delay_cnt = 1;
key_click.init = 1;
key_click.event = KEY_ACTION_CLICK;
key_click.value = scan_para->last_key;
goto __notify;
#else
key_event = KEY_ACTION_CLICK;
key_value = scan_para->last_key;
scan_para->click_delay_cnt = 1;
goto __notify;
#endif
}
} else {
//cur_key = valid_key, last_key = NO_KEY -> 按键被按下
scan_para->press_cnt = 1; //用于判断long和hold事件的计数器重新开始计时;
scan_para->press_sum_cnt = 1;
scan_para->click_delay_cnt = 0;
key_down_event_handler(cur_key_value);
#if CONFIG_LVGL_UI_ENABLE
key_event = KEY_ACTION_LVGL_DOWN;
key_value = cur_key_value;
goto __notify;
#endif
}
//返回, 等待延时时间到
goto __scan_end;
} else {
//cur_key = last_key -> 没有按键按下/按键长按(HOLD)
if (cur_key_value == NO_KEY) {
//last_key = NO_KEY; cur_key = NO_KEY -> 没有按键按下
if (scan_para->click_delay_cnt > 0) {
scan_para->click_delay_cnt++;
if (scan_para->click_delay_cnt > scan_para->click_delay_time) {
key_event = KEY_ACTION_NO_KEY;
scan_para->click_delay_cnt = 0;
goto __notify; //有按键需要消息需要处理
}
}
goto __scan_end; //没有按键需要处理
} else {
//last_key = valid_key; cur_key = valid_key, press_cnt累加用于判断long和hold
scan_para->press_cnt++;
if (scan_para->press_sum_cnt) {
scan_para->press_sum_cnt++;
}
if (scan_para->press_cnt == scan_para->long_time) {
key_event = KEY_ACTION_LONG;
} else if (scan_para->press_cnt >= scan_para->hold_time) {
key_event = KEY_ACTION_HOLD;
scan_para->press_cnt = scan_para->long_time;
} else {
goto __scan_end; //press_cnt没到长按和HOLD次数, 返回
}
key_value = cur_key_value;
goto __notify;
}
}
__notify:
key.event = key_event;
key.value = key_value;
key.tmr = sys_timer_get_ms();
/* printf("key_value: 0x%x, event: %d\n", key_value, key_event); */
key_event_handler(&key);
#if CONFIG_LVGL_UI_ENABLE
if (key_click.init) {
key_click.tmr = sys_timer_get_ms();
key_event_handler(&key_click);
}
#endif
__scan_end:
scan_para->last_key = cur_key_value;
return;
}
/* --------------------------------------------------------------------------*/
/**
* @brief wakeup回调函数
*
* @param port:唤醒口
*/
/* ----------------------------------------------------------------------------*/
void key_active_set(u8 port)
{
g_is_key_active = 35; //35*10Ms
}
/* --------------------------------------------------------------------------*/
/**
* @brief 按键初始化函数,初始化所有注册的按键驱动
*/
/* ----------------------------------------------------------------------------*/
void key_driver_init(void)
{
const struct key_driver_ops *key;
list_for_each_key(key) {
if (!key->key_init) {
continue;
}
if ((!key->key_init()) && key->get_value) {
sys_s_hi_timer_add((void *)key, key_driver_scan, key->param->scan_time); //注册按键扫描定时器
if (key->idle_query_en) {
g_key_idle_query_en = true;
}
}
}
}
/* --------------------------------------------------------------------------*/
/**
* @brief 按键模块是否可进低功耗查询函数
*
* @return 0:不可进
* 1:可进
*/
/* ----------------------------------------------------------------------------*/
static u8 key_idle_query(void)
{
if (g_key_idle_query_en) {
return !g_is_key_active;
} else {
return 1;
}
}
REGISTER_LP_TARGET(key_driver_target) = {
.name = "key",
.is_idle = key_idle_query,
};
+247
View File
@@ -0,0 +1,247 @@
#ifndef SYS_KEY_DRIVER_H
#define SYS_KEY_DRIVER_H
#include "typedef.h"
#define NO_KEY 0xff
#define KEY_NOT_SUPPORT 0x01
#define KEY_POWER 0
#define KEY_PREV 1
#define KEY_NEXT 2
#define KEY_SLIDER 3
#define KEY_MODE 4
#define KEY_PLAY 5
#define KEY_AD_NUM0 10
#define KEY_AD_NUM1 11
#define KEY_AD_NUM2 12
#define KEY_AD_NUM3 13
#define KEY_AD_NUM4 14
#define KEY_AD_NUM5 15
#define KEY_AD_NUM6 16
#define KEY_AD_NUM7 17
#define KEY_AD_NUM8 18
#define KEY_AD_NUM9 19
#define KEY_AD_NUM10 20
#define KEY_AD_NUM11 21
#define KEY_AD_NUM12 22
#define KEY_AD_NUM13 23
#define KEY_AD_NUM14 24
#define KEY_AD_NUM15 25
#define KEY_AD_NUM16 26
#define KEY_AD_NUM17 27
#define KEY_AD_NUM18 28
#define KEY_AD_NUM19 29
#define KEY_IR_NUM0 30
#define KEY_IR_NUM1 31
#define KEY_IR_NUM2 32
#define KEY_IR_NUM3 33
#define KEY_IR_NUM4 34
#define KEY_IR_NUM5 35
#define KEY_IR_NUM6 36
#define KEY_IR_NUM7 37
#define KEY_IR_NUM8 38
#define KEY_IR_NUM9 39
#define KEY_IR_NUM10 40
#define KEY_IR_NUM11 41
#define KEY_IR_NUM12 42
#define KEY_IR_NUM13 43
#define KEY_IR_NUM14 44
#define KEY_IR_NUM15 45
#define KEY_IR_NUM16 46
#define KEY_IR_NUM17 47
#define KEY_IR_NUM18 48
#define KEY_IR_NUM19 49
#define KEY_IR_NUM20 50
#define KEY_IR_NUM21 51
#define KEY_IR_NUM22 52
#define KEY_IR_NUM23 53
#define KEY_IR_NUM24 54
#define KEY_IR_NUM25 55
#define KEY_IR_NUM26 56
#define KEY_IR_NUM27 57
#define KEY_IR_NUM28 58
#define KEY_IR_NUM29 59
#define KEY_IR_NUM30 60
#define KEY_IR_NUM31 61
#define KEY_IR_NUM32 62
#define KEY_IR_NUM33 63
#define KEY_IR_NUM34 64
#define KEY_IO_NUM0 65
#define KEY_IO_NUM1 66
#define KEY_IO_NUM2 67
#define KEY_IO_NUM3 68
#define KEY_IO_NUM4 69
#define KEY_IO_NUM5 70
#define KEY_IO_NUM6 71
#define KEY_IO_NUM7 72
#define KEY_IO_NUM8 73
#define KEY_IO_NUM9 74
#define KEY_IO_NUM10 75
#define KEY_IO_NUM11 76
#define KEY_IO_NUM12 77
#define KEY_IO_NUM13 78
#define KEY_IO_NUM14 79
#define KEY_IO_WATCH_UPPER_LEFT 80 //手表左上的按键
#define KEY_IO_WATCH_UPPER_RIGHT 81 //手表右上的按键
#define KEY_IO_WATCH_LOWER_LEFT 82 //手表左下的按键
#define KEY_IO_WATCH_LOWER_RIGHT 83 //手表右下的按键
#define KEY_IO_WATCH_ENCODER 84 //手表编码器所带的按键
typedef enum __KEY_DRIVER_TYPE {
KEY_DRIVER_TYPE_IO = 0x0,
KEY_DRIVER_TYPE_AD,
KEY_DRIVER_TYPE_RTCVDD_AD,
KEY_DRIVER_TYPE_IR,
KEY_DRIVER_TYPE_TOUCH,
KEY_DRIVER_TYPE_CTMU_TOUCH,
KEY_DRIVER_TYPE_RDEC,
KEY_DRIVER_TYPE_SLIDEKEY,
KEY_DRIVER_TYPE_SOFTKEY,
KEY_DRIVER_TYPE_BRIGHTNESS,
KEY_DRIVER_TYPE_VOICE,
KEY_DRIVER_TYPE_MAX,
} KEY_DRIVER_TYPE;
enum key_action {
KEY_ACTION_CLICK,
KEY_ACTION_LONG,
KEY_ACTION_HOLD,
KEY_ACTION_UP,
KEY_ACTION_DOUBLE_CLICK,
KEY_ACTION_TRIPLE_CLICK,
KEY_ACTION_FOURTH_CLICK,
KEY_ACTION_FIRTH_CLICK,
KEY_ACTION_HOLD_3SEC,
KEY_ACTION_HOLD_5SEC,
/*=======新增按键动作请在此处之上增加=======*/
KEY_ACTION_LVGL_DOWN,
KEY_ACTION_RDEC_ROTATE,
KEY_ACTION_NO_KEY,
KEY_ACTION_MAX,
};
enum watch_key_action {
KEY_WATCH_UPPER_LEFT_DOWN,
KEY_WATCH_UPPER_LEFT_UP,
KEY_WATCH_UPPER_LEFT_HOLD,
KEY_WATCH_UPPER_RIGHT_DOWN,
KEY_WATCH_UPPER_RIGHT_UP,
KEY_WATCH_UPPER_RIGHT_HOLD,
KEY_WATCH_LOWER_LEFT_DOWN,
KEY_WATCH_LOWER_LEFT_UP,
KEY_WATCH_LOWER_LEFT_HOLD,
KEY_WATCH_LOWER_RIGHT_DOWN,
KEY_WATCH_LOWER_RIGHT_UP,
KEY_WATCH_LOWER_RIGHT_HOLD,
KEY_WATCH_ENCODER_DOWN,
KEY_WATCH_ENCODER_UP,
KEY_WATCH_NO_KEY,
};
enum slider_key_action {
KEY_SLIDER_UP,
KEY_SLIDER_DOWN,
KEY_SLIDER_LEFT,
KEY_SLIDER_RIGHT,
};
enum key_event_type {
KEY_CLICK_EVENT,
KEY_COMB_EVENT,
};
struct key_event {
u8 init;
u8 type;
u16 event;
u32 value;
u32 tmr;
};
struct key_driver_para {
u8 last_key; //上一次get_value按键值
//== 用于消抖类参数
u8 filter_value; //用于按键消抖
u8 filter_cnt; //用于按键消抖时的累加值
//== 用于判定连击事件参数
u8 click_delay_cnt; //按键被抬起后等待连击事件延时计数
u8 press_cnt; //与long_time和hold_time对比, 判断long_event和hold_event
u16 press_sum_cnt;
const u8 key_type;
const u8 filter_time; //当filter_cnt累加到base_cnt值时, 消抖有效
const u8 long_time; //按键判定长按数量
const u8 hold_time; //按键判定HOLD数量
const u8 click_delay_time; //按键被抬起后等待连击事件延时数量
const u32 scan_time; //按键扫描频率, 单位ms
};
struct key_driver_ops {
const u8 idle_query_en;
const struct key_driver_para *param;
u8(*get_value)(void);
int (*key_init)(void);
};
#define REGISTER_KEY_OPS(key_ops) \
const struct key_driver_ops key_ops sec(.key_operation)
extern const struct key_driver_ops key_ops_begin[];
extern const struct key_driver_ops key_ops_end[];
#define list_for_each_key(p) \
for (p = key_ops_begin; p < key_ops_end; p++)
struct key_callback {
char *name;
void *arg;
int(*cb_deal)(void *arg);
};
#define REGISTER_KEY_DET_CALLBACK(cb) \
const struct key_callback cb sec(.key_cb)
extern const struct key_callback key_callback_begin[];
extern const struct key_callback key_callback_end[];
#define list_for_each_key_callback(p) \
for (p = key_callback_begin; p < key_callback_end; p++)
//组合按键映射按键值
struct key_remap {
u8 bit_value;
u8 remap_value;
};
struct key_remap_data {
u8 remap_num;
const struct key_remap *table;
};
/* --------------------------------------------------------------------------*/
/**
* @brief 按键初始化函数,初始化所有注册的按键驱动
*/
/* ----------------------------------------------------------------------------*/
void key_driver_init(void);
/* --------------------------------------------------------------------------*/
/**
* @brief 按键事件过滤、检测和发送
*
* @param key:基础按键动作(mono_click、long、hold、up)和键值
*/
/* ----------------------------------------------------------------------------*/
void key_event_handler(struct key_event *key);
#endif
+77
View File
@@ -0,0 +1,77 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".rdec_key.data.bss")
#pragma data_seg(".rdec_key.data")
#pragma const_seg(".rdec_key.text.const")
#pragma code_seg(".rdec_key.text")
#endif
#include "app_config.h"
#include "gpio.h"
#include "rdec.h"
#include "system/timer.h"
#include "key_driver.h"
#include "rdec_key.h"
#if TCFG_RDEC_KEY_ENABLE
extern const struct rdec_platform_data rdec_key_data;
static const struct rdec_platform_data *__this = NULL;
static u32 rdec_id;
void rdec_get_key_value(void *p)
{
int i;
s8 rdec_data;
struct key_event key = {0};
if (!__this->enable) {
return;
}
for (i = 0; i < __this->num; i++) {
rdec_data = rdec_get_value(rdec_id);
if (rdec_data != 0) {
key.init = 1;
key.type = KEY_DRIVER_TYPE_RDEC;
key.event = KEY_ACTION_RDEC_ROTATE;
key.value = rdec_data;
key.tmr = sys_timer_get_ms();
key_event_handler(&key);
}
}
}
int rdec_key_init(void)
{
__this = &rdec_key_data;
if (!__this) {
return -EINVAL;
}
if (!__this->enable) {
return KEY_NOT_SUPPORT;
}
for (int i = 0; i < __this->num; i++) {
const struct rdec_config user_cfg = {
.rdec_a = __this->rdec[i].sin_portA,
.rdec_b = __this->rdec[i].sin_portB,
.phase_mode = __this->rdec[i].phase_mode,
.work_mode = RDEC_WORK_AUTO,
.rdec_x = RDEC_0,
};
gpio_set_mode(IO_PORT_SPILT(__this->rdec[i].sin_portA), __this->rdec[i].sin_portA_io_mode);
gpio_set_mode(IO_PORT_SPILT(__this->rdec[i].sin_portB), __this->rdec[i].sin_portB_io_mode);
rdec_id = rdec_init(&user_cfg);
rdec_start(rdec_id);
sys_s_hi_timer_add(NULL, rdec_get_key_value, __this->rdec[i].scan_time);
}
printf("[rdec] rdec_key_init ");
return rdec_id;
}
#endif /* #if TCFG_RDEC_KEY_ENABLE */
+33
View File
@@ -0,0 +1,33 @@
#ifndef RDEC_KEY_H
#define RDEC_KEY_H
#include "typedef.h"
#include "key_driver.h"
#include "gpio.h"
#include "rdec.h"
/*目前rdec模块是1个*/
#define CONFIG_RDEC_KEY_MAX_NUM 1
struct rdec_device {
u8 index; //编码器序号
u32 sin_portA; //采样信号端口A
enum gpio_mode sin_portA_io_mode;
u32 sin_portB; //采样信号端口B
enum gpio_mode sin_portB_io_mode;
int scan_time; //扫描频率, 单位: ms
rdec_phase_mode phase_mode; //编码器分辨率
int (*get_value)(); //rdec获取单位时间内转动步数值 目前步数值是8位符号数
};
struct rdec_platform_data {
u8 enable; //是否使能rdec
u8 num; //rdec数量
const struct rdec_device *rdec; //rdec参数表
};
int rdec_key_init(void);
#endif
+71
View File
@@ -0,0 +1,71 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".touch_key.data.bss")
#pragma data_seg(".touch_key.data")
#pragma const_seg(".touch_key.text.const")
#pragma code_seg(".touch_key.text")
#endif
#include "touch_key.h"
#include "key_driver.h"
#include "app_config.h"
#if TCFG_TOUCH_KEY_ENABLE
/* =========== 触摸键使用说明 ============= */
//1. 使用plcnt模块作计数;
//2. 配置参数时, 在配置好时钟后, 需要调试no_touch_cnt和touch_cnt的值;
static const struct touch_key_platform_data *__this = NULL;
//按键驱动扫描参数列表
struct key_driver_para touch_key_scan_para = {
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
.key_type = KEY_DRIVER_TYPE_TOUCH,
.filter_time = 1, //按键消抖延时;
.long_time = 75, //按键判定长按数量
.hold_time = (75 + 15), //按键判定HOLD数量
.click_delay_time = 20, //按键被抬起后等待连击延时数量
.scan_time = 10, //按键扫描频率, 单位: ms
};
#define TOUCH_KEY_DEBUG 0
#if TOUCH_KEY_DEBUG
#define touch_key_debug(fmt, ...) printf("[TOUCH] "fmt, ##__VA_ARGS__)
#else
#define touch_key_debug(fmt, ...)
#endif
u8 touch_key_get_value(void)
{
u8 key = get_plcnt_value();
if (key != NO_KEY) {
touch_key_debug("key = %d", key);
return __this->port_list[key].key_value;
}
return NO_KEY;
}
int touch_key_init(void)
{
__this = &touch_key_data;
printf("touch_key_init >>>> ");
return plcnt_init((void *)touch_key_data);
}
REGISTER_KEY_OPS(touch_key) = {
.param = &touch_key_scan_para,
.get_value = touch_key_get_value,
.key_init = touch_key_init,
};
#endif /* #if TCFG_TOUCH_KEY_ENABLE */
+16
View File
@@ -0,0 +1,16 @@
#ifndef DEVICE_TOUCH_KEY_H
#define DEVICE_TOUCH_KEY_H
#include "typedef.h"
#include "asm/plcnt.h"
/* =========== touch key API ============= */
//触摸按键初始化
int touch_key_init(void);
//获取触摸按键键值
u8 touch_key_get_value(void);
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".uart_key.data.bss")
#pragma data_seg(".uart_key.data")
#pragma const_seg(".uart_key.text.const")
#pragma code_seg(".uart_key.text")
#endif
#include "key_driver.h"
#include "uart.h"
#include "app_config.h"
#if TCFG_UART_KEY_ENABLE
static int uart_key_init(void)
{
return 0;
}
static u8 uart_get_key_value(void)
{
char c;
u8 key_value;
if (getbyte(&c) == 0) {
return NO_KEY;
}
switch (c) {
case 'm':
key_value = KEY_MODE;
break;
case 'u':
key_value = KEY_UP;
break;
case 'd':
key_value = KEY_DOWN;
break;
case 'o':
key_value = KEY_OK;
break;
case 'e':
key_value = KEY_MENU;
break;
default:
key_value = NO_KEY;
break;
}
return key_value;
}
#endif /* #if TCFG_UART_KEY_ENABLE */