// 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: CAN-jig.c
*
* Description: A useful jig for debugging CAN bus issues. Can Transmit/Receive
* Standard & Extended frames at various bit-rates. Also capable of
* transmitting (and responding to) Remote frames. All options are selected
* using GPIO0-GPIO3 or through a hard-coded value in the program.
* 
* On both eCAN-A and eCAN-B modules:
* ----------------------------------
* Mailbox 0 is used for TRANSMIT. If Tx option is chosen, it could loop forever or
* transmit "n" times, where "n" is the TXCOUNT value.
* Mailbox 4 is used for RECEIVE
*          
* This example can be used to check CAN-A and CAN-B. Both CAN ports of
* the MCU need to be connected to each other (via CAN transceivers)
* Both modules are configured for the same bit-rate. If CAN-A is configured
* for Transmission, CAN-B is configured for Reception and vice versa.
*
*********************************************************************/

//
// Included Files
//
#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

void MBXwrA(void);                 // This function initializes all 32 MBOXes of CAN-A
void MBXwrB(void);                 // This function initializes all 32 MBOXes of CAN-B

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

#define Read_GPIO 0      // Switch to decide if GPIO pins have to be read
int		GPIO_val = 0;		// Hard-coded value. If Read_GPIO = 1, will be replaced by actual GPIO value.
int     i;

long 	TX_A_loopcount = 0;	// Counts the # of times eCAN-A transmitted successfully
long 	TX_B_loopcount = 0;	// Counts the # of times eCAN-B transmitted successfully
long 	RX_A_loopcount = 0;	// Counts the # of times eCAN-A Received successfully
long 	RX_B_loopcount = 0;	// Counts the # of times eCAN-B Received successfully

/************************************************************
 These functions are invoked based on the GPIO value read
*************************************************************/

void Use_Ext_ID(void);		// Use Extended ID for the Mailbox
void Use_Std_ID(void);		// Use Standard ID for the Mailbox

void Transmit_A(void);		// Transmit Mailbox Data function for eCAN-A
void Receive_A(void);		// Receive Mailbox Data function for eCAN-A
void Transmit_B(void);		// Transmit Mailbox Data function for eCAN-B
//void Receive_B(void);		// Receive Mailbox Data function for eCAN-B - Not needed, since eCAN-B is merely going to ACK frames from eCAN-A

void TxLoop_A(void);        // Transmit loop for CAN-A
void TxLoop_B(void);        // Transmit loop for CAN-B
void RxLoop_A(void);        // Receive loop for CAN-A
void RxLoop_B(void);        // Receive loop for CAN-B

void _1_Mbps(void);			// Configure the modules for 1 Mbps
void _500_kbps(void);		// Configure the modules for 500 kbps
void _250_kbps(void);		// Configure the modules for 250 kbps
void _100_kbps(void);		// Configure the modules for 100 kbps
void _50_kbps(void);		// Configure the modules for 50 kbps

void Xmit_Remote_frame(void);	// Transmit a Remote frame
void Resp_Remote_frame(void);	// Respond to a Remote frame

void CAN_traffic(void);         // Generates CAN traffic

void CCR_Enable(void);
void CCR_Disable(void);

void Enable_Mailboxes(void);
void Disable_Mailboxes(void);

/* Create a shadow register structure for the CAN control registers. 

This is needed, since, only 32-bit access is allowed to these registers. 16-bit access
 to these registers could potentially corrupt the register contents. This is
 especially true while writing to a bit (or group of bits) among bits 16 - 31 */

struct ECAN_REGS ECanaShadow;
struct ECAN_REGS ECanbShadow;

main()
{

/* Kill Watchdog, Init PLL, Enable peripheral clocks */

	InitSysCtrl();
	
/* Initialize the CAN module */

	InitECan();	
	InitECanGpio();
	
	EALLOW;

/* Zero out (or initialize) the entire MBX RAM area */

	MBXwrA();
	MBXwrB();

/* Configure Mailbox as Transmit or Receive , as needed */

	ECanaShadow.CANMD.all = 0;
	ECanaShadow.CANMD.bit.MD0 = 0;
	ECanaShadow.CANMD.bit.MD4 = 1;
	ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;

	ECanbShadow.CANMD.all = 0;
	ECanbShadow.CANMD.bit.MD0 = 0;
	ECanbShadow.CANMD.bit.MD4 = 1;
	ECanbRegs.CANMD.all = ECanbShadow.CANMD.all;

/* Write to DLC field in Master Control reg */ // By default, in this code, the mailboxes are configured for 8-bytes

	ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
	ECanbMboxes.MBOX0.MSGCTRL.bit.DLC = 8;

/* Write to the mailbox RAM field */

	ECanaMboxes.MBOX0.MDL.all = 0x0A0A0A0A; // "0A" denotes a byte coming out of MBX0 in node A
	ECanaMboxes.MBOX0.MDH.all = 0x0A0A0A0A;

	ECanbMboxes.MBOX0.MDL.all = 0x0B0B0B0B; // "0B" denotes a byte coming out of MBX0 in node B
	ECanbMboxes.MBOX0.MDH.all = 0x0B0B0B0B;

/* Read GPIO pins, only if Read_GPIO = 1 */ // Else, use the hard-coded GPIO_val value....

	if(Read_GPIO)
	{
	GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;	/* Configure GPIO3-GPIO0 for GPIO function */
	GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;
	GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
	GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0;

	GpioCtrlRegs.GPADIR.bit.GPIO0 = 0;	// Configure GPIO15-GPIO0 for input function
	GpioCtrlRegs.GPADIR.bit.GPIO1 = 0;
	GpioCtrlRegs.GPADIR.bit.GPIO2 = 0;
	GpioCtrlRegs.GPADIR.bit.GPIO3 = 0;


	GPIO_val = GpioDataRegs.GPADAT.all;	// Read GPIO15-GPIO0
	GPIO_val &= 0x000F;					// Mask all bits except GPIO3-GPIO0
	}


/* Choose what to do based on GPIO_val value */


	 switch(GPIO_val)
	   {
	   	case 0:             // Transmit 8 bytes @ 1 Mbps       Extended ID
	   		Use_Ext_ID();
	   		_1_Mbps();
	   		TxLoop_A();
	   		break;

	   	case 1:             // Transmit 8 bytes @ 500 kbps      Extended ID
	   		Use_Ext_ID();
	   		_500_kbps();
	   		TxLoop_A();
	   		break;

	   	case 2:             // Transmit 8 bytes @ 250 kbps      Extended ID
	   		Use_Ext_ID();
	   		_250_kbps();
	   		TxLoop_A();
	   		break;

	   	case 3:             // Transmit 8 bytes @ 100 kbps      Standard ID
	   		Use_Std_ID();
	   		_100_kbps();
	   		TxLoop_A();
	   		break;

	   	case 4:             // Transmit 8 bytes @ 50 kbps       Standard ID
	   		Use_Std_ID();
	   		_50_kbps();
	   		TxLoop_A();
	   		break;

	   	case 5:             // Receive @ 1 Mbps
	   		Use_Ext_ID();
	   		_1_Mbps();
	   		Transmit_B();       // Transmits "TXCOUNT" frames and after that node merely provides an ACK
	   		Receive_A();
	   		break;

	   	case 6:             // Receive @ 500 kbps
	   		Use_Ext_ID();
	   		_500_kbps();
	   		Transmit_B();       // Transmits "TXCOUNT" frames and after that node merely provides an ACK
	   		Receive_A();
	   		break;

	   	case 7:             // Receive @ 250 kbps
	   		Use_Ext_ID();
	   		_250_kbps();
	   		Transmit_B();       // Transmits "TXCOUNT" frames and after that node merely provides an ACK
	   		Receive_A();
	   		break;

	   	case 8:             // Receive @ 100 kbps (node merely provides an ACK)
	   		Use_Std_ID();
	   		_100_kbps();
	   		Transmit_B();       // Transmits "TXCOUNT" frames and after that node merely provides an ACK
	   		Receive_A();
	   		break;

	   	case 9:             // Receive @ 50 kbps (node merely provides an ACK)
	   		Use_Std_ID();
	   		_50_kbps();
	   		Transmit_B();       // Transmits "TXCOUNT" frames and after that node merely provides an ACK
	   		Receive_A();
	   		break;

	   	case 10:            // Transmit 0 bytes @ 1 Mbps       Extended ID
	   		Use_Ext_ID();
	   		ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 0;
	   		_1_Mbps();
	   		TxLoop_A();
	   		break;

	   	case 11:            // Transmit 0 bytes @ 50 kbps       Extended ID
	   		Use_Std_ID();
	   		ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 0;
	   		_50_kbps();
	   		TxLoop_A();
	   		break;

	   	case 12:            // Transmit a remote frame @ 1 Mbps    Standard ID
	   		_1_Mbps();
	   		Xmit_Remote_frame();
	   		break;

	   	case 13:            // Respond to a remote frame @ 1 Mbps    Standard ID
	   		_1_Mbps();
	   		Resp_Remote_frame();
	   		break;

	   	case 14:            // Tx a STD frame followed by an Ext.frame @ 50 kbps. Repeat the cycle, but give 0.5 sec delay between frames.
	   	    _50_kbps();
	   	    while(1){CAN_traffic();}  // Generates CAN traffic
	   	    break;
	   }
	 ESTOP0;
}

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

void Use_Ext_ID(void)			// Use Extended ID for the Mailbox
{
	ECanaMboxes.MBOX0.MSGID.all = 0x95555555; // Extended Identifier
	ECanbMboxes.MBOX4.MSGID.all = 0x95555555; // Extended Identifier
	Enable_Mailboxes();
}

void Use_Std_ID(void)			// Use Standard ID for the Mailbox
{
	ECanaMboxes.MBOX0.MSGID.all = 0x0FFC0000;  // IDE=0, AME=0, AAM=0, STD ID = 3FF
	ECanbMboxes.MBOX4.MSGID.all = 0x0FFC0000;  // IDE=0, AME=0, AAM=0, STD ID = 3FF
	Enable_Mailboxes();
}


void TxLoop_A(void)               // Transmit Mailbox Data
{
    //while(1)                           // Uncomment this line for infinite transmissions
    for(i=0; i < TXCOUNT; i++)                // Uncomment this line for finite transmissions
    {
        Transmit_A();
    }
    asm(" ESTOP0");
}

void Transmit_A(void)				// Transmit Mailbox Data
{
	     ECanaShadow.CANTRS.all = 0;
	     ECanaShadow.CANTRS.bit.TRS0 = 1;     // Set TRS for mailbox under test
	     ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;

			do
	        {
	        ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;	// Wait for TA0 bit to be set..
	        } while(ECanaShadow.CANTA.bit.TA0 == 0 );

	     ECanaShadow.CANTA.all = 0;
	     ECanaShadow.CANTA.bit.TA0 = 1;     	 // Clear TA0
	     ECanaRegs.CANTA.all = ECanaShadow.CANTA.all;

	     TX_A_loopcount ++;

}

void Receive_A(void)				// Receive Data
{

    while(1)
    {
     while(ECanaRegs.CANRMP.all != 0x00000010 ) {}  // Wait for RMP4 to be set..

     ECanaRegs.CANRMP.all = 0x00000010;			   // Clear RMP4 bit and start
     RX_A_loopcount++ ;		                           // all over again...
    }
}

void Transmit_B(void)				// Transmit Mailbox Data
{
	/* Begin transmitting */

	    //while(1) 							// Uncomment this line for infinite transmissions
	    for(i=0; i < TXCOUNT; i++)				// Uncomment this line for finite transmissions
	    {
	    ECanbShadow.CANTRS.all = 0;
	    ECanbShadow.CANTRS.bit.TRS0 = 1;     // Set TRS for mailbox under test
	    ECanbRegs.CANTRS.all = ECanbShadow.CANTRS.all;

			do
	        {
				ECanbShadow.CANTA.all = ECanbRegs.CANTA.all;	// Wait for TA0 bit to be set..
	        } while(ECanbShadow.CANTA.bit.TA0 == 0 );

		ECanbShadow.CANTA.all = 0;
		ECanbShadow.CANTA.bit.TA0 = 1;     	 // Clear TA0
		ECanbRegs.CANTA.all = ECanbShadow.CANTA.all;

		TX_B_loopcount ++;

	    }
	    // asm(" ESTOP0");
}
void _1_Mbps(void)			// Configure the modules for 1 Mbps
{
	CCR_Enable();
	ECanaShadow.CANBTC.bit.BRPREG = 4;
	ECanbShadow.CANBTC.bit.BRPREG = 4;
	CCR_Disable();
}

void _500_kbps(void)		// Configure the modules for 500 kbps
{
	CCR_Enable();
	ECanaShadow.CANBTC.bit.BRPREG = 9;
	ECanbShadow.CANBTC.bit.BRPREG = 9;
	CCR_Disable();
}

void _250_kbps(void)		// Configure the modules for 250 kbps
{
	CCR_Enable();
	ECanaShadow.CANBTC.bit.BRPREG = 19;
	ECanbShadow.CANBTC.bit.BRPREG = 19;
	CCR_Disable();
}

void _100_kbps(void)		// Configure the modules for 100 kbps
{
	CCR_Enable();
	ECanaShadow.CANBTC.bit.BRPREG = 49;
	ECanbShadow.CANBTC.bit.BRPREG = 49;
	CCR_Disable();
}

void _50_kbps(void)			// Configure the modules for 50 kbps
{
	CCR_Enable();
	ECanaShadow.CANBTC.bit.BRPREG = 99;
	ECanbShadow.CANBTC.bit.BRPREG = 99;
	CCR_Disable();
}

void _10_kbps(void)         // Configure the modules for 10 kbps
{
    CCR_Enable();
    ECanaShadow.CANBTC.bit.BRPREG = 499;
    ECanbShadow.CANBTC.bit.BRPREG = 499;
    CCR_Disable();
}

void Xmit_Remote_frame(void)	// Transmit a Remote frame
{
	ECanaMboxes.MBOX4.MSGID.all  = 0x00080000;  // eCAN-A -> Std identifier (Will eventually transmit a Remote frame)
	ECanaMboxes.MBOX4.MSGCTRL.bit.RTR = 1;  	// eCAN-A -> RTR bit will be cleared upon successful reception of data
	ECanaMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
	ECanbMboxes.MBOX0.MSGID.all  = 0x20080000;  // eCAN-B -> Std identifier with AAM bit set (Will transmit the Data frame)
	Enable_Mailboxes();
	ECanaRegs.CANTRS.all = 0x00000010;
	DELAY_US(1000000);
	while(1){}

}

void Resp_Remote_frame(void)	// Respond to a Remote frame
{
    ECanbMboxes.MBOX0.MSGID.all  = 0x20080000;  // eCAN-B -> Std identifier with AAM bit set (Will transmit the Data frame)
    Enable_Mailboxes();
    while(1){}
}

void CAN_traffic(void)          // Generates CAN traffic
{
    Disable_Mailboxes();
    Use_Std_ID();
    Enable_Mailboxes();
    Transmit_A();
    DELAY_US(1000000);
    Disable_Mailboxes();
    Use_Ext_ID();
    Enable_Mailboxes();
    Transmit_A();
}

void CCR_Enable(void)
{
		ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
		ECanaShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
	    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

	    // Wait until the CPU has been granted permission to change the configuration registers
	    do
	    {
	      ECanaShadow.CANES.all = ECanaRegs.CANES.all;
	    } while(ECanaShadow.CANES.bit.CCE != 1 );  		// Wait for CCE bit to be set..

	    ECanaShadow.CANBTC.all = ECanaRegs.CANBTC.all;

	/* Configure bit timing parameters for eCANB*/

		ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
		ECanbShadow.CANMC.bit.CCR = 1 ;            // Set CCR = 1
	    ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;

	    // Wait until the CPU has been granted permission to change the configuration registers
	    do
	    {
	      ECanbShadow.CANES.all = ECanbRegs.CANES.all;
	    } while(ECanbShadow.CANES.bit.CCE != 1 );  		// Wait for CCE bit to be set..

	    ECanbShadow.CANBTC.all = ECanbRegs.CANBTC.all;
}

void CCR_Disable(void)
{
			ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

			ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
	       	ECanaShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
	       	ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

	        // Wait until the CPU no longer has permission to change the configuration registers
	        do
	        {
	          ECanaShadow.CANES.all = ECanaRegs.CANES.all;
	        } while(ECanaShadow.CANES.bit.CCE != 0 ); 		// Wait for CCE bit to be  cleared..

	        ECanbRegs.CANBTC.all = ECanbShadow.CANBTC.all;

	        ECanbShadow.CANMC.all = ECanbRegs.CANMC.all;
	        ECanbShadow.CANMC.bit.CCR = 0 ;            // Set CCR = 0
	        ECanbRegs.CANMC.all = ECanbShadow.CANMC.all;

	        // Wait until the CPU no longer has permission to change the configuration registers
	        do
	        {
	          ECanbShadow.CANES.all = ECanbRegs.CANES.all;
	        } while(ECanbShadow.CANES.bit.CCE != 0 ); 		// Wait for CCE bit to be  cleared..
}

void Enable_Mailboxes(void)			/* Enable Mailboxes under test */
{
	ECanaShadow.CANME.all = 0;
	ECanaShadow.CANME.bit.ME0 = 1;
	ECanaShadow.CANME.bit.ME4 = 1;
	ECanaRegs.CANME.all = ECanaShadow.CANME.all;

	ECanbShadow.CANME.all = 0;
	ECanbShadow.CANME.bit.ME0 = 1;
	ECanbShadow.CANME.bit.ME4 = 1;
	ECanbRegs.CANME.all = ECanbShadow.CANME.all;
}

void Disable_Mailboxes(void)         /* Disable Mailboxes  */
{
    ECanaRegs.CANME.all = 0;
    ECanbRegs.CANME.all = 0;
}

/* Zero-out the MBX RAM of CAN-A */

void MBXwrA()
    {
    int j;
    volatile struct MBOX *Mailbox  = (void *) 0x6100;

        for(j=0; j<32; j++)
        {
            Mailbox->MSGID.all = 0;
            Mailbox->MSGCTRL.all = 0;
            Mailbox->MDH.all = 0;
            Mailbox->MDL.all = 0;
            Mailbox = Mailbox + 1;

        }
    }

/* Zero-out the MBX RAM of CAN-B */

void MBXwrB()
    {
    int j;
    volatile struct MBOX *Mailbox  = (void *) 0x6300;

        for(j=0; j<32; j++)
        {
            Mailbox->MSGID.all = 0;
            Mailbox->MSGCTRL.bit.DLC = 0;
            Mailbox->MDH.all = 0;
            Mailbox->MDL.all = 0;
            Mailbox = Mailbox + 1;

        }
    }
/*
--------------------------------------------------------------------------------
GPIO value	Decimal			Operation						Comments
--------------------------------------------------------------------------------
0000		0		Transmit 8 bytes @ 1 Mbps		Extended ID
0001		1		Transmit 8 bytes @ 500 kbps		Extended ID
0010		2		Transmit 8 bytes @ 250 kbps		Extended ID
0011		3		Transmit 8 bytes @ 100 kbps		Standard ID
0100		4		Transmit 8 bytes @ 50 kbps		Standard ID
0101		5		Receive @ 1 Mbps                Toggle GPIO for known MSGID, Else, node merely provides an ACK
0110		6		Receive @ 500 kbps              Toggle GPIO for known MSGID, Else, node merely provides an ACK
0111		7		Receive @ 250 kbps				Toggle GPIO for known MSGID, Else, node merely provides an ACK
1000		8		Receive @ 100 kbps				Toggle GPIO for known MSGID, Else, node merely provides an ACK
1001		9		Receive @ 50 kbps				Toggle GPIO for known MSGID, Else, node merely provides an ACK
1010		10		Transmit 0 bytes @ 1 Mbps       Extended ID
1011		11		Transmit 0 bytes @ 50 kbps      Standard ID
1100		12		Transmit a remote frame @ 1 Mbps    Standard ID
1101		13		Respond to a remote frame @ 1 Mbps  Standard ID
1110		14		Tx a STD frame followed by an Ext.frame @ 50 kbps. Repeat the cycle, but give 0.5 sec delay between frames.
1111		15		Free

 */


