📄 vp310_driver.c
字号:
*scan_time_ms = clock() - scan_start_time;
*V_channel_cnt = channel_cnt[0];
*H_channel_cnt = channel_cnt[1];
return VP310_NO_ERROR;
}
/*-----------------------------------------------------------------------------------------------*/
/* Obtaining channel parameters */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS
VP310_get_channel_status( ULONG KHz_tuner_freq,
VP310_CHANNEL_PARAMS *channel_params,
int *KHz_freq_offset)
{
VP310_CHANNEL_PARAMS channel_params_init = { 1000000, CODE_3_4, 27500, IQ_NORMAL,
POL_VERTICAL, TONE_OFF};
VP310_STATUS status;
BYTE buffer[8];
VP310_BOOLEAN fec_locked;
/* Note that this function does NOT include the offset frequency in the KHz_tuner_freq
of channel_params. */
*channel_params = channel_params_init;
channel_params->KHz_tuner_freq = KHz_tuner_freq;
/* Read VP310 registers for code rate and frequency offset */
if ((status = VP310_Read_Registers(VP310_FEC_STATUS, buffer, 3, VP310_FALSE)) != VP310_NO_ERROR)
return status;
*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;
channel_params->code_rate = int2coderate((buffer[0] >> 4) & 7, VP310_TRUE);
if ((buffer[0] & 12) == 12)
fec_locked = VP310_TRUE;
else
fec_locked = VP310_FALSE;
/* Read VP310 registers for Baud rate */
if ((status = VP310_Read_Registers(VP310_MONITOR_H, buffer, 2, VP310_FALSE)) != VP310_NO_ERROR)
return status;
channel_params->KBd_rate = (((buffer[0] << 8) + buffer[1]) * 1000) >> 10;
/* Read VP310 registers for spectral inversion */
if ((status = VP310_Read_Registers(VP310_VIT_MODE, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
return status;
channel_params->iq_mode = int2iqmode((buffer[0] >> 6) & 1);
/* Read VP310 registers for polarisation and 22 kHz */
if ((status = VP310_Read_Registers(VP310_DISEQC_MODE, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
return status;
channel_params->lnb_polar = int2lnbpolar((buffer[0] >> 6) & 1);
channel_params->khz_22 = int2lnbtone((buffer[0]) & 1);
if (fec_locked)
return VP310_LOCK;
else
return VP310_NO_FEC_LOCK;
}
/*-----------------------------------------------------------------------------------------------*/
/* Centering channel */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS
VP310_centre_channel( VP310_CHANNEL_PARAMS *channel_params,
UINT lock_time_lim_ms,
int *KHz_freq_offset,
ULONG *KHz_tuner_freq,
ULONG *acq_time_ms)
/* This program will modify the data structure channel_params, to reflect new tuner frequency */
{
VP310_BOOLEAN fec_lock;
clock_t start_time, current_time;
VP310_STATUS status;
BYTE buffer[8];
*acq_time_ms = 0;
*KHz_freq_offset = 0;
/* Read VP310 registers for lock status and frequency offset */
if ((status = VP310_Read_Registers(VP310_FEC_STATUS, buffer, 3, VP310_FALSE)) != VP310_NO_ERROR)
return status;
if ((buffer[0] & 12) != 12)
return VP310_NO_FEC_LOCK; /* There is little point in trying to centre a channel
without lock */
*KHz_freq_offset = ((buffer[1] & 0x7F) << 8) + buffer[2] - ((buffer[1] & 128) << 8);
*KHz_freq_offset = ((*KHz_freq_offset) * 1000) >> 9;
*KHz_tuner_freq = channel_params->KHz_tuner_freq + (*KHz_freq_offset);
channel_params->KHz_tuner_freq = *KHz_tuner_freq;
/* Program tuner synthesiser */
if ((status = VP310_program_tuner(*KHz_tuner_freq, lock_time_lim_ms)) != VP310_NO_ERROR)
return status;
/* Apply GO pulse */
buffer[0] = 1;
if ((status = VP310_Write_Registers(VP310_GO, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
return status;
start_time = clock();
current_time = start_time;
*acq_time_ms = 0L;
fec_lock = VP310_FALSE;
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;
if ((buffer[0] & 12) == 12)
{
fec_lock = VP310_TRUE;
break;
}
go_to_sleep(DELTA_LOCK_DET_MS);
current_time = clock();
*acq_time_ms = current_time - start_time;
}
/* Read frequency offset for test purposes */
if ((status = VP310_Read_Registers(VP310_LNB_FREQ_H, buffer, 2, VP310_FALSE)) != VP310_NO_ERROR)
return status;
if (fec_lock)
{
*KHz_freq_offset = ((buffer[0] & 0x7F) << 8) + buffer[1] - ((buffer[0] & 128) << 8);
*KHz_freq_offset = ((*KHz_freq_offset) * 1000) >> 9;
return VP310_LOCK;
}
else
{
return VP310_NO_FEC_LOCK;
*KHz_freq_offset = 10000;
}
}
/*----------------------------------------------------------------------------------------------*/
/* Obtaining QPSK Bit Error Rate (BER) */
/*----------------------------------------------------------------------------------------------*/
VP310_STATUS
VP310_get_ber ( UINT ber_time_in_seconds,
VP310_BOOLEAN qpsk_ber_only,
float *qpsk_ber,
ULONG *qpsk_bit_errors,
float *vit_ber,
ULONG *vit_bit_errors,
float *rs_ber,
ULONG *rs_blk_errors
)
{
clock_t start_time;
ULONG elapsed_time;
VP310_STATUS status;
BYTE buffer[10];
BYTE code_rate, sym_rate_mbd_h, sym_rate_mbd_l;
VP310_BOOLEAN first_int_recd;
ULONG vit_dec_bits;
*qpsk_ber = 0.0;
*qpsk_bit_errors = 0;
*vit_ber = 0.0;
*vit_bit_errors = 0;
*rs_ber = 0.0;
*rs_blk_errors = 0;
/* Clearing FEC_INT register and testing lock and getting code rate */
if ((status = VP310_Read_Registers(VP310_FEC_INT, buffer, 4, VP310_FALSE)) != VP310_NO_ERROR)
return status;
if ((buffer[3] & 12) != 12)
return VP310_NO_FEC_LOCK;
code_rate = (buffer[3] >> 4) & 7;
/* Read symbol rate */
if ((status = VP310_Read_Registers(VP310_MONITOR_H, buffer, 2, VP310_FALSE)) != VP310_NO_ERROR)
return status;
sym_rate_mbd_h = buffer[0];
sym_rate_mbd_l = buffer[1];
/* Clear RS BER and RS Block error registers by reading them */
if ((status = VP310_Read_Registers(VP310_RS_BERCNT_H, buffer, 5, VP310_FALSE)) != VP310_NO_ERROR)
return status;
start_time = clock();
elapsed_time = 0;
while (elapsed_time < (ber_time_in_seconds*1000))
{
if (qpsk_ber_only)
{
if ((status = VP310_Read_Registers(VP310_FEC_INT, buffer, 1, VP310_FALSE)) != VP310_NO_ERROR)
return status;
if ((buffer[0] & 4) != 0)
if (!first_int_recd)
first_int_recd = VP310_TRUE;
else
{
/* Read Viterbi bit error count registers and form qpsk_ber */
if ((status = VP310_Read_Registers(VP310_VIT_ERRCNT_H, buffer, 3, VP310_FALSE)) != VP310_NO_ERROR)
return status;
*qpsk_bit_errors = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
*qpsk_ber = ((float)(*qpsk_bit_errors))/((float)(1 << 26));
return VP310_NO_ERROR;
}
}
go_to_sleep(10);
elapsed_time = clock() - start_time;
}
if (qpsk_ber_only)
return VP310_BER_TIME_TOO_SMALL;
/* Read all BER registers */
if ((status = VP310_Read_Registers(VP310_VIT_ERRCNT_H, buffer, 8, VP310_FALSE)) != VP310_NO_ERROR)
return status;
*qpsk_bit_errors = (buffer[0] << 16) + (buffer[1] << 8) + buffer[2];
*qpsk_ber = ((float)(*qpsk_bit_errors))/((float)(1 << 26));
/* Get the number of RS detected bit errors */
*vit_bit_errors = (buffer[3] << 16) + (buffer[4] << 8) + buffer[5];
/* Get symbol rate in Baud */
vit_dec_bits = (((sym_rate_mbd_h << 8) + (sym_rate_mbd_l)) * 1000000) >> 10;
/* Include coding rate information, assuming QPSK */
switch (code_rate)
{
case 0 : vit_dec_bits = vit_dec_bits; break;
case 1 : (vit_dec_bits = vit_dec_bits * 4)/3; break;
case 2 : (vit_dec_bits = vit_dec_bits * 6)/4; break;
case 3 : (vit_dec_bits = vit_dec_bits * 10)/6; break;
case 5 : (vit_dec_bits = vit_dec_bits * 16)/7; break;
default: vit_dec_bits = vit_dec_bits;
}
*vit_ber = ((float) (*vit_bit_errors)) / ( ((float) vit_dec_bits) * ((float) ber_time_in_seconds) );
*rs_blk_errors = (buffer[6] << 8) + buffer[7];
*rs_ber = (((float) (*rs_blk_errors)) * 1632) / ( ((float) vit_dec_bits) * ((float) ber_time_in_seconds) );
return VP310_NO_ERROR;
}
/*-----------------------------------------------------------------------------------------------*/
/* obtain AGC value */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS VP310_get_agc_value (float *fe_agc)
{
VP310_STATUS status;
BYTE buffer[8];
if ((status = VP310_Read_Registers(VP310_AGC_H, buffer, 2, VP310_FALSE)) != VP310_NO_ERROR)
return status;
*fe_agc = ( (float) ((buffer[0]<<6) + ((buffer[1] >> 2) & 0x3F)))/((float) (1 << 14));
return VP310_NO_ERROR;
}
/*-----------------------------------------------------------------------------------------------*/
/* Read VP310 registers */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS
VP310_Read_Registers(BYTE address, BYTE *buffer, BYTE no_of_bytes, VP310_BOOLEAN i2c_tuner_access_on)
{
VP310_STATUS status;
BYTE i, usDevice_Id;
if (i2c_tuner_access_on)
usDevice_Id = tuner_device_id;
else
usDevice_Id = VP310_DEVICE_ID;
if ((address != 0) && (!i2c_tuner_access_on))
{
i = address;
if ((status = I2C_DRIVER_Write_Without_Stop(usDevice_Id, &i, 1)) != VP310_NO_ERROR)
return status;
}
if ((status = I2C_DRIVER_Read(usDevice_Id, buffer, no_of_bytes)) != VP310_NO_ERROR)
return status;
return VP310_NO_ERROR;
}
/*-----------------------------------------------------------------------------------------------*/
/* Write VP310 Registers */
/*-----------------------------------------------------------------------------------------------*/
VP310_STATUS
VP310_Write_Registers(BYTE address, BYTE *buffer, BYTE no_of_bytes, VP310_BOOLEAN i2c_tuner_access_on)
{
VP310_STATUS status;
BYTE i;
if (i2c_tuner_access_on)
{
/* We do not write an address to the tuner */
if ((status = I2C_DRIVER_Write(tuner_device_id, buffer, no_of_bytes)) != VP310_NO_ERROR)
return status;
}
else
{
for (i = no_of_bytes; i > 0; i--)
buffer[i] = buffer[i-1];
buffer[0] = address;
status = I2C_DRIVER_Write(VP310_DEVICE_ID, buffer, no_of_bytes+1);
if (status != VP310_NO_ERROR)
return status;
}
return VP310_NO_ERROR;
}
/*-----------------------------------------------------------------------------------------------*/
/* Sleeping for a short time */
/*-----------------------------------------------------------------------------------------------*/
void go_to_sleep (int sleep_time_ms)
{
clock_t start_time, current_time;
start_time = clock();
current_time = clock();
while ((current_time - start_time) < sleep_time_ms)
current_time = clock();
return;
}
/*-----------------------------------------------------------------------------------------------*/
/* Integer to enum conversion functions (needed for visual C), */
/*-----------------------------------------------------------------------------------------------*/
VP310_BOOLEAN int2boolean(int A)
{
if (A==0)
return VP310_FALSE;
else
return VP310_TRUE;
}
VP310_CODE_RATE int2coderate(int A, VP310_BOOLEAN from_vp310)
{
/* This function is different from other conversion functions.
Others convert to an enum type as defined in the enum declaration.
However, if from_vp310 = VP310_TRUE, then
this converts the 3-bit code rate in FEC_STATUS registers into enum.
Hence 5 converted to CODE_7_8, although enum value for this is 4.
Because 4 has been assigned by VP310 to DSS code rate 6/7.
If from_vp310 = VP310_TRUE, this does the conversion from
external to enum type. 4 : CODE_7_8, 5 : CODE_AUTO */
switch (A)
{
case 0 : return CODE_1_2;
case 1 : return CODE_2_3;
case 2 : return CODE_3_4;
case 3 : return CODE_5_6;
case 4 : if (from_vp310) return CODE_AUTO; /* because this is DSS 6/7 */
else return CODE_7_8;
case 5 : if (from_vp310) return CODE_7_8; /* because this is DSS 6/7 */
else return CODE_AUTO;
default : return CODE_AUTO;
}
}
VP310_IQ_MODE int2iqmode(int A)
{
if (A == 0)
return IQ_NORMAL;
else if (A == 1)
return IQ_INVERSE;
else
return IQ_AUTO;
}
VP310_LNB_POLAR int2lnbpolar(int A)
{
if (A == 0)
return POL_VERTICAL;
else
return POL_HORIZONTAL;
}
VP310_LNB_TONE int2lnbtone(int A)
{
if (A == 0)
return TONE_OFF;
else
return TONE_ON;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -