/*******************************************************************
Analog Devices, Inc. All Rights Reserved.

This software is proprietary and confidential.  By using this software
you agree to the terms of the associated Analog Devices License Agreement.

Project Name:  	Power_On_Self_Test

Hardware:		ADSP-BF526/BF537 EZ-KIT Lite

Description:	This file is used to initialize everything necessary
				to write to the LCD display
*******************************************************************/

/*******************************************************************
*  include files and processor specific defines
*******************************************************************/

#if defined(__ADSPBF537__)		/* __ADSPBF537__ */

#include <cdefBF537.h>

#define LQ035Q1DH02_DMA_NEXT_DESC_PTR		DMA0_NEXT_DESC_PTR
#define LQ035Q1DH02_CS						PF14
#define LQ035Q1DH02_PPI_DMA_IMASK			SIC_IMASK
#define LQ035Q1DH02_PPI_DMA_IMASK_BIT		0x00000010
#define LQ035Q1DH02_SPI_CTRL				SPI_CTL

#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */

#include <cdefBF526.h>

#define LQ035Q1DH02_DMA_NEXT_DESC_PTR		DMA0_NEXT_DESC_PTR
#define LQ035Q1DH02_CS						PG1
#define LQ035Q1DH02_PPI_DMA_IMASK			SIC_IMASK0
#define LQ035Q1DH02_PPI_DMA_IMASK_BIT		0x00008000
#define LQ035Q1DH02_SPI_CTRL				SPI_CTL

#elif defined(__ADSPBF548__)	/* __ADSPBF548__ */

#include <cdefBF548.h>

#define LQ035Q1DH02_DMA_NEXT_DESC_PTR		DMA13_NEXT_DESC_PTR
#define LQ035Q1DH02_CS						PG5
#define LQ035Q1DH02_PPI_DMA_IMASK			SIC_IMASK1
#define LQ035Q1DH02_PPI_DMA_IMASK_BIT		0x00000020
#define LQ035Q1DH02_SPI_CTRL				SPI1_CTL

#elif defined(__ADSPBF518__)	/* __ADSPBF518__ */

#include <cdefBF518.h>

#define LQ035Q1DH02_DMA_NEXT_DESC_PTR		DMA0_NEXT_DESC_PTR
#define LQ035Q1DH02_CS						PH6
#define LQ035Q1DH02_PPI_DMA_IMASK			SIC_IMASK0
#define LQ035Q1DH02_PPI_DMA_IMASK_BIT		0x00008000
#define LQ035Q1DH02_SPI_CTRL				SPI1_CTL

#else							/* NOT DEFINED */
#error *** Processor not supported ***
#endif

#include <ccblkfn.h>
#include <sys\exception.h>
#include "lq035q1dh02.h"


#define pLQ035Q1DH02_DMA_NEXT_DESC_PTR 		((void * volatile *)LQ035Q1DH02_DMA_NEXT_DESC_PTR)
#define pLQ035Q1DH02_DMA_START_ADDR 		((void * volatile *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x4))
#define pLQ035Q1DH02_DMA_CONFIG 			((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x8))
#define pLQ035Q1DH02_DMA_X_COUNT 			((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x10))
#define pLQ035Q1DH02_DMA_X_MODIFY 			((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x14))
#define pLQ035Q1DH02_DMA_Y_COUNT 			((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x18))
#define pLQ035Q1DH02_DMA_Y_MODIFY 			((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x1C))
#define pLQ035Q1DH02_DMA_IRQ_STATUS 		((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x28))
#define pLQ035Q1DH02_DMA_PERIPHERAL_MAP 	((volatile unsigned short *)(LQ035Q1DH02_DMA_NEXT_DESC_PTR + 0x2C))

#define pLQ035Q1DH02_PPI_DMA_IMASK 			((volatile unsigned long *)LQ035Q1DH02_PPI_DMA_IMASK)

#define pLQ035Q1DH02_SPI_CTRL 				((volatile unsigned short *)LQ035Q1DH02_SPI_CTRL)
#define pLQ035Q1DH02_SPI_FLG 				((volatile unsigned short *)(LQ035Q1DH02_SPI_CTRL + 0x4))
#define pLQ035Q1DH02_SPI_STAT 				((volatile unsigned short *)(LQ035Q1DH02_SPI_CTRL + 0x8))
#define pLQ035Q1DH02_SPI_TDBR 				((volatile unsigned short *)(LQ035Q1DH02_SPI_CTRL + 0xC))
#define pLQ035Q1DH02_SPI_RDBR 				((volatile unsigned short *)(LQ035Q1DH02_SPI_CTRL + 0x10))
#define pLQ035Q1DH02_SPI_BAUD 				((volatile unsigned short *)(LQ035Q1DH02_SPI_CTRL + 0x14))




/*******************************************************************
*  function prototypes
*******************************************************************/
static void Setup_SPI(int spi_setting);
static void SPI_OFF(void);
static void Wait_For_SPIF(void);
static void Clear_CS(void);
static void Set_CS(void);

/****************************************************************************
*   Function:    DMA0_PPI_ISR
*   Description: PPI ISR
******************************************************************************/
EX_INTERRUPT_HANDLER(DMA_PPI_ISR)
{
	/* acknowledge the interrupt request */
	*pLQ035Q1DH02_DMA_IRQ_STATUS = 0x1;
	ssync();
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Init_PPI_Ints
*   Description: Initialize PPI interrupts
******************************************************************************/
void LQ035Q1DH02_Init_PPI_Ints(void)
{
#if defined(__ADSPBF548__)		/* __ADSPBF548__ */

	register_handler(ik_ivg9, DMA_PPI_ISR);	/* assign DMA_PPI_ISR to interrupt vector 9 */

	*pILAT |= EVT_IVG9;						/* clear pending IVG8 interrupts */
	ssync();
#else

	register_handler(ik_ivg8, DMA_PPI_ISR);		/* assign DMA_PPI_ISR to interrupt vector 8 */

	*pILAT |= EVT_IVG8;							/* clear pending IVG8 interrupts */
	ssync();
#endif

	*pLQ035Q1DH02_PPI_DMA_IMASK |= LQ035Q1DH02_PPI_DMA_IMASK_BIT; 	/* enable DMA0 PPI interrupt enabled */
	ssync();
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Enable_PPI
*   Description: Enable PPI
******************************************************************************/
void LQ035Q1DH02_Enable_PPI (void)
{
#if defined(__ADSPBF548__)		/* __ADSPBF548__ */
	*pEPPI1_CONTROL |= 0x1;
#else
	*pPPI_CONTROL |= PORT_EN;
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Disable_PPI
*   Description: Disable PPI
******************************************************************************/
void LQ035Q1DH02_Disable_PPI (void)
{
#if defined(__ADSPBF548__)		/* __ADSPBF548__ */
	*pEPPI1_CONTROL &= ~0x1;
#else
	*pPPI_CONTROL &= ~PORT_EN;
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Init_PPI
*   Description: Initialize necessary PPI registers
******************************************************************************/
void LQ035Q1DH02_Init_PPI(void)
{
#if defined(__ADSPBF537__)		/* __ADSPBF537__ */

	/* configure PPI D0-D15 */
	*pPORTG_FER |= 0xFFFF;
	ssync();

	*pPORT_MUX &= 0xF1FF;
	ssync();

	/* PPI CLK, FS1, FS2 */
	*pPORTF_FER |= 0x8300;
    ssync();

#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */

	/* configure PPI D0-D15 */
	*pPORTF_FER |= 0xFFFF;
    ssync();

    /* enable PPICLK/TMRCLK */
    *pPORTF_MUX |= 0x1000;
    ssync();

    /* configure PPI FS2 */
	*pPORTG_FER |= 0x0020;
    ssync();
	*pPORTG_MUX &= 0xFFF3;
    ssync();

#elif defined(__ADSPBF548__)	/* __ADSPBF548__ */

	/* configure PPI D0-D15 */
	*pPORTD_MUX = 0x0000;
    *pPORTD_FER = 0xFFFF;
    ssync();

    /* enable PPI1 CLK, FS1, and FS2 */
    *pPORTE_MUX = 0x0000;
    *pPORTE_FER |= 0x3800;
    ssync();

#elif defined(__ADSPBF518__)	/* __ADSPBF518__ */

	/* configure PPI D0-D15 */
	*pPORTF_FER |= 0xFFFF;
    ssync();
    /* enable PPI D0-D15 */
    *pPORTF_MUX |= 0x555;
    ssync();

    /* configure PPI CLK, FS1, FS2 */
	*pPORTG_FER |= 0x00E0;
    ssync();
	*pPORTG_MUX |= 0x80;
    ssync();

#else							/* NOT DEFINED */
#error *** Processor not supported ***
#endif

#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	*pEPPI1_HDELAY = 8;
	*pEPPI1_VDELAY = 2;

	*pEPPI1_LINE = 336;
	*pEPPI1_FRAME = 244;

	*pEPPI1_FS1W_HBL = 1;
	*pEPPI1_FS1P_AVPL = 336;
	*pEPPI1_FS2W_LVB = 1;
	*pEPPI1_FS2P_LAVF = 244*336;

	*pEPPI1_HCOUNT = 320;
	*pEPPI1_VCOUNT = 240;

	*pEPPI1_CLKDIV = 20;		// PPI CLK = 133/20 = 6.65Mhz
    *pEPPI1_CONTROL = 0x27C2E;

	ssync();
#else
	*pPPI_DELAY = H_START;
	*pPPI_COUNT = (H_ACTPIX-1);
	*pPPI_FRAME = V_LINES;

	*pPPI_CONTROL = PPI_TX_MODE			|	/* output mode , PORT_DIR */
					PPI_XFER_TYPE_11	|	/* sync mode XFR_TYPE */
					PPI_PORT_CFG_01		|	/* two frame sync	PORT_CFG */
				    DLEN_16				|	/* 16 bit data length */
					PPI_POLS_1;				/* faling edge syncs POLS */
#endif

}//end Init_PPI

/****************************************************************************
*   Function:    LQ035Q1DH02_Init_DMA
*   Description: Initialize DMA
******************************************************************************/
void LQ035Q1DH02_Init_DMA(void * buffer)
{
	DESCRIPTOR_LARGE *pChannel = (DESCRIPTOR_LARGE *)buffer;

	*pLQ035Q1DH02_DMA_NEXT_DESC_PTR = pChannel->pNext;
	*pLQ035Q1DH02_DMA_START_ADDR = pChannel->StartAddress;

	/* X count */
	*pLQ035Q1DH02_DMA_X_COUNT = pChannel->XCount;
	*pLQ035Q1DH02_DMA_X_MODIFY = pChannel->XModify;

	/* Y count */
	*pLQ035Q1DH02_DMA_Y_COUNT = pChannel->YCount;
	*pLQ035Q1DH02_DMA_Y_MODIFY = pChannel->YModify;

#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	/* map PPI as peripheral for this DMA */
	*pLQ035Q1DH02_DMA_PERIPHERAL_MAP = 0x0;
#endif

	/* DMA Config, to be replaced by definitions */
	*pLQ035Q1DH02_DMA_CONFIG = pChannel->Config;

}//end Init_DMA

/****************************************************************************
*   Function:    LQ035Q1DH02_Enable_DMA
*   Description: Enable DMA
******************************************************************************/
void LQ035Q1DH02_Enable_DMA (void)
{
	*pLQ035Q1DH02_DMA_CONFIG |= DMAEN;
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Disable_DMA
*   Description: Disable DMA
******************************************************************************/
void LQ035Q1DH02_Disable_DMA (void)
{
	*pLQ035Q1DH02_DMA_CONFIG &= ~DMAEN;
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Init_TIMER0
*   Description: Init Timer0 to act as the horizontal frame sync
******************************************************************************/
void LQ035Q1DH02_Init_TIMER0 (void)
{
#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	*pTIMER_DISABLE |= TIMDIS0;						/* disable Timer */
	ssync();
	*pTIMER_STATUS  |= TIMIL0 | TOVF_ERR0 | TRUN0;	/* clear status */
	ssync();

	*pTIMER0_PERIOD  = H_PERIOD;
	ssync();
	*pTIMER0_WIDTH   = H_PULSE;
	ssync();

	*pTIMER0_CONFIG  = TMODE_PWMOUT |
					   PERIOD_CNT   |
					   TIN_SEL      |
					   CLK_SEL      |
					   EMU_RUN;
	ssync();
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Enable_TIMER0
*   Description: Enable timer0
******************************************************************************/
void LQ035Q1DH02_Enable_TIMER0 (void)
{
#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	*pTIMER_ENABLE  |= TIMEN0;
	ssync();
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Init_TIMER1
*   Description: Init Timer1 to act as the veritical frame sync
******************************************************************************/
void LQ035Q1DH02_Init_TIMER1 (void)
{
#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	*pTIMER_DISABLE |= TIMDIS1;						/* disable Timer */
	ssync();
	*pTIMER_STATUS  |= TIMIL1 | TOVF_ERR1 | TRUN1;	/* clear status */
	ssync();


	*pTIMER1_PERIOD  = V_PERIOD;
	ssync();
	*pTIMER1_WIDTH   = V_PULSE;
	ssync();

	*pTIMER1_CONFIG  = TMODE_PWMOUT |
					   PERIOD_CNT   |
					   TIN_SEL      |
					   CLK_SEL      |
					   EMU_RUN;
	ssync();
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Enable_TIMER1
*   Description: Enable timer1
******************************************************************************/
void LQ035Q1DH02_Enable_TIMER1 (void)
{
#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	*pTIMER_ENABLE  |= TIMEN1;
	ssync();
#endif
}

/****************************************************************************
*   Function:    LQ035Q1DH02_Disable_Timers
*   Description: Disable timer0 and timer1
******************************************************************************/
void LQ035Q1DH02_Disable_Timers (void)
{
#if defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* don't do anything here */
#else
	*pTIMER_DISABLE  |= (TIMDIS1| TIMDIS0);
	ssync();
#endif
}

/****************************************************************************
*   Function:    Setup_SPI
*   Description: setup spi for communication with the maxim 1233
******************************************************************************/
void Setup_SPI(int spi_setting)
{
  	int i;

#if defined(__ADSPBF537__)		/* __ADSPBF537__ */

	/* configure SPI SCK, MISO, and MOSI */
	*pPORTF_FER   |= 0x3800;

#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */

	/* configure SPI SCK, MISO, and MOSI */
	*pPORTG_FER   |= 0x1C;
	*pPORTG_MUX   &= 0xFFFC;

#elif defined(__ADSPBF548__)	/* __ADSPBF548__ */

	/* configure SPI SCK, MISO, and MOSI */
	*pPORTG_FER   = PG8 | PG9 | PG10;
	*pPORTG_MUX   &= (~0x3F0000);


#elif defined(__ADSPBF518__)	/* __ADSPBF518__ */

	/* configure SPI SCK, MISO, and MOSI */
	*pPORTH_FER   |= 0xE;
	*pPORTH_MUX   = 0x01;

#else							/* NOT DEFINED */
#error *** Processor not supported ***
#endif

   	for(i=0; i<100; i++)
	{
		asm("nop;");
	}

    *pLQ035Q1DH02_SPI_BAUD = BAUD_DIV;		/* set SPI BAUD */
   	*pLQ035Q1DH02_SPI_CTRL = spi_setting;	/* configure SPI CTL */
}

/****************************************************************************
*   Function:    SPI_OFF
*   Description: disable the SPI
******************************************************************************/
void SPI_OFF(void)
{
	int i;

	*pLQ035Q1DH02_SPI_CTRL = 0x0000;	/* disable SPI */
	*pLQ035Q1DH02_SPI_FLG = 0;
	for( i=0 ; i < SPI_DELAY; i++ )
	{
		asm("nop;");
	}
}

/****************************************************************************
*   Function:    Wait_For_SPIF
*   Description: Polls the SPIF (SPI single word transfer complete) bit
* 				 of SPISTAT until the transfer is complete.
******************************************************************************/
void Wait_For_SPIF()
{
	int n;
	unsigned char dummyread;

	for( n=0; n < SPI_DELAY; n++ )
	{
		asm("nop;");
	}

	while(1)
	{
		unsigned short iTest = *pLQ035Q1DH02_SPI_STAT;
		if( (iTest & SPIF) )
		{
			break;
		}
	}

	dummyread = *pLQ035Q1DH02_SPI_RDBR;	/*read dummy to empty the receive register */
	asm("nop;");
}

/****************************************************************************
*   Function:    Select_LQ035Q1DH02_Register
*   Description: Select the Register in the lq035q1dh02
******************************************************************************/
void Select_LQ035Q1DH02_Register(unsigned char LCDReg)
{
	unsigned char FirstByte = 0x74;	/* DC and RW low */
	unsigned char SecondByte = 0;
	unsigned char dummyread;

	/* configure SPI registers */
	Setup_SPI( (COMMON_SPI_SETTINGS|TIMOD01) );

	/* pull CS low */
	Clear_CS();

	/* write to the register passed in */
	*pLQ035Q1DH02_SPI_TDBR = FirstByte;
	Wait_For_SPIF();

	*pLQ035Q1DH02_SPI_TDBR = SecondByte;
	Wait_For_SPIF();

	*pLQ035Q1DH02_SPI_TDBR = LCDReg;
	Wait_For_SPIF();

	/* purge the RX FIFO */
	dummyread  = *pLQ035Q1DH02_SPI_RDBR;

	/* CS back high */
	Set_CS();

	/* Turns the SPI off */
	SPI_OFF();

	asm("nop;");
}

/****************************************************************************
*   Function:    Write_LQ035Q1DH02_Data
*   Description: write data to the register selected by SelectLCDRegister
******************************************************************************/
void Write_LQ035Q1DH02_Data(unsigned short data)
{
	unsigned char FirstByte = 0x76;	/* DC high and RW low */
	unsigned char dummyread;

	/* configure SPI registers */
	Setup_SPI( (COMMON_SPI_SETTINGS|TIMOD01) );

	/* pull CS low */
	Clear_CS();

	/* write first byte telling part a write is starting */
	*pLQ035Q1DH02_SPI_TDBR = FirstByte;
	Wait_For_SPIF();

	/* write HI byte */
	*pLQ035Q1DH02_SPI_TDBR = (data >> 8) & 0xFF;
	Wait_For_SPIF();

	/* write LO byte */
	*pLQ035Q1DH02_SPI_TDBR = data & 0xFF;
	Wait_For_SPIF();

	/* purge the RX FIFO */
	dummyread  = *pLQ035Q1DH02_SPI_RDBR;

	/* CS back high */
	Set_CS();

	/* Turns the SPI off */
	SPI_OFF();
}

/****************************************************************************
*   Function:    Clear_CS
*   Description: clears the chip select
******************************************************************************/
void Clear_CS()
{

#if defined(__ADSPBF537__)		/* __ADSPBF537__ */
	/* pull CS low */
	*pPORTFIO_DIR |= LQ035Q1DH02_CS;
 	*pPORTFIO_CLEAR = LQ035Q1DH02_CS;
#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */
	/* pull CS low */
	*pPORTGIO_DIR |= LQ035Q1DH02_CS;
 	*pPORTGIO_CLEAR = LQ035Q1DH02_CS;
#elif defined(__ADSPBF548__)	/* __ADSPBF548__ */
 	/* pull CS low */
 	*pPORTG_DIR_SET = LQ035Q1DH02_CS;
 	*pPORTG_CLEAR = LQ035Q1DH02_CS;
#elif defined(__ADSPBF518__)	/* __ADSPBF518__ */
	/* pull CS low */
	*pPORTHIO_DIR |= LQ035Q1DH02_CS;
 	*pPORTHIO_CLEAR = LQ035Q1DH02_CS;
#else							/* NOT DEFINED */
#error *** Processor not supported ***
#endif

}

/****************************************************************************
*   Function:    Set_CS
*   Description: sets the chip select
******************************************************************************/
void Set_CS()
{

#if defined(__ADSPBF537__)		/* __ADSPBF537__ */
	/* CS back high */
	*pPORTFIO_SET = LQ035Q1DH02_CS;
#elif defined(__ADSPBF526__)	/* __ADSPBF526__ */
	/* CS back high */
	*pPORTGIO_SET = LQ035Q1DH02_CS;
#elif defined(__ADSPBF548__)	/* __ADSPBF548__ */
	/* CS back high */
	*pPORTG_SET = LQ035Q1DH02_CS;
#elif defined(__ADSPBF518__)	/* __ADSPBF518__ */
	/* CS back high */
	*pPORTHIO_SET = LQ035Q1DH02_CS;
#else							/* NOT DEFINED */
#error *** Processor not supported ***
#endif

}
