254 lines
6.7 KiB
C
254 lines
6.7 KiB
C
|
#include "includes.h"
|
|||
|
#include "key_driver.h"
|
|||
|
#include "adkey.h"
|
|||
|
#include "gpio.h"
|
|||
|
#include "system/event.h"
|
|||
|
#include "app_config.h"
|
|||
|
#include "asm/power/p33.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;
|
|||
|
|
|||
|
static const struct adkey_rtcvdd_platform_data *__this = NULL;
|
|||
|
|
|||
|
|
|||
|
u8 adkey_rtcvdd_get_key_value(void);
|
|||
|
//按键驱动扫描参数列表
|
|||
|
struct key_driver_para adkey_rtcvdd_scan_para = {
|
|||
|
.scan_time = 10, //按键扫描频率, 单位: ms
|
|||
|
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
|||
|
.filter_time = 2, //按键消抖延时;
|
|||
|
.long_time = 75, //按键判定长按数量
|
|||
|
.hold_time = (75 + 15), //按键判定HOLD数量
|
|||
|
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
|||
|
.key_type = KEY_DRIVER_TYPE_RTCVDD_AD,
|
|||
|
.get_value = adkey_rtcvdd_get_key_value,
|
|||
|
};
|
|||
|
|
|||
|
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(const struct adkey_rtcvdd_platform_data *adkey_data)
|
|||
|
{
|
|||
|
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_direction(__this->adkey_pin, 1);
|
|||
|
gpio_set_pull_down(__this->adkey_pin, 0);
|
|||
|
gpio_set_die(__this->adkey_pin, 0);
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif /* #if TCFG_ADKEY_RTCVDD_ENABLE */
|
|||
|
|