From: Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> --- 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); _______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb