📄 config.cpp
字号:
if (g_dwCursorAreaOffset
< g_dwFrameBufferOffset + g_dwFrameBufferSize) {
// If the top of the cursor area is within the frame buffer,
// the video memory space is not enough.
RETAILMSG(1,
(TEXT("AMADisp: Not enough video memory space.\r\n")));
return FALSE;
}
g_dwDisplayClock = dwDisplayClock;
g_dwCursorBlinkFrames = dwFrameRate / 2; // 0.5s for each pattern
// Linear-tile hardware translation setup
// Like Q2SD, HD64404 GE can render only to the tilemapped screen.
// In HD64404, the hardware translates tilemapped frame buffer to
// linear bitmap screen, so the WinCE GWES can handle it directly.
// Linear-tile translation address
AMADispMode[0].MPXIFRegs[MPXIF_LTAD] =
g_dwVideoMemoryOffset & 0x07F80000;
// Linear-tile translation bit mask, used to extend translation area
AMADispMode[0].MPXIFRegs[MPXIF_LTAM] =
0x07F80000 & (1 + ~g_dwVideoMemorySize); // video memory size
AMADispMode[0].DORegs[DO_DSAR0H ] = // display start address for FB0
(g_dwFrameBufferOffset & 0x03FF0000) >> 16
| (g_dwFrameBufferOffset & 0x04000000) >> 10;
AMADispMode[0].DORegs[DO_DSAR0L ] =
g_dwFrameBufferOffset & 0x0000FC00;
AMADispMode[0].DORegs[DO_DSAR1H ] = // display start address for FB1
(g_dwFrameBufferOffset & 0x03FF0000) >> 16
| (g_dwFrameBufferOffset & 0x04000000) >> 10;
AMADispMode[0].DORegs[DO_DSAR1L ] =
g_dwFrameBufferOffset & 0x0000FC00;
// WSAR requires 32kB alignment. (worst case)
AMADispMode[0].GERegs[GE_WSAR ] = // rendering work start address
(g_dwWorkAreaOffset >> 16) | (g_dwWorkAreaOffset & 0xE000);
// CSARn requires 2kB (32x32) or 8kB (64x64) alignment.
AMADispMode[0].DORegs[DO_CSAR1 ] = // cursor 1 pattern address
(g_dwCursorAreaOffset & 0x04000000) >> 10
| (g_dwCursorAreaOffset & 0x03FF0000) >> 16
| (g_dwCursorAreaOffset & 0x0000F800);
AMADispMode[0].DORegs[DO_CSAR2 ] = // cursor 2 pattern address
((g_dwCursorAreaOffset + CURSOR_BYTES * 2) & 0x04000000) >> 10
| ((g_dwCursorAreaOffset + CURSOR_BYTES * 2) & 0x03FF0000) >> 16
| ((g_dwCursorAreaOffset + CURSOR_BYTES * 2) & 0x0000F800);
// GPEMode parameter setup
// mode id
AMADispMode[0].gpeMode.modeId = 0;
// screen width in pixels
AMADispMode[0].gpeMode.width = dwScreenWidth;
// screen height in lines
AMADispMode[0].gpeMode.height = dwScreenHeight;
// color depth, bit per pixel
AMADispMode[0].gpeMode.Bpp = dwBpp;
// screen refresh rate
AMADispMode[0].gpeMode.frequency = dwFrameRate;
// pixel format in GPE style
AMADispMode[0].gpeMode.format =
dwBpp == 8 ? gpe8Bpp : gpe16Bpp;
return GPEEnableDriver( iEngineVersion, cj, pded, pEngCallbacks );
}
//
// CalcInternalPLLParams
//
// - This function searches applicatable HD64404 display clock PLL parameters
// to get nearest frequency from requested.
BOOL CalcInternalPLLParams(
DWORD dwBaseFreq,
DWORD dwTargetFreq,
DWORD *pdwOutputFreq,
DWORD *pdwDivN,
DWORD *pdwDivA,
DWORD *pdwDivB,
DWORD *pdwDivC,
DWORD *pdwDivP )
{
DWORD dwN; // This is not altered.
DWORD dwA, dwAMin, dwAMax;
DWORD dwB, dwBMin, dwBMax;
DWORD dwC, dwCMin, dwCMax;
DWORD dwP;
DWORD dwSearchStatus; // O means not found, other means found.
DWORD dwCurA, dwCurB, dwCurC, dwCurP;
LONG lErrPermil, lCurErrPermil; // 1 Permil = 1/1000
DWORD dwOscFreq, dwOutputFreq, dwCurOutputFreq;
// This function assumes that each of DivN, DivA, DivB, DivC, and DivP
// parameters are in available range, or REG_NOTSPECIFIED that means the
// corresponding registry key is omitted. Specified parameters are not
// altered while searching available PLL configurations.
// Feedback divider N
if (*pdwDivN == REG_NOTSPECIFIED) dwN = 1;
else dwN = *pdwDivN;
// Input divider A
if (*pdwDivA == REG_NOTSPECIFIED) {
// DivA is not specified. This allows scanning DivA.
dwAMin = 1;
dwAMax = 16;
}
else {
// DivA is specified. DivA is fixed.
dwAMin = *pdwDivA;
dwAMax = *pdwDivA;
}
// Feedback divider B
if (*pdwDivB == REG_NOTSPECIFIED) {
// DivB is not specified. This allows scanning DivB.
dwBMin = 1;
dwBMax = 16;
}
else {
// DivB is specified. DivB is fixed.
dwBMin = *pdwDivB;
dwBMax = *pdwDivB;
}
// Output divider C
if (*pdwDivC == REG_NOTSPECIFIED) {
// DivC is not specified. This allows scanning DivC.
dwCMin = 1;
dwCMax = 4;
}
else {
// DivC is specified. DivC is fixed.
dwCMin = *pdwDivC;
dwCMax = *pdwDivC;
}
dwSearchStatus = 0; // This means available set is not found.
lCurErrPermil = 1000; // Current minimum error, set to enough large.
// Main loop for searching PLL parameters.
for (dwA = dwAMin; dwA <= dwAMax; dwA++) {
for (dwB = dwBMin; dwB <= dwBMax; dwB++) {
for (dwC = dwCMin; dwC <= dwCMax; dwC++) {
// VCO oscillation frequency check
if (*pdwDivP == REG_NOTSPECIFIED) {
// Both 1 and 2 are available for DivP.
dwOscFreq = dwBaseFreq * dwB / dwA;
if (dwOscFreq * 2 > DO_PLL_VCOHIGH) goto NotAvail; // P=1
else if (dwOscFreq * 2 >= DO_PLL_VCOLOW) dwP = 1;
else if (dwOscFreq * 4 >= DO_PLL_VCOLOW) dwP = 2;
else goto NotAvail;
}
else {
// check with specified DivP
dwP = *pdwDivP;
dwOscFreq = dwBaseFreq * dwB / dwA * (1 << dwP);
if (dwOscFreq < DO_PLL_VCOLOW
|| dwOscFreq > DO_PLL_VCOHIGH) goto NotAvail;
}
// Total feedback divisor must be lower or equal 32.
if (dwN * dwB * (1 << dwP) > 32) goto NotAvail;
// Calculate output frequency and error rate.
dwOutputFreq = dwBaseFreq * dwN / dwA * dwB / dwC;
lErrPermil =
((LONG)dwOutputFreq - (LONG)dwTargetFreq)
/ (LONG)(dwTargetFreq / 1000);
// Error rate must be within -3.0% to 3.0%.
if (lErrPermil > 30 || lErrPermil < -30) goto NotAvail;
DEBUGMSG(GPE_ZONE_HW,
(TEXT("A=%d B=%d C=%d DCLK=%d, %d.%d percent error.\r\n"),
dwA, dwB, dwC, dwOutputFreq, lErrPermil / 10,
abs(lErrPermil) - abs(lErrPermil / 10) * 10));
// Store PLL parameters if this set provides lowest error
// or this is the first available set.
if (abs(lErrPermil) < abs(lCurErrPermil)
|| dwSearchStatus == 0) {
dwSearchStatus = 1; // available parameter set is found
dwCurA = dwA;
dwCurB = dwB;
dwCurC = dwC;
dwCurP = dwP;
dwCurOutputFreq = dwOutputFreq;
lCurErrPermil = lErrPermil;
}
NotAvail: ; // Try next combination if the loop have not reached to end.
}
}
}
if (!dwSearchStatus) { // Failed to find parameter set.
RETAILMSG(1,
(TEXT("AMADisp: Failed to find available PLL parameter set.\r\n")));
return FALSE;
}
else { // Available parameter set is found.
DEBUGMSG(1,
(TEXT("AMADisp: Available PLL parameter set is found.\r\n")));
DEBUGMSG(1,
(TEXT("AMADisp: A=%d, B=%d, C=%d, N=%d, P=%d, DisplayClock=%d.\r\n"),
dwCurA, dwCurB, dwCurC, dwN, dwCurP, dwCurOutputFreq));
*pdwOutputFreq = dwCurOutputFreq;
*pdwDivA = dwCurA;
*pdwDivB = dwCurB;
*pdwDivC = dwCurC;
*pdwDivN = dwN;
*pdwDivP = dwCurP;
return TRUE;
}
}
//
// CalcICD2053PLLParams
//
// - This function searches applicatable ICD2053 clock generator PLL
// parameters to get nearest frequency from requested.
BOOL CalcICD2053PLLParams(
DWORD dwBaseFreq,
DWORD dwTargetFreq,
DWORD *pdwOutputFreq,
DWORD *pdwDivP,
DWORD *pdwDivQ,
DWORD *pdwMux )
{
DWORD dwP, dwPMin, dwPMax;
DWORD dwQ, dwQMin, dwQMax;
DWORD dwM, dwMMin, dwMMax;
DWORD dwSearchStatus; // O means not found, other means found.
DWORD dwCurP, dwCurQ, dwCurM;
LONG lErrPermil, lCurErrPermil; // 1 Permil = 1/1000
DWORD dwOscFreq, dwOutputFreq, dwCurOutputFreq;
DWORD dwTemp;
// This function assumes that each of DivP, DivQ and Mux parameters are in
// available range, or REG_NOTSPECIFIED that means the corresponding
// registry key is omitted. Specified parameters are not altered while
// searching available PLL configurations.
// Feedback divider P
if (*pdwDivP == REG_NOTSPECIFIED) {
// DivP is not specified. This allows scanning DivP.
dwPMin = 4;
dwPMax = 130;
}
else {
// DivP is specified. DivP is fixed.
dwPMin = *pdwDivP;
dwPMax = *pdwDivP;
}
// Input divider Q
if (*pdwDivQ == REG_NOTSPECIFIED) {
// DivQ is not specified. This allows scanning DivQ.
dwQMin = 3;
dwQMax = 129;
}
else {
// DivQ is specified. DivQ is fixed.
dwQMin = *pdwDivQ;
dwQMax = *pdwDivQ;
}
// Output multiplexer M
if (*pdwMux == REG_NOTSPECIFIED) {
// Mux is not specified. This allows scanning Mux.
dwMMin = 0;
dwMMax = 7;
}
else {
// Mux is specified. Mux is fixed.
dwMMin = *pdwMux;
dwMMax = *pdwMux;
}
dwSearchStatus = 0; // This means available set is not found.
lCurErrPermil = 1000; // Current minimum error, set to enough large.
// Main loop for searching PLL parameters.
for (dwP = dwPMin; dwP <= dwPMax; dwP++) {
for (dwQ = dwQMin; dwQ <= dwQMax; dwQ++) {
for (dwM = dwMMin; dwM <= dwMMax; dwM++) {
// Divided reference frequency must be in 200kHz - 1MHz.
dwTemp = dwBaseFreq / dwQ;
if (dwTemp < 200000 || dwTemp > 1000000) goto NotAvail;
// VCO oscillation frequency check
dwOscFreq = dwBaseFreq * 2 * dwP / dwQ;
if (dwOscFreq < 50000000 || dwOscFreq > 150000000)
goto NotAvail;
// Calculate output frequency and error rate.
dwOutputFreq = dwOscFreq / (1 << dwM);
lErrPermil =
((LONG)dwOutputFreq - (LONG)dwTargetFreq)
/ (LONG)(dwTargetFreq / 1000);
// Error rate must be within -3.0% to 3.0%.
if (lErrPermil > 30 || lErrPermil < -30) goto NotAvail;
DEBUGMSG(GPE_ZONE_HW,
(TEXT("P=%d Q=%d M=%d DCLK=%d, %d.%d percent error.\r\n"),
dwP, dwQ, dwM, dwOutputFreq, lErrPermil / 10,
abs(lErrPermil) - abs(lErrPermil / 10) * 10));
// Store PLL parameters if this set provides lowest error
// or this is the first available set.
if (abs(lErrPermil) < abs(lCurErrPermil)
|| dwSearchStatus == 0) {
dwSearchStatus = 1; // available parameter set is found
dwCurP = dwP;
dwCurQ = dwQ;
dwCurM = dwM;
dwCurOutputFreq = dwOutputFreq;
lCurErrPermil = lErrPermil;
}
NotAvail: ; // Try next combination if the loop have not reached to end.
}
}
}
if (!dwSearchStatus) { // Failed to find parameter set.
RETAILMSG(1,
(TEXT("AMADisp: No available PLL parameter set.\r\n")));
return FALSE;
}
else { // Available parameter set is found.
DEBUGMSG(1,
(TEXT("AMADisp: Available PLL parameter set is found.\r\n")));
DEBUGMSG(1,
(TEXT("AMADisp: P=%d, Q=%d, M=%d, DisplayClock=%d.\r\n"),
dwCurP, dwCurQ, dwCurM, dwCurOutputFreq));
*pdwOutputFreq = dwCurOutputFreq;
*pdwDivP = dwCurP;
*pdwDivQ = dwCurQ;
*pdwMux = dwCurM;
return TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -