#include "app.h"

CAN_HandleTypeDef   CAN_Handle;

CanTxRxMsg CAN_RxMessage;
CanTxRxMsg CAN_TxMessage;

volatile uint8_t gu8_CAN_ReceiveFlag = 0;

void CAN_ReceiveIT_Callback(CAN_HandleTypeDef *hcan)
{
    gu8_CAN_ReceiveFlag = 1;
}

/******************************************************************************
*@brief : config the CAN module. eg: Mode,baudrate
*         
*@param : None
*@return: None
*@note  : The parameters below config the CAN baudrate as 500K, 
            when system clock = 120MHz, and PCLK1 = 60MHz
******************************************************************************/
static void CAN_Mode_Config(void)
{  
    CAN_Handle.Instance = CANx;
    CAN_Handle.Init.CAN_Mode    = CAN_OperatingMode_Normal;     
    CAN_Handle.Init.CAN_SJW     = CAN_SJW_1tq;        
    CAN_Handle.Init.CAN_BRP     = 5;                       
    CAN_Handle.Init.CAN_TSEG1   = CAN_TSEG1_5tq;
    CAN_Handle.Init.CAN_TSEG2   = CAN_TSEG2_4tq;    
    CAN_Handle.Init.CAN_BOR     = CAN_BOR_ENABLE;  

    CAN_Handle.CAN_ReceiveIT_Callback = CAN_ReceiveIT_Callback; 
    HAL_CAN_Init(&CAN_Handle);
}

/******************************************************************************
*@brief : config the CAN filter
*         
*@param : None
*@return: None
******************************************************************************/
static void CAN_Filter_Config()
{
    CAN_FilterInitTypeDef  CAN_FilterInitStruct;
    
    CAN_FilterInitStruct.FilterMode = CAN_FilterMode_Dual;
    CAN_FilterInitStruct.FilterBank = 0;
    CAN_FilterInitStruct.FilterId1  = 0x18FE0000;
    CAN_FilterInitStruct.FilterId2  = 0x12340000;
    /* if want receive all data,please set the CAN_FilterMaskId = 0xFFFFFFFF*/
    CAN_FilterInitStruct.FilterMaskId1  = 0x0000FFFF; /* only receive CAN id=0x18FExxxx */	
    CAN_FilterInitStruct.FilterMaskId2  = 0x0000FFFF; /* only receive CAN id=0x1234xxxx	*/
    CAN_FilterInitStruct.FilterActivation = CAN_FILTER_ENABLE;
    
    printfS("Filter Mode: Dual\r\n");
    printfS("Filter Id1 = 0x%08X, MaskId1 = 0x%08X\r\n", CAN_FilterInitStruct.FilterId1, CAN_FilterInitStruct.FilterMaskId1);
    printfS("Filter Id2 = 0x%08X, MaskId2 = 0x%08X\r\n\r\n", CAN_FilterInitStruct.FilterId2, CAN_FilterInitStruct.FilterMaskId2);
    HAL_CAN_ConfigFilter(&CAN_Handle, &CAN_FilterInitStruct);
}


void CAN_PrintfReceive()
{
    uint8_t i=0;
    printfS("\r\n---------------------------------\r\n");
    printfS("Receive CAN data!\n");
    if(CAN_RxMessage.IDE==CAN_Id_Standard)	
    {
        printfS("CAN IDE type: Standard\n"); 
        printfS("CAN ID=0x%.8x\n",CAN_RxMessage.StdId);
    }
    else
    {
        printfS("CAN IDE type: Extended\n"); 
        printfS("CAN ID=0x%.8x\n",CAN_RxMessage.ExtId);
    }
    if(CAN_RxMessage.RTR==CAN_RTR_Data)	
    {
        printfS("CAN RTR type: Data frame\n"); 
        printfS("data length=%d\n",CAN_RxMessage.DLC);
        for(i=0;i<CAN_RxMessage.DLC;i++)
        {
            printfS("%.2x ",CAN_RxMessage.Data[i]);
        }       
        printfS("\n");
    }
    else
    {
        printfS("CAN RTR type: Remote frame\n"); 
    }
}

void CAN_Receive(enum_TEST_MODE_t fe_Mode)
{
    switch (fe_Mode)
    {
        /* Loop mode */
        case TEST_LOOP: 
        {   
            while(1)
            {
                if(HAL_CAN_Receive(&CAN_Handle,&CAN_RxMessage, 1000) == HAL_OK) 
                {   
                    /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                    CAN_PrintfReceive();
                    CAN_TxMessage = CAN_RxMessage;
                    HAL_CAN_Transmit(&CAN_Handle, &CAN_TxMessage, 10);
                }
            } 
        }        
        /* IT mode */
        case TEST_IT: 
        {  
            HAL_CAN_Receive_IT(&CAN_Handle, &CAN_RxMessage);
            while(1)
            {
                if(gu8_CAN_ReceiveFlag == 1)
                {
                    gu8_CAN_ReceiveFlag = 0;

                    CAN_PrintfReceive();
                    CAN_TxMessage = CAN_RxMessage;
                    HAL_CAN_Transmit(&CAN_Handle, &CAN_TxMessage, 10);/* echo back */
                    
                }
            }
        }
        default: break; 
    }
}

void CAN_Networking_Test(void)
{	
    uint8_t i = 0;
    
    /* Initialise the CAN module */
    CAN_Mode_Config();
    
    /* Configure the CAN filter */
    CAN_Filter_Config();
    
    /* Prepare the message to send */
    CAN_TxMessage.StdId = 0x666;		            //11bits, not used in extended mode			 
    CAN_TxMessage.ExtId = 0x18FE0000;			    //29bits
    CAN_TxMessage.IDE   = CAN_Id_Extended;			//extended mode
    CAN_TxMessage.RTR   = CAN_RTR_Data;				//frame type: data
    CAN_TxMessage.DLC   = 8;					    //data length

    for (i = 0; i < CAN_TxMessage.DLC; i++)
    {
        CAN_TxMessage.Data[i] = 1 + i;
    }
    
    printfS("Please press the USR_PB button to continue......\r\n\r\n");
    
    while(GPIO_PIN_SET == BSP_PB_GetState());

    /* Send data */
    if(HAL_CAN_Transmit(&CAN_Handle, &CAN_TxMessage, 10) != HAL_OK)
    {
        CAN_ErrCodeInfo_t ErrCode;
        
        HAL_CAN_GetErrorCode(&CAN_Handle, &ErrCode);

        printfS("CAN send failed!\r\n");
        printfS("ErrCode.ALC = %d\r\n", ErrCode.ALC);
        printfS("ErrCode.ErrCode = %d\r\n", ErrCode.ErrCode);
        printfS("ErrCode.ErrDirection = %d\r\n", ErrCode.ErrDirection);
        printfS("ErrCode.SegCode = %d\r\n", ErrCode.SegCode);
    }
    else
    {
        printfS("CAN Networking send data OK\r\n");
    }
	
    printfS("\r\nWaiting for receiving data...\r\n");
    CAN_Receive(TEST_LOOP);
	
}
