Commit 3b148ac5 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

temporary work-in-progress

parent 01c57d7c
......@@ -56,16 +56,19 @@ enum ft_zattr_in_idx {
};
enum ft_command {
FT_CMD_WR_ENABLE = 0,
FT_CMD_WR_DISABLE,
FT_CMD_WR_QUERY,
FT_CMD_IDENTIFY_ON,
FT_CMD_WR_ENABLE = 0, /* Enable White Rabbit */
FT_CMD_WR_DISABLE, /* Disable it */
FT_CMD_WR_QUERY, /* Check if WR is locked */
FT_CMD_SET_HOST_TIME, /* Set board time to current host time */
FT_CMD_IDENTIFY_ON, /* Identify card by blinking status LEDs, reserved for future use. */
FT_CMD_IDENTIFY_OFF
};
/* rest of the file is kernel-only */
#ifdef __KERNEL__
#define FT_USER_OFFSET_RANGE 1000000000 /* picoseconds */
enum ft_channel_flags {
FT_FLAG_CH_TERMINATED = 0,
FT_FLAG_CH_DO_INPUT,
......@@ -206,6 +209,8 @@ void ft_ts_sub(struct ft_wr_timestamp *a, struct ft_wr_timestamp *b);
int ft_set_tai_time(struct fmctdc_dev *ft, uint64_t seconds, uint32_t coarse);
int ft_get_tai_time(struct fmctdc_dev *ft, uint64_t * seconds,
uint32_t * coarse);
int ft_set_host_time (struct fmctdc_dev *ft);
int ft_enable_wr_mode(struct fmctdc_dev *ft, int enable);
int ft_check_wr_mode(struct fmctdc_dev *ft);
......
......@@ -113,6 +113,9 @@ void ft_enable_acquisition(struct fmctdc_dev *ft, int enable)
uint32_t ien, cmd;
int i;
if (ft->acquisition_on == ( enable ? 1: 0 ))
return;
ien = ft_readl(ft, TDC_REG_INPUT_ENABLE);
if (enable) {
......@@ -130,6 +133,9 @@ void ft_enable_acquisition(struct fmctdc_dev *ft, int enable)
ft_writel(ft, TDC_CTRL_CLEAR_DACAPO_FLAG, TDC_REG_CTRL);
ft_writel(ft, cmd, TDC_REG_CTRL);
ft->acquisition_on = enable;
if(ft->verbose)
dev_info(&ft->fmc->dev, "acuqisition is %s\n", enable ? "on" : "off");
}
static int ft_channels_init(struct fmctdc_dev *ft)
......
......@@ -123,7 +123,7 @@ static inline void process_timestamp(struct fmctdc_dev *ft,
ts.channel = channel;
ts.seconds = hwts->utc;
frac = hwts->bins * 81 * 64 / 125; /* reduce fraction to avoid 64-bit division */
frac = hwts->bins * 81 * 64 / 125; /* 64/125 = 4096/8000: reduce fraction to avoid 64-bit division */
ts.coarse = hwts->coarse + frac / 4096;
ts.frac = frac % 4096;
......@@ -185,7 +185,7 @@ static irqreturn_t ft_irq_handler(int irq, void *dev_id)
struct fmctdc_dev *ft = fmc->mezzanine_data;
/* called outside an IRQ context - probably from the polling timer simulating
not-yet-supported IRQs on the SVEC */
the not-yet-supported IRQs on the SVEC */
if (unlikely(!in_interrupt())) {
ft_readout_tasklet((unsigned long)ft);
} else
......
......@@ -54,7 +54,7 @@ static int ft_spec_reset(struct fmctdc_dev *ft)
/* set local bus clock to 160 MHz. The FPGA can't handle more. */
gennum_writel(spec, 0xE001F04C, 0x808);
/* fixme: there is no possibility of doing a software reset of the TDC core
/* fixme: there is no possibility of doing a software reset of the TDC core on the SPEC
other than through a Gennum config register. This begs for a fix in the
gateware! */
......@@ -63,7 +63,8 @@ static int ft_spec_reset(struct fmctdc_dev *ft)
gennum_writel(spec, 0x00025000, GNPCI_SYS_CFG_SYSTEM);
msleep(3000); /* it takes a while for the PLL to bootstrap.... or not!
We have no possibility to check :( */
We have no possibility to check, as the PLL status register is driven
by the clock from this PLL :( */
return 0;
}
......
......@@ -68,7 +68,7 @@ static int ft_svec_reset(struct fmctdc_dev *ft)
/* FIXME: An UGLY hack: ft_svec_reset() executed on slot 0 (first mezzanine to
be initialized) resets BOTH cards. The reason is that we need both mezzanines PLLs
running to read the entire SDB tree (parts of the system interconnect are clocked from
FMC clock lines - a f***up in the HDL. */
FMC clock lines. */
if (ft->fmc->slot_id != 0)
return 0;
......
......@@ -23,13 +23,9 @@
void ft_ts_from_picos(uint32_t picos, struct ft_wr_timestamp *result)
{
result->frac = picos % 4096;
picos -= picos % 4096;
picos /= 4096;
result->coarse = picos % 125000000;
picos -= picos % 125000000;
picos /= 125000000;
result->seconds = picos;
result->frac = (picos % 8000) * 4096 / 8000;
result->coarse = (picos / 8000);
result->seconds = 0;
}
void ft_ts_add(struct ft_wr_timestamp *a, struct ft_wr_timestamp *b)
......@@ -89,9 +85,16 @@ void ft_ts_apply_offset(struct ft_wr_timestamp *ts, int32_t offset_picos)
int ft_set_tai_time(struct fmctdc_dev *ft, uint64_t seconds, uint32_t coarse)
{
if (ft->acquisition_on) /* can't change time when inputs are enabled */
return -EAGAIN;
if (ft->verbose)
dev_info(&ft->fmc->dev, "Setting TAI time to %lld:%d\n",
seconds, coarse);
if(coarse != 0)
dev_warn(&ft->fmc->dev, "Warning: ignoring sub-second part (%d) when setting time.\n", coarse);
ft_writel(ft, seconds & 0xffffffff, TDC_REG_CURRENT_UTC);
ft_writel(ft, TDC_CTRL_LOAD_UTC, TDC_REG_CTRL);
return 0;
......@@ -105,6 +108,18 @@ int ft_get_tai_time(struct fmctdc_dev *ft, uint64_t * seconds,
return 0;
}
int ft_set_host_time (struct fmctdc_dev *ft)
{
struct timespec local_ts;
if (ft->acquisition_on) /* can't change time when inputs are enabled */
return -EAGAIN;
getnstimeofday(&local_ts);
ft_writel(ft, local_ts.tv_sec & 0xffffffff, TDC_REG_CURRENT_UTC);
return 0;
}
int ft_enable_wr_mode(struct fmctdc_dev *ft, int enable)
{
return -ENOTSUPP;
......
......@@ -41,8 +41,8 @@ static struct zio_attribute ft_zattr_dev[] = {
ZIO_ATTR_EXT("seconds", _RW_, FT_ATTR_DEV_SECONDS, 0),
ZIO_ATTR_EXT("coarse", _RW_, FT_ATTR_DEV_COARSE, 0),
ZIO_ATTR_EXT("command", S_IWUGO, FT_ATTR_DEV_COMMAND, 0),
ZIO_ATTR_EXT("enable_inputs", S_IWUGO, FT_ATTR_DEV_ENABLE_INPUTS, 0),
ZIO_ATTR_EXT("temperature", _RW_, FT_ATTR_DEV_TEMP, 0)
ZIO_ATTR_EXT("enable_inputs", _RW_, FT_ATTR_DEV_ENABLE_INPUTS, 0),
ZIO_ATTR_EXT("temperature", S_IRUGO, FT_ATTR_DEV_TEMP, 0)
};
/* Extended attributes for the TDC (== input) cset */
......@@ -153,6 +153,7 @@ static int ft_zio_conf_channel(struct device *dev, struct zio_attribute *zattr,
struct zio_cset *cset;
struct fmctdc_dev *ft;
struct ft_channel_state *st;
int32_t user_offs;
cset = to_zio_cset(dev);
ft = cset->zdev->priv_d;
......@@ -164,6 +165,9 @@ static int ft_zio_conf_channel(struct device *dev, struct zio_attribute *zattr,
return 0;
case FT_ATTR_TDC_USER_OFFSET:
user_offs = usr_val;
if(user_offs < -FT_USER_OFFSET_RANGE || user_offs > FT_USER_OFFSET_RANGE)
return -EINVAL;
spin_lock(&ft->lock);
st->user_offset = usr_val;
spin_unlock(&ft->lock);
......@@ -217,24 +221,23 @@ static int ft_zio_conf_set(struct device *dev, struct zio_attribute *zattr,
attr = zdev->zattr_set.ext_zattr;
ft = zdev->priv_d;
if (zattr->id == FT_ATTR_DEV_SECONDS) {
/* current gw does not allow changing time when acquisition is enabled */
dev_err(&ft->fmc->dev,
"%s: no time setting supported due to bugs in gateware.\n",
__func__);
printk("conf-set: zattr %lu val %u\n", zattr->id, zattr->value);
/*return ft_set_tai_time( ft, attr[FT_ATTR_DEV_SECONDS].value,
if (zattr->id == FT_ATTR_DEV_SECONDS) {
return ft_set_tai_time( ft, attr[FT_ATTR_DEV_SECONDS].value,
attr[FT_ATTR_DEV_COARSE].value
); */
);
return -ENOTSUPP;
} else if (zattr->id == FT_ATTR_DEV_ENABLE_INPUTS)
ft_enable_acquisition(ft, zattr->value);
ft_enable_acquisition(ft, zattr->value);
/* Not command, nothing to do */
if (zattr->id != FT_ATTR_DEV_COMMAND)
return 0;
switch (usr_val) {
case FT_CMD_SET_HOST_TIME:
return ft_set_host_time(ft);
case FT_CMD_WR_ENABLE:
case FT_CMD_WR_DISABLE:
case FT_CMD_WR_QUERY:
......
......@@ -4,23 +4,11 @@ LIB = libfmctdc.a
LOBJ := fmctdc-lib.o
CFLAGS = -Wall -ggdb -O2 -I../kernel -I../zio/include
LDFLAGS = -L. -lfmctdc
TEST_OBJS = fmctdc-test.o
modules all: lib testprog
all: lib
lib: $(LIB)
testprog: $(TEST_OBJS)
$(CC) -o fmctdc-test $(TEST_OBJS) $(LIB)
ln -sf fmctdc-test fmctdc-identify
ln -sf fmctdc-test fmctdc-read
ln -sf fmctdc-test fmctdc-termination
ln -sf fmctdc-test fmctdc-time
ln -sf fmctdc-test fmctdc-list
%: %.c $(LIB)
$(CC) $(CFLAGS) $*.c $(LDFLAGS) -o $@
......
......@@ -25,10 +25,9 @@
#include <linux/zio.h>
#include <linux/zio-user.h>
#define FMCTDC_INTERNAL
#include "fmctdc-lib.h"
#include <fmc-tdc.h>
#include "fmctdc-lib.h"
#include "fmctdc-lib-private.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
......@@ -210,23 +209,6 @@ int fmctdc_close(struct fmctdc_board *userb)
}
int fmctdc_wr_mode(struct fmctdc_board *userb, int on)
{
__define_board(b, userb);
if (on)
return __fmctdc_command(b, FT_CMD_WR_ENABLE);
else
return __fmctdc_command(b, FT_CMD_WR_DISABLE);
}
extern int fmctdc_check_wr_mode(struct fmctdc_board *userb)
{
__define_board(b, userb);
if (__fmctdc_command(b, FT_CMD_WR_QUERY) == 0)
return 0;
return errno;
}
float fmctdc_read_temperature(struct fmctdc_board *userb)
{
uint32_t t;
......@@ -236,15 +218,6 @@ float fmctdc_read_temperature(struct fmctdc_board *userb)
return (float)t / 16.0;
}
int fmctdc_identify_card(struct fmctdc_board *userb, int blink_led)
{
__define_board(b, userb);
if (blink_led)
return __fmctdc_command(b, FT_CMD_IDENTIFY_ON);
else
return __fmctdc_command(b, FT_CMD_IDENTIFY_OFF);
}
int fmctdc_set_termination(struct fmctdc_board *userb, int channel, int on)
{
__define_board(b, userb);
......@@ -254,11 +227,10 @@ int fmctdc_set_termination(struct fmctdc_board *userb, int channel, int on)
if(channel < FMCTDC_CH_1 || channel > FMCTDC_NUM_CHANNELS)
return -EINVAL;
snprintf(attr, sizeof(attr), "fd-ch%d/termination", channel);
snprintf(attr, sizeof(attr), "ft-ch%d/termination", channel);
val = on ? 1 : 0;
return fmctdc_sysfs_set(b, attr, &val);
}
int fmctdc_get_termination(struct fmctdc_board *userb, int channel)
......@@ -271,7 +243,7 @@ int fmctdc_get_termination(struct fmctdc_board *userb, int channel)
if(channel < FMCTDC_CH_1 || channel > FMCTDC_NUM_CHANNELS)
return -EINVAL;
snprintf(attr, sizeof(attr), "fd-ch%d/termination", channel);
snprintf(attr, sizeof(attr), "ft-ch%d/termination", channel);
ret = fmctdc_sysfs_get(b, attr, &val);
if(ret)
......@@ -279,11 +251,33 @@ int fmctdc_get_termination(struct fmctdc_board *userb, int channel)
return val;
}
int fmctdc_get_acquisition(struct fmctdc_board *userb)
{
__define_board(b, userb);
uint32_t val;
int ret;
ret = fmctdc_sysfs_get(b, "enable_inputs", &val);
if(ret)
return ret;
return val;
}
int fmctdc_set_acquisition(struct fmctdc_board *userb, int on)
{
__define_board(b, userb);
uint32_t val;
val = on ? 1 : 0;
return fmctdc_sysfs_set(b, "enable_inputs", &val);
}
static int __fmctdc_open_channel(struct __fmctdc_board *b, int channel)
{
char fname[128];
if (b->fdc[channel - 1] <= 0) {
snprintf(fname, sizeof(fname), "%s-%d-0-ctrl", b->devbase, channel);
snprintf(fname, sizeof(fname), "%s-%d-0-ctrl", b->devbase, channel - 1);
b->fdc[channel - 1] = open(fname, O_RDONLY | O_NONBLOCK);
}
return b->fdc[channel - 1];
......@@ -319,9 +313,9 @@ int fmctdc_read(struct fmctdc_board *userb, int channel, struct fmctdc_time *t,
if (j == sizeof(ctrl)) {
/* one sample: pick it */
attrs = ctrl.attr_channel.ext_val;
t->seconds = ctrl.tstamp.secs;
t->coarse = ctrl.tstamp.ticks;
t->frac = ctrl.tstamp.bins;
t->seconds = attrs[FT_ATTR_TDC_SECONDS];
t->coarse = attrs[FT_ATTR_TDC_COARSE];
t->frac = attrs[FT_ATTR_TDC_FRAC];
t->seq_id = attrs[FT_ATTR_TDC_SEQ];
i++;
continue;
......@@ -360,3 +354,75 @@ int fmctdc_fread(struct fmctdc_board *userb, int channel, struct fmctdc_time *t,
}
return i;
}
static char *names[] = { "seconds", "coarse" };
int fmctdc_set_time(struct fmctdc_board *userb, struct fmctdc_time *t)
{
__define_board(b, userb);
uint32_t attrs[ARRAY_SIZE(names)];
int i, ret;
attrs[0] = t->seconds & 0xffffffff;
attrs[1] = t->coarse;
for (i = ARRAY_SIZE(names) - 1; i >= 0; i--)
{
ret = fmctdc_sysfs_set(b, names[i], attrs + i);
if(ret < 0)
return ret;
}
return 0;
}
int fmctdc_get_time(struct fmctdc_board *userb, struct fmctdc_time *t)
{
__define_board(b, userb);
uint32_t attrs[ARRAY_SIZE(names)];
int i, ret;
for (i = 0; i < ARRAY_SIZE(names); i++)
{
ret = fmctdc_sysfs_get(b, names[i], attrs + i);
if(ret < 0)
return ret;
}
t->seconds = attrs[0];
t->coarse = attrs[1];
t->frac = 0;
return 0;
}
int fmctdc_set_host_time(struct fmctdc_board *userb)
{
__define_board(b, userb);
return __fmctdc_command(b, FT_CMD_SET_HOST_TIME);
}
int fmctdc_wr_mode(struct fmctdc_board *userb, int on)
{
__define_board(b, userb);
if (on)
return __fmctdc_command(b, FT_CMD_WR_ENABLE);
else
return __fmctdc_command(b, FT_CMD_WR_DISABLE);
}
extern int fmctdc_check_wr_mode(struct fmctdc_board *userb)
{
int ret;
__define_board(b, userb);
ret = __fmctdc_command(b, FT_CMD_WR_QUERY);
switch(ret)
{
case 0:
return 1; /* no error: locked to WR */
case -EAGAIN:
return 0; /* EAGAIN: not locked yet */
default:
return ret; /* other error code: just an error ;) */
}
}
......@@ -21,6 +21,7 @@ enum fmctdc_channel {
FMCTDC_CH_3 = 3,
FMCTDC_CH_4 = 4,
FMCTDC_CH_5 = 5,
FMCTDC_CH_LAST = 5,
FMCTDC_NUM_CHANNELS = 5
};
......@@ -45,105 +46,20 @@ extern int fmctdc_set_time(struct fmctdc_board *b, struct fmctdc_time *t);
extern int fmctdc_get_time(struct fmctdc_board *b, struct fmctdc_time *t);
extern int fmctdc_set_host_time(struct fmctdc_board *b);
extern int fmctdc_set_acquisition(struct fmctdc_board *b, int enable);
extern int fmctdc_get_acquisition(struct fmctdc_board *b);
extern int fmctdc_set_termination(struct fmctdc_board *b, int channel, int enable);
extern int fmctdc_get_termination(struct fmctdc_board *b, int channel);
extern int fmctdc_purge_fifo(struct fmctdc_board *b, int channel);
extern int fmctdc_identify_card(struct fmctdc_board *b, int blink_led);
extern int fmctdc_fread(struct fmctdc_board *b, int channel, struct fmctdc_time *t, int n);
extern int fmctdc_fileno_channel(struct fmctdc_board *b, int channel);
extern int fmctdc_read(struct fmctdc_board *b, int channel, struct fmctdc_time *t, int n,
int flags);
extern int fmctdc_wr_mode(struct fmctdc_board *b, int on);
extern int fmctdc_check_wr_mode(struct fmctdc_board *b);
extern float fmctdc_read_temperature(struct fmctdc_board *b);
#ifdef FMCTDC_INTERNAL /* Libray users should ignore what follows */
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/* Internal structure */
struct __fmctdc_board {
int dev_id;
char *devbase;
char *sysbase;
int fdc[5]; /* The 5 control channels */
int fdd[5]; /* The 5 data channels */
};
static inline int fmctdc_is_verbose(void)
{
return getenv("FMCTDC_LIB_VERBOSE") != 0;
}
#define __define_board(b, ub) struct __fmctdc_board *b = (void *)(ub)
/* These two from ../tools/fdelay-raw.h, used internally */
static inline int __fmctdc_sysfs_get(char *path, uint32_t *resp)
{
FILE *f = fopen(path, "r");
if (!f)
return -1;
errno = 0;
if (fscanf(f, "%i", resp) != 1) {
fclose(f);
if (!errno)
errno = EINVAL;
return -1;
}
fclose(f);
return 0;
}
static inline int __fmctdc_sysfs_set(char *path, uint32_t *value)
{
char s[16];
int fd, ret, len;
len = sprintf(s, "%i\n", *value);
fd = open(path, O_WRONLY);
if (fd < 0)
return -1;
ret = write(fd, s, len);
close(fd);
if (ret < 0)
return -1;
if (ret == len)
return 0;
errno = EINVAL;
return -1;
}
/* And these two for the board structure */
static inline int fmctdc_sysfs_get(struct __fmctdc_board *b, char *name,
uint32_t *resp)
{
char pathname[128];
sprintf(pathname, "%s/%s", b->sysbase, name);
return __fmctdc_sysfs_get(pathname, resp);
}
static inline int fmctdc_sysfs_set(struct __fmctdc_board *b, char *name,
uint32_t *value)
{
char pathname[128];
sprintf(pathname, "%s/%s", b->sysbase, name);
return __fmctdc_sysfs_set(pathname, value);
}
static inline int __fmctdc_command(struct __fmctdc_board *b, uint32_t cmd)
{
return fmctdc_sysfs_set(b, "command", &cmd);
}
extern int fmctdc_wr_mode(struct fmctdc_board *b, int on);
extern int fmctdc_check_wr_mode(struct fmctdc_board *b);
#endif /* fmctdc_INTERNAL */
#endif /* __fmctdc_H__ */
#endif /* __FMCTDC_LIB_H__ */
\ No newline at end of file
ZIO ?= $(HOME)/zio
CFLAGS = -I. -I../lib -I../kernel -Wall -ggdb3
TESTS = fmctdc-list fmctdc-term fmctdc-read fmctdc-acquisition
COMMON_SRCS = test-common.c
LDFLAGS = -L../lib -lfmctdc
LIB = libtdc.a
LOBJ := libtdc.o
all: $(TESTS)
CFLAGS = -Wall -ggdb -I.. -I../lib -I$(ZIO)/include
LDFLAGS = -L../lib/ -ltdc
%: %.c $(COMMON_SRCS)
$(CC) $(CFLAGS) $*.c $(COMMON_SRCS) $(LDFLAGS) -o $@
modules all: lib sanity-test
lib:
$(MAKE) -C ../lib
sanity-test:
$(CC) $(CFLAGS) $@.c $(LDFLAGS) -o $@
clean:
$(MAKE) clean -C ../lib
rm -f *.o *~ sanity-test
rm -f $(TESTS) test-common.o
\ No newline at end of file
/*
* The fmc-tdc (a.k.a. FmcTdc1ns5cha) library test program.
*
* Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*
* fmctdc-acquisition: enables/disables acquisition (all inputs).
*/
#include "test-common.h"
int main(int argc, char **argv)
{
init (argc, argv);
check_help(argc, argv, 2,
"[-h] <device> [on/off]",
"Enables or disables acquisition (that is, all inputs simultaneosly). Disabling acquisition\n"
"also empties the timestamp buffers.",
"");
open_board(argv[1]);
if (argc == 2)
{
printf("board %s: acquisition is %s\n", argv[1], fmctdc_get_acquisition(brd) ? "on" : "off" );
} else if (argc > 2) {
int on;
if(!strcmp(argv[2], "on"))
on = 1;
else if(!strcmp(argv[2], "off"))
on = 0;
else {
fprintf(stderr,"%s: on/off expected.\n", argv[0]);
return -1;
}
if( fmctdc_set_acquisition(brd, on) < 0);
return -1;
}
return 0;
}
\ No newline at end of file
/*
* The fmc-tdc (a.k.a. FmcTdc1ns5cha) library test program.
*
* Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*
* fmctdc-list: displays all FmcTdc cards installed in the system.
*
*/
#include "test-common.h"
int main(int argc, char **argv)
{
int i;
init(argc, argv);
check_help(argc, argv, 1,
"[-h]",
"lists all installed fmc-tdc boards.",
"");
printf("Found %i board(s): \n", n_boards);
for (i = 0; i < n_boards; i++)
{
struct __fmctdc_board *b;
struct fmctdc_board *ub;
ub = fmctdc_open(i, -1);
b = (typeof(b))ub;
printf("%04x, %s, %s\n", b->dev_id, b->devbase, b->sysbase);
}
return 0;
}
\ No newline at end of file
/*
* The fmc-tdc (a.k.a. FmcTdc1ns5cha) library test program.
*
* Author: Tomasz Włostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*
* fmctdc-read: read timestamps from a given FmcTdc card.
*/
#include "test-common.h"
int main(int argc, char **argv)
{
int channels [FMCTDC_NUM_CHANNELS];
int chan_count = 0, i, n;
int non_block = 0;
int n_samples = -1;
int fmt_wr = 0;
char opt;
fd_set rfds;
init (argc, argv);
check_help(argc, argv, 2,
"[options] <device> [channels]",
"reads timestamps from the selected fmc-tdc channels. No [channels] means all channels.",
"Options are:\n"
" -n: non-blocking mode\n"
" -s n_samples: keep reading until n_samples timestamps\n"
" -w: dump timestamps in hardware (White Rabbit) format\n"
" -h: print this message\n"
);
while ((opt = getopt(argc, argv, "wns:")) != -1) {
switch(opt)
{
case 's':
sscanf(optarg,"%i", &n_samples);
break;
case 'n':
non_block = 1;
break;
case 'w':
fmt_wr = 1;
break;
}
}
if(optind >= argc)
{
fprintf(stderr,"%s: device ID expected\n", argv[0]);
return -1;
}
open_board(argv[optind++]);
memset(channels, 0, sizeof(channels));