Initial commit: TXW82x FPV v2.7.0.7-42229 SDK + project sources
This commit is contained in:
125
sdk/lib/key/adkey.c
Normal file
125
sdk/lib/key/adkey.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "adkey.h"
|
||||
#include "keyScan.h"
|
||||
|
||||
#include "dev/adc/hgadc_v0.h"
|
||||
#include "hal/gpio.h"
|
||||
#ifdef PIN_FROM_PARAM
|
||||
#include "pin_param.h"
|
||||
#endif
|
||||
|
||||
static adkey_t adkey= {
|
||||
.priv = NULL,
|
||||
.pull = GPIO_PULL_NONE,
|
||||
.pull_level = GPIO_PULL_LEVEL_4_7K,
|
||||
};
|
||||
|
||||
static void key_adkey_init(key_channel_t *key)
|
||||
{
|
||||
adkey_t *adkey = (adkey_t *)key->priv;
|
||||
struct hgadc_v0 *adc = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
|
||||
adkey->pin = MACRO_PIN(PIN_ADKEY1);
|
||||
adc_open((struct adc_device *)adc);
|
||||
gpio_set_mode(adkey->pin,adkey->pull,adkey->pull_level);
|
||||
adc_add_channel((struct adc_device *)adc, adkey->pin);
|
||||
|
||||
adkey->priv = (void*)adc;
|
||||
key->enable = 1;
|
||||
|
||||
}
|
||||
|
||||
static uint8 key_adkey_scan(key_channel_t *key)
|
||||
{
|
||||
adkey_t *adkey = (adkey_t *)key->priv;
|
||||
uint32 vol;
|
||||
struct adkey_scan_code *key_scan = (struct adkey_scan_code*)key->key_table;
|
||||
adc_get_value((struct adc_device *)adkey->priv, adkey->pin, &vol);
|
||||
// printf("vol:%d\n",vol);
|
||||
//记录当前adc的值,用与发送到应用层,至于应用层是否需要,由应用层去管理
|
||||
key->extern_value = vol;
|
||||
for(;;)
|
||||
{
|
||||
if(vol>=key_scan->adc)
|
||||
{
|
||||
key_scan++;
|
||||
}
|
||||
else
|
||||
{
|
||||
key_scan--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// printf("key_scan->key:%d\tvol:%d\n",key_scan->key,vol);
|
||||
return key_scan->key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************
|
||||
* adkey的参数配置
|
||||
*
|
||||
default: 2117
|
||||
up:910
|
||||
down:462
|
||||
left:6
|
||||
right:1368
|
||||
press:1826
|
||||
|
||||
默认开发板先检查每一个按键的值,然后大概每一个ad-100填到下表
|
||||
************************************************************/
|
||||
#ifdef SYS_APP_WALKIE_TALKIE
|
||||
static const struct adkey_scan_code adkey_table[] =
|
||||
{
|
||||
{0, AD_DOWN},
|
||||
{200, AD_DOWN},
|
||||
{635, AD_SPEACH},
|
||||
{1275, AD_UP},
|
||||
{1620, AD_RIGHT},
|
||||
{2047, KEY_NONE},
|
||||
{3200, KEY_NONE},
|
||||
{3800, KEY_NONE},
|
||||
{4000, KEY_NONE},
|
||||
{4096, KEY_NONE},
|
||||
};
|
||||
#else
|
||||
static const struct adkey_scan_code adkey_table[] =
|
||||
{
|
||||
{0, AD_LEFT},
|
||||
{350, AD_DOWN},
|
||||
{800, AD_UP},
|
||||
{1200, AD_RIGHT},
|
||||
{1700, AD_PRESS},
|
||||
{2000, KEY_NONE},
|
||||
{3200, KEY_NONE},
|
||||
{3800, KEY_NONE},
|
||||
{4000, KEY_NONE},
|
||||
{4096, KEY_NONE},
|
||||
};
|
||||
#endif
|
||||
|
||||
static const keys_t adkey_arg =
|
||||
{
|
||||
.period_long = 500,
|
||||
.period_repeat = 1000,
|
||||
.period_dither = 80,
|
||||
};
|
||||
|
||||
//外部调用
|
||||
key_channel_t adkey_key =
|
||||
{
|
||||
.init = key_adkey_init,
|
||||
.scan = key_adkey_scan,
|
||||
.prepare = NULL,
|
||||
.priv = (void*)&adkey,
|
||||
.key_arg = &adkey_arg,//按键的参数,可能不同的类型按键,参数不一样
|
||||
.key_table = &adkey_table,
|
||||
};
|
||||
|
||||
|
||||
|
||||
39
sdk/lib/key/adkey.h
Normal file
39
sdk/lib/key/adkey.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef _ADKEY_H
|
||||
#define _ADKEY_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "osal/timer.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "keyScan.h"
|
||||
|
||||
|
||||
|
||||
struct adkey_t;
|
||||
struct keys_t;
|
||||
typedef struct adkey_t adkey_t;
|
||||
|
||||
|
||||
|
||||
struct adkey_t
|
||||
{
|
||||
void *priv;
|
||||
uint32 pin; //io
|
||||
uint8 pull; //上拉下拉
|
||||
uint8 pull_level; //上下拉电阻
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct adkey_scan_code
|
||||
{
|
||||
int adc;
|
||||
uint8 key;
|
||||
};
|
||||
|
||||
key_channel_t adkey_key;
|
||||
#endif
|
||||
216
sdk/lib/key/keyScan.c
Normal file
216
sdk/lib/key/keyScan.c
Normal file
@@ -0,0 +1,216 @@
|
||||
#include "keyScan.h"
|
||||
|
||||
/*************************************************************************************
|
||||
* 按键扫描判断的timer事件
|
||||
* 最终调用key_scan_init来注册事件
|
||||
*
|
||||
*
|
||||
**************************************************************************************/
|
||||
static void g_key_scan(key_channel_t *ch)
|
||||
{
|
||||
const keys_t *arg = ch->key_arg;
|
||||
uint8 key = ch->scan(ch);
|
||||
uint8 key_code = KEY_EVENT_MAX;
|
||||
uint8 key_event = KEY_EVENT_MAX;
|
||||
|
||||
//分析按键情况
|
||||
//按键可能被释放或者说原本就是没有被按下
|
||||
if(key == 0)
|
||||
{
|
||||
//按键没有被按下,无需去管理
|
||||
if(ch->last_key == 0)
|
||||
{
|
||||
goto g_key_scan_end;
|
||||
}
|
||||
|
||||
//按键从被按下到释放,反馈事件,有两种可能:短按释放,长按释放,异常情况则是(消抖没有完成就被释放)
|
||||
else
|
||||
{
|
||||
|
||||
//异常事件,正常不可能存在,检查程序,可能存在按键抖动情况,不作任何判断
|
||||
if(ch->last_event == KEY_EVENT_MAX)
|
||||
{
|
||||
//printf("%s:%d err,last key:%d,now key:%d\tlast_event:%d\n",__FUNCTION__,__LINE__,ch->last_key,key,ch->last_event );
|
||||
//printf("last time:%d\tnow time:%d\n",ch->last_time,os_jiffies());
|
||||
}
|
||||
else if(ch->last_event == KEY_EVENT_LDOWN || ch->last_event == KEY_EVENT_REPEAT)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_MAX;
|
||||
key_event = KEY_EVENT_LUP;
|
||||
key_code = ch->last_key;
|
||||
}
|
||||
else if(ch->last_event == KEY_EVENT_DOWN)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_MAX;
|
||||
key_event = KEY_EVENT_SUP;
|
||||
key_code = ch->last_key;
|
||||
}
|
||||
ch->last_key = key;
|
||||
}
|
||||
}
|
||||
|
||||
//有多种情况,key与last key不一样,分两种情况,按键抖动(相隔的时间太短),则以后面的key为准,并且时间清0,另一种则是按键检测的时候,错过了up的事件(因为用软定时,有可能错过,这个时候应该发出一个up事件,但也有可能按键接触不良,可以先发出up事件,key当作没有,等待下次的key再去判断)
|
||||
else
|
||||
{
|
||||
|
||||
//同样按键,判断时间超出按键抖动范围,如果是,则发出被按下事件
|
||||
if(key == ch->last_key)
|
||||
{
|
||||
//上一次没有事件,则是消抖时间完成,发出按键按下事件
|
||||
if(ch->last_event == KEY_EVENT_MAX)
|
||||
{
|
||||
if(os_jiffies() - ch->last_time > arg->period_dither)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_DOWN;
|
||||
key_event = KEY_EVENT_DOWN;
|
||||
key_code = ch->last_key;
|
||||
//无需更新时间,下一次则进入去判断是否长按
|
||||
ch->last_time = os_jiffies();
|
||||
|
||||
}
|
||||
//消抖时间没有完成
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
//上一次已经有down的事件,则需要继续判断后续的事件(是否为长按或者重复按键)
|
||||
else
|
||||
{
|
||||
|
||||
//短按,超过长按的时间,发出长按被按下的事件
|
||||
if(ch->last_event == KEY_EVENT_DOWN )
|
||||
{
|
||||
if(os_jiffies() - ch->last_time > arg->period_long)
|
||||
{
|
||||
//长按事件被按下
|
||||
ch->last_event = KEY_EVENT_LDOWN;
|
||||
key_event = KEY_EVENT_LDOWN;
|
||||
key_code = ch->last_key;
|
||||
//用于判断是否是重复按键
|
||||
ch->last_time = os_jiffies();
|
||||
}
|
||||
//不是长按,还在等待时间
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ch->last_event == KEY_EVENT_LDOWN || ch->last_event == KEY_EVENT_REPEAT)
|
||||
{
|
||||
if(os_jiffies() - ch->last_time > arg->period_repeat)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_REPEAT;
|
||||
key_event = KEY_EVENT_REPEAT;
|
||||
key_code = ch->last_key;
|
||||
//用于判断下一次判断
|
||||
ch->last_time = os_jiffies();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os_printf("%s:%d err,last key:%d,now key:%d\tlast_event:%d\n",__FUNCTION__,__LINE__,ch->last_key,key,ch->last_event );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//刚被按下,则记录时间,等待抖动结束
|
||||
if(!ch->last_key)
|
||||
{
|
||||
ch->last_time = os_jiffies();
|
||||
ch->last_key = key;
|
||||
}
|
||||
|
||||
//两次按键不一致,那么就要去识别事件,如果last_event没有事件,代表消抖没有完成,则重新计算时间,如果消抖完成,则需要发出up事件,last_key = 0
|
||||
else if(ch->last_key != key)
|
||||
{
|
||||
//消抖没有完成,更新按键的值
|
||||
if(ch->last_event == KEY_EVENT_MAX)
|
||||
{
|
||||
ch->last_time = os_jiffies();
|
||||
ch->last_key = key;
|
||||
}
|
||||
//消抖完成,发出up事件,然后last_key设置为0,等待下次按键判断
|
||||
else
|
||||
{
|
||||
if(ch->last_event == KEY_EVENT_LDOWN || ch->last_event == KEY_EVENT_REPEAT)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_MAX;
|
||||
key_event = KEY_EVENT_LUP;
|
||||
key_code = ch->last_key;
|
||||
}
|
||||
else if(ch->last_event == KEY_EVENT_DOWN)
|
||||
{
|
||||
ch->last_event = KEY_EVENT_MAX;
|
||||
key_event = KEY_EVENT_SUP;
|
||||
key_code = ch->last_key;
|
||||
ch->last_time = os_jiffies();
|
||||
}
|
||||
ch->last_key = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_key_scan_end:
|
||||
if(key_event != KEY_EVENT_MAX)
|
||||
{
|
||||
// key_map_t *map = ch->key_table_map;
|
||||
//uint32 map_msg = map[key_code][key_event];
|
||||
uint32 map_msg = (key_code<<8 | key_event);
|
||||
if(map_msg && ch->key_send)
|
||||
{
|
||||
ch->key_send(map_msg,ch->extern_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//timer事件
|
||||
static void key_auto_timer_cb(void *arg)
|
||||
{
|
||||
key_channel_t **channel = (key_channel_t **)arg;
|
||||
key_channel_t **ch;
|
||||
for (ch = &channel[0]; *ch; ++ch)
|
||||
{
|
||||
if(!(*ch)->enable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if((*ch)->prepare)
|
||||
{
|
||||
(*ch)->prepare(*ch);
|
||||
}
|
||||
if((*ch)->scan)
|
||||
{
|
||||
g_key_scan(*ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static os_timer_t key_timer;
|
||||
//先初始化,然后注册timer,注册按键的映射表,最后启动timer
|
||||
void key_button_scan_init(key_channel_t **channel,key_send_msg send)
|
||||
{
|
||||
key_channel_t **ch = channel;
|
||||
for (; *ch; ++ch)
|
||||
{
|
||||
(*ch)->last_event = KEY_EVENT_MAX;
|
||||
(*ch)->last_key = KEY_EVENT_MAX;
|
||||
(*ch)->last_time = os_jiffies();
|
||||
(*ch)->key_send = send;
|
||||
if((*ch)->init)
|
||||
{
|
||||
(*ch)->init(*ch);
|
||||
}
|
||||
}
|
||||
os_timer_init(&key_timer, key_auto_timer_cb, OS_TIMER_MODE_PERIODIC, (void*)channel);
|
||||
os_timer_start(&key_timer, 5);
|
||||
}
|
||||
|
||||
|
||||
92
sdk/lib/key/keyScan.h
Normal file
92
sdk/lib/key/keyScan.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef __KEYSCAN_H
|
||||
#define __KEYSCAN_H
|
||||
#include "basic_include.h"
|
||||
/**************************************************************************
|
||||
* 按键的事件
|
||||
* 说明:按键触发可能短时间由多个事件,比如长按:先是有个按键按下->长按按下->长按释放
|
||||
* 所以要考虑监听哪个事件,比如短按的,最好监听短按释放,毕竟按键按下事件都会有触发的
|
||||
***************************************************************************/
|
||||
enum
|
||||
{
|
||||
KEY_EVENT_DOWN, //按键按下
|
||||
KEY_EVENT_SUP, //短按释放
|
||||
KEY_EVENT_LDOWN, //长按按下
|
||||
KEY_EVENT_LUP, //长按释放
|
||||
KEY_EVENT_REPEAT, //一直按住按键
|
||||
KEY_EVENT_MAX,
|
||||
};
|
||||
|
||||
/***************************************
|
||||
* 按键值的定义
|
||||
***************************************/
|
||||
enum
|
||||
{
|
||||
KEY_NONE,
|
||||
AD_UP,
|
||||
AD_DOWN,
|
||||
AD_LEFT,
|
||||
AD_RIGHT,
|
||||
AD_PRESS,
|
||||
AD_A,
|
||||
AD_B,
|
||||
AD_C,
|
||||
AD_SPEACH,
|
||||
KEY_BACK,
|
||||
KEY_MAGIC_SWITCH,
|
||||
KEY_IPF_SWITCH,
|
||||
KEY_PAIR,
|
||||
KEY_POWER,
|
||||
KEY_POWEROFF,
|
||||
LOWPOWER_CHECK,
|
||||
KEY_CALLING_START,
|
||||
KEY_CALLING_STOP,
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct key_channel_t ;
|
||||
struct keys_t ;
|
||||
|
||||
typedef struct key_channel_t key_channel_t;
|
||||
typedef void (*keyinit_func) (struct key_channel_t*);
|
||||
typedef void (*keyprepare_func) (struct key_channel_t*);
|
||||
typedef uint8 (*keyscan_func) (struct key_channel_t*);
|
||||
typedef int32 (*key_send_msg) (uint32 data,uint32_t value);
|
||||
typedef uint32 key_map_t[KEY_EVENT_MAX];
|
||||
typedef struct keys_t keys_t;
|
||||
|
||||
|
||||
|
||||
struct keys_t
|
||||
{
|
||||
uint32_t period_long;
|
||||
uint32_t period_repeat;
|
||||
uint32_t period_dither;
|
||||
};
|
||||
|
||||
struct key_channel_t
|
||||
{
|
||||
keyinit_func init; //初始化
|
||||
keyprepare_func prepare;//scan之前的准备,可以设置为NULL,也可以去设置enable值来作为是否要进行按键检测
|
||||
keyscan_func scan; //获取按键键值
|
||||
const void *key_table;//按键表格,scan需要用到,如果是adc需要根据表格获取是哪个按键被按下
|
||||
const keys_t *key_arg;
|
||||
|
||||
|
||||
void *priv;
|
||||
key_send_msg key_send;
|
||||
uint32_t last_key;
|
||||
uint32_t last_time;
|
||||
uint32_t last_event;
|
||||
|
||||
uint32_t extern_value;
|
||||
uint8 enable;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void key_button_scan_init(key_channel_t **channel,key_send_msg send);
|
||||
#endif
|
||||
169
sdk/lib/key/keyWork.c
Normal file
169
sdk/lib/key/keyWork.c
Normal file
@@ -0,0 +1,169 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "osal/string.h"
|
||||
#include "osal/msgqueue.h"
|
||||
#include "osal/work.h"
|
||||
#include "osal/string.h"
|
||||
#include "keyWork.h"
|
||||
#include "keyScan.h"
|
||||
#include "adkey.h"
|
||||
#include "power_checkkey.h"
|
||||
#include "csi_kernel.h"
|
||||
/*****************************************
|
||||
* 按照不同按键,请注册对应按键进来,参看adkey.c
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* adkey或者ioKey或者touchkey
|
||||
* 添加多个的例子
|
||||
* static key_channel_t *button_channels[] = {&adkey_key,&powercheck_key,NULL};
|
||||
*****************************************/
|
||||
|
||||
static key_channel_t *button_channels[] = {&adkey_key,NULL};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//添加其他不同类型的按键头文件
|
||||
static void *g_key_msgq = NULL;
|
||||
static struct list_head wait_register_list;
|
||||
static struct list_head register_list;
|
||||
static uint8_t key_callback_change = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
void *add_keycallback(key_callback callback,void *priv)
|
||||
{
|
||||
struct key_callback_list_s *add_list = os_zalloc(sizeof(struct key_callback_list_s));
|
||||
if(!add_list)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
add_list->priv = priv;
|
||||
add_list->callback = callback;
|
||||
add_list->flag = 0;
|
||||
INIT_LIST_HEAD(&add_list->list);
|
||||
|
||||
uint32_t flags;
|
||||
os_printf("add_list:%X\n",add_list);
|
||||
flags = disable_irq();
|
||||
list_add_tail(&add_list->list, &wait_register_list);
|
||||
key_callback_change = 1;
|
||||
enable_irq(flags);
|
||||
return add_list;
|
||||
|
||||
}
|
||||
|
||||
uint8_t remove_keycallback(struct key_callback_list_s *remove_list)
|
||||
{
|
||||
uint32_t flags;
|
||||
flags = disable_irq();
|
||||
remove_list->flag = 1;
|
||||
key_callback_change = 1;
|
||||
enable_irq(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//获取按键的workqueue或者任务
|
||||
static int32 key_read_loop(struct os_work *work)
|
||||
{
|
||||
struct key_msg_s key_msg;
|
||||
struct key_callback_list_s *ptr, *next;
|
||||
void *msg = g_key_msgq;
|
||||
int res;
|
||||
uint32_t val = 0;
|
||||
uint32_t extern_value = 0;
|
||||
//判断一下标志位
|
||||
//可能有链表要移除或者新增加callback
|
||||
if(key_callback_change)
|
||||
{
|
||||
uint32_t flags;
|
||||
|
||||
flags = disable_irq();
|
||||
//先添加,后移除
|
||||
list_for_each_entry_safe(ptr, next, &wait_register_list, list)
|
||||
{
|
||||
list_del(&ptr->list);
|
||||
list_add_tail(&ptr->list, ®ister_list);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ptr, next, ®ister_list, list)
|
||||
{
|
||||
// 对每个节点执行操作
|
||||
if(ptr->flag)
|
||||
{
|
||||
os_printf("del key_callback:%X\n",ptr);
|
||||
list_del(&ptr->list); // 从链表中删除节点
|
||||
os_free(ptr); // 释放节点内存
|
||||
}
|
||||
}
|
||||
key_callback_change = 0;
|
||||
enable_irq(flags);
|
||||
}
|
||||
res = csi_kernel_msgq_get(msg,&key_msg,0);
|
||||
if(!res)
|
||||
{
|
||||
val = key_msg.keycode;
|
||||
extern_value = key_msg.extern_value;
|
||||
//os_printf("key:%d\tstatus:%d\textern_value:%d\n",val>>8,val&0xff,extern_value);
|
||||
list_for_each_entry_safe(ptr, next, ®ister_list, list)
|
||||
{
|
||||
//_os_printf("register ptr:%X\n",ptr);
|
||||
if(ptr->callback)
|
||||
{
|
||||
ptr->callback(ptr,val,extern_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//隔1ms读取一次按键,因为用的是workqueue,不能卡住这个任务,这里的1ms也不是准确的,因为按键,所以可以延时,如果延时太大,要检查
|
||||
//workqueue哪个事件卡住导致的
|
||||
os_run_work_delay(work, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//注册的的消息函数
|
||||
static int32 key_send_msg_func(uint32_t data,uint32_t extern_value)
|
||||
{
|
||||
struct key_msg_s key_msg = {data,extern_value};
|
||||
if(g_key_msgq)
|
||||
{
|
||||
return csi_kernel_msgq_put(g_key_msgq,&key_msg,0,0);;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
//初始化函数
|
||||
static struct os_work key_wk;
|
||||
|
||||
|
||||
|
||||
|
||||
int32 keyWork_init(int listen_max)
|
||||
{
|
||||
//创建key的信号量
|
||||
INIT_LIST_HEAD(&wait_register_list);
|
||||
INIT_LIST_HEAD(®ister_list);
|
||||
void *key_msgq = (void*)csi_kernel_msgq_new(listen_max,sizeof(struct key_msg_s));
|
||||
if(key_msgq)
|
||||
{
|
||||
g_key_msgq = key_msgq;
|
||||
key_button_scan_init(button_channels,key_send_msg_func);
|
||||
//使用workqueue去监听按键?如果没有workqueue就使用创建线程吧
|
||||
OS_WORK_INIT(&key_wk, key_read_loop, 0);
|
||||
os_run_work_delay(&key_wk, 1);
|
||||
return RET_OK;
|
||||
}
|
||||
return RET_ERR;
|
||||
}
|
||||
30
sdk/lib/key/keyWork.h
Normal file
30
sdk/lib/key/keyWork.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef __KEYWORK_H
|
||||
#define __KEYWORK_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
struct key_callback_list_s;
|
||||
|
||||
|
||||
//keyvalue:按键的键值和状态
|
||||
//extern_value:额外参数,根据不同按键传输数据不一样,比如adkey传的是adc的值,如果是powerkey,可以传输对应的电量值
|
||||
typedef uint32_t (*key_callback)(struct key_callback_list_s *key_callback_list,uint32_t keyvalue,uint32_t extern_value);
|
||||
|
||||
struct key_callback_list_s
|
||||
{
|
||||
struct list_head list;
|
||||
key_callback callback;
|
||||
void *priv;
|
||||
uint8_t flag; //0正常 1要删除
|
||||
};
|
||||
|
||||
struct key_msg_s
|
||||
{
|
||||
uint32_t keycode;
|
||||
uint32_t extern_value;
|
||||
};
|
||||
|
||||
void *add_keycallback(key_callback callback,void *priv);
|
||||
uint8_t remove_keycallback(struct key_callback_list_s *remove_list);
|
||||
int32 keyWork_init(int listen_max);
|
||||
#endif
|
||||
98
sdk/lib/key/power_checkkey.c
Normal file
98
sdk/lib/key/power_checkkey.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "adkey.h"
|
||||
#include "keyScan.h"
|
||||
|
||||
#include "dev/adc/hgadc_v0.h"
|
||||
#include "hal/gpio.h"
|
||||
|
||||
|
||||
static void key_powerkey_init(key_channel_t *key)
|
||||
{
|
||||
adkey_t *adkey = (adkey_t *)key->priv;
|
||||
struct hgadc_v0 *adc = (struct hgadc_v0*)dev_get(HG_ADC0_DEVID);
|
||||
|
||||
adc_open((struct adc_device *)adc);
|
||||
gpio_set_mode(adkey->pin,adkey->pull,adkey->pull_level);
|
||||
adc_add_channel((struct adc_device *)adc, adkey->pin);
|
||||
|
||||
adkey->priv = (void*)adc;
|
||||
key->enable = 1;
|
||||
|
||||
}
|
||||
|
||||
static uint8 key_powerkey_scan(key_channel_t *key)
|
||||
{
|
||||
adkey_t *adkey = (adkey_t *)key->priv;
|
||||
uint32 vol;
|
||||
struct adkey_scan_code *key_scan = (struct adkey_scan_code*)key->key_table;
|
||||
adc_get_value((struct adc_device *)adkey->priv, adkey->pin, &vol);
|
||||
//记录当前adc的值,用与发送到应用层,至于应用层是否需要,由应用层去管理
|
||||
key->extern_value = vol;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(vol>=key_scan->adc)
|
||||
{
|
||||
key_scan++;
|
||||
}
|
||||
else
|
||||
{
|
||||
key_scan--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return key_scan->key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************
|
||||
* powerkey的参数配置
|
||||
*
|
||||
* 可以配置类似低电量的检测
|
||||
************************************************************/
|
||||
static const struct adkey_scan_code powerkey_table[] =
|
||||
{
|
||||
{0, LOWPOWER_CHECK},
|
||||
{400, KEY_NONE},
|
||||
{4096, KEY_NONE},
|
||||
};
|
||||
|
||||
//配置对应的时间,正常来说,电量检测不需要短按事件,只要设置长按以及repeat的事件就行了,repeat就是
|
||||
//当前电量
|
||||
static const keys_t powerkey_arg =
|
||||
{
|
||||
.period_long = 500,
|
||||
.period_repeat = 1000,
|
||||
.period_dither = 80,
|
||||
};
|
||||
|
||||
|
||||
static adkey_t powerkey= {
|
||||
.priv = NULL,
|
||||
.pin = PA_3,
|
||||
.pull = GPIO_PULL_NONE,
|
||||
.pull_level = GPIO_PULL_LEVEL_100K,
|
||||
};
|
||||
|
||||
|
||||
|
||||
//这里逻辑与ADKEY一样,因为都是ad检测
|
||||
key_channel_t powercheck_key =
|
||||
{
|
||||
.init = key_powerkey_init,
|
||||
.scan = key_powerkey_scan,
|
||||
.prepare = NULL,
|
||||
.priv = (void*)&powerkey,
|
||||
.key_arg = &powerkey_arg,//按键的参数,可能不同的类型按键,参数不一样
|
||||
.key_table = &powerkey_table,
|
||||
};
|
||||
|
||||
|
||||
|
||||
15
sdk/lib/key/power_checkkey.h
Normal file
15
sdk/lib/key/power_checkkey.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __POWER_CHECKKEY_H
|
||||
#define __POWER_CHECKKEY_H
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "hal/gpio.h"
|
||||
#include "osal/timer.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/mutex.h"
|
||||
#include "keyScan.h"
|
||||
|
||||
key_channel_t powercheck_key;
|
||||
#endif
|
||||
Reference in New Issue
Block a user