📄 cne2000.c
字号:
/******************************************************************************//* cne2000.c : specific code for NE2000 board* REALmagic Quasar Hardware Library* Created by Aurelia Popa-Radu* Copyright Sigma Designs Inc* Sigma Designs Proprietary and confidential* Created on 8/7/01* Description:/******************************************************************************//****h* HwLib/CNE2000_Implementation * DESCRIPTION * CNE2000 implementation of the IDecoderBoard interface. * NE2000 uses EM840X, EM9010, EM9038, AD7170 components to implement * analog overlay output, TV output, HDTV output. * Identified by HwLib reading MD5,MD4,MD3,MD2 pins = 0100 (MDCFG_NE2000). * PIO0 - IIC Clock for EM9010, AD7170, Eeprom * PIO1 - IIC Data for EM9010, AD7170, Eeprom * PIO2 - signal for presence of VCXO for new NE2000/4000 boards * PIO3 - VCXO control for new NE2000/4000 boards * PIO4 - IIC Clock for EM9038 * PIO5 - IIC Data for EM9038 * PIO6 - DVCLK_PIO = 1/0 select VClk 27MHz/NovaClk * PIO7 - NO_LOOP_PIO = 1/0 select HDTV/Vga overlay * Specific implementation: * QRESULT CNE2000__HwReset(IDecoderBoard* pIDecoderBoard) * QRESULT CNE2000__UpdateOverlay(IDecoderBoard* pIDecoderBoard) * QRESULT CNE2000__VidChangeDisplayResolution(IDecoderBoard* pIDecoderBoard, PMPEG_DISPLAY_RESOLUTION pDisplay) * QRESULT CNE2000__SetCustomTvHdtv(IDecoderBoard* pIDecoderBoard, void* pTvHdtv, DWORD TvHdtvSize) * QRESULT CNE2000__VidSetVGATV(IDecoderBoard* pIDecoderBoard, DWORD VideoRunning, DWORD TvOut) * QRESULT CNE2000__AudioSetSampleRate(IDecoderBoard* pIDecoderBoard, DWORD Rate) * QRESULT CNE2000__SelectVClk(IDecoderBoard* pIDecoderBoard, VCLK_TYPE Type, void* pContext, DWORD ContextSize) * QRESULT CNE2000__OverlaySetVgaKey(IDecoderBoard* pIDecoderBoard, PMPEG_OVERLAY_KEY pKey) * QRESULT CNE2000__OverlayGetVgaKey(IDecoderBoard* pIDecoderBoard, PMPEG_OVERLAY_KEY pKey) * QRESULT CNE2000__OverlaySetVgaKey2(IDecoderBoard* pIDecoderBoard, PMPEG_OVERLAY_KEY2 pKey2) * QRESULT CNE2000__OverlayGetVgaKey2(IDecoderBoard* pIDecoderBoard, PMPEG_OVERLAY_KEY2 pKey2) * QRESULT CNE2000__OverlaySetMode(IDecoderBoard* pIDecoderBoard, MPEG_OVERLAY_MODE Mode) * QRESULT CNE2000__OverlaySetColorCalibration(IDecoderBoard* pIDecoderBoard, PCALIBRATION_PARAMETERS p) * QRESULT CNE2000__AdjTopBorder(IDecoderBoard* pIDecoderBoard, SHORT* pYOffset) * QRESULT CNE2000__AdjLeftBorder(IDecoderBoard* pIDecoderBoard, SHORT* pXOffset) * QRESULT CNE2000__AdjCorrection(IDecoderBoard* pIDecoderBoard, SHORT BorderOfsX, DWORD* pCorrection) * QRESULT CNE2000__OverlayColorCalibrate(IDecoderBoard* pIDecoderBoard, OVERLAY_COLOUR_REGISTERS *pIn, * OVERLAY_COLOUR_REGISTERS *pOut) * QRESULT CNE2000__OverlayCalibrate(IDecoderBoard* pIDecoderBoard, POVERLAY_COLOUR_REGISTERS pIn, POVERLAY_COLOUR_REGISTERS pOut)/******************************************************************************/#include "pch.h"#if defined ANALOG_OVERLAY#include "cqsrbrd.h"#define DICOM_UPDATE_TIME 30000 // 30ms ~ 2 Vsyncs/****f* HwLib/IDecoderBoard_HwReset * USAGE * DWORD IDecoderBoard_HwReset(IDecoderBoard* pIDecoderBoard) * Specific implementation: * CNE2000__HwReset * CNE2000TV__HwReset * CVE2000__HwReset * DESCRIPTION * IDecoderBoard_HwReset - Initialize RISC, Dram, load microcode in Dram, * initialize variables, disable interrupt, start the RISC * PARAMETERS * IN IDecoderBoard* pIDecoderBoard - pointer to the board object * RETURN VALUE * If the function succeeds, the return value is Q_OK. * If the function fails, the return value can be: * E_LOAD_MICROCODE_FAILED - the microcode cannot be written in DRAM * E_MICROCODE_FAILED - some variables in DataMemory are not initialized * E_VIDEO_WRITE_COMMAND_FAILED - usually no VSync,HSync/******************************************************************************/QRESULT CNE2000__HwReset(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; QRESULT qr = Q_OK; CommonSymbolTable* pQ = (CommonSymbolTable*)this->pQ; int i = 0; DWORD temp; this->m_bEnableSync = TRUE; this->FirstSystemSCR = TRUE; this->VideoState = VideoStoppedAfterReset; if( !this->pRegistry->DoHwReset ) return CQuasarBoard__DontDoHwReset(pIDecoderBoard); // program TV with Dacs disable before HwReset to minimize flashing on TV if(this->m_pIExtTv) ITvEncoder_InitTvEncoder(this->m_pIExtTv); //Risc and DRAM Init, set channels priorities,download microcode if( QFAILED(qr = IDecoder_HwReset(this->m_pIDecoder)) ) return qr; // Restore the PIO state for (i = 0; i < 16 ; i++) { if( (this->PioAccessedByUser>>i) && 1 ) // PIO accessed by user { if( (this->PioDirState>>i) && 1) // PIO is Output IDecoder_WritePIO(this->m_pIDecoder, i, (this->PioDataState>>i) & 1 ); else // PIO is input IDecoder_ReadPIO(this->m_pIDecoder, i, &temp ); } } ITvEncoder_InitTvEncoder(this->m_pISigmaTv); IDecoder_InitCloseCaption(this->m_pIDecoder); IAnalogOverlay_SetVgaResolution(this->m_pINova1, &this->DisplayResolution); IAnalogOverlay_InitAnalogMux(this->m_pINova1, this->pRegistry->MaximumDvclk); if( OSmemcmp (&this->NewDisplayResolution, &this->DisplayResolution, sizeof (MPEG_DISPLAY_RESOLUTION)) ) { OSmemcpy (&this->NewDisplayResolution, &this->DisplayResolution, sizeof (MPEG_DISPLAY_RESOLUTION)); this->DisplayResolutionChanged = 1; } if( this->m_pINovaLite ) IAnalogOverlay_InitAnalogMux(this->m_pINovaLite, 0); this->ReqYcYuvRgb = OUTPUT_OFF;// analog Tv dacs are off IDecoderBoard_VidSetVGATV(pIDecoderBoard, 0, this->TvOut); // force the hardware to set the sample rate IDecoderBoard_AudioSetSampleRate(pIDecoderBoard, this->BoardAudioRate | FORCED_HW_UPDATE); if(this->PixelClockPolarity == 1) { IDecoder_WriteDM(this->m_pIDecoder, pQ->DICOM_Control2.addr, IDecoder_ReadDM(this->m_pIDecoder, pQ->DICOM_Control2.addr) | Q3CTRL2_PIXCLK_POLARITY); } if(this->VideoClipEnable == 1) { IDecoder_WriteDM(this->m_pIDecoder, pQ->DICOM_Control2.addr, IDecoder_ReadDM(this->m_pIDecoder, pQ->DICOM_Control2.addr) | Q3CTRL2_VIDEO_CLIP_ENABLE); } IDecoder_WriteDM(this->m_pIDecoder, pQ->Force_PanScanDefHorSize.addr, this->Force_PanScanDefHorSize); if( QFAILED(qr = IDecoder_HwStart(this->m_pIDecoder)) ) return qr; // Risc Start and BlackFrame if(this->TvOut == SET_VGA) this->IsInterlaced = IDecoder_IsInterlaced(this->m_pIDecoder, this->DisplayResolution.iScreenHeight); IDecoderBoard_UpdateOverlay(pIDecoderBoard); IDecoder_SetCurrentIrqMask( this->m_pIDecoder, 0 ); return Q_OK;}void CNE2000__ProgramVclkForHdtv(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; DWORD N, M = 40, K = 0; if( this->HdtvMode.PixelFreq > 82000000 ) { QDbgLog((QLOG_TRACE, QDebugLevelWarning, TEXT("PixF=%dKHz LIMITED to 82 MHz!!!"), (this->HdtvMode.PixelFreq)/1000)); this->HdtvMode.PixelFreq = 82000000; } //limit N to 8 bits N = (this->HdtvMode.PixelFreq) * (M+2) * (1<<K) / this->RefFreqForPLL23 - 2; IAnalogOverlay_ProgramPLL(this->m_pINova1, PLL2, N, M, K); // PixelFreq will be smaller than the wanted one because of arithmetic aproximation // We have to reevaluate: this->HdtvMode.PixelFreq = this->RefFreqForPLL23 * (N+2) /((M+2) * (1<<K));}/****f* HwLib/CNE2000__UpdateScaledVideoWindow * USAGE * NOT PRESENT in IDecoderBoard interface * BOOL CNE2000__UpdateScaledVideoWindow(IDecoderBoard* pIDecoderBoard) * DESCRIPTION * CNE2000__UpdateScaledVideoWindow - used only for analog overlay, to display * the MPEG in a scalable window. * It is called only by IDecoderBoard_VGAUpdateVideoWindow. * In order to display with or without zoom, we need three input windows: * - SrcWnd = MPEG source window (ex: MPEG2 NTSC 0x0,720x480) * - AcqWnd = acquisition window requested by user. If no zoom AcqWnd == SrcWnd. * If zoom is required AcqWnd < SrcWnd. * - DstWnd = destination window requested by user. This will be limited by the screen resolution. * We need to send down to microcode two windows: * ..................................>+--------------------------------------------+ * ./ | | * ./ | ************************* | * / ...........................................>+----------------+ * | * +----/-----------------+ | * | | * | * | +--------+ | | * | | * | * | | | | | * | | * | * | | | | | * | | * | * | |AcqWnd | | | * | | * | * | +--------+ | | * | VisWnd = DstWnd| * | * | | | * +----------------+ * | * | | | * * | * | SrcWnd | | * * | * +----------------------+ | * VGA Monitor * | * | ************************* | * | | * | | * | FrameWnd | * +--------------------------------------------+ * * - VisWnd = the real coordinates starting from HSync/VSync in pixel/line unit * corresponding both to DstWnd and AcqWnd. * Because we are using a specific anolog overlay chip we need to apply some * horizontal and vertical offsets to DstWnd (XOffset, YOffset). We need also to * apply a correction factor for the horizontal coordinates because the pixel * clock doesn't perfectly match the VGA clock (Correction). * XOffset, YOffset, Correction should be determined through AutoCalibration procedure. * - FrameWnd = the real coordinates starting from HSync/VSync in pixel/line unit * corresponding to SrcWnd. The mathematical relation is: * FrmWnd = VisWnd * SrcWnd / AcqWnd. * CNE2000__UpdateScaledVideoWindow is using IDecoder_UpdateVideoWindow to send the * the VisWnd and FrameWnd to the hardware. This will update subpicture, highlights and OSD also. * Note. OSD is not scalable. It is the user responsability to modify the size of the bitmap. * PARAMETERS * IN IDecoderBoard* pIDecoderBoard - pointer to the board object * RETURN VALUE * The return value is FALSE only if: * - Enabled is FALSE * - DstWnd left/top are outside screen * - DstWnd right/bottom are negative or width/height are less than 8 * In this case the video will be hidden * SEE ALSO * IDecoderBoard_VGAUpdateVideoWindow/*****************************************************************************/BOOL CNE2000__UpdateScaledVideoWindow(IDecoderBoard* pIDecoderBoard){ CQuasarBoard *this = (CQuasarBoard*) pIDecoderBoard; WND FrameWnd, VisWnd, ValidWnd, OsdWnd; OsdWnd = this->OsdWnd; this->MaxDisplayWnd.x = 0; this->MaxDisplayWnd.y= 0; this->MaxDisplayWnd.w = this->DisplayResolution.iScreenWidth; this->MaxDisplayWnd.h = this->DisplayResolution.iScreenHeight; // use the user requested values FrameWnd.x = VisWnd.x = this->DstWnd.x; FrameWnd.y = VisWnd.y = this->DstWnd.y; FrameWnd.w = VisWnd.w = this->DstWnd.w >= 0 ? this->DstWnd.w : -this->DstWnd.w; FrameWnd.h = VisWnd.h = this->DstWnd.h >= 0 ? this->DstWnd.h : -this->DstWnd.h; this->RealDestWnd.x = 0; this->RealDestWnd.y = 0; this->RealDestWnd.w = this->DstWnd.w; this->RealDestWnd.h = this->DstWnd.h; if( this->NewOverlayFlags & VIDEO_VALID_ENABLE ) { // for time being don't check the screen limits ValidWnd.x = this->XOffset + OSDDiv(this->ValidWnd.x, 1000, this->Correction); ValidWnd.y = this->YOffset + this->ValidWnd.y; ValidWnd.w = OSDDiv(this->ValidWnd.w, 1000, this->Correction); ValidWnd.h = this->ValidWnd.h; } if( this->IsInterlaced ) { FrameWnd.y >>= 1; FrameWnd.h >>= 1; VisWnd.y >>= 1; VisWnd.h >>= 1; ValidWnd.y >>= 1; ValidWnd.h >>= 1; } if( !CQuasarBoard__LimitDestByScreen(&VisWnd, &OsdWnd, this->DisplayResolution.iScreenWidth, this->DisplayResolution.iScreenHeight) ) { QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT("UpdateScaledVideoWindow: outside screen-> MinimizeWnd & MpegModeNone") )); FrameWnd.x = max( 16, (this->XOffset - 8)); FrameWnd.y = max( 4, (this->YOffset - 8)); FrameWnd.w = 8; FrameWnd.h = 8; OsdWnd = FrameWnd; IDecoder_UpdateVideoWindow(this->m_pIDecoder, &FrameWnd, &FrameWnd, NULL, &OsdWnd, &this->OsdHiLiWnd, this->LetterBox); return FALSE; } QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" DestReq=%dx%d_%dx%d DestReqLimit=Vis=%dx%d_%dx%d Frame=%dx%d_%dx%d"), this->DstWnd.x, this->DstWnd.y, this->DstWnd.w, this->DstWnd.h, VisWnd.x, VisWnd.y, VisWnd.w, VisWnd.h, FrameWnd.x, FrameWnd.y, FrameWnd.w, FrameWnd.h )); // find out FrameWnd for the zoom asked if(this->OverlayFlags & VIDEO_ZOOM_ENABLE) { CQuasarBoard__ZoomCalc(pIDecoderBoard, &FrameWnd); QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" AfterZoom: Vis=%dx%d_%dx%d Frame=%dx%d_%dx%d"), VisWnd.x, VisWnd.y, VisWnd.w, VisWnd.h, FrameWnd.x, FrameWnd.y, FrameWnd.w, FrameWnd.h )); } // We need horizontal correction because in analog overlay 1 mpeg pixel != 1 vga pixel VisWnd.x = this->XOffset + OSDDiv(VisWnd.x, 1000, this->Correction); VisWnd.y = this->YOffset + VisWnd.y; VisWnd.w = OSDDiv(VisWnd.w, 1000, this->Correction); FrameWnd.x = this->XOffset + OSDDiv(FrameWnd.x, 1000, this->Correction); FrameWnd.y = this->YOffset + FrameWnd.y; FrameWnd.w = OSDDiv(FrameWnd.w, 1000, this->Correction); QDbgLog((QLOG_TRACE, QDebugLevelTrace, TEXT(" AfterCorr: C=%d X=%d Y=%d Vis=%dx%d_%dx%d Frame=%dx%d_%dx%d"), this->Correction, this->XOffset, this->YOffset, VisWnd.x, VisWnd.y, VisWnd.w, VisWnd.h, FrameWnd.x, FrameWnd.y, FrameWnd.w, FrameWnd.h )); if(this->OverlayFlags & OSD_VIDEO_INDEPENDENT_DEST) { OsdWnd.x = this->XOffset + OSDDiv(OsdWnd.x, 1000, this->Correction);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -