mcu_ab568x/userboot240328/app/platform/bsp/bsp_key.c
2025-05-30 18:03:10 +08:00

390 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "include.h"
#include "func.h"
void bsp_qdec_init(void);
AT(.com_rodata.key.table)
const key_shake_tbl_t key_shake_table = {
.scan_cnt = KEY_SCAN_TIMES,
.up_cnt = KEY_UP_TIMES,
.long_cnt = KEY_LONG_TIMES,
.hold_cnt = KEY_LONG_HOLD_TIMES,
};
#if USER_ADKEY
AT(.com_text.port.key)
static u8 get_adkey(u8 key_val)
{
u8 num = 0;
while (key_val > adkey_table[num].adc_val) {
num++;
}
return adkey_table[num].usage_id;
}
#endif // USER_ADKEY
#if USER_PWRKEY
AT(.com_text.port.key)
static u8 get_pwrkey(void)
{
u8 num = 0;
u32 wko_val = saradc_get_value10(ADCCH_WKO);
u16 key_val = ((u32)wko_val << 8) / adc_cb.vrtc_val;
if (key_val > 0xff) {
key_val = 0xff;
}
while ((u8)key_val > pwrkey_table[num].adc_val) {
num++;
}
return pwrkey_table[num].usage_id;
}
#endif // USER_PWRKEY
bool power_off_check(void)
{
#if CHARGE_EN
u16 charge_cnt = 0;
#endif
u32 pwron_press_nms;
int pwrkey_pressed_flag, ticks = 0, up_cnt = 0;
u8 restart_chk_en = 1;
pwrkey_pressed_flag = 0;
pwron_press_nms = PWRON_PRESS_TIME;
if (pwron_press_nms == 0) {
pwron_press_nms = 100;
}
//要等PWRKEY开关释放后再次按下才能重新开机, 否则充电过程中5分钟关机, 低电关机等异常
if ((PWRKEY_2_HW_PWRON) && (sys_cb.poweron_flag)) {
restart_chk_en = 0;
sys_cb.poweron_flag = 0;
}
while (1) {
WDT_CLR();
delay_ms(5);
if (get_pwrkey() == key_cb.pwr_usage_id) {
up_cnt = 0;
if (restart_chk_en) {
if (!pwrkey_pressed_flag) {
ticks = tick_get();
pwrkey_pressed_flag = 1;
sys_cb.ms_ticks = tick_get(); //记录PWRKEY按键按下的时刻
}
if (!sys_cb.poweron_flag) {
if (tick_check_expire(ticks, pwron_press_nms)) { //长按开机时间配置
sys_cb.poweron_flag = 1;
sys_cb.pwrdwn_hw_flag = 0; //清PWRKEY硬开关的关机标志
}
}
}
} else {
if (up_cnt < 3) {
up_cnt++;
}
if (up_cnt == 3) {
up_cnt = 10;
sys_cb.poweron_flag = 0;
pwrkey_pressed_flag = 0;
restart_chk_en = 1;
}
}
#if CHARGE_EN
if (xcfg_cb.charge_en) {
charge_cnt++;
if (charge_cnt > 20) {
charge_cnt = 0;
charge_detect(0);
}
}
#endif // CHARGE_EN
if (sys_cb.poweron_flag) {
if ((CHARGE_DC_NOT_PWRON) && CHARGE_DC_IN()) {
continue;
}
//长按PP/POWER开机
dac_restart();
bsp_change_volume(sys_cb.vol);
#if WARNING_POWER_ON
mp3_res_play(RES_BUF_POWERON_MP3, RES_LEN_POWERON_MP3);
#endif // WARNING_POWER_ON
func_cb.sta = FUNC_CLOCK;
return true;
} else {
if (CHARGE_DC_IN()) {
continue;
} else {
return false;
}
}
}
}
AT(.text.bsp.power)
bool is_powron_frist_enable(u32 rtccon9)
{
if (!PWRON_FRIST_BAT_EN) {
return false;
}
if (rtccon9 & BIT(2)) { //WKO wakeup不能直接开机
return false;
}
if (CHARGE_DC_IN() && (CHARGE_DC_NOT_PWRON)) { //VUSB充电禁止开机
return false;
}
return true;
}
AT(.text.bsp.power)
void power_on_check(void)
{
#if CHARGE_EN
u16 charge_cnt = 0;
#endif
int pwrkey_pressed_flag = 0;
u32 pwron_press_nms;
u32 rtccon9 = RTCCON9; //wakeup pending
RTCCON9 = 0xfff; //Clr pending
RTCCON10 = 0xfff; //Clr pending
RTCCON1 &= ~BIT(6); //wko pin low level wakeup
if (LVDCON & BIT(19)) {
if (IS_PWRKEY_PRESS()) {
sys_cb.poweron_flag = 1;
}
return; //长按PWRKEY 10S复位后直接开机。
}
if (rtccon9 & BIT(0)) {
printf("alarm wakeup\n");
return;
}
#if USER_PWRKEY
int up_cnt = 0, ticks = 0;
if (!IS_PWRKEY_PRESS()) {
pwrkey_pressed_flag = 1;
ticks = sys_cb.ms_ticks;
}
#endif // USER_PWRKEY
pwron_press_nms = PWRON_PRESS_TIME;
if (pwron_press_nms < 100) {
pwron_press_nms = 100; //最小开机时间在100ms左右
}
//第一次上电是否直接开机
if (is_powron_frist_enable(rtccon9)) {
return;
}
while (1) {
WDT_CLR();
delay_ms(5);
u8 key_val = bsp_key_scan();
if ((key_val & KEY_USAGE_MASK) == key_cb.pwr_usage_id) {
up_cnt = 0;
if (!pwrkey_pressed_flag) {
ticks = tick_get();
sys_cb.ms_ticks = ticks; //记录PWRKEY按键按下的时刻
pwrkey_pressed_flag = 1;
}
if (!sys_cb.poweron_flag) {
if (tick_check_expire(ticks, pwron_press_nms)) { //长按开机时间配置
sys_cb.poweron_flag = 1;
}
}
} else {
if (up_cnt < 3) {
up_cnt++;
}
if (up_cnt == 3) {
up_cnt = 10;
pwrkey_pressed_flag = 0;
sys_cb.poweron_flag = 0;
}
}
#if CHARGE_EN
if (xcfg_cb.charge_en) {
charge_cnt++;
if ((charge_cnt % 20) == 0) {
charge_detect(0);
}
if (charge_cnt >= 200) { //1S
charge_cnt = 0;
}
//充满且蓝灯已灭,进入关机状态
if ((sys_cb.charge_sta == 2) && (!sys_cb.charge_bled_flag)) {
bsp_saradc_exit();
sfunc_pwrdown(0);
}
}
#endif // CHARGE_EN
if (sys_cb.poweron_flag) {
__pwron:
#if VBAT_DETECT_EN
if (sys_cb.vbat <= LPWR_OFF_VBAT) { //电压小于3.1v不开机
continue;
}
#endif
if ((CHARGE_DC_NOT_PWRON) && CHARGE_DC_IN()) {
continue;
}
//长按PP/POWER开机
break;
} else {
//PWKKEY松开立刻关机
if (!pwrkey_pressed_flag) {
if (!CHARGE_DC_IN()) {
if ((!SOFT_POWER_ON_OFF) || ((!USER_PWRKEY) && (!PWRKEY_2_HW_PWRON))) {
goto __pwron; //没有软开关机功能,直接开机。
}
bsp_saradc_exit();
// sfunc_pwrdown(1);
}
}
}
}
}
void key_init(void)
{
key_var_init();
#if USER_IOKEY
io_key_init();
#endif
#if USER_ADKEY
saradc_set_channel(BIT(ADKEY_CH));
// adcch_io_pu10k_enable(ADKEY_CH); //开内部10K上拉
#endif
#if USER_PWRKEY
saradc_set_channel(BIT(ADCCH_VRTC) | BIT(ADCCH_WKO));
key_cb.pwr_usage_id = pwrkey_table[USER_PWRON_KEY_SEL].usage_id; //开关机按键定义
#endif
#if VBAT_DETECT_EN
saradc_set_channel(BIT(ADCCH_BGOP) | BIT(VBAT2_ADCCH));
#endif
#if USER_KEY_QDEC_EN || USER_ADKEY_QDEC_EN
bsp_qdec_init(); //旋转编码器初始化
#endif
bsp_saradc_init();
power_on_check();
CRSTPND = 0x1ff0000; //clear reset pending
}
AT(.com_text.bsp.key)
bool get_poweron_flag(void)
{
return sys_cb.poweron_flag;
}
AT(.com_text.bsp.key)
void set_poweron_flag(bool flag)
{
sys_cb.poweron_flag = flag;
}
u8 get_pwroff_pressed_time(void)
{
return PWROFF_PRESS_TIME;
}
u8 get_double_key_time(void)
{
if (USER_MULTI_KEY_TIME > 8) {
return 70;
} else {
return (u8)(USER_MULTI_KEY_TIME*20 + 1);
}
}
//AT(.com_rodata.bsp.key)
//const char key_str[] = "enqueue: %04x\n";
AT(.com_text.bsp.key)
u16 bsp_key_process(u16 key_val)
{
u16 key_return = NO_KEY, key;
key_return = key_process(key_val);
key = key_return;
//多击处理
#if USER_MULTI_PRESS_EN
key_return = key_multi_press_process(key_return);
if (key != key_return && (key & KEY_TYPE_MASK) == KEY_SHORT_UP) {
msg_enqueue(key); //short up key
// printf(key_str, key);
}
#endif
return key_return;
}
AT(.com_text.bsp.key)
u8 bsp_key_scan(void)
{
u8 key_val = NO_KEY;
u16 key = NO_KEY;
#if VBAT_DETECT_EN
if (adc_vbat2_flag) {
adc_vbat2_flag = false;
sys_cb.vbat = bsp_vbat_get_voltage();
}
#endif
#if USER_ADKEY
if (key_val == NO_KEY) {
key_val = get_adkey(saradc_get_value8(ADKEY_CH));
}
#endif // USER_ADKEY
#if USER_PWRKEY
if (key_val == NO_KEY) {
key_val = get_pwrkey();
}
#endif // USER_PWRKEY
#if USER_IOKEY
if (key_val == NO_KEY) {
key_val = get_iokey();
}
#endif // USER_IOKEY
key = bsp_key_process(key_val);
if (key != NO_KEY) {
//防止enqueue多次HOLD消息
if ((key & KEY_TYPE_MASK) == KEY_LONG) {
sys_cb.kh_vol_msg = (key & KEY_USAGE_MASK) | KEY_HOLD;
} else if ((key & KEY_TYPE_MASK) == KEY_LONG_UP) {
msg_queue_detach(sys_cb.kh_vol_msg, 0);
sys_cb.kh_vol_msg = NO_KEY;
} else if (sys_cb.kh_vol_msg == key) {
msg_queue_detach(key, 0);
}
// printf(key_str, key);
if (sys_cb.gui_sleep_sta) {
sys_cb.gui_need_wakeup = 1;
}
msg_enqueue(key);
reset_sleep_delay_all();
}
return key_val;
}