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

📄 cem840x.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************************************//*  cem840x.c : Implementation of the EM8400/EM8401 interface*  REALmagic Quasar Hardware Library*  Created by Aurelia Popa-Radu*  Copyright Sigma Designs Inc*  Sigma Designs Proprietary and confidential*  Created on 8/1/01*  Description:/********************************************************************************************/#include "pch.h"#if defined EM840X_OBJECT#include "cquasar.h"#include "em840x.h"#include "regs840x.h"/****v* HwLib/Q3 * NAME *	Q3 * DESCRIPTION *	Global array of symbols used to send commands and data to EM8400 through microcode./********************************************************************************************/Q3SymbolTable Q3;UCHAR UCodeQuasar3[] =  {	#ifdef MICROCODE_NO_DOLBY		#include "quasar3/tst_no_dolby.h"	// doesn't play dolby no matter the bonding of the chip	#else		#include "quasar3/tst.h"			// play dolby no matter the bonding of the chip	#endif};QRESULT InitializeSymbolsTable( IDecoder* pIDecoder );QRESULT CEM840X__SetMicrocode(IDecoder* pIDecoder, DWORD Id){	CQuasar *this = (CQuasar*) pIDecoder;	if(Id == ebiUcode_MpegDecode)	{		this->pUCode = (BYTE*)UCodeQuasar3;		this->UCodeSize = sizeof(UCodeQuasar3);		this->pQ = (void*)&Q3;	// symbol table		this->SymbolTableSize = sizeof(Q3);		return InitializeSymbolsTable(pIDecoder);	}	else		return E_NOT_SUPPORTED;}/****f* HwLib/IDecoder_InitPtsFifo * USAGE *	void IDecoder_InitPtsFifo(IDecoder* pIDecoder, DWORD type) *	void CEM840X__InitPtsFifo(IDecoder* pIDecoder, DWORD type) * DESCRIPTION *	IDecoder_InitPtsFifo initialize the PTS_FIFO structure associated with "type" stream. *	The decoder object keeps 3 PACKETS_FIFO structures for video, audio, subpicture and osd. *	IDecoder_InitPtsFifo is called by IDecoderBoard_VideoHwStop, IDecoderBoard_AudioHwStop, *	IDecoder_HwReset. * PARAMETERS *	IN IDecoder* pIDecoder - pointer to the decoder object *	IN DWORD type - one of VIDEO, AUDIO, SUBPICTURE. * SEE ALSO *	IDecoder_PtsFifoEmptiness, IDecoder_WritePts/********************************************************************************************/void CEM840X__InitPtsFifo(IDecoder* pIDecoder, DWORD type){#define VPTS_ENTRIES_SIZE		4		// 16 bits words#define APTS_ENTRIES_SIZE		4		// 16 bits words#define SPTS_ENTRIES_SIZE		2		// 16 bits words	CQuasar *this = (CQuasar*) pIDecoder;	PTS_FIFO* p = &this->PtsFifo[type];	DWORD i;	switch (type)	{	case AUDIO:		p->Start = Q3.Audio_PTSFifo.addr;		p->EntrySize = APTS_ENTRIES_SIZE;		p->Size = CQuasar__ReadDM(pIDecoder, Q3.Audio_PTSSize.addr) / p->EntrySize;		CQuasar__WriteDM(pIDecoder, Q3.Audio_PTSRdPtr.addr, p->Start);		for (i=0;i<p->Size;i++)			CQuasar__WriteDM(pIDecoder, p->Start + 3 + i * p->EntrySize, 0);	// disable new PTS entry		break;	case SUBPICTURE:		p->Start = Q3.SP_PTSFifo.addr;		p->EntrySize = SPTS_ENTRIES_SIZE;		p->Size = CQuasar__ReadDM(pIDecoder, Q3.SP_PTSSize.addr) / p->EntrySize;		CQuasar__WriteDM(pIDecoder, Q3.SP_PTSRdPtr.addr, p->Start);		for (i=0;i<p->Size;i++)			CQuasar__WriteDM(pIDecoder, p->Start + 1 + i * p->EntrySize, 0);	// disable new PTS entry		break;	case VIDEO:	default:		p->Start = Q3.MV_PTSFifo.addr;		p->EntrySize = VPTS_ENTRIES_SIZE;		p->Size = CQuasar__ReadDM(pIDecoder, Q3.MV_PTSSize.addr) / p->EntrySize;		CQuasar__WriteDM(pIDecoder, Q3.MV_PTSRdPtr.addr, p->Start);		for (i=0;i<p->Size;i++)			CQuasar__WriteDM(pIDecoder, p->Start + 3 + i * p->EntrySize, 0);	// disable new PTS entry		break;	}	p->RdPtr = 0;	p->WrPtr = 0;	p->Emptiness = p->Size;	p->Fullness = 0;}/****f* HwLib/IDecoder_PtsFifoEmptiness * USAGE *	DWORD IDecoder_PtsFifoEmptiness(IDecoder* pIDecoder, DWORD type) *	DWORD CEM840X__PtsFifoEmptiness(IDecoder* pIDecoder, DWORD type) * DESCRIPTION *	IDecoder_PtsFifoEmptiness updates from hardware the RdPtr in PTS_FIFO and calculates *	Emptiness and Fullness members of PTS_FIFO. *	The fifo is empty when RdPtr==WrPtr and in this case Emptiness=Size, Fullness=0. *	The fifo is full when there is only one entry empty and in this case Emptiness=1, Fullness=Size-1. *	It is called by IDecoderBoard_SendVideoPayload, IDecoderBoard_SendAudioPayload, *	IDecoderBoard_SendSpuPayload, IDecoderBoard_PtsFifoEmptiness. * PARAMETERS *	IN IDecoder* pIDecoder - pointer to the decoder object *	IN DWORD type - one of VIDEO, AUDIO, SUBPICTURE. * RETURN VALUE *	returns Emptiness of the PTS fifo * SEE ALSO *	IDecoder_InitPtsFifo, IDecoder_WritePts/********************************************************************************************/DWORD CEM840X__PtsFifoEmptiness(IDecoder* pIDecoder, DWORD type){	CQuasar *this = (CQuasar*) pIDecoder;	PTS_FIFO* p = &this->PtsFifo[type];	switch (type)	{	case AUDIO:		p->RdPtr = (CQuasar__ReadDM(pIDecoder, Q3.Audio_PTSRdPtr.addr) - p->Start) / p->EntrySize;		break;	case SUBPICTURE:		p->RdPtr = (CQuasar__ReadDM(pIDecoder, Q3.SP_PTSRdPtr.addr) - p->Start) / p->EntrySize;		break;	case VIDEO:	default:		p->RdPtr = (CQuasar__ReadDM(pIDecoder, Q3.MV_PTSRdPtr.addr) - p->Start) / p->EntrySize;		break;	}	p->Emptiness = (p->Size + p->RdPtr - p->WrPtr - 1) % p->Size + 1;// number of empty entries	p->Fullness = p->Size - p->Emptiness;// number of non-empty entries	if( p->Emptiness == 1)	{		QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT("%s FifoPts E=%x F=%x Rd=%x Wr=%x"),			(type==AUDIO)?"A": (type==VIDEO)?"V":"S", p->Emptiness, p->Fullness, p->RdPtr, p->WrPtr ));	}	return p->Emptiness;}/****f* HwLib/IDecoder_WritePTS * USAGE *	BOOL IDecoder_WritePTS(IDecoder* pIDecoder, DWORD type, DWORD ByteCount, MPEG_SCR pts) *	BOOL CEM840X__WritePTS(IDecoder* pIDecoder, DWORD type, DWORD ByteCount, MPEG_SCR pts) * DESCRIPTION *	SCR(system clock reference) and PTS(presentation time stamp) have 90kHz unit and they *	are represeted on 33 bits. *	Our Mpeg2 decoder has 45kHz unit for SCR and PTS in order to use only 32 bits representation. *	IDecoder_WritePTS writes a PTS in the circular PTS_FIFO without checking if there is *	place for a new entry. This means that it is possible to overwrite a PTS not consummed *	yet by the decoder. The caller should check overwriting using IDecoder_PtsFifoEmptiness. *	It is called by IDecoderBoard_SendVideoPayload, IDecoderBoard_SendAudioPayload, *	IDecoderBoard_SendSpuPayload. * PARAMETERS *	IN IDecoder* pIDecoder - pointer to the decoder object *	IN DWORD type - one of VIDEO, AUDIO, SUBPICTURE. *	IN DWORD ByteCount - number of bytes sent already to the hardware. *	IN DWORD pts - presentation time stamp in 90KHz units of the next packet of data. * RETURN VALUE *	TRUE * SEE ALSO *	IDecoder_InitPtsFifo, IDecoder_PtsFifoEmptiness/********************************************************************************************/BOOL CEM840X__WritePTS(IDecoder* pIDecoder, DWORD type, DWORD ByteCount, MPEG_SCR PtsIn){// pts is in 45kHz units = 22.(2)us units	CQuasar *this = (CQuasar*) pIDecoder;	PTS_FIFO* p = &this->PtsFifo[type & ~CTS_AVAILABLE_FLAG];	// Size, RdPtr, WrPtr are in "EntrySize" units, RdPtr, WrPtr are relative to Start	int AbsoluteWrPtr = p->Start + p->EntrySize * p->WrPtr;	DWORD pts = DWORDLONG_Cast_DWORD(PtsIn);	p->WrPtr = (p->WrPtr + 1)%p->Size;	QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT("%s WrPTS45k= %x n= %x"),		(type==AUDIO)?"A": (type==VIDEO)?"V":"S", pts, ByteCount));	switch (type)	{	case SUBPICTURE:		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 0, HIWORD(pts));		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 1, (LOWORD(pts)) | 1);	// enable new PTS entry		break;	case AUDIO:	case VIDEO:	default:		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 0, HIWORD(ByteCount));		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 1, LOWORD(ByteCount));		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 2, HIWORD(pts));		CQuasar__WriteDM(pIDecoder, AbsoluteWrPtr + 3, (LOWORD(pts)) | 1);	// enable new PTS entry		break;	}	return TRUE;}/****f* HwLib/IDecoder_WritePCR * USAGE *	QRESULT IDecoder_WritePCR(IDecoder* pIDecoder, MPEG_SCR pcr) *	QRESULT CEM840X__WritePCR(IDecoder* pIDecoder, MPEG_SCR pcr) * DESCRIPTION *	PCR has 45kHz unit in order to use only 32 bits representation. *	IDecoder_WritePCR writes a PCR after checking if there is place for a new entry. This means that it is possible to overwrite a PTS not consummed/********************************************************************************************/QRESULT CEM840X__WritePCR(IDecoder* pIDecoder, MPEG_SCR PcrIn){	// pts is in 45kHz units = 22.(2)us units	DWORD pts = DWORDLONG_Cast_DWORD(PcrIn);	if( IDecoder_ReadDM(pIDecoder, Q3.PCR_Frac.addr) == 0 )	{		IDecoder_WriteDM(pIDecoder, Q3.PCR_Hi.addr, HIWORD(pts) );		IDecoder_WriteDM(pIDecoder, Q3.PCR_Lo.addr, LOWORD(pts) );		IDecoder_WriteDM(pIDecoder, Q3.PCR_Frac.addr, 1 );		return Q_OK;	}	return Q_FAIL;}QRESULT CEM840X__SetProperty( IDecoder* pIDecoder,	DWORD PropSet, DWORD PropId, DWORD Flags, void* pData, DWORD dwSizeIn, DWORD* pdwSizeOut){	CQuasar *this = (CQuasar*) pIDecoder;	// DECODER use DWORD for changing information and size condition is already checked	DWORD Value = *(DWORD*)pData;	//	QRESULT qr = Q_OK;	QDbgLog((QLOG_TRACE, QDebugLevelTrace,		TEXT("   --> CEM840X__SetProperty: set=%x id=%x flags=%x sz=%x value=%x"),		PropSet, PropId, Flags, dwSizeIn, Value));	switch(PropId)	{	case edecAudioInOutConfig:		// Normal=I2SInv doesn't need EM84xx frame inversion!		this->SerialCtrl0Config = Q3_ASctrl0_CkoutInverted | Q3_ASctrl0_MSbitfirst;		// I2S needs EM84xx frame inversion!		if(Value == I2S_SCkinSCIN_Jda1CkinGCK_ScinIN_DamckIN)			this->SerialCtrl0Config |= Q3_ASctrl0_FrameInverted;		this->SerialCtrl1Config = Q3_ASctrl1_Irclkin;		return E_NOT_SUPPORTED;	default:		return CQuasar__SetProperty(pIDecoder, PropSet, PropId, Flags, pData, dwSizeIn, pdwSizeOut);	}	return Q_OK;}QRESULT CEM840X__GetProperty( IDecoder* pIDecoder,	DWORD PropSet, DWORD PropId, DWORD Flags, void* pData, DWORD dwSizeIn, DWORD* pdwSizeOut){	//	CQuasar *this = (CQuasar*) pIDecoder;	// DECODER use DWORD for changing information and size condition is already checked	DWORD Value;	switch(PropId)	{	case edecAudioInOutConfig:		return E_NOT_SUPPORTED;	default:		return CQuasar__GetProperty(pIDecoder, PropSet, PropId, Flags, pData, dwSizeIn, pdwSizeOut);	}	*(DWORD*)pData = Value;	QDbgLog((QLOG_TRACE, QDebugLevelTrace,		TEXT("   <-- CEM840X__GetProperty: set=%x id=%x flags=%x sz=%x value=%x"),		PropSet, PropId, Flags, dwSizeIn, Value));	return Q_OK;}void CEM840X__InitPropertySet(IDecoder* pIDecoder, void* pPropSet, DWORD dwSize){	CQuasar *this = (CQuasar*) pIDecoder;	if(dwSize != sizeof(PROPERTY_SET_ITEM))		return;	InitPropSet(pIDecoder, pPropSet, DECODER_SET, edecMax,\		this->DecoderPropertyList, CEM840X__SetProperty, CEM840X__GetProperty)}QRESULT CEM840X__SetPIODir(IDecoder* pIDecoder, DWORD PIONumber, DWORD Dir){	CQuasar *this = (CQuasar*) pIDecoder;	if(PIONumber < 8)		CQuasar__WriteReg(pIDecoder, this->Pio07DirReg, ((Dir ? 0x0101:0x0100) << PIONumber) );	else		return Q_FAIL;	return Q_OK;}QRESULT CEM840X__WritePIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD Data){	CQuasar *this = (CQuasar*) pIDecoder;	// don't assume that PIO is output	if(PIONumber < 8)	{		CQuasar__WriteReg(pIDecoder, this->Pio07DataReg,			((Data? 0x0101:0x0100) << PIONumber));		CQuasar__WriteReg(pIDecoder, this->Pio07DirReg,			(0x0101 << PIONumber));	}	else		return Q_FAIL;	return Q_OK;}QRESULT CEM840X__ReadPIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD* pData){	CQuasar *this = (CQuasar*) pIDecoder;	// don't assume that PIO is input	if(PIONumber < 8)	{		CQuasar__WriteReg(pIDecoder, this->Pio07DirReg,			(0x0100 << PIONumber) );		*pData = (CQuasar__ReadReg(pIDecoder, this->Pio07DataReg) & (0x0100 << PIONumber)) ? 1:0;	}	else		return Q_FAIL;	return Q_OK;}QRESULT CEM840X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate){	CQuasar *this = (CQuasar*) pIDecoder;	this->CurrentAudioRate = Rate;	QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT("   CQ__SetAudioSampleRate=%lu"), Rate));	if( this->AudioSampleRateSupport_96kHz )	{		this->ChannelStatus = (this->ChannelStatus & ~Q3_ASpdifStat1_rate) |			((Rate==32000) ? Q3_ASpdifStat1_32k :			((Rate==44100) ? Q3_ASpdifStat1_44k :			((Rate==88200) ? Q3_ASpdifStat1_88k :			((Rate==96000) ? Q3_ASpdifStat1_96k :			Q3_ASpdifStat1_48k))));	}	else	{		this->ChannelStatus = (this->ChannelStatus & ~Q3_ASpdifStat1_rate) |

⌨️ 快捷键说明

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