[linux-dvb] [RFC] [PATCH] Make S/N values to appear at cx24123 frontend

Mauro Carvalho Chehab mchehab at infradead.org
Thu Apr 13 18:30:42 CEST 2006


From: Mauro Carvalho Chehab  <mchehab at infradead.org>
Make S/N values to appear at cx24123 frontend with higher range

SNR is estimated based on BER. The problem is that BER estimation were not
called when reading SNR, so calls to read_snr without previously calling
read_ber produces bad results.
This patch makes it fill SNR value based at the estimative value calculated by BER.
Also, it improves SNR estimation by interpolating from the closest exponential curve
that plots the previous values.

Signed-off-by: Mauro Carvalho Chehab <mchehab at infradead.org>


---

diff -r 3f15cb7ff008 linux/drivers/media/dvb/frontends/cx24123.c
--- a/linux/drivers/media/dvb/frontends/cx24123.c	Thu Apr 13 15:40:59 2006 +0100
+++ b/linux/drivers/media/dvb/frontends/cx24123.c	Thu Apr 13 13:23:05 2006 -0300
@@ -811,21 +799,6 @@ static int cx24123_read_ber(struct dvb_f
 		(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;
@@ -843,10 +816,54 @@ static int cx24123_read_signal_strength(
 	return 0;
 }
 
+static int ber_table[][2] = {	{ 100, 4798 },
+				{  99, 5380 },
+				{  98, 6032 },
+				{  95, 8502 },
+				{  90, 15066 },
+				{  85, 26696 },
+				{  80, 47306 },
+				{  75, 83826 },
+				{  70, 148539 },
+				{  65, 263210 },
+				{  60, 466406 },
+				{  40, 4598482 },
+				{  30, 14439082} };
+
 static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
-	*snr = state->snr;
+
+	int ber, i=0;
+
+	cx24123_read_ber(fe,&ber);
+
+	/* 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
+	 * It uses linear interpolation between each segment of an exponencial
+	 * curve given by ber_table aproximated values.
+	 */
+
+	if (ber<ber_table[0][1]) {
+		*snr=65535*ber_table[0][0]/100;
+	} else {
+		*snr=0;
+		i++;
+		while (i< ARRAY_SIZE(ber_table)) {
+			if (ber>=ber_table[i-1][1] &&
+			    ber<ber_table[i][1]) {
+				int slope1=(ber_table[i-1][0]-ber_table[i][0]);
+				int slope2=(ber_table[i-1][1]-ber_table[i][1]);
+				int origin=ber_table[i-1][0]
+					  -slope1*ber_table[i-1][1]/slope2;
+				*snr=65535*(origin+((slope1*ber)/slope2))/100;
+				break;
+			}
+			i++;
+		}
+	}
+
+	state->snr = *snr;
 
 	dprintk("%s:  read S/N index = %d\n",__FUNCTION__,*snr);
 





More information about the linux-dvb mailing list