📄 mt352.c
字号:
* Remarks: packs up to 4 bytes (msb or lsb first) into a 32 bit result
* Inputs: reg : address of first register
* count : number of bytes to read +ve reads MSB first, -ve reads LSB first
* Outputs: result 32bit unsigned value
********************************************************************************/
bool8 Tnim_ReadRegisterValue(PSTNIMCTL psTnim, u8 byReg,s8 cCount,u32 * pdwValue)
{
u8 Buffer[4]={0,0,0,0};/* only 4 Uint8Ts allowed for up to u32*/
s16 counter;
u32 ans = 0;
bool8 ret;
if ((u8) ABSVAL(cCount)>sizeof(Buffer))
return FALSE;
ans =0;
if (RegisterRead2wb(psTnim->DeviceID,byReg, Buffer,(u8)ABSVAL(cCount)))
{
if (cCount>0) /* MSB first */
{
for (counter=0;counter<cCount;counter++)
{
ans <<=8;
ans +=(Buffer[counter]);
}
*pdwValue = ans;
ret = TRUE;
}
else /* LSB first*/
{
for (counter=(u16)(-1-cCount);counter>=0;counter--)
{
ans <<=8;
ans +=(Buffer[counter]);
}
*pdwValue = ans;
ret = TRUE;
}
}
else
ret = FALSE;
return ret;
}
/************************Zarlink Semiconductor*********************************
* Name:Tnim_Initialise()
* Purpose:Initialise the MT352 after power up
* Remarks:
* Inputs:
* Outputs:
********************************************************************************/
bool8 Tnim_Initialise(PSTNIMCTL psTnim)
{
u8 ucBuffer;/* one byte buffer for now */
/*Assume we have been hardware reset */
/* set config register*/
ucBuffer = MT352_CONF_ENABLE |
MT352_CONF_TEIEN |
MT352_CONF_BKERRINV |
MT352_CONF_MDOSWAP |
MT352_CONF_BG12;
if (psTnim->MpegOff)
ucBuffer |=MT352_CONF_MPEGDIS;
if (psTnim->MPEGserial)
ucBuffer |=MT352_CONF_BSO;
if (psTnim->NoTEI)
ucBuffer &=~MT352_CONF_TEIEN;
if (psTnim->NoBKERRinvert)
ucBuffer &= ~MT352_CONF_BKERRINV;
/*psTnim->NoMD0swap=1*/
if (psTnim->NoMDOswap)
ucBuffer &= ~MT352_CONF_MDOSWAP;//0x02
if (psTnim->NoMPEGgap12)
ucBuffer &=~MT352_CONF_BG12;
//printf("config=%x\n", ucBuffer); getch();
//ucBuffer=0x2d
if (! MT352_WRITE(MT352_CONFIG))
return FALSE;//MT352_CONFIG=0x8A
/* set clock mode*/
ucBuffer = (u8)(Tnim_GetClockMode(psTnim)
+psTnim->MPEGclkinEn?MT352_CLKCTL_MCLKINEN:0
+psTnim->NoMPEGClkInv?0:MT352_CLKCTL_MCLKINV
+MT352_CLKCTL_ADC_ENABLE);
//printf("config=%x\n", ucBuffer);
//ucBuffer=0x30
if (! MT352_WRITE(MT352_CLOCK_CTL))
return FALSE;//MT352_CLOCK_CTL=0x89
/* delay around 200礢 use dummy read*/
if (!MT352_READ(MT352_FECSTAT))
return FALSE;
/*reset*/
ucBuffer=MT352_RESET_ALL;//0xFF
if (! MT352_WRITE(MT352_RESET))
return FALSE;//MT352_RESET=0x50
/* Initialise ADC (only first byte needed)*/
ucBuffer = MT352_ADC_CTL_INIT;//0x40
if (! MT352_WRITE(MT352_ADC_CTL))
return FALSE;//MT352_ADC_CTL=0x8E
/*tuner AGC settings (10 bytes from AGC target onwards*/
RegisterWrite2wb(psTnim->DeviceID,MT352_AGC_TARGET,psTnim->psTunerInfo->AGC,10);
//MT352_AGC_TARGET=0x67
/* enable Viterbi error measurements */
ucBuffer=MT352_VIT_CTL_DEFAULT+MT352_VIT_CTL_ERRPER_EN;//0x78, 0x02
if (! MT352_WRITE(MT352_VIT_CTL))
return FALSE;//MT352_VIT_CTL=0xB5
/* set up the ITB frequency & spectral inversion */
if (!Tnim_SetITB(psTnim))
return FALSE;
MT352_READ(MT352_CHIP_ID);
// printf("MT352 Chip ID: %x\n", (int)ucBuffer);
if ( ucBuffer != 0x13 )
{
return FALSE;
}
return TRUE;
}
/************************Zarlink Semiconductor*********************************
* Name:Tnim_GetClockMode()
* Purpose:Determines the clock mode from the settings
* Remarks: 2 ADC rates are availble. If tuner IF is 44.75MHz
* and the output is at IF1, we select the lower frequency (~19.5 MHz)
* otherwise we use the higher 20.5MHz.
* NOTE: this means that the 19.5 Xtal option is only suitable for
* 4.57 and 44.75 MHz inputs.
* Inputs:STnimControl Structure
* Outputs: Byte containing 20_8 bit and three clock mode bits
********************************************************************************/
u8 Tnim_GetClockMode(PSTNIMCTL psTnim)
{
return g_tnim2_ucModes[psTnim->Xtal]
[((psTnim->psTunerInfo->IF1kHz>40000) && ((psTnim->psTunerInfo->Settings) & TUNER_IF1_OUTPUT))?1:0]
[psTnim->AdcPll];
}
/************************Zarlink Semiconductor*********************************
* Name:Tnim_SetITB()
* Purpose:programs the ITB frequency and spectral inversion
* Remarks:
* ITB = -Fin*16384/Fadc where
* Fin = 4.57 for "baseband input"
* Fin = 2*Fadc-Fin for IF input
* Inputs:STnimControl Structure
* Outputs: success TRUE or FALSE
********************************************************************************/
bool8 Tnim_SetITB(STnimControl* psTnim)
{
s32 freqITB;
u16 clockADC=Tnim_ADCClock_x3(psTnim);
u8 ucBuffer;
if ((psTnim->psTunerInfo->Settings) & TUNER_IF1_OUTPUT)
{
freqITB = clockADC;
freqITB *=2;
freqITB /=3;
freqITB-=psTnim->psTunerInfo->IF1kHz;
}
else
{
freqITB = 4571;
}
freqITB *= 49152;
freqITB += (clockADC/2);
freqITB /= clockADC;
clockADC=0; /* use to keep track of net spectral inversion*/
if (freqITB>0)
freqITB=-freqITB;/* make result -ve */
else
clockADC++; /* already negative, need inversion*/
/*Each of the following adds an inversion*/
if ((psTnim->psTunerInfo->Settings) & TUNER_LO_INJECTION)
clockADC++;
if ((psTnim->psTunerInfo->Settings) & TUNER_SPECTRAL_INV)
clockADC++;
/* set up spectral inversion*/
if (!MT352_READ(MT352_ACQ_CTL))
return FALSE;
if (clockADC & 0x01)
ucBuffer |=MT352_ACQ_CTL_SPECINV;
else
ucBuffer &=~MT352_ACQ_CTL_SPECINV;
if (!MT352_WRITE(MT352_ACQ_CTL))
return FALSE;
return Tnim_WriteRegisterValue(psTnim,MT352_INPUT_FREQ,2,(u32)freqITB);
}
/************************Zarlink Semiconductor*********************************
* Name:TnimReadPreViterbiBER()
* Purpose:Calculates Pre Viterbi BER
* Remarks:Pre Viterbi BER = VIT_ERCNT/(VIT_ERRPER*4)
* Output is BER * 1000
* Inputs:
* Outputs:
********************************************************************************/
bool8 TnimReadPreViterbiBER(PSTNIMCTL psTnim, u32 *pdwBER)
{
bool8 ret= TRUE;
u32 dwPeriod;
u32 dwCount=0;
u8 ucBuffer=0;
TNIM_ENTRYB;
if (pdwBER!=NULL)
{/* get the period*/
ret=Tnim_ReadRegisterValue(psTnim,MT352_CIT_ERRPER,3,&dwPeriod);
if (ret && dwPeriod!=0)
{/*get the count*/
ret=Tnim_ReadRegisterValue(psTnim,MT352_VIT_ERRCNT,3,&dwCount);
}
if (ret) ret = MT352_READ(MT352_VIT_CTL);
if (ret && (ucBuffer & MT352_VIT_CTL_ERRPER_EN))
{/* calculate the BER*/
*pdwBER = dwCount *250;
*pdwBER /=dwPeriod;
}
else
{
*pdwBER=Uint32T_MAX;
ret=FALSE;
}
}
TNIM_EXIT;
return ret;
}
/************************Zarlink Semiconductor*********************************
* Name:TnimReadPostViterbiBER()
* Purpose:Calculates PostViterbi BER
* Remarks:formula is RS_BERCNT/(RS_ERRPER*1024*204*8)
* the result is multiplied by 100E6 to get an integer value, the
* formula becomes
* BER = 100e6/(1024*204*8) *RS_BERCNT/RS_ERRPER = 60*RS_BERCNT/RS_ERRPER
* Inputs:
* Outputs:
********************************************************************************/
bool8 TnimReadPostViterbiBER(PSTNIMCTL psTnim, u32 *pdwBER,u32 *pdwCount)
{
bool8 ret= TRUE;
u32 dwCount,dwPeriod;
TNIM_ENTRYB;
ret = Tnim_ReadRegisterValue(psTnim,MT352_RS_ERRCNT,3,&dwCount);//MT352_RS_ERRCNT=0x0D
// printf("\nResult of Read MT352_RS_ERRCNT=%d, dwCount=%ld\n", ret, dwCount);
if (ret && (pdwCount!=NULL))*pdwCount = dwCount;/* wants the count*/
if (ret && (pdwBER !=NULL))
{/* wants the calculated error*/
ret=Tnim_ReadRegisterValue(psTnim,MT352_RS_ERRPER,2,&dwPeriod);//MT352_RS_ERRPER=0x7C
// printf("\nResult of Read MT352_RS_ERRPER=%d, dwPeriod=%X\n", ret, dwPeriod);
if (ret && dwPeriod>0
&& ((psTnim->RSUBC<50) || psTnim->NoAutoRSUBC)
/*&& TNIM_STATEINTERNAL_LOCK==psTnim->State*/)
{/* calculate the result*/
*pdwBER = dwCount * 240;/* maximise before arithmetic*/
*pdwBER /=dwPeriod;
*pdwBER +=2;/* rounding*/
*pdwBER /=4; /* finish off */
}
else
{/* error reading error period, or the RS count is too high*/
*pdwBER=Uint32T_MAX;
ret = FALSE;
}
}
TNIM_EXIT;
return ret;
}
/************************Zarlink Semiconductor*********************************
* Name: TnimSelectLPdata()
* Purpose:selects LP data stream (if bWantLP is true) or HP data stream
* Remarks:Initial channel acquisition defaults to HP
* Inputs:
* Outputs:
********************************************************************************/
bool8 TnimSelectLPdata(PSTNIMCTL psTnim, bool8 bWantLP)
{
bool8 ret;
u8 ucBuffer,u8retry=0;
TNIM_ENTRYB;
while(u8retry<6) //2004.12.13 Alex: make sure read lock is vaild.
{
delay(50);
ret = Tnim_IsLocked(psTnim);
if(ret) break ;
u8retry++;
}
if (ret)
{
//printf("[mt352.c] Tnim is locked.\n");
ret=MT352_READ(MT352_TPS_RECEIVED);//MT352_TPS_RECEIVED=0x1E
if (ret && ((0x80<(ucBuffer & 0x9C)) || !bWantLP) )
{/*TPS is valid and hierarchical*/
ret = MT352_READ(MT352_TPS_GIVEN);//MT352_TPS_GIVEN=0x51
ucBuffer &= ~MT352_TPS_GIVENH_LP;//MT352_TPS_GIVENH_LP=0x80
if (bWantLP) ucBuffer |=MT352_TPS_GIVENH_LP;
if (ret) ret = MT352_WRITE(MT352_TPS_GIVEN);
//printf("[mt352.c] Write HP/LP.\n");
}
}
TNIM_EXIT;
return ret;
}
void TestPrintTPSdata(STnimAuxChannelInfo aux, bool8 bShowActive)
{
switch (TPS_CONSTELLATION(aux.wTPS))
{
case 0: printf(" QPSK ");break;
case 1: printf(" 16QAM ");break;
case 2: printf(" 64QAM ");break;
default:printf(" ????? ");
}
switch(TPS_HIERARCHY(aux.wTPS))
{
case 0: printf(" none ");break;
case 1: printf(" 1 ");break;
case 2: printf(" 2 ");break;
case 3: printf(" 4 ");break;
default:printf(" ??? ");
}
printf(" %d/%d %s%d/%d", FORMAT_CODERATE(TPS_HPCODERATE(aux.wTPS)),
FORMAT_CODERATE(TPS_HPCODERATE(aux.wTPS))+1,
bShowActive?(TPS_LPACTIVE(aux.wTPS)?" >":"< "):" ",
FORMAT_CODERATE(TPS_LPCODERATE(aux.wTPS)),
FORMAT_CODERATE(TPS_LPCODERATE(aux.wTPS))+1 );
switch (TPS_GUARDINTERVAL(aux.wTPS))
{
case 0:printf(" 1/32");break;
case 1:printf(" 1/16");break;
case 2:printf(" 1/8 ");break;
case 3:printf(" 1/4 ");break;
default:printf(" ????");break;
}
printf(" %sk", TPS_FFTMODE8K(aux.wTPS)?"8":"2" );
printf(" 0x%04x%s\n",aux.wCellID,(aux.ucValid & UCVALID_CELLIDVALID)?" ":"?");
}
/************************Zarlink Semiconductor*********************************
* Name: TnimReadChannel()
* Purpose:Reads channel information when locked, and restarts scan if any
* Remarks: fills in STnimChannel and/or STnimAuxChannelInfo, if relevant
* pointer is non NULL
* Inputs:
* Outputs:
********************************************************************************/
bool8 TnimReadChannel(PSTNIMCTL psTnim, PSCHANNEL psChannel,PSAUXINFO psAuxInfo)
{
bool8 isTps=FALSE, isID=FALSE;
u8 ucBuffer;
u32 dwTemp;
TNIM_ENTRYB;
if (psChannel!=NULL)
{
if (psTnim->Channel.Number & 0x80)
{/* channel number is invalid*/
psChannel->Number=0xFF;
psChannel->Offset=0;
}
else
{
*psChannel=psTnim->Channel;
if (psTnim->State==TNIM_STATEINTERNAL_SCANSTOP)
{
if (Tnim_ReadOffsetkHz(psTnim,(s32*)&dwTemp))
{
if ((s32)dwTemp >84)
psChannel->Offset = 1;
else if ((s32)dwTemp <-84)
psChannel->Offset = -1;
}
}
}
}
if (psAuxInfo!=NULL)
{
psAuxInfo->ucValid=0;
psAuxInfo->wCellID=0;
psAuxInfo->wTPS=0;
if (Tnim_IsLocked(psTnim))
{
isTps = Tnim_ReadRegisterValue(psTnim,MT352_TPS_RECEIVED,2,&dwTemp);//MT352_TPS_RECEIVED=0x1E
if (isTps && dwTemp & 0x8000)
{
psAuxInfo->ucValid |= UCVALID_TPSVALID;//UCVALID_TPSVALID=0x01
psAuxInfo->wTPS = (u16)(dwTemp & 0x7FFF);/* remove valid flag*/
isTps=MT352_READ(MT352_TPS_GIVEN);/* get LP flag*/ //MT352_TPS_GIVEN=0x51
if (ucBuffer & MT352_TPS_GIVENH_LP)//MT352_TPS_GIVENH_LP 0x80
psAuxInfo->wTPS |= 0x8000;
}
isID = Tnim_ReadRegisterValue(psTnim,MT352_TPS_CELL_ID,2,&dwTemp);//0x22
if (isID)
psAuxInfo->wCellID = (u16) dwTemp;
isID = MT352_READ(MT352_FSMSTAT);//0x02
if (isID)
{/* check if reported as valid */
if (isID && (ucBuffer &0x01)==0x01)
psAuxInfo->ucValid |= UCVALID_CELLIDVALID;//0x02
}
}
}
TNIM_COMMAND(TNIM_COMMAND_PROCEED);//TNIM_COMMAND_PROCEED 6
TNIM_EXIT;
return isID && isTps;
}
/************************Zarlink Semiconductor*********************************
* Name: Tnim_ReadOffsetkH()
* Purpose:calculates frequency offset (transmitter relative to tuner)
* Remarks:
* Foff kHz= CRL * BW(MHz) /29360/x where x is 1(2k) or 4 (8k)
* Inputs:
* Outputs:TRUE if read was sucessful.
********************************************************************************/
bool8 Tnim_ReadOffsetkHz(PSTNIMCTL psTnim, s32 *lOffsetkHz)
{
u8 ucBuffer;
if (!Tnim_ReadRegisterValue(psTnim,MT352_FREQ_OFFSET,3,(u32*)lOffsetkHz))//MT352_FREQ_OFFSET=0x17
return FALSE;
/* get low byte of TPS with fft mode in it*/
if (!MT352_READ(MT352_TPS_RECEIVED+1))
return FALSE;//MT352_TPS_RECEIVED=0x1E
// printf("lOffsetkHz =0x%lx , 0x%x\n", *lOffsetkHz, (int)ucBuffer );
*lOffsetkHz = -(*lOffsetkHz<<8)>>8;
// printf("lOffsetkHz =0x%lx.\n", *lOffsetkHz);
*lOffsetkHz *= psTnim->ucBW;
if (ucBuffer &0x01)
*lOffsetkHz/=4;
*lOffsetkHz/=29360;
// printf("lOffsetkHz =0x%lx, %ld.\n", *lOffsetkHz, *lOffsetkHz);
return TRUE; /* finished*/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -