📄 cx24108_tuner.c
字号:
/* init the tuner vco_edge struct for div4 values: vc06/d4, vc07/d4, vc08/d4 */
nim->tuner.cx24108.vco_edge[VCO6D4].lower = nim->tuner.cx24108.vco_edge[VCO6D2].lower/2UL;
nim->tuner.cx24108.vco_edge[VCO6D4].upperthresh = nim->tuner.cx24108.vco_edge[VCO6D2].upperthresh/2UL;
nim->tuner.cx24108.vco_edge[VCO7D4].lower = nim->tuner.cx24108.vco_edge[VCO7D2].lower/2UL;
nim->tuner.cx24108.vco_edge[VCO7D4].upperthresh = nim->tuner.cx24108.vco_edge[VCO7D2].upperthresh/2UL;
nim->tuner.cx24108.vco_edge[VCO8D4].lower = max((1019UL*M),(nim->tuner.cx24108.vco_edge[VCO8D2].lower/2UL));
nim->tuner.cx24108.vco_edge[VCO8D4].upperthresh = max((1075UL*M),(nim->tuner.cx24108.vco_edge[VCO8D2].upperthresh/2UL));
/* set all frequencies into Hz from khz */
for (i = (int)VCO1D2 ; i < (int)VCO8D4+1 ; i++)
{
nim->tuner.cx24108.vco_edge[i].lower *= M;
nim->tuner.cx24108.vco_edge[i].upperthresh *= M;
/* determine the estimated vco lengths, used in vco high-edge calculations (these vco lengths should hold ~ True) */
nim->tuner.cx24108.vco_len[i] = (nim->tuner.cx24108.vco_edge[i].upperthresh - nim->tuner.cx24108.vco_edge[i].lower);
}
/* adjust pre-set vco's if below 2150/2 */
_TUNER_CX24108_adjust(nim);
/* init the tuner breakpoint structure */
for (i = 0 ; i < CX24108_BPCNT ; i++)
nim->tuner.cx24108.vco_bp[i].percentage = (int)nim->tuner.cx24108.BPPercentage;
/* recalculate breakpoints */
_TUNER_CX24108_calc_bp(nim);
/* configure the tuner I/O interface with default settings */
_TUNER_CX24108_defaultsettings(nim);
return;
} /* _TUNER_CX24108_initialize() */
#endif
/*******************************************************************************************************/
/* _TUNER_CX24108_setgainparms() */
/*******************************************************************************************************/
BOOL _TUNER_CX24108_setgainparms( /* copies caller's TUNERPARMS struct into nim */
NIM *nim, /* nim pointer */
TUNERPARMS *tunerparms) /* caller's TUNERPARMS struct that will overwrite nim's struct */
{
/* copy caller's tunerparms settings into nim */
if (tunerparms != NULL)
{
memcpy(&nim->tuner.cx24108.tunerparms,tunerparms,sizeof(TUNERPARMS));
return(True);
}
DRIVER_SetError(nim,API_BAD_PARM);
return(False);
} /* _Tuner_CX24108_setgainparms() */
/*******************************************************************************************************/
/* _TUNER_CX24108_band_info() */
/*******************************************************************************************************/
BOOL _TUNER_CX24108_band_info( /* function to calc and return band-select prog bits to caller */
NIM *nim, /* pointer to nim */
ULONG Fr, /* Fr (Freq. Receive) input */
DWORD *bandbin, /* binary bits to program band-select for Fr */
DWORD *vcodivbin, /* binary bit to program vco divider in band-select for Fr */
VCOSET *vcoset, /* vco chosen for Fr */
VCODIV *vcodiv, /* vco divider chosen for Fr */
VCONO *vcono, /* vco number chosen (always 1..8) */
ULONG *tunpll) /* calculated generic tuner pll programming setting */
{
int i;
int j;
int start_pt;
ULONG vco_len;
ULONG srm;
static VCONO _vcono[] = {(UCHAR)VCO1D2,(UCHAR)VCO2D2,(UCHAR)VCO3D2,(UCHAR)VCO4D2,(UCHAR)VCO5D2,(UCHAR)VCO6D2,
(UCHAR)VCO7D2,(UCHAR)VCO8D2,(UCHAR)VCO6D2,(UCHAR)VCO7D2,(UCHAR)VCO8D2};
static VCONO _vcosearchorder[] =
{(UCHAR)VCO1D2,(UCHAR)VCO2D2,(UCHAR)VCO3D2,(UCHAR)VCO4D2,
(UCHAR)VCO5D2,(UCHAR)VCO6D2,(UCHAR)VCO7D2,(UCHAR)VCO8D2,
(UCHAR)VCO8D4,(UCHAR)VCO7D4,(UCHAR)VCO6D4};
static VCOSET _vcoset[] = {VCO1D2,VCO2D2,VCO3D2,VCO4D2,VCO5D2,VCO6D2,VCO7D2,VCO8D2,VCO6D4,VCO7D4,VCO8D4};
static VCODIV _vcodiv[] = {VCODIV2,VCODIV2,VCODIV2,VCODIV2,VCODIV2,VCODIV2,VCODIV2,VCODIV2,VCODIV4,VCODIV4,VCODIV4};
static DWORD _bandbin[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x20,0x40,0x80};
static int _vcodivbin[] = {-1,-1,1,-1,0}; /* 2=0x01, 4=0x00 */
/* set the starting search pt. If div/4, then start at the div/4 vcos */
start_pt = CX24108_START_DIV2;
if (nim->tuner.cx24108.vcodiv == VCODIV4) start_pt = CX24108_START_DIV4;
/* step through each VCO, examine for a valid VCO edge, if edge is not valid, generate a warning */
for (j = 0 ; j < CX24108_VCOEDGES ; j++)
{
ULONG Fl = nim->tuner.cx24108.vco_edge[j].lower;
ULONG Fh = nim->tuner.cx24108.vco_edge[j].upperthresh;
if (Fl <= MAX_TUNER_VCOERROR || Fh <= MAX_TUNER_VCOERROR)
{
/* an invalid VCO edge was detected, flag as warning, then continue */
DRIVER_SetError(nim,API_TUNERVCO);
}
}
/* match Fr to vco edges, using high and low breakpoints, not actual edges */
for (j = start_pt ; j < CX24108_VCOEDGES ; j++)
{
/* find a VCO by looking into 1/2 .. 8/2, then 8/4, 8/4, 6/4 vcos */
i = _vcosearchorder[j]; /* remove this line if vco search s/b 1/2..8/2,6/4..8/4 */
if (_TUNER_CX24108_vco_range(nim,Fr,i) == True)
{
int idx;
/* grab vcoset, vcodiv, return to caller */
*vcono = (VCONO)(_vcono[i]+1); /* returns VCO number before divider is set */
*vcoset = _vcoset[i]; /* returns actual VCOSET enum value */
*vcodiv = _vcodiv[i]; /* vco divider */
*bandbin = _bandbin[i]; /* band sel prog'd directly to cx24108 */
*vcodivbin = (DWORD)_vcodivbin[*vcodiv]; /* vcodiv prog'd directly to cx24108 */
*tunpll = 0UL;
/* compute current vco length */
vco_len = nim->tuner.cx24108.vco_edge[i].upperthresh - nim->tuner.cx24108.vco_edge[i].lower;
/* set cpc default current to mid level */
nim->tuner.cx24108.CPCCurrent = (int)nim->tuner.cx24108.tunerparms.CPC[_vcono[*vcoset]].mid;
/* is fr in lower percentage area (defined by tunerparms.low percentage)? */
if (Fr < (nim->tuner.cx24108.vco_edge[i].lower+
((vco_len/100UL)*nim->tuner.cx24108.tunerparms.CPC[_vcono[*vcoset]].LowPercentage)))
{
nim->tuner.cx24108.CPCCurrent = (int)nim->tuner.cx24108.tunerparms.CPC[_vcono[*vcoset]].low;
}
else
{
if (Fr >= (nim->tuner.cx24108.vco_edge[i].lower+
((vco_len/100UL)*nim->tuner.cx24108.tunerparms.CPC[_vcono[*vcoset]].HighPercentage)))
{
nim->tuner.cx24108.CPCCurrent = (int)nim->tuner.cx24108.tunerparms.CPC[_vcono[*vcoset]].high;
}
}
/* save tuner slope data into rosie (current settings) */
idx = 0;
srm = MM;
if (nim->symbol_rate < MM) srm = M;
if (nim->symbol_rate >= (1UL*srm) && nim->symbol_rate <= (5UL*srm)) idx = CX24108_MSPS_1_TO_5;
else if (nim->symbol_rate >= (5UL*srm) && nim->symbol_rate <= (15UL*srm)) idx = CX24108_MSPS_5_TO_15;
else if (nim->symbol_rate >= (15UL*srm) && nim->symbol_rate <= (45UL*srm)) idx = CX24108_MSPS_15_TO_45;
nim->tuner.cx24108.VCASlope = nim->tuner.cx24108.tunerparms.SLP[idx].VCASlope;
nim->tuner.cx24108.VCAOffset = nim->tuner.cx24108.tunerparms.SLP[idx].VCAOffset;
nim->tuner.cx24108.VGA1Offset = nim->tuner.cx24108.tunerparms.SLP[idx].VGA1Offset;
nim->tuner.cx24108.VGA2Offset = nim->tuner.cx24108.tunerparms.SLP[idx].VGA2Offset;
return(True);
}
}
/* this error number is set if a valid freq can not be found within the present VCO edges. */
/* (default VCO edges might have been used) */
DRIVER_SetError(nim,API_TUNERVCO);
return(False);
} /* _TUNER_CX24108_band_info() */
/*******************************************************************************************************/
/* _TUNER_CX24108_vco_range() */
/*******************************************************************************************************/
BOOL _TUNER_CX24108_vco_range( /* function to test if Freq. requested is within vcoidx bounds */
NIM *nim, /* pointer to nim */
ULONG Fr, /* frequency requested */
int vcoidx) /* vco index */
{
ULONG Ft; /* Freq-test */
ULONG Fl = nim->tuner.cx24108.vco_edge[vcoidx].lower;
ULONG Fh = nim->tuner.cx24108.vco_edge[vcoidx].upperthresh;
if (Fr >= Fl && Fr <= Fh)
{
/* test Fr against valid low range */
Ft = _TUNER_CX24108_vco_low(nim,vcoidx);
if (Fr < Ft) return(False);
Ft = _TUNER_CX24108_vco_high(nim,vcoidx);
if (Fr > Ft) return(False);
return(True);
}
return(False);
} /* _TUNER_CX24108_vco_range() */
/*******************************************************************************************************/
/* _TUNER_CX24108_vco_low() */
/*******************************************************************************************************/
ULONG _TUNER_CX24108_vco_low( /* function to return Fr low range based on vcoidx */
NIM *nim, /* pointer to nim */
int vcoidx) /* vco index */
{
if (vcoidx >= 0)
{
switch(vcoidx)
{
case 0:
{
return(nim->tuner.cx24108.vco_bp[CX24108_BPCNT-1].breakpt);
break;
}
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
{
return(nim->tuner.cx24108.vco_bp[vcoidx-1].breakpt);
break;
}
case 8:
{
return(nim->tuner.cx24108.vco_edge[vcoidx].lower);
break;
}
case 9:
{
/* no other BP's to test, so return lowest freq tested */
return(nim->tuner.cx24108.vco_bp[7].breakpt);
break;
}
case 10:
{
return(nim->tuner.cx24108.vco_bp[8].breakpt);
break;
}
default:
{
break;
}
} /* switch(... */
}
return(0UL);
} /* _TUNER_vco_low() */
/*******************************************************************************************************/
/* _TUNER_CX24108_vco_high() */
/*******************************************************************************************************/
ULONG _TUNER_CX24108_vco_high(/* function to return Fr high range based on vcoidx */
NIM *nim, /* pointer to nim */
int vcoidx) /* vco index */
{
if (vcoidx >= 0)
{
switch(vcoidx)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
{
return(nim->tuner.cx24108.vco_bp[vcoidx].breakpt);
break;
}
case 7:
{
return(nim->tuner.cx24108.vco_edge[vcoidx].upperthresh);
break;
}
case 8:
{
/* (CR 7452) should return the current break pt. */
return(nim->tuner.cx24108.vco_bp[7].breakpt);
break;
}
case 9:
{
/* no other BP's to test, so return lowest freq tested */
return(nim->tuner.cx24108.vco_bp[8].breakpt);
break;
}
case 10:
{
return(nim->tuner.cx24108.vco_edge[vcoidx].upperthresh);
break;
}
default:
{
break;
}
} /* switch(... */
}
return(0UL);
} /* _TUNER_vco_high() */
/*******************************************************************************************************/
/* _TUNER_CX24108_calc_bp() */
/*******************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -