Hi, On Thursday 22 May 2008, Ales Jurik wrote: > Hi, > > my friend told me that he is sometimes able to get lock by decreasing (not > increasing) the frequency. Yesterday I've tested it and it seems to me he was > right. So I'm able to get (not very stable, for few minutes) lock as well as > by increasing and by decreasing frequency of the same channel (EurosportHD). The derotator code in the stb0899 seems to be setting the initial frequency to the lowest search range and never changes this (as it should increase steadily to find a lock) > > It was also detected (not by me, I don't have riser card) that when the card > is connected not directly into PCI slot but with some riser card, the needed > difference for getting lock is higher (up to 10MHz). So also some noise from > PC is going into calculations. > > I don't think the problem is in computation of frequency but in for example > not stable signal amplitude at input of demodulator or in not fluently > changing the gain and bandwith of tuner within the band. As I see in the code > some parameters are changing in steps and maybe 3 steps for whole band is not > enough? Especially in real conditions (not in lab)? Could you please try the attached patch if this fixes the problem with nominal frequency/symbolrate settings? > > But under Windows no problems were detected, so it seems that all that > problems are solveable by driver (software). > > BR, > > Ales > > > > _______________________________________________ > linux-dvb mailing list > linux-dvb@xxxxxxxxxxx > http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb > Dominik
diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_algo.c --- a/linux/drivers/media/dvb/frontends/stb0899_algo.c Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_algo.c Sun Jun 15 11:37:56 2008 +0200 @@ -48,6 +48,49 @@ static u32 stb0899_calc_srate(u32 master tmp >>= 24; return tmp; +} + +s32 stb0899_get_frequency_offset(struct stb0899_state *state) { + s32 offset = 0; + s16 w; + u8 cfr[2]; + + struct stb0899_internal *internal = &state->internal; + switch (state->delsys) { + case DVBFE_DELSYS_DVBS: + stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */ + /* don't why it is 3/2 here */ + w = MAKEWORD16(cfr[0], cfr[1]); + offset = w * 3/2; + break; + case DVBFE_DELSYS_DVBS2: + offset = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); + if (offset & 0x20000000) { + /* sign extension */ + offset |= 0xc0000000; + } + /* + * what is the range of offsetfreq here: assume +- 20MHz as sane range + * 1MHz -> offsetfreq = 1000kHz * (2^30/1000) / 99 = 10 845 877 + * offset/kHz = offsetfreq * mclk / 1e6 / 2^30 * 1e3 + * = (((offsetfreq / 1024) * 1000) * (mclk/1e6)) / 2^20 + */ +#if 0 + /* 64 Bit arithmetic */ + offset = (s32)((s64)offset * + ((s64)internal->master_clk / (s64)1000000) / + (s64)((1 << 30) / (s64)1000)); +#else + /* 32 Bit arithmetic */ + offset = ((((offset / 1024) * 1000) / (1<<7)) * (s32)(internal->master_clk/1000000)) / (s32)(1<<13); +#endif + break; + case DVBFE_DELSYS_DSS: + default: + /* TODO: */ + break; + } + return offset; } /* @@ -132,6 +175,8 @@ long stb0899_carr_width(struct stb0899_s return (internal->srate + (internal->srate * internal->rolloff) / 100); } + +#if 0 /* * stb0899_first_subrange * Compute the first subrange of the search @@ -161,6 +206,7 @@ static void stb0899_first_subrange(struc internal->tuner_offst = 0L; internal->sub_dir = 1; } +#endif /* * stb0899_check_tmg @@ -212,7 +258,7 @@ static enum stb0899_status stb0899_searc internal->status = NOTIMING; /* timing loop computation & symbol rate optimisation */ - derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_limit = 0;//(internal->sub_range / 2L) / internal->mclk; derot_step = (params->srate / 2L) / internal->mclk; while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { @@ -267,6 +313,7 @@ static enum stb0899_status stb0899_check return internal->status; } +#if 0 /* * stb0899_search_carrier * Search for a QPSK carrier with the derotator @@ -322,6 +369,7 @@ static enum stb0899_status stb0899_searc return internal->status; } +#endif /* * stb0899_check_data @@ -390,7 +438,7 @@ static enum stb0899_status stb0899_searc struct stb0899_params *params = &state->params; derot_step = (params->srate / 4L) / internal->mclk; - derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_limit = 0;//(internal->sub_range / 2L) / internal->mclk; derot_freq = internal->derot_freq; do { @@ -426,6 +474,7 @@ static enum stb0899_status stb0899_searc return internal->status; } +#if 0 /* * stb0899_check_range * check if the found frequency is in the correct range @@ -477,6 +526,7 @@ static void next_sub_range(struct stb089 internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000; internal->sub_dir = -internal->sub_dir; } +#endif /* * stb0899_dvbs_algo @@ -494,6 +544,7 @@ enum stb0899_status stb0899_dvbs_algo(st u8 eq_const[10]; s32 clnI = 3; u32 bandwidth = 0; + int count; /* BETA values rated @ 99MHz */ s32 betaTab[5][4] = { @@ -571,7 +622,9 @@ enum stb0899_status stb0899_dvbs_algo(st stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */ stb0899_write_reg(state, STB0899_VITSYNC, 0x19); - stb0899_first_subrange(state); + /* start where the user told us.... */ + internal->freq = params->freq; + count = 0; do { /* Initialisations */ cfr[0] = cfr[1] = 0; @@ -589,7 +642,7 @@ enum stb0899_status stb0899_dvbs_algo(st stb0899_i2c_gate_ctrl(&state->frontend, 1); /* Move tuner to frequency */ - dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency"); + dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency: %d", internal->freq); if (state->config->tuner_set_frequency) state->config->tuner_set_frequency(&state->frontend, internal->freq); @@ -617,7 +670,7 @@ enum stb0899_status stb0899_dvbs_algo(st "TIMING OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - if (stb0899_search_carrier(state) == CARRIEROK) { /* Search for carrier */ + if (stb0899_check_carrier(state) == CARRIEROK) { /* Check for carrier */ dprintk(state->verbose, FE_DEBUG, 1, "CARRIER OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); @@ -627,12 +680,13 @@ enum stb0899_status stb0899_dvbs_algo(st "DATA OK ! Derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - if (stb0899_check_range(state) == RANGEOK) { + internal->status = RANGEOK; dprintk(state->verbose, FE_DEBUG, 1, "RANGE OK ! derot freq=%d, mclk=%d", internal->derot_freq, internal->mclk); - internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000); + dprintk(state->verbose, FE_DEBUG, 1, "derot=%d user_freq=%d\n", internal->derot_freq, params->freq); + internal->freq = params->freq + stb0899_get_frequency_offset(state); reg = stb0899_read_reg(state, STB0899_PLPARM); internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg); dprintk(state->verbose, FE_DEBUG, 1, @@ -642,14 +696,13 @@ enum stb0899_status stb0899_dvbs_algo(st dprintk(state->verbose, FE_DEBUG, 1, "internal puncture rate=%d", internal->fecrate); - } } } } - if (internal->status != RANGEOK) - next_sub_range(state); - } while (internal->sub_range && internal->status != RANGEOK); + /* avoid infinite loop */ + count++; + } while (count < 3 && internal->status != RANGEOK); /* Set the timing loop to tracking */ stb0899_write_reg(state, STB0899_RTC, 0x33); @@ -1491,16 +1544,8 @@ enum stb0899_status stb0899_dvbs2_algo(s STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02); stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg); - /* Store signal parameters */ - offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ); - - offsetfreq = offsetfreq / ((1 << 30) / 1000); - offsetfreq *= (internal->master_clk / 1000000); - reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2); - if (STB0899_GETFIELD(SPECTRUM_INVERT, reg)) - offsetfreq *= -1; - - internal->freq = internal->freq - offsetfreq; + /* store acutal frequency */ + internal->freq = internal->freq + stb0899_get_frequency_offset(state); internal->srate = stb0899_dvbs2_get_srate(state); reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_drv.c --- a/linux/drivers/media/dvb/frontends/stb0899_drv.c Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c Sun Jun 15 11:37:56 2008 +0200 @@ -1718,6 +1718,7 @@ static enum dvbfe_search stb0899_search( return DVBFE_ALGO_SEARCH_ERROR; } +#if 0 static enum stb0899_status stb0899_track_carrier(struct stb0899_state *state) { u8 reg; @@ -1906,6 +1907,8 @@ static int stb0899_get_modcod(struct stb return 0; } +#endif + /* * stb0899_track * periodically check the signal level against a specified @@ -1992,6 +1995,8 @@ static int stb0899_get_params(struct dvb { struct stb0899_state *state = fe->demodulator_priv; struct stb0899_internal *internal = &state->internal; + struct stb0899_params *intparams = &state->params; + params->frequency = internal->freq; params->inversion = internal->inversion; @@ -1999,6 +2004,7 @@ static int stb0899_get_params(struct dvb switch (state->delsys) { case DVBFE_DELSYS_DVBS: dprintk(verbose, FE_DEBUG, 1, "Get DVB-S params"); + params->frequency = intparams->freq + stb0899_get_frequency_offset(state); params->delsys.dvbs.symbol_rate = internal->srate; params->delsys.dvbs.modulation = DVBFE_MOD_QPSK; break; @@ -2009,6 +2015,9 @@ static int stb0899_get_params(struct dvb break; case DVBFE_DELSYS_DVBS2: dprintk(verbose, FE_DEBUG, 1, "Get DVB-S2 params"); + + params->frequency = intparams->freq + stb0899_get_frequency_offset(state); + params->delsys.dvbs2.symbol_rate = internal->srate; break; default: diff -r fbcc9fa65f56 linux/drivers/media/dvb/frontends/stb0899_priv.h --- a/linux/drivers/media/dvb/frontends/stb0899_priv.h Wed May 28 12:08:48 2008 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_priv.h Sun Jun 15 11:37:56 2008 +0200 @@ -165,13 +165,11 @@ struct stb0899_params { struct stb0899_internal { u32 master_clk; - u32 freq; /* Demod internal Frequency */ + u32 freq; /* Demod internal Frequency (kHz) */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ + u32 srch_range; /* Demod internal Search Range (Hz) */ u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ @@ -184,7 +182,6 @@ struct stb0899_internal { s16 derot_step; /* Derotator step (binary value) */ s16 t_derot; /* Derotator time constant (ms) */ s16 t_data; /* Data recovery time constant (ms) */ - s16 sub_dir; /* Direction of the next sub range */ s16 t_agc1; /* Agc1 time constant (ms) */ s16 t_agc2; /* Agc2 time constant (ms) */ @@ -270,5 +267,11 @@ extern enum stb0899_status stb0899_dvbs_ extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state); extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state); extern long stb0899_carr_width(struct stb0899_state *state); +/* + * read offset registers and + * calculate frequency offset in kHz + * according to the currently selected standard + */ +extern s32 stb0899_get_frequency_offset(struct stb0899_state *state); #endif //__STB0899_PRIV_H
Attachment:
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb