/*****************************************************************************

Henry Laredo Quispe
Jr. Pablo Bermudez 214 Of.1004 - Jesus Maria
Lima Lima LIMA 01
Peru
(511) 423-0500


 *  Solomon Systech. SSD1963 LCD controller driver
 *****************************************************************************
 * FileName:        SSD1963.c
 * Dependencies:    SSD1963.h
 * Processor:       Microchip PIC32MX360F512L
 * Compiler:       	MPLAB C32 version 1.10 or higher
 * Linker:          MPLAB LINK32
 * Company:			TechToys Company
 *
 * Author           Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * John Leung		    17/06/2011
 *****************************************************************************/

#include "SSD1963.h"




/******************************** GLOBAL VARIABLE ********************************/
/**************** LOCAL FUNCTION PROTOTYPE (SSD1963 SPECIFIC) ****************/
static void SetArea(SHORT start_x, SHORT start_y, SHORT end_x, SHORT end_y);
static void GPIO_WR(BYTE pin, BOOL state);

                             
const char FONT[51][5] ={0x00, 0x00, 0x00, 0x00, 0x00, // SPACE
                         0x00, 0x00, 0x5F, 0x00, 0x00, // !
                         0x00, 0x03, 0x00, 0x03, 0x00, // "
                         0x14, 0x3E, 0x14, 0x3E, 0x14, // #
                         0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
                         0x43, 0x33, 0x08, 0x66, 0x61, // %
                         0x36, 0x49, 0x55, 0x22, 0x50, // &
                         0x00, 0x05, 0x03, 0x00, 0x00, // '
                         0x00, 0x1C, 0x22, 0x41, 0x00, // (
                         0x00, 0x41, 0x22, 0x1C, 0x00, // )
                         0x14, 0x08, 0x3E, 0x08, 0x14, // *
                         0x08, 0x08, 0x3E, 0x08, 0x08, // +
                         0x00, 0x50, 0x30, 0x00, 0x00, // ,
                         0x08, 0x08, 0x08, 0x08, 0x08, // -
                         0x00, 0x00, 0x60, 0x60, 0x00, // .
                         0x20, 0x10, 0x08, 0x04, 0x02, // /
                         0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
                         0x00, 0x04, 0x02, 0x7F, 0x00, // 1
                         0x42, 0x61, 0x51, 0x49, 0x46, // 2
                         0x22, 0x41, 0x49, 0x49, 0x36, // 3
                         0x18, 0x14, 0x12, 0x7F, 0x10, // 4
                         0x27, 0x45, 0x45, 0x45, 0x39, // 5
                         0x3E, 0x49, 0x49, 0x49, 0x32, // 6
                         0x01, 0x01, 0x71, 0x09, 0x07, // 7
                         0x36, 0x49, 0x49, 0x49, 0x36, // 8
                         0x26, 0x49, 0x49, 0x49, 0x3E, // 9
                         0x00, 0x36, 0x36, 0x00, 0x00, // :
                         0x00, 0x56, 0x36, 0x00, 0x00, // ;
                         0x08, 0x14, 0x22, 0x41, 0x00, // <
                         0x14, 0x14, 0x14, 0x14, 0x14, // =
                         0x00, 0x41, 0x22, 0x14, 0x08, // >
                         0x02, 0x01, 0x51, 0x09, 0x06, // ?
                         0x3E, 0x41, 0x59, 0x55, 0x5E, // @
                         0x7E, 0x09, 0x09, 0x09, 0x7E, // A
                         0x7F, 0x49, 0x49, 0x49, 0x36, // B
                         0x3E, 0x41, 0x41, 0x41, 0x22, // C
                         0x7F, 0x41, 0x41, 0x41, 0x3E, // D
                         0x7F, 0x49, 0x49, 0x49, 0x41, // E
                         0x7F, 0x09, 0x09, 0x09, 0x01, // F
                         0x3E, 0x41, 0x41, 0x49, 0x3A, // G
                         0x7F, 0x08, 0x08, 0x08, 0x7F, // H
                         0x00, 0x41, 0x7F, 0x41, 0x00, // I
                         0x30, 0x40, 0x40, 0x40, 0x3F, // J
                         0x7F, 0x08, 0x14, 0x22, 0x41, // K
                         0x7F, 0x40, 0x40, 0x40, 0x40, // L
                         0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
                         0x7F, 0x02, 0x04, 0x08, 0x7F, // N
                         0x3E, 0x41, 0x41, 0x41, 0x3E, // O
                         0x7F, 0x09, 0x09, 0x09, 0x06, // P
                         0x1E, 0x21, 0x21, 0x21, 0x5E, // Q
                         0x7F, 0x09, 0x09, 0x09, 0x76};// R

const char FONT2[44][5]={0x26, 0x49, 0x49, 0x49, 0x32, // S
                         0x01, 0x01, 0x7F, 0x01, 0x01, // T
                         0x3F, 0x40, 0x40, 0x40, 0x3F, // U
                         0x1F, 0x20, 0x40, 0x20, 0x1F, // V
                         0x7F, 0x20, 0x10, 0x20, 0x7F, // W
                         0x41, 0x22, 0x1C, 0x22, 0x41, // X
                         0x07, 0x08, 0x70, 0x08, 0x07, // Y
                         0x61, 0x51, 0x49, 0x45, 0x43, // Z
                         0x00, 0x7F, 0x41, 0x00, 0x00, // [
                         0x02, 0x04, 0x08, 0x10, 0x20, // 
                         0x00, 0x00, 0x41, 0x7F, 0x00, // ]
                         0x04, 0x02, 0x01, 0x02, 0x04, // ^
                         0x40, 0x40, 0x40, 0x40, 0x40, // _
                         0x00, 0x01, 0x02, 0x04, 0x00, // `
                         0x20, 0x54, 0x54, 0x54, 0x78, // a
                         0x7F, 0x44, 0x44, 0x44, 0x38, // b
                         0x38, 0x44, 0x44, 0x44, 0x44, // c
                         0x38, 0x44, 0x44, 0x44, 0x7F, // d
                         0x38, 0x54, 0x54, 0x54, 0x18, // e
                         0x04, 0x04, 0x7E, 0x05, 0x05, // f
                         0x08, 0x54, 0x54, 0x54, 0x3C, // g
                         0x7F, 0x08, 0x04, 0x04, 0x78, // h
                         0x00, 0x44, 0x7D, 0x40, 0x00, // i
                         0x20, 0x40, 0x44, 0x3D, 0x00, // j
                         0x7F, 0x10, 0x28, 0x44, 0x00, // k
                         0x00, 0x41, 0x7F, 0x40, 0x00, // l
                         0x7C, 0x04, 0x78, 0x04, 0x78, // m
                         0x7C, 0x08, 0x04, 0x04, 0x78, // n
                         0x38, 0x44, 0x44, 0x44, 0x38, // o
                         0x7C, 0x14, 0x14, 0x14, 0x08, // p
                         0x08, 0x14, 0x14, 0x14, 0x7C, // q
                         0x00, 0x7C, 0x08, 0x04, 0x04, // r
                         0x48, 0x54, 0x54, 0x54, 0x20, // s
                         0x04, 0x04, 0x3F, 0x44, 0x44, // t
                         0x3C, 0x40, 0x40, 0x20, 0x7C, // u
                         0x1C, 0x20, 0x40, 0x20, 0x1C, // v
                         0x3C, 0x40, 0x30, 0x40, 0x3C, // w
                         0x44, 0x28, 0x10, 0x28, 0x44, // x
                         0x0C, 0x50, 0x50, 0x50, 0x3C, // y
                         0x44, 0x64, 0x54, 0x4C, 0x44, // z
                         0x00, 0x08, 0x36, 0x41, 0x41, // {
                         0x00, 0x00, 0x7F, 0x00, 0x00, // |
                         0x41, 0x41, 0x36, 0x08, 0x00, // }
                         0x00, 0x07, 0x05, 0x07, 0x00};// °
                         //0x02, 0x01, 0x02, 0x04, 0x02};// ~
 
//BYTE _gpioStatus = 0;

/*********************************************************************
* Macros:  WriteCommand(cmd)
*
* PreCondition: 
*
* Input: cmd - controller command
*
* Output: none
*
* Side Effects: none
*
* Overview: writes command
*
* Note: Since Microchip's PMP module is used, the syntax PMDIN = cmd
*		is used. For other MCUs, this could be PORTx=cmd that PORTx
*		is the data bus from your MCU.
********************************************************************/
#define WriteCommand(cmd) {RS_LAT_BIT = 0;LATD = cmd;CS_LAT_BIT = 0;WR_LAT_BIT = 0;WR_LAT_BIT = 1;CS_LAT_BIT = 1;}

/*********************************************************************
* Function:  void  WriteData(WORD data)
*
* PreCondition: 
*
* Input:  value - value to be written in WORD format
*
* Output: none
*
* Side Effects: none
*
* Overview: 
*
* Note: Since Microchip's PMP module is used, the syntax PMDIN = data
*		is used. For other MCUs, this could be PORTx=data that PORTx
*		is the data bus from your MCU.
********************************************************************/
#define WriteData(data) {RS_LAT_BIT = 1;LATD = data;WR_LAT_BIT = 0;WR_LAT_BIT = 1;}


