525 lines
15 KiB
C
525 lines
15 KiB
C
#include "include.h"
|
||
#include "func.h"
|
||
#include "app_variable.h"
|
||
void bsp_qdec_init(void);
|
||
void rtc_alarm_disable(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(SysVariable.vol);
|
||
#if WARNING_POWER_ON
|
||
mp3_res_play(RES_BUF_POWERON_MP3, RES_LEN_POWERON_MP3);
|
||
#endif // WARNING_POWER_ON
|
||
|
||
func_switch_to_assign_screen(FUNC_CLOCK, false);
|
||
|
||
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 && exception_restart_cause() == RESTART_FIRST_ON) {
|
||
return false;
|
||
}
|
||
if (rtccon9 & BIT(2)) { //WKO wakeup不能直接开机
|
||
return false;
|
||
}
|
||
if (CHARGE_DC_IN() && (CHARGE_DC_NOT_PWRON)) { //VUSB充电禁止开机
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void sniff_rc_init(void)
|
||
{
|
||
CLKGAT1 |= BIT(26);
|
||
CLKCON1 = (CLKCON1 & ~(3 << 28)) | BIT(29); //freq_clkin select xosc26m_clk
|
||
CLKCON1 = (CLKCON1 & ~(3 << 30)); //freqdet_clk select rtc_rc2m
|
||
FREQDETCON = (2000-1) << 16; //timer pr
|
||
|
||
RTCCON0 |= BIT(2); //rtc_rc2m
|
||
RTCCON0 &= ~BIT(20); //SNIFF_RC_RTC
|
||
RTCCON0 = (RTCCON0 & ~(3 << 16)) | (1 << 16); //RI_BIAS = 1
|
||
RTCCON0 |= BIT(18); //RI_EN_SNIFF = 1
|
||
}
|
||
|
||
void rtc_power_on_calibration(void)
|
||
{
|
||
rtc_alarm_disable();
|
||
if (cm_read8(PARAM_RTC_CAL_VALID) == 1) {
|
||
sniff_rc_init();
|
||
rtc_calibration_read(PARAM_RTC_CAL_ADDR);
|
||
rtc_clock_calc_by_rc(1);
|
||
rtc_printf();
|
||
}
|
||
}
|
||
|
||
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
|
||
u32 rtccon10 = RTCCON10;
|
||
|
||
RTCCON9 = 0xfff; //Clr pending
|
||
RTCCON10 = 0xfff; //Clr pending
|
||
RTCCON1 &= ~BIT(6); //wko pin low level wakeup
|
||
#if defined(TJD_SET_PUSH_DIAL_FLAH_TO_BUILT_IN_DIAL_FLASH)
|
||
param_dial_update_read();
|
||
|
||
// printf("sys_cb.ble_dial_updated : %d \n",sys_cb.ble_dial_updated);
|
||
if(sys_cb.ble_dial_updated == 2){
|
||
SysVariable.dial_watch = 0;
|
||
}
|
||
// printf("SysVariable.dial_watch : %d \n",SysVariable.dial_watch);
|
||
#endif
|
||
|
||
if ((LVDCON & BIT(19)) && (rtccon10 & BIT(10)) && (sys_cb.vbat >LPWR_OFF_VBAT)) {
|
||
if (IS_PWRKEY_PRESS()) {
|
||
sys_cb.poweron_flag = 1;
|
||
}
|
||
return; //长按PWRKEY 10S复位后直接开机。
|
||
}
|
||
|
||
if (rtccon9 & BIT(0) && (sys_cb.vbat >LPWR_OFF_VBAT)) {
|
||
// 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) && (sys_cb.vbat >LPWR_OFF_VBAT)) {
|
||
return;
|
||
}
|
||
|
||
while (1) {
|
||
WDT_CLR();
|
||
delay_ms(1);
|
||
bsp_saradc_tmr1ms_process();
|
||
|
||
#if CHARGE_EN
|
||
// 实时更新电池电压会有100mv的误差 否则在while(1)循环中电池电压更新慢且不准
|
||
if ((charge_cnt %5) == 0) {
|
||
saradc_kick_start_do(saradc_cb.channel | (BIT(ADCCH_VBAT)), 0, 0);
|
||
sys_cb.vbat = bsp_vbat_get_voltage(1);
|
||
}
|
||
#endif
|
||
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*5) {
|
||
up_cnt++;
|
||
}
|
||
if (up_cnt == 3*5) {
|
||
up_cnt = 10*5;
|
||
pwrkey_pressed_flag = 0;
|
||
sys_cb.poweron_flag = 0;
|
||
}
|
||
}
|
||
|
||
#if CHARGE_EN
|
||
if (xcfg_cb.charge_en) {
|
||
charge_cnt++;
|
||
if ((charge_cnt % (20*5)) == 0) {
|
||
charge_detect(0);
|
||
}
|
||
if (charge_cnt >= (200*5)) { //1S
|
||
charge_cnt = 0;
|
||
// printf("sys_cb.vbat %d \n", sys_cb.vbat);
|
||
}
|
||
|
||
if (CHARGE_DC_IN()&&(sys_cb.vbat <= CHARGE_PWRON_VBAT)) {
|
||
continue;
|
||
}
|
||
|
||
if (CHARGE_DC_IN()&&(sys_cb.vbat > CHARGE_PWRON_VBAT)) {
|
||
// printf(" break sys_cb.vbat %d \n", sys_cb.vbat);
|
||
break;
|
||
}
|
||
//充满且蓝灯已灭,进入关机状态
|
||
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 <= CHARGE_PWRON_VBAT) { //电压小于3.3v不开机
|
||
continue;
|
||
}
|
||
#endif
|
||
if ((CHARGE_DC_NOT_PWRON) && CHARGE_DC_IN()) {
|
||
continue;
|
||
}
|
||
//长按PP/POWER开机
|
||
rtc_power_on_calibration();
|
||
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();
|
||
if (cm_read8(PARAM_RTC_CAL_VALID) == 1) {
|
||
sniff_rc_init();
|
||
rtc_calibration_read(PARAM_RTC_CAL_ADDR);
|
||
rtc_sleep_process();
|
||
rtc_printf();
|
||
}
|
||
|
||
bsp_i2c_init();
|
||
/* 心率传感器初始化 */
|
||
bsp_sensor_hr_init();
|
||
bsp_sensor_hr_stop();
|
||
|
||
sys_clk_set(SYS_26M);
|
||
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_text.bsp.key)
|
||
u16 key_process(u16 key_val)
|
||
{
|
||
u16 key_return = NO_KEY;
|
||
const key_shake_tbl_t *s = &key_shake_table;
|
||
|
||
if (key_val == NO_KEY || key_val != key_cb.val) {
|
||
if (key_cb.up < s->up_cnt) {
|
||
key_cb.up++;
|
||
} else {
|
||
if (key_cb.cnt >= s->long_cnt) { //长按抬键
|
||
key_return = key_cb.val | KEY_LONG_UP;
|
||
if (key_cb.val == key_cb.pwr_usage_id || key_cb.val == pwrkey_table[0].usage_id) {
|
||
set_poweron_flag(false);
|
||
}
|
||
} else if (key_cb.cnt >= s->scan_cnt) { //短按抬键
|
||
key_return = key_cb.val | KEY_SHORT_UP;
|
||
}
|
||
key_cb.val = key_val;
|
||
key_cb.cnt = 0;
|
||
key_cb.hcnt = 0;
|
||
}
|
||
} else {
|
||
key_cb.cnt++;
|
||
if (key_cb.cnt == s->scan_cnt) { //去抖
|
||
key_cb.up = 0;
|
||
key_return = key_cb.val;
|
||
} else if (key_cb.cnt == s->long_cnt) { //长按
|
||
key_return = key_cb.val | KEY_LONG;
|
||
key_cb.hcnt = 0;
|
||
} else if (key_cb.cnt == s->hold_cnt) { //连按
|
||
key_return = key_cb.val | KEY_HOLD;
|
||
key_cb.cnt = s->long_cnt;
|
||
if (key_cb.hcnt < PWROFF_PRESS_TIME) {
|
||
key_cb.hcnt++;
|
||
} else if (key_cb.hcnt == PWROFF_PRESS_TIME) {
|
||
if ((key_cb.val == key_cb.pwr_usage_id || key_cb.val == pwrkey_table[0].usage_id) && (!get_poweron_flag())) {
|
||
key_return = key_cb.val | KEY_LHOLD;
|
||
}
|
||
key_cb.hcnt = PWROFF_PRESS_TIME + 10;
|
||
}
|
||
|
||
//if (key_cb.val != key_cb.pwr_usage_id) {
|
||
// RTCCON10 = BIT(10); //clear pwrkey10s pending and counter
|
||
//}
|
||
}
|
||
}
|
||
return key_return;
|
||
}
|
||
|
||
|
||
|
||
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) {
|
||
if((!sys_cb.gui_sleep_sta)&&(tick_check_expire(sys_cb.sleep_exit_tick, 500))){
|
||
// printf(key_str, key);
|
||
my_msg_enqueue(key); //short up 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(0);
|
||
|
||
// }
|
||
// #endif
|
||
|
||
#if VUSB_DETECT_EN
|
||
sys_cb.vusb = bsp_vusb_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 (tick_check_expire(sys_cb.sleep_exit_tick, 500))
|
||
{
|
||
if (sys_cb.gui_sleep_sta) {
|
||
sys_cb.gui_need_wakeup = 1;
|
||
} else {
|
||
my_msg_enqueue(key);
|
||
// printf(key_str, key);
|
||
reset_sleep_delay_all();
|
||
}
|
||
}
|
||
}
|
||
return key_val;
|
||
}
|
||
|