📄 vp310_driver.c
字号:
*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 + -