/*********************************************************************
* Function:  SetArea(start_x,start_y,end_x,end_y)
*
* PreCondition: SetActivePage(page)
*
* Input: start_x, end_x	- start column and end column
*		 start_y,end_y 	- start row and end row position (i.e. page address)
*
* Output: none
*
* Side Effects: none
*
* Overview: defines start/end columns and start/end rows for memory access
*			from host to SSD1963
* Note: none
********************************************************************/
void SetArea(SHORT start_x, SHORT start_y, SHORT end_x, SHORT end_y)
{
	WriteCommand(CMD_SET_COLUMN);
	CS_LAT_BIT = 0;
	WriteData(start_x>>8);
	WriteData(start_x);
	WriteData(end_x>>8);
	WriteData(end_x);
	CS_LAT_BIT = 1;
	WriteCommand(CMD_SET_PAGE);
	CS_LAT_BIT = 0;
	WriteData(start_y>>8);
	WriteData(start_y);
	WriteData(end_y>>8);
	WriteData(end_y);
	CS_LAT_BIT = 1;
}

/*********************************************************************
* Function: Set a GPIO pin to state high(1) or low(0)
*
* PreCondition: Set the GPIO pin an output prior using this function
*
* Arguments: BYTE pin	- 	LCD_RESET
*							LCD_SPENA
*							LCD_SPCLK
*							LCD_SPDAT	defined under GraphicsConfig.h
*							
*			 BOOL state - 	0 for low
*							1 for high
* Return: none
*
* Note:
*********************************************************************/
static void GPIO_WR(BYTE pin, BOOL state)
{
	BYTE _gpioStatus = 0;

	if(state==1)
		_gpioStatus = _gpioStatus|pin;
	else
		_gpioStatus = _gpioStatus&(~pin);

	WriteCommand(CMD_SET_GPIO_VAL);	// Set GPIO value
	CS_LAT_BIT = 0;
	WriteData(_gpioStatus);
	CS_LAT_BIT = 1;
}

/*********************************************************************
* Function:  void EnterSleepMode (void)
* PreCondition: none
* Input:  none
* Output: none
* Side Effects: none
* Overview: SSD1963 enters sleep mode
* Note: Host must wait 5mS after sending before sending next command
********************************************************************/
void EnterSleepMode (void)
{
	WriteCommand(CMD_ENT_SLEEP);
}//

/*********************************************************************
* Function:  void ExitSleepMode (void)
* PreCondition: none
* Input:  none
* Output: none
* Side Effects: none
* Overview: SSD1963 enters sleep mode
* Note:   none
********************************************************************/
void ExitSleepMode (void)
{
	WriteCommand(CMD_EXIT_SLEEP);
}//

/*********************************************************************
* Function		: void DisplayOff(void)
* PreCondition	: none
* Input			: none
* Output		: none
* Side Effects	: none
* Overview		: SSD1963 changes the display state to OFF state
* Note			: none
********************************************************************/
void DisplayOff(void)
{
	WriteCommand(CMD_BLANK_DISPLAY);
}

/*********************************************************************
* Function		: void DisplayOn(void)
* PreCondition	: none
* Input			: none
* Output		: none
* Side Effects	: none
* Overview		: SSD1963 changes the display state to ON state
* Note			: none
********************************************************************/
void DisplayOn(void)
{
	WriteCommand(CMD_ON_DISPLAY);
}

/*********************************************************************
* Function		: void EnterDeepSleep(void)
* PreCondition	: none
* Input			: none
* Output		: none
* Side Effects	: none
* Overview		: SSD1963 enters deep sleep state with PLL stopped
* Note			: none
********************************************************************/
void EnterDeepSleep(void)
{
	WriteCommand(CMD_ENT_DEEP_SLEEP);
}

/*********************************************************************
* Function:  void  SetBacklight(BYTE intensity)
*
* Overview: This function makes use of PWM feature of ssd1963 to adjust
*			the backlight intensity. 
*
* PreCondition: Backlight circuit with shutdown pin connected to PWM output of ssd1963.
*
* Input: 	(BYTE) intensity from 
*			0x00 (total backlight shutdown, PWM pin pull-down to VSS)
*			0xff (99% pull-up, 255/256 pull-up to VDD)
*
* Output: none
*
* Note: The base frequency of PWM set to around 300Hz with PLL set to 120MHz.
*		This parameter is hardware dependent
********************************************************************/
void SetBacklight(BYTE intensity)
{
	WriteCommand(CMD_SET_PWM_CONF);// Set PWM configuration for backlight control
	CS_LAT_BIT = 0;
	WriteData(0x0E);			// PWMF[7:0] = 2, PWM base freq = PLL/(256*(1+5))/256 = 
								// 300Hz for a PLL freq = 120MHz
	WriteData(0xFF);		// Set duty cycle, from 0x00 (total pull-down) to 0xFF 
								// (99% pull-up , 255/256)
	WriteData(0xFF);			// PWM enabled and controlled by host (mcu)
	WriteData(0xFF);
	WriteData(0xFF);
	WriteData(0x00);

	CS_LAT_BIT = 1;
}//

/*********************************************************************
* Function:  void  SetTearingCfg(BOOL state, BOOL mode)
*
* Overview: This function enable/disable tearing effect
*
* PreCondition: none
*
* Input: 	BOOL state -	1 to enable
*							0 to disable
*			BOOL mode -		0:  the tearing effect output line consists
*								of V-blanking information only
*							1:	the tearing effect output line consists
*								of both V-blanking and H-blanking info.
* Output: none
*
* Note:
********************************************************************/
void SetTearingCfg(BOOL state, BOOL mode)
{
	if(state == 1)
	{
		WriteCommand(CMD_SET_TEAR_ON);
		CS_LAT_BIT = 0;
		WriteData(mode&0x01);
		CS_LAT_BIT = 1;
	}//
	else
	{
		WriteCommand(0x34);
	}//
}//

/*********************************************************************
* Function:  void ResetDevice()
*
* PreCondition: none
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: Resets LCD, initializes PMP
*			Initialize low level IO port for mcu,
*			initialize SSD1963 for PCLK,
*			HSYNC, VSYNC etc
*
* Note: Need to set the backlight intensity by SetBacklight(BYTE intensity)
*		in main()
*		MCU specific. 
********************************************************************/
void ResetDevice(void)
{
	#if defined (PIC32_STARTER_KIT)
	//Set digital for AN/digital multiplex pins, only required if ADC pins are used for digital IO
	AD1PCFGbits.PCFG4 	= 1;//set TE_PORT_BIT digital
	AD1PCFGbits.PCFG15 	= 1;//set CS_LAT_BIT digital
	#endif

	RST_LAT_BIT  = 1;		
	RST_TRIS_BIT = 0;      	// enable RESET line

	RS_TRIS_BIT = 0;       	// enable RS line 

	CS_LAT_BIT  = 1;        	// SSD1963 is not selected by default
	CS_TRIS_BIT = 0;       	// enable SSD1963 CS line    

	RD_LAT_BIT  = 1;
	RD_TRIS_BIT = 0;

	WR_LAT_BIT  = 1;
	WR_TRIS_BIT = 0;

	TE_TRIS_BIT	= 1;

	TRISD = 0;	

/*
	// PMP setup 
	PMMODE = 0; PMAEN = 0; PMCON = 0;
	PMMODEbits.MODE   = 2;  // Intel 80 master interface
	// Before PLL is set and locked, the reference clock = crystal freq.
	// Set the largest data setup time for 10MHz clock
	PMMODEbits.WAITB  = 3;
	PMMODEbits.WAITM  = 15;
	PMMODEbits.WAITE  = 3;

	PMMODEbits.MODE16 = 1;  // 16 bit mode

	PMCONbits.PTRDEN = 0;  	// disable RD line
	PMCONbits.PTWREN = 0; 	// disable WR line
	PMCONbits.PMPEN  = 1;  	// enable PMP
*/
	RST_LAT_BIT = 0;
	__delay_ms(1);
	RST_LAT_BIT = 1;       // release from reset state to sleep state

	//Set MN(multipliers) of PLL, VCO = crystal freq * (N+1)
	//PLL freq = VCO/M with 250MHz < VCO < 800MHz
	//The max PLL freq is around 120MHz. To obtain 120MHz as the PLL freq

	WriteCommand(CMD_SET_PLL_MN);	// Set PLL with OSC = 10MHz (hardware)
									// Multiplier N = 35, VCO (>250MHz)= OSC*(N+1), VCO = 360MHz
	CS_LAT_BIT = 0;
	WriteData(0x23);
	WriteData(0x02);				// Divider M = 2, PLL = 360/(M+1) = 120MHz
	WriteData(0x54);				// Validate M and N values
	CS_LAT_BIT = 1;	

	WriteCommand(CMD_PLL_START);	// Start PLL command
	CS_LAT_BIT = 0;
	WriteData(0x01);				// enable PLL
	CS_LAT_BIT = 1;	

	__delay_ms(1);						// wait stablize
	WriteCommand(CMD_PLL_START);	// Start PLL command again
	CS_LAT_BIT = 0;
	WriteData(0x03);				// now, use PLL output as system clock	
	CS_LAT_BIT = 1;	
	//once PLL locked (at 120MHz), the data hold time set shortest
//	PMMODEbits.WAITB  = 0;
//	PMMODEbits.WAITM  = 0;
//	PMMODEbits.WAITE  = 0;	

	WriteCommand(CMD_SOFT_RESET);	// Soft reset
	__delay_ms(10);
	/*
	*************************************************
	* 4.3" TFT panel model # TY430TFT480272
	*************************************************
	*/
#if (DISPLAY_PANEL==TY430TFT480272)	
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TY430TFT480272 is 9MHz
	//9MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 78642 (0x13332)
	WriteCommand(CMD_SET_PCLK);		//set pixel clock (LSHIFT signal) frequency
	CS_LAT_BIT = 0;
	WriteData(0x01);
	WriteData(0x33);
	WriteData(0x32);
	CS_LAT_BIT = 1;
	/*
	*************************************************
	* 5.0" TFT panel model # TY500TFT800480
	*************************************************
	*/
#elif (DISPLAY_PANEL==TY500TFT800480)	
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TY500TFT800480 is 33MHz
	//30MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 262143 (0x3FFFF)
	WriteCommand(CMD_SET_PCLK);		//set pixel clock (LSHIFT signal) frequency
	CS_LAT_BIT = 0;
	WriteData(0x03);
	WriteData(0xff);
	WriteData(0xff);
	CS_LAT_BIT = 1;
	/*
	****************************************************************
	* 7" TFT model # TY700TFT800480
	****************************************************************
	*/
#elif (DISPLAY_PANEL==TY700TFT800480)
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for TY700TFT800480 is 33.3MHz(datasheet), experiment shows 30MHz gives a stable result
	//30MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 262143 (0x3FFFF)
	//Time per line = (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)/30 us = 1056/30 = 35.2us
	WriteCommand(CMD_SET_PCLK);		//set pixel clock (LSHIFT signal) frequency
	CS_LAT_BIT = 0;
	WriteData(0x03);
	WriteData(0xff);
	WriteData(0xff);	
	CS_LAT_BIT = 1;
	/*
	*************************************************
	* 3.5" TFT model # LVC75Z779V1S
	*************************************************
	*/
#elif (DISPLAY_PANEL==LVC75Z779V1S)
	//Set LSHIFT freq, i.e. the DCLK with PLL freq 120MHz set previously
	//Typical DCLK for LVC75Z779V1S is 6.5MHz in 24 bit format
	//6.5MHz = 120MHz*(LCDC_FPR+1)/2^20
	//LCDC_FPR = 56796 (0x00DDDC)
	WriteCommand(CMD_SET_PCLK);		//set pixel clock (LSHIFT signal) frequency
	CS_LAT_BIT = 0;
	WriteData(0x00);
	WriteData(0xDD);
	WriteData(0xDC);
	CS_LAT_BIT = 1;
#endif
	
	//Set panel mode, varies from individual manufacturer
	WriteCommand(CMD_SET_PANEL_MODE);
#if ((DISPLAY_PANEL==TY430TFT480272)||(DISPLAY_PANEL==LVC75Z779V1S))
	CS_LAT_BIT = 0;
	WriteData(0x20);				// set 24-bit for TY430TF480272 4.3" panel, or LVC75Z779V1S 3.5" TFT Panel, data latch in rising edge for LSHIFT
	WriteData(0x00);				// set Hsync+Vsync mode
	WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
	WriteData(DISP_HOR_RESOLUTION-1);
	WriteData((DISP_VER_RESOLUTION-1)>>8);
	WriteData(DISP_VER_RESOLUTION-1);
	WriteData(0x00);				//RGB sequence
	CS_LAT_BIT = 1;
#elif (DISPLAY_PANEL==TY500TFT800480)
	CS_LAT_BIT = 0;
	WriteData(0x24);				// set 24-bit for TY500TFT800480 5" panel, data latch in falling edge for LSHIFT
	WriteData(0x00);				// set Hsync+Vsync mode
	WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
	WriteData(DISP_HOR_RESOLUTION-1);
	WriteData((DISP_VER_RESOLUTION-1)>>8);
	WriteData(DISP_VER_RESOLUTION-1);
	WriteData(0x00);				//RGB sequence
	CS_LAT_BIT = 1;
#elif (DISPLAY_PANEL==TY700TFT800480)
	CS_LAT_BIT = 0;
	WriteData(0x10);				// set 18-bit for 7" panel TY700TFT800480
	WriteData(0x80);				// set TTL mode
	WriteData((DISP_HOR_RESOLUTION-1)>>8); //Set panel size
	WriteData(DISP_HOR_RESOLUTION-1);
	WriteData((DISP_VER_RESOLUTION-1)>>8);
	WriteData(DISP_VER_RESOLUTION-1);
	WriteData(0x00);				//RGB sequence	
	CS_LAT_BIT = 1;
#endif//

////ORIENTACION DE LA PANTALLA

	WriteCommand(CMD_SET_ADDR_MODE);
	CS_LAT_BIT = 0;
	WriteData(CMD_180_GRADOS);
	CS_LAT_BIT = 1;



	//Set horizontal period
	WriteCommand(CMD_SET_HOR_PERIOD);
	#define HT (DISP_HOR_RESOLUTION+DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH+DISP_HOR_FRONT_PORCH)
	CS_LAT_BIT = 0;
	WriteData((HT-1)>>8);	
	WriteData(HT-1);
	#define HPS (DISP_HOR_PULSE_WIDTH+DISP_HOR_BACK_PORCH)
	WriteData((HPS-1)>>8);
	WriteData(HPS-1);
	WriteData(DISP_HOR_PULSE_WIDTH-1);
	WriteData(0x00);
	WriteData(0x00);
	WriteData(0x00);
	CS_LAT_BIT = 1;
	//Set vertical period
	WriteCommand(CMD_SET_VER_PERIOD);
	#define VT (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH+DISP_VER_FRONT_PORCH+DISP_VER_RESOLUTION)
	CS_LAT_BIT = 0;
	WriteData((VT-1)>>8);
	WriteData(VT-1);
	#define VSP (DISP_VER_PULSE_WIDTH+DISP_VER_BACK_PORCH)
	WriteData((VSP-1)>>8);
	WriteData(VSP-1);
	WriteData(DISP_VER_PULSE_WIDTH-1);
	WriteData(0x00);
	WriteData(0x00);
	CS_LAT_BIT = 1;
	
	//Set pixel format, i.e. the bpp
	WriteCommand(CMD_SET_PIXEL_FORMAT);
	CS_LAT_BIT = 0;
	WriteData(0x55); 				// set 16bpp
	CS_LAT_BIT = 1;

	//Set pixel data interface
	WriteCommand(CMD_SET_DATA_INTERFACE);

	CS_LAT_BIT = 0;
	WriteData(0x03);				//16-bit(565 format) data for 16bpp PIC32MX only
	CS_LAT_BIT = 1;


#if ((DISPLAY_PANEL==TY500TFT800480)||(DISPLAY_PANEL==TY430TFT480272)||(DISPLAY_PANEL==LVC75Z779V1S))
	WriteCommand(CMD_SET_GPIO_CONF);// Set all GPIOs to output, controlled by host
	CS_LAT_BIT = 0;
	WriteData(0x0f);				// Set GPIO0 as output
	WriteData(0x01);				// GPIO[3:0] used as normal GPIOs
	CS_LAT_BIT = 1;
	// LL Reset to LCD!!!
	GPIO_WR(LCD_SPENA, 1);
	GPIO_WR(LCD_SPCLK, 1);
	GPIO_WR(LCD_SPDAT,1);
	GPIO_WR(LCD_RESET,1);
	GPIO_WR(LCD_RESET,0);
	__delay_ms(1);
	GPIO_WR(LCD_RESET,1);
#endif

	WriteCommand(CMD_SET_POST_PROC);
	CS_LAT_BIT = 0;
	WriteData(118);				// Set contraste
	WriteData(224);				// set brillo
	WriteData(125);				// set saturacion
	WriteData(1);				// GPIO[3:0] used as normal GPIOs
	CS_LAT_BIT = 1;


SetBacklight(255);	//full brightness
WriteCommand(CMD_ON_DISPLAY);	// Turn on display; show the image on display	
}//


void modifica(unsigned char contraste,unsigned char brillo, unsigned char saturacion)
{
	WriteCommand(CMD_SET_POST_PROC);
	CS_LAT_BIT = 0;
	WriteData(contraste);				// Set contraste
	WriteData(brillo);				// set brillo
	WriteData(saturacion);				// set saturacion
	WriteData(1);				// GPIO[3:0] used as normal GPIOs
	CS_LAT_BIT = 1;
}



/*********************************************************************
* Function: void PutPixel(SHORT x, SHORT y)
*
* PreCondition: none
*
* Input: x,y - pixel coordinates
*
* Output: none
*
* Side Effects: none
*
* Overview: puts pixel
*
* Note: 
********************************************************************/
void PutPixel(SHORT x, SHORT y, SHORT color__)
{
	SetArea(x,y,DISP_HOR_RESOLUTION-1,DISP_VER_RESOLUTION-1);
	WriteCommand(CMD_WR_MEMSTART);
	CS_LAT_BIT = 0;
	WriteData(color__);
	CS_LAT_BIT = 1;
}


/*********************************************************************
* Function: void ClearDevice(void)
*
* PreCondition: none
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: clears screen with current color 
*
* Note: none
*
********************************************************************/
void ClearDevice(SHORT color)
{
//	DWORD	counter;
	DWORD 	xcounter, ycounter;

	SetArea(0,0,DISP_HOR_RESOLUTION-1,DISP_VER_RESOLUTION-1);

	WriteCommand(CMD_WR_MEMSTART);

	CS_LAT_BIT = 0;
	for(ycounter=0;ycounter<DISP_VER_RESOLUTION;ycounter++)
	{
		for(xcounter=0;xcounter<DISP_HOR_RESOLUTION;xcounter++)
		{
			WriteData(color);
		}
	}

	CS_LAT_BIT = 1;
}//

void glcd_line(short x1, short y1, short x2, short y2, unsigned short color)
{
      short     dy;
    short     dx;
      short     addx=1;
      short     addy=1;
      short    P;
      short     diff;
   short    i=0;

   dx = abs(x2 - x1);
   dy = abs(y2 - y1);

   if(x1 > x2)
      addx = -1;
   if(y1 > y2)
      addy = -1;

   if(dx >= dy)
   {
      dy *= 2;
      P = dy - dx;
      diff = P - dx;

      for(; i<=dx; ++i)
      {
         PutPixel(x1,y1,color);

         if(P < 0)
         {
            P  += dy;
            x1 += addx;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
   else
   {
      dx *= 2;
      P = dx - dy;
      diff = P - dy;

      for(; i<=dy; ++i)
      {
         PutPixel(x1,y1,color);

         if(P < 0)
         {
            P  += dx;
            y1 += addy;
         }
         else
         {
            P  += diff;
            x1 += addx;
            y1 += addy;
         }
      }
   }
}/////////////////////////////////////////////////////////////////////////

void glcd_rect(short x1, short y1, short x2, short y2, unsigned char fill, unsigned short color)
{

   if(fill)
   {
         //short i;
      short xmin;
      short xmax;
      short ymin;
      short ymax;

      if(x1 < x2)                            //  Find x min and max
      {
         xmin = x1;
         xmax = x2;
      }
      else
      {
         xmin = x2;
         xmax = x1;
      }

      if(y1 < y2)                            // Find the y min and max
      {
         ymin = y1;
         ymax = y2;
      }
      else
      {
         ymin = y2;
         ymax = y1;
      }
////FUNCIONAMIENTO TAL CUAL EL CLEAR DEVICE
	DWORD 	xcounter, ycounter;

	SetArea(x1,y1,x2,y2);

	WriteCommand(CMD_WR_MEMSTART);

	CS_LAT_BIT = 0;
	for(ycounter=y1;ycounter<y2;ycounter++)
	{
		for(xcounter=x1;xcounter<x2;xcounter++)
		{
			WriteData(color);
		}
	}

	CS_LAT_BIT = 1;
   }
   else
   {
      glcd_line(x1, y1, x2, y1, color);      // Draw the 4 sides
      glcd_line(x1, y2, x2, y2, color);
      glcd_line(x1, y1, x1, y2, color);
      glcd_line(x2, y1, x2, y2, color);
   }
}//

void glcd_circle(short x, short y, short radius, short fill, unsigned short color)
{
short  a;
short  b;
short  P;

   a = 0;
   b = radius;
   P = 1 - radius;
   do
   {
      if(fill)
      {
         glcd_line(x-a, y+b, x+a, y+b, color);
         glcd_line(x-a, y-b, x+a, y-b, color);
         glcd_line(x-b, y+a, x+b, y+a, color);
         glcd_line(x-b, y-a, x+b, y-a, color);
      }
      else
      {
         PutPixel(a+x, b+y,color);
         PutPixel(b+x, a+y,color);
         PutPixel(x-a, b+y,color);
         PutPixel(x-b, a+y,color);
         PutPixel(b+x, y-a,color);
         PutPixel(a+x, y-b,color);
         PutPixel(x-a, y-b,color);
         PutPixel(x-b, y-a,color);
      }

      if(P < 0)
         P += 3 + 2 * a++;
      else
         P += 5 + 2 * (a++ - b--);
    } while(a <= b);
}//

void glcd_text57(short x, short y, char* textptr, unsigned short size, unsigned short color)
{
   unsigned short   j;
   unsigned short   k;
   unsigned short   l;
   unsigned short   m;
   unsigned char   pixelData[6]; 

   for(; *textptr != '\0'; ++textptr, ++x)// Loop through the passed string
   {

   //_p2 = *textptr;
      if(*textptr < 'S') // Checks if the letter is in the first font array
         memcpy(pixelData, FONT[*textptr - ' '], 5);
      else if(*textptr <= '~') // Check if the letter is in the second font array
         memcpy(pixelData, FONT2[*textptr - 'S'], 5);
      else
         memcpy(pixelData, FONT[0], 5);   // Default to space

      if(x+5*size >= DISP_HOR_RESOLUTION)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 7*size + 1;                 // Set y at next position down
      }

   //pixelData[5] = 0;

     for(j=0; j<5; ++j, x+=size)         // recorre cada columna del caracter
      {
         for(k=0; k < 7; ++k)             //recorre cada pixel de cada columna
         {
         unsigned char _des = 1;
         _des <<= k;
         _des = pixelData[j] & _des;
            if(_des)                   // verifica si el pixel debe ser o no dibujado
            	{
               	for(l=0; l < size; ++l)       // estos FOR cambian el tamaņo del caracter
               		{                          
                  	for(m=0; m < size; ++m)
                  		{
                     	PutPixel(x+m, y+k*size+l,color); // Draws the pixel
                  		}//
               		}//
         		}//
         }//
      }//

	 if(size == 2){x++;}//
else if(size == 3){x++;x++;}//
else if(size == 4){x++;x++;x++;}//
else if(size == 5){x++;x++;x++;x++;}//
else if(size == 6){x++;x++;x++;x++;x++;}//
else if(size == 7){x++;x++;x++;x++;x++;x++;}//
else if(size == 8){x++;x++;x++;x++;x++;x++;x++;}//
else if(size == 9){x++;x++;x++;x++;x++;x++;x++;x++;}//

   }//
}//

void glcd_text57B(short x, short y, char* textptr, unsigned short size, unsigned short color, unsigned short color_fondo)
{
   unsigned short   j;
   unsigned short   k;
   unsigned short   l;
   unsigned short   m;
   unsigned char   pixelData[6]; 

   for(; *textptr != '\0'; ++textptr, ++x)// Loop through the passed string
   {

   //_p2 = *textptr;
      if(*textptr < 'S') // Checks if the letter is in the first font array
         memcpy(pixelData, FONT[*textptr - ' '], 5);
      else if(*textptr <= '~') // Check if the letter is in the second font array
         memcpy(pixelData, FONT2[*textptr - 'S'], 5);
      else
         memcpy(pixelData, FONT[0], 5);   // Default to space

      if(x+5*size >= DISP_HOR_RESOLUTION)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 7*size + 1;                 // Set y at next position down
      }

   //pixelData[5] = 0;

     for(j=0; j<5; ++j, x+=size)         // recorre cada columna del caracter
      {
         for(k=0; k < 7; ++k)             //recorre cada pixel de cada columna
         {
         unsigned char _des = 1;
         _des <<= k;
         _des = pixelData[j] & _des;
            if(_des)                   // verifica si el pixel debe ser o no dibujado
            	{
               	for(l=0; l < size; ++l)       // estos FOR cambian el tamaņo del caracter
               		{                          
                  	for(m=0; m < size; ++m)
                  		{
                     	PutPixel(x+m, y+k*size+l,color); // Draws the pixel
                  		}//
               		}//
         		}//
			else
            	{
               	for(l=0; l < size; ++l)       // estos FOR cambian el tamaņo del caracter
               		{                          
                  	for(m=0; m < size; ++m)
                  		{
                     	PutPixel(x+m, y+k*size+l,color_fondo); // Draws the pixel
                  		}//
               		}//
         		}//
         }//
      }//

	 if(size == 2){x++;}//
else if(size == 3){x++;x++;}//
else if(size == 4){x++;x++;x++;}//
else if(size == 5){x++;x++;x++;x++;}//
else if(size == 6){x++;x++;x++;x++;x++;}//
else if(size == 7){x++;x++;x++;x++;x++;x++;}//
else if(size == 8){x++;x++;x++;x++;x++;x++;x++;}//
else if(size == 9){x++;x++;x++;x++;x++;x++;x++;x++;}//



   }//
}//


void PutImage16BPP(SHORT left, SHORT top, FLASH_BYTE *bitmap, BYTE stretch)
{
    register FLASH_WORD *flashAddress;
    register FLASH_WORD *tempFlashAddress;
    WORD                sizeX, sizeY;
    register WORD       x, y;
//    WORD                temp;
    register BYTE       stretchX, stretchY;
	SHORT	color;
    // Move pointer to size information
    flashAddress = (FLASH_WORD *)bitmap + 1;

    // Read image size
    sizeY = *flashAddress;
    flashAddress++;
    sizeX = *flashAddress;
    flashAddress++;

   	SetArea(left,top,left+sizeX*stretch-1,top+sizeY*stretch-1);
	WriteCommand(CMD_WR_MEMSTART);
   	CS_LAT_BIT = 0;


    for(y = 0; y < sizeY; y++)
       {
        tempFlashAddress = flashAddress;
        for(stretchY = 0; stretchY < stretch; stretchY++)
           {
            flashAddress = tempFlashAddress;
            for(x = 0; x < sizeX; x++)
               {
                color = *flashAddress;
				
                flashAddress++;
                for(stretchX = 0; stretchX < stretch; stretchX++)
                   {
               		WriteData(color);
                   }//
               }//
           }//   
       }//
   CS_LAT_BIT = 1;

}//
