From 508119dc22d9b4730ee2996863d2fd5aaab0a5fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 19 Jan 2013 09:30:18 -0200 Subject: [PATCH] dvbv5-zap: better display BER Instead of masking the BER scale, if the device has DVBv5 stats, it will now display BER as it should be: BER= 1.45x10^-6 BER= 329x10^-9 Signed-off-by: Mauro Carvalho Chehab --- utils/dvb/Makefile.am | 2 +- utils/dvb/dvbv5-zap.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/utils/dvb/Makefile.am b/utils/dvb/Makefile.am index bab1409..86b5260 100644 --- a/utils/dvb/Makefile.am +++ b/utils/dvb/Makefile.am @@ -6,7 +6,7 @@ dvb_fe_tool_LDFLAGS = $(ARGP_LIBS) dvbv5_zap_SOURCES = dvbv5-zap.c dvbv5_zap_LDADD = ../../lib/libdvbv5/libdvbv5.la -dvbv5_zap_LDFLAGS = $(ARGP_LIBS) +dvbv5_zap_LDFLAGS = $(ARGP_LIBS) -lm dvbv5_scan_SOURCES = dvbv5-scan.c dvbv5_scan_LDADD = ../../lib/libdvbv5/libdvbv5.la diff --git a/utils/dvb/dvbv5-zap.c b/utils/dvb/dvbv5-zap.c index 6cc978d..b784df3 100644 --- a/utils/dvb/dvbv5-zap.c +++ b/utils/dvb/dvbv5-zap.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -323,12 +324,97 @@ static void print_stat(struct dtv_stats *stat, char *name, int layer, *show = 1; } +/* + * As BER/PER measures are always positive, the routine assumes + * that the value is always positive. + */ +int snprintf_eng(char *buf, int len, float val) +{ + int digits = 3; + int exp, signal = 1; + + /* If value is zero, nothing to do */ + if (val == 0.) + return snprintf(buf, len, " 0"); + + /* Take the absolute value */ + if (val < 0.) { + signal = -1; + val = -val; + } + + /* + * Converts the number into an expoent and a + * value between 0 and 1000, exclusive + */ + exp = (int)log10(val); + if (exp > 0) + exp = (exp / 3) * 3; + else + exp = (-exp + 3) / 3 * (-3); + + val *= pow(10, -exp); + + if (val >= 1000.) { + val /= 1000.0; + exp += 3; + } else if(val >= 100.0) + digits -= 2; + else if(val >= 10.0) + digits -= 1; + + if (exp) { + if (signal > 0) + return snprintf(buf, len, " %.*fx10^%d", digits - 1, val, exp); + else + return snprintf(buf, len, " -%.*fx10^%d", digits - 1, val, exp); + } else { + if (signal > 0) + return snprintf(buf, len, " %.*f", digits - 1, val); + else + return snprintf(buf, len, " -%.*f", digits - 1, val); + } +} + +static void print_stat_float(struct dtv_stats *stat, float val, char *name, + int layer, char **buf, int *len, int *show, + int is_strength) +{ + int size; + + if (stat->scale == FE_SCALE_NOT_AVAILABLE) + return; + + if (!*show && layer) { + size = snprintf(*buf, *len, " Layer %c:", 'A' + layer - 1); + *buf += size; + *len -= size; + *show = 1; + } + size = snprintf(*buf, *len, " %s=", name); + *buf += size; + *len -= size; + *show = 1; + switch (stat->scale) { + case FE_SCALE_RELATIVE: + size = snprintf(*buf, *len, " %u", (unsigned int)val); + break; + case FE_SCALE_COUNTER: + size = snprintf_eng(*buf, *len, val); + break; + } + *buf += size; + *len -= size; + *show = 1; +} + static int print_frontend_stats(struct dvb_v5_fe_parms *parms) { char buf[256], *p = buf; int rc, i, s, len = sizeof(buf), show = 0; fe_status_t status; struct dtv_stats *stat; + float ber; rc = dvb_fe_get_stats(parms); if (rc) { @@ -369,9 +455,8 @@ static int print_frontend_stats(struct dvb_v5_fe_parms *parms) if (stat) print_stat(stat, "C/N", i, &p, &len, &show, 0); - stat = dvb_fe_retrieve_stats_layer(parms, DTV_BER, i); - if (stat) - print_stat(stat, "BER", i, &p, &len, &show, 0); + ber = dvb_fe_retrieve_ber(parms, i, (enum fecap_scale_params *)&stat->scale); + print_stat_float(stat, ber, "BER", i, &p, &len, &show, 0); stat = dvb_fe_retrieve_stats_layer(parms, DTV_STAT_ERROR_BLOCK_COUNT, i); if (stat) -- 2.7.4