#include "bsp_hmi.h"

#include "kit_time.h"
#include "kit_data.h"
#include "kit_debug.h"

#define HMI_PROTOCOL_PREFIX 0xA55A

static void hmi_fill_data(HmiItem *item, uint8_t *buf, uint16_t *len);

void bsp_hmi_analyse_arch(HmiItem *item, bool is_reflesh)
{
    uint8_t addr, func,cmdc,stype,rtype,addr1,addr2,addr3;
    uint16_t tmp,prefix = 0;
    uint32_t tick_diff;
    
    //判断超时时关闭接收中断,防止刚判断完超时后,马上收到数据,导致数据丢失
    if((item != NULL) && (item->ctrl_rx_int_call != NULL) && (item->func_call != NULL))
    {
        item->ctrl_rx_int_call(item->comm_dev, false);
        tick_diff = kit_time_get_interval_by_now(item->tick);
        if((tick_diff >= 10) || (is_reflesh == true))
        {    
            item->occupy_dly += tick_diff;
			//转发数据增加延时
            if((item->occupy != kHmiOccupy_None) && (item->occupy_dly > item->time_out))
            {
                item->occupy = kHmiOccupy_None;
            }
            
            tmp = item->buf_pos;
            item->buf_pos = 0;
            item->tick = kit_time_get_tick();
            item->ctrl_rx_int_call(item->comm_dev, true);
			
			prefix = READ_BT_INT16U(item->comm_buf,addr);  //获取前缀
			
            if((tmp >= HMI_PROTOCOL_MIN_LEN) && (prefix == HMI_PROTOCOL_PREFIX))
            {
                if(kit_check_crc16(item->comm_buf, tmp) == 0)
                {
                    stype = item->comm_buf[HMI_PROTOCOL_SEND_TYPE_POS];
                    rtype = item->comm_buf[HMI_PROTOCOL_RECV_TYPE_POS];
					
					addr1 = item->comm_buf[HMI_PROTOCOL_SRLI_POS];
					addr2 = item->comm_buf[HMI_PROTOCOL_SRLII_POS];
					addr3 = item->comm_buf[HMI_PROTOCOL_SRLIII_POS];
					
					cmdc = item->comm_buf[HMI_PROTOCOL_FUN_POS];
                    func = item->comm_buf[HMI_PROTOCOL_CMD_POS];
					
                    item->snd_type = stype;
                    item->rcv_type = rtype;
                    item->rcv_addr = addr2;
					
					item->rcv_addr1 = addr1;
					item->rcv_addr2 = addr2;
					item->rcv_addr3 = addr3;
					
					//void hmi_func_call(HmiItem *item, uint8_t main_fun, uint8_t sub_fun, uint8_t *buf, uint16_t len)
                    item->func_call(item, cmdc, func, &item->comm_buf[HMI_PROTOCOL_DATA_POS], tmp - 8);
                    //if(item->occupy == kHmiOccupy_Request)
                    {
                        item->occupy = kHmiOccupy_None;
                    }
                }
            }
        }
        else
        {
            item->ctrl_rx_int_call(item->comm_dev, true);
        }
    }
}

void bsp_hmi_analyse(HmiItem *item, bool is_reflesh)
{
    uint8_t addr, type, func;
    uint16_t tmp;
    uint32_t tick_diff;
    
    //判断超时时关闭接收中断,防止刚判断完超时后,马上收到数据,导致数据丢失
    if((item != NULL) && (item->ctrl_rx_int_call != NULL) && (item->func_call != NULL))
    {
        item->ctrl_rx_int_call(item->comm_dev, false);
        tick_diff = kit_time_get_interval_by_now(item->tick);
        if((tick_diff >= 10) || (is_reflesh == true))
        {    
            item->occupy_dly += tick_diff;
			//转发数据增加延时
            if((item->occupy != kHmiOccupy_None) && (item->occupy_dly > item->time_out))
            {
                item->occupy = kHmiOccupy_None;
            }
            
            tmp = item->buf_pos;
            item->buf_pos = 0;
            item->tick = kit_time_get_tick();
            item->ctrl_rx_int_call(item->comm_dev, true);

            if((tmp >= 7) && (item->comm_buf[0] == 0xEE))
            {
                if(kit_check_crc16(item->comm_buf, tmp) == 0)
                {
                    type = item->comm_buf[HMI_DEVICE_TYPE_POS];
                    addr = item->comm_buf[HMI_SLAVE_ADDR_POS];
                    func = item->comm_buf[HMI_FUNC_CODE_POS];
                    
                    item->snd_type = type >> 4;
                    item->rcv_type = type & 0x0F;
                    item->rcv_addr = addr;
                    item->func_call(item, func >> 4, func & 0x0F, &item->comm_buf[HMI_DATA_POS], tmp - 8);
                    //if(item->occupy == kHmiOccupy_Request)
                    {
                        item->occupy = kHmiOccupy_None;
                    }
                }
            }
        }
        else
        {
            item->ctrl_rx_int_call(item->comm_dev, true);
        }
    }
}

bool bsp_hmi_request(HmiItem *item, uint8_t master_type, uint8_t slave_type, uint8_t slave_addr, uint8_t main_fun, uint8_t sub_fun, uint8_t *buf, uint16_t len, uint16_t time_out)
{
    bool res = false;
    if((item != NULL) && (item->send_call != NULL) && (item->occupy == kHmiOccupy_None))
    {
        item->occupy = kHmiOccupy_Request;
        item->occupy_dly = 0;
        item->rcv_type = master_type;
        item->snd_type = slave_type;
        item->time_out = time_out;
        item->comm_buf[0] = 0xEE;
        item->comm_buf[HMI_SLAVE_ADDR_POS]  = slave_addr;
        item->comm_buf[HMI_FUNC_CODE_POS] = (main_fun << 4) | (sub_fun & 0x0F);
        
        hmi_fill_data(item, buf, &len);
        item->send_call(item->comm_dev, item->comm_buf, len);
        res = true;
    }
    return res;
}

static void hmi_fill_data(HmiItem *item,  uint8_t *buf, uint16_t *len)
{
	if(buf != NULL)
	{
		kit_copy_buf(&item->comm_buf[HMI_DATA_POS], buf, *len);
	}
	*len += 1 + 4 + 1 + 2;
    kit_lt_write_buf(item->comm_buf, HMI_BUF_LEN_POS, *len, 2);
    item->comm_buf[HMI_DEVICE_TYPE_POS] = item->rcv_type << 4 | item->snd_type;
    kit_append_crc16(item->comm_buf, *len - 2);
}
/*
#define HMI_PROTOCOL_SEND_TYPE_POS     (4u) //发送类型
#define HMI_PROTOCOL_RECV_TYPE_POS     (5u) //接收类型
#define HMI_PROTOCOL_CMD_POS     (6u) //命令类型
#define HMI_PROTOCOL_FUN_POS     (7u) //功能类型
#define HMI_PROTOCOL_SRLI_POS    (8u) //序号码 (serial1)
#define HMI_PROTOCOL_SRLII_POS   (9u) //序号码 (serial1)
#define HMI_PROTOCOL_SRLIII_POS  (10u)//序号码 (serial1)
*/
static void hmi_fill_std_data(HmiItem *item,  uint8_t *buf, uint16_t *len)
{
	if(buf != NULL)
	{
		kit_copy_buf(&item->comm_buf[HMI_PROTOCOL_DATA_POS], buf, *len);
	}
	*len += 2 + 2 + 7 + 2;
    kit_lt_write_buf(item->comm_buf, HMI_PROTOCOL_BUF_LEN_POS, *len, 2);
	item->comm_buf[0] = HMI_PROTOCOL_PREFIX >> 8;
	item->comm_buf[1] = HMI_PROTOCOL_START_POS << 8;
	
    item->comm_buf[HMI_PROTOCOL_SEND_TYPE_POS] = item->rcv_type; 
	item->comm_buf[HMI_PROTOCOL_RECV_TYPE_POS] = item->snd_type;

	item->comm_buf[HMI_PROTOCOL_CMD_POS] = item->main_func; 
	item->comm_buf[HMI_PROTOCOL_FUN_POS] = item->sub_func;

	item->comm_buf[HMI_PROTOCOL_SRLI_POS] = item->rcv_addr1; 
	item->comm_buf[HMI_PROTOCOL_SRLII_POS] = item->rcv_addr2;
	item->comm_buf[HMI_PROTOCOL_SRLIII_POS] = item->rcv_addr3;
	
    kit_append_crc16(item->comm_buf, *len - 2);
}



bool bsp_hmi_forward(HmiItem *rcv_item, HmiItem *fwd_item, uint16_t len)
{
    bool res = false;
    if((rcv_item != NULL) && (fwd_item != NULL) 
    && (fwd_item->send_call != NULL) && (fwd_item->occupy != kHmiOccupy_Request))
    {
        fwd_item->occupy_dly = 0;
        fwd_item->time_out = 4000;
        fwd_item->fwd_item = rcv_item;
        fwd_item->occupy = kHmiOccupy_Forward;
        fwd_item->send_call(fwd_item->comm_dev, rcv_item->comm_buf, len + 7 + 1);
        res = true;
    }
    return res;
}

void bsp_hmi_pos_send(HmiItem *item, uint8_t *buf, uint16_t len)
{
    KIT_ASSERT_PARAM(item->send_call != NULL);

    if((item != NULL) && (item->send_call != NULL))
    {
        item->comm_buf[HMI_SLAVE_ADDR_POS] = item->dev_addr;
        hmi_fill_data(item, buf, &len); 
        item->send_call(item->comm_dev, item->comm_buf, len);
    }
}

void bsp_hmi_send(HmiItem *item, uint8_t *buf, uint16_t len)
{
    KIT_ASSERT_PARAM(item->send_call != NULL);

    if((item != NULL) && (item->send_call != NULL))
    {
        hmi_fill_std_data(item, buf, &len); 
        item->send_call(item->comm_dev, item->comm_buf, len);
    }
}




void bsp_hmi_neg_send(HmiItem *item, uint16_t ex_code)
{
    if(item != NULL)
    {
        item->comm_buf[HMI_FUNC_CODE_POS] |= 0x80;
        bsp_hmi_pos_send(item, (uint8_t *)&ex_code, 2);
    }
}

void bsp_hmi_push_data(HmiItem *item, uint8_t *buf, uint16_t len)
{
    uint32_t i;
   
    if(item != NULL)
    {
        item->tick = kit_time_get_tick();
        item->occupy_dly = 0;
        if (item->buf_pos + len < item->buf_len)
        {
            for (i = 0; i < len; i++)
            {
                item->comm_buf[item->buf_pos++] = buf[i];
            }
        }    
    }
}

void bsp_hmi_set_dev_addr(HmiItem *item, uint8_t addr)
{
    if(item != NULL)
    {
        item->dev_addr = addr;
    }
}

void bsp_hmi_set_comm_dev(HmiItem *item, uint8_t dev)
{
    if(item != NULL)
    {
        item->comm_dev = dev;
    }
}

void bsp_hmi_set_fun_07_call(HmiItem *item, Fun07Call call)
{
    if(item != NULL)
    {
        item->fun_07_call = call;
    }
}