diff options
author | Mark Purcell <msp@debian.org> | 2008-06-22 11:00:40 +1000 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:42 +0200 |
commit | 891c51ff368ed700dec6025eeb47ce4d96f76418 (patch) | |
tree | 3729664829e4faa691d403274f38eb10890b533c /util/dib3000-watch | |
parent | 1c6e1f28f54ec2606c23936c1d8689f2be55a86c (diff) | |
parent | ab959d7b4194715870128e616b8e29d4a101e488 (diff) | |
download | linux-dvb-apps-a966623153d5c69ef1565422644280751ce04112.tar.gz |
Imported Debian patch 1.1.1+rev1207-1debian/1.1.1+rev1207-1
Diffstat (limited to 'util/dib3000-watch')
-rw-r--r-- | util/dib3000-watch/Makefile | 13 | ||||
-rw-r--r-- | util/dib3000-watch/README.dib3000-watch | 29 | ||||
-rw-r--r-- | util/dib3000-watch/dib-i2c.h | 43 | ||||
-rw-r--r-- | util/dib3000-watch/dib3000-watch.c | 296 | ||||
-rw-r--r-- | util/dib3000-watch/dib3000-watch.h | 46 | ||||
-rw-r--r-- | util/dib3000-watch/dib3000.h | 56 | ||||
-rw-r--r-- | util/dib3000-watch/make-i2c-dev | 6 |
7 files changed, 489 insertions, 0 deletions
diff --git a/util/dib3000-watch/Makefile b/util/dib3000-watch/Makefile new file mode 100644 index 0000000..2961905 --- /dev/null +++ b/util/dib3000-watch/Makefile @@ -0,0 +1,13 @@ +# Makefile for linuxtv.org dvb-apps/util/dib3000-watch + +binaries = dib3000-watch + +inst_bin = $(binaries) + +LDLIBS += -lm + +.PHONY: all + +all: $(binaries) + +include ../../Make.rules diff --git a/util/dib3000-watch/README.dib3000-watch b/util/dib3000-watch/README.dib3000-watch new file mode 100644 index 0000000..a9499d5 --- /dev/null +++ b/util/dib3000-watch/README.dib3000-watch @@ -0,0 +1,29 @@ +This is a small tool for gathering and evaluating more reception-related data +from the dib3000-demodulators, than the DVB-API currently makes use of. + +It uses the i2c-dev-interface. In order to use it, you have to enable i2c-dev +in your kernel. The module i2c-dev is loaded automatically, when you want to +access the /dev/i2c-*-node. + +If your distribution hasn't create the /dev/i2c-*-nodes you can use the +make-i2c-dev-script located its source directory. + +It is not yet completed, but works fine for all dib3000mb-demods (all of the +USB1.1 dibusb-devices are equipped with it). +Having a CSV output would certainly be useful, when you want to make range +tests by driving around with your car and check the signal. Nevertheless, +this isn't written yet, but should be easy-going. Each line then should +have an timestamp. + +I cannot guarantee for the values this program calculates, I'm not a signal +expert, thus I don't know if they are correct. + +Thanks to Amaury Demol from DiBcom, who provides source for showing me how to +calculate frequencies from the demod values. + +Patrick Boettcher <patrick.boettcher@desy.de> + +PS: Please feel free to modify the source to fullfil your wishes. But please +remember, it is released under the GPL, thus please send back patches to the +author or to the linux-dvb mailing list, so other users can have benefit from +it. diff --git a/util/dib3000-watch/dib-i2c.h b/util/dib3000-watch/dib-i2c.h new file mode 100644 index 0000000..2e9c661 --- /dev/null +++ b/util/dib3000-watch/dib-i2c.h @@ -0,0 +1,43 @@ +/* + * adapted from different kernel headers + * "this is the current way of doing things."-Greg K-H + * + * everything copied from linux kernel 2.6.10 source + */ + +#ifndef _DIB_I2C_H +#define _DIB_I2C_H + + +/* from <linux/i2c.h> */ +#define I2C_SLAVE 0x0703 +#define I2C_SLAVE_FORCE 0x0706 +#define I2C_TENBIT 0x0704 +#define I2C_PEC 0x0708 +#define I2C_RETRIES 0x0701 +#define I2C_TIMEOUT 0x0702 + +#define I2C_FUNCS 0x0705 +#define I2C_RDWR 0x0707 +#define I2C_SMBUS 0x0720 + +struct i2c_msg { + __u16 addr; + __u16 flags; +#define I2C_M_RD 0x0001 +#define I2C_M_TEN 0x0010 +#define I2C_M_NOSTART 0x4000 +#define I2C_M_REV_DIR_ADDR 0x2000 +#define I2C_M_IGNORE_NAK 0x1000 +#define I2C_M_NO_RD_ACK 0x0800 + __u16 len; + __u8 *buf; +}; + +/* from <linux/i2c-dev.h> */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg *msgs; + __u32 nmsgs; +}; + +#endif diff --git a/util/dib3000-watch/dib3000-watch.c b/util/dib3000-watch/dib3000-watch.c new file mode 100644 index 0000000..16bccb7 --- /dev/null +++ b/util/dib3000-watch/dib3000-watch.c @@ -0,0 +1,296 @@ +/* + * Tool for watching the dib3000*-demodulators, + * with an extended output. + * + * Copyright (C) 2005 by Patrick Boettcher <patrick.boettcher@desy.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +#include <getopt.h> + +#include <signal.h> + +#include <math.h> + +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#include <linux/types.h> + +#include "dib-i2c.h" +#include "dib3000-watch.h" +#include "dib3000.h" + +void usage (void) +{ + verb("usage: dib3000-watch -d <i2c-device> -a <i2c-address> [-o <type>] [-i <seconds>]\n" + " -d normally one of /dev/i2c-[0-255]\n" + " -a is 8 for DiB3000M-B and 9, 10, 11 or 12 for DiB3000M-C or DiB3000-P\n" + " -o output type (print|csv) (default: print)\n" + " -i query interval in seconds (default: 0.1)\n" + "\n" + "Don't forget to run tzap or any other dvb-tune program (vdr, kaxtv) in order to tune a channel,\n" + "tuning isn't done by this tool.\n" + "\n" + "A lot of thing have been taken for the dibusb, dib3000m[bc] driver from kernel and\n" + "from t_demod-test software created by DiBcom. Both is GPL, so is dib-demod-watch.\n" + "\n" + "Copyright (C) 2005 by Patrick Boettcher <patrick.boettcher@desy.de>\n" + "\n" + "The source of this tool is released under the GPL.\n" + ); + exit(1); +} + +__u16 dib_read_reg(struct dib_demod *dib,__u16 reg) +{ + int ret; + __u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; + __u8 rb[2]; + struct i2c_msg msg[] = { + { .addr = dib->i2c_addr, .flags = 0, .buf = wb, .len = 2 }, + { .addr = dib->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + struct i2c_rdwr_ioctl_data i2c_data = { + .msgs = msg, + .nmsgs = 2, + }; + + if ((ret = ioctl(dib->fd,I2C_RDWR,&i2c_data)) != 2) { + err("i2c_rdwr read failed. (%d)\n",ret); + return 0; + } + return (rb[0] << 8)| rb[1]; +}; + +int dib_write_reg(struct dib_demod *dib, __u16 reg, __u16 val) +{ + int ret; + __u8 b[] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg[] = { + { .addr = dib->i2c_addr, .flags = 0, .buf = b, .len = 4 } + }; + struct i2c_rdwr_ioctl_data i2c_data = { + .msgs = msg, + .nmsgs = 1, + }; + + if ((ret = ioctl(dib->fd,I2C_RDWR,&i2c_data)) != 1) { + err("i2c_rdwr write failed. (%d)\n",ret); + return -1; + } + return 0; +} + +int dib3000mb_monitoring(struct dib_demod *dib,struct dib3000mb_monitoring *m) +{ + int dds_freq, p_dds_freq, + n_agc_power = dib_read_reg(dib,DIB3000MB_REG_AGC_POWER), + rf_power = dib_read_reg(dib,DIB3000MB_REG_RF_POWER), + timing_offset; + double ad_power_dB, minor_power; + + m->invspec = dib_read_reg(dib,DIB3000MB_REG_DDS_INV); + m->nfft = dib_read_reg(dib,DIB3000MB_REG_TPS_FFT); + + m->agc_lock = dib_read_reg(dib,DIB3000MB_REG_AGC_LOCK); + m->carrier_lock = dib_read_reg(dib,DIB3000MB_REG_CARRIER_LOCK); + m->tps_lock = dib_read_reg(dib,DIB3000MB_REG_TPS_LOCK); + m->vit_lock = dib_read_reg(dib,DIB3000MB_REG_VIT_LCK); + m->ts_sync_lock = dib_read_reg(dib,DIB3000MB_REG_TS_SYNC_LOCK); + m->ts_data_lock = dib_read_reg(dib,DIB3000MB_REG_TS_RS_LOCK); + + p_dds_freq = ((dib_read_reg(dib,DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 8) | + ((dib_read_reg(dib,DIB3000MB_REG_DDS_FREQ_LSB) & 0xff00) >> 8); + dds_freq = ((dib_read_reg(dib,DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 8) | + ((dib_read_reg(dib,DIB3000MB_REG_DDS_VALUE_LSB) & 0xff00) >> 8); + if (m->invspec) + dds_freq = (1 << 16) - dds_freq; + m->carrier_offset = (double)(dds_freq - p_dds_freq) / (double)(1 << 16) * DEF_SampFreq_KHz; + + m->ber = (double)((dib_read_reg(dib,DIB3000MB_REG_BER_MSB) << 16) | dib_read_reg(dib,DIB3000MB_REG_BER_LSB)) / (double) 1e8; + m->per = dib_read_reg(dib,DIB3000MB_REG_PACKET_ERROR_RATE); + m->unc = dib_read_reg(dib,DIB3000MB_REG_UNC); + m->fft_pos = dib_read_reg(dib,DIB3000MB_REG_FFT_WINDOW_POS); + m->snr = 10.0 * log10( (double)(dib_read_reg(dib,DIB3000MB_REG_SIGNAL_POWER) << 8) / + (double)((dib_read_reg(dib,DIB3000MB_REG_NOISE_POWER_MSB) << 16) + dib_read_reg(dib,DIB3000MB_REG_NOISE_POWER_LSB))); + + m->mer = (double) ((dib_read_reg(dib,DIB3000MB_REG_MER_MSB) << 16) + dib_read_reg(dib,DIB3000MB_REG_MER_LSB)) + / (double) (1<<9) / (m->nfft ? 767.0 : 191.0); + + if (n_agc_power == 0) + n_agc_power = 1; + ad_power_dB = 10 * log10( (double)(n_agc_power) / (double)(1<<16)); + minor_power = ad_power_dB - DEF_agc_ref_dB ; + m->rf_power = -DEF_gain_slope_dB * (double)rf_power/(double)(1<<16) + DEF_gain_delta_dB + minor_power; + + timing_offset = + (dib_read_reg(dib,DIB3000MB_REG_TIMING_OFFSET_MSB) << 16) + dib_read_reg(dib,DIB3000MB_REG_TIMING_OFFSET_LSB); + if (timing_offset >= 0x800000) + timing_offset |= 0xff000000; + m->timing_offset_ppm = -(double)timing_offset / (double)(m->nfft ? 8192 : 2048) * 1e6 / (double)(1<<20); + + return 0; +} + +int dib3000mb_print_monitoring(struct dib3000mb_monitoring *m) +{ + printf("DiB3000M-B status\n\n"); + printf(" AGC lock: %10d\n",m->agc_lock); + printf(" carrier lock: %10d\n",m->carrier_lock); + printf(" TPS synchronize lock: %10d\n",m->tps_lock); + printf(" Viterbi lock: %10d\n",m->vit_lock); + printf(" MPEG TS synchronize lock: %10d\n",m->ts_sync_lock); + printf(" MPEG TS data lock: %10d\n",m->ts_data_lock); + printf("\n\n"); + printf(" spectrum inversion: %10d\n",m->invspec); + printf(" carrier offset: %3.7g\n",m->carrier_offset); + printf("\n\n"); + printf(" bit error rate: %3.7g\n",m->ber); + printf(" packet error rate: %10d\n",m->per); + printf(" packet error count: %10d\n",m->unc); + printf("\n\n"); + printf(" fft position: %10d\n",m->fft_pos); + printf(" transmission mode: %10s\n",m->nfft ? "8k" : "2k"); + printf("\n\n"); + printf(" C / (N + I) = %3.7g\n",m->snr); + printf(" MER = %3.7g dB\n",m->mer); + printf(" RF power = %3.7g dBm\n",m->rf_power); + printf(" timing offset = %3.7g ppm\n",m->timing_offset_ppm); + return 0; +} + +int interrupted; + +void sighandler (int sig) +{ + (void)sig; + interrupted = 1; +} + +typedef enum { + OUT_PRINT = 0, + OUT_CSV, +} dib3000m_output_t; + +int main (int argc, char * const argv[]) +{ + struct dib_demod dib; + struct dib3000mb_monitoring mon; + const char *dev = NULL; + float intervall = 0.1; + dib3000m_output_t out = OUT_PRINT; + int c; + + while ((c = getopt(argc,argv,"d:a:o:i:")) != -1) { + switch (c) { + case 'd': + dev = optarg; + break; + case 'a': + dib.i2c_addr = atoi(optarg); /* The I2C address */ + break; + case 'o': + if (strcasecmp(optarg,"print") == 0) out = OUT_PRINT; + else if (strcasecmp(optarg,"csv") == 0) out = OUT_CSV; + else usage(); + break; + case 'i': + intervall = atof(optarg); + break; + default: + usage(); + } + } + + if (dev == NULL) + usage(); + + interrupted = 0; + signal(SIGINT, sighandler); + signal(SIGKILL, sighandler); + signal(SIGHUP, sighandler); + + verb("will use '%s' as i2c-device and %d as i2c address.\n",dev,dib.i2c_addr); + + if ((dib.fd = open(dev,O_RDWR)) < 0) { + err("could not open %s\n",dev); + exit(1); + } + + if (ioctl(dib.fd,I2C_SLAVE,dib.i2c_addr) < 0) { + err("could not set i2c address\n"); + exit(1); + } + + if (dib_read_reg(&dib,DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) { + err("could not find a dib3000 demodulator at i2c-address %d\n",dib.i2c_addr); + exit(1); + } + + switch (dib_read_reg(&dib,DIB3000_REG_DEVICE_ID)) { + case DIB3000MB_DEVICE_ID: + verb("found a DiB3000M-B demodulator.\n"); + dib.rev = DIB3000MB; + break; + case DIB3000MC_DEVICE_ID: + verb("found a DiB3000M-C demodulator.\n"); + dib.rev = DIB3000MC; + break; + case DIB3000P_DEVICE_ID: + verb("found a DiB3000-P demodulator.\n"); + dib.rev = DIB3000P; + break; + default: + err("unsupported demodulator found.\n"); + } + + while (!interrupted) { + switch (dib.rev) { + case DIB3000MB: + dib3000mb_monitoring(&dib,&mon); + if (out == OUT_PRINT) { + printf("\E[H\E[2J"); + dib3000mb_print_monitoring(&mon); + } else if (out == OUT_CSV) { + printf("no csv output implemented yet.\n"); + } + break; + default: + interrupted=1; + err("no monitoring writting for this demod, yet.\n"); + } + usleep((int) (intervall * 1000000)); + } + + close(dib.fd); + + return 0; +} diff --git a/util/dib3000-watch/dib3000-watch.h b/util/dib3000-watch/dib3000-watch.h new file mode 100644 index 0000000..6d50521 --- /dev/null +++ b/util/dib3000-watch/dib3000-watch.h @@ -0,0 +1,46 @@ +#ifndef __DIB_DEMOD_WATCH__ +#define __DIB_DEMOD_WATCH__ + +#define err(args...) fprintf(stderr,"error '%s': ",strerror(errno)); fprintf(stderr,args) +#define verb(args...) fprintf(stderr,args) + +typedef enum { + DIB3000MB = 0, + DIB3000MC, + DIB3000P, +} dib_demod_t; + + +struct dib_demod { + int fd; + __u8 i2c_addr; + + dib_demod_t rev; +}; + +struct dib3000mb_monitoring { + int agc_lock; + int carrier_lock; + int tps_lock; + int vit_lock; + int ts_sync_lock; + int ts_data_lock; + + int invspec; + + int per; + int unc; + + int fft_pos; + + int nfft; + + double carrier_offset; + double ber; + double snr; + double mer; + double rf_power; + double timing_offset_ppm; +}; + +#endif diff --git a/util/dib3000-watch/dib3000.h b/util/dib3000-watch/dib3000.h new file mode 100644 index 0000000..7c3b8bd --- /dev/null +++ b/util/dib3000-watch/dib3000.h @@ -0,0 +1,56 @@ +#ifndef __DIB3000_H__ +#define __DIB3000_H__ + +/* most of this is taken from dib3000-common.h, dib3000mc_priv.h and dib3000mb_priv.h */ + +#define DIB3000_REG_MANUFACTOR_ID ( 1025) +#define DIB3000_I2C_ID_DIBCOM (0x01b3) + +#define DIB3000_REG_DEVICE_ID ( 1026) +#define DIB3000MB_DEVICE_ID (0x3000) +#define DIB3000MC_DEVICE_ID (0x3001) +#define DIB3000P_DEVICE_ID (0x3002) + +/* dib3000mb_priv.h */ + +#define DIB3000MB_REG_DDS_INV ( 5) +#define DIB3000MB_REG_AGC_LOCK ( 324) +#define DIB3000MB_REG_CARRIER_LOCK ( 355) +#define DIB3000MB_REG_TPS_LOCK ( 394) +#define DIB3000MB_REG_VIT_LCK ( 421) +#define DIB3000MB_REG_TS_SYNC_LOCK ( 423) +#define DIB3000MB_REG_TS_RS_LOCK ( 424) + +#define DIB3000MB_REG_DDS_FREQ_MSB ( 6) +#define DIB3000MB_REG_DDS_FREQ_LSB ( 7) +#define DIB3000MB_REG_DDS_VALUE_MSB ( 339) +#define DIB3000MB_REG_DDS_VALUE_LSB ( 340) + +#define DIB3000MB_REG_BER_MSB ( 414) +#define DIB3000MB_REG_BER_LSB ( 415) +#define DIB3000MB_REG_PACKET_ERROR_RATE ( 417) +#define DIB3000MB_REG_UNC ( 420) + +#define DIB3000MB_REG_FFT_WINDOW_POS ( 353) +#define DIB3000MB_REG_TPS_FFT ( 404) + +#define DIB3000MB_REG_NOISE_POWER_MSB ( 372) +#define DIB3000MB_REG_NOISE_POWER_LSB ( 373) + +#define DIB3000MB_REG_SIGNAL_POWER ( 380) + +#define DIB3000MB_REG_MER_MSB ( 381) +#define DIB3000MB_REG_MER_LSB ( 382) + +#define DIB3000MB_REG_AGC_POWER ( 325) +#define DIB3000MB_REG_RF_POWER ( 328) + +#define DIB3000MB_REG_TIMING_OFFSET_MSB ( 341) +#define DIB3000MB_REG_TIMING_OFFSET_LSB ( 342) + +#define DEF_agc_ref_dB -14 +#define DEF_gain_slope_dB 100 +#define DEF_gain_delta_dB -2 +#define DEF_SampFreq_KHz 27700 + +#endif diff --git a/util/dib3000-watch/make-i2c-dev b/util/dib3000-watch/make-i2c-dev new file mode 100644 index 0000000..8f02bbd --- /dev/null +++ b/util/dib3000-watch/make-i2c-dev @@ -0,0 +1,6 @@ +for i in `seq 0 10`; +do + mknod /dev/i2c-$i c 89 $i + chown root.video /dev/i2c-$i + chmod 664 /dev/i2c-$i +done |