
/*************************************************************
   此文件函数主要是idle模式按键处理和事件处理

	void app_idle_task()
   idle模式主函数

	static int idle_sys_event_handler(struct sys_event *event)
   idle模式系统事件所有处理入口

	static void idle_task_close(void)
	idle模式退出

	该模式只是作为系统空跑的，可以做家关机，把没有用的模块关闭

**************************************************************/
#include "system/includes.h"
#include "media/includes.h"
#include "app_config.h"
#include "app_task.h"
#include "tone_player.h"
#include "asm/charge.h"
#include "app_charge.h"
#include "app_main.h"
#include "ui_manage.h"
#include "vm.h"
#include "app_chargestore.h"
#include "user_cfg.h"
#include "ui/ui_api.h"
#include "key_event_deal.h"

#define LOG_TAG_CONST       APP_IDLE
#define LOG_TAG             "[APP_IDLE]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"


static int timer_printf_1sec = 0;
static u8 is_idle_flag = 0;
static u8 goto_poweron_cnt = 0;
static u8 goto_poweron_flag = 0;

extern u8 get_power_on_status(void);

static void idle_key_poweron_deal(u8 step);
static void idle_app_open_module();

#define POWER_ON_CNT       10
/// idle 是否关闭不用的模块，减少功耗
#define LOW_POWER_IN_IDLE    0


#if LOW_POWER_IN_IDLE
///*----------------------------------------------------------------------------*/
/**@brief  下面处理是为了关闭不需要用的模块，减少系统功耗
   @param
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
#include "usb/otg.h"
#include "usb/host/usb_host.h"
#include "asm/power/p33.h"
struct timer_hdl {
    u32 ticks;
    int index;
    int prd;
    u32 fine_cnt;
    void *power_ctrl;
    struct list_head head;
};

static struct timer_hdl hdl;
static u8 suspend_flag = 0;

#define __this  (&hdl)

static const u32 timer_div[] = {
    /*0000*/    1,
    /*0001*/    4,
    /*0010*/    16,
    /*0011*/    64,
    /*0100*/    2,
    /*0101*/    8,
    /*0110*/    32,
    /*0111*/    128,
    /*1000*/    256,
    /*1001*/    4 * 256,
    /*1010*/    16 * 256,
    /*1011*/    64 * 256,
    /*1100*/    2 * 256,
    /*1101*/    8 * 256,
    /*1110*/    32 * 256,
    /*1111*/    128 * 256,
};

#define APP_TIMER_CLK           clk_get("timer")
#define MAX_TIME_CNT            0x7fff
#define MIN_TIME_CNT            0x100

#define TIMER_UNIT_MS           2
#define MAX_TIMER_PERIOD_MS     (1000/TIMER_UNIT_MS)

extern void adc_scan(void *priv);
___interrupt
static void idle_timer2_isr()
{
    static u32 cnt = 0;
    JL_TIMER2->CON |= BIT(14);

    ++cnt;
    if ((cnt % 5) == 0) {
    }

    if (cnt == 500) {
        cnt = 0;
    }
    /* adc_scan(NULL); */
}

static int idle_timer2_init()
{
    u32 prd_cnt;
    u8 index;

    for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) {
        prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index];
        if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) {
            break;
        }
    }
    __this->index   = index;
    __this->prd     = prd_cnt;

    JL_TIMER2->CNT = 0;
    JL_TIMER2->PRD = prd_cnt; //2ms
    request_irq(IRQ_TIME2_IDX, 3, idle_timer2_isr, 0);
    JL_TIMER2->CON = (index << 4) | BIT(0) | BIT(3);

    log_info("PRD : 0x%x / %d", JL_TIMER2->PRD, clk_get("timer"));

    return 0;
}

static void idle_timer2_uninit()
{
    JL_TIMER2->CON &= ~(BIT(1) | BIT(0));
}

static void idle_timer1_open()
{
    JL_TIMER1->CON |= BIT(0);
}

static void idle_timer1_close()
{
    JL_TIMER1->CON &= ~(BIT(1) | BIT(0));
}

u32 regs_buf[11] = {0};
void resume_some_peripheral()
{
    u32 *regs_ptr = regs_buf;

    if (!suspend_flag) {
        return;
    }

    clk_set("sys", 24 * 1000000L);

    JL_ANA->DAA_CON0 = *regs_ptr++ ;
    JL_ANA->DAA_CON1 = *regs_ptr++ ;
    JL_ANA->DAA_CON2 = *regs_ptr++ ;
    JL_ANA->DAA_CON3 = *regs_ptr++ ;
    JL_ANA->DAA_CON7 = *regs_ptr++ ;

    JL_ANA->ADA_CON0 = *regs_ptr++ ;
    JL_ANA->ADA_CON1 = *regs_ptr++ ;
    JL_ANA->ADA_CON2 = *regs_ptr++ ;
    JL_ANA->ADA_CON3 = *regs_ptr++ ;
    JL_ANA->ADA_CON4 = *regs_ptr++ ;

    suspend_flag = 0;
}

void suspend_some_peripheral()
{
    u32 *regs_ptr = regs_buf;

    if (suspend_flag) {
        return;
    }

    clk_set("sys", 6 * 1000000L);
    SYSVDD_VOL_SEL(SYSVDD_VOL_SEL_102V);
    VDC13_VOL_SEL(VDC13_VOL_SEL_105V);

    *regs_ptr++ = JL_ANA->DAA_CON0;
    *regs_ptr++ = JL_ANA->DAA_CON1;
    *regs_ptr++ = JL_ANA->DAA_CON2;
    *regs_ptr++ = JL_ANA->DAA_CON3;
    *regs_ptr++ = JL_ANA->DAA_CON7;

    *regs_ptr++ = JL_ANA->ADA_CON0;
    *regs_ptr++ = JL_ANA->ADA_CON1;
    *regs_ptr++ = JL_ANA->ADA_CON2;
    *regs_ptr++ = JL_ANA->ADA_CON3;
    *regs_ptr++ = JL_ANA->ADA_CON4;

    JL_ANA->DAA_CON0 = 0;
    JL_ANA->DAA_CON1 = 0;
    JL_ANA->DAA_CON2 = 0;
    JL_ANA->DAA_CON3 = 0;
    JL_ANA->DAA_CON7 = 0;

    JL_ANA->ADA_CON0 = 0;
    JL_ANA->ADA_CON1 = 0;
    JL_ANA->ADA_CON2 = 0;
    JL_ANA->ADA_CON3 = 0;
    JL_ANA->ADA_CON4 = 0;

    suspend_flag = 1;
}

static u8 is_idle_query(void)
{
    return is_idle_flag;
}
#if 0
REGISTER_LP_TARGET(idle_lp_target) = {
    .name = "not_idle",
    .is_idle = is_idle_query,
};
#endif

#endif

static void idle_key_poweron_deal(u8 step)
{
    switch (step) {
    case 0:
        goto_poweron_cnt = 0;
        goto_poweron_flag = 1;
        break;
    case 1:
        log_info("poweron flag:%d cnt:%d\n", goto_poweron_flag, goto_poweron_cnt);
        if (goto_poweron_flag) {
            goto_poweron_cnt++;
            if (goto_poweron_cnt >= POWER_ON_CNT) {
                goto_poweron_cnt = 0;
                goto_poweron_flag = 0;
                app_var.goto_poweroff_flag = 0;
#if LOW_POWER_IN_IDLE
                idle_app_open_module();
#endif

#if TWFG_APP_POWERON_IGNORE_DEV
                app_task_switch_to(APP_POWERON_TASK);
#endif
            }
        }
        break;
    }
}

#if (TWFG_APP_POWERON_IGNORE_DEV == 0)
static u16 ignore_dev_timeout = 0;
static void poweron_task_switch_to_bt(void *priv) //超时还没有设备挂载，则切到蓝牙模式
{
    app_task_switch_to(APP_BT_TASK);
}
#endif

//*----------------------------------------------------------------------------*/
/**@brief    idle 按键消息入口
   @param    无
   @return   1、消息已经处理，不需要发送到common  0、消息发送到common处理
   @note
*/
/*----------------------------------------------------------------------------*/
static int idle_key_event_opr(struct sys_event *event)
{
    int ret = true;
    int key_event = event->u.key.event;
    int key_value = event->u.key.value;

    log_info("key_event:%d \n", key_event);

    switch (key_event) {
    case KEY_POWER_ON:
    case KEY_POWER_ON_HOLD:
        idle_key_poweron_deal(key_event - KEY_POWER_ON);
        break;
    }
    return ret;
}

//*----------------------------------------------------------------------------*/
/**@brief    idle 模式活跃状态 所有消息入口
   @param    无
   @return   1、当前消息已经处理，不需要发送comomon 0、当前消息不是idle处理的，发送到common统一处理
   @note
*/
/*----------------------------------------------------------------------------*/
extern int app_common_otg_devcie_event(struct sys_event *event);
static int idle_sys_event_handler(struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        return idle_key_event_opr(event);

    case SYS_BT_EVENT:
        /* return 0; */
        return true;
    case SYS_DEVICE_EVENT:
#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE
        if ((u32)event->arg == DEVICE_EVENT_CHARGE_STORE) {
            app_chargestore_event_handler(&event->u.chargestore);
        }
#endif
        return 0;
    default:
        return true;
    }
}

//*----------------------------------------------------------------------------*/
/**@brief    idle 退出
   @param    无
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
static void idle_task_close()
{
}

//*----------------------------------------------------------------------------*/
/**@brief    idle 重新打开需要的模块
   @param    无
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
static void idle_app_open_module()
{
#if LOW_POWER_IN_IDLE
    is_idle_flag = 0;
#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0)
    resume_some_peripheral();
#endif

#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE)
    extern void sdx_dev_detect_timer_add();
    sdx_dev_detect_timer_add();
#endif

#if (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)
    extern void usb_detect_timer_add();
    usb_detect_timer_add();
#endif

#if TCFG_LINEIN_ENABLE
    extern void linein_detect_timer_add();
    linein_detect_timer_add();
#endif
    if (timer_printf_1sec) {
        sys_timer_del(timer_printf_1sec);
    }
#endif //LOW_POWER_IN_IDLE
}

//*----------------------------------------------------------------------------*/
/**@brief    idle 关闭不需要的模块
   @param    无
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
static void idle_app_close_module()
{
#if LOW_POWER_IN_IDLE
    int ret = false;
    is_idle_flag = 1;

#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE)
    extern void sdx_dev_detect_timer_del();
    sdx_dev_detect_timer_del();
#endif

#if (((TCFG_PC_ENABLE) && (!TCFG_USB_PORT_CHARGE)) || ((TCFG_UDISK_ENABLE) && (!TCFG_PC_ENABLE)))
    extern void usb_detect_timer_del();
    extern u32 usb_otg_online(const usb_dev usb_id);
    extern int usb_mount_offline(usb_dev usb_id);
    extern void usb_pause();
    extern int dev_manager_del(char *logo);
    usb_detect_timer_del();
    os_time_dly((TCFG_OTG_DET_INTERVAL + 9) / 10);
    if (usb_otg_online(0) == HOST_MODE) {
#if TCFG_UDISK_ENABLE
        dev_manager_del("udisk0");
        usb_host_unmount(0);
        usb_h_sie_close(0);

        /*
         经过测试发现，有相当一部分在DP/DM设成高阻状态下U盘的电流仍维持在
         20 ~ 30mA，需要把DP设成上拉，DM设成下拉，这些U盘的电流才能降到2mA
         以下。即有部分U盘需要主机维持在空闲时J状态才能进入suspend。
         */
        usb_iomode(1);
        gpio_set_die(IO_PORT_DP, 1);
        gpio_set_pull_up(IO_PORT_DP, 1);
        gpio_set_pull_down(IO_PORT_DP, 0);
        gpio_set_direction(IO_PORT_DP, 1);

        gpio_set_die(IO_PORT_DM, 1);
        gpio_set_pull_up(IO_PORT_DM, 0);
        gpio_set_pull_down(IO_PORT_DM, 1);
        gpio_set_direction(IO_PORT_DM, 1);

        usb_mount_offline(0);
#endif
    } else if (usb_otg_online(0) == SLAVE_MODE) {
#if TCFG_PC_ENABLE
        usb_pause();

        usb_iomode(1);
        gpio_set_die(IO_PORT_DP, 0);
        gpio_set_pull_up(IO_PORT_DP, 0);
        gpio_set_pull_down(IO_PORT_DP, 0);
        gpio_set_direction(IO_PORT_DP, 1);

        gpio_set_die(IO_PORT_DM, 0);
        gpio_set_pull_up(IO_PORT_DM, 0);
        gpio_set_pull_down(IO_PORT_DM, 0);
        gpio_set_direction(IO_PORT_DM, 1);
#endif
    }
#endif

#if TCFG_LINEIN_ENABLE
    extern void linein_detect_timer_del();
    linein_detect_timer_del();
#endif

#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0)
    suspend_some_peripheral();
#endif
#endif
}
//*----------------------------------------------------------------------------*/
/**@brief    idle 启动
   @param    无
   @return
   @note     关闭SD卡 、 usb 、假关机还是软关机
*/
/*----------------------------------------------------------------------------*/
static void idle_app_start()
{
#if LOW_POWER_IN_IDLE
    idle_app_close_module();
#endif

#if (TCFG_CHARGE_ENABLE && !TCFG_CHARGE_POWERON_ENABLE)

#else
    sys_key_event_enable();
#endif
}


//*----------------------------------------------------------------------------*/
/**@brief    idle 主任务
  @param    无
  @return   无
  @note
 */
/*----------------------------------------------------------------------------*/
void app_idle_task()
{
    int res;
    int msg[32];

    idle_app_start();

    while (1) {
        app_task_get_msg(msg, ARRAY_SIZE(msg), 1);

        switch (msg[0]) {
        case APP_MSG_SYS_EVENT:
            if (idle_sys_event_handler((struct sys_event *)(&msg[1])) == false) {
                app_default_event_deal((struct sys_event *)(&msg[1]));    //由common统一处理
            }
            break;
        default:
            break;
        }

        if (app_task_exitting()) {
            idle_task_close();
            return;
        }
    }
}

