[media] dib8000: make a better estimation for dBm
Use multiple linear segments to better interpolate the dBm for the signal strength. The table that converts from linear strength to dB was empirically determinated with the help of a signal generator (DTA-2111). The entries from -35dBm to -22.5dBm were taken using just the signal generator and the board. For the entries from -36dBm to -51dBm, a 16 dB tap was used, in order to extend its range. Signals below to -51dBm are just linearly interpolated. Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> Acked-by: Patrick Boettcher <pboettcher@kernellabs.com>
This commit is contained in:
Родитель
b4600d70c0
Коммит
42ff76bdb0
|
@ -3843,35 +3843,108 @@ static const struct per_layer_regs per_layer_regs[] = {
|
|||
{ 556, 581, 583 },
|
||||
};
|
||||
|
||||
struct linear_segments {
|
||||
unsigned x;
|
||||
signed y;
|
||||
};
|
||||
|
||||
/*
|
||||
* Table to estimate signal strength in dBm.
|
||||
* This table was empirically determinated by measuring the signal
|
||||
* strength generated by a DTA-2111 RF generator directly connected into
|
||||
* a dib8076 device (a PixelView PV-D231U stick), using a good quality
|
||||
* 3 meters RC6 cable and good RC6 connectors.
|
||||
* The real value can actually be different on other devices, depending
|
||||
* on several factors, like if LNA is enabled or not, if diversity is
|
||||
* enabled, type of connectors, etc.
|
||||
* Yet, it is better to use this measure in dB than a random non-linear
|
||||
* percentage value, especially for antenna adjustments.
|
||||
* On my tests, the precision of the measure using this table is about
|
||||
* 0.5 dB, with sounds reasonable enough.
|
||||
*/
|
||||
static struct linear_segments strength_to_db_table[] = {
|
||||
{ 55953, 108500 }, /* -22.5 dBm */
|
||||
{ 55394, 108000 },
|
||||
{ 53834, 107000 },
|
||||
{ 52863, 106000 },
|
||||
{ 52239, 105000 },
|
||||
{ 52012, 104000 },
|
||||
{ 51803, 103000 },
|
||||
{ 51566, 102000 },
|
||||
{ 51356, 101000 },
|
||||
{ 51112, 100000 },
|
||||
{ 50869, 99000 },
|
||||
{ 50600, 98000 },
|
||||
{ 50363, 97000 },
|
||||
{ 50117, 96000 }, /* -35 dBm */
|
||||
{ 49889, 95000 },
|
||||
{ 49680, 94000 },
|
||||
{ 49493, 93000 },
|
||||
{ 49302, 92000 },
|
||||
{ 48929, 91000 },
|
||||
{ 48416, 90000 },
|
||||
{ 48035, 89000 },
|
||||
{ 47593, 88000 },
|
||||
{ 47282, 87000 },
|
||||
{ 46953, 86000 },
|
||||
{ 46698, 85000 },
|
||||
{ 45617, 84000 },
|
||||
{ 44773, 83000 },
|
||||
{ 43845, 82000 },
|
||||
{ 43020, 81000 },
|
||||
{ 42010, 80000 }, /* -51 dBm */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static u32 interpolate_value(u32 value, struct linear_segments *segments,
|
||||
unsigned len)
|
||||
{
|
||||
u64 tmp64;
|
||||
u32 dx;
|
||||
s32 dy;
|
||||
int i, ret;
|
||||
|
||||
if (value >= segments[0].x)
|
||||
return segments[0].y;
|
||||
if (value < segments[len-1].x)
|
||||
return segments[len-1].y;
|
||||
|
||||
for (i = 1; i < len - 1; i++) {
|
||||
/* If value is identical, no need to interpolate */
|
||||
if (value == segments[i].x)
|
||||
return segments[i].y;
|
||||
if (value > segments[i].x)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Linear interpolation between the two (x,y) points */
|
||||
dy = segments[i - 1].y - segments[i].y;
|
||||
dx = segments[i - 1].x - segments[i].x;
|
||||
|
||||
tmp64 = value - segments[i].x;
|
||||
tmp64 *= dy;
|
||||
do_div(tmp64, dx);
|
||||
ret = segments[i].y + tmp64;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
|
||||
{
|
||||
struct dib8000_state *state = fe->demodulator_priv;
|
||||
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
|
||||
int i, lock;
|
||||
u64 tmp;
|
||||
u32 snr, val;
|
||||
s32 db;
|
||||
u16 strength;
|
||||
|
||||
/* Get Signal strength */
|
||||
dib8000_read_signal_strength(fe, &strength);
|
||||
|
||||
/*
|
||||
* Estimate it in dBm
|
||||
* This calculus was empirically determinated by measuring the signal
|
||||
* strength generated by a DTA-2111 RF generator directly connected into
|
||||
* a dib8076 device. The real value can actually be different on other
|
||||
* devices, depending if LNA is enabled or not, if diversity is enabled,
|
||||
* etc.
|
||||
*/
|
||||
if (strength == 65535) {
|
||||
c->strength.stat[0].svalue = -22000;
|
||||
} else {
|
||||
tmp = strength * 25000L;
|
||||
do_div(tmp, 11646);
|
||||
c->strength.stat[0].svalue = tmp - 142569;
|
||||
if (c->strength.stat[0].svalue > -22000)
|
||||
c->strength.stat[0].svalue = -22000;
|
||||
}
|
||||
val = strength;
|
||||
db = interpolate_value(val,
|
||||
strength_to_db_table,
|
||||
ARRAY_SIZE(strength_to_db_table)) - 131000;
|
||||
c->strength.stat[0].svalue = db;
|
||||
|
||||
/* Check if 1 second was elapsed */
|
||||
if (!time_after(jiffies, state->get_stats_time))
|
||||
|
|
Загрузка…
Ссылка в новой задаче