📄 hw_screen.c
字号:
void Screen_CreatRGB(BACKGRND *Screen, DWDMALLP *LLPList, UINT32 SdramAddr, UINT16 XSize, UINT16 YSize)
{
UINT32 ViewXSize, ViewYSize;
LCDCCONFIG *Config;
Config = &Screen->LCDCConfig;
Screen->OffsetX = 0;
Screen->OffsetY = 0;
Screen->RawXSize = XSize;
Screen->RawYSize = YSize;
Screen->LLPList = LLPList;
Screen->SdramAddr = SdramAddr;
Screen->ScrFormat = (32==IMAGE_BMP_BITCOUNT) ? RGB888 : RGB565;
Screen->ViewXSize = LCDCDev.XSize;
Screen->ViewYSize = LCDCDev.YSize;
ViewXSize = LCDCDev.XSize;
ViewYSize = LCDCDev.YSize;
Config->StartX = 0;
Config->StartY = 0;
Config->ScaleX = 0x200;
Config->ScaleY = 0x200;
if (RGB888==Screen->ScrFormat)
{
Config->LineYAddr[0] = 0x7fe;
Config->LineYAddr[1] = ViewXSize - 2;
if (ViewXSize > 448)
{
Config->LineYAddr[2] = Config->LineYAddr[0];
Config->LineYAddr[3] = Config->LineYAddr[1];
}
else
{
Config->LineYAddr[2] = ViewXSize * 2 - 2;
Config->LineYAddr[3] = ViewXSize * 3 - 2;
}
Config->Rgb565 = 0;
}
else
{
Config->LineYAddr[0] =0;
Config->LineYAddr[1] =ViewXSize/2;
if (ViewXSize>448*2)
{
Config->LineYAddr[2] =Config->LineYAddr[0];
Config->LineYAddr[3] =Config->LineYAddr[1];
}
else
{
Config->LineYAddr[2] =(ViewXSize/2)*2;
Config->LineYAddr[3] =(ViewXSize/2)*3;
}
Config->Rgb565 = 1;
}
Config->LineUVAddr[0] = Config->LineYAddr[0] + 1;
Config->LineUVAddr[1] = Config->LineYAddr[1] + 1;
Config->LineUVAddr[2] = Config->LineYAddr[2] + 1;
Config->LineUVAddr[3] = Config->LineYAddr[3] + 1;
Config->YMIX = 0;
if (Screen_GetType() == MCULCD)
Config->IntrMask = b_INTR_EVENLINE;
else
Config->IntrMask = b_VERT_INTR | b_INTR_EVENLINE;
Screen_CreatLLPRGB(Screen);
}
/*---------------------------------------------------------
Name : Screen_CreatVideo
Dec : 创建视频相关设置参数
Params: Screen -> MIX YUV背景的相关配置参数
LLPList -> LLP链条首地址
SdramAddr-> 数据源首地址
XSize -> 数据源宽度
YSize -> 数据源高度
Mode -> 显示比例模式
Return:
Author: nzy
Date :
-----------------------------------------------------------*/
void Screen_CreatVideo(BACKGRND *Screen, DWDMALLP *LLPList, UINT32 SdramAddr, UINT16 XSize, UINT16 YSize, SCALEMODE Mode)
{
UINT32 Scale, ScaleX, ScaleY, MaxXSize;
LCDCCONFIG *Config;
Config = &Screen->LCDCConfig;
Screen->RawXSize = (XSize + 15) & 0xfff0;
XSize &= 0xfffc;
Screen->RawYSize = YSize;
Screen->LLPList = LLPList;
Screen->SdramAddr = SdramAddr;
Screen->ScrFormat = MIX420;
MaxXSize = ((0x800 - LCDCDev.XSize / 2) * 4 / 9) & 0xfffc;
if (XSize > MaxXSize)
{
XSize = MaxXSize; //限制于720,留出空间以备ALPHA
}
ScaleX = ((UINT32)(XSize - 1) * 0x200) / (LCDCDev.XSize - 1);
ScaleY = ((UINT32)(YSize - 1) * 0x200) / (LCDCDev.YSize - 1);
ScaleX = (ScaleX > 0x3ff) ? 0x3ff : ScaleX;
ScaleY = (ScaleY > 0x3ff) ? 0x3ff : ScaleY;
if (Mode == LineArity)
{
if ((ScaleX > ScaleY) || (XSize == MaxXSize))
ScaleY = ScaleX;
else
ScaleX = ScaleY;
}
else if (Mode == Zoom)
{
if ((ScaleX < ScaleY) || (XSize == MaxXSize))
ScaleY = ScaleX;
else
ScaleX = ScaleY;
}
XSize = ((LCDCDev.XSize * ScaleX + 0x7ff) >> 9) & 0xfffc;//调整实际Xscale所需的X值的大小,填补到最小数值和满足4的倍数
if (XSize > MaxXSize)
{
ScaleX = MaxXSize * 0x200 / LCDCDev.XSize;
XSize = ((LCDCDev.XSize * ScaleX + 0x7ff) >> 9) & 0xfffc;
ScaleY = (Mode == LineArity) ? ScaleX : ScaleY;
}
while ((((ScaleY*(LCDCDev.YSize - 1) >> 10) % 3) == 0x00) && (ScaleY < 0x3ff))
{
ScaleY++; //避免最后一行使用LINE0导致的数据冲突
}
YSize = (LCDCDev.YSize * ScaleY + 0x1ff) >> 9; //调整实际Yscale所需的Y值的大小,填补到最小数值
Screen->ViewXSize = XSize;
Screen->ViewYSize = YSize;
Screen->OffsetX = (Screen->RawXSize > Screen->ViewXSize) ? ((Screen->RawXSize - Screen->ViewXSize) / 2) : 0;
Screen->OffsetY = (Screen->RawYSize > Screen->ViewYSize) ? ((Screen->RawYSize - Screen->ViewYSize) / 2) : 0;
Config->StartX = 0;
Config->StartY = 0;
Config->ScaleX = ScaleX;
Config->ScaleY = ScaleY;
Config->LineYAddr[0] = 0x0 | b_YUV_SRC | b_SCALE_EN;
Config->LineYAddr[1] = XSize * 1 / 2 | b_YUV_SRC | b_SCALE_EN;
Config->LineYAddr[2] = XSize * 2 / 2 | b_YUV_SRC | b_SCALE_EN;
Config->LineYAddr[3] = 0x0 | b_YUV_SRC | b_SCALE_EN;
Config->LineUVAddr[0] = XSize * 3 / 2;
Config->LineUVAddr[1] = XSize * 7 / 4;
Config->LineUVAddr[2] = XSize * 8 / 4;
Config->LineUVAddr[3] = XSize * 3 / 2;
Config->YMIX = 1;
Config->Rgb565 = 0;
if (Screen_GetType() == MCULCD)
Config->IntrMask = b_INTR_PERLINE;
else
Config->IntrMask = b_VERT_INTR | b_INTR_PERLINE;
Screen_CreatLLPMIX(Screen);
}
/*---------------------------------------------------------
Name : Screen_CreatMPEG2
Dec : 创建MPEG2相关设置参数
Params: Screen -> Camera背景的相关配置参数
LLPList -> LLP链条首地址
SdramAddr -> 数据源首地址
XSize -> 数据源宽度
YSize -> 数据源高度
Return:
Author: nzy
Date :
-----------------------------------------------------------*/
void Screen_CreatMPEG2(BACKGRND *Screen, DWDMALLP *LLPList, UINT32 SdramAddr, UINT32 SdramAddrUV, UINT16 XSize, UINT16 YSize, SCALEMODE Mode)
{
UINT32 ScaleX,ScaleY,MaxXSize;
LCDCCONFIG *Config;
Config = &Screen->LCDCConfig;
Screen->RawXSize = (XSize+15)&0xfff0;
Screen->RawYSize = YSize;
MaxXSize = ((0x800-LCDCDev.XSize/2)*4/8)&0xfffc;
if (XSize>MaxXSize)
{
XSize = MaxXSize; //留出空间以备ALPHA
}
ScaleX = (UINT32)(XSize-1)*0x200/(LCDCDev.XSize-1);
ScaleY = (UINT32)(YSize-1)*0x200/(LCDCDev.YSize-1);
ScaleX = (ScaleX>0x3ff) ? 0x3ff : ScaleX;
ScaleY = (ScaleY>0x3ff) ? 0x3ff : ScaleY;
if (Mode==LineArity)
{
if ( (ScaleX > ScaleY) || (XSize==MaxXSize) )
ScaleY = ScaleX;
else
ScaleX = ScaleY;
}
XSize = ((LCDCDev.XSize*ScaleX+0x7ff)>>9) &0xfffc; //调整实际scale所需的X值的大小,填补到最小数值和满足4的倍数
if (XSize >MaxXSize)
{
ScaleX =MaxXSize*0x200/LCDCDev.XSize;
XSize =((LCDCDev.XSize*ScaleX+0x7ff)>>9) &0xfffc;
ScaleY = (Mode == LineArity) ? ScaleX : ScaleY;
}
while ((((ScaleY*(LCDCDev.YSize-1)>>10)&0x03)==0x00)&&(ScaleY<0x3ff))
{
ScaleY++; //避免最后一行使用LINE0导致的数据冲突
}
YSize =(LCDCDev.YSize*ScaleY+0x1ff)>>9; //调整实际scale所需的Y值的大小,填补到最小数值
Screen->OffsetX = (XSize<Screen->RawXSize) ? (Screen->RawXSize-XSize)/2 : 0;
Screen->OffsetY = 0;
if (XSize < Screen->RawXSize) XSize = Screen->RawXSize;
Screen->ViewXSize = XSize;
Screen->ViewYSize = YSize;
Screen->LLPList =LLPList;
Screen->SdramAddr = SdramAddr;
Screen->SdramAddr2 = SdramAddrUV;
Screen->ScrFormat =YUV420;
Config->StartX =0;
Config->StartY =0;
Config->ScaleX =ScaleX;
Config->ScaleY =ScaleY;
Config->YMIX =0;
Config->Rgb565 = 0;
if (Screen_GetType()==MCULCD)
Config->IntrMask =b_INTR_PERLINE;
else
Config->IntrMask =b_VERT_INTR|b_INTR_PERLINE;
Config->LineYAddr[0] = (XSize*0/4) | b_YUV_SRC|b_SCALE_EN;
Config->LineYAddr[1] = (XSize*1/4) | b_YUV_SRC|b_SCALE_EN;
Config->LineYAddr[2] = (XSize*2/4) | b_YUV_SRC|b_SCALE_EN;
Config->LineYAddr[3] = (XSize*3/4) | b_YUV_SRC|b_SCALE_EN;
Config->LineUVAddr[0] = XSize*4/4;
Config->LineUVAddr[1] = XSize*4/4;
Config->LineUVAddr[2] = XSize*5/4;
Config->LineUVAddr[3] = XSize*5/4;
Screen_CreatLLPMPEG2(Screen);
}
/*---------------------------------------------------------
Name : Screen_CreatAlpha
Dec : 创建Alpha相关设置参数
Params: FrontGrnd -> RGB565前景的相关配置参数
LLPList -> LLP链条首地址
SdramAddr -> 数据源首地址
XSize -> 数据源宽度
YSize -> 数据源高度
StartX -> Alpha区域的X方向启始点
TopY -> Alpha区域的Y方向启始点
BottomY -> Alpha区域的Y方向终止点
AlphaLevel-> Alpha参数
Return:
Author: nzy
Date :
-----------------------------------------------------------*/
SCREENRESULT Screen_CreatAlpha(FRONTGRND *FrontGrnd, DWDMALLP *LLPList, UINT32 SdramAddr, UINT16 XSize, UINT16 YSize, UINT16 StartX, UINT16 TopY, UINT16 BottomY, UINT16 AlphaLevel)
{
UINT32 EndX;
UINT32 Width, Height;
if (BottomY < TopY || BottomY > LCDCDev.YSize)
return ScreenError;
StartX = StartX & 0xfff0; //align 16
EndX = ((StartX + XSize) & 0xfff0) - 1; //align 4
if (EndX >= LCDCDev.XSize)
{
EndX = LCDCDev.XSize - 1;
}
BottomY++; //remaind one line for fill dark;
Width = EndX - StartX + 1;
Height = BottomY - TopY + 1;
FrontGrnd->LLPList = LLPList;
FrontGrnd->ScrFormat = RGB565;
FrontGrnd->SdramAddr = SdramAddr;
FrontGrnd->OffsetX = 0x0;
FrontGrnd->OffsetY = 0x0;
FrontGrnd->ViewXSize = Width;
FrontGrnd->ViewYSize = Height;
FrontGrnd->RawXSize = XSize;
FrontGrnd->RawYSize = YSize;
FrontGrnd->AlphaConfig.AlphaLevel = AlphaLevel;
FrontGrnd->AlphaConfig.ALX = StartX;
FrontGrnd->AlphaConfig.ATY = TopY;
FrontGrnd->AlphaConfig.ARX = EndX;
FrontGrnd->AlphaConfig.ABY = BottomY;
FrontGrnd->AlphaConfig.FifoAddr = 0x800 - Width / 2;
FrontGrnd->AlphaConfig.BLX = 0x3ff;
FrontGrnd->AlphaConfig.BTY = 0x3ff;
FrontGrnd->AlphaConfig.BRX = 0x3ff;
FrontGrnd->AlphaConfig.BBY = 0x3ff;
Screen_CreatLLPAlpha(FrontGrnd);
return ScreenOK;
}
/*---------------------------------------------------------
Name : Screen_CreatLLPMIX
Dec : 设置MIX YUV的相关LLP链接
Params: Screen -> MIX YUV背景的相关配置参数
Return:
Author: nzy
Date :
-----------------------------------------------------------*/
void Screen_CreatLLPMIX(BACKGRND *Screen)
{
UINT32 Line, Bufoffset, Lineoffset, ScaleStep;
UINT32 SYWidth, SUVWidth, DYWidth, DUVWidth, Datalen;
UINT32 SourYAddr, SourUVAddr, DestYAddr, DestUVAddr;
UINT32 OffsetX, OffsetY, Temp;
UINT32 VirTolLine = 0, VirLine = 0, ActLine = 0;
DWDMALLP *LLPList;
SYWidth = Screen->RawXSize / 2;
SUVWidth = Screen->RawXSize / 4;
DYWidth = Screen->ViewXSize / 2;
DUVWidth = Screen->ViewXSize / 4;
Datalen = Screen->RawXSize > Screen->ViewXSize ? DUVWidth : SUVWidth;
Bufoffset = Screen->RawXSize > Screen->ViewXSize ? 0 : ((Screen->ViewXSize - Screen->RawXSize) / 2) & 0xfffc;
Lineoffset = Screen->RawYSize > Screen->ViewYSize ? 0 : ((Screen->ViewYSize - Screen->RawYSize) / 2) & 0xfffe;
OffsetX = Screen->OffsetX / 4;
OffsetY = Screen->OffsetY / 2;
SourYAddr = 8 * OffsetX + 4 * SYWidth * OffsetY + Screen->SdramAddr;
SourUVAddr = 4 * OffsetX + 4 * SUVWidth * OffsetY + Screen->SdramAddr + Screen->RawXSize * ((Screen->RawYSize + 15) & 0xfff0);
DestYAddr = (UINT32)RegLCDC_BUF;
DestUVAddr = DestYAddr + 12 * DYWidth;
ScaleStep = Screen->LCDCConfig.ScaleY;
LLPList = Screen->LLPList;
Temp = (Screen_GetType() == TVOUT) ? 3 : 0;
DWDMA_LLPCfg((UINT32)SDRAM_DARK_Y, DestYAddr, LLPList, 3*DYWidth);
DWDMA_LLPCfg((UINT32)SDRAM_DARK_UV, DestUVAddr, LLPList + 1, 3*DUVWidth);
DWDMA_LLPChange(LLPList + 1, LLPList + 6);
LLPList += 2;
for (Line = 0; Line < LCDCDev.YSize; Line++, LLPList += 2)
{
if (Line > 1)
{
//LCD的第一行请求用来发送LCDC的LINE3
VirTolLine += ScaleStep;
VirLine = 4 + (VirTolLine >> 9);
}
//缩放和DWA的协调功能
if ((VirLine / 2) >= ActLine)
{
if ((ActLine < Temp + Lineoffset / 2) || (ActLine >= (Screen->RawYSize + Lineoffset) / 2))
{
//当Y方向上无法满屏显示时,上下填充黑色
DWDMA_LLPCfg((UINT32)SDRAM_DARK_Y, DestYAddr + (ActLine % 3)*4*DYWidth, LLPList, DYWidth);
DWDMA_LLPCfg((UINT32)SDRAM_DARK_UV, DestUVAddr + (ActLine % 3)*4*DUVWidth, LLPList + 1, DUVWidth);
}
else
{
//填充有效的视频数据
DWDMA_LLPCfg(SourYAddr + (ActLine - Temp - Lineoffset / 2)*4*SYWidth, DestYAddr + 2*Bufoffset + ((ActLine - Temp) % 3)*4*DYWidth, LLPList, 2*Datalen);
DWDMA_LLPCfg(SourUVAddr + (ActLine - Temp - Lineoffset / 2)*4*SUVWidth, DestUVAddr + Bufoffset + ((ActLine - Temp) % 3)*4*DUVWidth, LLPList + 1, Datalen);
}
ActLine ++;
}
else
{
//等待LCDC当前行的Buffer数据发送完毕
DWDMA_LLPCfg(SourYAddr, SourYAddr, LLPList, 1);
DWDMA_LLPCfg(SourYAddr, SourYAddr, LLPList + 1, 1);
}
//先发送两行到LCDC buffer
if (Line < 1) VirLine += 2;
}
DWDMA_LLPChange(LLPList - 1, &LCDCDev.LLPTable);//上一屏的LLP的最后位置链接到当前屏的LLP的首位置
if (Screen_GetType() != MCULCD)
{
DWDMA_LLPChange(Screen->LLPList + 5, LLPList);
for (Line = 0; Line < 4; Line++, LLPList++)
DWDMA_LLPCfg(SourYAddr, SourYAddr, LLPList, 1);
DWDMA_LLPChange(LLPList - 1, Screen->LLPList + 6);
}
else
DWDMA_LLPEnd(Screen->LLPList + 3);//传完LCD的前两行后停止LLP链接
}
/*---------------------------------------------------------
Name : Screen_CreatLLPRGB
Dec : 设置RGB888的相关LLP链接
Params: Screen -> RGB888背景的相关配置参数
Return:
Author: nzy
Date :
-----------------------------------------------------------*/
void Screen_CreatLLPRGB(BACKGRND *Screen)
{
UINT32 Line, Bufoffset, Lineoffset;
UINT32 SWidth, DWidth, Datalen, LineFactor;
UINT32 SourRGBAddr, DestRGBAddr;
UINT32 SourAddr, DestAddr;
DWDMALLP *LLPList;
SWidth = Screen->RawXSize;
DWidth = Screen->ViewXSize;
Bufoffset = Screen->RawXSize>Screen->ViewXSize ? 0 : (Screen->ViewXSize -Screen->RawXSize)/2;
Lineoffset = Screen->RawYSize>Screen->ViewYSize ? 0 : (Screen->ViewYSize -Screen->RawYSize)/2;
if (RGB565==Screen->ScrFormat)
{
SWidth = SWidth/2;
DWidth = DWidth/2;
Bufoffset = Bufoffset/2;
Lineoffset = Lineoffset/2;
}
Datalen = Screen->RawXSize > Screen->ViewXSize ? DWidth : SWidth;
SourRGBAddr = Screen->SdramAddr;
DestRGBAddr = (UINT32)RegLCDC_BUF;
LLPList = Screen->LLPList;
LineFactor = (DWidth > 448) ? 2 : 4;
for (Line = 0; Line < LCDCDev.YSize; Line++, LLPList++)
{
if ((Line < Lineoffset) || (Line >= Screen->RawYSize + Lineoffset))
SourAddr = (UINT32)SDRAM_DARK_RGB;//当Y方向上无法满屏显示时,上下填充黑色
else
SourAddr = SourRGBAddr + (Line - Lineoffset) * 4 * SWidth;//填充有效的系统UI数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -