📄 sync.c
字号:
/*
********************************************************************************
*
* LCD控制程序
*
* 这是一个同步信号处理模块
*
* 文件名 : SYNC.C
* 设计者 : Terry
********************************************************************************
* 功 能 描 述
*
* 目前采用的是查询方式的同步信号处理
********************************************************************************
*/
#include "global.h"
#include "scalar.h"
#include "osd.h"
#if EN_85HZ_FRAME_RATE
#include "mode_85.h"
#else
#include "mode.h"
#endif
static void SyncSetInterlace(void);
static void SyncGetModePixels(void);
static uint8 SyncGetIndex(void);
static void SyncOutRelPar(void);
static void SyncOutOneTimePar(void);
static uint16 SyncGetHcnt(void);
static uint16 SyncGetVcnt(void);
static uint8 SyncGetPol(void);
static void SyncGetAttr(SYNCATTR * Sync);
static void SyncSetVsErrRange(uint16 Vcount);
static void SyncSetHsErrRange(uint16 Hcount);
static uint16 SyncGetVcnt(void);
static void SyncEnterSleep(void);
static void SyncSetCapture(void);
/*
********************************************************************************
* 同步信号处理模块参数的定义
********************************************************************************
*/
#define NOPOL 0x80 // 忽略同步信号极性
#define SYNC_VGA_RETRY 6 // 在VGA条件下等待同步信号稳定的次数
#define SYNC_VIDEO_RETRY 6 // 在VIDEO条件下等待同步信号稳定的次数
#define SYNC_DETTIME 50 // 清除同步标志到标志建立需延时的时间,单位毫秒
#define VGA_HTOLE 2 // VGA输入条件下,显示模式变化的水平计数值门限
#define VGA_VTOLE 2 // VGA输入条件下,显示模式变化的水平计数值门限
/*================================= END ======================================*/
SYNCATTR xdata SyncAttr={123,456,0};
bit Flg_Interlace = 0; // (0)表示逐行扫描; (1)表示隔行扫描
bit Flg_SyncInt = 0; // 如果等于1表示有同步处理需求的中断产生
uint16 xdata Hfre,Vfre,Vtotal;
uint16 DispModeWidth, DispModeHeight;
uint8 ModeState;
/*
********************************************************************************
* 函 数 名: SyncSetInterlace
* 功能描述: 检测当前同步扫描方式是隔行扫描还是逐行扫描,并建立反映扫描方式的
* 标记以及相应寄存器的设置。
* 输 入: 无
* 返 回: 无
* 注 意: 目前完成的处理是针对图形输入接口的,对视频输入的情况没有进行处理
********************************************************************************
*/
static void SyncSetInterlace(void)
{
uint8 i, CountI, CountNI;
WrScalarReg(rP199, 0x03);
CountI = 0;
CountNI = 0;
for (i = 0; i < 5; i++) {
if (RdScalarReg(rP19A) & 0x04) CountI++;
else CountNI++;
Delay(30);
}
if (CountI > CountNI) {
WrScalarRegBit(rP020, 0x04, 0x04);
SyncAttr.HVPol |= 0x08;
Flg_Interlace = 1;
}
else {
WrScalarRegBit(rP020, 0x00, 0x04);
SyncAttr.HVPol &= 0xF7;
Flg_Interlace = 0;
}
}
/*
********************************************************************************
* 函 数 名: SyncGetIndex
* 功能描述: 搜索内建数据表ModeAttr,判断当前显示模式符合内建的哪一个
* 显示模式
* 输 入: 无
* 返 回: 返回数据表的索引
********************************************************************************
*/
static uint8 SyncGetIndex(void)
{
uint8 mode;
uint8 num;
Flg_ModeDetectContinue = 1;
num = EN_M640X350_50 + EN_M640X350_60 + EN_M640X350_70 +
EN_M640X350_85 + EN_M640X400_50 + EN_M640X400_60 + EN_M640X400_70 + EN_M640X400_85;
//SysPar.Flag &= ~FLAG_720MODE;
#if EN_720MODE
#else
SysPar.Flag |= FLAG_720MODE;
#endif
mode = 0;
while (ModeAttr[mode].Hscnt != 0)
{
if (((ModeAttr[mode].Pol&NOPOL) || ((ModeAttr[mode].Pol&0x03) == SyncAttr.HVPol)) &&
(abs(SyncAttr.Hcount - ModeAttr[mode].Hscnt) <= ModeAttr[mode].HErr) &&
(abs(SyncAttr.Vcount - ModeAttr[mode].Vscnt) <= ModeAttr[mode].VErr))
{
#if 0
#if USE_MODE_GLS //解决848x480/60Hz与640x480/60 被识别为同一模式的方法 // chen 08-05-23
#if EN_M848X480_60
if((uint8)(Hfre/100)>30 && (uint8)(Hfre/100)<32 && ((uint8)((Vfre+50)/100) == 60))
{
if(Flg_ModeDetectContinue)
{
if(Vtotal > 520)
{
mode++;
Flg_ModeDetectContinue = 0;
continue;
}
}
}
#endif
#endif
#endif
#if EN_720MODE
if(SysPar.Flag & FLAG_720MODE)
{
#endif
if (mode >= 2 && mode < num + 2)
{
if (SysPar.Flag & FLAG_720MODE) mode += num;
}
#if EN_720MODE
}
#endif
return mode;
}
mode++;
}
return 0xFF;
}
/*
********************************************************************************
* 函 数 名: SyncGetModePixels
* 功能描述: 获取当前显示模式的的水平和垂直像素
* 输 入: 该显示模式的索引号
* 返 回: 无
********************************************************************************
*/
void SyncGetModePixels(void)
{
if (ModePar.mode != 0xFF) {
DispModeWidth = ModeAttr[ModePar.mode].Hdisp;
DispModeHeight = ModeAttr[ModePar.mode].Vdisp;
}
else {
DispModeWidth = 1024;
DispModeHeight = 768;
}
}
uint32 SyncGetHscnt(void)
{
uint32 hcnt;
hcnt = RdScalarWord(rP0DE);
hcnt <<= 8;
hcnt += RdScalarReg(rP0DD);
return hcnt;
}
/*
********************************************************************************
* 函 数 名: SyncOutRelPar
* 功能描述: 当显示模式稳定后,输出该显示模式相关的参数, 这里所输出的参数是当模
* 式变化时,必须去输出的参数,系统开机之后仅需要输出一次的参数则放
* 到另一个函数中去处理
* 输 入: 该显示模式的索引号
* 返 回: 无
********************************************************************************
*/
static void SyncOutRelPar(void)
{
uint16 dstVtotal,dstHtotal;
uint16 DispActiveHeight;
uint8 val;
xdata float temp;
if (Flg_Interlace) {
if (DispModeWidth > 750) WrScalarReg(rP199, 0x03);
else WrScalarReg(rP199, 0x01);
}
val = 0x04;
if (DispModeWidth >= PanelWidth) val |= 0x40;
if (DispModeHeight >= PanelHeight) val |= 0x80;
WrScalarReg(rP191, val); //rP191在NT68167中没有定义,而该值的6,7位会影响图象以及功耗。// chen 08-05-08
// 设置捕获窗口的宽度、宽度和位置
if (Flg_Interlace) WrScalarWord(rP032, DispModeHeight<<1);
else WrScalarWord(rP032, DispModeHeight);
WrScalarWord(rP036, DispModeWidth);
AdjHpos(HIDE, 0);
AdjVpos(HIDE, 0);
/*
================================================================================
= 输出和SCALAR输出部分相关的参数
================================================================================
*/
// 以kHz为单位计算输出的点时钟频率
ulDotClk = (((uint32)PanelHeight * Vtotal)/DispModeHeight) * ((uint32)Vfre/10) * PanelMinHTotal / 10000; // 单位是kHz
if (Flg_Interlace) ulDotClk = ulDotClk << 1; // 如果是隔行方式, 则将时钟加倍
DispActiveHeight = PanelHeight; // 如果是满屏显示,那么可以这么处理
dstHtotal = PanelMinHTotal;
// 计算输出的垂直所有像素
dstVtotal = ((((uint32)Vtotal * DispActiveHeight) << 4) / DispModeHeight + 8) >> 4; //add .5 for rounding, make even
if (Flg_Interlace) dstVtotal = dstVtotal << 1;
if (dstVtotal < PanelMinVTotal) dstVtotal = PanelMinVTotal;
else if (dstVtotal > PanelMaxVTotal) dstVtotal = PanelMaxVTotal;
// 对ulDotClk的范围进行校正
// 这里先不进行处理
if (ulDotClk < PanelMinPClk) dstHtotal = PanelTypHTotal;
WrScalarWord(rP164, DispActiveHeight);
WrScalarWord(rP171, DispActiveHeight);
// 重新计算ulDotClk, 前面的值仅仅是一个预估值
temp = (((float)dstHtotal-0.1) * DispActiveHeight * 4096) / ulHfreqCounter / DispModeHeight;
ulDotClk = (uint32)(temp * 12000000);
SarSetDPLL();
WrScalarWord(rP15B, dstVtotal); // Display Vertical Total
WrScalarWord(rP15E, dstHtotal); // Display Horixontal Total
}
/*
********************************************************************************
* 函 数 名: SyncOutOneTimePar
* 功能描述: 当显示模式稳定后,输出该显示模式相关的参数
* 输 入: 该显示模式的索引号
* 返 回: 无
********************************************************************************
*/
static void SyncOutOneTimePar(void)
{
/*
================================================================================
= 亮度和颜色部分的参数输出
= 需要注意的是: 红绿蓝增益的部分,在对比度的输出中已经输出,因为他们都是
= 通过sRGB的方式来输出的
================================================================================
*/
AdcUpdatePara(&AdcPar);
AdjBacklight(HIDE, 0);
AdjBri(HIDE, 0);
AdjCon(HIDE, 0);
/*
================================================================================
= 输出其他部分的参数
================================================================================
*/
#if USE_AUDIO
AdjMute(HIDE, 0);
AdjVolume(HIDE, 0);
#endif
/*
================================================================================
= 滤波器设置和BF3的亮度/对比度/饱和度设置
================================================================================
*/
if ((InputSource == SOURCE_VGA ) ||(InputSource == SOURCE_DVI_A)) {
WrScalarReg(rP068, 0x7A);
// WrScalarReg(rP06A, 0xD1);
WrScalarReg(rP06A, 0x00); // 08-05-09
SarBF3Bri(0x80);
SarBF3Con(0x80);
SarBF3Sat(0x80);
}
else if (InputSource == SOURCE_DVI_D) {
WrScalarReg(rP068, 0x00);
WrScalarReg(rP06A, 0x00);
SarBF3Bri(0x80);
SarBF3Con(0x80);
SarBF3Sat(0x80);
}
else {
SarBF3Bri(0x80);
SarBF3Con(0x90);
SarBF3Sat(0x90);
}
Adj4B3Disp(HIDE, 0);
AdjCMWindow(HIDE, 0);
}
/*
********************************************************************************
* 与同步处理相关的初始化数据表
********************************************************************************
*/
uint8 code SyncInitTab[] = {
0x04, RegAddr(rP196),
B0110_1010, // rP196 Graphic Sync Processor Control 1
B1100_0000, // rP197 Graphic Sync Processor Control 2
// bit4,bit5在正常的情况下不能置位,会导致显示乱
0x4C, // rP198 Interlace Detector Control
//B0100_0001, // rP199 Graphic SYNC Processor Control 3
B0100_0011, // rP199 // 2006-12-27 修改
// rP1A3-rP1A6的结果是在时钟频率为12M时计算得来的
0x0A, RegAddr(rP1A3),
366/8, // rP1A3 Hsync not present
366/15, // rP1A4 Hsync present
366/5, // rP1A5 Vsync not present
1465/20, // rP1A6 Vsync present
0x08, // rP1A7 Hcounter change threshold
0x24, // rP1A8 Vcounter change threshold
0xBC, // rP1A9 H/V interrupt enable1
0x03, // rP1AA H/V interrupt enable2
0x3C, // rP1AB H/V interrupt clear1
0x03, // rP1AC H/V interrupt clear2
0x02, RegAddr(rP1AF),
0x4C, // rP1AF Video Field Decision Windows
0x00, // rP1B0 Field Polarity Control
0x01, RegAddr(rP37A),
0x41, // 2006-12-27 添加
0, // 如果记录长度为0, 那么表示数据表结束
};
/*
********************************************************************************
* 函 数 名: SyncInit
* 功能描述: 初始化SCALAR的同步处理
* 输 入: 无
* 返 回: 无
********************************************************************************
*/
void SyncInit(void)
{
RegDataTableOut(SyncInitTab);
SelVideoInput(SOURCE_VGA);
SyncClearIntFlag(); // 清除中断标志
}
/*
********************************************************************************
* 函 数 名: SyncGetIntState
* 功能描述: 获取是否有同步终端产生, 设置相应的标志(Flg_SyncInt), 并返回状态
* 输 入: 无
* 返 回: 如果有中断产生则返回1, 否则返回0
********************************************************************************
*/
uint8 SyncGetIntState(void)
{
return Flg_SyncInt;
}
/*
********************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -