// 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: MOTO.c                                                
*                                                                    
* Description: This example illustrates the "MOTO" feature.
* (MOTO - Message Object Time-Out)
* Deliberately let a transmit mailbox timeout and check whether the
* corresponding interrupt flag (MTOFn) and TOSn is set.
* Mailbox 0 is used in this example
*
**********************************************************************/

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

// Variable declarations

long      i;
int int0count = 0;		// Counter to track the # of level 0 interrupts
int int1count = 0;	    // Counter to track the # of level 1 interrupts

// Prototype statements for functions found within this file.

interrupt void eCAN0INT_ISR(void);
interrupt void eCAN1INT_ISR(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;

void InitECan(void);

main() 
{

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

        InitSysCtrl();

/* Initialize the CAN module */

        InitECan();
        InitECanGpio();

        EALLOW;

/* Initialize PIE vector table To a Known State: */
	// The PIE vector table is initialized with pointers to shell "Interrupt 
    // Service Routines (ISR)".  The shell routines are found in DSP28_DefaultIsr.c.
	// Insert user specific ISR code in the appropriate shell ISR routine in 
    // the DSP28_DefaultIsr.c file.
    
    // InitPieVectTable();	 // uncomment this line if the shell ISR routines are needed
    
    // This function is found in DSP28_PieVect.c. It populates the PIE vector table
    // with pointers to the shell ISR functions found in DSP28_DefaultIsr.c. This 
    // function is not useful in this code because the user-specific ISR is present
    // in this file itself. The shell ISR routine in the DSP28_DefaultIsr.c file is
    // not used. If the shell ISR routines are needed, uncomment this line and add 
    // DSP28_PieVect.c & DSP28_DefaultIsr.c files to the project

/* Disable and clear all CPU interrupts: */

	DINT;
	IER = 0x0000;
	IFR = 0x0000;

/* Initialize Pie Control Registers To Default State */
        
	InitPieCtrl(); // This function is found in the DSP28_PieCtrl.c file. 

 /* Write to the MSGID field */
    
    ECanaMboxes.MBOX0.MSGID.all  = 0x9555AA00; 
     
 /* Configure Mailbox under test as Tx */

	ECanaRegs.CANMD.all = 0; 		// All mailboxes are made transmit..
	
/* Enable Mailbox under test */
	
	ECanaShadow.CANME.all = ECanaRegs.CANME.all;	
	ECanaShadow.CANME.bit.ME0 = 1;
	ECanaRegs.CANME.all = ECanaShadow.CANME.all; 
	
/* Write to Master Control field */
 
    ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;
        
/* Write to the mailbox RAM field */
    
     ECanaMboxes.MBOX0.MDL.all = 0x9555AAA0;
	 ECanaMboxes.MBOX0.MDH.all = 0x89ABCDEF;
		           
/* Configure CAN interrupts */ 

	ECanaShadow.CANMIL.all = ECanaRegs.CANMIL.all;	
	//ECanaShadow.CANMIL.bit.MIL0 = 0 ; // MBOX0 asserts MTOF0 (eCAN0INT)
	ECanaShadow.CANMIL.bit.MIL0 = 1 ;  // MBOX0 asserts MTOF1 (eCAN1INT)
	ECanaRegs.CANMIL.all = ECanaShadow.CANMIL.all;
	
	ECanaShadow.CANGIM.all = 0;	
    ECanaShadow.CANGIM.bit.I0EN = 1;     // Enable eCAN0INT 
    ECanaShadow.CANGIM.bit.I1EN = 1;	 // Enable eCAN1INT
    ECanaShadow.CANGIM.bit.MTOM = 1;	 // Enable MBX Timeout interrupt
    ECanaRegs.CANGIM.all = ECanaShadow.CANGIM.all;
    
/* Reassign ISRs. i.e. reassign the PIE vector for ECAN0INTA_ISR and ECAN0INTA_ISR 
   to point to a different ISR than the shell routine found in DSP28_DefaultIsr.c.
   This is done if the user does not want to use the shell ISR routine but instead
   wants to embed the ISR in this file itself. */
	
	PieVectTable.ECAN0INTA = &eCAN0INT_ISR;
	PieVectTable.ECAN1INTA = &eCAN1INT_ISR;	
    
/* Configure PIE interrupts */    
  
	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;  // Enable vector fetching from PIE block
	
	PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU

// The 'MOTO' interrupt can be asserted in either of the eCAN interrupt lines
// Comment out the unwanted line...

	PieCtrlRegs.PIEIER9.bit.INTx5 = 1;  // Enable INTx.5 of INT9 (eCAN0INT)
	PieCtrlRegs.PIEIER9.bit.INTx6 = 1;  // Enable INTx.6 of INT9 (eCAN1INT)	
	
/* Configure system interrupts */
	
	IER |= 0x0100;					// Enable INT9 of CPU
	EINT;							// Global enable of interrupts   
	
/* Write to MOTO reg of Mailbox under test */

	ECanaMOTORegs.MOTO0 = 0x80; // It was experimentally determined that  
						// this value would let MBX0 to timeout...MOTS0 contains
						// 8Eh after transmission is complete..See Note 1
						// This value may have to tweaked a bit based on the clock frequency etc..

/* Enable time-out function for the mailbox */
    	 	
    ECanaShadow.CANTOC.all = 0;	
	ECanaShadow.CANTOC.bit.TOC0 = 1;
	ECanaRegs.CANTOC.all = ECanaShadow.CANTOC.all; 
	
/* Clear the "Time Stamp Counter"  */

	ECanaRegs.CANTSC = 0;

/* Begin transmitting */       
     		 	
     ECanaShadow.CANTRS.all = 0; 	
     ECanaShadow.CANTRS.bit.TRS0 = 1;     // Set TRS for mailbox under test       
     ECanaRegs.CANTRS.all = ECanaShadow.CANTRS.all;     
     
     for(i=0; i<999999; i++) 	// A very long loop. Code loops here when CAN module transmits
	 	{ asm(" NOP"); }        // the data and executes the ISR
	 
	 asm(" ESTOP0");									 // Code stops here after transmission

}

/* --------------------------------------------------- */
/* ISR for PIE INT9.5                                  */
/* Connected to HECC0-INTA  eCAN                       */
/* ----------------------------------------------------*/

interrupt void eCAN0INT_ISR(void)  // eCAN
{
   ECanaShadow.CANTOS.all = ECanaRegs.CANTOS.all ;  // Copy TOS reg for inspection
   ECanaShadow.CANGIF0.all = ECanaRegs.CANGIF0.all; // Copy GIF0 reg for inspection
     
   ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
      do {ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;}   // Wait for TA0 bit to be set..
       while(ECanaShadow.CANTA.bit.TA0 == 0 );

// Clear TAn  
   ECanaShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any  
   ECanaShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
   							// other TAn bit that is set could be inadvertently cleared
   ECanaRegs.CANTA.all =  ECanaShadow.CANTA.all ;   // Clear TAn bit

// Clear MTOF0   
   // MTOF0 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
   // which is automatically cleared when the message is successfully transmitted.
   

// Re-enable PIE and Core interrupts   
   PieCtrlRegs.PIEACK.bit.ACK9 = 1;    	// Enables PIE to drive a pulse into the CPU
   IER |= 0x0100;					 	// These 2 lines allow for nested interrupts 
   EINT;								// Strictly not needed for this example.
   int0count++;
   return;
}

/* --------------------------------------------------- */
/* ISR for PIE INT9.6                                  */
/* Connected to HECC1-INTA  eCAN                       */
/* ----------------------------------------------------*/

interrupt void eCAN1INT_ISR(void)  // eCAN
{
   ECanaShadow.CANTOS.all = ECanaRegs.CANTOS.all ;  // Copy TOS reg for inspection
   ECanaShadow.CANGIF1.all = ECanaRegs.CANGIF1.all; // Copy GIF1 reg for inspection
  
   ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;
      do {ECanaShadow.CANTA.all = ECanaRegs.CANTA.all;}   // Wait for TA0 bit to be set..
       while(ECanaShadow.CANTA.bit.TA0 == 0 );
   
// Clear TAn  
   ECanaShadow.CANTA.all = 0; 			// Initialize TA to zero before setting any  
   ECanaShadow.CANTA.bit.TA0 = 1 ;		// bit in order to clear it. Otherwise, some
   							// other TAn bit that is set could be inadvertently cleared
   ECanaRegs.CANTA.all =  ECanaShadow.CANTA.all ;   // Clear TAn bit

// Clear MTOF1   
   // MTOF1 cannot be manually cleared. It is automatically cleared when TOSn is cleared, 
   // which is automatically cleared when the message is successfully transmitted.
   
// Re-enable PIE and Core interrupts   
   PieCtrlRegs.PIEACK.bit.ACK9 = 1;    // Enables PIE to drive a pulse into the CPU
   IER |= 0x0100;					 // Enable INT9 
   EINT;
   int1count++;
   return;
}

/* Notes:

The TOS.n bit will be cleared upon (eventual) successful transmission.
The only way to ascertain if a time-out occurred is to copy TOS and GIFn
registers in the ISR to check if the relevant bits were set when the 
ISR was just entered. 

It can be verified that whether the MTOF bit gets set in GIF0 or GIF1 
depends on the value of MILn. 

This example is useful to check that MTOFn gets cleared if TOSn is cleared. 

Note 1: TSC does not start running until the bit timing registers
are configured. After configuration, it is a free running timer clocked by the 
bit rate clock of the CAN module. The delay between the last instruction 
that configures the bit timing to the instruction that initiates transmission will
therefore affect this "experimentally determined" value. Since the counter runs at
the bit clock rate, the fastest bit clock rate is 1 uS, which equates to 150 CPU
clock cycles (@ 150 MHz SYSCLKOUT). Therefore adding/deleting a few instructions 
will not make a significant change. A delay loop would.

*/

