/******************** Copyright @ SuZhou Inovance CO.,LTD ********************
* File Name 		 : f_CAN_drive.c
* Version			 : v0.1
* Date				 : 2018/5/6
* Description		 : CAN应用层
* History			 :
   
1. Date: 2018/5/6  Version: v0.1
   Author:		  
   ID:
   Modification: 
   
*******************************************************************************/



#include "f_CAN_drive.h"

// 主频160MHz

const CAN_BAUD_ST StCanBaud[CAN_BAUD_SUM] = 
{
	{100, CAN_BS1_16tq, CAN_BS2_3tq},	    // 0-20Kbps	
	{40, CAN_BS1_16tq, CAN_BS2_3tq},	    // 1-50Kbps		
	{20, CAN_BS1_16tq, CAN_BS2_3tq},	    // 2-100Kbps	
	{16, CAN_BS1_16tq, CAN_BS2_3tq},	    // 3-125Kbps	17/20
	{8,  CAN_BS1_16tq, CAN_BS2_3tq},	    // 4-250Kbps	17/20
	{4,  CAN_BS1_16tq, CAN_BS2_3tq},	    // 5-500Kbps	17/20  85%	
	{2,  CAN_BS1_16tq, CAN_BS2_3tq},	    // 6-1Mbps	 	17/20  85%	 
};

CAN_TX_DATA gCanTxBuf = {0, 0, 0,{0}} ;  			// CAN发送缓存
CAN_RX_DATA gCANRxBuf = {0, 0, 0,{0}, 0};			// CAN接收缓存                                        // 测试接收帧数

Uint16 TestAA[10];

void InitRecMbox(Uint16 mbox, Uint32 msgid, Uint32 lam, Uint16 fifoNo);
void InitCANIO(void);

static void CanDataSendDemo(DspCanDataStru *pData);


// CAN_FIFO_0接收中断
#ifdef USE_CAN1
    void CAN1_RX0_IRQHandler(void)
#else
    void CAN2_RX0_IRQHandler(void)
#endif
{
	DspCanDataStru *RxData;   
	
	TestAA[0] ++;
	
	RxData = (DspCanDataStru *)(&(gCANRxBuf.RxMessage[gCANRxBuf.write]));

    // 直接从底层寄存器读数据，尽量减少参数拷贝耗时
    if ((E_CAN->sFIFOMailBox[CAN_FIFO0].RIR & CAN_RI0R_IDE) == CAN_ID_STD)// 标准
    {
        RxData->msgid = (Uint32)0x000007FF & (E_CAN->sFIFOMailBox[CAN_FIFO0].RIR >> 21);
    }
    else                                                    // 扩展
    {
        RxData->msgid  = (Uint32)0x1FFFFFFF & (E_CAN->sFIFOMailBox[CAN_FIFO0].RIR >> 3);
    }

    if ((E_CAN->sFIFOMailBox[CAN_FIFO0].RIR & CAN_RI0R_RTR) == CAN_RTR_DATA)// 数据帧
    {
        RxData->rtr = 0;
    }
    else
    {
        RxData->rtr = 1;                                    // 远程帧
    }

    RxData->len = (Uint16)(CAN_RDT0R_DLC & E_CAN->sFIFOMailBox[CAN_FIFO0].RDTR);

    RxData->data[0] = (Uint8)(CAN_RDL0R_DATA0 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDLR);
    RxData->data[1] = (Uint8)((CAN_RDL0R_DATA1 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDLR) >> 8);
    RxData->data[2] = (Uint8)((CAN_RDL0R_DATA2 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDLR) >> 16);
    RxData->data[3] = (Uint8)((CAN_RDL0R_DATA3 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDLR) >> 24);

    RxData->data[4] = (Uint8)(CAN_RDH0R_DATA4 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDHR);
    RxData->data[5] = (Uint8)((CAN_RDH0R_DATA5 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDHR) >> 8);
    RxData->data[6] = (Uint8)((CAN_RDH0R_DATA6 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDHR) >> 16);
    RxData->data[7] = (Uint8)((CAN_RDH0R_DATA7 & E_CAN->sFIFOMailBox[CAN_FIFO0].RDHR) >> 24);

    E_CAN->RF0R |= CAN_RF0R_RFOM0;                          // Release FIFO0
    
    CanDataSendDemo(RxData);
    
    if (0 != CANIntHook(RxData))                                // 需要缓存
    {
        if (gCANRxBuf.len < MAX_RX_MSG_COUNT)              		// 不存在覆盖情况
        {
        	if (gCANRxBuf.write < MAX_RX_MSG_COUNT)
        	{
        		gCANRxBuf.write ++;
        	}
        	else
        	{
        		gCANRxBuf.write = 0;
        	}
        	
            gCANRxBuf.len ++;
        }
        else
        {
            gCANRxBuf.bufOver = CANBUF_OVER;            		// 覆盖置标志位
        }    
    }
}

// CAN_FIFO_1接收中断
#ifdef USE_CAN1
    void CAN1_RX1_IRQHandler(void)
#else
    void CAN2_RX1_IRQHandler(void)
#endif
{
	DspCanDataStru *RxData;

	TestAA[1] ++;
	
	RxData = (DspCanDataStru *)(&(gCANRxBuf.RxMessage[gCANRxBuf.write]));
	
    // 直接从底层寄存器读数据，尽量减少参数拷贝耗时
    if ((E_CAN->sFIFOMailBox[CAN_FIFO1].RIR & CAN_RI0R_IDE) == CAN_ID_STD)// 标准
    {
        RxData->msgid = (Uint32)(0x000007FF & (E_CAN->sFIFOMailBox[CAN_FIFO1].RIR >> 21));
    }
    else                                                    // 扩展
    {
        RxData->msgid = (Uint32)(0x1FFFFFFF & (E_CAN->sFIFOMailBox[CAN_FIFO1].RIR >> 3));
    }

    if ((E_CAN->sFIFOMailBox[CAN_FIFO1].RIR & CAN_RI0R_RTR) == CAN_RTR_DATA)// 数据帧
    {
        RxData->rtr = 0;
    }
    else
    {
        RxData->rtr = 1;                                    // 远程帧
    }

    RxData->len = (Uint16)(CAN_RDT0R_DLC & E_CAN->sFIFOMailBox[CAN_FIFO1].RDTR);

    RxData->data[0] = (Uint8)(CAN_RDL0R_DATA0 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDLR);
    RxData->data[1] = (Uint8)((CAN_RDL0R_DATA1 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDLR) >> 8);
    RxData->data[2] = (Uint8)((CAN_RDL0R_DATA2 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDLR) >> 16);
    RxData->data[3] = (Uint8)((CAN_RDL0R_DATA3 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDLR) >> 24);

    RxData->data[4] = (Uint8)(CAN_RDH0R_DATA4 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDHR);
    RxData->data[5] = (Uint8)((CAN_RDH0R_DATA5 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDHR) >> 8);
    RxData->data[6] = (Uint8)((CAN_RDH0R_DATA6 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDHR) >> 16);
    RxData->data[7] = (Uint8)((CAN_RDH0R_DATA7 & E_CAN->sFIFOMailBox[CAN_FIFO1].RDHR) >> 24);

    E_CAN->RF1R |= CAN_RF1R_RFOM1;                          	// Release FIFO1
    
	CanDataSendDemo(RxData);
	
    if (0 != CANIntHook(RxData))                                // 需要缓存
    {
        if (gCANRxBuf.len < MAX_RX_MSG_COUNT)              		// 不存在覆盖情况
        {
        	if (gCANRxBuf.write < MAX_RX_MSG_COUNT)
        	{
        		gCANRxBuf.write ++;
        	}
        	else
        	{
        		gCANRxBuf.write = 0;
        	}
        	
            gCANRxBuf.len ++;
        }
        else
        {
            gCANRxBuf.bufOver = CANBUF_OVER;            		// 覆盖置标志位
        }    
    }
}

// 测试代码 发送数据
static void CanDataSendDemo(DspCanDataStru *pData)
{
	DspCanDataStru TranData;
	
	TranData.len = pData->len;
	TranData.msgid = pData->msgid + 1;
	TranData.rtr = pData->rtr;
	
	TranData.data[0] = pData->data[0] + 1;
	TranData.data[1] = pData->data[1] + 1;
	TranData.data[2] = pData->data[2] + 1;
	TranData.data[3] = pData->data[3] + 1;
	TranData.data[4] = pData->data[4] + 1;
	TranData.data[5] = pData->data[5] + 1;
	TranData.data[6] = pData->data[6] + 1;
	TranData.data[7] = pData->data[7] + 1;
	
	eCanDataTran(&TranData);
}


// CAN发送中断
#ifdef USE_CAN1
void CAN1_TX_IRQHandler(void)
#else
void CAN2_TX_IRQHandler(void)
#endif
{
	TestAA[2] ++;
	
    for (;;)                                  
    {
        if (gCanTxBuf.len > 0)                              // 缓存未空，发送数据
        {
        	if (CAN_NO_MB != CAN_Transmit(E_CAN, &gCanTxBuf.TxMessage[gCanTxBuf.read]))
            {                                               // 发送成功
            	if (gCanTxBuf.read < MAX_TX_MSG_COUNT)
            	{
            		gCanTxBuf.read ++;
            	}
            	else
            	{
            		gCanTxBuf.read = 0;
            	}
            	
                gCanTxBuf.len --;
            }
            else
            {
                break;                                      // 邮箱满退出中断
            }    
        }
        else
        {
            CAN_ITConfig(E_CAN, CAN_IT_TME, DISABLE);  		// 缓存内无数据，禁止发送中断
            break;
        }
    }
}


// 初始化CAN_IO
void InitCANIO(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
	GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT); 

    // Configure CAN RX and TX pins
	GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN | CAN_TX_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
	GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
}

// 初始化CAN底层
Uint16 InitCanDrive(const Uint16 baud)
{
    static Uint16 con = 0;
	static Uint16 count = 0;								// 超时计数器

	CAN_InitTypeDef     CAN_InitStructure;	
    NVIC_InitTypeDef    NVIC_InitStructure;
    
	if (baud >= CAN_BAUD_SUM)
	{
		return CAN_INIT_BAUD_ERR;							// 波特率出错
	}	
		
	if (count > IINIT_CAN_TIME)								// 初始化超时出错
    {
    	con = 0;
    	count = 0;
		return  CAN_INIT_TIMEOUT;        
    }

    if (con == 0)
    {
        RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK, ENABLE);       // Enable GPIO CLK

		InitCANIO();	                                    // Init CAN IO
		
        RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);            // Enable CAN CLK

        CAN_DeInit(E_CAN);                                  // CAN register init

        E_CAN->MCR &= ~CAN_MCR_SLEEP;                       // exit from sleep mode

        E_CAN->MCR |= CAN_MCR_INRQ ;                        // Request initialisation

        con = 1;                                            // 第一阶段完成
    }

    if (con == 1)
    {
		if ((E_CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
		{
			count++;
			return CAN_INIT_TIME;							// 初始化进行中
		}
		else
			con = 2;
    }
    
    if (con == 2)
	{
        CAN_StructInit(&CAN_InitStructure);                 // 复位初始化单元
      
        E_CAN->MCR &=0xFFFEFFFF;	                        // CAN cell init
        
        CAN_InitStructure.CAN_TTCM = DISABLE;
        CAN_InitStructure.CAN_ABOM = ENABLE;
        CAN_InitStructure.CAN_AWUM = ENABLE;
        CAN_InitStructure.CAN_NART = DISABLE;
        CAN_InitStructure.CAN_RFLM = DISABLE;
        CAN_InitStructure.CAN_TXFP = ENABLE; 				// 禁用发送fifo按ID优先级发送 ENABLE;
        //CAN_InitStructure.CAN_Mode = CAN_Mode_Silent;
		CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
        CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;	    	// 36MHz/(1+6+1)/9=500K
        
        CAN_InitStructure.CAN_Prescaler = StCanBaud[baud].PRE;	//4
        CAN_InitStructure.CAN_BS1 = StCanBaud[baud].BS1;
        CAN_InitStructure.CAN_BS2 = StCanBaud[baud].BS2;    // 初始化波特率
        
        // Set the time triggered communication mode
        if (CAN_InitStructure.CAN_TTCM == ENABLE)
            E_CAN->MCR |= CAN_MCR_TTCM;
        else
            E_CAN->MCR &= ~CAN_MCR_TTCM;

        // Set the automatic bus-off management
        if (CAN_InitStructure.CAN_ABOM == ENABLE)
            E_CAN->MCR |= CAN_MCR_ABOM;
        else
            E_CAN->MCR &= ~CAN_MCR_ABOM;

        // Set the automatic wake-up mode
        if (CAN_InitStructure.CAN_AWUM == ENABLE)
            E_CAN->MCR |= CAN_MCR_AWUM;
        else
            E_CAN->MCR &= ~CAN_MCR_AWUM;
        
        // Set the no automatic retransmission
        if (CAN_InitStructure.CAN_NART == ENABLE)
            E_CAN->MCR |= CAN_MCR_NART;
        else
            E_CAN->MCR &= ~CAN_MCR_NART;

        // Set the receive FIFO locked mode
        if (CAN_InitStructure.CAN_RFLM == ENABLE)
            E_CAN->MCR |= CAN_MCR_RFLM;
        else
            E_CAN->MCR &= ~CAN_MCR_RFLM;

        // Set the transmit FIFO priority
        if (CAN_InitStructure.CAN_TXFP == ENABLE)
            E_CAN->MCR |= CAN_MCR_TXFP;
        else
            E_CAN->MCR &= ~CAN_MCR_TXFP;

        // Set the bit timing register
        E_CAN->BTR =  (Uint32)(((Uint32)CAN_InitStructure.CAN_Mode << 30)
        			| ((Uint32)CAN_InitStructure.CAN_SJW << 24)
        			| ((Uint32)CAN_InitStructure.CAN_BS1 << 16)
        			| ((Uint32)CAN_InitStructure.CAN_BS2 << 20)
        			| ((Uint32)CAN_InitStructure.CAN_Prescaler - 1));
        
        E_CAN->MCR &= ~CAN_MCR_INRQ;                        // Request leave initialisation

        
        con = 3;
    }
	if (con == 3)
	{
		if ((E_CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) 				
		{
		    count++;
			return CAN_INIT_TIME;		
		}

    }
    con = 0;
	count = 0;

    // 初始化CAN中断
    NVIC_InitStructure.NVIC_IRQChannel = CAN_RX0_IRQ_CHANNEL;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN_RX0_IRQ_Priority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN_RX0_IRQ_SubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);	

    NVIC_InitStructure.NVIC_IRQChannel = CAN_RX1_IRQ_CHANNEL;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN_RX1_IRQ_Priority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN_RX1_IRQ_SubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = CAN_TX_IRQ_CHANNEL;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = CAN_TX_IRQ_Priority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = CAN_TX_IRQ_SubPriority;
    NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
    NVIC_Init(&NVIC_InitStructure);	

    CAN_ITConfig(E_CAN, CAN_IT_FMP0, ENABLE);               // 使能接收中断1 
    CAN_ITConfig(E_CAN, CAN_IT_FMP1, ENABLE);               // 使能接收中断2 

	return CAN_INIT_SUCC;									// 初始化成功 
}	


// 初始化接收邮箱配置
void InitRecMbox(Uint16 mbox, Uint32 msgid, Uint32 lam, Uint16 fifoNo)
{
	CAN_FilterInitTypeDef  CAN_FilterInitStructure;
	Uint32  wTemp = 0;                                      // 帧ID
    Uint32  wLamTemp = 0;                                   // 匹配结构

    if (mbox & 0x80)
    {
        wTemp |= CAN_RI0R_RTR;                              // 远程帧
        wLamTemp |= CAN_RI0R_RTR; 
    }
    
    if (msgid & 0x80000000)                                 // 扩展帧
    {
        wTemp |= (((msgid & 0x1FFFFFFF) << 3) | CAN_RI0R_IDE);

        wLamTemp |= (((lam & 0x1FFFFFFF) << 3) | CAN_RI0R_IDE);
    }
    else                                                    // 标准帧
    {
        wTemp &= ~CAN_RI0R_IDE;
        wTemp |= ((msgid & 0x7FF) << 21);

        wLamTemp &= ~CAN_RI0R_IDE;
        wLamTemp |= ((lam & 0x7FF) << 21);        
    }
    
	CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
	CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    CAN_FilterInitStructure.CAN_FilterNumber = (mbox & 0x1F);//0x1f是否更合理一点，原0x7f
	CAN_FilterInitStructure.CAN_FilterIdHigh = (wTemp >> 16) & 0x0000FFFF;
    CAN_FilterInitStructure.CAN_FilterIdLow = wTemp & 0x0000FFFF;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (wLamTemp >> 16) & 0x0000FFFF;
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = wLamTemp & 0x0000FFFF;
    if (fifoNo)
        CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO1;
    else
        CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
    CAN_FilterInit(&CAN_FilterInitStructure);
}

// 发送CAN数据
Uint16 eCanDataTran(DspCanDataStru *pdata)
{

	Uint16 i;
	Uint16 stat = CAN_MBOX_TRAN_SUCC;
	 
	CanTxMsg TxMessage = {0};

    if (pdata->msgid & 0x80000000)                           // 扩展帧
    {
        TxMessage.IDE = CAN_ID_EXT;
        TxMessage.ExtId = pdata->msgid;
    }
    else                                                    // 标准帧
    {
        TxMessage.IDE = CAN_ID_STD;
        TxMessage.StdId = pdata->msgid;
    }

    if (pdata->rtr)                                          // 远程帧
        TxMessage.RTR = CAN_RTR_REMOTE;
    else
        TxMessage.RTR = CAN_RTR_DATA;                       // 数据帧
        
    TxMessage.DLC = pdata->len;
	
	for (i = 0; i < 8; i++)
	{
		TxMessage.Data[i] = pdata->data[i];
	}	

    // 必须关发送中断，否则会有错误
    NVIC_DisableIRQ(CAN1_TX_IRQn);                          // 关中断，防止与发送中断冲突

	if (CAN_NO_MB != CAN_Transmit(E_CAN, &TxMessage))		// 直接发送成功   yuzhijie 2015.7.13
    {   
        NVIC_EnableIRQ(CAN1_TX_IRQn);                       // 开中断
        return CAN_MBOX_TRAN_SUCC;
    }
 
    if (gCanTxBuf.len < MAX_TX_MSG_COUNT)                   // 长度小于最大
    {        
        gCanTxBuf.TxMessage[gCanTxBuf.write] = TxMessage;   // 结构体直接赋值
		if (gCanTxBuf.write < MAX_TX_MSG_COUNT)
		{
			gCanTxBuf.write ++;
		}
		else
		{
			gCanTxBuf.write = 0; 
		}
		
        gCanTxBuf.len ++;
        
        CAN_ITConfig(E_CAN, CAN_IT_TME, ENABLE);             // 使能中断
        
        stat = CAN_MBOX_TRAN_SUCC;
    }
    else
    {
        stat = CAN_MBOX_BUSY;                               // 无缓存空间
    }    

    NVIC_EnableIRQ(CAN1_TX_IRQn);                           // 开中断 
    
    return stat;

}

