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));
/* parse channel list */
while(optind < argc)
{
int ch = atoi(argv[optind]);
if(ch < FMCTDC_CH_1 || ch > FMCTDC_CH_LAST)
{
fprintf(stderr,"%s: invalid channel.\n", argv[0]);
return -1;
}
optind++;
channels[ch - FMCTDC_CH_1] = fmctdc_fileno_channel(brd, ch);
chan_count++;
}
if(!chan_count)
{
for(i = FMCTDC_CH_1; i <= FMCTDC_CH_LAST; i++)
channels[i - FMCTDC_CH_1] = fmctdc_fileno_channel(brd, i);
chan_count = FMCTDC_NUM_CHANNELS;
}
n = 0;
while(n < n_samples || n_samples < 0)
{
struct fmctdc_time ts;
struct timeval tv = {0, 0};
FD_ZERO(&rfds);
for(i = FMCTDC_CH_1; i <= FMCTDC_CH_LAST; i++)
{
int fd = channels [i - FMCTDC_CH_1];
if( fd < 0)
{
fprintf(stderr, "Can't open channel %d\n", i);
return -1;
}
if( fd > 0)
FD_SET(fd, &rfds);
}
if( select (FMCTDC_NUM_CHANNELS + 1, &rfds, NULL, NULL, non_block ? &tv : NULL) <= 0)
{
if(non_block)
break;
else
continue;
}
for(i = FMCTDC_CH_1; i <= FMCTDC_CH_LAST; i++)
{
int fd = channels[i - FMCTDC_CH_1];
if( fd && FD_ISSET(fd, &rfds) && fmctdc_read (brd, i, &ts, 1, 0) == 1)
{
if(fmt_wr)
printf("channel %d seq %-12u ts %10llu:%09u:%04u\n", i, ts.seq_id, ts.seconds, ts.coarse, ts.frac);
else
{
uint64_t picoseconds = (uint64_t) ts.coarse * 8000ULL + (uint64_t) ts.frac * 8000ULL / 4096ULL;
printf("channel %d seq %-12u ts %10llu.%03llu,%03llu,%03llu,%03llu ps\n", i, ts.seq_id, ts.seconds,
picoseconds / 1000000000ULL,
(picoseconds / 1000000ULL) % 1000ULL,
(picoseconds / 1000ULL) % 1000ULL,
picoseconds % 1000ULL
);
}
n++;
if(n == n_samples)
break;
}
}
}
return 0;
}
/*
* 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-term: get/set input termination status.
*/
#include "test-common.h"
int main(int argc, char **argv)
{
init (argc, argv);
check_help(argc, argv, 2,
"[-h] <device> <channel> [on/off]",
"Enables or disables the 50 Ohm termination of a given input channel.\n"
"No on/off command returns the current state of termination resistor.",
"");;
open_board(argv[1]);
if (argc == 2)
{
int i;
for(i = FMCTDC_CH_1; i <= FMCTDC_CH_LAST; i++)
printf("channel %d: 50 Ohm termination is %s\n", i,
fmctdc_get_termination(brd, i) ? "on" : "off");
return 0;
}
int channel = atoi(argv[2]);
if(channel < FMCTDC_CH_1 || channel > FMCTDC_CH_LAST)
{
fprintf(stderr,"%s: invalid channel.\n", argv[0]);
return -1;
}
if(argc >= 4)
{
int term_on;
if(!strcasecmp(argv[3],"on"))
term_on = 1;
else if(!strcasecmp(argv[3],"off"))
term_on = 0;
else {
fprintf(stderr,"%s: invalid command.\n", argv[0]);
return -1;
}
if( fmctdc_set_termination(brd, channel, term_on) < 0)
{
fprintf(stderr,"%s: error setting termination: %s\n", argv[0], strerror(errno));
return -1;
}
}
printf("channel %d: 50 Ohm termination is %s\n", channel,
fmctdc_get_termination(brd, channel) ? "on" : "off");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <inttypes.h>
#include "libtdc.h"
int main(int argc, char **argv)
{
struct tdc_board *b;
struct tdc_time *t;
uint32_t set, get;
int res;
int i;
b = tdc_open(1);
if (!b) {
printf("Unable to open device with lun 1\n");
exit(1);
}
/* set/get UTC time */
set = 123;
if (tdc_set_utc_time(b, set))
printf("Error setting UTC time\n");
if (tdc_get_dac_word(b, &get))
printf("Error getting UtC time\n");
if (set != get)
printf("UTC time set and get don't match (this may not be an error)\n");
else
printf("UTC time functions OK\n");
/* set/get DAC word */
set = 123;
if (tdc_set_dac_word(b, set))
printf("Error setting DAC word\n");
if (tdc_get_dac_word(b, &get))
printf("Error getting DAC word\n");
if (set != get)
printf("DAC word set and get don't match\n");
else
printf("DAC word functions OK\n");
/* set/get time threshold */
set = 12;
if (tdc_set_time_threshold(b, set))
printf("Error setting time thresh\n");
if (tdc_get_time_threshold(b, &get))
printf("Error getting time thresh\n");
if (set != get)
printf("Time thresh set and get don't match\n");
else
printf("Time threshold functions OK\n");
/* set/get timestamps threshold */
set = 12;
if (tdc_set_timestamp_threshold(b, set))
printf("Error setting timestamps thresh\n");
if (tdc_get_timestamp_threshold(b, &get))
printf("Error getting timestamps thresh\n");
if (set != get)
printf("Timestamps thresh set and get don't match\n");
else
printf("Timestamps threshold functions OK\n");
/* set/get channel termination */
set = CHAN0 | CHAN2 | CHAN4;
if (tdc_set_channels_term(b, set))
printf("Error setting channels termination\n");
if (tdc_get_channels_term(b, &get))
printf("Error getting channels term\n");
if (set != get)
printf("Channels termination set and get don't match\n");
else
printf("Channel termination functions OK\n");
/* read from valid chan */
tdc_activate_channels(b);
tdc_set_time_threshold(b, 1);
tdc_set_timestamp_threshold(b, 100);
tdc_start_acquisition(b);
t = tdc_zalloc(1);
// wait 2 seconds to ensure that there are samples
sleep(2);
for (i = 0; i <10; i++) {
/* this should be a blocking read */
res = tdc_read(b, CHAN0, t, 1, 0);
if (res == 1) {
printf("Got sample: utc %"PRIu64" ticks %"PRIu64" bins %"PRIu64" dacapo %i\n",
t->utc, t->ticks, t->bins, t->da_capo);
} else {
printf("Error reading sample\n");
}
}
tdc_stop_acquisition(b);
tdc_close(b);
tdc_free(t);
return 0;
}
/*
* 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.
*
* test-common.c: some shared routines
*/
#include "test-common.h"
int n_boards;
struct fmctdc_board *brd;
void usage_msg(const char *name, const char *msg)
{
printf("usage: %s %s\n", name, msg);
exit(0);
}
void open_board(char *dev_id_str)
{
unsigned int dev_id;
if(sscanf(dev_id_str, "%04x", &dev_id) != 1)
{
fprintf(stderr, "Error parsing device ID %s\n", dev_id_str);
exit(-1);
}
brd = fmctdc_open(-1, dev_id);
if(!brd)
{
fprintf(stderr, "Can't open device %s: %s\n", dev_id_str, strerror(errno));
exit(-1);
}
}
void check_help(int argc, char **argv, int min_args, char *usage, char *desc, char *options)
{
if (argc >= 2 && !strcmp(argv[1], "-h"))
{
printf("%s: %s\n", argv[0], desc);
printf("usage: %s %s\n", argv[0], usage);
printf("%s\n", options);
exit(0);
} else if(argc < min_args)
{
printf("usage: %s %s\n", argv[0], usage);
exit(0);
}
}
static void cleanup()
{
fmctdc_exit();
}
void init(int argc, char *argv[])
{
n_boards = fmctdc_init();
if (n_boards < 0) {
fprintf(stderr, "%s: fmctdc_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
atexit(cleanup);
}
/*
* 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.
*/
#ifndef __TEST_COMMON_H
#define __TEST_COMMON_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <libgen.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <getopt.h>
#include "fmctdc-lib.h"
#include "fmctdc-lib-private.h" /* for some extra debugging stuff */
extern int n_boards;
extern struct fmctdc_board *brd;
void usage_msg(const char *name, const char *msg);
void open_board(char *dev_id_str);
void check_help(int argc, char **argv, int min_args, char *usage, char *desc, char *options);
void init(int argc, char *argv[]);
#endif
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2012
# Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org/projects/fmc-tdc-sw
import sys
import cmd
import os, os.path
import stat
from ctypes import *
from optparse import OptionParser
lun = -1;
device = -1;
class tdc_dev (Structure):
_fields_ = [("dev_id", c_int),
("lun", c_int),
("devbase", POINTER(c_char)),
("sysbase", POINTER(c_char)),
("chan_config", c_uint32),
("ctrl", POINTER(c_int)),
("data", POINTER(c_int))]
class tdc_time (Structure):
_fields_ = [("utc", c_ulonglong),
("ticks", c_ulonglong),
("bins", c_ulonglong),
("dacapo", c_uint32)]
def print_header():
print ('')
print ('\t FMC TDC Testing program \t')
print ('')
print ('Author: Samuel Iglesias Gonsalvez - Igalia S.L. ')
print ('Version: 1.0')
print ('License: GPLv2 or later')
print ('Website: http://www.ohwr.org/projects/fmc-tdc-sw')
print ('')
def chan_mask(chans_str):
"returns the binary mask representing a string of channels"
mask = 0
chans_list = chans_str.split()
for i in range(len(chans_list)):
mask = mask | (1 << int(chans_list[i]))
return mask
class Cli(cmd.Cmd):
def __init__(self, arg):
cmd.Cmd.__init__(self)
self.ruler = ''
self.libtdc = arg
self.tdc_open = 0;
self.tdc = POINTER(tdc_dev)
def do_version(self, arg):
"print version, license and author of the test program"
print_header()
def do_open(self, arg):
"open a TDC device: open <lun>"
self.lun = int(arg);
if (self.lun < 0) or (self.lun > 15):
print "Bad lun number"
return
ptr = POINTER(tdc_dev);
self.libtdc.tdc_open.restype = ptr;
self.tdc = self.libtdc.tdc_open(self.lun);
self.tdc_open = 1;
def do_close(self, arg):
"close an open TDC device"
if self.tdc_open == 0:
print "No device to close"
return
self.libtdc.tdc_close(self.tdc);
self.tdc_open = 0;
def do_start_acq (self, arg):
"start acquisition"
if (self.tdc_open):
self.libtdc.tdc_start_acquisition(self.tdc)
else:
print "No device open"
def do_stop_acq (self, arg):
"stop acquisition"
if (self.tdc_open):
self.libtdc.tdc_stop_acquisition(self.tdc)
else:
print "No device open"
def do_set_host_utc_time (self, arg):
"set board's UTC time with localhost reference"
if (self.tdc_open):
self.libtdc.tdc_set_host_utc_time(self.tdc)
else:
print "No device open"
def do_get_circular_buffer_ptr (self, arg):
"get circular buffer pointer"
if (self.tdc_open):
val = c_uint32(0)
self.libtdc.tdc_get_circular_buffer_pointer(self.tdc, byref(val))
print val
else:
print "No device open"
def do_clear_dacapo_flag (self, arg):
"get clear dacapo flag"
if (self.tdc_open):
self.libtdc.tdc_clear_dacapo_flag(self.tdc)
else:
print "No device open"
def do_activate_channels (self, arg):
"Activate all channels"
if (self.tdc_open):
self.libtdc.tdc_activate_channels(self.tdc)
else:
print "No device open"
def do_deactivate_channels (self, arg):
"Deactivate all channels"
if (self.tdc_open):
self.libtdc.tdc_deactivate_channels(self.tdc)
else:
print "No device open"
def do_utc_time (self, arg):
"get/set UTC time in seconds from EPOC: utc_time [value]"
if (self.tdc_open == 0):
print "No device open"
return
if arg == "":
val = c_uint32(0)
self.libtdc.tdc_get_utc_time(self.tdc, byref(val))
print val
else:
val = c_uint32(int(arg))
self.libtdc.tdc_set_utc_time(self.tdc, val)
def do_timestamp_threshold (self, arg):
"get/set timestamp threshold: timestamp_threshold [value]"
if (self.tdc_open == 0):
print "No device open"
return
if arg == "":
val = c_uint32(0)
self.libtdc.tdc_get_timestamp_threshold(self.tdc, byref(val))
print val
else:
val = c_uint32(int(arg))
if (val > c_ulong(127)):
print "wrong timestamp value. Valid values [0-127]"
return
self.libtdc.tdc_set_timestamp_threshold(self.tdc, val)
def do_time_threshold (self, arg):
"get/set time threshold (in seconds): timestamp_threshold [value]"
if (self.tdc_open == 0):
print "No device open"
return
if arg == "":
val = c_uint32(0)
self.libtdc.tdc_get_time_threshold(self.tdc, byref(val))
print val
else:
val = c_uint32(int(arg))
self.libtdc.tdc_set_time_threshold(self.tdc, val)
def do_channels_term (self, arg):
"get/set active channels: active_channels [value]"
if (self.tdc_open == 0):
print "No device open"
return
if arg == "":
val = c_uint32(0)
self.libtdc.tdc_get_channels_term(self.tdc, byref(val))
print val
else:
val = c_uint32(chan_mask(arg))
self.libtdc.tdc_set_channels_term(self.tdc, val)
def do_read (self, arg):
"read samples from a channel: read [chan] [samples]"
if (self.tdc_open == 0):
print "No device open"
return
args = arg.split()
if (len(args) != 2):
print "Invalid arguments"
return
if (int(args[0]) < 0) or (int(args[0]) > 4):
print "Invalid channel"
return
chan = chan_mask(args[0])
nsamples = int(args[1])
ptr = POINTER(tdc_time)
self.libtdc.tdc_zalloc.restype = ptr
samples = self.libtdc.tdc_zalloc(nsamples)
res = self.libtdc.tdc_read(self.tdc, chan, byref(samples[0]), nsamples, 0)
if (res < 0):
print "Got no samples"
return
for i in range(res):
print ("Sample: utc: %s ticks: %s bins: %s da_capo: %s"
% (samples[i].utc, samples[i].ticks,
samples[i].bins, samples[i].dacapo))
self.libtdc.tdc_free(samples)
# -------------------------------------------
def do_EOF(self, arg):
print
return True
def do_quit(self, arg):
"exit cli"
return True
def do_show(self, arg):
"show current configuration of suite"
params_to_list = (
'current_utc', )
for param in params_to_list:
if param in self.__dict__:
print '%-12s' % (param + ':'),
print self.__getattribute__(param)
do_q = do_quit
do_h = cmd.Cmd.do_help
def main():
usage = ( '%prog: [options] test ...\n'
'run %prog with option -h or --help for more help' )
parser = OptionParser(usage)
parser.add_option("-l", "--lib", dest="lib", type="str",
help =("Path to the shared library libtdc.so. [default: %default]"))
parser.add_option("-v", "--version", action="store_true", dest="version")
parser.set_defaults(version=0, lib="../lib")
(options, args) = parser.parse_args()
# validate arguments and set up Suite object
if options.version :
print_header()
s = options.lib + '/libtdc.so'
libtdc = cdll.LoadLibrary(s);
# Start the command line interface
s = Cli(libtdc)
s.__dict__.update(options.__dict__)
s.cmdloop("Execute 'help' command or 'h' for more help\nExecute 'quit' or 'q' to exit.\n")
if __name__ == '__main__':
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment