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

📄 cx24108_tuner.c

📁 QPSK Tuner details, for conexant chipset.
💻 C
📖 第 1 页 / 共 5 页
字号:
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 + -