1224 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1224 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***
 | 
						||
	*****************************************************************************************
 | 
						||
	*	@file  	lcd.c
 | 
						||
	*	@brief   使用STM32F29本身的控制器驱动液晶屏,一下代码移植于官方 STM32F429I_DISCOVERY 
 | 
						||
	*				实验板的例程,并作出相应的修改
 | 
						||
   *****************************************************************************************
 | 
						||
   *  
 | 
						||
	* 
 | 
						||
	* 
 | 
						||
	* 
 | 
						||
	******************************************************************************************
 | 
						||
***/
 | 
						||
 | 
						||
#include "lcd_rgb.h"
 | 
						||
#include "mymem.h"
 | 
						||
 | 
						||
// 函数:IO口初始化
 | 
						||
//
 | 
						||
void LCD_GPIO_Config(void)
 | 
						||
{ 
 | 
						||
	GPIO_InitTypeDef GPIO_InitStruct;
 | 
						||
 | 
						||
	RCC_AHB1PeriphClockCmd( LCD_GPIO_CLK,ENABLE); 	
 | 
						||
						
 | 
						||
	GPIO_InitStruct.GPIO_Pin   = LTDC_R0_PIN;                             
 | 
						||
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
 | 
						||
	GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF;
 | 
						||
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
 | 
						||
	GPIO_InitStruct.GPIO_PuPd  = GPIO_PuPd_UP;
 | 
						||
 | 
						||
	// LCD 颜色 R 引脚配置 
 | 
						||
	GPIO_PinAFConfig(LTDC_R0_PORT, LTDC_R0_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R1_PORT, LTDC_R1_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R2_PORT, LTDC_R2_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R3_PORT, LTDC_R3_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R4_PORT, LTDC_R4_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R5_PORT, LTDC_R5_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
	GPIO_PinAFConfig(LTDC_R6_PORT, LTDC_R6_PINSOURCE, GPIO_AF_LTDC);
 | 
						||
	GPIO_PinAFConfig(LTDC_R7_PORT, LTDC_R7_PINSOURCE, GPIO_AF_LTDC);	
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R0_PIN;	
 | 
						||
	GPIO_Init(LTDC_R0_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R1_PIN;
 | 
						||
	GPIO_Init(LTDC_R1_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R2_PIN;
 | 
						||
	GPIO_Init(LTDC_R2_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R3_PIN;
 | 
						||
	GPIO_Init(LTDC_R3_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R4_PIN;
 | 
						||
	GPIO_Init(LTDC_R4_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R5_PIN;
 | 
						||
	GPIO_Init(LTDC_R5_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R6_PIN;
 | 
						||
	GPIO_Init(LTDC_R6_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_R7_PIN;
 | 
						||
	GPIO_Init(LTDC_R7_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
  
 | 
						||
  // LCD 颜色 G 引脚配置 
 | 
						||
  
 | 
						||
	GPIO_PinAFConfig(LTDC_G0_PORT, LTDC_G0_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_G1_PORT, LTDC_G1_PINSOURCE, GPIO_AF_LTDC); 
 | 
						||
	GPIO_PinAFConfig(LTDC_G2_PORT, LTDC_G2_PINSOURCE, GPIO_AF_LTDC); 
 | 
						||
	GPIO_PinAFConfig(LTDC_G3_PORT, LTDC_G3_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_G4_PORT, LTDC_G4_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_G5_PORT, LTDC_G5_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_G6_PORT, LTDC_G6_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_G7_PORT, LTDC_G7_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
  
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G0_PIN;
 | 
						||
	GPIO_Init(LTDC_G0_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G1_PIN;
 | 
						||
	GPIO_Init(LTDC_G1_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G2_PIN;
 | 
						||
	GPIO_Init(LTDC_G2_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G3_PIN;
 | 
						||
	GPIO_Init(LTDC_G3_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G4_PIN;
 | 
						||
	GPIO_Init(LTDC_G4_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G5_PIN;
 | 
						||
	GPIO_Init(LTDC_G5_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G6_PIN;
 | 
						||
	GPIO_Init(LTDC_G6_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_G7_PIN;
 | 
						||
	GPIO_Init(LTDC_G7_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
  
 | 
						||
  // LCD 颜色 B 引脚配置 
 | 
						||
  
 | 
						||
	GPIO_PinAFConfig(LTDC_B0_PORT, LTDC_B0_PINSOURCE, GPIO_AF_LTDC); 
 | 
						||
	GPIO_PinAFConfig(LTDC_B1_PORT, LTDC_B1_PINSOURCE, GPIO_AF_LTDC); 	
 | 
						||
	GPIO_PinAFConfig(LTDC_B2_PORT, LTDC_B2_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_B3_PORT, LTDC_B3_PINSOURCE, GPIO_AF_LTDC);
 | 
						||
	GPIO_PinAFConfig(LTDC_B4_PORT, LTDC_B4_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_B5_PORT, LTDC_B5_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_B6_PORT, LTDC_B6_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_B7_PORT, LTDC_B7_PINSOURCE, GPIO_AF_LTDC);  
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B0_PIN;
 | 
						||
	GPIO_Init(LTDC_B0_PORT, &GPIO_InitStruct);
 | 
						||
	
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B1_PIN;
 | 
						||
	GPIO_Init(LTDC_B1_PORT, &GPIO_InitStruct);
 | 
						||
	
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B2_PIN;
 | 
						||
	GPIO_Init(LTDC_B2_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B3_PIN;
 | 
						||
	GPIO_Init(LTDC_B3_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B4_PIN;
 | 
						||
	GPIO_Init(LTDC_B4_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B5_PIN;
 | 
						||
	GPIO_Init(LTDC_B5_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B6_PIN;
 | 
						||
	GPIO_Init(LTDC_B6_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_B7_PIN;
 | 
						||
	GPIO_Init(LTDC_B7_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
  
 | 
						||
  //控制线
 | 
						||
	GPIO_PinAFConfig(LTDC_CLK_PORT,   LTDC_CLK_PINSOURCE,  GPIO_AF_LTDC); 
 | 
						||
	GPIO_PinAFConfig(LTDC_HSYNC_PORT, LTDC_HSYNC_PINSOURCE,GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_VSYNC_PORT, LTDC_VSYNC_PINSOURCE,GPIO_AF_LTDC);  
 | 
						||
	GPIO_PinAFConfig(LTDC_DE_PORT,    LTDC_DE_PINSOURCE,   GPIO_AF_LTDC);
 | 
						||
    
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_CLK_PIN;
 | 
						||
	GPIO_Init(LTDC_CLK_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_HSYNC_PIN;
 | 
						||
	GPIO_Init(LTDC_HSYNC_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_VSYNC_PIN;
 | 
						||
	GPIO_Init(LTDC_VSYNC_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_DE_PIN;
 | 
						||
	GPIO_Init(LTDC_DE_PORT, &GPIO_InitStruct);
 | 
						||
			
 | 
						||
	//背光
 | 
						||
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
 | 
						||
	GPIO_InitStruct.GPIO_Pin = LTDC_Black_PIN; 
 | 
						||
	GPIO_Init(LTDC_Black_PORT, &GPIO_InitStruct);
 | 
						||
 | 
						||
	GPIO_SetBits(LTDC_Black_PORT,LTDC_Black_PIN);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
void LCD_Backlight (u8 power)
 | 
						||
{
 | 
						||
	if (power)
 | 
						||
	{
 | 
						||
		GPIO_SetBits(LTDC_Black_PORT,LTDC_Black_PIN);
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
		GPIO_ResetBits(LTDC_Black_PORT,LTDC_Black_PIN);
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static u32* LCD_ADDR =((u32*)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET*0));
 | 
						||
static u32* LCD_ADDR1 =((u32*)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET*1));
 | 
						||
#define LCD_ADDR_BUFF0  ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*0))
 | 
						||
#define LCD_ADDR_BUFF1  ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*1))
 | 
						||
#define LCD_ADDR_BUFF2  ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*2))
 | 
						||
 | 
						||
const static u32 g_lcdAddrTable[3]=
 | 
						||
{
 | 
						||
	(u32)LCD_ADDR_BUFF0,
 | 
						||
	(u32)LCD_ADDR_BUFF1,	
 | 
						||
	(u32)LCD_ADDR_BUFF2,
 | 
						||
};
 | 
						||
 | 
						||
static LCD_Struct g_lcd={0};
 | 
						||
 
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 函数:初始化LCD控制器
 | 
						||
//	说明:在emWin初始化里被调用
 | 
						||
//
 | 
						||
void LCD_Init(void)
 | 
						||
{ 
 | 
						||
	u16 LCD_PLLSAIN = 0;		//用于倍频的PLLSAIN参数,可取范围为50~432
 | 
						||
	u8  LCD_PLLSAIR = 3;		//用于分频的PLLSAIR参数,可取范围为2~7
 | 
						||
	u8  LCD_CLKDIV	 = 8;		//LCD时钟分频参数,默认设置为8分频,数值上等于RCC_PLLSAIDivR_Div8
 | 
						||
	
 | 
						||
	LTDC_InitTypeDef       LTDC_InitStruct;
 | 
						||
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE); 
 | 
						||
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE); 
 | 
						||
 | 
						||
	LCD_GPIO_Config();  //初始化LCD引脚
 | 
						||
 | 
						||
	LCD_PLLSAIN = LCD_CLK * LCD_PLLSAIR * LCD_CLKDIV;	//根据需要使用的LCD时钟计算PLLSAIN参数,可取范围为50~432
 | 
						||
	RCC_PLLSAIConfig(LCD_PLLSAIN,7,LCD_PLLSAIR);  		//时钟配置
 | 
						||
	RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8);	 		//LCD时钟分频设置,要和LCD_CLKDIV对应
 | 
						||
	RCC_PLLSAICmd(ENABLE);		//使能PLLSAI时钟
 | 
						||
	while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET);	//等待时钟配置完成
 | 
						||
	
 | 
						||
	LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL;     
 | 
						||
	LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL;     
 | 
						||
	LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL;     
 | 
						||
	LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC;
 | 
						||
              
 | 
						||
	LTDC_InitStruct.LTDC_BackgroundRedValue = 0;            
 | 
						||
	LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;          
 | 
						||
	LTDC_InitStruct.LTDC_BackgroundBlueValue = 0;   
 | 
						||
 | 
						||
	LTDC_InitStruct.LTDC_HorizontalSync =HSW;
 | 
						||
	LTDC_InitStruct.LTDC_VerticalSync = VSW;
 | 
						||
	LTDC_InitStruct.LTDC_AccumulatedHBP =HBP;
 | 
						||
	LTDC_InitStruct.LTDC_AccumulatedVBP = VBP;
 | 
						||
	LTDC_InitStruct.LTDC_AccumulatedActiveW = LCD_Width+HBP;
 | 
						||
	LTDC_InitStruct.LTDC_AccumulatedActiveH = LCD_Height+VBP;
 | 
						||
	LTDC_InitStruct.LTDC_TotalWidth =LCD_Width + HBP + HFP; 
 | 
						||
	LTDC_InitStruct.LTDC_TotalHeigh =LCD_Height + VBP + VFP;
 | 
						||
 | 
						||
	LTDC_Init(<DC_InitStruct);	//初始化LCD控制器
 | 
						||
	LTDC_ITConfig (LTDC_IT_LI,ENABLE);
 | 
						||
	NVIC_SetPriority(LTDC_IRQn, 0);
 | 
						||
	NVIC_EnableIRQ(LTDC_IRQn); 
 | 
						||
	LTDC_Cmd(ENABLE);	//使能LCD控制器
 | 
						||
	
 | 
						||
	LCD_LayerInit();
 | 
						||
	
 | 
						||
	g_lcd.x_size = LCD_Width;
 | 
						||
	g_lcd.y_size = LCD_Height;
 | 
						||
	g_lcd.show = (u16 *)g_lcdAddrTable[0];
 | 
						||
	g_lcd.draw = (u16 *)g_lcdAddrTable[1];
 | 
						||
	LCD_SetWindow(0, 0, g_lcd.x_size, g_lcd.y_size);
 | 
						||
	g_lcd.bkColor = 0x0;
 | 
						||
 | 
						||
}  
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 函数:LCD层设置初始化
 | 
						||
//	
 | 
						||
void LCD_LayerInit(void)
 | 
						||
{
 | 
						||
	LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct; 
 | 
						||
 | 
						||
	LTDC_Layer_InitStruct.LTDC_HorizontalStart = HBP + 1;
 | 
						||
	LTDC_Layer_InitStruct.LTDC_HorizontalStop = (LCD_Width + HBP);
 | 
						||
	LTDC_Layer_InitStruct.LTDC_VerticalStart =  VBP + 1;
 | 
						||
	LTDC_Layer_InitStruct.LTDC_VerticalStop = (LCD_Height + VBP);
 | 
						||
	//LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_ARGB8888;	//像素格式设置
 | 
						||
	LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_RGB565;	//像素格式设置
 | 
						||
	LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255; 
 | 
						||
	LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0; 	//  默认的颜色       
 | 
						||
	LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0;       
 | 
						||
	LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0;         
 | 
						||
	LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0;
 | 
						||
	LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA;    
 | 
						||
	LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_CA;
 | 
						||
	LTDC_Layer_InitStruct.LTDC_CFBLineNumber  = LCD_Height; //显示区域的行数
 | 
						||
	LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_MemoryAdd; //第一层的起始地址
 | 
						||
	
 | 
						||
	//这里ARGB8888和RGB888使用相同的计算方式
 | 
						||
	{	
 | 
						||
//		LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 4) + 3);	//每行的像素占的总字节数
 | 
						||
//		LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 4);  			   //行间距,某像素的起始处到下一行的起始处的增量
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 2) + 3);	//每行的像素占的总字节数
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 2);  			   //行间距,某像素的起始处到下一行的起始处的增量
 | 
						||
	}
 | 
						||
	LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct);	//初始化层1
 | 
						||
 	LTDC_LayerCmd(LTDC_Layer1, ENABLE);  //使能层1
 | 
						||
 | 
						||
#if ( LCD_NUM_LAYERS == 2 )	//当定义了双层时
 | 
						||
 | 
						||
	LTDC_Layer_InitStruct.LTDC_PixelFormat = ColorMode_1;		//像素格式设置
 | 
						||
	LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA;  
 | 
						||
	LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA;
 | 
						||
	LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_MemoryAdd + LCD_MemoryAdd_OFFSET; //层2的起始地址
 | 
						||
 | 
						||
	if( ColorMode_1 == LCD_RGB565 || ColorMode_1 == LCD_ARGB1555 ) //判断颜色格式
 | 
						||
	{
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 2) + 3);	//每行的像素占的总字节数
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 2);  				//行间距,某像素的起始处到下一行的起始处的增量
 | 
						||
	}
 | 
						||
	else //这里ARGB8888和RGB888使用相同的计算方式
 | 
						||
	{	
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 4) + 3);	//每行的像素占的总字节数
 | 
						||
		LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 4); 			 //行间距,某像素的起始处到下一行的起始处的增量
 | 
						||
	}
 | 
						||
	LTDC_LayerInit(LTDC_Layer2, <DC_Layer_InitStruct);	//初始化层2
 | 
						||
	LTDC_LayerCmd(LTDC_Layer2, ENABLE);  //使能层2
 | 
						||
#endif
 | 
						||
 | 
						||
	LTDC_ReloadConfig(LTDC_IMReload); //重新载入参数
 | 
						||
	LTDC_DitherCmd(ENABLE);		//使能颜色抖动,24位色必须打开,否则无法达到24位色的效果
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
void LTDC_ISR_Handler (void)
 | 
						||
{
 | 
						||
	LTDC_ClearFlag (LTDC_FLAG_LI);
 | 
						||
	if (g_lcd.LcdSwitchEn==1)
 | 
						||
	{
 | 
						||
		g_lcd.LcdSwitchEn=0;
 | 
						||
		LTDC_Layer1->CFBAR =(u32 )g_lcd.show;
 | 
						||
		LTDC->SRCR=1;
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static int LCD_UpDataWindow(void)
 | 
						||
{
 | 
						||
	LCD_WindowStruct *win = &g_lcd.win;
 | 
						||
	LCD_WindowStruct *draw = &g_lcd.realwin;
 | 
						||
	int real = 1;
 | 
						||
	if (win->xs >= 0 && win->xs < g_lcd.x_size)
 | 
						||
		draw->xs = win->xs;
 | 
						||
	else if (win->xs < 0)
 | 
						||
		draw->xs = 0;
 | 
						||
	else if (win->xs >= g_lcd.x_size)
 | 
						||
		real = 0;//在显示区域外
 | 
						||
 | 
						||
	if (win->ys >= 0 && win->ys < g_lcd.y_size)
 | 
						||
		draw->ys = win->ys;
 | 
						||
	else if (win->ys < 0)
 | 
						||
		draw->ys = 0;
 | 
						||
	else if (win->ys >= g_lcd.y_size)
 | 
						||
		real = 0;//在显示区域外
 | 
						||
 | 
						||
	if (win->xe >= 0 && win->xe < g_lcd.x_size)
 | 
						||
		draw->xe = win->xe;
 | 
						||
	else if (win->xe < 0)
 | 
						||
		real = 0;//在显示区域外
 | 
						||
	else if (win->xe>=g_lcd.x_size)
 | 
						||
		draw->xe = g_lcd.x_size-1;
 | 
						||
 | 
						||
	if (win->ye >= 0 && win->ye < g_lcd.y_size)
 | 
						||
		draw->ye = win->ye;
 | 
						||
	else if (win->ye < 0)
 | 
						||
		real = 0;//在显示区域外
 | 
						||
	else if (win->ye >= g_lcd.y_size)
 | 
						||
		draw->ye = g_lcd.y_size - 1;
 | 
						||
 | 
						||
	if ((win->xs > win->xe) || (win->ys > win->ye))
 | 
						||
		real = 0;
 | 
						||
	g_lcd.effective = real;
 | 
						||
	return real;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//设置活动窗口
 | 
						||
void LCD_SetWindow (int x_s,int y_s,int x_size,int y_size)
 | 
						||
{
 | 
						||
	g_lcd.win.xs = x_s;
 | 
						||
	g_lcd.win.ys = y_s;
 | 
						||
	g_lcd.win.xe = x_s + x_size - 1;
 | 
						||
	g_lcd.win.ye = y_s + y_size - 1;
 | 
						||
	LCD_UpDataWindow();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
//int LCD_GetWindowSizeX (void)
 | 
						||
//{
 | 
						||
//	return g_lcd_struct.WindowDstX-g_lcd_struct.WindowSrcX+1;
 | 
						||
//}
 | 
						||
 | 
						||
//int LCD_GetWindowSizeY (void)
 | 
						||
//{
 | 
						||
//	return g_lcd_struct.WindowDstY-g_lcd_struct.WindowSrcY+1;
 | 
						||
//}
 | 
						||
 | 
						||
int LCD_GetLcdSizeX(void)
 | 
						||
{
 | 
						||
	return LCD_Width;
 | 
						||
}
 | 
						||
 | 
						||
int LCD_GetLcdSizeY (void)
 | 
						||
{
 | 
						||
	return LCD_Height;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//获取图像显示地址
 | 
						||
u32 *LCD_GetShowAddr (void)
 | 
						||
{
 | 
						||
	uint32_t *ret=(u32*)LTDC_Layer1->CFBAR;
 | 
						||
	ret=(u32*)g_lcd.show;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
//获取图像绘制地址
 | 
						||
u32 *LCD_GetDrawAddr (void)
 | 
						||
{
 | 
						||
	uint32_t *ret=0;
 | 
						||
	ret=(u32*)g_lcd.draw;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//设置屏幕显示地址,这个地址直接输出到屏幕上,返回上一个输出到屏幕的地址
 | 
						||
u32 LCD_SetLayer (u32 AddrIndex)
 | 
						||
{
 | 
						||
	uint32_t ret=LTDC_Layer1->CFBAR;
 | 
						||
	if (AddrIndex<3)
 | 
						||
	{
 | 
						||
		g_lcd.show=(u16 * )g_lcdAddrTable[AddrIndex];
 | 
						||
		LTDC_Layer1->CFBAR = g_lcdAddrTable[AddrIndex];
 | 
						||
		LTDC->SRCR=1;
 | 
						||
	}
 | 
						||
	for (int i=0;i<3;i++)
 | 
						||
	{
 | 
						||
		if (ret==g_lcdAddrTable[i])
 | 
						||
		{
 | 
						||
			ret=i;
 | 
						||
			break;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	if (ret>=3) ret=0;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
//设置绘图地址,所有绘制操作在这个地址执行
 | 
						||
u32 LCD_SetDrawLayer (u32 Index)
 | 
						||
{
 | 
						||
	u32 ret=(u32)g_lcd.draw;
 | 
						||
	if (Index<3)
 | 
						||
	{
 | 
						||
		g_lcd.draw=(u16*)g_lcdAddrTable[Index];
 | 
						||
	}
 | 
						||
	for (int i=0;i<3;i++)
 | 
						||
	{
 | 
						||
		if (ret==g_lcdAddrTable[i])
 | 
						||
		{
 | 
						||
			ret=i;
 | 
						||
			break;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	if (ret>=3) ret=0;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
u32 LCD_SetLcdColor (u32 color)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.color;
 | 
						||
	//g_lcd_struct.Color=color;
 | 
						||
	g_lcd.color=COLOR888TO565(color);
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
u32 LCD_SetLcdBkColor (u32 color)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.bkColor;
 | 
						||
	//g_lcd_struct.BackColor=color;
 | 
						||
	ret=g_lcd.bkColor=COLOR888TO565(color);
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
u32 LCD_SetLcdColor16 (u32 color)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.color;
 | 
						||
	g_lcd.color=(color);
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
u32 LCD_SetLcdBkColor16 (u32 color)
 | 
						||
{
 | 
						||
	u32 ret=ret=g_lcd.bkColor;
 | 
						||
	ret=g_lcd.bkColor=(color);
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
u32 LCD_GetLcdColor (void)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.color;
 | 
						||
	return COLOR565TO888(ret);
 | 
						||
}
 | 
						||
 | 
						||
u32 LCD_GetLcdBkColor (void)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.bkColor;
 | 
						||
	return COLOR565TO888(ret);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
u32 LCD_GetLcdColor16 (void)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.color;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
u32 LCD_GetLcdBkColor16 (void)
 | 
						||
{
 | 
						||
	u32 ret=g_lcd.bkColor;
 | 
						||
	return ret;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
//设置绘制模式,1,不绘制背景,0,绘制背景
 | 
						||
void LCD_SetLcdDrawMode (int mode)
 | 
						||
{
 | 
						||
	if (mode)
 | 
						||
	{
 | 
						||
		//g_lcd.DrawMode=1;//此时调用画点函数时不绘制背景色
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
		//g_lcd.DrawMode=0;
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static void LCD_DmaCopy(void * pSrc, void * pDst, uint32_t x_size,uint32_t y_size)
 | 
						||
{
 | 
						||
	DMA2D_DeInit();
 | 
						||
  /* Set up mode */
 | 
						||
  
 | 
						||
  DMA2D->CR      = 0x00010000UL | (1 << 9);         /* Control Register (Memory to memory with pixel format conversion and TCIE) */
 | 
						||
  
 | 
						||
  /* Set up pointers */
 | 
						||
  DMA2D->FGMAR   = (uint32_t)pSrc;                       /* Foreground Memory Address Register (Source address) */
 | 
						||
  DMA2D->OMAR    = (uint32_t)pDst;                       /* Output Memory Address Register (Destination address) */
 | 
						||
  
 | 
						||
  /* Set up offsets */
 | 
						||
  DMA2D->FGOR    = 0;                               /* Foreground Offset Register (Source line offset) */
 | 
						||
  DMA2D->OOR     = 0;                               /* Output Offset Register (Destination line offset) */
 | 
						||
  
 | 
						||
  /* Set up pixel format */
 | 
						||
  DMA2D->FGPFCCR = LTDC_Pixelformat_RGB565;                  /* Foreground PFC Control Register (Defines the input pixel format) */
 | 
						||
  DMA2D->OPFCCR  = LTDC_Pixelformat_RGB565;                  /* Output PFC Control Register (Defines the output pixel format) */
 | 
						||
  
 | 
						||
  /* Set up size */
 | 
						||
  DMA2D->NLR     = (uint32_t)(x_size << 16) | y_size;       /* Number of Line Register (Size configuration of area to be transfered) */
 | 
						||
  
 | 
						||
  /* Execute operation */
 | 
						||
  DMA2D->CR     |= DMA2D_CR_START;  
 | 
						||
    
 | 
						||
  while (DMA2D->CR & DMA2D_CR_START) 
 | 
						||
  {
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static void LCD_FillColor(void * pDst, int x,int y, int x_size,int y_size,u32 color)
 | 
						||
{
 | 
						||
	DMA2D_DeInit();
 | 
						||
 | 
						||
	DMA2D->OPFCCR = DMA2D_RGB565;
 | 
						||
 | 
						||
 | 
						||
	DMA2D->CR     = DMA2D_R2M;
 | 
						||
	DMA2D->OCOLR  = color;
 | 
						||
	DMA2D->OMAR   = (u32)pDst+(y*LCD_Width+x)*2;
 | 
						||
	DMA2D->OOR    = LCD_Width-x_size;
 | 
						||
	DMA2D->NLR    = (x_size<<16)|y_size;
 | 
						||
 | 
						||
	
 | 
						||
  /* Execute operation */
 | 
						||
  DMA2D->CR     |= DMA2D_CR_START;  
 | 
						||
    
 | 
						||
  while (DMA2D->CR & DMA2D_CR_START) 
 | 
						||
  {
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void LCD_FillImg(const u16 *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits)
 | 
						||
{
 | 
						||
 | 
						||
	DMA2D_DeInit();
 | 
						||
 | 
						||
	DMA2D->OPFCCR = DMA2D_RGB565;
 | 
						||
 | 
						||
	DMA2D->CR = DMA2D_M2M;
 | 
						||
 | 
						||
	DMA2D->OMAR   = (u32)pSurf+(y*LCD_Width+x)*2;
 | 
						||
	DMA2D->OOR    = LCD_Width-w;
 | 
						||
 | 
						||
	DMA2D->NLR    = (w<<16)|h;
 | 
						||
 | 
						||
	DMA2D->FGPFCCR = CM_RGB565;
 | 
						||
	DMA2D->FGMAR  = (u32)bits;
 | 
						||
	DMA2D->FGOR   = (width_bytes>>1)-w;
 | 
						||
 | 
						||
 | 
						||
  /* Execute operation */
 | 
						||
  DMA2D->CR     |= DMA2D_CR_START;  
 | 
						||
    
 | 
						||
  while (DMA2D->CR & DMA2D_CR_START) 
 | 
						||
  {
 | 
						||
  }
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//层复制
 | 
						||
void LCD_LayerCopy (int dst,int src)
 | 
						||
{
 | 
						||
	u32 *p_dst=0;
 | 
						||
	u32 *p_src=0;
 | 
						||
	if ((dst<3)&&(src<3))
 | 
						||
	{
 | 
						||
		p_dst=(u32 *)g_lcdAddrTable[dst];
 | 
						||
		p_src=(u32 *)g_lcdAddrTable[src];
 | 
						||
//		for (int i=0;i<LCD_Pixels;i++)
 | 
						||
//		{
 | 
						||
//			p_dst[i]=p_src[i];
 | 
						||
//		}
 | 
						||
		LCD_DmaCopy (p_src,p_dst,LCD_Width,LCD_Height);
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
//开始在缓冲区绘制
 | 
						||
void LCD_LayerBufferOn (void)
 | 
						||
{
 | 
						||
	//为了兼容以前的窗口,保留这个空函数,2019.12.26
 | 
						||
}
 | 
						||
 | 
						||
//显示缓冲层
 | 
						||
void LCD_LayerBuffShow (void)
 | 
						||
{
 | 
						||
	//为了兼容以前的窗口,保留这个空函数,2019.12.26
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
//进入缓冲区
 | 
						||
void LCD_EnterLayerBuff (void)
 | 
						||
{
 | 
						||
	if (g_lcd.LayerBuffEnter!=0) return;
 | 
						||
	g_lcd.LayerBuffEnter++;
 | 
						||
	
 | 
						||
	//while(LCD_GetLayerUpdataStat()==0);
 | 
						||
	if (g_lcd.LcdSwitchEn==1)
 | 
						||
	{
 | 
						||
		//如果上次更改还没来得及刷新,不刷新了,这次更改之后一起刷新
 | 
						||
		//如果应用程序中屏幕刷新太快,会造成丢帧
 | 
						||
		g_lcd.LcdSwitchEn=0;
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
		//刷新了之后,lcd显示区和绘图区是同一段内存,需要错开
 | 
						||
		if ((u32)g_lcd.show==g_lcdAddrTable[0])
 | 
						||
		{
 | 
						||
			g_lcd.draw=(u16*)g_lcdAddrTable[1];
 | 
						||
			LCD_LayerCopy(1,0);
 | 
						||
		}
 | 
						||
		else if ((u32)g_lcd.show==g_lcdAddrTable[1])
 | 
						||
		{
 | 
						||
			g_lcd.draw=(u16*)g_lcdAddrTable[0];
 | 
						||
			LCD_LayerCopy(0,1);
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
//切换层,不用复制显示,播放视频时用
 | 
						||
void LCD_SwitchLayerBuff (void)
 | 
						||
{
 | 
						||
	if (g_lcd.LayerBuffEnter!=0) return;
 | 
						||
	g_lcd.LayerBuffEnter++;
 | 
						||
	if (g_lcd.LcdSwitchEn==1)
 | 
						||
	{
 | 
						||
		//如果上次更改还没来得及刷新,不刷新了,这次更改之后一起刷新
 | 
						||
		//如果应用程序中屏幕刷新太快,会造成丢帧
 | 
						||
		g_lcd.LcdSwitchEn=0;
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
		//刷新了之后,lcd显示区和绘图区是同一段内存,需要错开
 | 
						||
		if ((u32)g_lcd.show==g_lcdAddrTable[0])
 | 
						||
		{
 | 
						||
			g_lcd.draw=(u16*)g_lcdAddrTable[1];
 | 
						||
		}
 | 
						||
		else if ((u32)g_lcd.show==g_lcdAddrTable[1])
 | 
						||
		{
 | 
						||
			g_lcd.draw=(u16*)g_lcdAddrTable[0];
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//退出缓冲区
 | 
						||
void LCD_ExitLayerBuff (void)
 | 
						||
{
 | 
						||
	g_lcd.show=g_lcd.draw;
 | 
						||
	g_lcd.LcdSwitchEn=1;
 | 
						||
	g_lcd.LayerBuffEnter=0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//获取屏幕刷新状态,1,已刷新
 | 
						||
int LCD_GetLayerUpdataStat (void)
 | 
						||
{
 | 
						||
	return !g_lcd.LcdSwitchEn;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//填充一条线,以窗口的起点为起点,最大填充到窗口的终点位置
 | 
						||
static void LCD_FillLine16(int x,int y, int xe,u16 *buff, int xsize)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	xe += g_lcd.win.xs;
 | 
						||
	if ((y < g_lcd.realwin.ys) || (y > g_lcd.realwin.ye)) return;
 | 
						||
	if ((x + xsize - 1 < g_lcd.realwin.xs) || x > g_lcd.realwin.xe) return;
 | 
						||
	int mx = x;
 | 
						||
	if (mx < g_lcd.realwin.xs) mx = g_lcd.realwin.xs;
 | 
						||
	buff += mx - x; xsize -= mx - x;
 | 
						||
	//不超过指定范围
 | 
						||
//	if (mx + xsize - 1 > xe) xsize=xe - mx + 1;
 | 
						||
	if (xsize>g_lcd.realwin.xe-mx+1) xsize=g_lcd.realwin.xe-mx+1;
 | 
						||
	for (int i = 0; i < xsize; i++)
 | 
						||
		g_lcd.draw[mx+y*g_lcd.x_size + i] = (buff[i]);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
//把图像填充到屏幕的活动窗口中,
 | 
						||
//参数xsize,图像的宽度
 | 
						||
//参数ysize,图像的高度
 | 
						||
static void LCD_FillRect16(int xs,int ys,int xe,int ye,u16 *buff, int xsize, int ysize)
 | 
						||
{
 | 
						||
	ys += g_lcd.win.ys;
 | 
						||
	ye += g_lcd.win.ys;
 | 
						||
	xs += g_lcd.win.xs;
 | 
						||
	xe += g_lcd.win.xs;
 | 
						||
	
 | 
						||
//	for (int y = ys; y<=ye; y++)
 | 
						||
//	{
 | 
						||
//		LCD_FillLine16( xs,y,xe,buff, xsize);
 | 
						||
//		buff += xsize;
 | 
						||
//	}
 | 
						||
	if(ye<g_lcd.realwin.ys||ys>g_lcd.realwin.ye) return;
 | 
						||
	if(xe<g_lcd.realwin.xs||xs>g_lcd.realwin.xe) return;
 | 
						||
	
 | 
						||
	if(ys<g_lcd.realwin.ys)
 | 
						||
	{
 | 
						||
		buff+=(g_lcd.realwin.ys-ys)*xsize;
 | 
						||
		ysize-=g_lcd.realwin.ys-ys;
 | 
						||
		if(ysize<0) return;
 | 
						||
		ys=g_lcd.realwin.ys;
 | 
						||
	}
 | 
						||
	if(xs<g_lcd.realwin.xs)
 | 
						||
	{
 | 
						||
		buff+=(g_lcd.realwin.xs-xs);
 | 
						||
		xsize-=g_lcd.realwin.xs-xs;
 | 
						||
		if(xsize<0) return;
 | 
						||
		xs=g_lcd.realwin.xs;
 | 
						||
	}
 | 
						||
	
 | 
						||
	int lcd_xsize=xe-xs+1;
 | 
						||
	if (lcd_xsize>xsize) lcd_xsize=xsize;
 | 
						||
	if(ysize>ye-ys+1) ysize=ye-ys+1;
 | 
						||
	if(lcd_xsize>0&&ysize>0)
 | 
						||
		LCD_FillImg(g_lcd.draw,xs,ys,lcd_xsize,ysize,xsize*2,(u8*)buff);
 | 
						||
		//DMA2D_DrawBitmap_RGB565(LCD_GetDrawAddr(),g_lcd_struct.WindowSrcX,g_lcd_struct.WindowSrcY,lcd_xsize,ysize,xsize*2,(u8*)buff);
 | 
						||
} 
 | 
						||
 | 
						||
//把图像偏移之后填充到屏幕的活动窗口中,
 | 
						||
//参数x_s,图像要显示的横向起始坐标
 | 
						||
//参数y_s,图像要显示的纵向起始坐标
 | 
						||
//参数xsize,图像的宽度
 | 
						||
//参数ysize,图像的高度
 | 
						||
static void LCD_FillRectOff16(int xs,int ys,int xe,int ye,u16 *buff, int x_s, int y_s, int xsize, int ysize)
 | 
						||
{
 | 
						||
	//图像偏移
 | 
						||
	int offset = y_s*xsize + x_s;
 | 
						||
	//图像相对屏幕偏移
 | 
						||
	//offset += xs + ys*xsize;
 | 
						||
	LCD_FillRect16(xs,ys,xe,ye,buff + offset, xsize, ysize - y_s);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void LCD_FillRectOff16At(int lcd_xs, int lcd_ys, int lcd_xsize, int lcd_ysize, u16 *buff, int xs, int ys, int xsize, int ysize)
 | 
						||
{
 | 
						||
	//绘图
 | 
						||
	LCD_FillRectOff16(lcd_xs,lcd_ys,lcd_xs+lcd_xsize-1,lcd_ys+lcd_ysize-1,buff, xs, ys, xsize, ysize);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static int LCD_FillImg_ARGB(const void *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits,u32 color_format);
 | 
						||
 | 
						||
 | 
						||
//把图像填充到屏幕的活动窗口中,
 | 
						||
//参数xsize,图像的宽度
 | 
						||
//参数ysize,图像的高度
 | 
						||
static void LCD_FillRectAlpha(int xs,int ys,int xe,int ye,u32 *buff, int xsize, int ysize)
 | 
						||
{
 | 
						||
	ys += g_lcd.win.ys;
 | 
						||
	ye += g_lcd.win.ys;
 | 
						||
	xs += g_lcd.win.xs;
 | 
						||
	xe += g_lcd.win.xs;
 | 
						||
	
 | 
						||
	if(ye<g_lcd.realwin.ys||ys>g_lcd.realwin.ye) return;
 | 
						||
	if(xe<g_lcd.realwin.xs||xs>g_lcd.realwin.xe) return;
 | 
						||
	
 | 
						||
	if(ys<g_lcd.realwin.ys)
 | 
						||
	{
 | 
						||
		buff+=(g_lcd.realwin.ys-ys)*xsize;
 | 
						||
		ysize-=g_lcd.realwin.ys-ys;
 | 
						||
		if(ysize<0) return;
 | 
						||
		ys=g_lcd.realwin.ys;
 | 
						||
	}
 | 
						||
	if(xs<g_lcd.realwin.xs)
 | 
						||
	{
 | 
						||
		buff+=(g_lcd.realwin.xs-xs);
 | 
						||
		xsize-=g_lcd.realwin.xs-xs;
 | 
						||
		if(xsize<0) return;
 | 
						||
		xs=g_lcd.realwin.xs;
 | 
						||
	}
 | 
						||
	
 | 
						||
	int lcd_xsize=xe-xs+1;
 | 
						||
	if (lcd_xsize>xsize) lcd_xsize=xsize;
 | 
						||
	if(ysize>ye-ys+1) ysize=ye-ys+1;
 | 
						||
	if(lcd_xsize>0&&ysize>0)
 | 
						||
		LCD_FillImg_ARGB(g_lcd.draw,xs,ys,lcd_xsize,ysize,xsize*4,(u8*)buff,CM_ARGB8888);
 | 
						||
} 
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static void LCD_FillRectOffAlpha(int xs,int ys,int xe,int ye,u32 *buff, int x_s, int y_s, int xsize, int ysize)
 | 
						||
{
 | 
						||
	//图像偏移
 | 
						||
	int offset = y_s*xsize + x_s;
 | 
						||
	//图像相对屏幕偏移
 | 
						||
	//offset += xs + ys*xsize;
 | 
						||
	LCD_FillRectAlpha(xs,ys,xe,ye,buff + offset, xsize, ysize - y_s);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
void LCD_FillRectOffAtAlpha(int lcd_xs, int lcd_ys, int lcd_xsize, int lcd_ysize, void *buff, int xs, int ys, int xsize, int ysize)
 | 
						||
{
 | 
						||
	//绘图
 | 
						||
	LCD_FillRectOffAlpha(lcd_xs,lcd_ys,lcd_xs+lcd_xsize-1,lcd_ys+lcd_ysize-1,buff, xs, ys, xsize, ysize);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//画点,不会进行安全性检查,调用时要保证要画的点不会超出屏幕
 | 
						||
//参数mode,1,画前景色,0,画背景色
 | 
						||
void LCD_DrawPoint (int x,int y,u32 mode)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	if (x<g_lcd.realwin.xs || x>g_lcd.realwin.xe) return;
 | 
						||
	if (y<g_lcd.realwin.ys || y>g_lcd.realwin.ye) return;
 | 
						||
	if (mode)
 | 
						||
		g_lcd.draw[x + y*g_lcd.x_size] = g_lcd.color;
 | 
						||
} 
 | 
						||
 | 
						||
 | 
						||
//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围
 | 
						||
void LCD_DrawPointSafe (int x,int y,u32 mode)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	if (x<g_lcd.realwin.xs || x>g_lcd.realwin.xe) return;
 | 
						||
	if (y<g_lcd.realwin.ys || y>g_lcd.realwin.ye) return;
 | 
						||
	if (mode)
 | 
						||
		g_lcd.draw[x + y*g_lcd.x_size] = g_lcd.color;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围
 | 
						||
//以指定颜色画点,而不是前景色
 | 
						||
void LCD_DrawPointSafeColor (int x,int y,u16 color)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	if (x<g_lcd.realwin.xs || x>g_lcd.realwin.xe) return;
 | 
						||
	if (y<g_lcd.realwin.ys || y>g_lcd.realwin.ye) return;
 | 
						||
	g_lcd.draw[x + y*g_lcd.x_size] = (color);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//快速ALPHA BLENDING算法.
 | 
						||
//src:源颜色
 | 
						||
//dst:目标颜色
 | 
						||
//alpha:透明程度(0~32)
 | 
						||
//返回值:混合后的颜色.
 | 
						||
static u16 alpha_blend565(u16 src,u16 dst,u8 alpha)
 | 
						||
{
 | 
						||
	u32 src2;
 | 
						||
	u32 dst2;	 
 | 
						||
	//Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB|
 | 
						||
	src2=((src<<16)|src)&0x07E0F81F;
 | 
						||
	dst2=((dst<<16)|dst)&0x07E0F81F;   
 | 
						||
	//Perform blending R:G:B with alpha in range 0..32
 | 
						||
	//Note that the reason that alpha may not exceed 32 is that there are only
 | 
						||
	//5bits of space between each R:G:B value, any higher value will overflow
 | 
						||
	//into the next component and deliver ugly result.
 | 
						||
	dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;
 | 
						||
	return (dst2>>16)|dst2;  
 | 
						||
}  	  
 | 
						||
 | 
						||
 | 
						||
//以指定色透明度画点0~32
 | 
						||
void LCD_DrawPointSafeColorAlpha (int x,int y,u16 color,u8 alpha)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	if (alpha==0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	if (x<g_lcd.realwin.xs || x>g_lcd.realwin.xe) return;
 | 
						||
	if (y<g_lcd.realwin.ys || y>g_lcd.realwin.ye) return;
 | 
						||
 | 
						||
	u32 color_old = g_lcd.draw[x + y*g_lcd.x_size];
 | 
						||
	color_old = (color_old);
 | 
						||
	color = alpha_blend565(color_old, color, alpha);
 | 
						||
	g_lcd.draw[x + y*g_lcd.x_size] = (color);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//填充矩形,已窗口坐标为原点
 | 
						||
void LCD_FillRectByColor (int x,int y,int x_size,int y_size)
 | 
						||
{
 | 
						||
//	for (int i=y;i<y+y_size;i++)
 | 
						||
//	{
 | 
						||
//		for (int j=x;j<x+x_size;j++)
 | 
						||
//		{
 | 
						||
//			LCD_DrawPointSafe (j,i,1);
 | 
						||
//		}
 | 
						||
//	}
 | 
						||
	
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	int xe=x+x_size-1;
 | 
						||
	int ye=y+y_size-1;
 | 
						||
	if (x<g_lcd.realwin.xs) x=g_lcd.realwin.xs;
 | 
						||
	if (y<g_lcd.realwin.ys) y=g_lcd.realwin.ys;
 | 
						||
	if (xe>g_lcd.realwin.xe) xe=g_lcd.realwin.xe;
 | 
						||
	if (ye>g_lcd.realwin.ye) ye=g_lcd.realwin.ye;
 | 
						||
	x_size=xe-x+1;
 | 
						||
	y_size=ye-y+1;
 | 
						||
	
 | 
						||
	if(x_size<0||y_size<0) return ;
 | 
						||
	
 | 
						||
	
 | 
						||
//	LCD_FillImg_ARGB(LCD_GetDrawAddr(),x,y,x_size,y_size, x_size*4,fb,CM_ARGB8888);
 | 
						||
	
 | 
						||
	LCD_FillColor(g_lcd.draw,x,y,x_size,y_size,g_lcd.color);
 | 
						||
}	
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static int LCD_MemSet(const void *pSurf,u16 w,u16 h,u32 color)
 | 
						||
{
 | 
						||
 | 
						||
	DMA2D_DeInit();
 | 
						||
	DMA2D->OPFCCR = DMA2D_ARGB8888;
 | 
						||
 | 
						||
 | 
						||
    DMA2D->CR     = DMA2D_R2M;
 | 
						||
    //DMA2D->OPFCCR = DMA2D_RGB565;
 | 
						||
    DMA2D->OCOLR  = color;
 | 
						||
    DMA2D->OMAR   = (u32)pSurf;
 | 
						||
    DMA2D->OOR    = 0;
 | 
						||
    DMA2D->NLR    = (w<<16)|h;
 | 
						||
 | 
						||
	
 | 
						||
  /* Execute operation */
 | 
						||
  DMA2D->CR     |= DMA2D_CR_START;  
 | 
						||
    
 | 
						||
  while (DMA2D->CR & DMA2D_CR_START) 
 | 
						||
  {
 | 
						||
  }
 | 
						||
 | 
						||
	return 1;
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static int LCD_FillImg_ARGB(const void *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits,u32 color_format)
 | 
						||
{
 | 
						||
 | 
						||
 | 
						||
    DMA2D_DeInit();
 | 
						||
 | 
						||
    DMA2D->OPFCCR = DMA2D_RGB565;
 | 
						||
    DMA2D->BGPFCCR =CM_RGB565;
 | 
						||
 | 
						||
    DMA2D->CR     = DMA2D_M2M_BLEND;
 | 
						||
    DMA2D->OMAR   = (u32)pSurf+(y*LCD_Width+x)*2;
 | 
						||
    DMA2D->OOR    = LCD_Width-w;
 | 
						||
 | 
						||
    DMA2D->NLR    = (w<<16)|h;
 | 
						||
 | 
						||
    DMA2D->BGMAR =DMA2D->OMAR;
 | 
						||
    DMA2D->BGOR  =DMA2D->OOR;
 | 
						||
 | 
						||
    DMA2D->FGPFCCR = NO_MODIF_ALPHA_VALUE|color_format;
 | 
						||
    DMA2D->FGMAR = (u32)bits;
 | 
						||
 | 
						||
    switch(color_format)
 | 
						||
    {
 | 
						||
    	case CM_ARGB4444:
 | 
						||
    		DMA2D->FGOR   = (width_bytes>>1)-w;
 | 
						||
    		break;
 | 
						||
    	case CM_ARGB8888:
 | 
						||
    		DMA2D->FGOR   = (width_bytes>>2)-w;
 | 
						||
    		break;
 | 
						||
    	default:
 | 
						||
    		return 0;
 | 
						||
    }
 | 
						||
 | 
						||
    ////
 | 
						||
 | 
						||
  /* Execute operation */
 | 
						||
  DMA2D->CR     |= DMA2D_CR_START;  
 | 
						||
    
 | 
						||
  while (DMA2D->CR & DMA2D_CR_START) 
 | 
						||
  {
 | 
						||
  }
 | 
						||
	return 1;
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//以透明度填充矩形,已窗口坐标为原点
 | 
						||
void LCD_FillRectByColorAlpha (int x,int y,int x_size,int y_size,u8 alpha)
 | 
						||
{
 | 
						||
//	for (int i=y;i<y+y_size;i++)
 | 
						||
//	{
 | 
						||
//		for (int j=x;j<x+x_size;j++)
 | 
						||
//		{
 | 
						||
//			LCD_DrawPointSafeColorAlpha (j,i,g_lcd.color,alpha);
 | 
						||
//		}
 | 
						||
//	}
 | 
						||
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	int xe=x+x_size-1;
 | 
						||
	int ye=y+y_size-1;
 | 
						||
	if (x<g_lcd.realwin.xs) x=g_lcd.realwin.xs;
 | 
						||
	if (y<g_lcd.realwin.ys) y=g_lcd.realwin.ys;
 | 
						||
	if (xe>g_lcd.realwin.xe) xe=g_lcd.realwin.xe;
 | 
						||
	if (ye>g_lcd.realwin.ye) ye=g_lcd.realwin.ye;
 | 
						||
	x_size=xe-x+1;
 | 
						||
	y_size=ye-y+1;
 | 
						||
	
 | 
						||
	if(x_size<0||y_size<0) return ;
 | 
						||
	
 | 
						||
	u8 *fb=mymalloc(x_size*y_size*4);
 | 
						||
	LCD_MemSet(fb,x_size,y_size,COLOR565TO888(g_lcd.color)|(alpha<<(24+3)));
 | 
						||
	
 | 
						||
	
 | 
						||
	LCD_FillImg_ARGB(LCD_GetDrawAddr(),x,y,x_size,y_size, x_size*4,fb,CM_ARGB8888);
 | 
						||
	
 | 
						||
	myfree(fb);
 | 
						||
}	
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//求矩形在屏幕中的显示区域
 | 
						||
static int LCD_RectIntersection(LCD_WindowStruct *out,int x,int y,int xsize,int ysize)
 | 
						||
{
 | 
						||
	//取得新矩形的左上角
 | 
						||
	int x_s = g_lcd.realwin.xs;
 | 
						||
	int y_s = g_lcd.realwin.ys;
 | 
						||
	if (x_s<x)
 | 
						||
		x_s = x;
 | 
						||
	if (y_s<y)
 | 
						||
		y_s = y;
 | 
						||
 | 
						||
	//取得新矩形的右下角
 | 
						||
	int x_e = g_lcd.realwin.xe;
 | 
						||
	int y_e = g_lcd.realwin.ye;
 | 
						||
	if (x_e>x + xsize - 1)
 | 
						||
		x_e = x + xsize - 1;
 | 
						||
	if (y_e>y + ysize - 1)
 | 
						||
		y_e = y + ysize - 1;
 | 
						||
	out->xs = x_s;
 | 
						||
	out->ys = y_s;
 | 
						||
	out->xe = x_e;
 | 
						||
	out->ye = y_e;
 | 
						||
 | 
						||
	if ((y_e >= y_s) && (x_e >= x_s))
 | 
						||
	{
 | 
						||
		return 1;
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
		return 0;
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//清除矩形内的显示
 | 
						||
void LCD_ClearRect(int x, int y, int xsize, int ysize)
 | 
						||
{
 | 
						||
	if (g_lcd.effective == 0) return;
 | 
						||
	x += g_lcd.win.xs;
 | 
						||
	y += g_lcd.win.ys;
 | 
						||
	LCD_WindowStruct out = { 0 };
 | 
						||
//	if (LCD_RectIntersection(&out, x, y, xsize, ysize))
 | 
						||
//	{
 | 
						||
//		for (int my = out.ys; my <= out.ye; my++)
 | 
						||
//		{
 | 
						||
//			for (int mx = out.xs; mx <= out.xe; mx++)
 | 
						||
//			{
 | 
						||
//				g_lcd.draw[mx + my*g_lcd.x_size] = g_lcd.bkColor;
 | 
						||
//			}
 | 
						||
//		}
 | 
						||
//	}
 | 
						||
	if (LCD_RectIntersection(&out, x, y, xsize, ysize))
 | 
						||
	{
 | 
						||
		LCD_FillColor(g_lcd.draw,out.xs,out.ys,out.xe-out.xs+1,out.ye-out.ys+1,g_lcd.bkColor);
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//获取指定矩形空间的屏幕颜色,屏幕的绝对坐标
 | 
						||
void LCD_GetColors (u16 *buff,int x_s,int y_s,int x_size,int y_size)
 | 
						||
{
 | 
						||
	u16 *addr=g_lcd.draw; 
 | 
						||
	if (x_s<0) x_s=0;
 | 
						||
	else if (x_s>LCD_Width-1) x_s=LCD_Width-1;
 | 
						||
	if (y_s<0) y_s=0;
 | 
						||
	else if (y_s>LCD_Height-1) y_s=LCD_Height-1;
 | 
						||
	if (x_size>LCD_Width-x_s) x_size= LCD_Width-x_s;
 | 
						||
	else if (x_size<0) x_size=0;
 | 
						||
	if (y_size>LCD_Height-y_s) y_size= LCD_Height-y_s;
 | 
						||
	else if (y_size<0) y_size=0;
 | 
						||
	for (int y=y_s;y<y_size+y_s;y++)
 | 
						||
	{
 | 
						||
		for (int x=x_s;x<x_size+x_s;x++)
 | 
						||
		{
 | 
						||
			u32 temp=addr[(y*LCD_Width+x)];
 | 
						||
			//*buff=COLOR888TO565(temp);
 | 
						||
			*buff=temp;
 | 
						||
			buff++;
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 |