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

📄 vp310_driver.c

📁 嵌入式软件VP310tuner驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:

	*buffer		= 128; /* To turn   symbol rate sweep on */
	*(buffer+1)	= 0;

	for (i = 0; i< kbd_params.nr_sweep_ranges; i++)
	{
		lo_lim	= kbd_params.KBd_rate_low_lim[i];
		hi_lim  = kbd_params.KBd_rate_high_lim[i];
		if (lo_lim >= hi_lim)
			return VP310_SYM_SW_LIM_ERROR;
		if (hi_lim > (VP310_KHz_sys_clk >> 1))
			return VP310_SYM_SW_LIM_ERROR;
		if (lo_lim < 900)
			return VP310_SYM_SW_LIM_ERROR;

		dec_ratio = 0;
		while ((hi_lim <= (VP310_KHz_sys_clk >> 2)) && (dec_ratio <= 5))
		{
			hi_lim = hi_lim << 1;
			dec_ratio++;
		}
		if ((hi_lim * 3) >= VP310_KHz_sys_clk)
			ext_dr_high = dec_ratio << 1;
		else
			ext_dr_high = (dec_ratio << 1) + 1;

		dec_ratio = 0;
		while ((lo_lim <= (VP310_KHz_sys_clk >> 2)) && (dec_ratio <= 5))
		{
			lo_lim = lo_lim << 1;
			dec_ratio++;
		}
		if ((lo_lim * 3) >= VP310_KHz_sys_clk)
			ext_dr_low = dec_ratio << 1;
		else
			ext_dr_low = (dec_ratio << 1) + 1;

		sub_ranges = (1 << (12 - ext_dr_high)) - (1 << (12 - ext_dr_low - 1));
		*buffer		= (*buffer) | ((sub_ranges >> 8) & 0xF);
		*(buffer+1)	= (*(buffer+1)) | (sub_ranges & 0xFF);
	}
	return VP310_NO_ERROR;
}

/*----------------------------------------------------------------------------------------------*/
/*  Form VIT_MODE register																		*/
/*----------------------------------------------------------------------------------------------*/

BYTE make_vit_mode_reg(VP310_CODE_RATE code_rate, VP310_IQ_MODE iq_mode)
{
	BYTE vit_mode_reg;

	switch (code_rate)
	{
		case CODE_1_2 : vit_mode_reg = 1; break;
		case CODE_2_3 : vit_mode_reg = 2; break;
		case CODE_3_4 : vit_mode_reg = 4; break;
		case CODE_5_6 : vit_mode_reg = 8; break;
		case CODE_7_8 : vit_mode_reg = 32; break;
		default       : vit_mode_reg = 47; break;
	}

	if (iq_mode == IQ_INVERSE)
		vit_mode_reg += 64;
	return vit_mode_reg;
}

/*-----------------------------------------------------------------------------------------------*/
/*  Tune to a channel with known parameters         										     */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS 
VP310_acquire_known_channel(		VP310_CHANNEL_PARAMS	channel_params,
									VP310_BOOLEAN			AFC_on,
									UINT					lock_time_lim_ms,
									int						*KHz_freq_offset,
									ULONG					*acq_time_ms)

{
	clock_t				acq_start_time;
	VP310_STATUS		status;
	BYTE				buffer[8];
	UINT				kbd_rate;

	*KHz_freq_offset = 0;
	*acq_time_ms = 0;

	/* Set the LNB Polarisation and 22KHz tone. */
	if (channel_params.khz_22 == TONE_ON)
		buffer[0] = 1;
	else
		buffer[0] = 0;
	if (channel_params.lnb_polar == POL_HORIZONTAL)
		buffer[0] += 64;
	if ((status = VP310_Write_Registers(VP310_DISEQC_MODE, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR) 
		return status;

	/* Program the tuner */
	if ((status = VP310_program_tuner(channel_params.KHz_tuner_freq, lock_time_lim_ms)) != VP310_NO_ERROR)
		return status;

	/* Symbol Rate */
	kbd_rate = channel_params.KBd_rate;
	kbd_rate = (kbd_rate * 131) >> 9;
	buffer[0]= (BYTE) ((kbd_rate >> 8) & 0xFF);
	buffer[1]= (BYTE) (kbd_rate & 0xFF);
	/* Code rate register */
	buffer[2] = make_vit_mode_reg(channel_params.code_rate, channel_params.iq_mode);
	/* AFC */
	if (AFC_on)
		buffer[3] = 4 + IQ_WIRES_CROSSED;
	else
		buffer[3] = IQ_WIRES_CROSSED;
	/* GO */
	buffer[4] = 1;
	acq_start_time = clock();
	if ((status = VP310_Write_Registers(VP310_SYM_RATE_H, buffer, 5, VP310_FALSE)) != VP310_NO_ERROR)
		return status;
	/* go_to_sleep(10000); */
	*acq_time_ms = 0;
	while ((*acq_time_ms) < ((ULONG)lock_time_lim_ms))
	{
		if ((status = VP310_Read_Registers(VP310_FEC_STATUS, buffer, 3, VP310_FALSE)) != VP310_NO_ERROR)
			return status;
		*acq_time_ms = clock() - acq_start_time;
		if ((buffer[0] & 12) == 12)
		{
			*KHz_freq_offset = ( (buffer[1] & 0x7F) << 8) + buffer[2] - ((buffer[1] & 128)<< 8);
			/* Third term is for two's complement correction */
			*KHz_freq_offset = ((*KHz_freq_offset) * 1000) >> 9;
			return VP310_LOCK;
		}
	}
	return VP310_NO_FEC_LOCK;
}

/*-----------------------------------------------------------------------------------------------*/
/*  Program the tuner synthesiser		         										         */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS	
VP310_program_tuner(ULONG KHz_tuner_freq, UINT qpsk_lock_time_lim_ms)
{
	ULONG			synth_prog_div;
	VP310_BOOLEAN	tuner_locked;
	clock_t			start_time, current_time;
	VP310_STATUS	status;
	BYTE			buffer[8];
	UINT			elapsed_time;
	ULONG			temp_value, residual_synth_freq;
	
	if (KHz_tuner_freq < TUNER_FREQ_LOW_LIM_KHZ)
		return TUNER_FREQ_OUT_OF_RANGE;

	if (KHz_tuner_freq > TUNER_FREQ_HIGH_LIM_KHZ)
		return TUNER_FREQ_OUT_OF_RANGE;

	/* Open Secondary I2C bus to access the tuner */
	buffer[0] = VP310_GPP_CTRL_I2C_PAS_OPEN;
	if ((status = VP310_Write_Registers(VP310_GPP_CTRL, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
		return status;

	synth_prog_div	= (ULONG) ((KHz_tuner_freq * 1000.0) / SYNTH_COMP_FREQ_HZ);
	/* The above replaced by the following integer code */
	synth_prog_div  = 0L;
	residual_synth_freq = KHz_tuner_freq * 1000L;
	while (residual_synth_freq >= SYNTH_COMP_FREQ_HZ) 
	{
		temp_value		= 1L;
		while((temp_value * SYNTH_COMP_FREQ_HZ) <= residual_synth_freq)
			temp_value = temp_value << 1;
		synth_prog_div = synth_prog_div + (temp_value >> 1);
		residual_synth_freq = residual_synth_freq - ((temp_value >> 1) * SYNTH_COMP_FREQ_HZ);
	}

	buffer[0]		= (BYTE)((synth_prog_div >> 8) & 0x7f);		/* Get bits 15-8 */
	buffer[1]		= (BYTE)(synth_prog_div & 0xff);			/* Get bits 7-0  */

	buffer[2]		= synth_byte4;

	if (KHz_tuner_freq <= 1100000L)
		buffer[3] = 0x02;		/*  P1 = 1 (Set Low Frequency Oscillator) */
	else if (KHz_tuner_freq <= 1500000L)
		buffer[3] = 0x02;		/*  P1 = 1 (Set Low Frequency Oscillator) */
	else if (KHz_tuner_freq <= 1800000L)
		buffer[3] = 0x00;		/*  P1 = 0 (Set High Frequency Oscillator) */
	else
		buffer[3] = 0x00;		/*  P1 = 0 (Set High Frequency Oscillator) */

	if ((status = VP310_Write_Registers(0, buffer, 4, VP310_TRUE)) != VP310_NO_ERROR)
		return status;

	/* Test lock status of the synthesiser. */
	tuner_locked	= VP310_FALSE;
	start_time		= clock();
	current_time	= start_time;
	elapsed_time = (UINT) (current_time - start_time);

	while ((elapsed_time) < qpsk_lock_time_lim_ms)
	{
		if ((status = VP310_Read_Registers(0, buffer, 1, VP310_TRUE)) != VP310_NO_ERROR)
			return status;
		if ((buffer[0] & 64) != 0) /* Lock flag is bit B6 of the Read register */
		{
			tuner_locked = VP310_TRUE;
			break;
		}
		current_time = clock();
		elapsed_time = (UINT) (current_time - start_time);
	}

	/* Close Secondary I2C bus to access the tuner */
	buffer[0] = VP310_GPP_CTRL_I2C_PAS_CLOSED;
	if ((status = VP310_Write_Registers(VP310_GPP_CTRL, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
		return status;
	if (tuner_locked)
		return	VP310_NO_ERROR;
	else
		return	TUNER_NO_LOCK;
}

/*-----------------------------------------------------------------------------------------------*/
/*  Frequency scanning	                                                                         */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS 
VP310_scan_freq(	ULONG					KHz_tuner_freq_min,
					ULONG					KHz_tuner_freq_max,
					ULONG					KHz_scan_step,
					VP310_BOOLEAN			auto_step_sizing_on,
					VP310_BOOLEAN			scan_up,
					VP310_LNB_PARAMS		lnb_params, /* However will scan both polarisations */
					VP310_BOOLEAN			lnb_tone_search_on, /* To search both 22 KHz on/off options */
					VP310_KBD_PARAMS		kbd_params,
					VP310_CODE_RATE			code_rate,
					VP310_IQ_MODE			iq_mode,
					VP310_BOOLEAN			AFC_on,
					UINT					qpsk_lock_time_lim_ms,
					UINT					fec_lock_time_lim_ms,
					VP310_CHANNEL_PARAMS	*channel_params,
					USHORT					*V_channel_cnt,
					USHORT					*H_channel_cnt,
					ULONG					*scan_time_ms)
{
	ULONG					KHz_tuner_freq, khz_new_scan_step;
	int						KHz_freq_offset;
	VP310_LNB_PARAMS		lnb_params_temp;
	VP310_CHANNEL_PARAMS	channel_params_temp;
	ULONG					acq_time_ms;
	VP310_BOOLEAN			set_diseqc, scan_complete;
	BYTE					i, khz22_loop_lim, khz22_loop_cnt;
	USHORT					total_channel_cnt, channel_cnt[2];
	clock_t					scan_start_time; 
	BYTE					sym_rate_index, scan_factor;
	ULONG					qpsk_acq_time_ms;
	VP310_STATUS			status;
	UINT					min_sym_rate;
	BYTE					buffer[4];


	if (auto_step_sizing_on)
	/* Then this function will work out the step size, to match with
	   smallest symbol rate.  It will also work out a new KHz_LNB_offset_lim
	   and load it to FR_LIM register. */
	{
		/* Get minimum symbol rate */
		min_sym_rate = 100000;
		if (kbd_params.sweep_on)
		{
			for (i=0; i < kbd_params.nr_sweep_ranges; i++)
			{
				if (kbd_params.KBd_rate_low_lim[i] < min_sym_rate)
					min_sym_rate = kbd_params.KBd_rate_low_lim[i];
			}
		}
		else
		{
			for (i=kbd_params.start_index; i <= kbd_params.end_index; i++)
			{
				if (kbd_params.KBd_sym_table[i] < min_sym_rate)
					min_sym_rate = kbd_params.KBd_sym_table[i];
			}
		}
		/* Channel bandwidth taken as 1.375 Symbol rate. Will not work for DSS */
		/* Step size is equal to the minimum channel bandwidth.  However, if a
		high symbol rate channel found, then goes to edge of this channel and step
		by half above step size. */
		khz_new_scan_step = (min_sym_rate * 11) >> 3;
		if (khz_new_scan_step > KHz_scan_step)
			khz_new_scan_step = KHz_scan_step;
	}
	else
		khz_new_scan_step = KHz_scan_step;

	/* Load FR_LIM register */
	/* The conversion factor is 33, but 34 used to provide a small overlap. */
	buffer[0] = (BYTE) ((((khz_new_scan_step >> 1) * 34) >> 12) & 0xFF);
	if ((status = VP310_Write_Registers(VP310_FR_LIM, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
		return status;

	*V_channel_cnt = 0;
	*H_channel_cnt = 0;
	total_channel_cnt = 0;
	*scan_time_ms = 0;
	scan_start_time = clock();

	if (lnb_tone_search_on)
		khz22_loop_lim			= 2;
	else
		khz22_loop_lim			= 1;
	if (scan_up)
		scan_factor = 1;
	else
		scan_factor = -1;

	for (i=0; i<2; i++)
	{
		/* First try Vertical polarisation, Then horizontal */
		lnb_params_temp.enPolar = int2lnbpolar(i);
		channel_cnt[i] = 0;

		for (khz22_loop_cnt=0; khz22_loop_cnt < khz22_loop_lim; khz22_loop_cnt++)
		{
			/* If lnb tone search is enabled, first try TONE_OFF */
			if (lnb_tone_search_on)
				lnb_params_temp.enTone = int2lnbtone(khz22_loop_cnt);
			else
				lnb_params_temp.enTone = lnb_params.enTone;
			set_diseqc = VP310_TRUE;
			if (scan_up)
				KHz_tuner_freq = KHz_tuner_freq_min;
			else
				KHz_tuner_freq = KHz_tuner_freq_max;

			scan_complete = VP310_FALSE;
			while (!scan_complete)
			{
				status = VP310_acquire_channel(	KHz_tuner_freq,
												lnb_params_temp,
												kbd_params,
												code_rate,
												iq_mode,
												AFC_on,
												set_diseqc,
												qpsk_lock_time_lim_ms,
												fec_lock_time_lim_ms,
												&sym_rate_index,
												&KHz_freq_offset,
												&channel_params_temp,
												&qpsk_acq_time_ms,
												&acq_time_ms);
			
				set_diseqc = VP310_FALSE;
				if (status == VP310_LOCK)
				{
					printf("\nChannel found at tuner frequency %ld KHz\n", KHz_tuner_freq + KHz_freq_offset);
					channel_params_temp.KHz_tuner_freq += KHz_freq_offset;
					*(channel_params + total_channel_cnt) = channel_params_temp;
					total_channel_cnt++;
					(channel_cnt[i])++;
					/* First go to the edge of the current channel */
					KHz_tuner_freq = (channel_params_temp.KHz_tuner_freq) + (scan_factor * (((channel_params_temp.KBd_rate)*11) >> 4));
					/* Then go half a step */
					KHz_tuner_freq = KHz_tuner_freq + (scan_factor * (khz_new_scan_step >> 1));
					/* Note that scan_factor is +1 for scan_up and -1 for scan_down */
				}
				else if (	!( (status != TUNER_NO_LOCK) || (status != VP310_NO_FEC_LOCK) || 
							   (status != VP310_NO_QPSK_LOCK) )	) /* Then there is an I2C error */
					return status;
				else
					KHz_tuner_freq = KHz_tuner_freq + (scan_factor*khz_new_scan_step);

				if ( (KHz_tuner_freq < (KHz_tuner_freq_min - 1000)) || (KHz_tuner_freq > (KHz_tuner_freq_max + 1000)) )
					scan_complete = VP310_TRUE;
			} /* One lnb tone option has been tried */
		} /* One polarisation option has been tried */
	} /* Both polarisations have been tried */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -