/**
 * \file    sys_i2c.c
 * \brief   I2C slave process engine
 *
 * \par     Copyright (c) 2016 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2016-05-19
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2016-05-19  Original Creation
 * 
 */

#include "libc.h"
#include "drivers.h"
#include "sys_i2c1.h"
#include "sys_config.h"
#include "crc16.h"

#define FW_DOWNLOAD_I2C_ID        1

#if (I2C_MODULE_ENABLED && I2C_MODULE_SLA_ENABLED  && !(I2C_SLA_CB_ENABLED))

void sys_i2c_handler(DRV_I2C_ID_t i2c_id)
{
    u8_t rx_len = g_i2c_info[i2c_id].rx_data_index;
    g_i2c_info[i2c_id].tx_data_index = 0;
    for (int i = 0; i < rx_len; i++)
    {
        g_i2c_info[i2c_id].tx_data[i] = g_i2c_info[i2c_id].rx_data[i];
    }
    g_i2c_info[i2c_id].tx_data_len = rx_len;
    g_i2c_info[i2c_id].rx_data_index = 0;
    //clear I2C interrupt
    drv_i2c_clear_si(i2c_id);
    //enable I2C interrupt
    drv_i2c_interrupt_enable(i2c_id);
    if (sys_cfg_dbg_get())
    {
        drv_uart_puts("I2C ACK");
    }
    rtc_delay_us(1000);
#if CLI_ENABLED
    if (sys_cfg_dbg_get() > SYS_DEBUG_LEVEL_2)
    {
        if (rx_len)
        {
            drv_uart_puts("I2C RX:");
            drv_uart_puthex(&(g_i2c_info[i2c_id].rx_data[0]), rx_len, FALSE);
        }
        if (g_i2c_info[i2c_id].tx_data_len)
        {
            drv_uart_puts("I2C TX:");
            drv_uart_puthex(&(g_i2c_info[i2c_id].tx_data[0]), g_i2c_info[i2c_id].tx_data_len, FALSE);
        }
    }
#endif /* CLI_ENABLED */
}

#elif (I2C_MODULE_ENABLED && I2C_MODULE_SLA_ENABLED  && I2C_SLA_CB_ENABLED)
#if 0
volatile u8_t i2c_sla_rx_len = 0;
volatile u8_t i2c_sla_rx_data[I2C_BUFFER_SIZE];
void sys_i2c_rx_handler(DRV_I2C_ID_t i2c_id, u8_t* received_data, u8_t received_len)
{
    i2c_sla_rx_len = received_len;
    for (int i = 0; ((i < received_len) && (i < I2C_BUFFER_SIZE)); i++)
    {
        i2c_sla_rx_data[i] = received_data[i];
    }
    drv_i2c_sla_cleanup(i2c_id);
#if CLI_ENABLED
    if (sys_cfg_dbg_get() > SYS_DEBUG_LEVEL_2)
    {
        if (received_len)
        {
            drv_uart_puts("I2C RX:");
            drv_uart_puthex(received_data, received_len, FALSE);
        }
    }
#endif /* CLI_ENABLED */
}

u8_t sys_i2c_tx_handler(DRV_I2C_ID_t i2c_id, u8_t tx_data_len_max, u8_t* transmit_data)
{
    u8_t i;
    for (i = 0; ((i < i2c_sla_rx_len) && (i < tx_data_len_max)); i++)
    {
        transmit_data[i] = i2c_sla_rx_data[i];
    }
#if CLI_ENABLED
    if (sys_cfg_dbg_get() > SYS_DEBUG_LEVEL_2)
    {
        drv_uart_puts("I2C TX:");
        drv_uart_puthex(transmit_data, i, FALSE);
    }
#endif /* CLI_ENABLED */
    return i;
}
#else
#if 0
void sys_i2c_handler(DRV_I2C_ID_t i2c_id)
{
    u8_t rx_len = g_i2c_info[i2c_id].rx_data_index;
    u8_t reg = g_i2c_info[i2c_id].rx_data[0];
    g_i2c_info[i2c_id].tx_data_len = 0;
    g_i2c_info[i2c_id].rx_data_index = 0;
    
    if (rx_len > 1)
    {
        //sys_reg_write(reg,&g_i2c_info[i2c_id].rx_data[1]);

    }
    else if(rx_len > 0)
    {
        //g_i2c_info[i2c_id].tx_data_len = sys_reg_read(reg, &g_i2c_info[i2c_id].tx_data[0]);
    }
    else 
    {


    }

    g_i2c_info[i2c_id].rx_data_index = 0;
    //clear I2C interrupt
    drv_i2c_clear_si(i2c_id);
    //enable I2C interrupt
    drv_i2c_interrupt_enable(i2c_id);
}
#endif

void sys_i2c_rx_handler(DRV_I2C_ID_t i2c_id, u8_t* received_data, u8_t received_len)
{
    u8_t rx_len = received_len;
    u8_t reg = (u8_t)received_data[0];
    if (rx_len > 1)
    {
        switch(reg)
        {
            case SYS_FW_UPDATE_CMD_REG:
                g_sys_fw_update.mcu_ctrl_fw_cmd = received_data[1]&0x07;
                break;
            case SYS_FW_INFO_REG:
                g_sys_fw_update.crc = SAL_2BYTES_U16(received_data[2],received_data[1]);
                g_sys_fw_update.lenth = SAL_4BYTES_U32(received_data[3],received_data[4],received_data[5],0);
                g_sys_fw_update.rx_fw_info_flg = TRUE;
                break;
            case SYS_FW_DATA_REG:
                g_sys_fw_update.rx_fw_data_flg = TRUE;
                g_sys_fw_update.s_rx_fw_data_lenth = received_len - 1;
                break;
            default:
                break;
        }

    }
    else if( rx_len > 0)
    {
        g_sys_fw_update.i2c_slave_tx_start_flg = TRUE;
        g_sys_fw_update.i2c_sla_tx_reg = reg;
    }
    else
    {
        // err

    }
}
u8_t sys_i2c_tx_handler(DRV_I2C_ID_t i2c_id, u8_t tx_data_len_max, u8_t* transmit_data)
{
    u8_t len = 0;
    
    if (g_sys_fw_update.i2c_slave_tx_start_flg)
    {
        g_sys_fw_update.i2c_slave_tx_start_flg = FALSE;
        
        switch(g_sys_fw_update.i2c_sla_tx_reg)
        {
            case SYS_FW_UPDATE_CMD_REG:
                transmit_data[0] = (u8_t)(g_sys_fw_update.mcu_ctrl_fw_cmd & 0xff);
                len = 1;
                break;
            case SYS_FW_UPDATE_STA_REG:
                transmit_data[0] = *(u8_t*)&g_sys_fw_update.sla_sta;
                len = 1;
                break;
            case SYS_FW_INFO_REG:
                transmit_data[0] = SAL_U16_BYTE0(g_sys_fw_update.crc);
                transmit_data[1] = SAL_U16_BYTE1(g_sys_fw_update.crc);
                transmit_data[2] = SAL_U32_BYTE0(g_sys_fw_update.lenth);
                transmit_data[3] = SAL_U32_BYTE1(g_sys_fw_update.lenth);
                transmit_data[4] = SAL_U32_BYTE2(g_sys_fw_update.lenth);
                g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_START_INFO;
                len = 5;
                break;    
            default:
            break;
        }
    }
    
    return len;
}

#endif
long fw_i2c_rx(unsigned long dest, unsigned long destsz)
{
    int buffsize = 0;
    s32_t fw_lenth = 0;
    unsigned long flash_address = dest;
    //register unsigned short fw_crc = 0;
    u32_t fw_crc = 0;
    if (g_sys_fw_update.lenth > destsz)
    {
        return -1;
    }
    fw_lenth = g_sys_fw_update.lenth;
    
    g_sys_fw_update.sla_sta.process = TRUE;
    
    for( ; ; )
    {
        if (g_sys_fw_update.rx_fw_data_flg)
        {
            g_sys_fw_update.rx_fw_data_flg = FALSE;
            
            if(fw_lenth >= 32)
            {
                if (g_sys_fw_update.s_rx_fw_data_lenth == 32)
                {
                    buffsize = 32;
                }
                else{
                    g_sys_fw_update.sla_sta.err = TRUE;
                    g_sys_fw_update.sla_sta.process = FALSE;
                    g_sys_fw_update.sla_sta.ready = FALSE;
                    g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_STOP;
                    //printf("s_rx_fw_data_lenth_err0 = %d\n",g_sys_fw_update.s_rx_fw_data_lenth);
                    drv_uart_puts("rx data lenth err0:");
                    drv_uart_putdec(g_sys_fw_update.s_rx_fw_data_lenth);
                    return -2;
                }
                 
            }
            else
            {  
                if (fw_lenth == g_sys_fw_update.s_rx_fw_data_lenth)
                {
                    buffsize = g_sys_fw_update.s_rx_fw_data_lenth;
                }
                else
                {
                    g_sys_fw_update.sla_sta.err = TRUE;
                    g_sys_fw_update.sla_sta.process = FALSE;
                    g_sys_fw_update.sla_sta.ready = FALSE;
                    g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_STOP;
                    //printf("s_rx_fw_data_lenth_err1 = %d\n",g_sys_fw_update.s_rx_fw_data_lenth);
                    drv_uart_puts("rx data lenth err1:");
                    drv_uart_putdec(g_sys_fw_update.s_rx_fw_data_lenth);
                    return -2;
                }
            }
            
            //fw_crc = crc16_ccitt_add(fw_crc,&g_i2c_info[FW_DOWNLOAD_I2C_ID].rx_data[1], buffsize);
            fw_crc = drv_crc16_8005_add(fw_crc,&g_i2c_info[FW_DOWNLOAD_I2C_ID].rx_data[1], buffsize);
            if (fw_lenth > 0)
            {
                drv_flash_write(flash_address, &g_i2c_info[FW_DOWNLOAD_I2C_ID].rx_data[1], buffsize);
            }
            fw_lenth -= buffsize;
            flash_address += buffsize;
            if (fw_lenth <= 0)
            {
                if (fw_crc == g_sys_fw_update.crc)
                {
                    g_sys_fw_update.sla_sta.process = FALSE;
                    g_sys_fw_update.sla_sta.finish = TRUE;
                    g_sys_fw_update.sla_sta.ready = FALSE;
                    g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_STOP;
                    drv_uart_puts("\ncrc ok:");
                    drv_uart_puthex16(g_sys_fw_update.crc);
                    return g_sys_fw_update.lenth ;
                }
                else
                {
                    g_sys_fw_update.sla_sta.process = FALSE;
                    g_sys_fw_update.sla_sta.finish = FALSE;
                    g_sys_fw_update.sla_sta.ready = FALSE;
                    g_sys_fw_update.sla_sta.err = TRUE;
                    g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_STOP;
                    //printf("crc check err,crc_count=%d,rx_crc=%d\n",fw_crc,g_sys_fw_update.crc);
                    drv_uart_puts("crc check err,crc count:");
                    drv_uart_puthex16(fw_crc);
                    //drv_uart_puts("\ncrc rx:");
                    drv_uart_puthex16(g_sys_fw_update.crc);
                    return -2 ;
                }  
            }
            
        }
        else if(g_sys_fw_update.mcu_ctrl_fw_cmd == FW_UPDATE_STA_STOP)
        {
            g_sys_fw_update.sla_sta.process = FALSE;
            g_sys_fw_update.sla_sta.ready = FALSE;
            g_sys_fw_update.sla_sta.sta0 = FW_UPDATE_STA_STOP;
            drv_uart_puts("\nmcu stop down fw process\n");
            return -3;
        }

    } 
    return 0;
}
u8_t i2c_upgrade()
{

#if 0    
    for (u8_t i = APP_SECTOR_ADDR_OFFSET; i < DRV_FLASH_SECTOR_CNT; i++ )
    {
        drv_flash_sector_erase(i*DRV_FLASH_SECTOR_SIZE);
    }
#endif  
    sys_fw_update_para_save();
    if (0 < fw_i2c_rx(APP_ADDR_OFFSET, APP_IMG_SIZE))
    {
        return 1;
    }
    return 0;
}

#endif

