📄 cem847x.c
字号:
{ CQuasar__WriteReg(pIDecoder, this->Pio8fDataReg, ((Data? 0x0101:0x0100) << (PIONumber-8))); CQuasar__WriteReg(pIDecoder, this->Pio8fDirReg, (0x0101 << (PIONumber-8))); } return Q_OK;}/****f* HwLib/IDecoder_ReadPIO * USAGE * QRESULT IDecoder_ReadPIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD* pData) * QRESULT CEM840X__ReadPIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD* pData) * QRESULT CEM847X__ReadPIO(IDecoder* pIDecoder, DWORD PIONumber, DWORD* pData) * DESCRIPTION * EM840x has 8 input/output pins PIOs * EM847x has 16 input/output pins PIOs * IDecoder_ReadPIO sets the direction of pin "PIONumber" to input and reads the pin input. * PARAMETERS * IN IDecoder* pIDecoder - pointer to the decoder object * IN DWORD PIONumber - one of PIO0 ... PIO15. * IN BOOL* pData - poiterto read PIO: TRUE means high level, FALSE means low level for PIO. * RETURN VALUE * The return value is Q_FAIL if PIONumber is greater then the maximum number of PIOs supported./********************************************************************************************/QRESULT CEM847X__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 { CQuasar__WriteReg(pIDecoder, this->Pio8fDirReg, (0x0100 << (PIONumber-8)) ); *pData = (CQuasar__ReadReg(pIDecoder, this->Pio8fDataReg) & (0x0100 << (PIONumber-8))) ? 1:0; } QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" PIO%d read %d"), PIONumber, *pData )); return Q_OK;}/****f* HwLib/IDecoder_SetDisplayFilter * USAGE * QRESULT IDecoder_SetDisplayFilter( IDecoder* pIDecoder, BYTE FilterId, BYTE* pData, DWORD dwSize) * QRESULT CEM847X__SetDisplayFilter( IDecoder* pIDecoder, BYTE FilterId, BYTE* pData, DWORD dwSize) * DESCRIPTION * IDecoder_SetDisplayFilter - sets the luma and chroma coefficients of the horizontal or vertical filter. * PARAMETERS * IN IDecoder* pIDecoder - pointer to the decoder object * IN BYTE FilterId - Selects display filters: * HorizontalBilinear - not recommended * Horizontal4tapDefault - recommended for mpeg scaled/not scaled, jpeg scaled * Horizontal4tapJpg - recommended for jpg not scaled * VerticalBilinear - used if width > 1536 * Vertical2tapDefault - used if width > 1536 * Vertical4tapDefault - used if width < 1536 * IN BYTE* pData - pointer to a 2x32 bytes table representing the 2 filter x 32 coefficients for: * luma, chroma (vertical or horizontal) * IN DWORD dwSize - size of the buffer sent (32 coefficients = 64 bytes)./********************************************************************************************/QRESULT CEM847X__SetDisplayFilter(IDecoder* pIDecoder, BYTE FilterId, BYTE* pDataIn, DWORD dwSizeIn){ CQuasar *this = (CQuasar*) pIDecoder; Q4SymbolTable* pQ4 = (Q4SymbolTable*)this->pQ; DWORD i, HwLumaAddr; BYTE* pLumaData = Default4TapDisplayFilter; BYTE* pChromaData = Default4TapDisplayFilter; DWORD Ctrl1 = IDecoder_ReadDM(pIDecoder, pQ4->DICOM_Control.addr) & ~(BIT5|BIT4); switch(FilterId) { case HorizontalBilinear: this->HorizontalFilter = HorizontalBilinear; CQuasar__WriteDM(pIDecoder, pQ4->DICOM_Control.addr, Ctrl1 | (Q3CTRL1_HORZ_DOWN_FILT_ENABLE | Q4CTRL1_BILIN_HORZ_UP) ); IDecoder_WriteDM(pIDecoder, pQ4->DICOM_UpdateFlag.addr, 1); IDecoder_WriteDM(pIDecoder, pQ4->DisplayInfo.addr, 0); return Q_OK; case CustomHorizontal4tap: this->HorizontalFilter = CustomHorizontal4tap; pLumaData = this->Horizontal4tapLumaCoef; pChromaData = this->Horizontal4tapChromaCoef; HwLumaAddr = 0x1e90; Ctrl1 = (Ctrl1 & ~Q4CTRL1_BILIN_HORZ_UP) | Q3CTRL1_HORZ_DOWN_FILT_ENABLE; IDecoder_WriteDM(pIDecoder, pQ4->DisplayInfo.addr, 0); break; case Horizontal4tapDefault: this->HorizontalFilter = Horizontal4tapDefault; HwLumaAddr = 0x1e90; Ctrl1 = (Ctrl1 & ~Q4CTRL1_BILIN_HORZ_UP) | Q3CTRL1_HORZ_DOWN_FILT_ENABLE; IDecoder_WriteDM(pIDecoder, pQ4->DisplayInfo.addr, 0); break; case Horizontal4tapJpg: this->HorizontalFilter = Horizontal4tapJpg; pLumaData = DefaultJpg4TapDisplayFilter; pChromaData = DefaultJpg4TapDisplayFilter; HwLumaAddr = 0x1e90; Ctrl1 = (Ctrl1 & ~Q4CTRL1_BILIN_HORZ_UP) | Q3CTRL1_HORZ_DOWN_FILT_ENABLE; IDecoder_WriteDM(pIDecoder, pQ4->DisplayInfo.addr, 0xD0); break; case VerticalBilinear: this->VerticalFilter = VerticalBilinear; CQuasar__WriteDM(pIDecoder, pQ4->DICOM_Control.addr, (Ctrl1 & ~Q4CTRL1_4TAP_VERT_UP_DOWN) | Q4CTRL1_BILIN_VERT_UP_DOWN); IDecoder_WriteDM(pIDecoder, pQ4->DICOM_UpdateFlag.addr, 1); return Q_OK; case CustomVertical2tap: this->VerticalFilter = CustomVertical2tap; pLumaData = this->Vertical2tapLumaCoef; pChromaData = this->Vertical2tapChromaCoef; HwLumaAddr = 0x1e80; Ctrl1 = Ctrl1 & ~(Q4CTRL1_4TAP_VERT_UP_DOWN | Q4CTRL1_BILIN_VERT_UP_DOWN); break; case Vertical2tapDefault: this->VerticalFilter = Vertical2tapDefault; HwLumaAddr = 0x1e80; Ctrl1 = Ctrl1 & ~(Q4CTRL1_4TAP_VERT_UP_DOWN | Q4CTRL1_BILIN_VERT_UP_DOWN); break; case CustomVertical4tap: this->VerticalFilter = CustomVertical4tap; pLumaData = this->Vertical4tapLumaCoef; pChromaData = this->Vertical4tapChromaCoef; HwLumaAddr = 0x1e80; Ctrl1 = (Ctrl1 & ~Q4CTRL1_BILIN_VERT_UP_DOWN) | Q4CTRL1_4TAP_VERT_UP_DOWN; break; case Vertical4tapDefault: this->VerticalFilter = Vertical4tapDefault; HwLumaAddr = 0x1e80; Ctrl1 = (Ctrl1 & ~Q4CTRL1_BILIN_VERT_UP_DOWN) | Q4CTRL1_4TAP_VERT_UP_DOWN; break; default: return E_NOT_SUPPORTED; } for( i=0; i<16; i++ ) // luma coef { CQuasar__WriteReg(pIDecoder, HwLumaAddr + i, MAKEWORD(pLumaData[2*i], pLumaData[2*i+1])); } for( i=0; i<16; i++ ) // chroma coef { CQuasar__WriteReg(pIDecoder, HwLumaAddr + i + 32, MAKEWORD(pChromaData[2*i], pChromaData[2*i+1])); } CQuasar__WriteDM(pIDecoder, pQ4->DICOM_Control.addr, Ctrl1); IDecoder_WriteDM(pIDecoder, pQ4->DICOM_UpdateFlag.addr, 1); return Q_OK;}QRESULT CEM847X__SetDisplayFilterCoef(IDecoder* pIDecoder, BYTE* pCoef, DWORD dwSizeIn){ CQuasar *this = (CQuasar*) pIDecoder; if( (pCoef == NULL) || (dwSizeIn < 6*32) ) return Q_FAIL; OSmemcpy(this->Horizontal4tapLumaCoef, pCoef, 32); OSmemcpy(this->Horizontal4tapChromaCoef, pCoef, 32); OSmemcpy(this->Vertical2tapLumaCoef, pCoef, 32); OSmemcpy(this->Vertical2tapChromaCoef, pCoef, 32); OSmemcpy(this->Vertical4tapLumaCoef, pCoef, 32); OSmemcpy(this->Vertical4tapChromaCoef, pCoef, 32); CEM847X__SetDisplayFilter(pIDecoder, this->HorizontalFilter, NULL, 0); return CEM847X__SetDisplayFilter(pIDecoder, this->VerticalFilter, NULL, 0);}ULONG EM847xFindBestPllSet(ULONG F0, BYTE* pn, BYTE* pm){ int ppmError = 10; // 50ppm = 0.005%; 100ppm=0.01%; 1000ppm=0.1% int InputFreq = 27000000; // Hz int PPM = 1000000; // ppm per unit int n,m; BYTE Noptim=255, Moptim=127; int LowLimit = 10000000, UpperLimit = 100000000; int F, Foptim; int minDiff = F0*100; if( minDiff < 0 ) minDiff = 0x7fffffff; // default value. Must be overwritten Foptim = 0; for( m=1; m<64; m++) { for( n=1; n<256; n++) { F = 10 * ( (InputFreq / 10) * (n+2) / (m+2) ); if( (F > LowLimit) && (F < UpperLimit) ) { if( ((int)(F - F0)) > (-minDiff) && ((int)(F - F0)) < (minDiff) ) { minDiff = F - F0; if(minDiff<0) minDiff = -minDiff; Foptim = F; Noptim = (BYTE)n; Moptim = (BYTE)m; } if( ((int)((F - F0)*100) > (int)(-ppmError * F0 * 100 / PPM)) && ((int)((F - F0)*100) < (int)(ppmError * F0 * 100 / PPM) )) { goto end; } } } }end: if( m<64 && n<256 ) { *pn = (BYTE)n; *pm = (BYTE)m; return F; } else { *pn = Noptim; *pm = Moptim; return Foptim; }}QRESULT CEM847X__ProgramVClk(IDecoder* pIDecoder, DWORD* pFreq){ // CQuasar *this = (CQuasar*) pIDecoder; DWORD N=0, M=0, F; // Internal PLL has Fout = FRef*(N+2)/(M+2), where N = bits 7..0, M = bits 13..8 switch(*pFreq) { case 0: IDecoder_WriteReg(pIDecoder, VID_INTERNAL_PLL, USE_EXTVCLK_FOR_VCLK );// no Q4_POWER_UP_VIDEO_PLL break; case 27000000: IDecoder_WriteReg(pIDecoder, VID_INTERNAL_PLL, USE_VIDEO_PLL_FOR_VCLK | Q4_POWER_UP_VIDEO_PLL | (3<<8) | 3 ); break; default: F = EM847xFindBestPllSet(*pFreq, (BYTE*)&N, (BYTE*)&M); QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT(" F0=%d F=%d M=%d N=%d"), *pFreq, F, M, N )); IDecoder_WriteReg(pIDecoder, VID_INTERNAL_PLL, USE_VIDEO_PLL_FOR_VCLK | Q4_POWER_UP_VIDEO_PLL | (M<<8) | N ); // PixelFreq will be smaller than the wanted one because of arithmetic aproximation // We have to reevaluate: *pFreq = OSDDiv(27000000, N+2, M+2); break; } return Q_OK;}/****f* HwLib/IDecoder_SetAudioSampleRate * USAGE * QRESULT IDecoder_SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate) * QRESULT CEM840X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate) * QRESULT CEM847X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate) * QRESULT CEM848X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate) * DESCRIPTION * IDecoder_SetAudioSampleRate sets the audio sample rate to 32kHz, 44.1kHz or default 48kHz * It is called only by IDecoderBoard_AudioSetSampleRate. * PARAMETERS * IN IDecoder* pIDecoder - pointer to the decoder object * IN DWORD Rate - any of 32000, 44100 or 48000/********************************************************************************************/QRESULT CEM847X__SetAudioSampleRate(IDecoder* pIDecoder, DWORD Rate){ CQuasar *this = (CQuasar*) pIDecoder; Q4SymbolTable* pQ4 = (Q4SymbolTable*)this->pQ; DWORD Value; this->CurrentAudioRate = Rate; QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" CEM847X__SetAudioSampleRate=%lu"), Rate)); // 24 bits = 0xc0, EIAJ/I2S mask 0x10, invert mask 0x08, right justified mask 0x04 CQuasar__WriteDM(pIDecoder, pQ4->Jda1_config.addr, (this->AudioDacBitsPerSample == 16) ? 0x84 : 0xC0); // Config15:8, Config7:0 from JDA1 spec - default recommended 0x0001 = PMW1, CompensatorIN, DitherON CQuasar__WriteDM(pIDecoder, pQ4->Jda1_setup_lo.addr, 0x0006); // Config31:24, Config23:16 from JDA1 spec - default recommended 0x0000 // = 44.1kHz,pseudo-slave, disable mute on softmute, slow softmute switch(Rate) { case 44056: Value = 0x0108 | 0x0060; break; case 52734: Value = 0x0108 | 0x00e0; break; case 16000: Value = 0x8108 | 0x0040; break; case 32000: Value = 0x0108 | 0x0040; break; case 22050: Value = 0x8108 | 0x0000; break; case 44100: Value = 0x0108 | 0x0000; break; case 88200: // Untested - Need 88.2Khz PCM file Value = 0x0108 | 0x0000; // jda1 clock is programmed at 44100 break; case 24000: Value = 0x8108 | 0x0020; break; case 96000: Value = 0x0108 | 0x0020; // jda1 clock is programmed at 48000 break; default: case 48000: Value = 0x0108 | 0x0020; break; }//ccc force the microcode to update the new settings CQuasar__WriteDM(pIDecoder, pQ4->Jda1_setup_hi.addr, Value); CQuasar__WriteReg(pIDecoder, AUDIO_jda1_setup_hi, Value); 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) | (((Rate==32000) || (Rate==64000)) ? Q3_ASpdifStat1_32k : (((Rate==44100) || (Rate==88200)) ? Q3_ASpdifStat1_44k : Q3_ASpdifStat1_48k)); } CQuasar__WriteReg(pIDecoder, AUDIO_spdif_chstat1, HIWORD(this->ChannelStatus)); return Q_OK;}BOOL FindDividerCoef(DWORD numerator, DWORD denominator, DWORD* pn, DWORD* pm){ // numerator M // Problem: ----------- = ----. Find M and N, M<=0xFFFF, N<=0xFFFF. // denominator M+N // Find the common factors of numerator and denominator and divide by them while (1) { if ( (numerator<0x10000) && ((denominator - numerator)<0x10000) ) break; if (((numerator % 2) == 0) && ((denominator % 2) == 0)) { numerator = numerator / 2; denominator = denominator / 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -