STM32f7 DMA2D驱动(包含自己定义的GRAM相关操作)

DMA2D可以加快图像填充,并且支持像素格式转换。

/*************************************************************************************************************
 * 文件名		:	dma2d.c
 * 功能			:	STM32F7 DMA2D驱动
 * 作者			:	[email protected]
 * 创建时间		:	2019-10-29
 * 最后修改时间	:	2019-10-29
 * 详细:			
*************************************************************************************************************/	
#include "dma2d.h"
#include "SYSTEM.H" 


/*************************************************************************************************************************
* 函数			:	void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX,  DMA2D_COLOR_MODE ColorMode, u32 Color)
* 功能			:	DMA2D进行单色填充
* 参数			:	FGRAM_Addr:GRAM地址,通过地址控制开始的X,Y坐标;Width:填充的宽度;Height:填充的高度;OffsetX:通过偏移设置跳过的X坐标;
					ColorMode:颜色模式;Color:颜色值
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-29
* 最后修改时间 	: 	2019-10-30
* 说明			:	用于填充矩形颜色,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX,  DMA2D_COLOR_MODE ColorMode, u32 Color)
{
	SYS_DeviceClockEnable(DEV_DMA2D, TRUE);		//使能DMA2D时钟
	DMA2D->CR = 0;								//先停止DMA2D
	DMA2D->IFCR |= 1<<1;						//清除传输完成标志 
	DMA2D->CR = DMA2D_MODE_REG<<16;	 			//寄存器到存储器模式
	DMA2D->OPFCCR = ColorMode;					//输出颜色格式
	DMA2D->OOR = OffsetX;						//输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
	DMA2D->OMAR = FGRAM_Addr;					//目的地址
	DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0);		//设置每行像素与行数
	DMA2D->OCOLR = Color;						//输出颜色

	DMA2D_Start();								//开始传输
}



/*************************************************************************************************************************
* 函数			:	void DMA2D_WaitTransferComplete(u32 TimeOutMs)
* 功能			:	等待DMA2D传输完成
* 参数			:	TimeOutMs:超时时间
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	超时后会取消传输
*************************************************************************************************************************/
void DMA2D_WaitTransferComplete(u32 TimeOutMs)
{
	u32 timeout = 0;
	
	while((DMA2D->ISR & (1<<1)) == 0)	//等待传输完成
	{
		timeout++;
		SYS_DelayMS(1);					//延时1ms
		if(timeout > TimeOutMs)
		{
			DMA2D_Abort();				//终止传输
			break;						//超时退出
		}
	}  
	DMA2D->IFCR |= 1<<1;				//清除传输完成标志 	
}

/*************************************************************************************************************************
* 函数			:	void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode)
* 功能			:	DMA2D进行矩形图形填充
* 参数			:	SourceImageAddr:源图像地址(通过地址控制开始的X,Y坐标);DestGRAMAddr:目标GRAM地址(通过地址控制开始的X,Y坐标);
					Width:填充的宽度;Height:填充的高度;SourceImageOffsetX:源图像X偏移(通过偏移设置跳过的X坐标);DestGRAMOffsetX:目标GRAM X偏移(通过偏移设置跳过的X坐标);
					ColorMode:颜色模式
* 返回			:	是否设置成功
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-28
* 最后修改时间 	: 	2019-10-28
* 说明			:	用于填充图形,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode)
{
	SYS_DeviceClockEnable(DEV_DMA2D, TRUE);		//使能DMA2D时钟
	DMA2D->CR = 0;								//先停止DMA2D
	DMA2D->CR = DMA2D_MODE_MEM<<16;			 	//存储器到存储器模式
	DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0);		//设置每行像素与行数
	DMA2D->OPFCCR = ColorMode;					//输出颜色格式
	DMA2D->OMAR = DestGRAMAddr;					//目的地址
	DMA2D->OOR = DestGRAMOffsetX;				//目的GRAM图像行偏移 
	DMA2D->FGPFCCR = ColorMode;					//源图像颜色格式
	DMA2D->FGOR = SourceImageOffsetX;			//输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
	DMA2D->FGMAR = SourceImageAddr;				//源地址
	
	DMA2D_Start();								//开始传输
}


/*************************************************************************************************************************
* 函数			:	void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode, 
						DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
* 功能			:	DMA2D进行矩形图形填充(会执行像素格式转换)
* 参数			:	SourceImageAddr:源图像地址(通过地址控制开始的X,Y坐标);DestGRAMAddr:目标GRAM地址(通过地址控制开始的X,Y坐标);
					Width:填充的宽度;Height:填充的高度;SourceImageOffsetX:源图像X偏移(通过偏移设置跳过的X坐标);DestGRAMOffsetX:目标GRAM X偏移(通过偏移设置跳过的X坐标);
					SourceColorMode:源图像颜色模式;DestColorMode:目标图像颜色模式
					AlphaMode:alpha模式;Alpha:Alpha值;
* 返回			:	是否设置成功
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-28
* 最后修改时间 	: 	2019-10-28
* 说明			:	用于填充图形,不会等待是否传输成功,需要调用DMA2D_WaitTransferComplete()等待传输结束
*************************************************************************************************************************/
void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode, 
	DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
{
	SYS_DeviceClockEnable(DEV_DMA2D, TRUE);		//使能DMA2D时钟
	DMA2D->CR = 0;								//先停止DMA2D
	DMA2D->CR = DMA2D_MODE_MEM_PFC<<16;			//存储器到存储器模式-激活PFC
	DMA2D->NLR = ((u32)(Width&0x3FFF)<<16) | ((u32)(Height&0xFFFF)<<0);		//设置每行像素与行数
	DMA2D->OPFCCR = DestColorMode;				//输出颜色格式
	DMA2D->OMAR = DestGRAMAddr;					//目的地址
	DMA2D->OOR = DestGRAMOffsetX;				//目的GRAM图像行偏移 
	DMA2D->FGPFCCR =((u32)Alpha << 24) |  ((u32)AlphaMode << 16) | SourceColorMode;			//源图像颜色格式
	DMA2D->FGOR = SourceImageOffsetX;			//输出行偏移寄存器-相当于设置X坐标填充间隔,可以实现对一行的部分进行填充
	DMA2D->FGMAR = SourceImageAddr;				//源地址
	
	DMA2D_Start();								//开始传输
}
/*************************************************************************************************************
 * 文件名		:	dma2d.H
 * 功能			:	STM32F7 DMA2D驱动
 * 作者			:	[email protected]
 * 创建时间		:	2019-10-29
 * 最后修改时间	:	2019-10-29
 * 详细:			
*************************************************************************************************************/	
#ifndef __DMA2D_H_
#define	__DMA2D_H_	   
#include "system.h"


typedef enum
{
	DMA2D_MODE_MEM		= 	0,		//存储器到存储器(仅限 FG前景色 获取)
	DMA2D_MODE_MEM_PFC	=	1,		//存储器到存储器并执行 PFC(仅限 FG PFC 激活时的 FG 获取)
	DMA2D_MODE_MEM_MIXED=	2,		//存储器到存储器并执行混合(执行 PFC 和混合时的 FG 和 BG 获取)
	DMA2D_MODE_REG		=	3,		//寄存器到存储器(无 FG 和 BG,仅输出阶段激活)
}DMA2D_MODE;

//颜色模式
typedef enum
{
	DMA2D_COLOR_ARGB8888 	= 0,
	DMA2D_COLOR_RGB888 		= 1,
	DMA2D_COLOR_RGB565 		= 2,
	/*DMA2D_COLOR_ARGB1555 	= 3,
	DMA2D_COLOR_ARGB4444 	= 4,
	DMA2D_COLOR_L8 			= 5,	//8 位 Luminance
	DMA2D_COLOR_AL44 		= 6,	//4 位 Alpha,4 位 Luminance
	DMA2D_COLOR_AL88 		= 7,	//8 位 Alpha,8 位 Luminance
	DMA2D_COLOR_L4 			= 8,	//4 位 Luminance
	DMA2D_COLOR_A8 			= 9,	//8 位 Alpha
	DMA2D_COLOR_A4 			= 10,	//4 位 Alpha*/
}DMA2D_COLOR_MODE;


//Alpha 模式
typedef enum
{
	DMA2D_ALPHA_NULL	=	0,//不修改前景层图像的 alpha 通道值
	DMA2D_ALPHA_REPLACE	=	1,//原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0]
	DMA2D_ALPHA_PRODUCT	=	2,//原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0] 与原始 alpha 通道值的乘积
}DMA2D_ALPHA_MODE;


__inline void DMA2D_Abort(void) {DMA2D->CR |= BIT2;}		//终止传输
__inline void DMA2D_Suspend(void) {DMA2D->CR |= BIT1;}		//挂起传输
__inline void DMA2D_Start(void) {DMA2D->CR |= BIT0;}		//开始传输

void DMA2D_FillColorToFGRAM(u32 FGRAM_Addr,u16 Width, u16 Height,u16 OffsetX,  DMA2D_COLOR_MODE ColorMode, u32 Color);	//DMA2D进行单色填充
void DMA2D_WaitTransferComplete(u32 TimeOutMs);																			//等待DMA2D传输完成
void DMA2D_FillImageToFGRAM(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE ColorMode);//DMA2D进行矩形图形填充
void DMA2D_FillImageToFGRAM_PFC(u32 SourceImageAddr, u32 DestGRAMAddr,u16 Width, u16 Height,u16 SourceImageOffsetX, u16 DestGRAMOffsetX, DMA2D_COLOR_MODE SourceColorMode, 
	DMA2D_COLOR_MODE DestColorMode, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha);//DMA2D进行矩形图形填充(会执行像素格式转换)
#endif //__DMA2D_H_
/*************************************************************************************************************
 * 文件名		:	DMA2D_GRAM.c
 * 功能			:	GRAM相关操作
 * 作者			:	[email protected]
 * 创建时间		:	2019-10-30
 * 最后修改时间	:	2019-10-30
 * 详细:			显存相关操作接口
*************************************************************************************************************/	
#include "dma2d.h"
#include "DMA2D_GRAM.h"
#include "SYSTEM.H" 

//基本接口
void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color);	//32bit色彩GRAM显存画点
void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color);	//24bit色彩GRAM显存画点
void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color);	//16bit色彩GRAM显存画点


//GRAM相关接口-16bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_16bit = 
{
	(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_16bit,			//GRAM显存画点(RGB565格式)
	(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill,				//GRAM矩形填充
	(void(*)(void *,u32))GRAM_Clear,							//GRAM清屏(使用DMA)
};

//GRAM相关接口-24bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_24bit = 
{
	(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_24bit,			//GRAM显存画点(RGB888格式)
	(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill,				//GRAM矩形填充
	(void(*)(void *,u32))GRAM_Clear,							//GRAM清屏(使用DMA)
};

//GRAM相关接口-32bit
const GDI_BasicInterface cg_GDI_GRAM_Interface_32bit = 
{
	(void(*)(void *,u16,u16,u32))GRAM_DrawPoint_32bit,			//GRAM显存画点(ARGB8888格式)
	(void(*)(void *,u16,u16,u16,u16,u32))GRAM_Fill,				//GRAM矩形填充
	(void(*)(void *,u32))GRAM_Clear,							//GRAM清屏(使用DMA)
};

/*************************************************************************************************************************
* 函数			:	void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
* 功能			:	GRAM句柄初始化(不会申请内存)
* 参数			:	pHandle:GRAM句柄;GRAM_Addr:GRAM内存;Width:显存宽度;Height:显存高度;ColorMode:颜色模式
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	初始化显存
*************************************************************************************************************************/
void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
{
	while(pHandle == NULL)
	{
		DEBUG("无效的句柄pHandle\r\n");
		SYS_DelayMS(500);
	}
	pHandle->GRAM_Addr = GRAM_Addr;					//GRAM地址
	pHandle->Width = Width;							//GRAM宽度
	pHandle->Height = Height;						//GRAM高度
	pHandle->pGRAM_32bit = (u32*)GRAM_Addr;			//32bit颜色模式下显存指针
	pHandle->pGRAM_24bit = (u8*)GRAM_Addr;			//24bit颜色模式下显存指针
	pHandle->pGRAM_16bit = (u16*)GRAM_Addr;			//16bit颜色模式下显存指针
	//像素模式
	switch(ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_32bit;
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_24bit;
		}break;
		default: //DMA2D_COLOR_RGB565
		{
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_16bit;
			ColorMode = DMA2D_COLOR_RGB565;
		}break;
	}
	
	pHandle->ColorMode = ColorMode;					//GRAM显存像素格式
	pHandle->InitStatusId = DMA_INIT_OK;			//初始化成功
}

/*************************************************************************************************************************
* 函数			:	void GRAM_Init(GRAM_HANDLE *pHandle, u16 Width,u16 Height,DMA2D_COLOR_MODE ColorMode)
* 功能			:	创建一个GRAM(会申请内存)
* 参数			:	Width:显存宽度;Height:显存高度;ColorMode:颜色模式
* 返回			:	NULL:失败;其他:GRAM句柄
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2020-02-02
* 最后修改时间 	: 	2020-02-02
* 说明			:	初始化显存
*************************************************************************************************************************/
GRAM_HANDLE *GRAM_Create( u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode)
{
	GRAM_HANDLE *pHandle = NULL;
	u32 GRAM_Addr;
	
	pHandle = (GRAM_HANDLE *)GRAM_malloc(sizeof(GRAM_HANDLE));	//为句柄申请内存
	while(pHandle == NULL)
	{
		DEBUG("无效的句柄pHandle\r\n");
		SYS_DelayMS(500);
	}
	
	switch(ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			GRAM_Addr = (u32)GRAM_malloc(sizeof(u32) * Width * Height);//为显存分配内存
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_32bit;
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			GRAM_Addr = (u32)GRAM_malloc(3 * Width * Height);			//为显存分配内存
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_24bit;
		}break;
		default: //DMA2D_COLOR_RGB565
		{
			GRAM_Addr = (u32)GRAM_malloc(sizeof(u16) * Width * Height);	//为显存分配内存
			pHandle->pBasicInterface = &cg_GDI_GRAM_Interface_16bit;
			ColorMode = DMA2D_COLOR_RGB565;
		}break;
	}
	
	while(GRAM_Addr == NULL)
	{
		DEBUG("显存申请内存失败\r\n");
		SYS_DelayMS(500);
	}
	
	pHandle->GRAM_Addr = GRAM_Addr;					//GRAM地址
	pHandle->ColorMode = ColorMode;					//GRAM显存像素格式
	pHandle->Width = Width;							//GRAM宽度
	pHandle->Height = Height;						//GRAM高度
	pHandle->pGRAM_32bit = (u32*)GRAM_Addr;			//32bit颜色模式下显存指针
	pHandle->pGRAM_24bit = (u8*)GRAM_Addr;			//24bit颜色模式下显存指针
	pHandle->pGRAM_16bit = (u16*)GRAM_Addr;			//16bit颜色模式下显存指针
	pHandle->InitStatusId = DMA_CREATE_OK;			//创建成功
	
	return pHandle;
}



/*************************************************************************************************************************
* 函数			:	void GRAM_Delete(GRAM_HANDLE *pHandle)
* 功能			:	删除一个GRAM(会释放内存)
* 参数			:	pHandle:GRAM句柄
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-12-16
* 最后修改时间 	: 	2019-12-16
* 说明			:	用于删除显存,释放内存
*************************************************************************************************************************/
void GRAM_Delete(GRAM_HANDLE *pHandle)
{
	if(pHandle!=NULL && pHandle->InitStatusId == DMA_CREATE_OK)
	{
		if(pHandle->GRAM_Addr != NULL)
		{
			GRAM_free((u8 *)pHandle->GRAM_Addr);		//释放显存内存
			pHandle->GRAM_Addr = NULL;
		}
		pHandle->InitStatusId = 0;
		GRAM_free(pHandle);								//释放句柄内存
		pHandle = NULL;
	}
}


/*************************************************************************************************************************
* 函数			:	void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能			:	32bit色彩GRAM显存画点
* 参数			:	pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_32bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
	pHandle->pGRAM_32bit[(u32)Ypos * pHandle->Width + Xpos] = Color;
}


/*************************************************************************************************************************
* 函数			:	void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能			:	24bit色彩GRAM显存画点
* 参数			:	pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_24bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
	memcpy(&pHandle->pGRAM_24bit[((u32)Ypos * pHandle->Width + Xpos)*3], &Color, 3);
}


/*************************************************************************************************************************
* 函数			:	void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能			:	16bit色彩GRAM显存画点
* 参数			:	pHandle:GRAM句柄,Xpos,Ypos:X,Y坐标;Color:颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	在显存中绘制点
*************************************************************************************************************************/
void GRAM_DrawPoint_16bit(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{
	pHandle->pGRAM_16bit[(u32)Ypos * pHandle->Width + Xpos] = Color;
}



/*************************************************************************************************************************
* 函数			:	void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color)	
* 功能			:	GRAM矩形填充(使用DMA2D)
* 参数			:	pHandle:GRAM句柄;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	采用DMA2D实现
*************************************************************************************************************************/
void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color)
{
	switch(pHandle->ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_32bit[(u32)sy * pHandle->Width + sx], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_ARGB8888, color);		//DMA2D进行单色填充
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_24bit[((u32)sy * pHandle->Width + sx)*3], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_RGB888, color);	//DMA2D进行单色填充
		}break;
		case DMA2D_COLOR_RGB565 :
		{
			DMA2D_FillColorToFGRAM((u32)&pHandle->pGRAM_16bit[(u32)sy * pHandle->Width + sx], ex-sx+1, ey-sy+1, pHandle->Width-(ex-sx+1), DMA2D_COLOR_RGB565, color);		//DMA2D进行单色填充
		}break;
		default:return;
	}
	
	DMA2D_WaitTransferComplete(500);																												//等待DMA2D传输完成
}


/*************************************************************************************************************************
* 函数			:	void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color)
* 功能			:	GRAM清屏(使用DMA2D)
* 参数			:	pHandle:GRAM句柄;color:需要填充的颜色
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2019-10-30
* 最后修改时间 	: 	2019-10-30
* 说明			:	采用DMA2D实现
*************************************************************************************************************************/
void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color)
{
	switch(pHandle->ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_ARGB8888, color);	//DMA2D进行单色填充
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_RGB888, color);		//DMA2D进行单色填充
		}break;
		case DMA2D_COLOR_RGB565 :
		{
			DMA2D_FillColorToFGRAM(pHandle->GRAM_Addr, pHandle->Width, pHandle->Height, 0, DMA2D_COLOR_RGB565, color);		//DMA2D进行单色填充
		}break;
		default:return;
	}
	SYS_DelayMS(5);
	DMA2D_WaitTransferComplete(500);																						//等待DMA2D传输完成
}


/*************************************************************************************************************************
* 函数			:	void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, 
						u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
* 功能			:	GRAM局部拷贝(支持Alpha)
* 参数			:	pDestHandle:目标GRAM句柄;DestSx,DestSy:目标开始坐标;
					pSourceHandle:源GRAM句柄;SourceSx,SourceSy:源开始坐标;Width:宽度;Height:宽度
					AlphaMode:alpha模式;Alpha:Alpha值;
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2020-02-02
* 最后修改时间 	: 	2020-02-02
* 说明			:	不会检查GRAM大小,请确保GRAM
*************************************************************************************************************************/
void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha)
{
	u32 SourceImageAddr;	//源图像地址(通过地址控制开始的X,Y坐标)
	u32 DestGRAMAddr;		//目标GRAM地址(通过地址控制开始的X,Y坐标);
	u32 PixelByteSize;		//像素字节大小
	
	if(pDestHandle == NULL || pDestHandle->GRAM_Addr == NULL)
	{
		DEBUG("无效的句柄,pDestHandle\r\n");
		return;
	}
	if(pSourceHandle == NULL || pSourceHandle->GRAM_Addr == NULL)
	{
		DEBUG("无效的句柄,pSourceHandle\r\n");
		return;
	}
	//源图像地址(通过地址控制开始的X,Y坐标) 计算
	switch(pSourceHandle->ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			PixelByteSize = 4;
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			PixelByteSize = 3;
		}break;
		default: //DMA2D_COLOR_RGB565
		{
			PixelByteSize = 2;
		}break;
	}
	SourceImageAddr = pSourceHandle->GRAM_Addr + (SourceSy * pSourceHandle->Width + SourceSx)*PixelByteSize;	//计算源开始地址
	
	//目标图像地址(通过地址控制开始的X,Y坐标) 计算
	switch(pDestHandle->ColorMode)
	{
		case DMA2D_COLOR_ARGB8888 :
		{
			PixelByteSize = 4;
		}break;
		case DMA2D_COLOR_RGB888 :
		{
			PixelByteSize = 3;
		}break;
		default: //DMA2D_COLOR_RGB565
		{
			PixelByteSize = 2;
		}break;
	}
	DestGRAMAddr = pDestHandle->GRAM_Addr + (DestSy * pDestHandle->Width + DestSx)*PixelByteSize;	//计算目标开始地址
	//进行拷贝
	DMA2D_FillImageToFGRAM_PFC(SourceImageAddr, DestGRAMAddr, Width, Height,pSourceHandle->Width-Width, pDestHandle->Width-Width, pSourceHandle->ColorMode, 
		pDestHandle->ColorMode, AlphaMode, Alpha);													//DMA2D进行矩形图形填充(会执行像素格式转换)
	DMA2D_WaitTransferComplete(200);																//等待DMA2D传输完成
}

/*************************************************************************************************************************
* 函数			:	void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, 
						u16 Height)
* 功能			:	GRAM局部拷贝(不支持Alpha)
* 参数			:	pDestHandle:目标GRAM句柄;DestSx,DestSy:目标开始坐标;
					pSourceHandle:源GRAM句柄;SourceSx,SourceSy:源开始坐标;Width:宽度;Height:宽度
* 返回			:	无
* 依赖			:	底层宏定义
* 作者			:	[email protected]
* 时间			:	2020-02-02
* 最后修改时间 	: 	2020-02-02
* 说明			:	不会检查GRAM大小,请确保GRAM
*************************************************************************************************************************/
void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, u16 SourceSx, u16 SourceSy, u16 Width, u16 Height)
{
	GRAM_LocalCopyAlpha(pDestHandle, DestSx, DestSy, pSourceHandle, SourceSx, SourceSy, Width, Height, DMA2D_ALPHA_NULL, 255);
}

/*************************************************************************************************************
 * 文件名		:	DMA2D_GRAM.h
 * 功能			:	GRAM相关操作
 * 作者			:	[email protected]
 * 创建时间		:	2019-10-30
 * 最后修改时间	:	2019-10-30
 * 详细:			显存相关操作接口
*************************************************************************************************************/	
#ifndef __DMA2D_GRAM_H_
#define	__DMA2D_GRAM_H_	   
#include "system.h"
#include "DMA2D.h"
#include "SYSMalloc.h"

