// TI Release: 28xx eCAN programming example
// Release Date: Fri Aug 4 2017
// Copyright:
// Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 

// Filename: ECHO-AB.c
//                                                                 
// Description: eCAN-A To eCAN-B TXLOOP - Transmit loop  	
//
//
// DESCRIPTION:   
// 		CAN-A transmits to CAN-B, which then echoes the data back to CAN-A.
//    	CAN-A then verifies the transmitted and received data.
//          
//    This example can be used to check CAN-A and CAN-B. Both CAN ports of 
//    the DSP need to be connected to each other (via CAN transceivers)
//    Make sure that the GPIO pins that are used for CAN configurations are 
//    properly configured in the DSP280x_ECan.c file.
//
//
// Included Files
//
#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

#define TXCOUNT  100  		// Transmission will take place (TXCOUNT) times..

void	copy_data(void);
void	ATX2B(void);		// This function transmits from CAN-A to CAN-B
void	BTX2A(void);		// This function transmits from CAN-B to CAN-A
void	check_data(void);	// This function checks the data echoed by CAN-B
void 	error(void);		// Program will terminate here upon error

// Globals for this example
int		i,j;
long	loopcount = 0;

int 	MBX_data[32];	// This array stores the data to be transmitted

void main()
{

/* Shadow register structure is not needed for this example as all accesses to
	the CAN control registers are 32-bit */

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
   InitSysCtrl();

// Step 2. Initalize GPIO: 
// InitGpio();  // Skipped for this example  

   // Just initalize eCAN pins for this example

   InitECanGpio();	
   EALLOW;	

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts 
   DINT;

// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.  
// This function is found in the DSP280x_PieCtrl.c file.
//   InitPieCtrl();
   
// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt 
// Service Routines (ISR).  
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// InitPieVectTable(); // Skipped for this example

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.  

// No interrupts used in this example.

// Step 4. Initialize all the Device Peripherals:
// InitPeripherals(); // Not required for this example
   
// In this case just initialize eCAN-A and eCAN-B

  
   InitECan();  
	EALLOW;	

// Step 5. User specific code:

// Intialize MBX_data array

	for(i=0; i<32; i++) {MBX_data[i] = i;}

/* Write to the MSGID field of both CAN modules */
    
	ECanaMboxes.MBOX0.MSGID.all = 0x9555AAA0; 
    ECanaMboxes.MBOX1.MSGID.all = 0x9555AAA1; 
    ECanaMboxes.MBOX2.MSGID.all = 0x9555AAA2; 
    ECanaMboxes.MBOX3.MSGID.all = 0x9555AAA3; 
    ECanaMboxes.MBOX4.MSGID.all = 0x9555AAA4; 
    ECanaMboxes.MBOX5.MSGID.all = 0x9555AAA5; 
    ECanaMboxes.MBOX6.MSGID.all = 0x9555AAA6; 
    ECanaMboxes.MBOX7.MSGID.all = 0x9555AAA7; 
    ECanaMboxes.MBOX8.MSGID.all = 0x9555AAA8; 
    ECanaMboxes.MBOX9.MSGID.all = 0x9555AAA9; 
    ECanaMboxes.MBOX10.MSGID.all = 0x9555AAAA; 
    ECanaMboxes.MBOX11.MSGID.all = 0x9555AAAB; 
    ECanaMboxes.MBOX12.MSGID.all = 0x9555AAAC; 
    ECanaMboxes.MBOX13.MSGID.all = 0x9555AAAD; 
    ECanaMboxes.MBOX14.MSGID.all = 0x9555AAAE; 
    ECanaMboxes.MBOX15.MSGID.all = 0x9555AAAF;  
    ECanaMboxes.MBOX16.MSGID.all = 0x9555AA10; 
    ECanaMboxes.MBOX17.MSGID.all = 0x9555AA11; 
    ECanaMboxes.MBOX18.MSGID.all = 0x9555AA12; 
    ECanaMboxes.MBOX19.MSGID.all = 0x9555AA13; 
    ECanaMboxes.MBOX20.MSGID.all = 0x9555AA14; 
    ECanaMboxes.MBOX21.MSGID.all = 0x9555AA15; 
    ECanaMboxes.MBOX22.MSGID.all = 0x9555AA16; 
    ECanaMboxes.MBOX23.MSGID.all = 0x9555AA17; 
    ECanaMboxes.MBOX24.MSGID.all = 0x9555AA18; 
    ECanaMboxes.MBOX25.MSGID.all = 0x9555AA19; 
    ECanaMboxes.MBOX26.MSGID.all = 0x9555AA1A; 
    ECanaMboxes.MBOX27.MSGID.all = 0x9555AA1B; 
    ECanaMboxes.MBOX28.MSGID.all = 0x9555AA1C; 
    ECanaMboxes.MBOX29.MSGID.all = 0x9555AA1D; 
    ECanaMboxes.MBOX30.MSGID.all = 0x9555AA1E; 
    ECanaMboxes.MBOX31.MSGID.all = 0x9555AA1F; 

	ECanbMboxes.MBOX0.MSGID.all = 0x9555AAA0; 
    ECanbMboxes.MBOX1.MSGID.all = 0x9555AAA1; 
    ECanbMboxes.MBOX2.MSGID.all = 0x9555AAA2; 
    ECanbMboxes.MBOX3.MSGID.all = 0x9555AAA3; 
    ECanbMboxes.MBOX4.MSGID.all = 0x9555AAA4; 
    ECanbMboxes.MBOX5.MSGID.all = 0x9555AAA5; 
    ECanbMboxes.MBOX6.MSGID.all = 0x9555AAA6; 
    ECanbMboxes.MBOX7.MSGID.all = 0x9555AAA7; 
    ECanbMboxes.MBOX8.MSGID.all = 0x9555AAA8; 
    ECanbMboxes.MBOX9.MSGID.all = 0x9555AAA9; 
    ECanbMboxes.MBOX10.MSGID.all = 0x9555AAAA; 
    ECanbMboxes.MBOX11.MSGID.all = 0x9555AAAB; 
    ECanbMboxes.MBOX12.MSGID.all = 0x9555AAAC; 
    ECanbMboxes.MBOX13.MSGID.all = 0x9555AAAD; 
    ECanbMboxes.MBOX14.MSGID.all = 0x9555AAAE; 
    ECanbMboxes.MBOX15.MSGID.all = 0x9555AAAF;  
    ECanbMboxes.MBOX16.MSGID.all = 0x9555AA10; 
    ECanbMboxes.MBOX17.MSGID.all = 0x9555AA11; 
    ECanbMboxes.MBOX18.MSGID.all = 0x9555AA12; 
    ECanbMboxes.MBOX19.MSGID.all = 0x9555AA13; 
    ECanbMboxes.MBOX20.MSGID.all = 0x9555AA14; 
    ECanbMboxes.MBOX21.MSGID.all = 0x9555AA15; 
    ECanbMboxes.MBOX22.MSGID.all = 0x9555AA16; 
    ECanbMboxes.MBOX23.MSGID.all = 0x9555AA17; 
    ECanbMboxes.MBOX24.MSGID.all = 0x9555AA18; 
    ECanbMboxes.MBOX25.MSGID.all = 0x9555AA19; 
    ECanbMboxes.MBOX26.MSGID.all = 0x9555AA1A; 
    ECanbMboxes.MBOX27.MSGID.all = 0x9555AA1B; 
    ECanbMboxes.MBOX28.MSGID.all = 0x9555AA1C; 
    ECanbMboxes.MBOX29.MSGID.all = 0x9555AA1D; 
    ECanbMboxes.MBOX30.MSGID.all = 0x9555AA1E; 
    ECanbMboxes.MBOX31.MSGID.all = 0x9555AA1F; 

/* Initialize the DLC field of CAN-A */

	 ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX1.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX2.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX3.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX5.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX6.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX7.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX8.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX9.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX10.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX11.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX12.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX13.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX14.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX15.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX16.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX17.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX18.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX19.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX20.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX21.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX22.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX23.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX24.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX25.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX26.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX27.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX28.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX29.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX30.MSGCTRL.bit.DLC = 8;
	 ECanaMboxes.MBOX31.MSGCTRL.bit.DLC = 8;
		 
/* Copy data into CAN-A MBX RAM for initial transmission */

	copy_data();
	
/* Enable CAN-A Mailboxes */	

   ECanaRegs.CANME.all = 0xFFFFFFFF; 

/* Enable CAN-B Mailboxes */	

   ECanbRegs.CANME.all = 0xFFFFFFFF; 
	
/* Begin transmitting */

   //while(1){}					// Uncomment this for infinite transmission loops
   for(j=0; j < TXCOUNT; j++)	// Uncomment this for TXCOUNT transmission loops		    		  	
   {
        ATX2B();
		BTX2A();
		check_data();  
     
       	loopcount ++; 			    
    }  
     asm(" ESTOP0");  // Stop here
}

/*****************/
/* End of main() */
/*****************/

/*---------------------------------------------*/
/* This function transmits from CAN-A to CAN-B */
/*---------------------------------------------*/

void	ATX2B(void)	 
{
// Configure CAN-A Mailboxes as Transmit mailboxes 
  
   ECanaRegs.CANMD.all = 0x00000000; 

// Configure CAN-B Mailboxes as Receive mailboxes 
  
   ECanbRegs.CANMD.all = 0xFFFFFFFF; 

// Initiate transmission for CAN-A mailboxes

    ECanaRegs.CANTRS.all = 0xFFFFFFFF;
	while(ECanaRegs.CANTA.all != 0xFFFFFFFF ) {} 	// Wait for TAn bits to be set..
	ECanaRegs.CANTA.all = 0xFFFFFFFF;				// Clear TAn bits
}

/*---------------------------------------------*/
/* This function transmits from CAN-B to CAN-A */
/*---------------------------------------------*/

void	BTX2A(void)	 
{
// Configure CAN-B Mailboxes as Transmit mailboxes 
  
   ECanbRegs.CANMD.all = 0x00000000; 

// Configure CAN-A Mailboxes as Receive mailboxes 
  
   ECanaRegs.CANMD.all = 0xFFFFFFFF; 

// Initiate transmission for CAN-B mailboxes

    ECanbRegs.CANTRS.all = 0xFFFFFFFF;
	while(ECanbRegs.CANTA.all != 0xFFFFFFFF ) {} 	// Wait for TAn bits to be set..
	ECanbRegs.CANTA.all = 0xFFFFFFFF;				// Clear TAn bits
}

/*------------------------------------------------*/
/* This function checks the data echoed by CAN-B  */
/*------------------------------------------------*/

void	check_data(void)	 
{
	volatile struct MBOX *Mailbox = (void *) 0x6100;

	for(i=0; i<32; i++)
	
	 {
		if(Mailbox->MDL.byte.BYTE0 != MBX_data[i]){error();}
		if(Mailbox->MDL.byte.BYTE1 != MBX_data[i]){error();}
		if(Mailbox->MDL.byte.BYTE2 != MBX_data[i]){error();}
		if(Mailbox->MDL.byte.BYTE3 != MBX_data[i]){error();}
		if(Mailbox->MDH.byte.BYTE4 != MBX_data[i]){error();}
		if(Mailbox->MDH.byte.BYTE5 != MBX_data[i]){error();}
		if(Mailbox->MDH.byte.BYTE6 != MBX_data[i]){error();}
		if(Mailbox->MDH.byte.BYTE7 != MBX_data[i]){error();}
		
		Mailbox++;	 
	 }
}

/*----------------------------------------------------------*/
/* This function copies data in MBX_data array into MBX RAM */
/*----------------------------------------------------------*/

void	copy_data(void)		
{
	volatile struct MBOX *Mailbox = (void *) 0x6100;

	for(i=0; i<32; i++)
	
	 {
		Mailbox->MDL.byte.BYTE0 = MBX_data[i];
		Mailbox->MDL.byte.BYTE1 = MBX_data[i];
		Mailbox->MDL.byte.BYTE2 = MBX_data[i];
		Mailbox->MDL.byte.BYTE3 = MBX_data[i];
		Mailbox->MDH.byte.BYTE4 = MBX_data[i];
		Mailbox->MDH.byte.BYTE5 = MBX_data[i];
		Mailbox->MDH.byte.BYTE6 = MBX_data[i];
		Mailbox->MDH.byte.BYTE7 = MBX_data[i];

		Mailbox++;	 
	 }

}

/*----------------------------------------*/
/* Program will terminate here upon error */
/*----------------------------------------*/
void error(void)
{
    asm("     ESTOP0");  // test failed!! Stop!
    for (;;);
}

