📄 snimdriv.c
字号:
else if (SNIM_MCLK_SYMB!=iClock)
{/* Settings above do not need changing*/
bOk = FALSE;
}
}
if (bOk)
{ /* write the two registers */
bOk = Snim_RegisterWrite(hSnim,SNIM_OP_CTRL,&OPcontrol,1)
&& Snim_RegisterWrite(hSnim,SNIM_FEC_SETUP,&FECsetup,1);
}
if (bOk && SNIM_ID_ZL10313==hSnim->ucChipID)
{ /*for ZL10313, write the extra 0 register as well*/
bOk = Snim_WriteExtra(hSnim,ZL313_CTRL_SELEXTRA_MPEG ,ucXtra);
}
return bOk;
}
/************************Zarlink Semiconductor*********************************
* Name: Snim_GetMpegClock()
* Purpose:returns the current MPEG clock setting
* Remarks: valid possibilities:
* hSnim->ucChipID MAN_MOCLK DIS_SR(MT312 only)
* ZL10312 0 X symbol rate
* ZL10312 1 X Pll derived
* MT312/ZL10313 0 0 symbol rate
* MT312/ZL10313 1 0 pll derived
* MT312/ZL10313 1 1 external
* Inputs:
*
* Outputs:current setting
*
********************************************************************************/
Sint32T Snim_GetMpegClock(PSSNIMCTL hSnim)
{
/* moclk ratio = (PLL frequency/moclckkHz ) -6*/
Uint8T OPcontrol=0,FECsetup=0,FECstaten=0,SysClock=0;
Sint32T lTemp = SNIM_MCLK_ERROR;
if (Snim_RegisterRead(hSnim,SNIM_SYS_CLK,&SysClock,1)
&& Snim_RegisterRead(hSnim,SNIM_OP_CTRL,&OPcontrol,1)
&& Snim_RegisterRead(hSnim,SNIM_FEC_SETUP,&FECsetup,1)
&& Snim_RegisterRead(hSnim,SNIM_FEC_STAT_EN,&FECstaten,1))
{
if (!(OPcontrol & SNIM_OP_CTRL_MANMOCLK))
{ /* symbol rate derived clock*/
if ((hSnim->ucChipID==SNIM_ID_MT312||hSnim->ucChipID==SNIM_ID_ZL10313) && (FECsetup & SNIM_FEC_SETUP_DIS_SR))
{ /* except MT312/ZL10313 with DIS_SR set */
lTemp = SNIM_MCLK_ERROR;
}
else
lTemp = SNIM_MCLK_SYMB;
}
else
{ /*pll derived clock */
if ((hSnim->ucChipID==SNIM_ID_MT312||hSnim->ucChipID==SNIM_ID_ZL10313) && (FECsetup & SNIM_FEC_SETUP_DIS_SR))
{ /* except MT312/ZL10313 with DIS_SR set = external clock */
lTemp = SNIM_MCLK_EXT;
}
else
{ /* calculate the clock frequency*/
lTemp = SysClock;
lTemp *= 5000;
lTemp/= ((FECstaten >>4) +6);
lTemp +=5;
lTemp /=10;
}
}
}
return lTemp;
}
/************************Zarlink Semiconductor*********************************
* Name:ReadQPSKBERSnim()
* Purpose:Calculates the bit error rate out of the QPSK core
* Remarks: Pre Viterbi BER = VIT_ERCNT/(VIT_ERRPER*4)
* BER*1000000 = VIT_ERCNT*250000/VIT_ERRPER
* Now uses only VIT_ERRPER_H (M and L assumed to be 0xFFFF), and result
* is same as with TNIM;
* Inputs:
*
* Outputs: BER * 1000000, or -1
*
********************************************************************************/
Sint32T Snim_CalcQPSKBER(PSSNIMCTL hSnim)
{
Uint32T dwCount;
Uint32T dwPeriod;
if (!Snim_ReadRegisterValue(hSnim,SNIM_VIT_ERRCNT,&dwCount)
|| !Snim_ReadRegisterValue(hSnim,SNIM_VIT_ERRPER,1,&dwPeriod))
{/* did not read both registers */
return-1;
}
dwPeriod<<=16;
dwPeriod +=65535;
/* got the data do the arithmetic*/
if (dwCount<=Uint32T_MAX/25000)
{
dwCount *=25000;
dwPeriod +=5;
dwPeriod /=10;
}
else if (dwCount<=Uint32T_MAX/2500)
{
dwCount *=2500;
dwPeriod +=50;
dwPeriod /=100;
}
else
{
dwCount *=250;
dwPeriod +=500;
dwPeriod /=1000;
}
if (dwPeriod>0)
dwCount /= dwPeriod;
return dwCount;
}
/************************Zarlink Semiconductor*********************************
* Name:Snim_CalcViterbiBER()
* Purpose:Calculates the Post Viterbi bit error rate
* Remarks: Vitberi BER = RS_BERCNT/(dt *Rs * CR * Q), where
* dt is the time in seconds
* Rs is the symbol rate in Baud
* CR is the code rate (expressed as a fraction 3/4 for example)
* Q is 1 (BPSK) or 2 (QPSK)
*
* Inputs:time and error counts cached by demodmain
*
* Outputs:PostViterbi BER (x 1E9)
*
*Calculation becomes:
* Viber BER (x10^9) = (RS_BERCNT x 1E9)/(dt Rs_x128 x10^6/128 xCR xQ)
* = (RS_BERCNT x 128000 x(c+1)) / (dt Rs_x128 x c xQ), where
* Rs_x128 is Rs in MBd x128
* c is the numerator and (c+1) the denominator (e.g. 3 and 4)
********************************************************************************/
Sint32T Snim_CalcViterbiBER(PSSNIMCTL hSnim)
{
Uint32T numerator;
Uint8T coderate;
Uint8T config;
Uint16T symbolratex128;
Uint32T denominator;
coderate=Snim_GetCodeRate(hSnim);
symbolratex128=Snim_GetSymbolRate(hSnim)/8;/* symbol rate in MS x128*/
if (!Snim_RegisterRead(hSnim,SNIM_CONFIG,&config,1) || (0==coderate) || (0==symbolratex128) )
return -1;
numerator = hSnim->dwErrorCount;
denominator = (hSnim->dwErrPer +500)/1000;/* time in seconds*/
if (denominator >74000) return -1; /* too long, arithmetic overflow will occur */
/* calculate the denominator */
denominator *= symbolratex128; /* 65535 x (64MBd max)x128 */
denominator *= coderate; /* x 7 => 3,758,039,040 max*/
denominator /= (coderate+1);
if (config & SNIM_CONFIG_BPSK)
denominator /=2; /* BPSK*/
else
denominator *=4; /*QPSK*/
/*spread the *256000 around the numerator and denominator to best effect
bearing in mind minimum value of denominator*/
if (numerator <=Uint32T_MAX/256000)
{
numerator *=256000;
}
else if (numerator <=Uint32T_MAX/25600)
{
numerator *=25600;
denominator +=5;
denominator /=10;
}
else if (numerator <=Uint32T_MAX/2560)
{
numerator *=2560;
denominator +=50;
denominator /=100;
}
else if (denominator < 5000)
{
/* error count is greater than Uint32T_MAX/2560 clip it*/
numerator = Uint32T_MAX/2560;
denominator +=50;
denominator /=100;
}
else
{
numerator *=256;
denominator +=500;
denominator /=1000;
}
/* post the answer and return*/
if (0== denominator) return -1;
numerator/=denominator;
if (numerator>Sint32T_MAX) numerator=Sint32T_MAX;
return numerator;
}
/************************Zarlink Semiconductor*********************************
* Name:SnimSetLnb()
* Purpose:Set the required LNB parameters
* Remarks:Takes effect next time a channel or scan is initialised
* Inputs:psLnb pointer to an Lnb specifier
*
* Outputs:
*
********************************************************************************/
void SnimSetLnb(HANDLE hSnim, SSnimLnb *psLnb)
{
ENTER_SNIM_CONTENTION_LOCK;
if (Snim_CheckPointers(PSSNIM) && psLnb!=NULL) PSSNIM->Lnb = *psLnb;
EXIT_SNIM_CONTENTION_LOCK;
}
/************************Zarlink Semiconductor*********************************
* Name: SnimReadChannel()
* Purpose:Reads current channel info
* Remarks:if psChannel returns tuning info in pchannel structure
*
* Inputs:none
*
* Outputs:FLASE if device read error
*
********************************************************************************/
BOOL SnimReadChannel(HANDLE hSnim, SSnimChannel *psChannel)
{
Sint32T temp;
BOOL ret;
ENTER_SNIM_CONTENTION_LOCK;
ret=TRUE;
if (!Snim_CheckPointers(PSSNIM))
{
ret = FALSE;
}
else
{
if (psChannel!=NULL)
{
*psChannel = PSSNIM->Channel;
if ((PSSNIM->DemodFsmState==SNIM_DEMODFSM_SCANSTOP) || (PSSNIM->DemodFsmState==SNIM_DEMODFSM_LOCK))
{/* locked, get the real values*/
psChannel->ucExt&= SCHANNELEXT_HORIZONTAL;
temp = Snim_GetLNBFreq(PSSNIM,_LNBFREQ_MODE_ACTUAL);
psChannel->MHz = Uint16T(((Uint32T)temp +500)/1000); /*rounded to MHz;*/
temp -= psChannel->MHz*1000; /* remaining kHz */
if (temp>=0) temp += 50; else temp -=50;
temp/=100; /* tenths */
psChannel->ucExt |= Uint8T((temp <<4) & 0xF0);
if (PSSNIM->DSSmode)
psChannel->kRs= SNIM_DSS_SYMBOLRATE;
else
psChannel->kRs = Snim_GetSymbolRate(PSSNIM);
psChannel->ucExt &= ~SCHANNELEXT_CODERATE;
psChannel->ucExt |= Snim_GetCodeRate(PSSNIM);
if (0==psChannel->kRs || 0 == (psChannel->ucExt &SCHANNELEXT_CODERATE)) ret = FALSE;
}
else if (PSSNIM->DemodFsmState>=SNIM_DEMODFSM_SCANINIT)
{/* scanning, set element to zero */
psChannel->kRs =0;
}
}
}
EXIT_SNIM_CONTENTION_LOCK;
return ret;
}
/************************Zarlink Semiconductor*********************************
* Name: SnimAcquire()
* Purpose: To start acquisition of a new known channel
* Remarks:Copies passed channel data into PSSNIM structure and forces state to PROGRAM_TUNER
* Inputs: Pointer to channel data, psChannel. If psChannel = NULL, Aquisition is restarted with current setting.
*
* Outputs:TRUE indicates no errors occured, and does not indicate lock occured
*
********************************************************************************/
BOOL SnimAcquire(HANDLE hSnim,PSSNIMCHANNEL psChannel)
{
BOOL ret;
ENTER_SNIM_CONTENTION_LOCK;
if (!Snim_CheckPointers(PSSNIM))
{/* error in pointers*/
printSnimDrvError(("[SnimAcquire] >> error in pointers\n"));
ret= FALSE;
}
else if (PSSNIM->DemodFsmState>=SNIM_DEMODFSM_SCANINIT ||PSSNIM->DemodFsmState<SNIM_DEMODFSM_IDLE)
{ /* off, standby or scanning */
printSnimDrvError(("[SnimAcquire] >> off, standby or scanning DemodFsmState : %x \n",PSSNIM->DemodFsmState));
ret = FALSE;
}
else
{ /* start acqusition (with new channel if required)*/
printSnimDrv(("[SnimAcquire] >> start acqusition (with new channel if required)\n"));
if (psChannel != NULL) PSSNIM->Channel = *psChannel;
PSSNIM->DemodFsmCommand=SNIM_FSMCOMMAND_NEWCHAN;
ret = TRUE;
}
EXIT_SNIM_CONTENTION_LOCK;
return ret;
}
/***********************Zarlink Semiconductor*********************************
* Name: Snim_DemodMain()
* Purpose: Finite state machine to run Snim power control, acquisition and scanning
* Remarks: Intended to be in host programs main loop, called regularly say every 10 msec.
* Actual performance depends on calling rate, faster the better
* PSSNIM->pMilliSeconds (32 bit millisecond counter) controls timeouts. The state machine will timeout of
* various activities based on this time value. This routine should be called frequently (say every 10 msec) with a
* new value of PSSNIM->pMilliSeconds for best performance. However the time may be updated less frequently (say every 50 msec)
* which will result in slower scanning performance due to longer timouts for example.
* Processing occurs in two stages: 1) any pending command in PSSNIM->ACQcoomand is processed
* 2) the state machine is run.
* Inputs: PSSNIM structure
*
* Outputs: return value descriptive of activity (e.g. IDLE, BUSY, LOCKED etc)
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -