/*
  ******************************************************************************
  * @file    APP_Can.c
  * @author  CWT
  * @version V1.0.0
  * @date    2020
  * @brief   CWT demo source code.
  ******************************************************************************
*/

#include "APP.h"

#define CAN_LOG_ENABLE

CAN_HandleTypeDef   CAN_Handle;

CanTxRxMsg CAN_RxMessage;

volatile uint8_t gu8_CAN_ReceiveFlag=0;


void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{
    /* NOTE : This function should not be modified, when the callback is needed,
                the HAL_UART_MspInit can be implemented in the user file
    */
    /* For Example */
    GPIO_InitTypeDef GPIO_InitStructure;

    /* Enable CAN clock */
    System_Module_Enable(EN_CAN1);
    System_Module_Enable(EN_GPIOCD);
    
    /* Initialization GPIO */
    /* PA11:Rx */  /* PA12:Tx */
    GPIO_InitStructure.Pin = GPIO_PIN_0|GPIO_PIN_1;	
    GPIO_InitStructure.Alternate=GPIO_FUNCTION_5;
    GPIO_InitStructure.Pull=GPIO_PULLUP;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
    
    /* 以下用于A070 LCD子板上CAN收发器的第8脚拉低 */
    GPIO_InitStructure.Pin = GPIO_PIN_4;	
    GPIO_InitStructure.Alternate=GPIO_FUNCTION_0;
    GPIO_InitStructure.Pull=GPIO_PULLUP;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
    
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_CLEAR);
    
    NVIC_ClearPendingIRQ(CAN1_IRQn);
    NVIC_SetPriority(CAN1_IRQn, 3);
    NVIC_EnableIRQ(CAN1_IRQn); 
    
}

/*********************************************************************************
* Function    : CAN_IRQHandler
* Description : CAN_IRQHandler handler
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void CAN_IRQHandler(void)
{
    HAL_CAN_IRQHandler(&CAN_Handle);
}

/*********************************************************************************
* Function    : CAN_ReceiveIT_Callback
* Description : CAN ReceiveIT_Callback Funtion
* Input       : CAN_HandleTypeDef
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void CAN_ReceiveIT_Callback(CAN_HandleTypeDef *hcan)
{
    gu8_CAN_ReceiveFlag=1;
}

/*********************************************************************************
* Function    : CAN_Mode_Config
* Description : Config CAN Mode.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_Mode_Config(void)
{  
    CAN_Handle.Instance=CANx;
    CAN_Handle.Init.CAN_Mode = CAN_Mode_Normal; //CAN_Mode_SelfTest;     //CAN_Mode_Normal
    CAN_Handle.Init.CAN_SJW=CAN_SJW_1tq;            //CAN_SJW_1tq
    CAN_Handle.Init.CAN_BRP=7;                       // //pclk =64M   BRP=2*(7+1)=16  TQ=16*(1/64M)=1/4M
    CAN_Handle.Init.CAN_TSEG1=CAN_TSEG1_3tq;
    CAN_Handle.Init.CAN_TSEG2=CAN_TSEG2_4tq;         //width=1+3+4=8 TQ    baud=1M/(1/4*8)=1M/2=500K
    CAN_Handle.Init.CAN_BOR=CAN_BOR_ENABLE;       	//ENABLE Bus off recover     
    CAN_Handle.CAN_ReceiveIT_Callback=CAN_ReceiveIT_Callback; 
    HAL_CAN_Init(&CAN_Handle);
}

/*********************************************************************************
* Function    : CAN_Filter_Config
* Description : Set CAN Filter to Receive data.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
static void CAN_Filter_Config()
{
    CAN_FilterInitTypeDef  CAN_FilterInitStruct;
    CAN_FilterInitStruct.CAN_FilterMode=CAN_FilterMode_Dual;
    CAN_FilterInitStruct.CAN_FilterId1=0x18fe0000;  //Extended Id:ID28...ID0
    CAN_FilterInitStruct.CAN_FilterId2=0x100<<18;   //Standard Id:ID28...ID18,so need (ID<<18)
    /* if want receive all data,please set the CAN_FilterMaskId = 0xFFFFFFFF*/
    CAN_FilterInitStruct.CAN_FilterMaskId1=0x0000FFFF; //only receive CAN id=0x18fexxxx(only care 0x18fexxxx)
    CAN_FilterInitStruct.CAN_FilterMaskId2=0x100<<18; //only receive CAN id=0x100     ( care ID28...ID18)
    HAL_CAN_ConfigFilter(&CAN_Handle, &CAN_FilterInitStruct);
}

/*********************************************************************************
* Function    : CAN_PrintfReceive
* Description : use uart to printf can receive data.
* Input       : 
* Outpu       : 
* Author      : CWT                         Data : 2020年
**********************************************************************************/
void CAN_PrintfReceive()
{
    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(int i=0;i<CAN_RxMessage.DLC;i++)
        {
            printfS("%.2x ",CAN_RxMessage.Data[i]);
        }
        printfS("\n");
    }
    else
    {
        printfS("CAN RTR type: Remote frame\n"); 
    }
}

/*********************************************************************************
* Function    : APP_Can_Test
* Description : 
* Input       : 
* Outpu       : 
* Author      :                          Data : 2023年
**********************************************************************************/
void APP_CAN_Test(enum_TEST_MODE_t fe_Mode)
{
    uint8_t i;
    
    CAN_Mode_Config();
    CAN_Filter_Config();
    CanTxRxMsg CAN_TxMessage;    
    
    CAN_TxMessage.ExtId = 0x18FE0000;
    CAN_TxMessage.RTR = CAN_RTR_Data;
    CAN_TxMessage.IDE = CAN_Id_Extended;
    for(i = 0; i < 8; i++)
            CAN_TxMessage.Data[i] = 0x11+i*2;
    CAN_TxMessage.DLC = 8;
    switch (fe_Mode)
    {
        /* 循环模式 */
        case TEST_LOOP: 
        {               
            printfS("\r\n====CAN Demo LOOP ====\r\n\r\n");
            
            if(HAL_CAN_Transmit(&CAN_Handle, &CAN_TxMessage, 0x10000) == HAL_OK)
                printfS("Transmit succeed\r\n");
            else
                printfS("Transmit timeout and aborted\r\n");
            
            while(1)
            {
                if(HAL_CAN_Receive(&CAN_Handle,&CAN_RxMessage, 0)==HAL_OK) 
                {   
                    /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                    #ifdef CAN_LOG_ENABLE
                    CAN_PrintfReceive();  
                    #endif 
                    CAN_TxMessage=CAN_RxMessage;
                    HAL_CAN_Transmit(&CAN_Handle,&CAN_TxMessage, 0x8000);
                }
            } 
        }        
        /* 中断模式 */
        case TEST_IT: 
        {
            printfS("\r\n====CAN Demo IT ====\r\n\r\n");
            
            if(HAL_CAN_TransmitSingleShot(&CAN_Handle,&CAN_TxMessage) == HAL_OK)
                printfS("Transmit succeed\r\n");
            else
                printfS("Transmit failed and aborted\r\n");
            
            HAL_CAN_Receive_IT(&CAN_Handle,&CAN_RxMessage);
            
            while(1)
            {
                if(gu8_CAN_ReceiveFlag==1)
                {
                    /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                    #ifdef CAN_LOG_ENABLE
                    CAN_PrintfReceive();  
                    #endif 
                    
                    CAN_TxMessage=CAN_RxMessage;
                    HAL_CAN_Transmit(&CAN_Handle,&CAN_TxMessage, 0x8000);//send can frame from receive 
                    gu8_CAN_ReceiveFlag=0;
                }
            }
        }
				//break;
				
				case TEST_SELF:
				{
						int i;

						printfS("\r\n====CAN Demo self receive ====\r\n\r\n");
					
						HAL_CAN_OperatingModeRequest(&CAN_Handle,CAN_OperatingMode_SelfTest);

						CAN_TxMessage.ExtId = 0x18FE0000;
						CAN_TxMessage.RTR = CAN_RTR_Data;
						CAN_TxMessage.IDE = CAN_Id_Extended;
						for(i = 0; i < 8; i++)
								CAN_TxMessage.Data[i] = 0x11+i*2;
						CAN_TxMessage.DLC = 8;

						while(1)
						{
								HAL_CAN_Transmit(&CAN_Handle,&CAN_TxMessage, 0);
								if(HAL_CAN_Receive(&CAN_Handle,&CAN_RxMessage, 0)==HAL_OK) 
								{
										CAN_PrintfReceive();  
										printf("\r\n");
								}
								System_Delay_MS(2000);
						}
				}
				//break;
        default: break; 
    }
}
