#include "can.h"
//==============================================================================
UBYTE *can_periph[NUMBEROFCANS] = {&CANCTL0};
//==============================================================================
tCAN_MSG    canRxMsg[NUMBEROFCANS], canTxMsg[NUMBEROFCANS]; // can structures of messages
tCAN_FILTER canFltr[NUMBEROFCANS];
//==============================================================================
void init_CAN(UBYTE can_num, UBYTE _canbtr0, UBYTE _canbtr1, UBYTE loop)
{
 tCAN_REGS *can;


 can=(tCAN_REGS*)(can_periph[can_num]);    // get base addres of the CAN channel

 if(loop) loop=CANCTL1_LOOPB_MASK;
 
 can->CTL0 = CANCTL0_INITRQ_MASK;
 while(!(can->CTL1 & CANCTL1_INITAK_MASK));
 

 can->CTL1  = 0x80 | loop | 0x08;           // Enables MSCAN, Oscillator Clock,
                                            // Loop Enabled/Disabled and Normal
                                            // Operation, BORM set

 can->BTR0  = _canbtr0;                     //
 can->BTR1  = _canbtr1;                     //

 if(canFltr[can_num].fltrType)              // open filters if required
  {
   if(canFltr[can_num].fltrType == CANFLTRCLOSED)
    {
     can->IDAC  = 0x30;
     can->IDMR0 = can->IDMR1 = can->IDMR2 = can->IDMR3 = 0xFF;
     can->IDMR4 = can->IDMR5 = can->IDMR6 = can->IDMR7 = 0xFF;
    }
   if(canFltr[can_num].fltrType == CANFLTR8)
    {
     can->IDAC  = 0x20;
     can->IDAR0 = canFltr[can_num].fltr.f8.fltr[0]; 
     can->IDMR0 = canFltr[can_num].fltr.f8.mask[0];
     can->IDAR1 = canFltr[can_num].fltr.f8.fltr[1]; 
     can->IDMR1 = canFltr[can_num].fltr.f8.mask[1];
     can->IDAR2 = canFltr[can_num].fltr.f8.fltr[2]; 
     can->IDMR2 = canFltr[can_num].fltr.f8.mask[2];
     can->IDAR3 = canFltr[can_num].fltr.f8.fltr[3]; 
     can->IDMR3 = canFltr[can_num].fltr.f8.mask[3];
     can->IDAR4 = canFltr[can_num].fltr.f8.fltr[4]; 
     can->IDMR4 = canFltr[can_num].fltr.f8.mask[4];
     can->IDAR5 = canFltr[can_num].fltr.f8.fltr[5]; 
     can->IDMR5 = canFltr[can_num].fltr.f8.mask[5];
     can->IDAR6 = canFltr[can_num].fltr.f8.fltr[6]; 
     can->IDMR6 = canFltr[can_num].fltr.f8.mask[6];
     can->IDAR7 = canFltr[can_num].fltr.f8.fltr[7]; 
     can->IDMR7 = canFltr[can_num].fltr.f8.mask[7];
    }

   if(canFltr[can_num].fltrType == CANFLTR16)
    {
     can->IDAC  = 0x10;
     *((UWORD*)(&(can->IDAR0))) = canFltr[can_num].fltr.f16.fltr[0];
     *((UWORD*)(&(can->IDMR0))) = canFltr[can_num].fltr.f16.mask[0];
     *((UWORD*)(&(can->IDAR2))) = canFltr[can_num].fltr.f16.fltr[1];
     *((UWORD*)(&(can->IDMR2))) = canFltr[can_num].fltr.f16.mask[1];
     *((UWORD*)(&(can->IDAR4))) = canFltr[can_num].fltr.f16.fltr[2];
     *((UWORD*)(&(can->IDMR4))) = canFltr[can_num].fltr.f16.mask[2];
     *((UWORD*)(&(can->IDAR6))) = canFltr[can_num].fltr.f16.fltr[3];
     *((UWORD*)(&(can->IDMR6))) = canFltr[can_num].fltr.f16.mask[3];
    }

   if(canFltr[can_num].fltrType == CANFLTR32)
    {
     can->IDAC  = 0x00;
     *((ULONG*)(&(can->IDAR0))) = canFltr[can_num].fltr.f32.fltr[0];
     *((ULONG*)(&(can->IDMR0))) = canFltr[can_num].fltr.f32.mask[0];
     *((ULONG*)(&(can->IDAR4))) = canFltr[can_num].fltr.f32.fltr[1];
     *((ULONG*)(&(can->IDMR4))) = canFltr[can_num].fltr.f32.mask[1];
    }
  } 
 else 
  {
    can->IDMR0 = can->IDMR1 = can->IDMR2 = can->IDMR3 = 0xFF;
    can->IDMR4 = can->IDMR5 = can->IDMR6 = can->IDMR7 = 0xFF;
  }


 can->CTL0  = 0x00;													// restarts MSCAN peripheral
 while(can->CTL1 & CANCTL1_INITAK_MASK);   // wait for Initialization Mode exit
 while(!(can->CTL0 & CANCTL0_SYNCH_MASK)); // waits for MSCAN synchronization with the CAN bus
}
//==============================================================================
//typedef struct { ULONG  id; BOOL  RTR; BOOL IDE; UBYTE data[8]; UBYTE len; UBYTE prty;}tCAN_MSG;
//==============================================================================
BOOL MSCANSendMsg(unsigned char can_num, tCAN_MSG *msg)
{	 
 tCAN_REGS *can;
 UBYTE tbuf_n_empty_flag = 0, i;
 
 can=(tCAN_REGS*)(can_periph[can_num]);     // get base addres of the CAN channel

 if(msg->len > 8) return(0);
 if(!(can->CTL0 & CANCTL0_SYNCH_MASK)) return(0);
 
 
 while(!(can->TFLG & (0x01<<tbuf_n_empty_flag))) // find empty transmit buffer from 3 buffers
  {
    tbuf_n_empty_flag ++;
    if(tbuf_n_empty_flag == 3) tbuf_n_empty_flag=0;
  }

 can->TBSEL  = 0x01 << tbuf_n_empty_flag;   // select found empty transmit buffer

 if(msg->IDE == 0)
  {
   can->TXIDR0 = (UBYTE)(msg->id>>3);         // insert ID MSB
   can->TXIDR1 = (UBYTE)(msg->id<<5);         // insert last 3 bits of ID to the msb
   can->TXIDR1 &= 0B11110111;                 // clear IDE
   if(msg->RTR) can->TXIDR1 |= 0x10;          // set/clear RTR
  }
 else
  {
   can->TXIDR0 = (UBYTE)(msg->id>>21);      // insert ID MSB
   
   
   can->TXIDR1 = (((UBYTE)(msg->id>>13)) & 0xE0) + (((UBYTE)(msg->id>>15)) & 0x07);
   
   
   
   can->TXIDR2 = (UBYTE)(msg->id>>7);
   can->TXIDR3 = ((UBYTE)(msg->id<<1)) & 0xFE;


   can->TXIDR1 |= 0x10;                       // SRR=1
   can->TXIDR1 |= 0B00001000;                 // set IDE
   if(msg->RTR) can->TXIDR3 |= 0x01;          // set/clear RTR
  }
 
 
 for(i = 0; i < msg->len; i++) 
                              can->TXDSR[i] = msg->data[i];

 can->TXDLR  = msg->len;										// set message data length
 can->TXTBPR = msg->prty;										// set message internal priority 
 can->TFLG   = (0x01<<tbuf_n_empty_flag);   // clear flag to send message

 return(1);
}
//==============================================================================

BOOL MSCANGetMsg(UBYTE can_num, tCAN_MSG *msg)
{
 tCAN_REGS *can;
 UBYTE i;
 ULONG t;
 
 can=(tCAN_REGS*)(can_periph[can_num]);     // get base addres of the CAN channel
 
 if(!(can->RFLG & CANRFLG_RXF_MASK)) return(0); // if no new message=>return


 if((can->RXIDR1 & 0x08) == 0)  // standard or extended?
  {
    msg->id = ((can->RXIDR0<<3)&0x0700) | (UBYTE)(can->RXIDR0<<3) | (UBYTE)(can->RXIDR1>>5);
 
    if(can->RXIDR1 & 0x10) msg->RTR = 1;
    else                   msg->RTR = 0;

    if(can->RXIDR1 & 0x08) msg->IDE = 1;
    else                   msg->IDE = 0;
  }
 else
  {
    t = *((ULONG *) (&(can->RXIDR0)));
    msg->id  = (t >> 3) & 0x1FFC0000;
    msg->id |= (t >> 1) & 0x0003FFFF;


    if(can->RXIDR3 & 0x01) msg->RTR = 1;
    else                   msg->RTR = 0;

    if(can->RXIDR1 & 0x08) msg->IDE = 1;
    else                   msg->IDE = 0;
  }

 
 msg->len = can->RXDLR;
 for(i = 0; i < msg->len; i++)
                              msg->data[i] = can->RXDSR[i];
 can->RFLG = CANRFLG_RXF_MASK; // clear flag
 return(1);
}
//==============================================================================
BOOL MSCANCheckRcvdMsg(UBYTE can_num)
{
  static tCAN_REGS *can;
  UBYTE x;
  
  can=(tCAN_REGS*)(can_periph[can_num]);     // get base addres of the CAN channel
  
  x=can->RFLG;
  x=x & CANRFLG_RXF_MASK;
  if(x) return(1);

//  if(can->RFLG & CANRFLG_RXF_MASK) return(1);
  return(0);
}
//==============================================================================
void createMessage(tCAN_MSG *msg,ULONG id,BOOL RTR,BOOL IDE,UBYTE len,UBYTE prty,
                   UBYTE d0,UBYTE d1,UBYTE d2,UBYTE d3,UBYTE d4,UBYTE d5,UBYTE d6,UBYTE d7 )
{
  msg->id  = id;
  msg->RTR = RTR; 
  msg->IDE = IDE;
  msg->data[0]= d0;
  msg->data[1]= d1;
  msg->data[2]= d2;
  msg->data[3]= d3;
  msg->data[4]= d4;
  msg->data[5]= d5;
  msg->data[6]= d6;
  msg->data[7]= d7;
  msg->len =len;       
  msg->prty=prty;
}
//==============================================================================




