Re: Re : Re : No lock possible at some DVB-S2 channels with TT S2-3200/linux

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux