/**
 * \file    main.c
 * \brief   main entry
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-03-05
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-03-05  Original Creation
 * 
 */

#include <stdarg.h>
#include "libc.h"
#include "drivers.h"
#include "xmodem.h"
#include "sys_i2c1.h"
#include "sys_reg.h"
#include "sys_config.h"


/**@name  ISP signal definitions
 * @{ 
 */
#define ISP_SIG_NULL        (0) ///< Null signal
#define ISP_SIG_XMODEM      (1) ///< Xmodem signal
#define ISP_SIG_I2C         (2) ///< I2C signal
#define ISP_SIG_CC          (3) ///< CC message signal
/** @}*/

/* */
#define T_30_SECONDS            30000000UL
#define T_ISP_SIGNAL_CHECKING   2000000UL
volatile timer_t g_isp_signal_check_timer;

u32_t app_addr = APP_ADDR_OFFSET;

u8_t isp_signal_checking()
{
#if SYS_XMODE_UPDATE_EN
    int rcv_cnt = 0;
    u8_t rcv = 0;

    //Init 500 miliseconds timer
    timer_start(T_ISP_SIGNAL_CHECKING, &g_isp_signal_check_timer);
    //sys_start_timer(T_30_SECONDS);

    while (1)   //receive the start of Xmodem
    {
        if (drv_uart_getbyte(&rcv))
        {
            if ((rcv == 'X') || (rcv == 'x'))
            {
                rcv_cnt++;
                if (rcv_cnt > 10)
                {
                    break;
                }
            }
            else
            {
                rcv_cnt = 0;
            }
        }

        if (timer_expired(&g_isp_signal_check_timer)) //timeout
        {
            return ISP_SIG_NULL;
        }
    }
    drv_uart_putstr("\nConfirm upgrade firmware?(Y/N) ");

    //Init 30 seconds timer
    timer_start(T_30_SECONDS, &g_isp_signal_check_timer);

    while (1)
    {
        if (drv_uart_getbyte(&rcv))
        {
            if ((rcv == 'Y') || (rcv == 'y'))
            {
                drv_uart_putstr("Y\n");
                return ISP_SIG_XMODEM;
            }
            else if ((rcv == 'N') || (rcv == 'n'))
            {
                drv_uart_putstr("N\n");
                return ISP_SIG_NULL;
            }
        }
        if (timer_expired(&g_isp_signal_check_timer)) //timeout
        {
            return ISP_SIG_NULL;
        }
    }
#else
    if ((g_f_fw_update_config.sync[0] == SYNC_FW_SYMBOL_0) &&
    (g_f_fw_update_config.sync[1] == SYNC_FW_SYMBOL_1) &&
    (g_f_fw_update_config.sync[2] == SYNC_FW_SYMBOL_2) &&
    (g_f_fw_update_config.sync[3] == SYNC_FW_SYMBOL_3) &&
    (g_f_fw_update_config.sync[4] == SYNC_FW_SYMBOL_4) &&
    (g_f_fw_update_config.sync[5] == SYNC_FW_SYMBOL_5) &&
    (g_f_fw_update_config.sync[6] == SYNC_FW_SYMBOL_6) &&
    (g_f_fw_update_config.sync[7] == SYNC_FW_SYMBOL_7) &&
    (g_f_fw_update_config.fw_update_process == TRUE) &&
    (g_f_fw_update_config.fw_update_fail == FALSE) &&
    (g_f_fw_update_config.fw_update_start == TRUE) &&
    (g_f_fw_update_config.fw_update_code == SYNC_FW_UPDATE_CODE))
    {
        g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_START;
        drv_uart_putstr("\n fw update fail reboot wait update\n");
        while(1)
        {
            if (g_sys_fw_update.mcu_ctrl_fw_cmd == FW_UPDATE_STA_START_INFO)
            {
                g_sys_fw_update.sla_sta.ready = TRUE;
                drv_wdt_init(0, FALSE);
                drv_uart_putstr("upd fw!\n");
                return ISP_SIG_I2C;
            }
        }
    }
    else if ((drv_wdt_reset_flag_get() && 
        (!fw_udate_resv_mem_ptr->fw_app_init))||
        ((fw_udate_resv_mem_ptr->fw_update_flg)&&
        (fw_udate_resv_mem_ptr->fw_update_code == 0xA5)))
    {
        g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_START;
        drv_uart_putstr("check sta info\n");
        timer_start(T_ISP_SIGNAL_CHECKING, &g_isp_signal_check_timer);
        
        while(1)
        {
            if (g_sys_fw_update.mcu_ctrl_fw_cmd == FW_UPDATE_STA_START_INFO)
            {
                g_sys_fw_update.sla_sta.ready = TRUE;
                drv_wdt_init(0, FALSE);
                drv_uart_putstr("upd fw!\n");
                return ISP_SIG_I2C;
            }
            if (timer_expired(&g_isp_signal_check_timer))
            {
                drv_uart_putstr("upfw exit");
                return ISP_SIG_NULL;
            }
        }
    }
    return ISP_SIG_NULL;
#endif
}
#if SYS_XMODE_UPDATE_EN
u8_t xmodem_upgrade()
{
    if (0 < xmodem_rx(APP_ADDR_OFFSET, APP_IMG_SIZE))
    {
        return 1;
    }
    return 0;
}
#endif

/**
 * Main entry
 *
 * \return 0 success, other failure
 */
int main (int argc, char *argv[])
{
    //Restore program address offset to 0
    DRV_REG_SET(PRG_ADDR_OFFSET_REG, 0);

    // If FreeRTOS is enabled, need to set system init flag
    sync_sys_init();
#if 0
    // MCU UPDATE EN ,
    drv_gpio_val_set(DRV_GPIO_17,0);
    drv_gpio_oe_set(DRV_GPIO_17,1);
    drv_gpio_en_set(DRV_GPIO_17,1);
#endif
    //Init interrtupt
    drv_intr_init();

    //Init uart
    drv_uart_init(); 
    
    //en  wdt
    drv_wdt_init(5000, TRUE);
    
    // init fw update info
    fw_update_init();
    
    sys_flash_fw_update_cfg_load();
#if I2C_MODULE_ENABLED
    //Init I2C
    drv_i2c_init();
    
    drv_i2c_master_freq_set(DRV_I2C_ID_0, I2C_FREQ_400K);
    drv_i2c_open(DRV_I2C_ID_0, SLAVE_ADDRESS_0);
    
#if (I2C_MODULE_SLA_ENABLED  && I2C_SLA_CB_ENABLED)
    drv_i2c_master_freq_set(DRV_I2C_ID_1, I2C_FREQ_400K);
    drv_i2c_open(DRV_I2C_ID_1, SLAVE_ADDRESS_1);
    
    drv_i2c_sla_rx_handler_set(DRV_I2C_ID_1, sys_i2c_rx_handler);
    drv_i2c_sla_tx_handler_set(DRV_I2C_ID_1, sys_i2c_tx_handler);
#endif
#endif /* I2C_MODULE_ENABLED */

    sync_sys_init_done();

    if (!drv_chip_wkup_flg())
    {
        switch (isp_signal_checking())
        {
#if SYS_XMODE_UPDATE_EN
            case ISP_SIG_XMODEM:
                DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, FALSE);
                drv_uart_putstr("\nXModem started ...\n");
                if (xmodem_upgrade())
                {
                    rtc_delay_us(1000000UL);
                    drv_uart_putstr("\nOK\n");
                    rtc_delay_us(1000000UL);
                    DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, TRUE);
                }
                else
                {
                    drv_uart_putstr("\nFAIL\n");
                    DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, TRUE);
                    DRV_REG_FIELD_SET(CHIP_REG_0, CHIP_RST, TRUE);
                }
                break;
#endif
            case ISP_SIG_I2C:
                DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, FALSE);
                if (i2c_upgrade())
                {
                    rtc_delay_us(1000000UL);
                    drv_uart_putstr("\nOK\n");
                    rtc_delay_us(1000000UL);
                    DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, TRUE);
                    sys_fw_update_para_erase();
                }
                else
                {
                    drv_uart_putstr("\nFAIL\n");
                    DRV_REG_FIELD_SET(FLASH_CTRL_REG, FLASH_PRG_ENA, TRUE);
                    DRV_REG_FIELD_SET(CHIP_REG_0, CHIP_RST, TRUE);
                    sys_flash_fw_update_cfg_load();

                }
                break;

            case ISP_SIG_CC:
                break;

            default: break;            
        }
    }

#ifdef FLASH_DUMP
    drv_uart_puthex(0,0x40000,TRUE);
    rtc_delay_us(1000000UL);
#endif
    fw_udate_resv_mem_ptr->fw_app_init = 0;
    
    DRV_INTR_GLOBAL_DISABLE();

    if ((g_f_fw_update_config.sync[0] == SYNC_FW_SYMBOL_0) &&
        (g_f_fw_update_config.sync[1] == SYNC_FW_SYMBOL_1) &&
        (g_f_fw_update_config.sync[2] == SYNC_FW_SYMBOL_2) &&
        (g_f_fw_update_config.sync[3] == SYNC_FW_SYMBOL_3) &&
        (g_f_fw_update_config.sync[4] == SYNC_FW_SYMBOL_4) &&
        (g_f_fw_update_config.sync[5] == SYNC_FW_SYMBOL_5) &&
        (g_f_fw_update_config.sync[6] == SYNC_FW_SYMBOL_6) &&
        (g_f_fw_update_config.sync[7] == SYNC_FW_SYMBOL_7) &&
        (g_f_fw_update_config.fw_update_process == TRUE) &&
        (g_f_fw_update_config.fw_update_fail == FALSE) &&
        (g_f_fw_update_config.fw_update_start == TRUE) &&
        (g_f_fw_update_config.fw_update_code == SYNC_FW_UPDATE_CODE))
    {
        DRV_REG_SET(PRG_ADDR_OFFSET_REG, 0);
        drv_uart_putstr("\n reset to bootloadr \n");
    }
    else
    {
        DRV_REG_SET(PRG_ADDR_OFFSET_REG, app_addr);
        drv_uart_putstr("\n reset to app \n");
    }
    
    DRV_REG_FIELD_SET(CHIP_REG_0, CHIP_RST, TRUE);

    return 0;
}
