📄 cx24108_tuner.c
字号:
void _TUNER_CX24108_calc_bp( /* calculates breakpoint values for nim's vco's */
NIM *nim) /* pointer to nim */
{
int i;
ULONG ulTemp;
ULONG ulTemp2;
LONG diff;
LONG bp;
/* build breakpoints for vcos: (1/2;2/3;3/4;4/5;5/6;6/7;7/8 )div2 -- count 7 */
for (i = 0 ; i < 7 ; i++)
{
ulTemp = (nim->tuner.cx24108.vco_edge[i].upperthresh/1000UL);
ulTemp2 = (nim->tuner.cx24108.vco_edge[i+1].lower/1000UL);
diff = ulTemp - ulTemp2;
bp = (diff * (LONG)nim->tuner.cx24108.vco_bp[i].percentage) / 100L;
nim->tuner.cx24108.vco_bp[i].breakpt = ((ULONG)bp * 1000UL);
nim->tuner.cx24108.vco_bp[i].breakpt += nim->tuner.cx24108.vco_edge[i+1].lower;
}
/* use 6/D2 breakpoint div by two, for D/4 breakpoint */
i = 7;
nim->tuner.cx24108.vco_bp[i].breakpt = (nim->tuner.cx24108.vco_bp[5].breakpt/2UL);
/* use 7/D2 breakpoint div by two, for D/4 breakpoint */
i = 8;
nim->tuner.cx24108.vco_bp[i].breakpt = (nim->tuner.cx24108.vco_bp[6].breakpt/2UL);
/* manually build breakpoint for vco 8/0 div4 -- count 1 */
i = CX24108_BPCNT-1;
ulTemp = (nim->tuner.cx24108.vco_edge[i+1].upperthresh/1000UL);
ulTemp2 = (nim->tuner.cx24108.vco_edge[0].lower/1000UL);
if (ulTemp2 < (ULONG)(1075UL*M)) ulTemp2 = (ULONG)(1075UL*M);
diff = ulTemp - ulTemp2;
bp = (diff * (LONG)nim->tuner.cx24108.vco_bp[i].percentage) / 100L;
nim->tuner.cx24108.vco_bp[i].breakpt = ((ULONG)bp * 1000UL);
nim->tuner.cx24108.vco_bp[i].breakpt += (nim->tuner.cx24108.vco_edge[0].lower);
return;
} /* _TUNER_CX24108_calc_bp() */
/*******************************************************************************************************/
/* _TUNER_CX24108_adjust() */
/*******************************************************************************************************/
void _TUNER_CX24108_adjust( /* adjusts VCO table, disallows vco below 2150 MHz */
NIM *nim) /* nim pointer */
{
if (nim == (NIM*)NULL) return;
/* adjust lower edge of vco 0 -- disallow use of this vco if freq is below 1075 */
/* REMOVED per CR 7878 */
/* if (nim->tuner.cx24108.vco_edge[0].lower < (ULONG)(1075UL*MM)) */
/* nim->tuner.cx24108.vco_edge[0].lower = (ULONG)(1075UL*MM); */
return;
} /* _TUNER_CX24108_adjust() */
/*******************************************************************************************************/
/* _TUNER_CX24108_hardware_vcoedges() */
/*******************************************************************************************************/
BOOL _TUNER_CX24108_hardware_vcoedges(/* calculates vco edges via bs-like algo */
NIM *nim) /* pointer to nim */
{
int vcoidx;
int CPCCurrent;
ULONG low_edge;
ULONG high_edge;
ULONG first_edge; /* returned from low edge detection */
/* set the default settings */
_TUNER_CX24108_initialize(nim);
/* save the current CPC setting to be restored after edge detection is done */
CPCCurrent = nim->tuner.cx24108.CPCCurrent;
/* step through each vco using index. stop after last vco (VCO8D4) is processed */
for (vcoidx = 0 ; vcoidx < (VCO8D2+1) ; vcoidx++) /* (CR 7453) was VCO8DIV4) */
{
/* grab the low-edge */
low_edge = _TUNER_CX24108_hardware_vcoedge_low(nim,vcoidx,&first_edge);
nim->frequency = 0UL;
/* nim->tuner.cx24108.vco_edge[vcoidx].lower = 0UL;*/ /* cr 7452 */
if (low_edge != 0UL) nim->tuner.cx24108.vco_edge[vcoidx].lower = low_edge;
if (low_edge == 0UL) return(False);
/* grab the high-edge */
high_edge = _TUNER_CX24108_hardware_vcoedge_high(nim,vcoidx,low_edge,first_edge,nim->tuner.cx24108.vco_len[vcoidx]);
nim->frequency = 0UL;
/* nim->tuner.cx24108.vco_edge[vcoidx].upperthresh = 0UL;*/ /* cr 7452 */
if (high_edge != 0UL) nim->tuner.cx24108.vco_edge[vcoidx].upperthresh = high_edge;
if (high_edge == 0UL) return(False);
}
/* restore the CPC setting */
nim->tuner.cx24108.CPCCurrent = CPCCurrent;
/* (CR 7453) vco edges calculated for DIV2 are valid for DIV4 edges */
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 = (nim->tuner.cx24108.vco_edge[VCO8D2].lower/2UL);
nim->tuner.cx24108.vco_edge[VCO8D4].upperthresh = (nim->tuner.cx24108.vco_edge[VCO8D2].upperthresh/2UL);
/* re-cal bp after vco edges detected */
_TUNER_CX24108_calc_bp(nim);
/* adjust pre-set vco's if below 2150/2 */
_TUNER_CX24108_adjust(nim);
return(True);
} /* _TUNER_CX24108_hardware_vcoedges() */
/*******************************************************************************************************/
/* _TUNER_CX24108_hardware_vcoedge_low() */
/*******************************************************************************************************/
ULONG _TUNER_CX24108_hardware_vcoedge_low( /* find vco's low edge */
NIM *nim, /* nim pointer */
int vcoidx, /* vco idx number to find edge of */
ULONG *first_edge) /* returns computed "middle" of detected vco */
{
int done = False;
int counter;
int pllerrcnt = 0;
int loopcnt = 0;
ULONG mid_pt;
ULONG lowest_pt;
ULONG test_pt;
ULONG ulTemp; /* unused: holds return state only */
BOOL locked;
BOOL fm;
mid_pt = (nim->tuner.cx24108.vco_edge[vcoidx].upperthresh - nim->tuner.cx24108.vco_edge[vcoidx].lower)/2UL;
mid_pt += nim->tuner.cx24108.vco_edge[vcoidx].lower;
/* use 2mA CPC current for low edge detection */
nim->tuner.cx24108.CPCCurrent = CX24108_CPC_LOW;
/* find the "mid-point" of vco to test edge of. (This MUST lock!) (CR 7452 changed below line to return 1 on fail) */
if (_TUNER_CX24108_first_edgelock(nim,&mid_pt,&locked,(VCOSET)vcoidx) == False) return(TUNER_VCOERROR_ONE);
*first_edge = mid_pt;
/* we've locked first time into the "middle" of a good band, so start the search */
lowest_pt = mid_pt;
while ((locked == True) && (loopcnt < CX24108_MAX_LOOP))
{
loopcnt++;
/* adjust lowest pt. with big jumps, set freq, get lock status */
/* when lock is lost, this is max bounds */
lowest_pt -= (CX24108_NOMSTEP*CX24108_EDGESTEP);
fm = _TUNER_CX24108_freq_manual(nim,lowest_pt);
ulTemp = _TUNER_CX24108_vcoband_manual(nim,vcoidx);
if (_TUNER_CX24108_pll_status(nim,&locked) == False) pllerrcnt++;
}
/* Check if hardware is stuck. */
if (loopcnt == CX24108_MAX_LOOP)
{
return(TUNER_VCOERROR_ZERO);
}
/* recalc mid-pt */
mid_pt = lowest_pt + (CX24108_NOMSTEP*CX24108_EDGESTEP);
/* mid_pt is highest last known lock position; lowest_pt is past known boundary, so we have binary search bounds */
/* so perform bin search to catch edge */
done = False;
counter = 0;
while (done == False)
{
test_pt = mid_pt - ((mid_pt-lowest_pt)/2UL);
fm = _TUNER_CX24108_freq_manual(nim,test_pt);
ulTemp = _TUNER_CX24108_vcoband_manual(nim,vcoidx);
if (_TUNER_CX24108_pll_status(nim,&locked) == False) pllerrcnt++;
if (locked == True) mid_pt = test_pt;
else lowest_pt = test_pt;
/* bail if we're within the ballpark of the edge */
if ((mid_pt-lowest_pt) < CX24108_MINHILOWDIST) return(mid_pt);
counter++;
if (counter > CX24108_MAX_EDGEDIV) done = True;
}
/* not successful finding middle-point of band (i.e. could not start) */
return(TUNER_VCOERROR_ZERO);
} /* _TUNER_CX24108_hardware_vcoedge_low() */
/*******************************************************************************************************/
/* _TUNER_CX24108_hardware_vcoedge_high() */
/*******************************************************************************************************/
ULONG _TUNER_CX24108_hardware_vcoedge_high( /* find vco's low edge */
NIM *nim, /* nim pointer */
int vcoidx, /* vco idx number to find edge of */
ULONG low_edge, /* low-edge found (used in high-edge start calc) */
ULONG first_edge, /* first-edge found when low-edge detected (used in high-edge calc) */
ULONG vco_len) /* estimated length of this vco */
{
int done = False;
int counter;
int pllerrcnt = 0;
int loopcnt = 0;
ULONG mid_pt;
ULONG highest_pt;
ULONG test_pt;
ULONG ulTemp; /* unused: holds return state only */
BOOL locked = True;
BOOL fm;
/* if neither potential edge is valid, we have a serious error. (save and bail) */
if ((low_edge <= MAX_TUNER_VCOERROR && first_edge <= MAX_TUNER_VCOERROR) /* || (vco_len < 0) */) return(TUNER_VCOERROR_TWO);
/* use 3mA CPC current for high edge detection */
nim->tuner.cx24108.CPCCurrent = CX24108_CPC_HIGH;
/* Use a known good start point to do the high edge search. */
mid_pt = first_edge;
/* we've locked first time into the middle of a good band, so start the search */
highest_pt = mid_pt;
while ((locked == True) && (loopcnt < CX24108_MAX_LOOP))
{
loopcnt++;
/* adjust highest pt., set freq, get lock status */
highest_pt += (CX24108_NOMSTEP*CX24108_EDGESTEP);
fm = _TUNER_CX24108_freq_manual(nim,highest_pt);
ulTemp = _TUNER_CX24108_vcoband_manual(nim,vcoidx);
if (_TUNER_CX24108_pll_status(nim,&locked) == False) pllerrcnt++;
}
/* Check if hardware is stuck. */
if (loopcnt == CX24108_MAX_LOOP)
{
return(TUNER_VCOERROR_ZERO);
}
/* recalc mid-pt (so edge is between mid_pt and highest_pt) */
mid_pt = highest_pt - (CX24108_NOMSTEP*CX24108_EDGESTEP);
/* now we have our binary search bounds, so perform bin search to catch edge */
done = False;
counter = 0;
while (done == False)
{
test_pt = mid_pt + ((highest_pt-mid_pt)/2UL);
fm = _TUNER_CX24108_freq_manual(nim,test_pt);
ulTemp = _TUNER_CX24108_vcoband_manual(nim,vcoidx);
if (_TUNER_CX24108_pll_status(nim,&locked) == False) pllerrcnt++;
if (locked == True) mid_pt = test_pt;
else highest_pt = test_pt;
/* bail if we're within the ballpark of the edge */
if ((highest_pt-mid_pt) < CX24108_MINHILOWDIST)
{
done = True;
return(mid_pt);
}
counter++;
if (counter > CX24108_MAX_EDGEDIV) done = True;
}
/* not successful finding middle-point of band (i.e. could not start) */
return(TUNER_VCOERROR_ZERO);
} /* _TUNER_CX24108_hardware_vcoedge_high() */
/*******************************************************************************************************/
/* _TUNER_CX24108_vcoband_manual() */
/*******************************************************************************************************/
ULONG _TUNER_CX24108_vcoband_manual( /* function to manually set the tuner band selection programming bits */
NIM *nim, /* pointer to nim */
int vcoband) /* vco number (0..10) to set tuner to */
{
int err = 0;
ULONG ulRegVal;
DWORD vcodivbin;
DWORD bandbin;
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 */
/* disallow invalid band setting */
if (vcoband >= CX24108_VCOEDGES) return(0UL);
vcodivbin = (DWORD)_vcodivbin[_vcodiv[vcoband]];
bandbin = _bandbin[vcoband];
ulRegVal = vcodivbin;
ulRegVal <<= 9;
ulRegVal |= bandbin;
if (_TUNER_CX24108_io(nim,CX24108_BAND_PROG,ulRegVal) == False) err++;
return(ulRegVal);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -