// 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: LAM.c
*                                                                    
* Description: This example code illustrates how Acceptance Mask Filtering
* works using CANLAM registers. 4 different cases are illustrated
*
* CAN-B is the transmitter and CAN-A is the receiver. They need to be connected
* together through CAN transceivers. This code can only be run with 28xx devices
* that have two eCAN modules on-chip.
*
*******************************************************************************/

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

int TX_COUNT = 0;
int j = 0;

void Config_Transmit_B(void);       // Configure Transmit Mailboxes in eCAN-B
void Check_Tx_B(void);              // Ensure completion of message transmission and clears TA flag
void MBXwrA(void);                 // This function initializes all 32 MBOXes of CAN-A
void MBXwrB(void);                 // This function initializes all 32 MBOXes of CAN-B

main() 
{

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

    InitSysCtrl();

/* Initialize the CAN modules */

    InitECan();
    InitECanGpio();

    EALLOW;

/* Zero out the entire MBX RAM area - Makes it easy to debug */

    MBXwrA();
    MBXwrB();

/* Configure Transmit Mailboxes in eCAN-B */

    Config_Transmit_B();
    
/* Write to the MSGID field of RECEIVE mailboxes */

    ECanaMboxes.MBOX30.MSGID.all = 0x90000030; // Extended Identifier - Acceptance mask NOT enabled

    ECanaMboxes.MBOX20.MSGID.all = 0xC1111120; // Extended Identifier - Acceptance mask enabled

    ECanaMboxes.MBOX10.MSGID.all = 0xC5555553; // Extended Identifier (0x9555555X - last nibble is a "don't care") - Acceptance mask enabled

    ECanaMboxes.MBOX5.MSGID.all  = 0xC48F2B95; // Extended Identifier (0xXXXXXXXX - All MSGIDs will be received in this mailbox) - Acceptance mask enabled

/* Configure the LAM registers */

	  ECanaLAMRegs.LAM20.all = 0x00000000;
	  ECanaLAMRegs.LAM10.all = 0x0000000F;
	  ECanaLAMRegs.LAM5.all  = 0x1FFFFFFF;
	 
 /* Configure Mailbox direction */

	ECanaRegs.CANMD.all = 0x40100420;   // Configure Mboxes30,20,10,5 in CAN-A for reception
	ECanbRegs.CANMD.all = 0x00000000;   // Configure Mboxes in CAN-B for transmission
	 
/* Enable Mailboxes */
	
	ECanaRegs.CANME.all = 0x40100420;
	ECanbRegs.CANME.all = 0xFFFFFFFF;

/* Begin transmitting */     
     
     ECanbRegs.CANTRS.all = 0x40000000;	// Set TRS for MBX30 (Will be received in eCAN-A.MBX30)
     Check_Tx_B();

     ECanbRegs.CANTRS.all = 0x00100000;	// Set TRS for MBX20 (Will be received in eCAN-A.MBX20)
     Check_Tx_B();

     ECanbRegs.CANTRS.all = 0x00000400;	// Set TRS for MBX10 (Will be received in eCAN-A.MBX10, but will be overwritten by the next message)
     Check_Tx_B();

     ECanbRegs.CANTRS.all = 0x00000200;	// Set TRS for MBX9  (Will be received in eCAN-A.MBX10, but will be overwritten by the next message)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX10 has a data of 1010101010101010

     ECanbRegs.CANTRS.all = 0x00000100;	// Set TRS for MBX8  (Will be received in eCAN-A.MBX10)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX10's data of 1010101010101010 is overwritten by 0909090909090909

     ECanbRegs.CANTRS.all = 0x00000020;	// Set TRS for MBX5  (Will be received in eCAN-A.MBX5, but will be overwritten by the next message)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX10's data of 0909090909090909 is overwritten by 0808080808080808

     ECanbRegs.CANTRS.all = 0x00000010; // Set TRS for MBX4  (Will be received in eCAN-A.MBX5, but will be overwritten by the next message)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX5 has a data of 0505050505050505

     ECanbRegs.CANTRS.all = 0x00000008;	// Set TRS for MBX3  (Will be received in eCAN-A.MBX5, but will be overwritten by the next message)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX5's data of 0505050505050505 is overwritten by 0404040404040404

     ECanbRegs.CANTRS.all = 0x00000004;	// Set TRS for MBX2  (Will be received in eCAN-A.MBX5, but will be overwritten by the next message)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX5's data of 0404040404040404 is overwritten by 0303030303030303

     ECanbRegs.CANTRS.all = 0x00000002;	// Set TRS for MBX1  (Will be received in eCAN-A.MBX5)
     Check_Tx_B();						// By setting up a breakpoint in the previous code line, it could be seen that MBX5's data of 0303030303030303 is overwritten by 0202020202020202

     asm("     ESTOP0");				// Stop here after program termination. MBX5 should have a data of 0101010101010101

}

/* -------------------------------------------------------------------------- */
/* Function that ensures transmission is complete and then clears the TAn bit */
/* -------------------------------------------------------------------------- */

void Check_Tx_B(void)
{

    while(ECanbRegs.CANTA.all == 0 ) {}         // Loop here until TAn bit is set..
         ECanbRegs.CANTA.all = 0xFFFFFFFF;      // Simply Clear all TAn
         TX_COUNT ++;                           // Should be 10 at program completion
}

/* ---------------------------------------------------- */
/* Function that configures transmit mailboxes in CAN-B */
/* ---------------------------------------------------- */

void Config_Transmit_B(void)
{

    /* Write to the MSGID field of TRANSMIT mailboxes */

        ECanbMboxes.MBOX30.MSGID.all = 0x90000030; // Extended Identifier

        ECanbMboxes.MBOX20.MSGID.all = 0x81111120; // Extended Identifier

        ECanbMboxes.MBOX10.MSGID.all = 0x85555553; // Extended Identifier
        ECanbMboxes.MBOX9.MSGID.all  = 0x85555554; // Extended Identifier
        ECanbMboxes.MBOX8.MSGID.all  = 0x85555558; // Extended Identifier

        ECanbMboxes.MBOX5.MSGID.all  = 0x848F2B95; // Extended Identifier
        ECanbMboxes.MBOX4.MSGID.all  = 0x8A6E50D4; // Extended Identifier
        ECanbMboxes.MBOX3.MSGID.all  = 0x80B37CA3; // Extended Identifier
        ECanbMboxes.MBOX2.MSGID.all  = 0x819D4E52; // Extended Identifier
        ECanbMboxes.MBOX1.MSGID.all  = 0x840F7E01; // Extended Identifier

     /* Write to Master Control field */

        ECanbMboxes.MBOX30.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX20.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX10.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX9.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX8.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX5.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX4.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX3.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX2.MSGCTRL.bit.DLC = 8;
        ECanbMboxes.MBOX1.MSGCTRL.bit.DLC = 8;

        /* Write to the mailbox RAM field */

        ECanbMboxes.MBOX30.MDL.all = 0x30303030;
        ECanbMboxes.MBOX30.MDH.all = 0x30303030;

        ECanbMboxes.MBOX20.MDL.all = 0x20202020;
        ECanbMboxes.MBOX20.MDH.all = 0x20202020;

        ECanbMboxes.MBOX10.MDL.all = 0x10101010;
        ECanbMboxes.MBOX10.MDH.all = 0x10101010;

        ECanbMboxes.MBOX9.MDL.all = 0x09090909;
        ECanbMboxes.MBOX9.MDH.all = 0x09090909;

        ECanbMboxes.MBOX8.MDL.all = 0x08080808;
        ECanbMboxes.MBOX8.MDH.all = 0x08080808;

        ECanbMboxes.MBOX5.MDL.all = 0x05050505;
        ECanbMboxes.MBOX5.MDH.all = 0x05050505;

        ECanbMboxes.MBOX4.MDL.all = 0x04040404;
        ECanbMboxes.MBOX4.MDH.all = 0x04040404;

        ECanbMboxes.MBOX3.MDL.all = 0x03030303;
        ECanbMboxes.MBOX3.MDH.all = 0x03030303;

        ECanbMboxes.MBOX2.MDL.all = 0x02020202;
        ECanbMboxes.MBOX2.MDH.all = 0x02020202;

        ECanbMboxes.MBOX1.MDL.all = 0x01010101;
        ECanbMboxes.MBOX1.MDH.all = 0x01010101;

}


/* 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.all = 0;
            Mailbox->MDH.all = 0;
            Mailbox->MDL.all = 0;
            Mailbox = Mailbox + 1;

        }
    }


/* 


Notes:
--------------------

When a message is received, the message controller starts looking for a matching identifier
at the mailbox with the highest mailbox number.

* Case A: No Acceptance Mask Filtering is used
* --------------------------------------------
* In this case, every bit of the transmitted frame's MSGID must match with
* (have the same value as) the corresponding bit of the Receive mailbox's MSGID.
*
* CANB.Mailbox30 will transmit to CANA.Mailbox30 and that message would be received in CANA.Mailbox30 only
*
* Case B: Acceptance Mask Filtering is used, but LAM bits are all zeroes
* ----------------------------------------------------------------------
* In this case, every bit of the transmitted frame's MSGID must STILL match with
* (have the same value as) the corresponding bit of the Receive mailbox's MSGID.
*
* CANB.Mailbox20 will transmit to CANA.Mailbox20 and that message would be received in CANA.Mailbox20 only
*
* Case C: Acceptance Mask Filtering is used; Some LAM bits are ones
* ----------------------------------------------------------------------
* In this case, SOME bits of the transmitted frame's MSGID are masked as
* "don't care" by making those bit-positions in the CANLAM register as "1".
* Transmitted MSGID bits that have a "0" in the corresponding bit-positions in CANLAM
* must match with the same bits of the Receive mailbox's MSGID. This is useful to
* receive a GROUP of MSGIDs that differ only in a few bit positions.
*
* CANB.Mailboxes 10,9,8 will transmit to CANA.Mailbox10 and those messages would be received in CANA.Mailbox10.
* Note that mailboxes 10,9,8 transmit messages with MSGIDs that are not exactly identical, but differing
* in a few bit positions. However, since the LAM is setup to ignore (mask) those differing bits, the messages
* will be correctly received in CANA.Mailbox10.
*
* Case D: Acceptance Mask Filtering is used; All LAM bits are ones
* ----------------------------------------------------------------------
* In this case, ALL bits of the transmitted frame's MSGID are masked as
* "don't care" by making ALL bit-positions in the CANLAM register as "1".
* This is useful to receive ANY MSGID in the same mailbox.
*
* CANB.Mailboxes 5,4,3,2,1 will transmit to CANA.Mailbox5 and those messages would be received in CANA.Mailbox5.
* Note that mailboxes 5,4,3,2,1 transmit messages with completely different/random MSGIDs.
* However, since the LAM is setup to ignore (mask) all bits, the messages will be correctly received in CANA.Mailbox5.
*

Status: Verified 3/27/2017

... */ 
