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

📄 mt352.c

📁 上海tower公司DVB-T tuner驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
*   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 + -