/** @file sys_main.c 
*   @brief Application main file
*   @date 15.December.2011
*   @version 03.00.00
*
*/

/* (c) Texas Instruments 2009-2012, All rights reserved. */

/* USER CODE BEGIN (0) */


// **************************************************************************
// the includes
#include "spi.h"
#include "can.h"

#include "sys_main.h"
/* USER CODE END */

#include "sys_common.h"
#include "system.h"

#include "sci.h"
#include "sys_dma.h"
#include <stdio.h>
#include <stdlib.h>

extern void dmaBTCAInterrupt(void);

/* dma control packet configuration stack */
g_dmaCTRL dma_config;

/* #define Enable_CIO      // Uncomment to enable Console CIO */
/* #define Enable_File_CIO // Uncomment to enable File CIO    */
#define Enable_SCI_Out
char buffer[4 * 500];


/* dma control packet configuration stack */
g_dmaCTRL g_dmaCTRLPKT;
g_dmaCTRL g_dmaCTRLPKTR;	// for receive
uint32_t DMA_Comp_Flag;

void Update_DMA_Comp_Flag();
typedef void (*t_isrFuncPTR)();
extern void vimChannelMap(uint32_t request, uint32_t channel, t_isrFuncPTR handler);
//void vimEnableInterrupt(uint32_t channel, systemInterrupt_t inttype);
extern void vimEnableInterrupt(uint32_t channel, int inttype);
extern void rs485Init(void);

/** @fn void number_string(char *string, uint32 count)
*   @brief Generate null ternimated string of characters starting at zero to count.
*   @note This function pads the end with extra null characters and overrun warning
*/
void number_string(char *string, uint32_t count) {
	uint32_t i, temp, offset = 0;

	for (i = 0; i < count; i++){
		temp = sprintf (&buffer[i + offset],"%d ", i);
		if (temp != -1U) {
			offset += temp - 1; // increment buffer by the number of characters written minus the null character.
		}
	}

	/* For debug purposes add extra characters to identify overrun */
	sprintf (&buffer[i + offset],"\0\0\0\0\0\0\0\0 !!! Overrun !!! ");

} /* number_string */

/** @fn void sci_printf(void)
*   @brief printf over sci function
*   @note This will transmit a formated variable argument string
*
*   This requires sciInit() to be called before to setup SCI2.
*   Length of resulting string is not to exceed length of local buffer variable.
*
*   Use compile time option Enable_CIO for debugging over JTAG to console or file.
*/
void sci_printf (char * format, ...) {
	uint8_t cSCI_printfbuffer[256] = {0};
	uint32_t length;

#ifdef Enable_CIO
	printf(format);
#endif

#ifdef Enable_SCI_Out
	va_list args;
	va_start (args, format);
	length = vsprintf ((char *)cSCI_printfbuffer, format, args);
	va_end (args);
	cSCI_printfbuffer[length+1] = 0;
	cSCI_printfbuffer[length+2] = 0;
//	sciSend(scilinREG, strlen((const char *)cSCI_printfbuffer) + 3, cSCI_printfbuffer);
	sciSend(sciREG, strlen((const char *)cSCI_printfbuffer) + 3, cSCI_printfbuffer);
#endif

#ifdef Enable_File_CIO
	fprintf(fid, format);
#endif
} // sci_printf



/** @fn void scidmaInit(short mode)
*   @brief Initialize the SCI and DMA to tranfer SCI data via DMA
*   @note This function configures the SCI to trigger a DMA request when the SCI TX is complete.
*/
void scidmaInit(sciBASE_t *sci)
{
	/* Enable DMA */
	dmaEnable();

	if (sci == sciREG) {          			/* SCI2 is the default serial comport on LAUNCHXL2 launch pads*/

		/* Enable Interrupt after reception of data */
		dmaEnableInterrupt(DMA_CH0, BTC);		/* DMA_CH0 is highest priority */

		/* assigning dma request: channel-0 with request line - 1  - TX*/
		/* DMA Request 29 is for LIN ( SCI2) Transmit */
		/* Refer Data sheet - Default DMA Request Map section */
		dmaReqAssign(DMA_CH0,31);


	} else if (0) { 				/* SCI1 */
		return;					   				/* SCI1 is not supported at this time */

		/* Enable Interrupt after reception of data */
		/*dmaEnableInterrupt(DMA_CH1, BTC);		// DMA_CH0 is highest priority */

		/* assigning dma request: channel-0 with request line - 1  - TX*/
		/* DMA Request 31 is for SCI1 Transmit */
		/* Refer Data sheet - Default DMA Request Map section */
		/*dmaReqAssign(DMA_CH1,31); */

	} else {
		return;					 				/* Unknown register */
	}

    /* - Populate dma control packets structure */
	g_dmaCTRLPKT.CHCTRL    = 0;                 /* channel control            */
	g_dmaCTRLPKT.ELCNT     = 1;                 /* element count              */
	g_dmaCTRLPKT.ELDOFFSET = 0;                 /* element destination offset */
	g_dmaCTRLPKT.ELSOFFSET = 0;                 /* element source offset      */
	g_dmaCTRLPKT.FRDOFFSET = 0;                 /* frame destination offset   */
	g_dmaCTRLPKT.FRSOFFSET = 0;                 /* frame source offset        */
	g_dmaCTRLPKT.PORTASGN  = 4;                 /* port b                     */
    g_dmaCTRLPKT.RDSIZE    = ACCESS_8_BIT;      /* read size                  */
	g_dmaCTRLPKT.WRSIZE    = ACCESS_8_BIT;      /* write size                 */
	g_dmaCTRLPKT.TTYPE     = FRAME_TRANSFER ;   /* transfer type              */
	g_dmaCTRLPKT.ADDMODERD = ADDR_INC1;         /* address mode read          */
	g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED;        /* address mode write         */
    g_dmaCTRLPKT.AUTOINIT  = AUTOINIT_OFF;      /* autoinit                   */

    /* Reset the Flag */
    DMA_Comp_Flag = 0x55AAD09E;

	/* Channel 40 - Enable the VIM channel in HalCoGen to include dmaBTCAInterrupt function */
	vimChannelMap(40, 40, &dmaBTCAInterrupt);

	/* Enable VIM DMA BTCA interrupt to CPU on SCI2 transfer complete */
	vimEnableInterrupt(40, SYS_IRQ);

} /* scidmaInit */
/* USER CODE END */


/** @fn void scidmaSend(char *source_address, short mode)
*   @brief Initialize the SCI and DMA to tranfer SCI data via DMA
*   @note This function configures the SCI to trigger a DMA request when the SCI TX is complete.
*
*   This function configures the DMA in single buffer or multibuffer mode.
*   In single buffer mode (0) the DMA moves each Byte to the SCI tranmit register when request is set.
*   In multi buffer mode (1)  the DMA moves 4 Bytes to the SCI transmit buffer when the request is set.
*/
void scidmaSend(char *source_address)
{
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
	uint8 dest_addr_offset=0;		/* 0 for LE */
#else
	uint8_t dest_addr_offset=3;		/* 3 for BE */
#endif

	/* Wait for the DMA to complete any existing transfers */
    while(DMA_Comp_Flag != 0x55AAD09E);

    /* Reset the Flag to not Done*/
    DMA_Comp_Flag = ~0x55AAD09E;

	/* - Populate dma control packets structure */
	g_dmaCTRLPKT.SADD       = (uint32_t)source_address;						/* source address             */

	if (1) {
    	g_dmaCTRLPKT.DADD   = (uint32_t)(&(sciREG->TD))+dest_addr_offset;	/* In big endianism devices, the destination address needs to be adjusted */
        g_dmaCTRLPKT.RDSIZE = ACCESS_8_BIT;     							/* read size                  */
    	g_dmaCTRLPKT.WRSIZE = ACCESS_8_BIT;     							/* write size                 */
        g_dmaCTRLPKT.FRCNT  = strlen(source_address);    					/* frame count                */

    } else {
    	g_dmaCTRLPKT.DADD      = (uint32_t)(&(sciREG->TD));	 				/* In big endianism devices, the destination address needs to be adjusted
    	                                                  	  	  	  	  	  	   	* for byte access. The DMA is a big endian master. But the SCI Transmit buffer
    	                                                  	  	  	  	  	     	    * is accessible at the least significant byte.  */
    	g_dmaCTRLPKT.RDSIZE    = ACCESS_32_BIT;   		 					/* read size                  */
    	g_dmaCTRLPKT.WRSIZE    = ACCESS_32_BIT;    		 					/* write size                 */
        g_dmaCTRLPKT.FRCNT     = strlen(source_address)/4+8;	    			/* frame count                */
    }

	/* - setting dma control packets for transmit */
    dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT);

    /* - setting the dma channel to trigger on h/w request */
    dmaSetChEnable(DMA_CH0, DMA_HW);

	/* Enable TX DMA */
    sciREG->SETINT = (1 << 16);

} /* scidmaSend */


/** @fn void main(void)
*   @brief Application main function
*   @note This function is empty by default.
*
*   This function is called after startup.
*   The user can use this function to implement the application.
*/


void main(void)
{
/* USER CODE BEGIN (3) */

	_mpuInit_();
	(*(volatile unsigned int *)(0xFFFFEA38))=0x83E70B13;
    (*(volatile unsigned int *)(0xFFFFEA3C))=0x95A4F1E0;
    (*(volatile unsigned int *)(0xFFFFEB88))=0x00000002;//ADC Alternate Trigger

    //enable all ePWM s + TZ + ECAP1,2,3,4 + EQEP1+EQEP2
    *(volatile unsigned int *) 0xFFFFEBA4 = 0x01010102; // Enable TBCLK 37[1]
#if 0
    *(volatile unsigned int *) 0xFFFFEB10 = 0x08010801; // nTZ1 0[19], nTZ2 0[27],
    *(volatile unsigned int *) 0xFFFFEB18 = 0x04010110; // ETPWM1A 2[26], EQEP2I 2[4]
    *(volatile unsigned int *) 0xFFFFEB1C = 0x01040101; // ETPWM1B 3[18]
    *(volatile unsigned int *) 0xFFFFEB20 = 0x20200104; // ETPWM2A 4[2], EQEP2A 4[21], EQEP2B 4[29]
    *(volatile unsigned int *) 0xFFFFEB24 = 0x01080404; // ETPWM2B 5[2], ETPWM3A 5[10], ETPWM3B 5[19]
    *(volatile unsigned int *) 0xFFFFEB2C = 0x01040101; // ETPWM5A 7[18]
    *(volatile unsigned int *) 0xFFFFEB30 = 0x01040104; // ETPWM5B 8[2], ECAP1 8[18]
    *(volatile unsigned int *) 0xFFFFEB34 = 0x01010801; //EQEP1B 9[11], SPI3CS0/EQEP1I 9[16/19]
    *(volatile unsigned int *) 0xFFFFEB40 = 0x20100101; // ECAP4 12[20],ECAP5 12[29]
    *(volatile unsigned int *) 0xFFFFEB40 = 0x04010101; // ECAP6 13[26]
    *(volatile unsigned int *) 0xFFFFEB54 = 0x01010110; // nTZ3 17[4]
    *(volatile unsigned int *) 0xFFFFEB5C = 0x01010801; // EQEP2S 19[11]
    *(volatile unsigned int *) 0xFFFFEB60 = 0x01100101; // EQEP1S 20[20]
    *(volatile unsigned int *) 0xFFFFEB7C = 0x01010104; // ETPWM4A 27[2]
    *(volatile unsigned int *) 0xFFFFEB94 = 0x01010102; // ETPWM4B 33[1], SPI3SOMI/ECAP2 33[8/10], SPI3SIMO/ECAP3 33[16/18],SPI3CLK/EQEP1A 33[24/26]
    *(volatile unsigned int *) 0xFFFFEB98 = 0x01020201; // ETPWM6A 34[9], ETPWM6B 34[17]
#endif
    *(volatile unsigned int *) 0xFFFFEB8C =0x01010102;//SRC=110, A2 31[1]
    // RC540 IOMUX
    *(volatile unsigned int *) (0xFFFFEB10 + 4*0) = 0x00000100;	// N2HET1[11]
    *(volatile unsigned int *) (0xFFFFEB10 + 4*2) = 0x04000010;	// ETPWM1A,EQEP2I
    *(volatile unsigned int *) (0xFFFFEB10 + 4*3) = 0x00040000;	// ETPWM1B
    *(volatile unsigned int *) (0xFFFFEB10 + 4*4) = 0x20200004;	// ETPWM2A,EQEP2A,EQEP2B
    *(volatile unsigned int *) (0xFFFFEB10 + 4*5) = 0x00080404;	// ETPWM2B,ETPWM3A,ETPWM3B
    *(volatile unsigned int *) (0xFFFFEB10 + 4*6) = 0x00100010;	// ETPWM7B,ETPWM7A
    *(volatile unsigned int *) (0xFFFFEB10 + 4*7) = 0x00020200;	// N2HET1[25],SCIRX
    *(volatile unsigned int *) (0xFFFFEB10 + 4*8) = 0x00010202;	// N2HET1[15],SCITX,N2HET1[19]
    *(volatile unsigned int *) (0xFFFFEB10 + 4*9) = 0x00080800;	// EQEP1B,EQEP1I
    *(volatile unsigned int *) (0xFFFFEB10 + 4*10) = 0x00000001;	// AD1EVT
    *(volatile unsigned int *) (0xFFFFEB10 + 4*11) = 0x01000000;	// N2HET1[24]
    *(volatile unsigned int *) (0xFFFFEB10 + 4*12)   = 0x11010000;	// MIBSPI5SOMI[1],MIBSPI1NENA,MIBSPI5NENA
    *(volatile unsigned int *) (0xFFFFEB10 + 4*13) = 0x01010101;	// MIBSPI1NCS[0],MIBSPI5CLK,MIBSPI5SIMO,MIBSPI5SOMI[0]
    *(volatile unsigned int *) (0xFFFFEB10 + 4*20) = 0x00020000;	// N2HET1[17]
    *(volatile unsigned int *) (0xFFFFEB10 + 4*27) = 0x00000004;	// ETPWM4A
    *(volatile unsigned int *) (0xFFFFEB10 + 4*33) = 0x04010102;	// ETPWM4B,MIBSPI3SOMI[0],MIBSPI3SIMO[0],EQEP1A
    *(volatile unsigned int *) (0xFFFFEB10 + 4*34) = 0x00020200;	// ETPWM6A,ETPWM6B

    (*(volatile unsigned int *)(0xFFFFEA38))=0x0;
    (*(volatile unsigned int *)(0xFFFFEA3C))=0x0;


	// RS485 initialize
	adcREG1->EVTDIR |= 0x1;
	adcREG1->EVTOUT |= 0x1;
    
	rs485Init();

	/* Print header on SCI2 */
	sci_printf("\033[2J"); // Clear terminal & return home commands
	sci_printf(" Hercule SCI DMA Example \n\r");
	sci_printf("*******************************************************************************\n\r\n\r");

	/* Setup null terminated string to transmit */
	number_string((char *) buffer, 500);

	/* Init SCI for DMA transfers */
	scidmaInit(sciREG);			/* Requires sciInit to be called first */

	/* Enable CPU Interrupts */
	_enable_IRQ();

	sci_printf("scidmaSend Example - DMA to transfer single Bytes from RAM to the SCI\n\r");

    scidmaSend(buffer);
    
    while(1);

/* USER CODE END */
}


/* USER CODE BEGIN (4) */

/** @fn void Update_DMA_Comp_Flag()
*   @brief Switch the DMA complete flag to done and disable the SCI2 TX DMA interrupt
*   @note This function needs to be called by dmaGroupANotification in notification.c
*/
void Update_DMA_Comp_Flag()
{
    /* Set the Flag to Done*/
	DMA_Comp_Flag = 0x55AAD09E;

	/* Disable TX DMA Interrupt */
	sciREG->CLRINT = (1 << 16);
	sciREG->CLRINT = (3 << 17);
}


/********************************************************************************
	ESM Notification	(a dummy-function for the compiler, no affects)
********************************************************************************/
void esmGroup1Notification(uint32_t channel){return;}
void esmGroup2Notification(uint32_t channel){return;}
void rtiNotification(uint32_t channel){return;}
void adcNotification(adcBASE_t *adc, uint32_t group){return;}
/* USER CODE END */
