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

📄 directif.cpp

📁 完整的基于Conxant平台的USB电视棒的WIN驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            _p_registers->RegMaskWrite( 32, DIF_AV_SEP_CTRL, 0, 31,   0x3F3530ec);
            _p_registers->RegMaskWrite( 32, DIF_COMP_FLT_CTRL, 0, 31,  0x00000000);
            _p_registers->RegMaskWrite( 32, DIF_SRC_PHASE_INC, 0, 31,  0x1befbf06);
            _p_registers->RegMaskWrite( 32, DIF_SRC_GAIN_CONTROL, 0, 31,  0x000035e8);
            _p_registers->RegMaskWrite( 32, DIF_RPT_VARIANCE, 0, 31,  0x00000000);   
            _p_registers->RegMaskWrite( 32, DIF_VIDEO_AGC_CTRL, 0, 31,  0xfc800000);
            
            // Save the Spec Inversion value
            dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
            dif_misc_ctrl_value |=0x3a023F11;
        break;

        default:
        case KS_AnalogVideo_NTSC_M:
        case KS_AnalogVideo_NTSC_M_J:

            // DIF Settings as per KY
            // These need to be different from Corona
            // For NTSC the centre frequency of video coming out of sidewinder is
            // around 7.1MHz or 3.6MHz depending on the spectral inversion.
            // so for a non spectrally inverted channel the pll freq word is 0x03420c49

            _p_registers->writeDword(DIF_PLL_CTRL,          0x6503BC0C);
            _p_registers->writeDword(DIF_PLL_CTRL1,         0xBD038C85);
            _p_registers->writeDword(DIF_PLL_CTRL2,         0x1DB4640A);
            _p_registers->writeDword(DIF_PLL_CTRL3,         0x00008800);
            _p_registers->writeDword(DIF_AGC_IF_REF,        0x44400570);
            _p_registers->writeDword(DIF_AGC_IF_INT_CURRENT,0x26001700);
            _p_registers->writeDword(DIF_AGC_RF_CURRENT,    0x00002660);
            _p_registers->writeDword(DIF_VIDEO_AGC_CTRL,    0x0c800800);
            _p_registers->writeDword(DIF_VID_AUD_OVERRIDE,  0x27000100);
            _p_registers->writeDword(DIF_AV_SEP_CTRL,       0x01296e1f);

            _p_registers->writeDword(DIF_COMP_FLT_CTRL,     0x009f50c1);
            _p_registers->writeDword(DIF_SRC_PHASE_INC,     0x1befbf06);
            _p_registers->writeDword(DIF_SRC_GAIN_CONTROL,  0x000035e8);
            
            _p_registers->writeDword(DIF_AGC_CTRL_IF,       0xDA202600);
            _p_registers->writeDword(DIF_AGC_CTRL_INT,      0xDA261700);
            _p_registers->writeDword(DIF_AGC_CTRL_RF,       0xDA262600);
            
            // Save the Spec Inversion value
            dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
            dif_misc_ctrl_value |= 0x3a000000;
        break;
    }
    // As per KY Aug 01 2007 
    //The AGC values should be the same for all standards, these values 
    // are however different to what is present in corona.
    //Test code commented out/ working for NTSC when uncommented.

    // AUD_SRC_SEL[19] should always be disabled    
    dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL;

    // It is still possible to get Set Standard calls even when we are in FM mode
    // This is done to override the value for FM.
    if (_mode == KSPROPERTY_TUNER_MODE_FM_RADIO)
        dif_misc_ctrl_value = 0x7a080000;
    
    //Write the calculated value for misc ontrol register
    _p_registers->writeDword(DIF_MISC_CTRL, dif_misc_ctrl_value);
}


//
// Correct DIF frequency offset
//
// Using the DIF, we can auto-center the frequency, then return zero offset
//
void DirectIF::correctSignalOffset()
{
    DWORD offset,pll_freq_word;

    BOOL bGotGoodOffset;
    BOOL bSubtractOffset;
    DWORD count;
    DWORD bad_count;

    // Need to sign extend
    _p_registers->readDword(DIF_PLL_FREQ_WORD, &pll_freq_word);

    count = 3;
    bGotGoodOffset = FALSE;

    while ((!bGotGoodOffset) && count--)
    {
        bSubtractOffset = FALSE;

        // Read and mask the frequency offset register from the DIF
        _p_registers->readDword(DIF_PLL_FREQ_ERR, &offset);
        offset &= FLD_DIF_CTL_IP;

        DbgLog(("DirectIF::getSignalOffset raw = %08lx\n",offset));

        // Negative value
        if (offset & 0x01000000)
        {
             // Convert to positive value
            offset ^=  0x01FFFFFF;
            offset += 1;
            bSubtractOffset = TRUE;
            DbgLog(("DirectIF::getSignalOffset negative signed = - %d\n",offset));

        }
        else
        {
            DbgLog(("DirectIF::getSignalOffset positive signed = %d\n",offset));
        }

        // This test value is arbitrary
        if (offset < 1048576)
        {            
            bGotGoodOffset = TRUE;
        }
        else
        {
            // Wait a millisecond and try again
            DbgLog(("DirectIF::getSignalOffset got out of range offset, pause and try again\n"));

            pauseThread(1);
        }
    }

    if (bGotGoodOffset)
    {
        if (bSubtractOffset)
        {
            pll_freq_word -= offset;
        }
        else
        {
            pll_freq_word += offset;
        }

        _p_registers->writeDword(DIF_PLL_FREQ_WORD,  pll_freq_word);
    }
    else
    {
        DbgLog(("DirectIF::getSignalOffset never got valid offset\n"));
    }

}

//
// VOID static_setDIFbandpass(DirectIF *p_DIF,DWORD if_freq, BOOL spectral_invert)
//
// Sets the DIF bandpass filter based on IF frequency
// Rounds to nearest 100 KHz value
// Valid if_freq is from 3 to 16 MHz
//
void DirectIF::static_setDIFbandpass(void *p_DIF,DWORD if_freq, BOOL spectral_invert, ULONG mode)
{
    ASSERT(p_DIF);

    if(p_DIF)
    {
        ((DirectIF *)p_DIF)->setDIFbandpass(if_freq, spectral_invert, mode);
    }
}

//
// VOID static_Gen_Si_Tuner_Callback(void *p_DIF,DWORD COMMAND, void* CALLBACK_CONTEXT)
// This function facilitates callbacks back to DIF/capture driver. Command are enumerated 
// constants defined in GEN_SI_TUNER_CALLBACK_COMMANDS. CALLBACK_CONTEXT is  a pointer
// to the argument that is sent with the call back function.
//
void DirectIF::static_Gen_Si_Tuner_Callback(void *p_Colibri,DWORD COMMAND, void* CALLBACK_CONTEXT)
{
    ASSERT(p_Colibri);
    void* p_DIF = ((Colibri*)p_Colibri)->getDIF();

    switch(COMMAND)
    {
    case CALCULATE_AVERAGE_SNR:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback CALCULATE_AVERAGE_SNR\n"));
            ((DirectIF *)p_DIF)->CalculateAverageSNR((ULONG*)CALLBACK_CONTEXT);
        }
        break;
    case FREEZE_DIF_AGC_FOR_MAXIMUM_SENSTIVITY:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback FREEZE_DIF_AGC_FOR_MAXIMUM_SENSTIVITY\n"));
            ((DirectIF *)p_DIF)->FreezeAgcForMaxSenstivity();
        }
        break;
    case FREEZE_DIF_AGC_FOR_NORMAL_SENSTIVITY:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback FREEZE_DIF_AGC_FOR_NORMAL_SENSTIVITY\n"));
            ((DirectIF *)p_DIF)->FreezeAgcForNormalSenstivity();
        }
        break;
    case SET_DIF_IF_AGC_STATE:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback SET_DIF_IF_AGC_STATE\n"));
            ((DirectIF *)p_DIF)->setIFAgcState((ULONG*)CALLBACK_CONTEXT);
        }
        break;
    case SET_DIF_RF_AGC_STATE:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback SET_DIF_RF_AGC_STATE\n"));
            ((DirectIF *)p_DIF)->setRFAgcState((ULONG*)CALLBACK_CONTEXT);
        }
        break;
    case DISABLE_DIF_AGC:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback DISABLE_DIF_AGC\n"));
            ((DirectIF *)p_DIF)->DisableAgc();
        }
        break;
    case ENABLE_DIF_AGC:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback ENABLE_DIF_AGC\n"));
            ((DirectIF *)p_DIF)->EnableAgc();
        }
        break;
    case RESET_DIF_AGC:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback RESET_DIF_AGC\n"));
            ((DirectIF *)p_DIF)->ResetAgc();
        }
        break;
    case GET_AGC_ALGORITHM_ENABLE_STATE:
        {
            DbgLogInfo(("DirectIF::static_Gen_Si_Tuner_Callback GET_AGC_ALGORITHM_ENABLE_STATE\n"));
            ((DirectIF *)p_DIF)->GetAgcAlgorithmEnableState((BOOL*)CALLBACK_CONTEXT);
        }
        break;
    }
}

// VOID DirectIF::CalculateAverageSNR(ULONG* p_snr)
// Computes an approximation of SNR by averaging the repeat variance
// the read sample is valid only if the value is less than 131071
VOID DirectIF::CalculateAverageSNR(ULONG* p_snr)
{    
	INT     counter;
	INT     timeout = 0;
	DWORD   sum = 0;
    DWORD   rep_variance = 0;
	DWORD   avg = 0;
    
    //read and compute video SNR from rpt_variance register
	for(counter = 0; counter < 256; counter++) 
	{		
        _p_registers->readDword(DIF_RPT_VARIANCE, &rep_variance);
		timeout++; 
		
        // the value is ignored if it is greater than 131071
        // At this time the counters are decremented.
		if (rep_variance < 131071) // 131071 is a number from scripts as per KY
			 sum = sum + rep_variance; 
		else
			 counter--;
			 
		if(timeout == 1000)// 1000 is a random number from scripts as per KY
		{	
			DbgLogInfo(("DirectIF::CalculateAverageSNR SNR too low to measure rep_variance(%d) count(%d)\n",rep_variance,counter)); 
            avg = 150000;
			break;
		} 
	}
	// if sum is valid
	if (timeout != 1000)
		avg = sum/counter;
    
    DbgLogInfo(("DirectIF::CalculateAverageSNR AVG = (%d)\n",avg));
    *p_snr = avg;
}

VOID DirectIF::FreezeAgcForMaxSenstivity()
{
    DWORD rf_agc = 0;

⌨️ 快捷键说明

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