/* 
* Purpose: TFT driver/interface
*
* Author: Allen Lin
*
* Date: 2008/5/9
*
* Copyright Generalplus Corp. ALL RIGHTS RESERVED.
*
* Version : 1.00
* History :
*/

//Include files
#include	"GPL951_Body.h"
#include	"drv_l1_tft.h"


/******************************************************************************
 * TFT CONTROL REGISTERS
 ******************************************************************************/
#define		P_TFT_Base				0x7050

#define		R_TFT_CTRL					*((volatile unsigned int*)(P_TFT_Base+0x00))
#define		R_TFT_V_PERIOD				*((volatile unsigned int*)(P_TFT_Base+0x01))
#define		R_TFT_VS_WIDTH				*((volatile unsigned int*)(P_TFT_Base+0x02))
#define		R_TFT_V_START				*((volatile unsigned int*)(P_TFT_Base+0x03))
#define		R_TFT_V_END					*((volatile unsigned int*)(P_TFT_Base+0x04))
#define		R_TFT_H_PERIOD				*((volatile unsigned int*)(P_TFT_Base+0x05))
#define		R_TFT_HS_WIDTH				*((volatile unsigned int*)(P_TFT_Base+0x06))
#define		R_TFT_H_START				*((volatile unsigned int*)(P_TFT_Base+0x07))
#define		R_TFT_H_END					*((volatile unsigned int*)(P_TFT_Base+0x08))
#define		R_TFT_LINE_RGB_ORDER		*((volatile unsigned int*)(P_TFT_Base+0x09))
#define		R_TFT_STATUS				*((volatile unsigned int*)(P_TFT_Base+0x0A))
#define		R_TFT_MEM_BUFF_WR			*((volatile unsigned int*)(P_TFT_Base+0x0B))
#define		R_TFT_MEM_BUFF_RD			*((volatile unsigned int*)(P_TFT_Base+0x0C))

#define		R_TFT_VS_START				*((volatile unsigned int*)(P_TFT_Base+0x1C))
#define		R_TFT_VS_END				*((volatile unsigned int*)(P_TFT_Base+0x1D))
#define		R_TFT_HS_START				*((volatile unsigned int*)(P_TFT_Base+0x1E))
#define		R_TFT_HS_END				*((volatile unsigned int*)(P_TFT_Base+0x1F))

#define		R_TFT_INT_EN 	            *((volatile unsigned int*)(P_TFT_Base+0x12))
#define		R_TFT_INT_CLR	            *((volatile unsigned int*)(P_TFT_Base+0x13))


#define		D_I80_16bit		0x0000
#define		D_I80_8bit		0x2000
#define		D_I80_Contiune	0x00C0
#define		D_I80_Single	0x00D0

#define		D_I80_DataBitMode	D_I80_8bit
#define		D_I80_TransferMode	D_I80_Single
#define		D_I80_CLK		0x01
#define		D_TFT_UnderRun_Ctrl 0x8000		//0:disable, 0x8000:enable 	


//=== This is for code configuration DON'T REMOVE or MODIFY it ===//
#if 1//(defined _DRV_L1_TFT) && (_DRV_L1_TFT == 1)                   //
//================================================================//

// Constant definitions used in this file only go here

// Type definitions used in this file only go here

// Global inline functions(Marcos) used in this file only go here

// Declaration of global variables and functions defined in other files

// Variables defined in this file

// Functions defined in this file

void cmd_delay(int i) 
{
	unsigned int j, cnt;
	
	cnt = i*2;
	for (j=0;j<cnt;j++);
}

void cmd_longdelay(int i) 
{
	unsigned long j, cnt;
	
	cnt = i*200;
	for (j=0;j<cnt;j++);
}

void gpio_write_io(int port, int data)
 {
    int TEMP = *P_IOE_Data;
    TEMP &= 0x07;			// Frank add
    
    if(port > 15)
       port = 0;
    
    if(data)
       TEMP |= (1<<port);
    else
       TEMP &= ~(1<<port);
    
    *P_IOE_Data = TEMP;   
}

void gpio_init_io(int port, int direction)
{   
    int TEMP = *P_IOE_Dir;
    
    if(port > 31)
       port = 0;
    
    if(direction)
       TEMP |= (1<<port);        //output
    else
       TEMP &= ~(1<<port);       //input
    
    *P_IOE_Dir = TEMP;      
}

void gpio_set_port_attribute(int port, int attribute)
{
    int TEMP = *P_IOE_Attrib;
    
    if(port > 15)
       port = 0;
    
    if(attribute)
       TEMP |= (1<<port);
    else
       TEMP &= ~(1<<port);
       
    *P_IOE_Attrib = TEMP;   
}

int gpio_read_io(int port)
{
 //   int TEMP = *P_IOE_Buffer;
 	int TEMP = *P_IOE_Data;
 	TEMP &= 0x07;			// Frank add
    
    if(port > 31)
       port = 0;
    
    if(TEMP & (1<<port))
    	return 1;
    else 
    	return 0;      
}	

void i80_write_cmd(char cmd)
{
//	gpio_write_io(IOE_PIN_1,0);	
	*P_TFT_MemMode_WCmd = cmd;

	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");		
	
	*P_TFT_Ctrl = 0x0080 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;
//	gpio_write_io(IOE_PIN_1,1);
}

void i80_write_data(char data)
{
//	gpio_write_io(IOE_PIN_1,0);
	*P_TFT_MemMode_WCmd = data;
	
	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");		
	
	*P_TFT_Ctrl = 0x00a0 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;			
//	gpio_write_io(IOE_PIN_1,1);
}

int i80_read_data(void)
{
	int TEMP;
//	gpio_write_io(IOE_PIN_1,0);	
	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");	
		
	*P_TFT_Ctrl = 0x00b0 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;		
	__asm ("NOP");
	TEMP = *P_TFT_MemMode_RCmd;
//	gpio_write_io(IOE_PIN_1,1);
	return TEMP;
}

void i80_write_cmd_only(char cmd)
{
	*P_TFT_MemMode_WCmd = cmd;

	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");	
	
	*P_TFT_Ctrl = 0x00b0 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;
}

void i80_write_data_only(char data)
{
	*P_TFT_MemMode_WCmd = data;
	
	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");		
	
	*P_TFT_Ctrl = 0x00a0 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;		
}

int i80_read_data_only(void)
{
	int TEMP;
	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");	
			
	*P_TFT_Ctrl = 0x00b0 + D_I80_CLK + D_I80_DataBitMode + D_TFT_UnderRun_Ctrl;		
	__asm ("NOP");
	TEMP = *P_TFT_MemMode_RCmd;
	return TEMP;
}

void tft_tft_en_set(int status)
{
	if (status) {
		*P_TFT_Ctrl |= TFT_EN;
	}		
	else {
		*P_TFT_Ctrl &= ~TFT_EN;
	}
}

void tft_clk_set(int clk)
{
	*P_TFT_Ctrl &= ~TFT_CLK_SEL;
	*P_TFT_Ctrl |= clk;	
}

void tft_mode_set(int mode)
{
	*P_TFT_Ctrl &= ~TFT_MODE;
	*P_TFT_Ctrl |= mode;		
}

void tft_mem_mode_ctrl_set(int mem_ctrl)
{
	*P_TFT_Ctrl &= ~TFT_MODE;
	*P_TFT_Ctrl |= (mem_ctrl|TFT_EN);		
}

void tft_signal_inv_set(int mask, int value)
{
	/*set vsync,hsync,dclk and DE inv */
	*P_TFT_Ctrl &= ~mask;
	*P_TFT_Ctrl |= (mask & value);		
}

void tft_h_compress_set(int status)
{
	if (status) {
		*P_TFT_Ctrl |= TFT_H_COMPRESS;
	}
	else {
		*P_TFT_Ctrl &= ~TFT_H_COMPRESS;
	}
}

void tft_mem_unit_set(int status)
{
	if (status) {
		*P_TFT_Ctrl |= TFT_MEM_BYTE_EN;
	}
	else {
		*P_TFT_Ctrl &= ~TFT_MEM_BYTE_EN; /* word */
	}
}

void tft_interlace_set(int status)
{
	if (status) {
		*P_TFT_Ctrl |= TFT_INTERLACE_MOD;
	}
	else {
		*P_TFT_Ctrl &= ~TFT_INTERLACE_MOD;
	}
}

