/*********************************************************************************************
* File：	lcd_test.c
* Author:	
* Desc：	c main entry
* History:	
*			
*********************************************************************************************/
/*------------------------------------------------------------------------------------------*/
/*                                     include files	                                    */
/*------------------------------------------------------------------------------------------*/
#include "2410lib.h"

 typedef unsigned short int UINT16;
 typedef unsigned  int UINT32;
 typedef unsigned char  UINT8;

#define LOWER21BITS(n)  ((n) & 0x1fffff)

#define BPPMODE_1BPP    0x8
#define BPPMODE_2BPP    0x9
#define BPPMODE_4BPP    0xA
#define BPPMODE_8BPP    0xB
#define BPPMODE_16BPP   0xC
#define BPPMODE_24BPP   0xD

#define LCDTYPE_TFT     0x3

#define ENVID_DISABLE   0
#define ENVID_ENABLE    1

#define FORMAT8BPP_5551 0
#define FORMAT8BPP_565  1

#define GET_DATA  1

#define HSYNC_NORM      0
#define HSYNC_INV       1

#define VSYNC_NORM      0
#define VSYNC_INV       1

#define BSWP            1
#define HWSWP           1

//TFT 240320
#define LCD_XSIZE_TFT_240320 	(320)	
#define LCD_YSIZE_TFT_240320 	(240)

//TFT 240320
#define HOZVAL_TFT_240320	(LCD_XSIZE_TFT_240320-1)
#define LINEVAL_TFT_240320	(LCD_YSIZE_TFT_240320-1)

#define CLKVAL_TFT_240320	(4)
// 60hz @133Mhz
// (9) 60hz @100Mhz

//Timing parameter for LTS350Q1(SAMSUNG) 
#define VBPD_240320		((2-1)&0xff)
#define VFPD_240320		((2-1)&0xff)
#define VSPW_240320		((2-1) &0x3f)
#define HBPD_240320		((37-1)&0x7f)
#define HFPD_240320		((20-1)&0xff)
#define HSPW_240320		((4-1)&0xff)

#define LCDFRAMEBUFFER 0x30400000


unsigned int fb_base_addr;
unsigned int bpp;
unsigned int xsize;
unsigned int ysize;
/*
 * 初始化用于LCD的引脚
 */
void Lcd_Port_Init(void)
{
    rGPCUP   = 0xffffffff;   // 禁止内部上拉
    rGPCCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND 
    rGPDUP   = 0xffffffff;   // 禁止内部上拉
    rGPDCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8]
    uart_printf("Initializing GPIO ports..........\n");
}

void Tft_Lcd_Init(void)
{
        /* 
         * 设置LCD控制器的控制寄存器LCDCON1~5
         * 1. LCDCON1:
         *    设置VCLK的频率：VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
         *    选择LCD类型: TFT LCD   
         *    设置显示模式: 16BPP
         *    先禁止LCD信号输出
         * 2. LCDCON2/3/4:
         *    设置控制信号的时间参数
         *    设置分辨率，即行数及列数
         * 现在，可以根据公式计算出显示器的频率：
         * 当HCLK=100MHz时，
         * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
         *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
         *              {2x(CLKVAL+1)/(HCLK)}]
         *            = 60Hz
         * 3. LCDCON5:
         *    设置显示模式为16BPP时的数据格式: 5:6:5
         *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
         *    半字(2字节)交换使能
         */
        rLCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
                  (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
        rLCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
                  (VFPD_240320<<6) | (VSPW_240320);
        rLCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
        rLCDCON4 = HSPW_240320;
        rLCDCON5 = (FORMAT8BPP_565<<11) |(GET_DATA<<10)|(HSYNC_INV<<9) | (VSYNC_INV<<8) | \
                  (HWSWP<<1);

        /*
         * 设置LCD控制器的地址寄存器LCDSADDR1~3
         * 帧内存与视口(view point)完全吻合，
         * 图像数据格式如下：
         *         |----PAGEWIDTH----|
         *    y/x  0   1   2       239
         *     0   rgb rgb rgb ... rgb
         *     1   rgb rgb rgb ... rgb
         * 1. LCDSADDR1:
         *    设置LCDBANK、LCDBASEU
         * 2. LCDSADDR2:
         *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
         * 3. LCDSADDR3:
         *    OFFSIZE等于0，PAGEWIDTH等于(240*2/2)
         */
        rLCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
        rLCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
                    (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*2)>>1);
        rLCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);

        /* 禁止临时调色板寄存器 */
        rTPAL = 0;

        fb_base_addr = LCDFRAMEBUFFER;
        bpp = 16;
        xsize = 320;
        ysize = 240;

}

/*
 * 设置是否输出LCD电源开关信号LCD_PWREN
 * 输入参数：
 *     invpwren: 0 - LCD_PWREN有效时为正常极性
 *               1 - LCD_PWREN有效时为反转极性
 *     pwren:    0 - LCD_PWREN输出有效
 *               1 - LCD_PWREN输出无效
 */
void Lcd_PowerEnable(int invpwren, int pwren)
{
    rGPGCON = (rGPGCON & (~(3<<8))) | (3<<8);   // GPG4用作LCD_PWREN
    rGPGUP  = (rGPGUP & (~(1<<4))) | (1<<4);    // 禁止内部上拉
    
    rLCDCON5 = (rLCDCON5 & (~(1<<5))) | (invpwren<<5);  // 设置LCD_PWREN的极性: 正常/反转
    rLCDCON5 = (rLCDCON5 & (~(1<<3))) | (pwren<<3);     // 设置是否输出LCD_PWREN
}    

/*
 * 设置LCD控制器是否输出信号
 * 输入参数：
 * onoff: 
 *      0 : 关闭
 *      1 : 打开
 */
void Lcd_EnvidOnOff(int onoff)
{
    if (onoff == 1)
        rLCDCON1 |= 1;         // ENVID ON
    else
        rLCDCON1 &= 0x3fffe; // ENVID Off
}    

/* 
 * 画点
 * 输入参数：
 *     x、y : 象素坐标
 *     color: 颜色值
 *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
 *     需要转换为5:6:5格式
 *         对于8BPP: color为调色板中的索引值，
 *     其颜色取决于调色板中的数值
 */


void PutPixel(UINT32 x, UINT32 y, UINT32 color)
{
    UINT8 red,green,blue;

    switch (bpp){
        case 16:
        {
            UINT16 *addr = (UINT16 *)fb_base_addr + (y * xsize + x);
            red   = (color >> 19) & 0xff;
            green = (color >> 10) & 0xff;
            blue  = (color >>  3) & 0xff;
            color = (red << 11) | (green << 5) | blue; // 格式5:6:5
            *addr = (UINT16) color;
            break;
        }
        
        case 8:
        {
            UINT8 *addr = (UINT8 *)fb_base_addr + (y * xsize + x);
            *addr = (UINT8) color;
            break;
        }

        default:
            break;
    }
}

 /* 
 * 将屏幕清成单色
 * 输入参数：
 *     color: 颜色值
 *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
 *     需要转换为5:6:5格式
 *         对于8BPP: color为调色板中的索引值，
 *     其颜色取决于调色板中的数值
 */
void ClearScr(unsigned int color)
{   
    unsigned int x,y;
    
    for (y = 0; y < ysize; y++)
        for (x = 0; x < xsize; x++)
            PutPixel(x, y, color);
}

/* 
 * 画线
 * 输入参数：
 *     x1、y1 : 起点坐标
 *     x2、y2 : 终点坐标
 *     color  : 颜色值
 *         对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
 *     需要转换为5:6:5格式
 *         对于8BPP: color为调色板中的索引值，
 *     其颜色取决于调色板中的数值
 */
void DrawLine(int x1,int y1,int x2,int y2,int color)
{
    int dx,dy,e;
    dx=x2-x1; 
    dy=y2-y1;
    
    if(dx>=0)
    {
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 1/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1+=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 2/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1+=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 8/8 octant
            {
                e=dy-dx/2;
                while(x1<=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1-=1;e-=dx;}   
                    x1+=1;
                    e+=dy;
                }
            }
            else        // 7/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1+=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }
    else //dx<0
    {
        dx=-dx;     //dx=abs(dx)
        if(dy >= 0) // dy>=0
        {
            if(dx>=dy) // 4/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1+=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 3/8 octant
            {
                e=dx-dy/2;
                while(y1<=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1-=1;e-=dy;}   
                    y1+=1;
                    e+=dx;
                }
            }
        }
        else           // dy<0
        {
            dy=-dy;   // dy=abs(dy)

            if(dx>=dy) // 5/8 octant
            {
                e=dy-dx/2;
                while(x1>=x2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){y1-=1;e-=dx;}   
                    x1-=1;
                    e+=dy;
                }
            }
            else        // 6/8 octant
            {
                e=dx-dy/2;
                while(y1>=y2)
                {
                    PutPixel(x1,y1,color);
                    if(e>0){x1-=1;e-=dy;}   
                    y1-=1;
                    e+=dx;
                }
            }
        }   
    }
}

/*end of the file*/
/**************************************************************
在LCD屏幕上指定坐标点画一个指定大小的图片
**************************************************************/
static void Paint_Bmp(int x0,int y0,int x1,int y1,const unsigned char bmp[])
{
	int x,y;

	int p = 0;

	//本图片显示是正的显示方式
    unsigned long addr = (unsigned long) 0x30400000;
	//memset(addr,0,0x400000);
    for( y = 0 ; y < y1 ; y++ )
    {
    	for( x = 0 ; x < x1 ; x++ )
    	{
    		
			if ( ( (x0+x) < 320) && ( (y0+y) < 240) )
				  *(unsigned short *)(addr + ((x + (y *320))<<1)) = (bmp[p+1])|(bmp[p]<<8);

    		p = p + 2 ;
    	}
    }
 }


 extern const unsigned char gImage_logo[153600] ;
/*********************************************************************************************
* name:		lcd_test
* func:		lcd test function
* para:		none
* ret:		none
* modify:
* comment:		
*********************************************************************************************/
void lcd_test(void)
{
 	Lcd_Port_Init();                     // 设置LCD引脚	
	Tft_Lcd_Init();						 // 初始化LCD控制器
    Lcd_PowerEnable(0, 0);               // 设置LCD_PWREN有效，它用于打开LCD的电源
	Lcd_EnvidOnOff(1);                   // 使能LCD控制器输出信号
	ClearScr(0x0);                       // 清屏
    Paint_Bmp(0,0,320,240,gImage_logo);    //显示图片
}