//初始化状态id
#define DMA_INIT_OK		0x1234423	//初始化成功(不可以释放)
#define DMA_CREATE_OK	0x3643423	//创建成功(可以释放)

//颜色模式
typedef DMA2D_COLOR_MODE GRAM_COLOR_MODE;


//基本GDI接口(由于两个结构体不能相互包含,此处将GRAM_HANDLE*使用void*替换,可能会出现变异警告)
typedef struct
{
	void (*pDrawPoint)(void *pHandle, u16 Xpos,u16 Ypos,u32 Color);					//绘点函数
	void (*pFill)(void *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color);			//填充
	void (*pClear)(void *pHandle, u32 color);										//清屏
}GDI_BasicInterface;


//GRAM相关接口-16bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_16bit;
//GRAM相关接口-24bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_24bit;
//GRAM相关接口-32bit
extern const GDI_BasicInterface cg_GDI_GRAM_Interface_32bit;

//所需的内存申请接口
__inline void *GRAM_malloc(u32 size)
{
	return mymalloc(SRAMEX, size);			//内存分配(外部调用)-使用外部SRAM
}

//所需的内存释放接口
__inline void GRAM_free(void *ptr)
{
	myfree(SRAMEX, ptr);					//使用外部SRAM
}


//显存句柄
typedef struct
{
	u32 InitStatusId;								//初始化状态id
	u32 GRAM_Addr;									//GRAM地址
	DMA2D_COLOR_MODE ColorMode;						//GRAM显存像素格式
	u16 Width;										//GRAM宽度
	u16 Height;										//GRAM高度
	u32 *pGRAM_32bit;								//32bit颜色模式下显存指针
	u8 *pGRAM_24bit;								//24bit颜色模式下显存指针
	u16 *pGRAM_16bit;								//16bit颜色模式下显存指针
	const GDI_BasicInterface *pBasicInterface;		//底层GDI接口
}GRAM_HANDLE;

void GRAM_Init(GRAM_HANDLE *pHandle, u32 GRAM_Addr, u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode);	//GRAM句柄初始化(不会申请内存)
void GRAM_Delete(GRAM_HANDLE *pHandle);																	//删除一个GRAM(会释放内存)
void GRAM_Fill(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 color);							//GRAM矩形填充(使用DMA2D)
void GRAM_Clear(GRAM_HANDLE *pHandle, u32 color);														//GRAM清屏(使用DMA2D)
GRAM_HANDLE *GRAM_Create( u16 Width, u16 Height, DMA2D_COLOR_MODE ColorMode);							//创建一个GRAM(会申请内存)
void GRAM_LocalCopyAlpha(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, 
	u16 SourceSx, u16 SourceSy, u16 Width, u16 Height, DMA2D_ALPHA_MODE AlphaMode, u8 Alpha);			//GRAM局部拷贝(支持Alpha)
void GRAM_LocalCopy(GRAM_HANDLE *pDestHandle,u16 DestSx, u16 DestSy, GRAM_HANDLE *pSourceHandle, 
	u16 SourceSx, u16 SourceSy, u16 Width, u16 Height);													//GRAM局部拷贝(不支持Alpha)

#endif //__DMA2D_GRAM_H_
/*************************************************************************************************************
 * 文件名		:	GDI.c
 * 功能			:	图形设备接口(Graphics Device Interface)
 * 作者			:	[email protected]
 * 创建时间		:	2019-11-02
 * 最后修改时间	:	2020-02-02
 * 详细			:	STM32F7 图形设备接口
*************************************************************************************************************/
#include "system.h"
#include "DMA2D.h"
#include "stm32f7_ltdc.h"
#include "DMA2D_GRAM.h"
#include "GDI.h"

//显示器Layer1 GRAM定义
const GRAM_HANDLE cg_LTDC_Layer1_GRAM_Handle = 
{
	DMA_INIT_OK,
	(u32) &g_LTDC_BUFF_RGB888[0],	//GRAM地址
	DMA2D_COLOR_ARGB8888,			//GRAM显存像素格式
	LTDC_WIDTH,						//GRAM宽度
	LTDC_HEIGHT,					//GRAM高度
	(u32 *)&g_LTDC_BUFF_RGB888[0],	//32bit颜色模式下显存指针
	(u8 *)&g_LTDC_BUFF_RGB888[0],	//24bit颜色模式下显存指针
	(u16 *)&g_LTDC_BUFF_RGB888[0],	//16bit颜色模式下显存指针
	&cg_GDI_GRAM_Interface_32bit,
	
};

//显示器Layer2 GRAM定义
const GRAM_HANDLE cg_LTDC_Layer2_GRAM_Handle = 
{
	DMA_INIT_OK,
	(u32) &g_LTDC_BUFF_RGB888[1],	//GRAM地址
	DMA2D_COLOR_ARGB8888,			//GRAM显存像素格式
	LTDC_WIDTH,						//GRAM宽度
	LTDC_HEIGHT,					//GRAM高度
	(u32 *)&g_LTDC_BUFF_RGB888[1],	//32bit颜色模式下显存指针
	(u8 *)&g_LTDC_BUFF_RGB888[1],	//24bit颜色模式下显存指针
	(u16 *)&g_LTDC_BUFF_RGB888[1],	//16bit颜色模式下显存指针
	&cg_GDI_GRAM_Interface_32bit,
};


/*************************************************************************************************************************
* 函数			:	void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color)
* 功能			:	绘制空心圆
* 参数			:	pHandle:GRAM句柄;Xpos,Ypos:圆心坐标;Radius:半径;Color:颜色
* 返回			:	无
* 依赖			:	画点函数
* 作者			:	[email protected]
* 时间			:	2011-09-20
* 最后修改时间 	: 	2019-11-02
* 说明			: 	无
*************************************************************************************************************************/
void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color)
{
	int a = 0,b = Radius;
	int di;
	di = 3 -(Radius << 1);           //判断下个点位置的标志

#if(GDI_PARAMETER_CHECK)			//参数检查
	while(pHandle==NULL)
	{
		DEBUG("无效的句柄 pHandle\r\n");
		SYS_DelayMS(1000);
	}	
#endif //GDI_PARAMETER_CHECK
	
	while(a <= b)
	{
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos - a,Color);             //3           
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + b,Ypos - a,Color);             //0           
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - a,Ypos + b,Color);             //1       
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos - a,Color);             //7           
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - a,Ypos - b,Color);             //2             
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + b,Ypos + a,Color);             //4               
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + a,Ypos - b,Color);             //5
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos + a,Ypos + b,Color);             //6 
		pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos - b,Ypos + a,Color);             
		a ++;
		//使用Bresenham算法画圆     
		if(di<0)
			di += 4 * a + 6;	  									   
		else
		{
			di += 10 + 4 * (a - b);   
			b --;
		} 									   	
	}										  
}
																	  

/*************************************************************************************************************************
* 函数			:	void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
* 功能			:	绘制直线(可以倾斜)
* 参数			:	pHandle:GRAM句柄;sx,sy:开始坐标;ex,ey:结束坐标;Color:颜色
* 返回			:	无
* 依赖			:	画点函数
* 作者			:	[email protected]
* 时间			:	2011-09-20
* 最后修改时间 	: 	2019-11-02
* 说明			: 	无
*************************************************************************************************************************/
void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
{
	u16 t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol;
	
#if(GDI_PARAMETER_CHECK)			//参数检查
	while(pHandle==NULL)
	{
		DEBUG("无效的句柄 pHandle\r\n");
		SYS_DelayMS(1000);
	}	
#endif //GDI_PARAMETER_CHECK	
	
	delta_x=ex-sx; //计算坐标增量 
	delta_y=ey-sy; 
	uRow=sx; 
	uCol=sy; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 
	for(t=0;t<=distance+1;t++ )//画线输出 
	{  
		pHandle->pBasicInterface->pDrawPoint(pHandle, uRow, uCol,Color);//画点 
		xerr+=delta_x ; 
		yerr+=delta_y ; 												
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}  
}


/*************************************************************************************************************************
* 函数			:	void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color)
* 功能			:	在指定位置画一个矩形
* 参数			:	pHandle:GRAM句柄;sx,sy:左上角坐标;ex,ey:右下角坐标;Color:颜色
* 返回			:	无
* 依赖			:	画线函数
* 作者			:	[email protected]
* 时间			:	2011-09-20
* 最后修改时间 	: 	2019-11-02
* 说明			: 	无
*************************************************************************************************************************/
void GDI_DrawRectangle(GRAM_HANDLE *pHandle, u16 sx, u16 sy, u16 ex, u16 ey,u16 Color)
{
	
#if(GDI_PARAMETER_CHECK)			//参数检查
	while(pHandle==NULL)
	{
		DEBUG("无效的句柄 pHandle\r\n");
		SYS_DelayMS(1000);
	}	
#endif //GDI_PARAMETER_CHECK
	
	GDI_DrawLine(pHandle, sx, sy, ex, sy, Color);
	GDI_DrawLine(pHandle, sx, sy, sx, ey, Color);
	GDI_DrawLine(pHandle, sx, ey, ex, ey, Color);
	GDI_DrawLine(pHandle, ex, sy, ex, ey, Color);
}								  	 


/*************************************************************************************************************************
* 函数			:	void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
* 功能			:	画一个2*2的大点
* 参数			:	pHandle:GRAM句柄;Xpos,Ypos:坐标;Color:颜色
* 返回			:	无
* 依赖			:	画点函数
* 作者			:	[email protected]
* 时间			:	2011-09-20
* 最后修改时间 	: 	2019-11-02
* 说明			: 	无
*************************************************************************************************************************/
void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{	
#if(GDI_PARAMETER_CHECK)			//参数检查
	while(pHandle==NULL)
	{
		DEBUG("无效的句柄 pHandle\r\n");
		SYS_DelayMS(1000);
	}	
#endif //GDI_PARAMETER_CHECK
	
	pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos, Color);		//中心点 
	pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos+1, Ypos, Color);
	pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos+1, Color);
	pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos+1, Ypos+1, Color);	 	  	
}	

/*************************************************************************************************************
 * 文件名		:	GDI.h
 * 功能			:	图形设备接口(Graphics Device Interface)
 * 作者			:	[email protected]
 * 创建时间		:	2019-11-02
 * 最后修改时间	:	2020-02-02
 * 详细			:	STM32F7 图形设备接口
*************************************************************************************************************/
#ifndef _GDI_H_
#define _GDI_H_
#include "system.h"
#include "DMA2D_GRAM.h"

#define GDI_PARAMETER_CHECK		1	//参数检查-主要检查指针
#define GDI_DEBUG				1	//调试输出

#if GDI_DEBUG
	#define GDI_debug(format,...)	uart_printf(format,##__VA_ARGS__)
#else
	#define GDI_debug(format,...)	/\
/
#endif	//GDI_DEBUG



extern const GRAM_HANDLE cg_LTDC_Layer1_GRAM_Handle;	//显示器Layer1 GRAM定义
extern const GRAM_HANDLE cg_LTDC_Layer2_GRAM_Handle; 	//显示器Layer2 GRAM定义
	
#define LTDC_Layer1_GRAM_HANDLE		((GRAM_HANDLE*) &cg_LTDC_Layer1_GRAM_Handle)	//显示器GRAM 1
#define LTDC_Layer2_GRAM_HANDLE		((GRAM_HANDLE*) &cg_LTDC_Layer2_GRAM_Handle)	//显示器GRAM 2

//GDI相关API
__inline void GDI_DrawPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color)
{	
	pHandle->pBasicInterface->pDrawPoint(pHandle, Xpos, Ypos, Color);						//画点 
}	
void GDI_DrawCircle(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u16 Radius, u32 Color);			//绘制空心圆
void GDI_DrawLine(GRAM_HANDLE *pHandle, u16 sx, u16 sy,u16 ex,u16 ey,u32 Color);			//绘制直线(可以倾斜)
void GDI_DrawRectangle(GRAM_HANDLE *pHandle, u16 sx, u16 sy, u16 ex, u16 ey,u16 Color);		//在指定位置画一个矩形
void GDI_DrawBigPoint(GRAM_HANDLE *pHandle, u16 Xpos,u16 Ypos,u32 Color);					//画一个2*2的大点


#endif /*_GDI_H_*/

测试代码,使用的FATFS,读取一个事先准备的图片bin文件,RGB565格式。

FIL *pFile;
		FILE_ERROR mError;
		GRAM_HANDLE *pGramHandle;
		
		pGramHandle = GRAM_Create(320, 240, DMA2D_COLOR_RGB565);	//创建一个GRAM(会申请内存),分辨率320*240,像素格式RGB565
		if(pGramHandle != NULL)
		{
			GRAM_Clear(pGramHandle, 0xff00);						//清除显存,防止读取失败了还是现实上一次的图片
			uart_printf("[OK]GRAM初始化成功\r\n");
			pFile = FILE_Open("0:\\16bit.bin", &mError, FA_READ);
			if(pFile != NULL)
			{
				uart_printf("[OK]打开文件成功\r\n");
				if(FILE_Read(pFile, (u8 *)(pGramHandle->GRAM_Addr), U32_MAX, &mError) == TRUE)//读取文件,将一个事先准备的RGB565的bin图片加载到显存中
				{
					uart_printf("[OK]读取文件成功\r\n");
				}
				else
				{
					uart_printf("读取文件错误:%d\r\n", mError);
				}
			}
			else
			{
				uart_printf("打开文件错误:%d\r\n", mError);
			}
			//将显存拷贝到屏幕中
			GRAM_LocalCopy(LTDC_Layer1_GRAM_HANDLE,(480-320)/2-1, (272-240)/2-1, pGramHandle, 0, 0, 320, 240);			//GRAM局部拷贝
		}

效果图

发布了143 篇原创文章 · 获赞 370 · 访问量 81万+

猜你喜欢

转载自blog.csdn.net/cp1300/article/details/104153594