📄 directif.cpp
字号:
_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 + -