void tft_vsync_unit_set(int status)
{
	if (status) {
		*P_TFT_Ctrl |= TFT_VSYNC_UNIT;
	}
	else {
		*P_TFT_Ctrl &= ~TFT_VSYNC_UNIT;
	}
}

void TXDT180L_ILI9163C_Init(void)
{
//	*P_TFT_RGB_Ctrl |= 0x0080; //memory mode
//
//	gpio_init_io(IOE_PIN_1,1);
//	gpio_set_port_attribute(IOE_PIN_1,1);
//	gpio_write_io(IOE_PIN_1, 1);
//
//	gpio_init_io(IOE_PIN_RST, 1);	
//	gpio_set_port_attribute(IOE_PIN_RST, 1);
//	gpio_write_io(IOE_PIN_RST, 1);
//	cmd_longdelay(1);
//    gpio_write_io(IOE_PIN_RST, 0);
//    cmd_longdelay(10);
//    gpio_write_io(IOE_PIN_RST, 1);
// 	cmd_longdelay(50);
//
//    i80_write_cmd(0x01);	//software reset
//
// /* TFT interface parameter */	
// 	*P_TFT_V_Width = 240 - 1;
//	*P_TFT_H_Width = 320 - 1;				
//	
//	*P_TFT_VSync_Setup = 20;
//	*P_TFT_V_Start = 5;	
//	*P_TFT_HSync_Setup = 0x3;	//3;				
//	*P_TFT_H_Start = 0x3;	//3;
//			
//	*P_TFT_V_Show_Start = 0;
//	*P_TFT_V_Show_End = 160;	//160;
//	
//	*P_TFT_H_Show_Start = 0;
//	*P_TFT_H_Show_End = 128-1;	//128 - 1;		
//		
//	*P_PPU_Free_Width= 0;//Display_Width;
//	*P_PPU_Free_Height= 0;//Display_Height;					 
//
//	//Start initial sequence 		    
//    i80_write_cmd(0x11);  	//exit sleep
//    cmd_longdelay(120);
//    
//	i80_write_cmd(0x26);	//set default gamma
//    i80_write_data(0x04); 
//    
//    i80_write_cmd(0xec);
//    i80_write_data(0x0c);
//	
//    i80_write_cmd(0xB1);  
//    i80_write_data(0x08);
//    i80_write_data(0x10);
//    
//    i80_write_cmd(0xc0);	//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
//    i80_write_data(0x02);
//    i80_write_data(0x00);
//	
//	i80_write_cmd(0xc1);	//Set BT[2:0] for AVDD & VCL & VGH & VGL
//	i80_write_data(0x02); 
//	
//	i80_write_cmd(0xc5);	//Set VMH[6:0] & VML[6:0] for VOMH & VCOML	
//	i80_write_data(0x4c);
//	i80_write_data(0x5e);
//		
//	i80_write_cmd(0xc7);	//VCOM Offset adjust
//	i80_write_data(0xb8);
//			
//	i80_write_cmd(0x3A);	//set color format
//	i80_write_data(0x05);	
//	
//	i80_write_cmd(0x2A);	//Set Column Address
//	i80_write_data(0x00);
//	i80_write_data(0x00);
//	i80_write_data(0x00);
//	i80_write_data(0x7f);
//	
//    i80_write_cmd(0x2B);	//Set Page Address
//	i80_write_data(0x00);
//	i80_write_data(0x00);
//	i80_write_data(0x00);
//	i80_write_data(0x9f);
//	
//    i80_write_cmd(0x36);	//Set Scanning Direction
//	i80_write_data(0xc0);	 
//
//	i80_write_cmd(0xB7); //Set Source Output Direction
//	i80_write_data(0x00);
//
//
//	i80_write_cmd(0xf2); //Enable Gamma bit
//	i80_write_data(0x01);
//
//	i80_write_cmd(0xE0);
//	i80_write_data(0x3F);//p1
//	i80_write_data(0x22);//p2
//	i80_write_data(0x20);//p3
//	i80_write_data(0x30);//p4
//	i80_write_data(0x29);//p5
//	i80_write_data(0x0C);//p6
//	i80_write_data(0x4E);//p7
//	i80_write_data(0xB7);//p8
//	i80_write_data(0x3C);//p9
//	i80_write_data(0x19);//p10
//	i80_write_data(0x22);//p11
//	i80_write_data(0x1E);//p12
//	i80_write_data(0x02);//p13
//	i80_write_data(0x01);//p14
//	i80_write_data(0x00);//p15
//
//	i80_write_cmd(0xE1);
//	i80_write_data(0x00);//p1
//	i80_write_data(0x1B);//p2
//	i80_write_data(0x1F);//p3
//	i80_write_data(0x0F);//p4
//	i80_write_data(0x16);//p5
//	i80_write_data(0x13);//p6
//	i80_write_data(0x31);//p7
//	i80_write_data(0x84);//p8
//	i80_write_data(0x43);//p9
//	i80_write_data(0x06);//p10
//	i80_write_data(0x1D);//p11
//	i80_write_data(0x21);//p12
//	i80_write_data(0x3D);//p13
//	i80_write_data(0x3E);//p14
//	i80_write_data(0x3F);//p15
//	
//	i80_write_cmd(0x29); // Display On
//	i80_write_cmd(0x2C);
}

void LCD_SetWindow(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{
//	CLR_DC;
	i80_write_cmd(0x2A);
	i80_write_data(0x00);
	i80_write_data(x1);
	i80_write_data(0x00);
	i80_write_data(x2);
	
	i80_write_cmd(0x2B);
	i80_write_data(0x00);
	i80_write_data(y1+32);
	i80_write_data(0x00);
	i80_write_data(y2+32);  
	i80_write_data(0x2C);            
	     				 
//	SET_DC;
}

void A250_ST7735S_Init(void)
{
	*P_TFT_RGB_Ctrl |= 0x0080; //memory mode

	gpio_init_io(IOE_PIN_1,1);
	gpio_set_port_attribute(IOE_PIN_1,1);
	gpio_write_io(IOE_PIN_1, 1);

	gpio_init_io(IOE_PIN_RST, 1);	
	gpio_set_port_attribute(IOE_PIN_RST, 1);
	gpio_write_io(IOE_PIN_RST, 1);
	cmd_longdelay(1);
    gpio_write_io(IOE_PIN_RST, 0);
    cmd_longdelay(10);
    gpio_write_io(IOE_PIN_RST, 1);
 	cmd_longdelay(50);

 /* TFT interface parameter */	
	R_TFT_V_PERIOD = 128-1;	//160-1; 
	R_TFT_VS_WIDTH = 20;	//20; 
	R_TFT_V_START  = 5; 
	R_TFT_H_PERIOD = 128-1;	//128-1; 
	R_TFT_HS_WIDTH = 5; 
	R_TFT_H_START  = 3; 
  
	R_TFT_HS_START = 0; 
	R_TFT_HS_END   = 127; 
	R_TFT_VS_START = 0; 
	R_TFT_VS_END   = 128; 
	
	*P_PPU_Free_Width= 128;//Display_Width;
	*P_PPU_Free_Height= 128;//Display_Height;	

    i80_write_cmd(0x01);	//software reset				 

	//Start initial sequence 		    
    i80_write_cmd(0x11);  	//exit sleep
    cmd_longdelay(120); 

	i80_write_cmd( 0xB1); 
	i80_write_data(0x05); 
	i80_write_data(0x3A); 
	i80_write_data(0x3A); 
	i80_write_cmd( 0xB2); 
	i80_write_data(0x05); 
	i80_write_data(0x3A); 
	i80_write_data(0x3A); 
	i80_write_cmd( 0xB3); 
	i80_write_data(0x05); 
	i80_write_data(0x3A); 
	i80_write_data(0x3A); 
	i80_write_data(0x05); 
	i80_write_data(0x3A); 
	i80_write_data(0x3A); 
	i80_write_cmd( 0xB4); //Dot inversion 
	i80_write_data(0x03); 
	i80_write_cmd( 0xC0); 
	i80_write_data(0x28); 
	i80_write_data(0x08); 
	i80_write_data(0x84); 
	i80_write_cmd( 0xC1); 
	i80_write_data(0xC5); 
	i80_write_cmd( 0xC2); 
	i80_write_data(0x0D); 
	i80_write_data(0x00); 
	i80_write_cmd( 0xC3); 
	i80_write_data(0x8D); 
	i80_write_data(0x2A); 
	i80_write_cmd( 0xC4); 
	i80_write_data(0x8D); 
	i80_write_data(0xEE); 
	i80_write_cmd( 0x35); //SET  TURN ON TE SINGLE
	i80_write_data(0x00); 
	i80_write_cmd( 0xC5); //VCOM 
	i80_write_data(0x12); 
	i80_write_cmd( 0x36); //MX, MY, RGB mode 
	i80_write_data(0xC8); 
	i80_write_cmd( 0xE0); 
	i80_write_data(0x03); 
	i80_write_data(0x1b); 
	i80_write_data(0x12); 
	i80_write_data(0x11); 
	i80_write_data(0x3f); 
	i80_write_data(0x3a); 
	i80_write_data(0x32); 
	i80_write_data(0x34); 
	i80_write_data(0x2f); 
	i80_write_data(0x2b); 
	i80_write_data(0x30); 
	i80_write_data(0x3a); 
	i80_write_data(0x00); 
	i80_write_data(0x01); 
	i80_write_data(0x02); 
	i80_write_data(0x05); 
	i80_write_cmd( 0xE1); 
	i80_write_data(0x03); 
	i80_write_data(0x1b); 
	i80_write_data(0x12); 
	i80_write_data(0x11); 
	i80_write_data(0x32); 
	i80_write_data(0x2f); 
	i80_write_data(0x2a); 
	i80_write_data(0x2f); 
	i80_write_data(0x2e); 
	i80_write_data(0x2c); 
	i80_write_data(0x35); 
	i80_write_data(0x3f); 
	i80_write_data(0x00); 
	i80_write_data(0x00); 
	i80_write_data(0x01); 
	i80_write_data(0x05); 
	i80_write_cmd( 0x3A); //65k mode 
	i80_write_data(0x05);

	i80_write_cmd(0x2A);	//Set Column Address
	i80_write_data(0x00);
	i80_write_data(0x00+2);
	i80_write_data(0x00);
	i80_write_data(0x7f+2);
	
    i80_write_cmd(0x2B);	//Set Page Address
	i80_write_data(0x00);
	i80_write_data(0x00+3);
	i80_write_data(0x00);
	// i80_write_data(0x9f);
	i80_write_data(0x7f+3);
 
	i80_write_cmd( 0x29); //Display on 

	i80_write_cmd(0x2C);
}

void LCD_I80_Align(void)
{
	i80_write_cmd(0x0);	// TFT Driver IC "NOP CMD", user should modify it for different TFT Driver IC
						// *P_TFT_Ctrl = 0x00 => RS = Low => Write CMD according to D[7:0]		
//	//1. stop CPU TFT
	*P_TFT_Ctrl = 0x00;						
//	i80tft_write_command(0x00);	//NOP command	
				
//	//2. send TFT module restart address command
	i80_write_cmd(0x2A);	//Set Column Address
	i80_write_data(0x00);
	i80_write_data(0x00+2);
	i80_write_data(0x00);
	i80_write_data(0x7f+2);
	
    i80_write_cmd(0x2B);	//Set Page Address
	i80_write_data(0x00);
	i80_write_data(0x00+3);
	i80_write_data(0x00);
	i80_write_data(0x7f+3);		
	i80_write_cmd(0x2C);	
	 					
	//3. restart CPU TFT
	while ((*P_TFT_Status & 0x00F0) != 0x0)		//restart TFT, check status = idle, 0x705A[7:4]=4'h0
		__asm ("nop");	
	*P_TFT_Ctrl = D_I80_TransferMode + D_I80_DataBitMode + D_I80_CLK + D_TFT_UnderRun_Ctrl;
	WaitBlanking();	
}


void tft_init(void)
{
    *P_TFT_Ctrl = 0;
}

void tft_start(int model)
{
    tft_init();
    switch(model) {   
		case A116_T180LA:
			A250_ST7735S_Init();
			break;
        default:
            return;
    }
#if 1
 //   *P_TFT_Ctrl = 0x20C9;	//0x20C7;			//Frank mask
#else
    tft_tft_en_set(1);
#endif    
}

//=== This is for code configuration DON'T REMOVE or MODIFY it ===//
#endif //(defined _DRV_L1_TFT) && (_DRV_L1_TFT == 1)                   //
//================================================================//
