/******************************************************************************
�� �� ����MSCAN0.h
����������MSCAN0�����շ����ƺ������ļ�
��    �ߣ�����
��    ����V1.0
��    �ڣ�2016.5.5
******************************************************************************/
#include "MSCAN0_J1939.h"


uint8_t          WakeUpFlag;
uint8_t          WakeUpID;
extern uint8_t   NM_RECEIVE;
extern uint8_t   sleepFl1g;
extern uint8_t   CanFrameExist;
extern INT8U     BUS_OFF_FLAG;       //----hyq--20180728
extern uint8_t DiagnosticReceived;
uint32_t                      MSCAN0TxID[3];
MSCAN0BusoffMonitorStruct     MSCAN0Busoff;

//
extern void CoCAN_L_Data_Indication(uint32_t Identifier, uint8_t DLC, uint8_t *Data);
//extern void CoCAN_L_Data_Confirm(uint32_t Identifier, uint8_t TransferStatus);

//
extern void DoCAN_L_Data_Indication(uint32_t Identifier, uint8_t dlc, uint8_t *pData);
extern void DoCAN_L_Data_Confirm(uint32_t Identifier, uint8_t TransferStatus);

/*
extern FUNC(void, CANNM_CODE) CanNm_RxIndication 
(
    PduIdType RxPudId,
    const uint16 RxId,
    P2CONST(PduInfoType, AUTOMATIC, CANNM_APPL_DATA)PduInfoPtr   
);

extern FUNC(void, CANNM_CODE) CanNm_TxConfirmation
(
    PduIdType TxPudId
);
*/
/******************************************************************************
��������MSCAN0_L_Data_Request
��   �ܣ��ú������ϲ����,���������������Ϸ���һ�鱨��
��   ����Identifier������ID
        DLC       �����ij���
        Data      ����������
        Priority  ���������ȼ� 0 - 2 ����ԽС���ȼ�Խ��
����ֵ����
******************************************************************************/

//�ⷢ���ĵ�ID�б�
static uint16_t CAN_TXIDS[] = {0x26D, 0x315, 0x530, 0x402, 0x7EB};
#define CAN_TXIDS_LEN 5

//CAN���ݷ�������
void MSCAN0_L_Data_Request(uint32_t Identifier, uint8_t DLC, uint8_t *Data, uint8_t Priority)
{
  uint8_t  i;
  uint8_t  BufSel;

  //MSCAN��CAN BUS��ͬ��,��ID��Ч,�������ݳ��ȴ���8,�����ȼ����ô���ʱ,�ϱ�����ʧ�ܲ��˳�����
  if ((CAN0CTL0_SYNCH == 0) || (DLC > 8) || (Priority > 2))
  {
    MSCAN0_L_Data_Confirm(Identifier, NOT_COMPLETE);
    return;
  }

  //ID���ڷ��͵ı���ID��
  /*
  for(i=0; i<CAN_TXIDS_LEN; i++)
  {
    if(Identifier==CAN_TXIDS[i])
	  break;
  }
  if(i>=CAN_TXIDS_LEN)
  	return;
  */
  
  //���ͻ���ָ��
  BufSel = (0x01 << Priority);
  
  //��ǰ���ȼ��ķ��ͻ�����Ϊ��ʱ,�ϱ�����ʧ�ܲ��˳�����
  if (CAN0TFLG & BufSel == 0)
  {
    MSCAN0_L_Data_Confirm(Identifier, NOT_COMPLETE);
    return;
  }

  //ǰһ�α��ķ���δ�õ��������Buffer���������
  if (MSCAN0TxID[Priority] != 0xFFFFFFFF)
    MSCAN0_L_Data_Confirm(MSCAN0TxID[Priority], NOT_COMPLETE);
  
  MSCAN0TxID[Priority] = Identifier;        //����ID

  //!!�Ĵ�������
  //ѡ��ָ��ָ���ķ��ͻ�����
  CAN0TBSEL  = BufSel;   		            
  //д���ʶ��ID
  CAN0TXIDR0 =  (uint8_t)(Identifier >> 21);
  CAN0TXIDR1 =  ((uint8_t)(Identifier >> 13) & 0xE0) | ((uint8_t)(Identifier >> 15) & 0x07);
  CAN0TXIDR2 =  (uint8_t)(Identifier >> 7);
  CAN0TXIDR3 =  (uint8_t)(Identifier << 1) & 0xFE;

  //���ͣ���չ֡��
  CAN0TXIDR1_SRR = 1;
  CAN0TXIDR1_IDE = 1;

  //�����
  for (i = 0; i < DLC; i++)
    *((&CAN0TXDSR0)+i) = Data[i];
  
  CAN0TXDLR = DLC;//DLC
  
  //CAN0TXTBPR = 0;                         //�������ȼ�,��Buffer���ȼ���ͬ,��BufferIDԽС,���ȼ�Խ��
  CAN0TFLG  = BufSel;                       //��������
  CAN0TIER |= BufSel;                       //������ӦCAN�����ж�
  //end
}

/******************************************************************************
��������MSCAN0_L_Data_Indication
��  �ܣ� �ú����������ϲ�ָʾһ֡���ĵĵ���,��ͬʱ���������ݴ������ϲ�
        ע�⣺1.ʹ��ʱӦ���ϲ�ı��Ĵ��ݺ��������ڱ�����֮��,���ĵ���ʱ������
                ��Ӧ�ĺ������ݱ�������
              2.���������ж����,�����õ��ϲ�ı��Ĵ��ݺ���Ӧ�����ܼ��
��  ���� Identifier������ID
        DLC       �����ij���
        Data      ����������
����ֵ����
******************************************************************************/
//��չ֡���ݽ���
unsigned long recv_id = 0UL;
void MSCAN0_L_Data_Indication(uint32_t Identifier, uint8_t DLC, uint8_t *Data)
{

  MSCANIDStruct * pID = (MSCANIDStruct*)(&Identifier);
  //����������Ĵ���
  //���������ı���
  //if(pID->PS==0x28 || pID->PS==0xBF || Identifier==0x1810A6A0)  //----hyq--20180728  ID����
  recv_id =               Identifier;
  if ((Identifier == 0x18DB33F1UL) || (Identifier == 0x18DAFCF1UL))
  {
    DoCAN_L_Data_Indication ( Identifier, DLC, Data );
  }
  else
  {
    CoCAN_L_Data_Indication(Identifier, DLC, Data);
    }
}

/******************************************************************************
��������MSCAN0_L_Data_Confirm
��  �ܣ��ú����������ϲ�ָʾ�����͵ı��ĵķ��ͽ��
        ע�⣺1.ʹ��ʱӦ���ϲ�ı��ķ��ͽ�����ݺ��������ڱ�����֮��,���ķ�����
                ������ʱ��������Ӧ�ĺ������ݱ��ķ��ͽ��
              2.���������ж����,�����õ��ϲ�ı��ķ��ͽ�����ݺ���Ӧ�����ܼ��
��  ����Identifier    ������ID
       TransferStatus�����ķ��ͽ����COMPLETE     �������
                                     NOT_COMPLETE ����δ�ܷ������
����ֵ����
******************************************************************************/
void MSCAN0_L_Data_Confirm(uint32_t Identifier, uint8_t TransferStatus)
{
  if (Identifier == 0x7EB)//0x7EB���DZ�����ӦID
  {
    DoCAN_L_Data_Confirm(Identifier, TransferStatus);
  }
  //�����������
  else if( ( Identifier >= 0x400 ) && ( Identifier <= 0x47F ) )
  {
    ;//CanNm_TxConfirmation(0);
  }
}

/******************************************************************************
��������MSCAN0_Bus_Off_Monitoring_Service
��   �ܣ�MSCAN0 Bus-off״̬��ط���,���Bus-off״̬�����Իָ�
��   ������
����ֵ����
*******************************************************************************
ע  �⣺�÷���������ÿ20ms������һ��
******************************************************************************/
void MSCAN0_Bus_Off_Monitoring_Service(void)
{
  #if !MSCAN0_BUS_OFF_AUTO_RECOVERY
    #if MSCAN0_BUS_LIMP_MODE_ENABLE
	  //CAN�����Ѿ�������ģʽ(��λָ�ʧ��),���ٻָ�
      if (MSCAN0Busoff.Status == MSCAN0_BUS_LIMP)
        return;
    #endif
    //���Bus-off����
    if (CAN0MISC_BOHOLD)
    {
      MSCAN0Busoff.Timer++;//bus off ��ʱ
      //����һ��bus off״̬
      if(MSCAN0Busoff.Status == MSCAN0_BUS_STABLE)
        MSCAN0Busoff.Status = MSCAN0_BUS_OFF_LV1;

	  //��һ��bus off״̬��
      if (MSCAN0Busoff.Status == MSCAN0_BUS_OFF_LV1)
      {
        if (MSCAN0Busoff.Timer >= MSCAN0_BUS_OFF_LV1_RECOVERY_TIME / 20)
        {
          MSCAN0Busoff.Timer = 0;
          
          CAN0MISC_BOHOLD = 1;                      //д1����,����ָ�Bus-off

          MSCAN0Busoff.Cnt++;
		  //����bus off ����
          if (MSCAN0Busoff.Cnt >= 10)
          {
            BUS_OFF_FLAG = 1;
            MSCAN0Busoff.Cnt = 0;
            MSCAN0Busoff.Status = MSCAN0_BUS_OFF_LV2;
          }
        }
      }
	  //����ģʽ
      else if (MSCAN0Busoff.Status == MSCAN0_BUS_OFF_LV2)
      {
        if (MSCAN0Busoff.Timer >= MSCAN0_BUS_OFF_LV2_RECOVERY_TIME / 20)
        {
          MSCAN0Busoff.Timer = 0;
          
          CAN0MISC_BOHOLD = 1;                      //д1����,����ָ�Bus-off
        }

		//��������ģʽ
        #if MSCAN0_BUS_LIMP_MODE_ENABLE         
          MSCAN0Busoff.Cnt++;
          if (MSCAN0Busoff.Cnt > MSCAN0_BUS_LIMP_MODE_THRESHOLD)
          {
            MSCAN0Busoff.Cnt = 0;
            
            MSCAN0Busoff.Status = MSCAN0_BUS_LIMP;  //����CAN��������ģʽ
            CAN0_PHY_STB = 1;                       //����ʡ��ģʽ
            MSCAN0_Init();				            //ͨ����ʼ����ֹ����CAN�շ�
            CAN0RIER_RXFIE = 0;   		            //��ֹCAN�����ж�
            CAN0RIER_WUPIE = 0;                     //�رջ����ж�
            CAN0CTL0_WUPE  = 0;                     //��ֹ����ʹ��
            if (CAN0RFLG_WUPIF)
              CAN0RFLG_WUPIF = 1;                   //����л����ж������־Ҳһ�����(д1����)
          }
        #endif
      }
    }
    else                                          //��������,û��Bus-off����
    { 
      BUS_OFF_FLAG = 0;
      MSCAN0Busoff.Status = MSCAN0_BUS_STABLE;
      MSCAN0Busoff.Timer = 0;
      MSCAN0Busoff.Cnt   = 0;
    }
  #endif
}

/******************************************************************************
��������MSCAN0_Get_Bus_Status
��  �ܣ���ȡMSCAN0����״̬
��  ������
����ֵ��MSCAN0_BUS_STABLE����������,�ȶ�����
        MSCAN0_BUS_OFF   �����ߴ���Bus-off״̬
        MSCAN0_BUS_LIMP  �����ߴ�������״̬(Bus-off���λָ���ʧ�ܶ��ر�����)
******************************************************************************/
uint8_t MSCAN0_Get_Bus_Status(void)
{
  return MSCAN0Busoff.Status;
}

/******************************************************************************
��������MSCAN0_Init
��  �ܣ�MSCAN0��ʼ������
��  ������
����ֵ����
******************************************************************************/
void MSCAN0_Init(void)  
{
  uint8_t i;
  
  CAN0CTL0 = 0x01;            //���� MSCAN�����ʼ��ģʽ					
  while(!(CAN0CTL1_INITAK));  //�ȴ������ʼ��ģʽ

  CAN0IDAC = 0;   		        //�����������ռĴ����Ĺ�����ʽ  two 32-bit filter 
	
  CAN0IDAR0 = 0x00;     	    //�������ռĴ���
  CAN0IDAR1 = 0x00;
  CAN0IDAR2 = 0x00;
  CAN0IDAR3 = 0x00;

  CAN0IDMR0 = 0xFF;             //�������μĴ��� (��������Ϊ���б���ID������)
  CAN0IDMR1 = 0xFF; 
  CAN0IDMR2 = 0xFF;
  CAN0IDMR3 = 0xFF;
  
  CAN0IDAR4 = 0x00;      	    //�������ռĴ���
  CAN0IDAR5 = 0x00; 
  CAN0IDAR6 = 0x00;
  CAN0IDAR7 = 0x00;
  
  CAN0IDMR4 = 0xFF;           //�������μĴ��� (��������Ϊ���б���ID������)
  CAN0IDMR5 = 0xFF;
  CAN0IDMR6 = 0xFF;
  CAN0IDMR7 = 0xFF;
  
  CAN0CTL1_CANE   = 1;        //ʹ��MSCANģ��
  CAN0CTL1_CLKSRC = 0;        //ѡ��OSCCLK(8MHz)ΪMSCAN��ʱ��Դ
  CAN0CTL1_LISTEN = 0;        //��������ģʽ(�Ǽ���ģʽ)
  
  #if MSCAN0_BUS_OFF_AUTO_RECOVERY
    CAN0CTL1_BORM = 0;	      //�Զ�����BUS_OFF�ָ�
  #else
    CAN0CTL1_BORM = 1;	      //����BUS_OFF���û����ƻָ�
  #endif
    
  CAN0CTL1_WUPM = 1;		      //�����Ѽ��˲� 
  
  CAN0BTR0 = 0X43;            //���������� 0x4314 250k  0x802B 500K
  CAN0BTR1 = 0X14;

  //�˳���ʼ��ģʽ
  CAN0CTL0 = 0x00;            
  while (CAN0CTL1_INITAK);    //�ȴ��˳���ʼ��ģʽ
  while (!CAN0CTL0_SYNCH);    //�ȴ�MSCAN��CAN����ͬ��
 	
  CAN0TIER = 0x00;            //��ֹCAN�����ж�  

  //CAN���յ��������ݺ����ж�
  CAN0RIER_RXFIE = 1;   	  //ʹ��CAN�����ж�
  CAN0RIER_WUPIE = 1;         //ʹ��WakeUP�ж�
  
  CAN0_STB = 0;   	          //ʹ��CAN�շ���
	
  MSCAN0Busoff.Status = MSCAN0_BUS_STABLE;
  MSCAN0Busoff.Timer = 0;
  
  #if MSCAN0_BUS_LIMP_MODE_ENABLE 
    MSCAN0Busoff.Cnt   = 0; 
  #endif

  for(i = 0; i < 3; i++)
    MSCAN0TxID[i] = 0xFFFF;   //0xFFFF��ʾ��ЧID
}

/******************************************************************************
��������MSCAN0_Enter_Low_Power_Mode
��  �ܣ���MSCAN0����͹���ģʽ
��  ������
����ֵ����
******************************************************************************/
void MSCAN0_Enter_Low_Power_Mode(void)
{
  MSCAN0_Init();              //͸����ʼ����ֹCAN�շ�
  
  CAN0_STB = 1;   	          //ʹ��CAN�շ���
  
  if(CAN0RFLG_WUPIF)          //�����ж������־ = 1 ��д1��0
    CAN0RFLG_WUPIF = 1;
  CAN0CTL0_WUPE = 1;			    //����ʹ��
	
	//��1��,��MSCAN���з������(���Ͷ��п�),����Ҳ���(CAN���߿���)��,
	//MSCAN ����SLEEPģʽ,������ CAN0CTL1_SLPAK=1��ʾȷ��
	//���ô�λǰ CAN0RFLG_WUPIF �������
          
	//��CAN0CTL0_SLPRQ=1,��CAN0CTL1_SLPAK=1 ,��ʾMSCAN�Ѿ�����˯��ģʽ
	CAN0CTL0_SLPRQ = 1;			    //������MSCAN����˯��ģʽ  
	
	//��MSCAN����˯��ģʽ��,��� CAN0CTL0_WUPE = 1 ���յ�CAN���ĺ�,MSCAN�˳�˯��,��CAN0RFLG_WUPIF��1
	//ͬʱ CAN0CTL0_SLPRQ,CAN0CTL1_SLPAK Ҳ���Զ���0.   
	
	//��MSCAN����˯��ģʽ��,����Ҳ����������CAN0CTL0_SLPRQ = 0,ʹ��MSCAN�˳�˯��,CAN0CTL1_SLPAK Ҳ���Զ���0. 
	//�� CAN0CTL0_SLPRQ = 1��,���MSCAN��û�н���˯��ģʽ,��ô����������CAN0CTL0_SLPRQ = 0.

  CAN0TARQ = 0x07;            //������ֹ���б��ķ���.
  
  //CAN0RIER_RXFIE = 0;   			//��ֹCAN�����ж�
}

/******************************************************************************
��������MSCAN0_Exit_Low_Power_Mode
��  �ܣ���MSCAN0�˳��͹���ģʽ
��  ������
����ֵ����
******************************************************************************/
void MSCAN0_Exit_Low_Power_Mode(void)
{
  CAN0CTL0_SLPRQ = 0;         //ʹ��MSCAN�˳�˯��
  
  if(CAN0RFLG_WUPIF)          //�����ж������־ = 1 ��д1��0
    CAN0RFLG_WUPIF = 1;
  CAN0CTL0_WUPE = 0;			    //���û��ѹ���
  
  CAN0_STB = 0;               //ʹ��CAN�շ���
  
  CAN0RIER_RXFIE = 1;   			//ʹ��CAN�����ж�
}

/******************************************************************************
��������MSCAN0_Get_Wake_Up_Flag
��  �ܣ���ȡMSCAN0�Ļ���״̬
��  ������
����ֵ��0 - δ������ 1 - �ѱ�����
******************************************************************************/
uint8_t MSCAN0_Get_Wake_Up_Flag(void)
{
  if (CAN0CTL0_SLPRQ == 0)
    return 1;
  
  //if (WakeUpFlag)
  //{
  //  WakeUpFlag = 0;
  //  return 1;
  //}
  
  return 0;
}

#pragma CODE_SEG __NEAR_SEG NON_BANKED   	//�������жϺ�������FLASH�ķǷ�ҳ��

/******************************************************************************
��������MSCAN0_TX_ISR
��   �ܣ�MSCAN0�����жϷ�������
        ����CAN���ķ�����ϻ���ֹ����ʱ��ִ�д˺���
��   ������
����ֵ����
******************************************************************************/
void interrupt MSCAN0_TX_ISR(void)
{
  uint8_t i;
  uint8_t TxFlag;
  uint8_t TxBuf;
  uint8_t BufDetect;
  
  do
  {
    TxFlag = CAN0TFLG;
    
    TxBuf = CAN0TIER & TxFlag;              //��ȡ������ϻ���ֹ���͵ı���Buffer
    CAN0TIER &= ~TxBuf;                     //�رշ�����ϻ���ֹ���͵ı���Buffer��Ӧ���ж�
    
    BufDetect = 1;
    for (i = 0; i < 3; i++)
    {
      if (BufDetect & TxBuf)
      {
        if (BufDetect & CAN0TAAK)           //���ı��ɹ���ֹ����
          MSCAN0_L_Data_Confirm(MSCAN0TxID[i], NOT_COMPLETE);
        else                                //���ķ��ͳɹ�
          MSCAN0_L_Data_Confirm(MSCAN0TxID[i], COMPLETE);
          
        MSCAN0TxID[i] = 0xFFFF;             //������ļ�¼
      }
      
      BufDetect <<= 1;
    }
  }
  while (TxFlag != CAN0TFLG);               //�����жϴ����ڼ����µı��ķ������

  //end
}

/******************************************************************************
��������MSCAN0_RX_ISR
��   �ܣ�MSCAN0�����жϷ�������
        ����CAN�����ʹ�ʱ������CAN����
��   ������
����ֵ����
******************************************************************************/
//J1939Э���RX�жϽ���
void interrupt MSCAN0_RX_ISR(void)
{
  uint32_t tmp;
  uint32_t CANMsgID;
  
  //CAN0RIER_RXFIE = 0;                      //�Ƚ�ֹMSCAN�����ж�

  //��ͨ֡
  if(!CAN0RXIDR1_IDE)                        //��׼֡ʶ��� 0 ��׼֡ 11 λ 1 ��չ֡ 29 λ
  {
    CAN0RFLG_RXF   = 1;                      //������жϱ�־
    CAN0RIER_RXFIE = 1;                      //��������MSCAN�����ж�
    return;
  }

  //���ݽ���
  tmp = (uint32_t)(CAN0RXIDR0) << 21;
  tmp &= 0x1FE00000; 
  CANMsgID =  tmp | ((uint32_t)(CAN0RXIDR1 & 0xE0) <<13) |  ((uint32_t)(CAN0RXIDR1 & 0x07) <<15)
                  | ((uint32_t)(CAN0RXIDR2) << 7)
                  | ((uint32_t)(CAN0RXIDR3) >> 1);//ID
                  
  MSCAN0_L_Data_Indication(CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0);
  
  CanFrameExist=1;
  CAN0RFLG_RXF   = 1;                      //������жϱ�־
  //CAN0RIER_RXFIE = 1;                      //��������MSCAN�����ж�
  //end
}

/*
void interrupt MSCAN0_RX_ISR(void)
{
  uint16_t CANMsgID;
	
	CAN0RIER_RXFIE = 0;                      //�Ƚ�ֹMSCAN�����ж�
	                                
	if (CAN0RXIDR1_IDE || CAN0RXIDR1_SRR)    //����յ�������Ϊ��չ֡,��ΪԶ��֡
	{
    CAN0RFLG_RXF=1;                        //������жϱ�־
		CAN0RIER_RXFIE=1;                      //��������MSCAN�����ж�
		
    return;
	}
	
	CANMsgID = ((uint16_t)(CAN0RXIDR0 << 3)) | ((uint16_t)(CAN0RXIDR1 >> 5));

  if((CANMsgID >= 0x400) && (CANMsgID <= 0x47F))
    MSCAN0_L_Data_Indication(CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0);
  else
  {
  	switch(CANMsgID)
  	{
    	case  0x068 :
    	case  0x268 :
    	case  0x2D7 :
      case  0x4D4 :
      case  0x1C8 :
      case  0x370 :
      case  0x1C9 :
      case  0x0F2 :
      case  0x0E2 :
      case  0x082 :
      case  0x094 :
      case  0x288 :
      case  0x088 :
      case  0x120 :
      case  0x293 :
      case  0x115 :
      case  0x160 :
      case  0x07A :
      case  0x30F :
      case  0x2F1 :
      case  0x10D :
      case  0x7E3 :
      case  0x7DF :
      case  0x279 : MSCAN0_L_Data_Indication(CANMsgID, CAN0RXDLR & 0x0F, &CAN0RXDSR0);
                    break;
      default     : break;
  	}
	}
	
  CAN0RFLG_RXF = 1;                        //������жϱ�־
	CAN0RIER_RXFIE = 1;                      //��������MSCAN�����ж�
}*/

/******************************************************************************
��������MSCAN0_WAKEUP_ISR
��  �ܣ�MSCAN0�����ж�
��  ������
����ֵ����
******************************************************************************/
void interrupt MSCAN0_WAKEUP_ISR(void)
{
  CAN0RFLG_WUPIF = 1;
  CAN0_STB = 0;             //----hyq--20180806
  WakeUpFlag     = 1;
}
#pragma CODE_SEG DEFAULT

//
/*
Std_ReturnType CanIf_Transmit(PduIdType CanTxPduId, PduInfoType* PduInfoPtr) 
{
  (void)CanTxPduId;
  MSCAN0_L_Data_Request( 0x402, (uint8_t)PduInfoPtr->SduLength, (uint8_t*)PduInfoPtr->SduDataPtr, 0 );
  return E_OK;
} */