#include "DSP2833x_Device.h"


void cana_dev_mailbox_disable_all()
{
	EALLOW;
	ECanaRegs.CANME.all = 0x00000000;
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_mailbox_enable_all()
{
	EALLOW;
	/* Enable all Mailboxes */
	ECanaRegs.CANME.all = 0xFFFFFFFF;
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_mailbox_disable(i_uint8 idx)
{
	i_uint32 tmp = ECanaRegs.CANME.all;
	tmp &= ~(((i_uint32)(0x00000001)) << idx);
	EALLOW;
	ECanaRegs.CANME.all = tmp;
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_mailbox_enable(i_uint8 idx)
{
	i_uint32 tmp = ECanaRegs.CANME.all;
	tmp |= ((i_uint32)(0x00000001)) << idx;
	EALLOW;
	ECanaRegs.CANME.all = tmp;
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_clock()
{
	EALLOW;
	SysCtrlRegs.PCLKCR0.bit.ECANAENCLK=1;
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_gpio()
{
	EALLOW;
	GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0;	    // Enable pull-up for GPIO30 (CANRXA)
	GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0;	    // Enable pull-up for GPIO31 (CANTXA)
	GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3;   // Asynch qual for GPIO30 (CANRXA)
	GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1;	// Configure GPIO30 for CANRXA operation
	GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1;	// Configure GPIO31 for CANTXA operation
	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_peripheral()
{
	struct ECAN_REGS ECanaShadow;
	EALLOW;

	/* Configure eCAN RX and TX pins for CAN operation using eCAN regs*/
	ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
	ECanaShadow.CANTIOC.bit.TXFUNC = 1;
	ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;

	ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
	ECanaShadow.CANRIOC.bit.RXFUNC = 1;
	ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;

	ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
	ECanaShadow.CANMC.bit.SCB = 1;	// eCAN
	ECanaShadow.CANMC.bit.CCR = 1;
	ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

	ECanaShadow.CANES.all = ECanaRegs.CANES.all;
	do{
		ECanaShadow.CANES.all = ECanaRegs.CANES.all;
	} while(ECanaShadow.CANES.bit.CCE != 1 );  		// Wait for CCE bit to be set..

	// configure timing
	ECanaShadow.CANBTC.all = 0;
	ECanaShadow.CANBTC.bit.BRPREG = 4;
	ECanaShadow.CANBTC.bit.TSEG2REG = 2;
	ECanaShadow.CANBTC.bit.TSEG1REG = 10;
    ECanaShadow.CANBTC.bit.SAM = 1;
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    // set control register bits
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR 	= 0;
    ECanaShadow.CANMC.bit.PDR 	= 0;
    ECanaShadow.CANMC.bit.SUSP 	= 0;
    ECanaShadow.CANMC.bit.MBCC 	= 1;
    ECanaShadow.CANMC.bit.SCB 	= 1;
    ECanaShadow.CANMC.bit.DBO 	= 1;
    ECanaShadow.CANMC.bit.WUBA 	= 1;
    ECanaShadow.CANMC.bit.ABO	= 0;
    ECanaShadow.CANMC.bit.STM	= 0;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    _memset((void *)&ECanaMboxes.MBOX0, 0, 32*sizeof(struct MBOX));

    ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

    ECanaShadow.CANGAM.all = ECanaRegs.CANGAM.all;
    ECanaShadow.CANGAM.bit.AMI = 1;
    ECanaRegs.CANGAM.all = ECanaShadow.CANGAM.all;

    ECanaMboxes.MBOX0.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX1.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX2.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX3.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX4.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX5.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX6.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX7.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX8.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX9.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX10.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX11.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX12.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX13.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX14.MSGID.all = 0xD0000000;
    ECanaMboxes.MBOX15.MSGID.all = 0xD0000000;

    ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    do {
       ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 ); 		// Wait for CCE bit to be  cleared..


	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_recv_mailboxes()
{
	struct ECAN_REGS ECanaShadow;
	EALLOW;

	ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
	ECanaShadow.CANMD.bit.MD16 = 0;
	ECanaShadow.CANMD.bit.MD17 = 0;
	ECanaShadow.CANMD.bit.MD18 = 0;
	ECanaShadow.CANMD.bit.MD19 = 0;
	ECanaShadow.CANMD.bit.MD20 = 0;
	ECanaShadow.CANMD.bit.MD21 = 0;
	ECanaShadow.CANMD.bit.MD22 = 0;
	ECanaShadow.CANMD.bit.MD23 = 0;
	ECanaShadow.CANMD.bit.MD24 = 0;
	ECanaShadow.CANMD.bit.MD25 = 0;
	ECanaShadow.CANMD.bit.MD26 = 0;
	ECanaShadow.CANMD.bit.MD27 = 0;
	ECanaShadow.CANMD.bit.MD28 = 0;
	ECanaShadow.CANMD.bit.MD29 = 0;
	ECanaShadow.CANMD.bit.MD30 = 0;
	ECanaShadow.CANMD.bit.MD31 = 0;
	ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;

	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_send_mailboxes()
{
	struct ECAN_REGS ECanaShadow;
	EALLOW;

	ECanaShadow.CANMD.all = ECanaRegs.CANMD.all;
	ECanaShadow.CANMD.bit.MD0 = 1;
	ECanaShadow.CANMD.bit.MD1 = 1;
	ECanaShadow.CANMD.bit.MD2 = 1;
	ECanaShadow.CANMD.bit.MD3 = 1;
	ECanaShadow.CANMD.bit.MD4 = 1;
	ECanaShadow.CANMD.bit.MD5 = 1;
	ECanaShadow.CANMD.bit.MD6 = 1;
	ECanaShadow.CANMD.bit.MD7 = 1;
	ECanaShadow.CANMD.bit.MD8 = 1;
	ECanaShadow.CANMD.bit.MD9 = 1;
	ECanaShadow.CANMD.bit.MD10 = 1;
	ECanaShadow.CANMD.bit.MD11 = 1;
	ECanaShadow.CANMD.bit.MD12 = 1;
	ECanaShadow.CANMD.bit.MD13 = 1;
	ECanaShadow.CANMD.bit.MD14 = 1;
	ECanaShadow.CANMD.bit.MD15 = 1;
	ECanaRegs.CANMD.all = ECanaShadow.CANMD.all;

	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_overwrite_protection()
{
	struct ECAN_REGS ECanaShadow;
	EALLOW;

	ECanaShadow.CANOPC.all = ECanaRegs.CANOPC.all;
	ECanaShadow.CANOPC.bit.OPC0 = 1;
	ECanaShadow.CANOPC.bit.OPC1 = 1;
	ECanaShadow.CANOPC.bit.OPC2 = 1;
	ECanaShadow.CANOPC.bit.OPC3 = 1;
	ECanaShadow.CANOPC.bit.OPC4 = 1;
	ECanaShadow.CANOPC.bit.OPC5 = 1;
	ECanaShadow.CANOPC.bit.OPC6 = 1;
	ECanaShadow.CANOPC.bit.OPC7 = 1;
	ECanaShadow.CANOPC.bit.OPC8 = 1;
	ECanaShadow.CANOPC.bit.OPC9 = 1;
	ECanaShadow.CANOPC.bit.OPC10 = 1;
	ECanaShadow.CANOPC.bit.OPC11 = 1;
	ECanaShadow.CANOPC.bit.OPC12 = 1;
	ECanaShadow.CANOPC.bit.OPC13 = 1;
	ECanaShadow.CANOPC.bit.OPC14 = 1;
	ECanaShadow.CANOPC.bit.OPC15 = 1;
	ECanaRegs.CANOPC.all = ECanaShadow.CANOPC.all;

	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init_acceptance_masks()
{
	EALLOW;

	ECanaLAMRegs.LAM0.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM1.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM2.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM3.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM4.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM5.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM6.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM7.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM8.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM9.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM10.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM11.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM12.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM13.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM14.all = 0x8FFFFFFF;
	ECanaLAMRegs.LAM15.all = 0x8FFFFFFF;

	EDIS;
}
/*---------------------------------------------------------------------------*/
void cana_dev_init()
{
	cana_dev_init_clock();
	cana_dev_init_gpio();
	cana_dev_init_peripheral();
	cana_dev_init_send_mailboxes();
	cana_dev_init_recv_mailboxes();
	cana_dev_init_overwrite_protection();
	cana_dev_init_acceptance_masks();
	cana_dev_mailbox_enable_all();
}
/*---------------------------------------------------------------------------*/
i_uint8 cana_dev_push(struct MBOX *mail)
{
	i_uint8 i;
	i_uint32 shiftRes;
	struct MBOX *ptr = (struct MBOX *)(&ECanaMboxes.MBOX0);
	for (i = 16; i < 32; i++) { // look for a non pending transmission mailbox
		shiftRes = ((i_uint64)0x00000001) << i;
		if (((ECanaRegs.CANTRS.all & shiftRes) == 0) && ((ECanaRegs.CANAA.all & shiftRes) == 0)) {
			// disable mailbox
			cana_dev_mailbox_disable(i);
			// update mailbox value
			ptr[i]= mail[0];
			// enable mailbox
			cana_dev_mailbox_enable(i);
			// set mailbox transfer flag
			ECanaRegs.CANTRS.all = shiftRes;
			return 1;
		}
	}
	return 0;
}
/*---------------------------------------------------------------------------*/
i_uint8 cana_dev_pop(struct MBOX * mail)
{
	i_uint8 i;
	i_uint32 shiftRes;
	struct MBOX *ptr = (struct MBOX *)(&ECanaMboxes.MBOX0);
	for (i = 0; i < 16; i++) {
		shiftRes = ((i_uint64)0x00000001) << i;
		if ((ECanaRegs.CANRMP.all & shiftRes) == shiftRes) {
			// update mailbox value
			mail[0].MSGID.all = ptr[i].MSGID.all;
			mail[0].MSGCTRL.all = ptr[i].MSGCTRL.all;
			mail[0].MDL.all = ptr[i].MDL.all;
			mail[0].MDH.all = ptr[i].MDH.all;
			// reset mailbox pending flag
			ECanaRegs.CANRMP.all = shiftRes;
			return 1;
		}
	}
	return 0;
}
