⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddc.cpp

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 CPP
字号:
/*
 * $Workfile: ddc.cpp $
 * $Revision: 3 $
 * $Date: 4/07/00 8:48a $
 * $Modtime: 4/07/00 8:38a $
 * $Author: Sarma $
 *
 * Contains routines for GXVideo initialization and also to set modes.
 *
 * Copyright (c) 1998 National Semiconductor Corporation.
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of National 
 * Semiconductor Corporation. ("Confidential Information").
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into
 * with National Semiconductor Corporation.
 * This code is supplied as is.
 *
 */

/*
 *$Log: /CE/Platform/Nsc/Drivers/Video/gxvideo/base/ddc.cpp $
 * 
 * 3     4/07/00 8:48a Sarma
 * Removed Cyrix Corporation from the legal/confidentail information.
 * 
 * 2     7/20/99 2:09p Sarma
 * Added Vss history tags.
*/

#include "precomp.h"
#include "ddc.h"

//Data locations in VESA ver1.0 format containg 128 Bytes
#define VESA1_VERSION 12
#define VESA1_REVSION 13
#define VESA1_EST_TIM1 35
#define VESA1_EST_TIM2 36
#define VESA1_EST_MANU_TIM 37
#define VESA1_EST_STAND_TIM 38

typedef struct _DispAspectRatio{
	int xRatio;
	int yRatio;
}DispAspectRatio;

static DispAspectRatio asp[4] = {
	{1, 1},
	{4, 3},
	{5, 4},
	{16, 9}
};
static  void standardTiming(unsigned char *data) 
{
	int width, height;
	int freq, ratio, pos;
	for (int i = 0; i < 8; i++) {
		//value = (HorizTiming /8) - 31
		pos = VESA1_EST_STAND_TIM + (i <<1); //Each timing uses 2 Bytes as info.
		if((data[pos] == 0x1 ) && (data[pos + 1] == 0x1))
			continue;
		width = (data[pos] + 31) << 3;
		freq = 60+(data[pos + 1] & 0x3F);
		ratio = (data[pos + 1] & 0xC0) >> 6;
		height = (width / asp[ratio].xRatio) * asp[ratio].yRatio;
		
	DEBUGMSG( 1,(TEXT("%d = %3dX%3d %dHz\n"),i, width, height, freq));
	//RETAILMSG( 1,(_T("%d = %3dX%3d %dHz\n"),i, width, height, freq));
	}
}

static void dumpData(unsigned char *data, int length) 
{
	for (int i = 0; i < length; i++) {
	DEBUGMSG( 1,(TEXT("%d = %2X %3d\n"),i, data[i],data[i]));
	//RETAILMSG( 1,(_T("%d = %2X %3d\n"),i, data[i],data[i]));
	}
}

DDC1_2B::DDC1_2B(unsigned char *regBase) {
	cxReg = regBase;
	displayDataLength = 128;
	displaySupports = 0;
	displayData = new byte[displayDataLength];
	memset(displayData, 0x0, displayDataLength);
	startXfer();
	init();
	getBlock(displayData, displayDataLength);
	endXfer();
	dumpData(displayData, displayDataLength);
	standardTiming(displayData);
}

DDC1_2B::~DDC1_2B() 
{
	DEBUGMSG( 0,(TEXT("DDC1_2B::~DDC1_2B\n")));
	if(displayData)
		delete [] displayData;
	displayData = 0x0;
}

// Data accessors for extracting information from the data block
bool DDC1_2B::doesDisplaySupport(unsigned long mode) 
{
	//Check if we were really able to read display
	if((displayData[VESA1_VERSION] == 0xFF) ||
		(displayData[VESA1_REVSION] == 0xFF))
		return false; 
	displaySupports = (displayData[VESA1_EST_TIM1] << 16) |
		(displayData[VESA1_EST_TIM2] << 8) | 
		displayData[VESA1_EST_MANU_TIM];
	DEBUGMSG( 1,(TEXT("doesDisplaySupport %X\n"),displaySupports));

	return ((displaySupports & mode) == mode);
}

//Wait for microSeconds
void DDC1_2B::wait(int uSec) 
{
	DEBUGMSG( 0,(TEXT("delay %d\n"),uSec));
	unsigned long target = GetTickCount() + uSec;

	while (GetTickCount() <= target);
}

unsigned char DDC1_2B::ReadByte(bool ack) 
{
	unsigned char val = 0;
	DEBUGMSG( 0,(TEXT("getByte\n")));
	for (int i = 0; i < 8; i++) {
		val <<= 1;
		val |= ReadBit();
	}

	Ack(ack);
	return val;
}

int DDC1_2B::ReadBit() 
{
	DEBUGMSG( 0,(TEXT("getBit\n")));
	wait();
	ClearSCL();
	wait();
	WaitSCLHigh();
	wait();
	return GetSDA();
}

void DDC1_2B::WaitSCLHigh() 
{
	DEBUGMSG( 0,(TEXT("WaitSCLHigh\n")));
	SetSCL();
	// slow down trasfer 

	unsigned long target = GetTickCount() + 2;
	for (;;) {	                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
		if (GetSCL() == 1) {
			break;
		} else if (GetTickCount() > target) {
			DEBUGMSG( 1,(TEXT("timeout")));
		}
		DEBUGMSG( 1,(TEXT("WaitSCLHigh - Delay 2 u Sec\n")));
	}
}

void DDC1_2B::SendByte(unsigned char data) 
{
	DEBUGMSG( 0,(TEXT("sendByte Enter\n")));
	for (int i = 7; i >= 0; i--) {
		SendBit((data >> i) & 1);
	}

	if (! waitForAck()) {
		DEBUGMSG( 1,(TEXT("NACK received\n")));
	}
	ClearSCL();
	DEBUGMSG( 0,(TEXT("sendByte Exit\n")));
}

void DDC1_2B::SendBit(bool flag) 
{
	DEBUGMSG( 0,(TEXT("sendBit\n")));
	wait();
	ClearSCL();
	wait();
	if (flag) {
		SetSDA();
	} else {
		ClearSDA();
	}
	wait();
	WaitSCLHigh();
}

void DDC1_2B::StartBit() 
{
	DEBUGMSG( 0,(TEXT("startBit\n")));
	wait();
	SetSDA();
	wait();
	WaitSCLHigh();
	wait();
	ClearSDA();
	wait();
}

void DDC1_2B::StopBit() 
{
	DEBUGMSG( 0,(TEXT("stopBit\n")));
	wait();
	WaitSCLHigh();
	wait();
	SetSDA();
	wait(2);
}

void DDC1_2B::Ack(bool flag)
{
	DEBUGMSG( 0,(TEXT("ACK\n")));
	wait();
	ClearSCL();
	wait();
	if (flag) {
		ClearSDA();
	} else {
		SetSDA();
	}
	WaitSCLHigh();
	ClearSCL();
	wait();
	SetSDA();
	DEBUGMSG( 0,(TEXT("ACK Exit\n")));
}

bool DDC1_2B::waitForAck()
{
	DEBUGMSG( 0,(TEXT("waitForACK\n")));
	wait();
	ClearSCL();
	wait();
	SetSDA();

	unsigned long target = GetTickCount() + 2;

	for (;;) {
		wait();
		if (GetSDA() == 0) {
			wait();
			WaitSCLHigh();
			return true;
	    //} else if(endtime > target) {
		} else if(GetTickCount() > target) {
			wait();
			WaitSCLHigh();
			return false;
		}
	}
}

void DDC1_2B::requestData() 
{
	DEBUGMSG( 0,(TEXT("requestData\n")));
	StartBit();
	SendByte(0xa0);
	SendByte(0);
	StopBit();

	StartBit();
	SendByte(0xa1);
}

void DDC1_2B::init() 
{
	DEBUGMSG( 0,(TEXT("setup\n")));
	SetSDA();
	WaitSCLHigh();
	ClearSCL();
	WaitSCLHigh();
	ClearSCL();
	WaitSCLHigh();
	requestData();
	ReadByte(false);
	StopBit();
}

void DDC1_2B::getBlock(unsigned char *block, int length) 
{
	DEBUGMSG( 0,(TEXT("getBlock\n")));
	requestData();

	int cksum = 0;
	int end = length - 1;

	for (int i = 0; i < length; i++) {
		block[i] = ReadByte((i != end));
		cksum += (int)block[i];
	}
	StopBit();

	DEBUGMSG( 0,(TEXT("getBlock %d\n"),cksum));

	if ((cksum & 0xff) != 0) {
		DEBUGMSG( 1,(TEXT("Checksum Error\n")));
	}
}

////////////////////////////////////////////////////////////////
// H/W DEPENDENT LOW LAYER ROUTINES
////////////////////////////////////////////////////////////////

// Toggle SDA from low to high while SCL is high.
void DDC1_2B::startXfer() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	DEBUGMSG( 0,(TEXT("startXfer\n")));
	data &= ~CX5530_DCFG_DDC_SCL;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data &= ~CX5530_DCFG_DDC_SDA;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data |= CX5530_DCFG_DDC_SCL;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data |= CX5530_DCFG_DDC_SDA;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}

// Toggle SDA from high to low while SCL is high.
void DDC1_2B::endXfer() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	DEBUGMSG( 0,(TEXT("endXfer\n")));
	data &= ~CX5530_DCFG_DDC_SCL;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data |= CX5530_DCFG_DDC_SDA;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data |= CX5530_DCFG_DDC_SCL;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	data &= ~CX5530_DCFG_DDC_SDA;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}

//Set clock high
void DDC1_2B::SetSCL() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	DEBUGMSG( 0,(TEXT("SetSCL\n")));
	data |= CX5530_DCFG_DDC_SCL;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}

//Set clock low
void DDC1_2B::ClearSCL() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	data &= ~CX5530_DCFG_DDC_SCL;
	DEBUGMSG( 0,(TEXT("DDCclockLo %X\n"),data));
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}

int DDC1_2B::GetSCL() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	DEBUGMSG( 0,(TEXT("GetSCL %X\n"), data));
	return ((data & CX5530_DCFG_DDC_SCL) >> 22);
}

//Set data high
void DDC1_2B::SetSDA() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	data |= CX5530_DCFG_DDC_SDA | CX5530_DCFG_DDC_OE;
	DEBUGMSG( 0,(TEXT("SetSDA %X\n"), data));
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}

//Set data low
void DDC1_2B::ClearSDA() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	data &= ~CX5530_DCFG_DDC_SDA; 
	data |= CX5530_DCFG_DDC_OE;
	DEBUGMSG( 0,(TEXT("ClearSDA %X\n"), data));
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
}


int DDC1_2B::GetSDA() 
{
	unsigned long data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	data &= ~CX5530_DCFG_DDC_OE;
	WRITE_REG32(cxReg, CX55xx_DISPLAY_CONFIG, data);
	wait(2); //10
	data = READ_REG32(cxReg, CX55xx_DISPLAY_CONFIG);
	DEBUGMSG( 0,(TEXT("GetSDA %X\n"), data));
	return (data >> 31);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -