#include "head.h"

#ifdef BATTERY_WITH_COMM

static const BYTE c_frameStartByte_1 = 0xEB;            // 帧起始字符1
static const BYTE c_frameStartByte_2 = 0x90;            // 帧起始字符2
static const BYTE c_frameBasisBytes = 0x04;             // 帧基础长度 2(帧头) + 1(表示长度) + 1(校验和)
static SIGNAL_FLG g_signalFlag;


static BYTE calcByteSum(BYTE *pbuf, int total)
{
    int i;
    BYTE sum = 0;

    for(i=0; i<total; i++)
        sum += pbuf[i];

    return sum;
}

static void parseRecvFrame(COMM_POW_MOD *p_instance, BYTE *pbuf)
{
    bool ctrl_ret;
    BYTE func = pbuf[4]; 
    BYTE son_type = pbuf[5];
    BYTE *p_data = &pbuf[6];

    switch(func)
    {
    case RX_READ_FUNC:
        if(son_type == 0x01){
            p_instance->tYc.batVolt = (WORD)(p_data[0]*256 + p_data[1]);
            p_instance->tYc.capacityVolt = (WORD)(p_data[2]*256 + p_data[3]);
            g_sw_pub.ac_in[PUB_AC_IN_UZ2] = (qs16)((float)p_instance->tYc.batVolt/100*Q16_BASE);
        }else if(son_type == 0x02){
        #ifdef BATTERY_BP_L500
            p_instance->tYx.yxStatus = (WORD)((p_data[0]>>8) + p_data[1]);
        #else
        	p_instance->tYx.yxStatus = p_data[0];
        #endif
            p_instance->tYx.BIT.lostVolt = p_instance->tYx.yxStatus&0x0001;
            p_instance->tYx.BIT.lowVolt = (p_instance->tYx.yxStatus>>2)&0x0001; 
            p_instance->tYx.BIT.actStatus = (p_instance->tYx.yxStatus>>1)&0x0001; 
            p_instance->tYx.BIT.offline = (p_instance->tYx.yxStatus>>4)&0x0001; 
		#ifdef BATTERY_BP_L500
            p_instance->tYx.BIT.R_Alarm = (p_instance->tYx.yxStatus>>8)&0x0001; 
            p_instance->tYx.BIT.OverHeat = (p_instance->tYx.yxStatus>>9)&0x0001; 
        #endif
        #ifdef FUNC_SEL_BAT_MODULE
			p_instance->tYx.BIT.rConnect = (p_instance->tYx.yxStatus>>5)&0x0001; 
			p_instance->tYx.BIT.backup = (p_instance->tYx.yxStatus>>6)&0x0001;
			p_instance->tYx.BIT.capAlarm = (p_instance->tYx.yxStatus>>7)&0x0001;
			p_instance->tYx.BIT.overVolt = (p_instance->tYx.yxStatus>>3)&0x0001; 
			
			g_run_stu.dcgygj =p_instance->tYx.BIT.overVolt;
			g_run_stu.dcfzgj= 	p_instance->tYx.BIT.rConnect;
			g_run_stu.dcbyjlsd=  p_instance->tYx.BIT.backup;
			g_run_stu.dcrlgz =p_instance->tYx.BIT.capAlarm; 
			
		    if(soe_check(EV_BAT_OVER_GJ) != g_run_stu.dcgygj){
                soe_record_ev(EV_BAT_OVER_GJ, g_run_stu.dcgygj, 0, 0, 0);
            }
            if(soe_check(EV_BAT_OFFLINE) != g_run_stu.dclxgj){
                soe_record_ev(EV_BAT_OFFLINE, g_run_stu.dclxgj, 0, 0, 0);
            }
            if(soe_check(EV_BAT_REVERSE) != g_run_stu.dcfzgj){
                soe_record_ev(EV_BAT_REVERSE, g_run_stu.dcfzgj, 0, 0, 0);
            }
            if(soe_check(EV_AC_BACKLOST) != g_run_stu.dcbyjlsd){
                soe_record_ev(EV_AC_BACKLOST, g_run_stu.dcbyjlsd, 0, 0, 0);
            }
 		    if(soe_check(EV_RL_ERR) != g_run_stu.dcrlgz){
                soe_record_ev(EV_RL_ERR, g_run_stu.dcrlgz, 0, 0, 0);
            }
		#endif
            
            g_run_stu.dcjlsd = p_instance->tYx.BIT.lostVolt;
            g_run_stu.dcqy = p_instance->tYx.BIT.lowVolt;
            g_run_stu.dchh = p_instance->tYx.BIT.actStatus;
            g_run_stu.dcdygz = p_instance->tYx.BIT.offline;

            if(soe_check(EV_BATERR) != g_run_stu.dcqy){
                soe_record_ev(EV_BATERR, g_run_stu.dcqy, 0, 0, 0);
            }

            if(soe_check(EV_BAT_ACT) != g_run_stu.dchh){
                soe_record_ev(EV_BAT_ACT, g_run_stu.dchh, 0, 0, 0);
            }

            if(soe_check(EV_AC_LOST) != g_run_stu.dcjlsd){
                soe_record_ev(EV_AC_LOST, g_run_stu.dcjlsd, 0, 0, 0);
            }
        }else if(son_type == 0x03){
            p_instance->tRunParam.dischargeTimeMax = (WORD)(p_data[0]*256 + p_data[1]);
            p_instance->tRunParam.dischargeTimeNow = (WORD)(p_data[2]*256 + p_data[3]);
            g_sw_pub.ac_in[PUB_AC_BATT_ACT_T_MAX] = (qs16)((float)p_instance->tRunParam.dischargeTimeMax/60*Q16_BASE);
            g_sw_pub.ac_in[PUB_AC_BATT_ACT_T_NOW] = (qs16)((float)p_instance->tRunParam.dischargeTimeNow/60*Q16_BASE);
        //   rt_printf("电池最大放电时间=%d 电池放电时长=%d \r\n",p_instance->tRunParam.dischargeTimeMax,p_instance->tRunParam.dischargeTimeNow);
        }
    #ifdef BATTERY_BP_L500
        else if(son_type == 0x10)
        {
        	p_instance->tRunParam.BatteryInResist = (WORD)((p_data[0]>>8) + p_data[1]);
            g_sw_pub.ac_in[PUB_AC_BATT_R] = (qs16)((float)p_instance->tRunParam.BatteryInResist*Q16_BASE);
        }
        else if(son_type == 0x11)
        {
        	p_instance->tRunParam.BatteryTemp = (WORD)((p_data[0]>>8) + p_data[1]);
            g_sw_pub.ac_in[PUB_AC_BATT_TEMP] = (qs16)((float)p_instance->tRunParam.BatteryTemp*Q16_BASE);
        }
        else if(son_type == 0x12)
        {
        	p_instance->tRunParam.BatteryRtPower = (WORD)((p_data[0]>>8) + p_data[1]);
            g_sw_pub.ac_in[PUB_AC_BATT_RT_POWER] = (qs16)((float)p_instance->tRunParam.BatteryRtPower*Q16_BASE);
        }
        else if(son_type == 0x0D)
        {
        	p_instance->tRunParam.BatDischageCurrent = (WORD)((p_data[2]>>8) + p_data[3]);
        	p_instance->tRunParam.BatRechageCurrent = (WORD)((p_data[4]>>8) + p_data[5]);
            g_sw_pub.ac_in[PUB_AC_BATT_DISCHARGE_CURRENT] = (qs16)((float)p_instance->tRunParam.BatDischageCurrent*Q16_BASE);
            g_sw_pub.ac_in[PUB_AC_BATT_RECHARGE_CURRENT] = (qs16)((float)p_instance->tRunParam.BatRechageCurrent*Q16_BASE);
        }
    #endif
        
        break;
    case RX_WRITE_FUNC:
        if(p_data[0] == 0x01)
            ctrl_ret = true;
        else
            ctrl_ret = false;

        if(son_type == 0x01){
            g_signalFlag.BIT.wActStartRet = ctrl_ret;
        }else if(son_type == 0x02){
            g_signalFlag.BIT.wActStopRet = ctrl_ret;
        }else if(son_type == 0x03){
            g_signalFlag.BIT.wDischargeStopRet = ctrl_ret;
        }
    #ifdef BATTERY_BP_L500
        else if(son_type == 0x0A)
        {
        	g_signalFlag.BIT.wBattRRet = ctrl_ret;
        	if(g_signalFlag.BIT.wBattRRet)
        	{
        		rt_printf_time("电池内阻检测成功\r\n");
        	}
        	else
        	{
        		rt_printf_time("电池内阻检测失败!!\r\n");
        	}
        }
    #endif
        break;
    case CFG_PARAM_FUNC:

        break;
    case READ_CFG_PARAM_FUNC:

    break;    
    default:
    //    rt_printf("接收帧功能码错误!\r\n");
        break;
    }
}

static void processRecv(COMM_POW_MOD *p_instance)
{
    int i;
    BYTE equ_addr;
    BYTE calc_sum;
    int frame_len;
    int unparse_len;
    BYTE tmp_buf[TX_BUF_SIZE_MAX];

    if(!p_instance->bData)
        return;

    p_instance->bData = false;

    p_instance->commFault = false;
    p_instance->sendMesgCount = 0;
    if(soe_check(EV_DYSTATUS)){
        soe_record_ev(EV_DYSTATUS, 0, 0, 0, 0); 
    }

    while(p_instance->recvPos != p_instance->parsePos){
        if(p_instance->recvBuf[p_instance->parsePos] != c_frameStartByte_1 || p_instance->recvBuf[(p_instance->parsePos+1)%RX_BUF_SIZE_MAX] != c_frameStartByte_2){
            p_instance->parsePos = (p_instance->parsePos + 1) % RX_BUF_SIZE_MAX;
        //    rt_printf("接收帧报文帧头错误!\r\n");
            continue;
        }

        unparse_len = (RX_BUF_SIZE_MAX + p_instance->recvPos - p_instance->parsePos) % RX_BUF_SIZE_MAX;
        frame_len = c_frameBasisBytes + p_instance->recvBuf[(p_instance->parsePos+2)%RX_BUF_SIZE_MAX];
        if(unparse_len < frame_len){
        //    rt_printf("未接收到完整的一帧报文!\r\n");
            break;
        }

        if(frame_len > TX_BUF_SIZE_MAX){
        //    rt_printf("接收帧长越限!\r\n");
            break;
        }

        for(i=0; i<frame_len; i++){
            tmp_buf[i] = p_instance->recvBuf[(p_instance->parsePos + i) % RX_BUF_SIZE_MAX];
        }

        equ_addr = tmp_buf[3];
        calc_sum = calcByteSum(tmp_buf,frame_len-1);

        p_instance->parsePos = (p_instance->parsePos + frame_len) % RX_BUF_SIZE_MAX;

        /*if(calc_sum != tmp_buf[frame_len-1] || equ_addr != p_instance->equAddr){
        //    rt_printf("接收帧校验和或者装置地址错误!\r\n");
            continue;
        }*/
        if(equ_addr != p_instance->equAddr){
            //rt_printf("装置地址错误!\r\n");
            continue;
        }

        parseRecvFrame(p_instance,tmp_buf);
    }
}

static void addFrameToSendBuff(COMM_POW_MOD *p_instance, BYTE *pbuf, int len)
{
    SERIAL_COMM *port = &g_tRsComm[p_instance->portChannel];

    port->sendbuf[0] = len;         // 第一个字节为长度

    memcpy(&port->sendbuf[1], pbuf, len);

    port->bSend = TRUE;
    port->nSendCnt = 1;       
}

static void sendFixedFrame(COMM_POW_MOD *p_instance,BYTE func,BYTE son_type)
{
    int pos=0;
    BYTE calc_sum;
    BYTE tx_buf[TX_BUF_SIZE_MAX];

    tx_buf[pos++] = c_frameStartByte_1;
    tx_buf[pos++] = c_frameStartByte_2;
    tx_buf[pos++] = 0x03;
    tx_buf[pos++] = p_instance->equAddr;
    tx_buf[pos++] = func;
    tx_buf[pos++] = son_type;
    calc_sum = calcByteSum(tx_buf,pos);
    tx_buf[pos++] = calc_sum;

    addFrameToSendBuff(p_instance,tx_buf,pos);
}

static void sendActInfoClearFrame(COMM_POW_MOD *p_instance)
{
    int pos=0;
    BYTE calc_sum;
    BYTE tx_buf[TX_BUF_SIZE_MAX];
    const WORD c_battCap = 0x07;    // 电池容量 
    const WORD c_ActDischargeEndVolt = 1800;  // 活化放电截止电压18V
    const WORD c_BattLowCapAlarm = 50;  // 电池剩余容量告警值 50% 

    tx_buf[pos++] = c_frameStartByte_1;
    tx_buf[pos++] = c_frameStartByte_2;
    tx_buf[pos++] = 0x09;
    tx_buf[pos++] = p_instance->equAddr;
    tx_buf[pos++] = 0x1A;
    tx_buf[pos++] = 0x01;
    tx_buf[pos++] = (c_battCap>>8)&0xFF;
    tx_buf[pos++] = c_battCap&0xFF;
    tx_buf[pos++] = (c_ActDischargeEndVolt>>8)&0xFF;
    tx_buf[pos++] = c_ActDischargeEndVolt&0xFF;
    tx_buf[pos++] = (c_BattLowCapAlarm>>8)&0xFF;
    tx_buf[pos++] = c_BattLowCapAlarm&0xFF;
    calc_sum = calcByteSum(tx_buf,pos);
    tx_buf[pos++] = calc_sum;

    addFrameToSendBuff(p_instance,tx_buf,pos);
}

static void processSend(COMM_POW_MOD *p_instance)
{   
    const DWORD c_readYxCycletimeSecond = 1;         // 1s 单位：s 
    const DWORD c_readRunInfoCycletimeSecond = 10;   // 10s 单位：s 

    if(g_signalFlag.BIT.wActStart){
        g_signalFlag.BIT.wActStart = FALSE;
        sendFixedFrame(p_instance,TX_WRITE_FUNC,0x01);
    }else if(g_signalFlag.BIT.wActStop){
        g_signalFlag.BIT.wActStop = FALSE;
        sendFixedFrame(p_instance,TX_WRITE_FUNC,0x02);
    }else if(g_signalFlag.BIT.wDischargeStop){
        g_signalFlag.BIT.wDischargeStop = FALSE;
        sendFixedFrame(p_instance,TX_WRITE_FUNC,0x03);
    }else if(g_signalFlag.BIT.cActData){
        g_signalFlag.BIT.cActData = FALSE;
        sendActInfoClearFrame(p_instance);
    }else if(g_signalFlag.BIT.rVolt){
        p_instance->readYxCount = ustimer_get_origin();
        g_signalFlag.BIT.rVolt = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x01);
    }else if(g_signalFlag.BIT.rStatus){
        p_instance->readYxCount = ustimer_get_origin();
        g_signalFlag.BIT.rStatus = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x02);
    }else if(g_signalFlag.BIT.rRunInfo){
        p_instance->readRunInfoCount = ustimer_get_origin();
        g_signalFlag.BIT.rRunInfo = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x03);
    }
#ifdef BATTERY_BP_L500
    else if(g_signalFlag.BIT.rBattR)
    {
        p_instance->ReadBattRCount = ustimer_get_origin();
        g_signalFlag.BIT.rBattR = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x10);
    }
    else if(g_signalFlag.BIT.rBattTemp)
    {
        p_instance->ReadBattTempCount = ustimer_get_origin();
        g_signalFlag.BIT.rBattTemp = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x11);
    }
    else if(g_signalFlag.BIT.rBattRtPower)
    {
        p_instance->ReadBattRtPowerCount = ustimer_get_origin();
        g_signalFlag.BIT.rBattRtPower = FALSE;
        sendFixedFrame(p_instance,TX_READ_FUNC,0x12);
    }
    else if(g_signalFlag.BIT.rBatCurrent)
	{
		p_instance->BatCurrentCount = ustimer_get_origin();
		g_signalFlag.BIT.rBatCurrent = FALSE;
		sendFixedFrame(p_instance,TX_READ_FUNC,0x0D);
	}
    else if(g_signalFlag.BIT.wBattR)
    {
    	//p_instance->DetectBattRCount = ustimer_get_origin();
        g_signalFlag.BIT.wBattR = FALSE;
        sendFixedFrame(p_instance,TX_WRITE_FUNC,0x0A);
    }

    if(ustimer_get_duration(p_instance->ReadBattRCount) > 500 * USTIMER_MS){
        g_signalFlag.BIT.rBattR = TRUE;
    }
    if(ustimer_get_duration(p_instance->ReadBattTempCount) > 1500 * USTIMER_MS){
        g_signalFlag.BIT.rBattTemp = TRUE;
    }
    if(ustimer_get_duration(p_instance->ReadBattRtPowerCount) > 2000 * USTIMER_MS){
        g_signalFlag.BIT.rBattRtPower = TRUE;
    }
    if(ustimer_get_duration(p_instance->BatCurrentCount) > 2500 * USTIMER_MS){
		g_signalFlag.BIT.rBatCurrent = TRUE;
	}
#endif

    if(ustimer_get_duration(p_instance->readYxCount) > c_readYxCycletimeSecond * USTIMER_SEC){
        g_signalFlag.BIT.rStatus = TRUE;
        g_signalFlag.BIT.rVolt = TRUE;
        p_instance->sendMesgCount++;
    }

    if(p_instance->sendMesgCount > 60){
        p_instance->commFault = true;
        if(!soe_check(EV_DYSTATUS)){
            soe_record_ev(EV_DYSTATUS, 1, 0, 0, 0); 
        }
    }

    if(ustimer_get_duration(p_instance->readRunInfoCount) > c_readRunInfoCycletimeSecond * USTIMER_SEC){
        g_signalFlag.BIT.rRunInfo = TRUE;
    }

#ifdef BATTERY_BP_L500
    if(ustimer_get_duration(p_instance->DetectBattRCount) > (180 * USTIMER_SEC))
    {
        g_signalFlag.BIT.wBattR = TRUE;
        rt_printf_time("启动电池内阻检测..\r\n");
		p_instance->DetectBattRCount = ustimer_get_origin();
    }
#endif
}

void ClearBattActInfo(void)
{
    g_signalFlag.BIT.cActData = TRUE;
}

void StartBattAct(void)
{
    g_signalFlag.BIT.wActStart = TRUE;
}

void StopBattAct(void)
{
    g_signalFlag.BIT.wActStop = TRUE;
}

void PowerModuleCommInit(COMM_POW_MOD *p_instance,int ch)
{
    memset(&g_signalFlag, 0, sizeof(SIGNAL_FLG));
    memset(p_instance, 0, sizeof(COMM_POW_MOD));
    p_instance->equAddr = 1;
    p_instance->portChannel = ch;
}

void PowerModuleCommRecv(COMM_POW_MOD *p_instance,BYTE rec_data)
{
    p_instance->recvBuf[p_instance->recvPos] = rec_data;  
    p_instance->recvPos = (p_instance->recvPos + 1) % RX_BUF_SIZE_MAX;

    switch(p_instance->recvFlg){
        case 0:
            p_instance->dataLen = 0;
            p_instance->recvCount = 0;
            if(rec_data == c_frameStartByte_1){
                p_instance->recvFlg = 1;
            }
            break;
        case 1:
            if(rec_data == c_frameStartByte_2){
                p_instance->recvFlg = 2;
            }else{
                p_instance->recvFlg = 0;
            }
        case 2:
            p_instance->dataLen = rec_data;
            p_instance->recvFlg = 3;
            break;
        case 3:
            if(++p_instance->recvCount >= p_instance->dataLen){
                p_instance->recvFlg = 4;
            }
            break;
        case 4:
            p_instance->recvFlg = 0;
            p_instance->bData = true;
            break;
        default:
            p_instance->recvFlg = 0;
            p_instance->bData = false;
            break;
    }
}

void PowerModuleCommRun(COMM_POW_MOD *p_instance)
{
    processSend(p_instance);

    processRecv(p_instance);
}

#endif