521 lines
15 KiB
C
521 lines
15 KiB
C
#include "include.h"
|
||
#include "func.h"
|
||
|
||
bool power_off_check(void);
|
||
void lock_code_pwrsave(void);
|
||
void unlock_code_pwrsave(void);
|
||
|
||
AT(.com_text.sleep)
|
||
void lowpwr_tout_ticks(void)
|
||
{
|
||
if(sys_cb.sleep_delay != -1L && sys_cb.sleep_delay > 0) {
|
||
sys_cb.sleep_delay--;
|
||
}
|
||
if(sys_cb.guioff_delay != -1L && sys_cb.guioff_delay > 0) {
|
||
sys_cb.guioff_delay--;
|
||
}
|
||
if(sys_cb.pwroff_delay != -1L && sys_cb.pwroff_delay > 0) {
|
||
sys_cb.pwroff_delay--;
|
||
}
|
||
}
|
||
|
||
AT(.com_text.sleep)
|
||
bool sys_sleep_check(u32 *sleep_time)
|
||
{
|
||
#if SYS_COTIME_EN
|
||
u32 co_min = sys_co_timer_get_min_time(true)*2;
|
||
|
||
if(*sleep_time > co_min) {
|
||
*sleep_time = co_min;
|
||
}
|
||
|
||
if(*sleep_time == 0){
|
||
*sleep_time = 1;
|
||
}
|
||
#endif
|
||
|
||
if(*sleep_time > sys_cb.sleep_wakeup_time) {
|
||
*sleep_time = sys_cb.sleep_wakeup_time;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
AT(.sleep_text.sleep)
|
||
void sys_sleep_cb(u8 lpclk_type)
|
||
{
|
||
//注意!!!!!!!!!!!!!!!!!
|
||
//此函数只能调用sleep_text或com_text函数
|
||
|
||
//此处关掉影响功耗的模块
|
||
u32 gpiogde = GPIOGDE;
|
||
GPIOGDE = BIT(2) | BIT(4); //SPICS, SPICLK
|
||
|
||
sys_enter_sleep(lpclk_type); //enter sleep
|
||
|
||
//唤醒后,恢复模块功能
|
||
GPIOGDE = gpiogde;
|
||
}
|
||
|
||
//休眠定时器,500ms进一次
|
||
AT(.sleep_text.sleep)
|
||
uint32_t sleep_timer(void)
|
||
{
|
||
uint32_t ret = 0;
|
||
|
||
sys_cb.sleep_counter++;
|
||
if (sys_cb.sleep_counter == 10) {
|
||
sys_cb.sleep_counter = 0;
|
||
#if LPWR_WARNING_VBAT
|
||
saradc_init();
|
||
saradc_adc15_analog_select(ADCCH15_ANA_VRTC);
|
||
saradc_kick_start(0, 0);
|
||
while(!bsp_saradc_process(0));
|
||
if (sys_cb.vbat < LPWR_WARNING_VBAT) {
|
||
//低电需要唤醒sniff mode
|
||
ret = 2;
|
||
}
|
||
saradc_exit();
|
||
#endif
|
||
}
|
||
|
||
#if CHARGE_EN
|
||
if (xcfg_cb.charge_en) {
|
||
charge_detect(0);
|
||
}
|
||
#endif // CHARGE_EN
|
||
|
||
sys_cb.sleep_wakeup_time = -1L;
|
||
|
||
if(sys_cb.pwroff_delay != -1L) {
|
||
if(sys_cb.pwroff_delay > 5) {
|
||
sys_cb.pwroff_delay -= 5;
|
||
} else {
|
||
sys_cb.pwroff_delay = 0;
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
if ((PWRKEY_2_HW_PWRON) && (!IS_PWRKEY_PRESS())){
|
||
ret = 1;
|
||
}
|
||
|
||
rtc_sleep_process();
|
||
|
||
return ret;
|
||
}
|
||
|
||
AT(.text.lowpwr.sleep)
|
||
static void sfunc_sleep(void)
|
||
{
|
||
uint32_t status, ret;
|
||
uint32_t usbcon0, usbcon1;
|
||
u8 pa_de, pb_de, pe_de, pf_de, pg_de;
|
||
u16 adc_ch;
|
||
uint32_t sysclk;
|
||
u32 wkie, wkpnd;
|
||
#if LE_EN
|
||
u16 interval = 0;
|
||
u16 latency = 0;
|
||
u16 tout = 0;
|
||
u16 adv_interval = 0;
|
||
#endif
|
||
|
||
if (sys_co_timer_is_plan()) {
|
||
return;
|
||
}
|
||
|
||
#if VBAT_DETECT_EN
|
||
if (bsp_vbat_get_lpwr_status()) { //低电不进sniff mode
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
printf("%s\n", __func__);
|
||
|
||
bt_enter_sleep();
|
||
#if LE_EN
|
||
adv_interval = ble_get_adv_interval();
|
||
ble_set_adv_interval(800); //interval: 500 * 0.625ms = 500ms
|
||
if (ble_is_connect()) { //ble已连接
|
||
interval = ble_get_conn_interval();
|
||
latency = ble_get_conn_latency();
|
||
tout = ble_get_conn_timeout();
|
||
ble_update_conn_param(400, 0, 500); //interval: 400*1.25ms = 500ms
|
||
}
|
||
#endif
|
||
#if BT_SINGLE_SLEEP_LPW_EN
|
||
if (!bt_is_connected()){ //蓝牙未连接
|
||
if (bt_get_scan()) { //双模休眠
|
||
bt_set_scan_param(0x0a20); //pscan int = 0x2100 , iscan int = 0xb00;
|
||
} else {
|
||
bt_set_scan_param(0xc0c0);
|
||
bt_scan_disable();
|
||
}
|
||
}
|
||
#else
|
||
if (!bt_is_connected()){ //蓝牙未连接
|
||
bt_set_scan_param(0x0a20); //pscan int = 0x2100 , iscan int = 0xb00;
|
||
}
|
||
#endif
|
||
|
||
#if DAC_DNR_EN
|
||
u8 sta = dac_dnr_get_sta();
|
||
dac_dnr_set_sta(0);
|
||
#endif
|
||
dac_power_off(); //dac power down
|
||
|
||
sys_set_tmr_enable(0, 0);
|
||
|
||
adc_ch = bsp_saradc_exit(); //close saradc及相关通路模拟
|
||
saradc_clr_channel(adc_ch);
|
||
saradc_set_channel(BIT(ADCCH_VBAT) | BIT(ADCCH_BGOP));
|
||
|
||
#if CHARGE_EN
|
||
bsp_charge_set_stop_time(3600);
|
||
#endif
|
||
|
||
#if MUSIC_UDISK_EN
|
||
if (dev_is_online(DEV_UDISK)) {
|
||
udisk_insert(); //udisk需要重新enum
|
||
}
|
||
#endif
|
||
|
||
usbcon0 = USBCON0; //需要先关中断再保存
|
||
usbcon1 = USBCON1;
|
||
USBCON0 = BIT(5);
|
||
USBCON1 = 0;
|
||
#if GUI_EN
|
||
gui_sleep();
|
||
#endif
|
||
sysclk = sys_clk_get();
|
||
sys_clk_set(SYS_26M);
|
||
DACDIGCON0 &= ~BIT(0); //disable digital dac
|
||
adda_clk_source_sel(0); //adda_clk48_a select xosc52m
|
||
PLL0CON &= ~(BIT(18) | BIT(6)); //pll0 sdm & analog disable
|
||
rtc_sleep_enter();
|
||
|
||
//io analog input
|
||
pa_de = GPIOADE;
|
||
pb_de = GPIOBDE;
|
||
pe_de = GPIOEDE;
|
||
pf_de = GPIOFDE;
|
||
pg_de = GPIOGDE;
|
||
GPIOADE = 0;
|
||
GPIOBDE = 0;
|
||
GPIOGDE = 0x3F; //MCP FLASH
|
||
|
||
#if SENSOR_EN
|
||
if (bsp_sensor_init_sta_get()) {
|
||
GPIOEDE = 0 | BIT(2) | BIT(1); //SENSOR I2C
|
||
GPIOFDE = 0 | BIT(2); //SENSOR PG
|
||
} else {
|
||
GPIOEDE = 0;
|
||
GPIOFDE = 0;
|
||
}
|
||
#endif
|
||
|
||
wkie = WKUPCON & BIT(16);
|
||
WKUPCON &= ~BIT(16); //休眠时关掉WKIE
|
||
sleep_wakeup_config();
|
||
|
||
sys_cb.sleep_counter = 0;
|
||
sys_cb.sleep_wakeup_time = -1L;
|
||
while(bt_is_sleep()) {
|
||
WDT_CLR();
|
||
status = bt_sleep_proc();
|
||
|
||
if(status == 1) {
|
||
ret = sleep_timer();
|
||
if(ret) {
|
||
if (ret == 1) {
|
||
func_cb.sta = FUNC_PWROFF;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
wkpnd = port_wakeup_get_status();
|
||
|
||
bsp_sensor_step_lowpwr_pro(&wkpnd);
|
||
|
||
if (wkpnd) {
|
||
printf("port wakeup: %x\n", wkpnd);
|
||
break;
|
||
}
|
||
if ((RTCCON9 & BIT(2)) || (RTCCON10 & BIT(2))) {
|
||
printf("wko wakeup\n");
|
||
break;
|
||
}
|
||
#if LE_EN
|
||
if (ble_app_need_wakeup()) {
|
||
break;
|
||
}
|
||
#endif
|
||
|
||
if (sys_co_timer_pro(true)) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
RTCCON9 = BIT(7) | BIT(5) | BIT(2); //clr port, bt, wko wakeup pending
|
||
RTCCON3 &= ~(BIT(17) | BIT(13)); //disable port, bt wakeup
|
||
sleep_wakeup_exit();
|
||
WKUPCON |= wkie; //还原WKIE
|
||
|
||
GPIOADE = pa_de;
|
||
GPIOBDE = pb_de;
|
||
GPIOEDE = pe_de;
|
||
GPIOFDE = pf_de;
|
||
GPIOGDE = pg_de;
|
||
USBCON0 = usbcon0;
|
||
USBCON1 = usbcon1;
|
||
|
||
bt_set_scan_param(0x0303); //pscan int = 0x400 , iscan int = 0x400;
|
||
#if BT_SINGLE_SLEEP_LPW_EN
|
||
if(!bt_is_connected() && bt_get_scan()){ //单模
|
||
bt_scan_enable();
|
||
}
|
||
#endif
|
||
rtc_sleep_exit();
|
||
CLKCON0 = (CLKCON0 & ~(0x03 << 2)) | (0x01 << 2); //sysclk select xosc26m_clk
|
||
RSTCON0 &= ~BIT(4); //pllsdm disable
|
||
adpll_init(DAC_OUT_SPR); //enable adpll
|
||
adda_clk_source_sel(1); //adda_clk48_a select pll0
|
||
sys_clk_set(sysclk);
|
||
saradc_set_channel(adc_ch);
|
||
bsp_saradc_init();
|
||
#if CHARGE_EN
|
||
bsp_charge_set_stop_time(18000);
|
||
bsp_charge_sta(sys_cb.charge_sta); //update充灯状态
|
||
#endif // CHARGE_EN
|
||
sys_set_tmr_enable(1, 1);
|
||
if (DAC_FAST_SETUP_EN) {
|
||
bsp_loudspeaker_mute();
|
||
}
|
||
#if GUI_EN
|
||
gui_wakeup();
|
||
#endif
|
||
#if LE_EN
|
||
ble_set_adv_interval(adv_interval);
|
||
if (interval | latency | tout) {
|
||
ble_update_conn_param(interval, latency, tout); //还原连接参数
|
||
}
|
||
#endif
|
||
dac_restart();
|
||
bsp_change_volume(sys_cb.vol);
|
||
#if DAC_DNR_EN
|
||
dac_dnr_set_sta(sta);
|
||
#endif
|
||
bt_exit_sleep();
|
||
printf("sleep_exit\n");
|
||
}
|
||
|
||
AT(.text.lowpwr.sleep)
|
||
bool sleep_process(is_sleep_func is_sleep)
|
||
{
|
||
if (sys_cb.gui_need_wakeup && sys_cb.gui_sleep_sta) {
|
||
#if GUI_EN
|
||
gui_wakeup(); //按键亮屏
|
||
#endif
|
||
reset_sleep_delay_all();
|
||
sys_cb.gui_need_wakeup = 0;
|
||
return false;
|
||
}
|
||
|
||
#if LE_EN
|
||
if (ble_app_need_wakeup()) {
|
||
reset_sleep_delay_all();
|
||
reset_pwroff_delay();
|
||
return false;
|
||
}
|
||
#endif
|
||
if ((*is_sleep)()) {
|
||
if (!sys_cb.sleep_en) {
|
||
reset_sleep_delay_all();
|
||
return false;
|
||
}
|
||
if (sys_cb.sleep_delay == 0) {
|
||
sfunc_sleep(); //熄屏且进入休眠
|
||
reset_sleep_delay_all();
|
||
reset_pwroff_delay();
|
||
return true;
|
||
}
|
||
} else {
|
||
#if GUI_EN
|
||
if (sys_cb.guioff_delay == 0 && !sys_cb.gui_sleep_sta) {
|
||
gui_sleep(); //仅熄屏
|
||
}
|
||
#endif
|
||
reset_sleep_delay();
|
||
reset_pwroff_delay();
|
||
}
|
||
return false;
|
||
}
|
||
|
||
////红外关机进入sleep mode
|
||
//AT(.text.lowpwr.sleep)
|
||
//void func_sleepmode(void)
|
||
//{
|
||
//
|
||
//}
|
||
|
||
///解决充满关机等待5V掉电,超时1分钟
|
||
AT(.text.pwroff.vusb)
|
||
u8 sfunc_pwrdown_w4_vusb_offline(void)
|
||
{
|
||
// u32 timeout = 10000, off_cnt = 0;
|
||
// while (timeout--) {
|
||
// WDT_CLR();
|
||
// delay_us(330); //5ms
|
||
// if (!CHARGE_DC_IN()) {
|
||
// off_cnt++;
|
||
// } else {
|
||
// off_cnt = 0;
|
||
// }
|
||
// if (off_cnt > 5) {
|
||
// return 1; //VUSB已掉线,打开VUSB唤醒
|
||
// }
|
||
// }
|
||
return 0; //关VUSB唤醒
|
||
}
|
||
|
||
AT(.text.pwroff.enter)
|
||
void sfunc_power_save_enter(void)
|
||
{
|
||
sys_clk_set(SYS_26M);
|
||
LOUDSPEAKER_MUTE_DIS();
|
||
WDT_CLR();
|
||
#if CHARGE_EN
|
||
if (xcfg_cb.charge_en) {
|
||
bsp_charge_off();
|
||
}
|
||
#endif
|
||
set_buck_mode(0); //关机前切回ldo mode
|
||
vusb_delay_rst_dis();
|
||
RTCCON4 = (RTCCON4 & ~(3 << 5)) | (1 << 5); //RI_VCORE_SVBT = 0, RI_VCORE_SVIO = 1
|
||
USBCON0 = BIT(5);
|
||
USBCON1 = 0;
|
||
GPIOADE = 0;
|
||
GPIOBDE = 0;
|
||
GPIOEDE = 0;
|
||
GPIOFDE = 0;
|
||
GPIOGDE = 0x3F; //MCP FLASH
|
||
RTCCON8 &= ~BIT(15); //RI_EN_VUSBDIV = 0
|
||
RTCCON0 = (RTCCON0 & ~(3 << 8)) | (1 << 8); //CLK32K_RTC Select RC2M_RTC
|
||
|
||
PICCONCLR = BIT(0); //Globle IE disable
|
||
CLKCON0 |= BIT(0); //enable RC
|
||
CLKCON0 = (CLKCON0 & ~(0x3 << 2)); //system clk select RC
|
||
|
||
RSTCON0 &= ~(BIT(4) | BIT(6)); //pllsdm, adda_clk
|
||
CLKGAT0 &= ~(BIT(12) | BIT(14)); //disable dac clk
|
||
PLL0CON &= ~(BIT(6) | BIT(18)); //PLL0 disable
|
||
XO26MCON &= ~((0xf<<24) | BIT(10) | BIT(5));//X26 output, xosc, xosc52m disable
|
||
PLL0CON &= ~(BIT(12) | BIT(0) | BIT(1)); //PLL0 & XOSC关电
|
||
RTCCON9 = 0xfff; //Clr pending
|
||
}
|
||
|
||
//硬开关方案,低电时,进入省电状态
|
||
AT(.text.pwroff)
|
||
void sfunc_lowbat_do(void)
|
||
{
|
||
sfunc_power_save_enter();
|
||
WDT_DIS();
|
||
RTCCON3 |= BIT(11); //VUSB Wakeup enable
|
||
while(1) {
|
||
LPMCON |= BIT(0); //Sleep mode enable
|
||
asm("nop");asm("nop");asm("nop");
|
||
if (RTCCON10 & BIT(3)) { //VUSB wake up pending
|
||
WDT_RST();
|
||
}
|
||
}
|
||
}
|
||
|
||
//软开关方案,POWER键/低电时,进入关机状态
|
||
AT(.text.pwroff.pwrdwn)
|
||
void sfunc_pwrdown_do(u8 vusb_wakeup_en)
|
||
{
|
||
sfunc_power_save_enter();
|
||
if (!vusb_wakeup_en) {
|
||
RTCCON8 = (RTCCON8 & ~BIT(6)) | BIT(1); //disable charger function
|
||
vusb_wakeup_en = sfunc_pwrdown_w4_vusb_offline();
|
||
}
|
||
RTCCON1 &= ~(BIT(5) | BIT(7)); //BIT(7): VRTC voltage for ADC, BIT(5):WK pin analog enable, output WKO voltage for ADC
|
||
RTCCON11 = (RTCCON11 & ~0x03) | BIT(2); //WK PIN filter select 8ms
|
||
RTCCON0 &= ~(BIT(0) | BIT(18) | BIT(2)); //RI_EN_SNIFF = 0, RI_EN_RINGOSC = 0
|
||
|
||
uint rtccon3 = RTCCON3 & ~BIT(11);
|
||
uint rtccon1 = RTCCON1 & ~0x1f;
|
||
#if CHARGE_EN
|
||
if ((xcfg_cb.charge_en) && (vusb_wakeup_en)) {
|
||
rtccon3 |= BIT(11); //VUSB wakeup enable
|
||
}
|
||
#endif
|
||
RTCCON3 = rtccon3 & ~BIT(10); //关WK PIN,再打开,以清除Pending
|
||
rtccon3 = RTCCON3 & ~0x87; //Disable VDDCORE VDDIO VDDBUCK VDDIO_AON
|
||
rtccon3 &= ~BIT(22); //RI_EN_VLCORE = 0,
|
||
rtccon3 &= ~(3 << 20); //RL2VDD12 = 0, C2VDD12 = 0
|
||
rtccon3 |= BIT(6) | BIT(4) | BIT(19); //PDCORE, PDCORE2, PDCORE3
|
||
rtccon3 |= BIT(10); //WK pin wake up enable
|
||
// rtccon3 |= BIT(16); //RTC_WDT wake ep enable
|
||
rtccon1 |= BIT(0) | BIT(2) | BIT(4); //WK 90K pull up enable
|
||
WDT_DIS();
|
||
RTCCON12 |= (0x3<<6); //DIS RTC_WDT
|
||
RTCCON |= BIT(5); //PowerDown Reset,如果有Pending,则马上Reset
|
||
RTCCON1 = rtccon1;
|
||
RTCCON3 = rtccon3;
|
||
LPMCON |= BIT(0);
|
||
asm("nop");asm("nop");asm("nop");
|
||
while (1);
|
||
}
|
||
|
||
void sfunc_pwrdown(u8 vusb_wakeup_en)
|
||
{
|
||
lock_code_pwrsave();
|
||
sfunc_pwrdown_do(vusb_wakeup_en);
|
||
}
|
||
|
||
void sfunc_lowbat(void)
|
||
{
|
||
lock_code_pwrsave();
|
||
sfunc_lowbat_do();
|
||
}
|
||
|
||
AT(.text.lowpwr.pwroff)
|
||
void func_pwroff(int pwroff_tone_en)
|
||
{
|
||
printf("%s\n", __func__);
|
||
#if WARNING_POWER_OFF
|
||
if (SOFT_POWER_ON_OFF) {
|
||
mp3_res_play(RES_BUF_POWEROFF_MP3, RES_LEN_POWEROFF_MP3);
|
||
}
|
||
#endif // WARNING_POWER_OFF
|
||
|
||
// gui_off();
|
||
|
||
if (SOFT_POWER_ON_OFF) {
|
||
if (!PWRKEY_2_HW_PWRON) {
|
||
while (IS_PWRKEY_PRESS()) { //等待PWRKWY松开
|
||
delay_5ms(1);
|
||
WDT_CLR();
|
||
}
|
||
}
|
||
// dac_power_off(); //dac power down
|
||
if (CHARGE_DC_IN()) {
|
||
if (power_off_check()) { //充电过程中等待结束再关机
|
||
return;
|
||
}
|
||
}
|
||
bsp_saradc_exit(); //close saradc及相关通路模拟
|
||
if ((PWRKEY_2_HW_PWRON) && (sys_cb.poweron_flag)) {
|
||
RTCCON1 |= BIT(6); //WK PIN High level wakeup
|
||
}
|
||
sfunc_pwrdown(1);
|
||
} else {
|
||
dac_power_off(); //dac power down
|
||
bsp_saradc_exit(); //close saradc及相关通路模拟
|
||
|
||
sfunc_lowbat(); //低电关机进入Sleep Mode
|
||
}
|
||
}
|