/*
  ******************************************************************************
  * @file    APP.c
  * @version V1.0.0
  * @date    2021
  * @brief   CAN demo source code.
  ******************************************************************************
*/
#include "app.h"

CAN_InitTypeDef        CAN_InitStructure;

CanTxRxMsg CAN_RxMessage;

extern volatile uint8_t gu8_CAN_ReceiveFlag;

static void CAN_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /* Enable GPIO clock */
    __RCC_GPIOB_CLK_ENABLE();
    
    /* Initialization GPIO */
    GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9;	
    GPIO_InitStructure.Alternate = GPIO_FUNCTION_6;
    GPIO_InitStructure.Pull = GPIO_PULLUP;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Drive = GPIO_DRIVE_LEVEL3;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}


static void CAN_NVIC_Config(void)
{
    /*CAN通信中断使能*/
    CAN_ITConfig(CANx, CAN_IER_RIE, ENABLE);

    NVIC_ClearPendingIRQ(CAN_IRQn);
    NVIC_SetPriority(CAN_IRQn, 5);
    NVIC_EnableIRQ(CAN_IRQn); 
}

static void CAN_Mode_Config(void)
{  
    CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
    CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;            //CAN_SJW_1tq
    CAN_InitStructure.CAN_BRP = 5;                       // //pclk = hclk/2=120M/2=60M   BRP=2*(5+1)=12  TQ=12*(1/60M)=1/5M
    CAN_InitStructure.CAN_TSEG1 = CAN_TSEG1_5tq;
    CAN_InitStructure.CAN_TSEG2 = CAN_TSEG2_4tq;         //width=1+4+5=10 TQ    baud=1M/(1/5*10)=1M/2=500K
    CAN_InitStructure.CAN_BOR = CAN_BOR_ENABLE;        //ENABLE Bus off recover 
    CAN_Init(CANx, &CAN_InitStructure);	
}

static void CAN_Filter_Config()
{
    CAN_FilterInitTypeDef  CAN_FilterInitStruct;
	
    CAN_FilterInitStruct.FilterBank = 0;
    CAN_FilterInitStruct.FilterMode = CAN_FilterMode_Dual;
    CAN_FilterInitStruct.FilterId1 = 0x18fe0000;  //Extended Id:ID28...ID0
    CAN_FilterInitStruct.FilterId2 = 0x100<<18;   //Standard Id:ID28...ID18,so need (ID<<18)
    /* if want receive all data,please set the CAN_FilterMaskId = 0xFFFFFFFF*/
    CAN_FilterInitStruct.FilterMaskId1 = 0x0000FFFF; //only receive CAN id=0x18fexxxx(only care 0x18fexxxx)
    CAN_FilterInitStruct.FilterMaskId2 = 0x100<<18; //only receive CAN id=0x100     ( care ID28...ID18)
    CAN_FilterInit(CANx, &CAN_FilterInitStruct);
}

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"); 
    }
}

void CAN_Config(void)
{
  CAN_GPIO_Config();
  CAN_Mode_Config();
  CAN_Filter_Config();
  CAN_NVIC_Config();
}

void APP_CAN_Test(enum_TEST_MODE_t fe_Mode)
{
    uint8_t i = 0;
    
    CAN_Config();
	
    CanTxRxMsg CAN_TxMessage;
        
    /* 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(CAN_Transmit_WithTimeout(CANx, &CAN_TxMessage, 3000) != CAN_Status_Success)
    {
        CAN_ErrCode_t ErrCode;
        
        ErrCode = CAN_GetErrorCode(CANx);

        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.Direction);
        printfS("ErrCode.SegCode = 0x%X\r\n", ErrCode.SegCode);
    }
    else
    {
        printfS("CAN Networking send data OK\r\n");
    }
    
    switch (fe_Mode)
    {
        /* 循环模式 */
        case TEST_LOOP: 
        {   
            while(1)
            {
                CAN_Receive(CANx,&CAN_RxMessage);
                /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                CAN_PrintfReceive();
                CAN_TxMessage=CAN_RxMessage;
                CAN_Transmit(CANx, &CAN_TxMessage);
                
            } 
        }        
        /* 中断模式 */
        case TEST_IT: 
        {  
            while(1)
            {
                if(gu8_CAN_ReceiveFlag==1)
                {
                    int8_t counter;
                    
                    counter = CAN_GetReceiveFiFoCounter(CANx);
                    printfS("counter = %d\r\n", counter);
                    CAN_GetErrorAlarmCounter(CANx);
                    CAN_GetReceiveFiFoAddr(CANx);
                    
                    /* 串口打印接收到的报文，注：连续高速接发报文时，打印可能会影响CAN报文收发，建议关闭，此处仅作为示例 */
                    CAN_PrintfReceive();
                    CAN_TxMessage=CAN_RxMessage;
                    CAN_Transmit(CANx, &CAN_TxMessage);//send can frame from receive 
                    gu8_CAN_ReceiveFlag=0;
                }
            }
        }

        default: break; 
    }
}
