more cx24123

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

 



A few more cx24123 patches:

cx24123-sdthresh.patch simply sets the soft decision threshold properly for the specified FEC rate. For the DVB standard, it's very simple -- it's only different for the 1/2 FEC rate. However, the spec recommends this, so it should be done.

cx24123-errcnt.patch changes the bit error counter configuration to be actual BER (previously it was returning a ucblocks value for both ucblocks and BER), and eliminates ucblocks entirely (it isn't practical to get both values with this demod, and IMO BER is more important)

It also replaces the BER-threshold-based SNR estimation with something based on the demod's Es/No counter. It's still totally bogus, since the card only gives Es/No in a raw count (of symbols observed below a certain amplitude threshold) and it's not clear to me exactly how to convert that into a meaningful Es/No so that it could be ultimately turned into a proper SNR dB figure. But it's still better than the BER-based figure, for a couple of reasons: the BER window is large enough that it doesn't update very frequently (especially for lower symbol rates), and you need a signal lock to get any BER data whereas the Es/No does not (so you get data even when there's no signal lock) -- in practical tests, the count ranges from around 32k for me with little or no signal, to a very strong signal giving nearly full scale 64k. I'm sure additional math can be done on this value to improve its meaningfulness, but it's at least the right raw quantity to base SNR on and it's much more useful even in this bogus form.

cx24123-hwalgo.patch changes this card to use HW algo tuning. This has been one of the driver's main problems from the beginning, and as a user I've always partially gotten around the issue by changing the module parameter that lets you alter swzigzag speed to some absurdly high value. This demod has a very robust acquistion and carrier tracking loop built into it -- you can set the acquisition and lock band to be anywhere from fsamplerate/8 all the way up to 10MHz, and it tracks relatively quickly. The problem is that some types of signals (low symbol rates especially) can take a few hundred milliseconds to tune under some circumstances, and with the software zigzag or retuning on, it prevents the demod's state machine from ever reaching the tuned state -- every time it does a retune it resets the whole search back to zero, so it ends up searching just part of the acquisiton space over and over again and never acquiring lock. (I think the AGC may be reset by a retune too, which if that's true is probably most of the problem right there)

Given that the demod itself already has a state machine that seems to be at least as good as what the swzigzag and other dvb_frontend retuning does, and they conflict in ways that sometimes prevent or delay tuning, I think the best thing right now is to disable SW tuning for this card. It improves performance dramatically for me anyway (especially with low symbol rates)

Comments and/or testing welcome.

-y

diff -r 265f2c767b45 linux/drivers/media/dvb/frontends/cx24123.c
--- a/linux/drivers/media/dvb/frontends/cx24123.c	Mon Jul 24 15:19:37 2006 -0300
+++ b/linux/drivers/media/dvb/frontends/cx24123.c	Wed Jul 26 02:43:51 2006 -0400
@@ -332,6 +332,12 @@ static int cx24123_set_fec(struct cx2412
 	if ( (fec < FEC_NONE) || (fec > FEC_AUTO) )
 		fec = FEC_AUTO;
 
+	/* Set the soft decision threshold */ 
+	if(fec == FEC_1_2)
+		cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) | 0x01);
+	else
+		cx24123_writereg(state, 0x43, cx24123_readreg(state, 0x43) & ~0x01);	
+
 	switch (fec) {
 	case FEC_1_2:
 		dprintk("%s:  set FEC to 1/2\n",__FUNCTION__);
diff -r 265f2c767b45 linux/drivers/media/dvb/frontends/cx24123.c
--- a/linux/drivers/media/dvb/frontends/cx24123.c	Mon Jul 24 15:19:37 2006 -0300
+++ b/linux/drivers/media/dvb/frontends/cx24123.c	Wed Jul 26 04:17:46 2006 -0400
@@ -45,9 +45,6 @@ struct cx24123_state
 
 	struct dvb_frontend frontend;
 
-	u32 lastber;
-	u16 snr;
-
 	/* Some PLL specifics for tuning */
 	u32 VCAarg;
 	u32 VGAarg;
@@ -234,7 +229,7 @@ static struct {
 	{0x44, 0x00}, /* Constellation (default) */
 	{0x45, 0x00}, /* Symbol count (default) */
 	{0x46, 0x0d}, /* Symbol rate estimator on (default) */
-	{0x56, 0x41}, /* Various (default) */
+	{0x56, 0xc1}, /* Error Counter = Viterbi BER */
 	{0x57, 0xff}, /* Error Counter Window (default) */
 	{0x67, 0x83}, /* Non-DCII symbol clock */
 };
@@ -806,29 +801,13 @@ static int cx24123_read_ber(struct dvb_f
 {
 	struct cx24123_state *state = fe->demodulator_priv;
 
-	state->lastber =
-		((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+	/* The true bit error rate is this value divided by
+	   the window size (set as 256 * 255) */
+	*ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
 		(cx24123_readreg(state, 0x1d) << 8 |
-		cx24123_readreg(state, 0x1e));
-
-	/* Do the signal quality processing here, it's derived from the BER. */
-	/* Scale the BER from a 24bit to a SNR 16 bit where higher = better */
-	if (state->lastber < 5000)
-		state->snr = 655*100;
-	else if ( (state->lastber >=   5000) && (state->lastber <  55000) )
-		state->snr = 655*90;
-	else if ( (state->lastber >=  55000) && (state->lastber < 150000) )
-		state->snr = 655*80;
-	else if ( (state->lastber >= 150000) && (state->lastber < 250000) )
-		state->snr = 655*70;
-	else if ( (state->lastber >= 250000) && (state->lastber < 450000) )
-		state->snr = 655*65;
-	else
-		state->snr = 0;
-
-	dprintk("%s:  BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr);
-
-	*ber = state->lastber;
+		 cx24123_readreg(state, 0x1e));
+
+	dprintk("%s:  BER = %d\n",__FUNCTION__,*ber);
 
 	return 0;
 }
@@ -846,19 +825,13 @@ static int cx24123_read_snr(struct dvb_f
 static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
-	*snr = state->snr;
+
+	/* Inverted raw Es/N0 count, totally bogus but better than the
+	   BER threshold. */
+	*snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+			 (u16)cx24123_readreg(state, 0x19));
 
 	dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
-
-	return 0;
-}
-
-static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	*ucblocks = state->lastber;
-
-	dprintk("%s:  ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks);
 
 	return 0;
 }
@@ -960,8 +933,6 @@ struct dvb_frontend* cx24123_attach(cons
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	state->lastber = 0;
-	state->snr = 0;
 	state->VCAarg = 0;
 	state->VGAarg = 0;
 	state->bandselectarg = 0;
@@ -1014,7 +985,6 @@ static struct dvb_frontend_ops cx24123_o
 	.read_ber = cx24123_read_ber,
 	.read_signal_strength = cx24123_read_signal_strength,
 	.read_snr = cx24123_read_snr,
-	.read_ucblocks = cx24123_read_ucblocks,
 	.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
 	.diseqc_send_burst = cx24123_diseqc_send_burst,
 	.set_tone = cx24123_set_tone,
diff -r 265f2c767b45 linux/drivers/media/dvb/frontends/cx24123.c
--- a/linux/drivers/media/dvb/frontends/cx24123.c	Mon Jul 24 15:19:37 2006 -0300
+++ b/linux/drivers/media/dvb/frontends/cx24123.c	Wed Jul 26 01:57:22 2006 -0400
@@ -933,6 +933,29 @@ static int cx24123_set_tone(struct dvb_f
 	return 0;
 }
 
+static int cx24123_tune(struct dvb_frontend* fe,
+			struct dvb_frontend_parameters* params,
+			unsigned int mode_flags,
+			int *delay,
+			fe_status_t *status)
+{
+	int retval = 0;
+
+	if (params != NULL)
+		retval = cx24123_set_frontend(fe, params);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		cx24123_read_status(fe, status);
+	*delay = HZ/10;
+
+	return retval;
+}
+
+static int cx24123_get_algo(struct dvb_frontend *fe)
+{
+	return 1; //FE_ALGO_HW
+}
+
 static void cx24123_release(struct dvb_frontend* fe)
 {
 	struct cx24123_state* state = fe->demodulator_priv;
@@ -1019,6 +1042,8 @@ static struct dvb_frontend_ops cx24123_o
 	.diseqc_send_burst = cx24123_diseqc_send_burst,
 	.set_tone = cx24123_set_tone,
 	.set_voltage = cx24123_set_voltage,
+	.tune = cx24123_tune,
+	.get_frontend_algo = cx24123_get_algo,
 };
 
 module_param(debug, int, 0644);
_______________________________________________

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