📄 cnova.c
字号:
// Select can be PLL1, PLL2, PLL3, RLIMIT, GLIMIT, BLIMIT, GAMMA,RD_PIX, RD_HS BYTE REG2_lsb, REG1_msb; if(Select>0x80) { CNovaBase__Write( pIAnalogOverlay, 3, 0 ); CNovaBase__Write( pIAnalogOverlay, 4, (BYTE)(Select | MAIN_CK14) ); } else { CNovaBase__Write( pIAnalogOverlay, 4, MAIN_CK14 ); CNovaBase__Write( pIAnalogOverlay, 3, (BYTE)Select ); } REG2_lsb = CNovaBase__Read( pIAnalogOverlay, 2 ); REG1_msb = CNovaBase__Read( pIAnalogOverlay, 1 ); return ( (REG1_msb<<8) + REG2_lsb );}/****f* HwLib/IAnalogOverlay_ProgramPLL * USAGE * void IAnalogOverlay_ProgramPLL(IAnalogOverlay* pIAnalogOverlay, DWORD pll, DWORD N, DWORD M, DWORD K) * void CNovaLite__ProgramPLL(IAnalogOverlay* pIAnalogOverlay, DWORD pll, DWORD N, DWORD M, DWORD K) * void CNova__ProgramPLL(IAnalogOverlay* pIAnalogOverlay, DWORD pll, DWORD N, DWORD M, DWORD K) * DESCRIPTION * IAnalogOverlay_ProgramPLL has different implementation for Nova(EM9010) and NovaLite(EM9038). * Nova(EM9010) has three programmable PLLs, PLL1, PLL2, PLL3. * NovaLite(EM9038) has only one programmable PLL, identified like PLL3, that can be used * for audio clock or pixel clock. * The output frequency is obtained from input frequency using next equation: * Fout = Fin *(N+2) / (2^K) for PLL1 * Fout = Fin *(N+2) / [(M+2)*2^K] for PLL2,PLL3 * N, M, K coefficients have different range(see the hardware specification) for every PLL, * and they are programmed in registers 1 and 2. * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * IN WORD pll - it should be PLL3 for NovaLite * - one of PLL1, PLL2, PLL3 for Nova * IN DWORD N, M, K - PLL coefficients/******************************************************************************/void CNova__ProgramPLL(IAnalogOverlay* pIAnalogOverlay, DWORD pll, DWORD N, DWORD M, DWORD K){ BYTE REG2_lsb, REG1_msb; REG1_msb = (BYTE)( (M & 0x3f) | (K<<6)); REG2_lsb = (BYTE)N; CNova__WriteREG12(pIAnalogOverlay, (WORD)pll, REG1_msb, REG2_lsb);}/****f* HwLib/IAnalogOverlay_InitAnalogMux * USAGE * void IAnalogOverlay_InitAnalogMux(IAnalogOverlay* pIAnalogOverlay, DWORD MaximumDvclk) * void CNovaLite__InitAnalogMux(IAnalogOverlay* pIAnalogOverlay, DWORD MaximumDvclk) * void CNova__InitAnalogMux(IAnalogOverlay* pIAnalogOverlay, DWORD MaximumDvclk) * DESCRIPTION * IAnalogOverlay_InitAnalogMux has different implementation for Nova(EM9010) and NovaLite(EM9038). * For Nova(EM9010) powers up comparators, analog delay, PLL1 and PLL2, disables video clock, * and it sets the analog comparators to hide the MPEG. * For NovaLite(EM9038) powers up the PLL and the DAC, sets the multiplexer to hide the Mpeg video. * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * IN DWORD MaximumDvclk - required digital video clock frequency in kHz: * If 0 - Dvclk will match the VGA pixel frequency * If 1 - Dvclk will be set to 80000kHz = 80MHz * If any other value than 0 or 1 - required Dvclk in kHz - it should be limited between * hardware limits (30000 and 80000 for Nova1)/******************************************************************************/void CNova__InitAnalogMux(IAnalogOverlay* pIAnalogOverlay, DWORD MaximumDvclk){ //reg 0 for pulse detection //reg 1,2,3,4,A for setting PLL, ChromaKey, Gamma //reg 5 for selecting some mux .... //reg 6 for VRDY Delay: 3bits coarse adjust(PCLK) and 4 bits(3ns) fine adjust //reg 7 for DVCLK Delay: 4bits(3ns) fine adjust //reg 8 for VMAX, enable Ext_clk pin, TV timing enable, ... //reg 9 for Gamma bypass, DVCK enable, NTSC/PAL .... //reg B for HSync counter .... //reg C for PowerDown //reg D for VSync, HSync polarity, Select input for PLL1 CNova *this = (CNova*) pIAnalogOverlay; // Hide the MPEG this->ComparatorsCommand = ComparatorsNoCommand; this->VGAKeyMask = OVERLAY_SHOW_ALL; // to force OverlayHide() CNova__Hide(pIAnalogOverlay); this->PLL1_FreqLim = MaximumDvclk; CNova__GetHFreq(pIAnalogOverlay, TRUE); // will get m_HFreq from hardware CNova__SetDVCLKFrequency(pIAnalogOverlay, this->m_HFreq);// will return DefCorrection QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" IAM: Default correction: %lu"), this->m_DefCorrection )); CNovaBase__Write( pIAnalogOverlay, 4, MAIN_CK14 ); // Select PLL1, YUV data from Quasar, VGA not delayded for now and // enable AuxRGB CNovaBase__Write( pIAnalogOverlay, 5, 0x60 ); CNovaBase__Write( pIAnalogOverlay, 6, this->m_VrdyDelay ); CNovaBase__Write( pIAnalogOverlay, 7, (BYTE)(0x40 | this->m_JitterAdj) );// VRDY selected CNovaBase__Write( pIAnalogOverlay, 8, 0x80 ); // en_14 if(this->m_bUse_Gamma) CNovaBase__Write( pIAnalogOverlay, 0x0C, NOVA_POWER_ON_GAMMA ); else CNovaBase__Write( pIAnalogOverlay, 0x0C, NOVA_POWER_ON_NOGAMMA ); CNovaBase__Write( pIAnalogOverlay, 9, this->m_bUse_Gamma ); // DVCLK disable}/****f* HwLib/IAnalogOverlay_SetVGA * USAGE * void IAnalogOverlay_SetVGA(IAnalogOverlay* pIAnalogOverlay) * void CNovaLite__SetVGA(IAnalogOverlay* pIAnalogOverlay) * void CNova__SetVGA(IAnalogOverlay* pIAnalogOverlay) * DESCRIPTION * IAnalogOverlay_SetVGA has different implementation for Nova(EM9010) and NovaLite(EM9038). * For Nova(EM9010) it enables the chroma comparators, enabling also the pixel clock DVCLK * and the sync signals Vync and HSync (Nova is master). The Mpeg will be selected on * VGA monitor, based on chroma key mask and limits and on VRDY signal. * For NovaLite(EM9038) it selects the Mpeg video to show up on VGA monitor in fullscreen. * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * SEE ALSO * IAnalogOverlay_SetTv, IAnalogOverlay_ShowAll, IAnalogOverlay_SetChromaKey/******************************************************************************/void CNova__SetVGA(IAnalogOverlay* pIAnalogOverlay){ CNova *this = (CNova*) pIAnalogOverlay; CNovaBase__Write( pIAnalogOverlay, 7, (BYTE)( 0x40 | this->m_JitterAdj )); // VRDY selected - show the MPEG CNovaBase__Write( pIAnalogOverlay, 9, (BYTE)( 0x04 | this->m_bUse_Gamma ) ); // DVCLK enable this->ComparatorsCommand = ComparatorsNoCommand;}/****f* HwLib/IAnalogOverlay_SetTv * USAGE * void IAnalogOverlay_SetTv(IAnalogOverlay* pIAnalogOverlay) * void CNovaLite__SetTv(IAnalogOverlay* pIAnalogOverlay) * void CNova__SetTv(IAnalogOverlay* pIAnalogOverlay) * DESCRIPTION * IAnalogOverlay_SetTv has different implementation for Nova(EM9010) and NovaLite(EM9038). * For Nova(EM9010) it disables the chroma comparators, disabling also the pixel clock DVCLK * and the sync signals Vync and HSync (Nova is slave). * For NovaLite(EM9038) it selects the VGA signal on VGA monitor. * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * SEE ALSO * IAnalogOverlay_SetVGA, IAnalogOverlay_ShowAll/******************************************************************************/void CNova__SetTv(IAnalogOverlay* pIAnalogOverlay){ CNova *this = (CNova*) pIAnalogOverlay; CNovaBase__Write( pIAnalogOverlay, 7, 0x80 ); // GND selected - hide the MPEG CNovaBase__Write( pIAnalogOverlay, 9, (BYTE)( 0x00 | this->m_bUse_Gamma ) ); // DVCLK disable}/****f* HwLib/IAnalogOverlay_Test * USAGE * QRESULT IAnalogOverlay_Test(IAnalogOverlay* pIAnalogOverlay) * QRESULT CNovaLite__Test(IAnalogOverlay* pIAnalogOverlay) * QRESULT CNova__Test(IAnalogOverlay* pIAnalogOverlay) * DESCRIPTION * IAnalogOverlay_Test has different implementation for Nova(EM9010) and NovaLite(EM9038), * checking if the registers can be write and read correct. * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * RETURN VALUE * Q_OK if test succeeded, E_TEST_NOVA_FAILED if not./******************************************************************************/QRESULT CNova__Test(IAnalogOverlay* pIAnalogOverlay){ WORD a=0; CNova__WriteREG12(pIAnalogOverlay, RLIMIT,0x55,0xaa); if( (a = CNova__ReadREG12(pIAnalogOverlay, RLIMIT)) != 0x55aa ) { OSsprintf(g_InfoError, TEXT("Test NOVA error: RLIMIT write=0x55aa read=%x"),a); QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("Test NOVA failed") )); return E_TEST_NOVA_FAILED; } QDbgLog((QLOG_TRACE, QDebugLevelError, TEXT("Test NOVA OK") )); return Q_OK;}/****f* HwLib/IAnalogOverlay_SetDVCLKFrequency * USAGE * void IAnalogOverlay_SetDVCLKFrequency(IAnalogOverlay* pIAnalogOverlay, DWORD HFrequency) * void CNova__SetDVCLKFrequency(IAnalogOverlay* pIAnalogOverlay, DWORD HFrequency) * DESCRIPTION * IAnalogOverlay_SetDVCLKFrequency is implemented only for Nova(EM9010). * IAnalogOverlay_SetDVCLKFrequency calculates the postdivider for PLL1 and the default * Correction coefficient. * On analog board designs PLL1 is fed with the VGA horizontal frequency and divides it to * generate a synchronous video pixel clock(DVCLK) for EM8400. * The output frequency of PLL1 is obtained from input frequency using next equation: * Fout = Fin *(N+2) / (2^K), where N has 12 bits, K has 2 bits. * The internal PLL1 frequency is [Fout * (2^K)] and is hardware limited in between 30MHz * and 80MHz. * The analog overlay idea is to generate a Mpeg pixel frequency(Dvclk) equal with VGA pixel * frequency, given by the VGA mode choosed by user. The VGA pixel frequency cannot be read * from the VGA or system but it can be evaluated knowing the horizontal frequency and * the horizontal resolution. The total number of VGA pixels per line is about: * TotalVGAPixels = HorzResolution * 13/10. * The total number of Mpeg pixels per line is : * TotalMpegPixels = Dvclk / HFreq. * Starting from the PLL1 equation: * Dvclk = HFreq * (N+2) / (2^K) we can calculate the PLL divider: * N = (Dvclk * (2^K) / HFreq) - 2 = TotalMpegPixels * 2^K - 2, taking care about internal * PLL frequency limit: * Dvclk * 2^K < PLL1_FreqLim. * If we can generate for Mpeg exactly the same pixel frequency like VGA, a destination size of * 100 VGA pixels will correspond to 100 Mpeg pixels. In this case the correction coefficient * should be one unit(1000). * In real life we cannot generate exactly the VGA pixel frequency because PLL1 is limited. * The condition is Dvclk * 2^K < PLL1_FreqLim. In this case the PLL1 will work at PLL1_FreqLim * and Dvclk = PLL1_FreqLim / 2^K. * This implies TotalMpegPixels < TotalVGAPixels and we need a horizontal correction: * Correction = 1000 * TotalVGAPixels / TotalMpegPixels. * IAnalogOverlay_SetDVCLKFrequency is called by IAnalogOverlay_InitAnalogMux and by * CNE2000__VidChangeResolution * PARAMETERS * IN IAnalogOverlay* pIAnalogOverlay - pointer to the overlay object * IN DWORD HFrequency - horizontal frequency in hHz * SEE ALSO * IAnalogOverlay_GetHFreq/******************************************************************************/void CNova__SetDVCLKFrequency(IAnalogOverlay* pIAnalogOverlay, DWORD HFrequency){ CNova *this = (CNova*) pIAnalogOverlay; DWORD PLL1_FreqLim; // Limit of NOVA's PLL frequency in KHz DWORD nPixVGA; // number of active + inactive VGA pixels on a VGA line ..HF DWORD Dvclk; // NOVA's PLL out frequency in kHz DWORD K, N, VGACorrection; switch(this->HorzRes) { case 640: nPixVGA = 880; break; // 1.375 case 720: nPixVGA = 920; break; // 1.28 case 800: nPixVGA = 1024; break; // 1.28 case 1024: nPixVGA = 1280; break; // 1.25 case 1152: nPixVGA = 1440; break; // 1.25 case 1280: nPixVGA = 1550; break; // 1.2109 case 1600: nPixVGA = 2000; break; // 1.25 case 2048: nPixVGA = 2560; break; // 1.25 case 848: nPixVGA = 1078; break; // 1.27 default: nPixVGA = (10 * this->HorzRes) / 8; // 1.25 break; } if( this->pRegistry->TotalPixelsPerLine ) { nPixVGA = this->pRegistry->TotalPixelsPerLine; QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" From REGISTRY TotalPixelsPerLine= %d"), nPixVGA)); } if( this->PLL1_FreqLim == 0 ) // Dvclk same as VGA pixel clock PLL1_FreqLim = MAXIMUM_PLL1; else if(this->PLL1_FreqLim == 1)// Dvclk at maximum default value PLL1_FreqLim = MAXIMUM_PLL1; else // Dvclk at required maximum value { // take some precautions! PLL1_FreqLim = max( 25000, this->PLL1_FreqLim); PLL1_FreqLim = min( 85000, PLL1_FreqLim); } // find the maximum video clock possible, find Correction and N K = 0; // internal PLL1 frequency is equal with the PLL1 output frequency Dvclk = PLL1_FreqLim; VGACorrection = 1000 * (nPixVGA * HFrequency/10) / Dvclk;// 1000* VgaPixFreq/MpegPixFreq=1000* nPixVGA/nPixMpeg N = 10 * PLL1_FreqLim / HFrequency - 2; if(N > 0xFFF) // N has only 12 bits { // limit the Dvclk. It will happen only if HFreq < (PLL1Limit/4096) ~= 17Hz IMPOSSIBLE ! N = 0xFFF; Dvclk = (N+2) * (HFrequency / 10 ); VGACorrection = 1000 * nPixVGA / (Dvclk / (HFrequency / 10 ));// npixVGA/nPixMpeg } if( this->PLL1_FreqLim == 0 ) { // Dvclk same as VGA pixel clock if( ( nPixVGA * HFrequency / 10 ) < Dvclk ) // VgaPixFreq < max Dvclk { // if Dvclk match with the VGA pixel clock we don't need correction VGACorrection = 1000; Dvclk = nPixVGA * HFrequency / 10; N = nPixVGA - 2; if( Dvclk <= 30000 ) // don't let PLL1 frequency too low { K+=1;// post-divider N = nPixVGA * ( 1<<K ) - 2; } } else QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" Dvclk limited at %d"), Dvclk)); if( (VGACorrection < 850) || (VGACorrection > 3500) ) // if it is an error.. VGACorrection = 1500; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -