📄 lpc32xx_lcd.cpp
字号:
// green not swapped
if (LCDPanelList[PanelType].bits_per_pixel == 16) {
tmp = CLCDC_LCDCTRL_BPP16_565;
}
else
{
tmp = CLCDC_LCDCTRL_BPP24;
}
pLCDRegs->lcdctrl = (tmp | CLCDC_LCDCTRL_RGB | CLCDC_LCDCTRL_TFT);
// Setup up display mode related constants
m_nScreenWidth = LCDPanelList[PanelType].pixels_per_line;
m_nScreenHeight = LCDPanelList[PanelType].lines_per_panel;
m_colorDepth = LCDPanelList[PanelType].bits_per_pixel;
m_cbScanLineLength = LCDPanelList[PanelType].pixels_per_line * bsize;
m_FrameBufferSize = m_nScreenHeight * m_cbScanLineLength;
// Allocate virtual memory for frame buffer
m_VirtualFrameBuffer = (DWORD) VirtualAlloc(NULL, m_FrameBufferSize,
MEM_RESERVE, (PAGE_READWRITE | PAGE_NOCACHE));
if (!m_VirtualFrameBuffer)
{
RETAILMSG(1, (TEXT("m_VirtualFrameBuffer is not allocated\n\r")));
return;
}
// Setup frame buffer
phya = IMAGE_WINCE_LCD_BUFFERS_PA;
if ((UseIRAM == 1) && (m_FrameBufferSize <= (256 * 1024)))
{
phya = DEVICE_IRAM_PA;
RETAILMSG(1, (TEXT("Using IRAM for LCD buffer\n\r")));
}
if (!VirtualCopy((PVOID)m_VirtualFrameBuffer, (PVOID) (phya >> 8),
m_FrameBufferSize, (PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)))
{
RETAILMSG(1, (TEXT("m_VirtualFrameBuffer is not mapped\n\r")));
VirtualFree((PVOID)m_VirtualFrameBuffer, 0, MEM_RELEASE);
return;
}
// Enable LCD
pLCDRegs->lcdupbase = phya;
pLCDRegs->lcdctrl |= (CLCDC_LCDCTRL_ENABLE | CLCDC_LCDCTRL_PWR);
// Enable LCD and backlight power
pa.QuadPart = GPIO_BASE;
pGPIOREGs = (GPIO_REGS_T *) MmMapIoSpace(pa, sizeof (GPIO_REGS_T), FALSE);
pGPIOREGs->pio_outp_set = _BIT(0);
#if BSP_BOARD_PHY3250_QVGA_LCD1307 > 0
pGPIOREGs->pio_outp_set = _BIT(4);
#else
pGPIOREGs->pio_outp_clr = _BIT(4);
#endif
MmUnmapIoSpace((PVOID) pGPIOREGs, 0);
DEBUGMSG(1, (TEXT("m_VirtualFrameBuffer is mapped at %x(PHY : %x)\n\r"),
m_VirtualFrameBuffer, phya));
#endif
}
//------------------------------------------------------------------------------
//
// Constructor
//
LPC32XXLCD::LPC32XXLCD()
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("LPC32XXLCD::LPC32XXLCD\r\n")));
// Initialize hardware
lpc32xx_hw_init();
// setup ModeInfo structure
m_gpeMode.modeId = 0;
m_gpeMode.width = m_nScreenWidth;
m_gpeMode.height = m_nScreenHeight;
if (LCDPanelList[PanelType].bits_per_pixel == 16) {
m_gpeMode.format = gpe16Bpp;
}
else
{
m_gpeMode.format = gpe24Bpp;
}
m_gpeMode.Bpp = m_colorDepth;
m_gpeMode.frequency = 60;
m_pMode = &m_gpeMode;
// Allocate display surface
m_pPrimarySurface = new GPESurf(m_nScreenWidth, m_nScreenHeight,
(void*)(m_VirtualFrameBuffer), m_cbScanLineLength, m_gpeMode.format);
if (m_pPrimarySurface)
{
memset ((void*)m_pPrimarySurface->Buffer(), 0x0, m_FrameBufferSize);
}
m_cursorVisible = FALSE;
m_cursorDisabled = TRUE;
m_cursorForcedOff = FALSE;
memset(&m_cursorRect, 0x0, sizeof(m_cursorRect));
m_cursorStore = NULL;
m_cursorXor = NULL;
m_cursorAnd = NULL;
DEBUGMSG(ZONE_FUNCTION, (TEXT("--LPC32XXLCD::LPC32XXLCD\r\n")));
}
//------------------------------------------------------------------------------
//
// Dectructor
//
LPC32XXLCD::~LPC32XXLCD()
{
delete [] m_cursorStore; m_cursorStore = NULL;
delete [] m_cursorXor; m_cursorXor = NULL;
delete [] m_cursorAnd; m_cursorAnd = NULL;
// lpc32xx_hw_deinit();
}
//------------------------------------------------------------------------------
//
// Method: NumModes
//
// This method returns number of modes supported by display.
//
int LPC32XXLCD::NumModes()
{
DEBUGMSG(ZONE_FUNCTION, (L"+LPC32XXLCD::NumModes()\r\n"));
return 1;
}
//------------------------------------------------------------------------------
//
// Method: GetModeInfo
//
// This method returns mode information for mode number of modes supported
// by display.
//
SCODE LPC32XXLCD::GetModeInfo(GPEMode* pMode, int modeNumber)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("++LPC32XXLCD::GetModeInfo\r\n")));
if (modeNumber != 0)
{
return E_INVALIDARG;
}
*pMode = m_gpeMode;
DEBUGMSG(ZONE_FUNCTION, (TEXT("--LPC32XXLCD::GetModeInfo\r\n")));
return S_OK;
}
//------------------------------------------------------------------------------
//
// Method: SetMode
//
// This method should set display hardware to given mode.
//
SCODE LPC32XXLCD::SetMode(int modeNumber, HPALETTE *pPalette)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("++LPC32XXLCD::SetMode\r\n")));
if (modeNumber != 0)
{
DEBUGMSG(ZONE_WARN, (TEXT("LPC32XXLCD::SetMode Want mode %d, only have mode 0\r\n"),
modeNumber));
return E_INVALIDARG;
}
if (pPalette)
{
*pPalette = EngCreatePalette (PAL_BITFIELDS, 0, NULL,
LCDPanelList[PanelType].m_BitMasks[0], LCDPanelList[PanelType].m_BitMasks[1],
LCDPanelList[PanelType].m_BitMasks[2]);
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("--LPC32XXLCD::SetMode\r\n")));
return S_OK;
}
//------------------------------------------------------------------------------
//
// Method: AllocSurface
//
// This method executes when the driver must allocate storage for surface
// pixels. In our case there isn't video memory which can be used for this
// purpose. In case that video memory is required we should fail call
// otherwise normal memory chunk will be allocated.
//
SCODE LPC32XXLCD::AllocSurface(
GPESurf **ppSurf, int width, int height, EGPEFormat format, int flags
) {
SCODE sc = S_OK;
// There isn't extra video memory, so fail if it is required
if ((flags & GPE_REQUIRE_VIDEO_MEMORY) != 0) {
DEBUGMSG(ZONE_ERROR, (L"LPC32XXLCD::AllocSurface: "
L"Flat display driver can't allocate extra video memory\r\n"
));
*ppSurf = NULL;
sc = E_OUTOFMEMORY;
goto cleanUp;
}
// Allocate surface and check result
*ppSurf = new GPESurf(width, height, format);
if (*ppSurf == NULL || (*ppSurf)->Buffer() == NULL) {
DEBUGMSG(ZONE_ERROR, (L"LPC32XXLCD::AllocSurface: "
L"Failed allocate surface (width: %d, height: %d, format %d\r\n",
width, height, format
));
delete *ppSurf; *ppSurf = NULL;
sc = E_OUTOFMEMORY;
goto cleanUp;
}
cleanUp:
return sc;
}
//------------------------------------------------------------------------------
//
// Method: WrapperEmulatedLine
//
// This function is wrapped around emulated line implementation. It must
// be implemented only if software pointer is used. It switch off/on cursor
// if line cross it.
//
SCODE LPC32XXLCD::WrappedEmulatedLine (GPELineParms *lineParameters)
{
SCODE sc;
RECT bounds;
int N_plus_1;
// If cursor is on check for line overlap
if (m_cursorVisible && !m_cursorDisabled) {
// Calculate the bounding-rect to determine overlap with cursor
if (lineParameters->dN) {
// The line has a diagonal component
N_plus_1 = 2 + (
(lineParameters->cPels * lineParameters->dN)/lineParameters->dM
);
} else {
N_plus_1 = 1;
}
switch (lineParameters->iDir) {
case 0:
bounds.left = lineParameters->xStart;
bounds.top = lineParameters->yStart;
bounds.right = lineParameters->xStart + lineParameters->cPels + 1;
bounds.bottom = bounds.top + N_plus_1;
break;
case 1:
bounds.left = lineParameters->xStart;
bounds.top = lineParameters->yStart;
bounds.bottom = lineParameters->yStart + lineParameters->cPels + 1;
bounds.right = bounds.left + N_plus_1;
break;
case 2:
bounds.right = lineParameters->xStart + 1;
bounds.top = lineParameters->yStart;
bounds.bottom = lineParameters->yStart + lineParameters->cPels + 1;
bounds.left = bounds.right - N_plus_1;
break;
case 3:
bounds.right = lineParameters->xStart + 1;
bounds.top = lineParameters->yStart;
bounds.left = lineParameters->xStart - lineParameters->cPels;
bounds.bottom = bounds.top + N_plus_1;
break;
case 4:
bounds.right = lineParameters->xStart + 1;
bounds.bottom = lineParameters->yStart + 1;
bounds.left = lineParameters->xStart - lineParameters->cPels;
bounds.top = bounds.bottom - N_plus_1;
break;
case 5:
bounds.right = lineParameters->xStart + 1;
bounds.bottom = lineParameters->yStart + 1;
bounds.top = lineParameters->yStart - lineParameters->cPels;
bounds.left = bounds.right - N_plus_1;
break;
case 6:
bounds.left = lineParameters->xStart;
bounds.bottom = lineParameters->yStart + 1;
bounds.top = lineParameters->yStart - lineParameters->cPels;
bounds.right = bounds.left + N_plus_1;
break;
case 7:
bounds.left = lineParameters->xStart;
bounds.bottom = lineParameters->yStart + 1;
bounds.right = lineParameters->xStart + lineParameters->cPels + 1;
bounds.top = bounds.bottom - N_plus_1;
break;
default:
DEBUGMSG(ZONE_WARN, (L"LPC32XXLCD::WrappedEmulatedLine: "
L"Invalid direction: %d\r\n", lineParameters->iDir));
sc = E_INVALIDARG;
goto cleanUp;
}
// If line overlap cursor, turn if off
RECTL cursorRect = m_cursorRect;
RotateRectl (&cursorRect);
if (cursorRect.top < bounds.bottom &&
cursorRect.bottom > bounds.top &&
cursorRect.left < bounds.right &&
cursorRect.right > bounds.left
) {
CursorOff();
m_cursorForcedOff = TRUE;
}
}
// Do emulated line
sc = EmulatedLine(lineParameters);
// If cursor was forced off turn it back on
if (m_cursorForcedOff) {
m_cursorForcedOff = FALSE;
CursorOn();
}
cleanUp:
return sc;
}
//------------------------------------------------------------------------------
//
// Method: Line
//
// This method executes before and after a sequence of line segments,
// which are drawn as a path. It examines the line parameters to determine
// whether the operation can be accelerated. It also places a pointer to
// a function to execute once per line segment into the pLine member
// of the GPELineParms structure.
//
SCODE LPC32XXLCD::Line(GPELineParms *pLineParms, EGPEPhase phase)
{
if (phase == gpeSingle || phase == gpePrepare) {
if ((pLineParms->pDst != m_pPrimarySurface)) {
pLineParms->pLine = &GPE::EmulatedLine;
} else {
pLineParms->pLine =
(SCODE (GPE::*)(struct GPELineParms *))&LPC32XXLCD::WrappedEmulatedLine;
}
}
return S_OK;
}
//------------------------------------------------------------------------------
//
// Method: BltPrepare
//
// This method identifies the appropriate functions needed to perform
// individual blits. This function executes before a sequence of clipped blit
// operations.
//
SCODE LPC32XXLCD::BltPrepare(GPEBltParms *pBltParms)
{
RECTL rect;
LONG swapTmp;
pBltParms->pBlt = &LPC32XXLCD::EmulatedBlt;
// Check if destination overlap with cursor
if (
pBltParms->pDst == m_pPrimarySurface &&
m_cursorVisible && !m_cursorDisabled
) {
if (pBltParms->prclDst != NULL) {
rect = *pBltParms->prclDst; // if so, use it
// There is no guarantee of a well
// ordered rect in blitParamters
// due to flipping and mirroring.
if (rect.top > rect.bottom) {
swapTmp = rect.top;
rect.top = rect.bottom;
rect.bottom = swapTmp;
}
if (rect.left > rect.right) {
swapTmp = rect.left;
rect.left = rect.right;
rect.right = swapTmp;
}
} else {
rect = m_cursorRect;
}
// Turn off cursor if it overlap
if (
m_cursorRect.top <= rect.bottom &&
m_cursorRect.bottom >= rect.top &&
m_cursorRect.left <= rect.right &&
m_cursorRect.right >= rect.left
) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -