初版
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user