Commit 856497c1 authored by Federico Vaga's avatar Federico Vaga

remove lib and libtools

The driver's users are supposed to use the generic `adc-lib`
library from OHWR.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent e3fc1b13
......@@ -4,7 +4,7 @@ CURDIR:=$(shell /bin/pwd)
REPO_PARENT ?= $(CURDIR)/..
-include $(REPO_PARENT)/parent_common.mk
all: kernel tools lib libtools
all: kernel tools
FMC_BUS ?= fmc-bus
ZIO ?= zio
......@@ -24,11 +24,9 @@ export ZIO_ABS
export SVEC_SW_ABS
export VMEBUS_ABS
DIRS = $(FMC_BUS_ABS) $(ZIO_ABS) kernel tools lib libtools
DIRS = $(FMC_BUS_ABS) $(ZIO_ABS) kernel tools
kernel: $(FMC_BUS_ABS) $(ZIO_ABS)
lib: $(ZIO_ABS)
tools libtools: lib
.PHONY: all clean modules install modules_install $(DIRS)
.PHONY: gitmodules prereq_install prereq_install_warn
......
.depend
\ No newline at end of file
# This is not a kbuild Makefile. It is a plain Makefile so it can be copied
# If it exists includes Makefile.specific. In this Makefile, you should put
# specific Makefile code that you want to run before this. For example,
# build a particular environment.
-include Makefile.specific
# include parent_common.mk for buildsystem's defines
REPO_PARENT ?= ../..
-include $(REPO_PARENT)/parent_common.mk
ZIO ?= ../zio
ZIO_ABS ?= $(abspath $(ZIO) )
GIT_VERSION := $(shell git describe --dirty --long --tags)
ZIO_GIT_VERSION := $(shell cd $(ZIO_ABS); git describe --dirty --long --tags)
LIB = libfmcadc.a
LOBJ := route.o
LOBJ += init.o
LOBJ += boards.o
LOBJ += config-zio.o
LOBJ += buffer-zio.o
LOBJ += lib.o
LOBJ += fmc-adc-100m14b4cha.o
CFLAGS = -Wall -ggdb -O2 -fPIC -I../kernel -I$(ZIO_ABS)/include $(EXTRACFLAGS)
CFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\""
CFLAGS += -DZIO_GIT_VERSION="\"$(ZIO_GIT_VERSION)\""
LDFLAGS = -L. -lfmcadc
CC ?= $(CROSS_COMPILE)gcc
modules all: $(LIB)
%: %.c $(LIB)
$(CC) $(CFLAGS) $*.c $(LDFLAGS) -o $@
$(LIB): $(LOBJ)
$(AR) r $@ $^
clean:
rm -f $(LIB) .depend *.o *~
.depend: Makefile $(wildcard *.c *.h ../*.h)
$(CC) $(CFLAGS) -M $(LOBJ:.o=.c) -o $@
install modules_install:
-include .depend
/*
* All the boards in the library
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.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.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
#define FMCADC_ZIO_TRG_MASK (1LL << FMCADC_CONF_TRG_SOURCE) | \
(1LL << FMCADC_CONF_TRG_SOURCE_CHAN) | \
(1LL << FMCADC_CONF_TRG_THRESHOLD) | \
(1LL << FMCADC_CONF_TRG_POLARITY) | \
(1LL << FMCADC_CONF_TRG_DELAY)
#define FMCADC_ZIO_ACQ_MASK (1LL << FMCADC_CONF_ACQ_N_SHOTS) | \
(1LL << FMCADC_CONF_ACQ_POST_SAMP) | \
(1LL << FMCADC_CONF_ACQ_PRE_SAMP) | \
(1LL << FMCADC_CONF_ACQ_DECIMATION) | \
(1LL << FMCADC_CONF_ACQ_FREQ_HZ) | \
(1LL << FMCADC_CONF_ACQ_N_BITS)
#define FMCADC_ZIO_CHN_MASK (1LL << FMCADC_CONF_CHN_RANGE) | \
(1LL << FMCADC_CONF_CHN_TERMINATION) | \
(1LL << FMCADC_CONF_CHN_OFFSET)
#define FMCADC_ZIO_BRD_MASK (1LL << FMCADC_CONF_BRD_STATE_MACHINE_STATUS) | \
(1LL << FMCADC_CONF_BRD_N_CHAN) | \
(1LL << FMCADC_CONF_UTC_TIMING_BASE_S) | \
(1LL << FMCADC_CONF_UTC_TIMING_BASE_T)
struct fmcadc_operations fa_100ms_4ch_14bit_op = {
.open = fmcadc_zio_open,
.close = fmcadc_zio_close,
.acq_start = fmcadc_zio_acq_start,
.acq_poll = fmcadc_zio_acq_poll,
.acq_stop = fmcadc_zio_acq_stop,
.apply_config = fmcadc_zio_apply_config,
.retrieve_config = fmcadc_zio_retrieve_config,
.get_param = fmcadc_zio_get_param,
.set_param = fmcadc_zio_set_param,
.request_buffer = fmcadc_zio_request_buffer,
.fill_buffer = fmcadc_zio_fill_buffer,
.tstamp_buffer = fmcadc_zio_tstamp_buffer,
.release_buffer = fmcadc_zio_release_buffer,
};
struct fmcadc_board_type fmcadc_100ms_4ch_14bit = {
.name = "fmc-adc-100m14b4cha", /* for library open() */
.devname = "adc-100m14b", /* for device named in /dev/zio */
.driver_type = "zio",
.capabilities = {
FMCADC_ZIO_TRG_MASK,
FMCADC_ZIO_ACQ_MASK,
FMCADC_ZIO_CHN_MASK,
FMCADC_ZIO_BRD_MASK,
},
.fa_op = &fa_100ms_4ch_14bit_op,
};
/*
* The following array is the main entry point into the boards
*/
static const struct fmcadc_board_type *fmcadc_board_types[] = {
&fmcadc_100ms_4ch_14bit,
/* add new boards here */
};
static const struct fmcadc_board_type *find_board(char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(fmcadc_board_types); i++)
if (!strcmp(name, fmcadc_board_types[i]->name))
return fmcadc_board_types[i];
errno = ENODEV;
return NULL;
}
/* Open should choose the buffer type (FIXME) */
struct fmcadc_dev *fmcadc_open(char *name, unsigned int dev_id,
unsigned long buffersize,
unsigned int nbuffer,
unsigned long flags)
{
const struct fmcadc_board_type *b;
b = find_board(name);
if (!b)
return NULL;
return b->fa_op->open(b, dev_id, buffersize, nbuffer, flags);
}
#define FMCADC_PATH_PATTERN "/dev/%s.%d"
/* Open by lun should lookup a database */
struct fmcadc_dev *fmcadc_open_by_lun(char *name, int lun,
unsigned long buffersize,
unsigned int nbuffer,
unsigned long flags)
{
ssize_t ret;
char dev_id_str[8];
char path[PATH_MAX];
int dev_id;
ret = snprintf(path, sizeof(path), "/dev/%s.%d",
"adc-100m14b" /* FIXME: this must be generic */,
lun);
if (ret < 0 || ret >= sizeof(path)) {
errno = EINVAL;
return NULL;
}
ret = readlink(path, dev_id_str, sizeof(dev_id_str));
if (sscanf(dev_id_str, "%4x", &dev_id) != 1) {
errno = ENODEV;
return NULL;
}
return fmcadc_open(name, dev_id, buffersize, nbuffer, flags);
}
int fmcadc_close(struct fmcadc_dev *dev)
{
struct fmcadc_gid *b = (struct fmcadc_gid *)dev;
return b->board->fa_op->close(dev);
}
/*
* ZIO-wide buffer management (device-independent)
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.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.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <linux/zio-user.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
/* Internal function to read the control, already allocated in the buffer */
static int fmcadc_zio_read_ctrl(struct __fmcadc_dev_zio *fa,
struct fmcadc_buffer *buf)
{
struct zio_control *ctrl;
int i;
i = read(fa->fdc, buf->metadata, sizeof(struct zio_control));
switch (i) {
case sizeof(struct zio_control):
return 0; /* ok */
case -1:
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: read: %s\n", __func__,
strerror(errno));
return -1;
case 0:
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: unexpected EOF\n", __func__);
return -1;
default:
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: read: %i bytes (expected %zi)\n",
__func__, i, sizeof(ctrl));
return -1;
}
}
/* Internal function to read or map the data, already allocated in the buffer */
static int fmcadc_zio_read_data(struct __fmcadc_dev_zio *fa,
struct fmcadc_buffer *buf)
{
struct zio_control *ctrl = buf->metadata;
int datalen;
int samplesize = buf->samplesize; /* Careful: includes n_chan */
int i;
/* we allocated buf->nsamples, we can have more or less */
if (buf->nsamples < ctrl->nsamples)
datalen = samplesize * buf->nsamples;
else
datalen = samplesize * ctrl->nsamples;
if (fa->flags & FMCADC_FLAG_MMAP) {
unsigned long mapoffset = ctrl->mem_offset;
unsigned long pagemask = fa->pagesize - 1;
if (buf->mapaddr) /* unmap previous block */
munmap(buf->mapaddr, buf->maplen);
buf->maplen = (mapoffset & pagemask) + datalen;
buf->mapaddr = mmap(0, buf->maplen, PROT_READ, MAP_SHARED,
fa->fdd, mapoffset & ~pagemask);
if (buf->mapaddr == MAP_FAILED)
return -1;
buf->data = buf->mapaddr + (mapoffset & pagemask);
return 0;
}
/* read */
i = read(fa->fdd, buf->data, datalen);
if (i == datalen)
return 0;
if (i > 0) {
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: read %i bytes (exp. %i)\n",
__func__, i, datalen);
buf->nsamples = i / fa->samplesize;
/* short read is allowed */
return 0;
}
if (i == 0) {
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: unexpected EOF\n", __func__);
errno = ENODATA;
return -1;
}
if (fa->flags & FMCADC_FLAG_VERBOSE)
fprintf(stderr, "%s: %s\n", __func__, strerror(errno));
return -1;
}
/* externally-called: malloc buffer and metadata, do your best with data */
struct fmcadc_buffer *fmcadc_zio_request_buffer(struct fmcadc_dev *dev,
int nsamples,
void *(*alloc)(size_t),
unsigned int flags)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
struct fmcadc_buffer *buf;
char s[16];
/* If this is the first buffer, we need to know which kind it is */
if ((fa->flags & (FMCADC_FLAG_MALLOC | FMCADC_FLAG_MMAP)) == 0) {
fmcadc_get_param(dev, "cset0/current_buffer", s, NULL);
if (!strcmp(s, "vmalloc"))
fa->flags |= FMCADC_FLAG_MMAP;
else
fa->flags |= FMCADC_FLAG_MALLOC;
}
buf = calloc(1, sizeof(*buf));
if (!buf) {
errno = ENOMEM;
return NULL;
}
buf->metadata = calloc(1, sizeof(struct zio_control));
if (!buf->metadata) {
free(buf);
errno = ENOMEM;
return NULL;
}
/* Allocate data: custom allocator, or malloc, or mmap */
if (!alloc && fa->flags & FMCADC_FLAG_MALLOC)
alloc = malloc;
if (alloc) {
buf->data = alloc(nsamples * fa->samplesize);
if (!buf->data) {
free(buf->metadata);
free(buf);
errno = ENOMEM;
return NULL;
}
} else {
/* mmap is done later */
buf->data = NULL;
}
/* Copy other information */
buf->samplesize = fa->samplesize;
buf->nsamples = nsamples;
buf->dev = (void *)&fa->gid;
buf->flags = flags;
return buf;
}
int fmcadc_zio_fill_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
unsigned int flags,
struct timeval *to)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
struct pollfd p;
int to_ms, ret;
/* So, first sample and blocking read. Wait.. */
p.fd = fa->fdc;
p.events = POLLIN | POLLERR;
if (!to)
to_ms = -1;
else
to_ms = to->tv_sec / 1000 + (to->tv_usec + 500) / 1000;
ret = poll(&p, 1, to_ms);
switch (ret) {
case 0:
errno = EAGAIN;
/* fall through */
case -1:
return -1;
}
if (p.revents & POLLERR) {
errno = FMCADC_EDISABLED;
return -1;
}
ret = fmcadc_zio_read_ctrl(fa, buf);
if (ret < 0)
return ret;
ret = fmcadc_zio_read_data(fa, buf);
if (ret < 0)
return ret;
return 0;
}
struct fmcadc_timestamp *fmcadc_zio_tstamp_buffer(struct fmcadc_buffer *buf,
struct fmcadc_timestamp *ts)
{
struct zio_control *ctrl = buf->metadata;
if (ts) {
memcpy(ts, &ctrl->tstamp, sizeof(*ts)); /* FIXME: endianness */
return ts;
}
return (struct fmcadc_timestamp *)&ctrl->tstamp;
}
int fmcadc_zio_release_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
void (*free_fn)(void *))
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
free(buf->metadata);
if (!free_fn && fa->flags & FMCADC_FLAG_MALLOC)
free_fn = free;
if (free_fn)
free_fn(buf->data);
else if (buf->mapaddr && buf->mapaddr != MAP_FAILED)
munmap(buf->mapaddr, buf->maplen);
free(buf);
return 0;
}
This diff is collapsed.
/*
* The ADC library for the specific card
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.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.
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <linux/zio-user.h>
#include <fmc-adc-100m14b4cha.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
#define ZIO_SYS_PATH "/sys/bus/zio/devices"
#define FMCADC_NCHAN 4
static int fmcadc_flush_input(struct __fmcadc_dev_zio *fa)
{
struct zio_control ctrl;
struct pollfd p = {
.fd = fa->fdc,
.events = POLLIN | POLLERR,
};
int i;
/* Read the control until one is there; data is discarded by zio */
while (1) {
i = poll(&p, 1, 0);
if (i < 0)
return -1;
if ((p.revents & POLLIN) == 0)
return 0;
read(fa->fdc, &ctrl, sizeof(ctrl));
}
}
struct fmcadc_dev *fmcadc_zio_open(const struct fmcadc_board_type *b,
unsigned int dev_id,
unsigned long totalsamples,
unsigned int nbuffer,
unsigned long flags)
{
struct __fmcadc_dev_zio *fa;
struct stat st;
char *syspath, *devpath, fname[128];
int udev_zio_dir = 1;
/* Check if device exists by looking in sysfs */
asprintf(&syspath, "%s/%s-%04x", ZIO_SYS_PATH, b->devname, dev_id);
if (stat(syspath, &st))
goto out_fa_stat; /* ENOENT or equivalent */
/* ZIO char devices are in /dev/zio or just /dev (older udev) */
if (stat("/dev/zio", &st) < 0)
udev_zio_dir = 0;
asprintf(&devpath, "%s/%s-%04x", (udev_zio_dir ? "/dev/zio" : "/dev"),
b->devname, dev_id);
/* Sysfs path exists, so device is there, hopefully */
fa = calloc(1, sizeof(*fa));
if (!fa)
goto out_fa_alloc;
fa->sysbase = syspath;
fa->devbase = devpath;
fa->cset = 0;
/* Open char devices */
sprintf(fname, "%s-0-i-ctrl", fa->devbase);
fa->fdc = open(fname, O_RDONLY);
sprintf(fname, "%s-0-i-data", fa->devbase);
fa->fdd = open(fname, O_RDONLY);
if (fa->fdc < 0 || fa->fdd < 0)
goto out_fa_open;
if (flags & FMCADC_F_FLUSH)
if (fmcadc_flush_input(fa) < 0)
goto out_fa_open;
fa->gid.board = b;
/*
* We need to save the page size and samplesize.
* Samplesize includes the nchan in the count.
*/
fa->samplesize = 8; /* FIXME: should read sysfs instead -- where? */
fa->pagesize = getpagesize();
/* Support verbose operation (turn user flag into internal flag)*/
if (flags & FMCADC_F_VERBOSE || getenv("LIB_FMCADC_VERBOSE"))
fa->flags |= FMCADC_FLAG_VERBOSE;
return (void *) &fa->gid;
out_fa_open:
if (fa->fdc >= 0)
close(fa->fdc);
if (fa->fdd >= 0)
close(fa->fdd);
free(fa);
out_fa_alloc:
free(devpath);
out_fa_stat:
free(syspath);
return NULL;
}
int fmcadc_zio_close(struct fmcadc_dev *dev)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
close(fa->fdc);
close(fa->fdd);
free(fa->sysbase);
free(fa->devbase);
free(fa);
return 0;
}
/* poll is used by start, so it's defined first */
int fmcadc_zio_acq_poll(struct fmcadc_dev *dev,
unsigned int flags, struct timeval *to)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
struct pollfd p;
int to_ms, ret;
/* So, first sample and blocking read. Wait.. */
p.fd = fa->fdc;
p.events = POLLIN | POLLERR;
if (!to)
to_ms = -1;
else
to_ms = to->tv_sec / 1000 + (to->tv_usec + 500) / 1000;
ret = poll(&p, 1, to_ms);
switch (ret) {
case 0:
errno = EAGAIN;
/* fall through */
case -1:
return -1;
}
if (p.revents & POLLERR) {
errno = FMCADC_EDISABLED;
return -1;
}
return 0;
}
int fmcadc_zio_acq_start(struct fmcadc_dev *dev,
unsigned int flags, struct timeval *timeout)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
uint32_t cmd = 1; /* hw command for "start" */
int err;
if (flags & FMCADC_F_FLUSH)
if (fmcadc_flush_input(fa) < 0)
return -1;
err = fa_zio_sysfs_set(fa, "cset0/fsm-command", &cmd);
if (err)
return err;
if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0)
return 0;
return fmcadc_zio_acq_poll(dev, flags, timeout);
}
int fmcadc_zio_acq_stop(struct fmcadc_dev *dev, unsigned int flags)
{
struct __fmcadc_dev_zio *fa = to_dev_zio(dev);
uint32_t cmd = 2; /* hw command for "stop" */
return fa_zio_sysfs_set(fa, "cset0/fsm-command", &cmd);
}
/*
* Copyright CERN 2013
* Author: Federico Vaga <federico.vaga@gmail.com>
*/
#ifndef FMCADC_LIB_INT_H_
#define FMCADC_LIB_INT_H_
/*
* offsetof and container_of come from kernel.h header file
*/
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = ((void *)ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define to_dev_zio(dev) (container_of(dev, struct __fmcadc_dev_zio, gid))
/* ->open takes different args than open(), so fa a fun to use tpyeof */
struct fmcadc_board_type;
struct fmcadc_dev *fmcadc_internal_open(const struct fmcadc_board_type *b,
unsigned int dev_id,
unsigned long totalsamples,
unsigned int nbuffer,
unsigned long flags);
/*
* The operations structure is the device-specific backend of the library
*/
struct fmcadc_operations {
typeof(fmcadc_internal_open) *open;
typeof(fmcadc_close) *close;
typeof(fmcadc_acq_start) *acq_start;
typeof(fmcadc_acq_poll) *acq_poll;
typeof(fmcadc_acq_stop) *acq_stop;
typeof(fmcadc_apply_config) *apply_config;
typeof(fmcadc_retrieve_config) *retrieve_config;
typeof(fmcadc_get_param) *get_param;
typeof(fmcadc_set_param) *set_param;
typeof(fmcadc_request_buffer) *request_buffer;
typeof(fmcadc_fill_buffer) *fill_buffer;
typeof(fmcadc_tstamp_buffer) *tstamp_buffer;
typeof(fmcadc_release_buffer) *release_buffer;
};
/*
* This structure describes the board supported by the library
* @name name of the board type, for example "fmc-adc-100MS"
* @devname name of the device in Linux
* @driver_type: the kind of driver that hanlde this kind of board (e.g. ZIO)
* @capabilities bitmask of device capabilities for trigger, channel
* acquisition
* @fa_op pointer to a set of operations
*/
struct fmcadc_board_type {
char *name;
char *devname;
char *driver_type;
uint32_t capabilities[__FMCADC_CONF_TYPE_LAST_INDEX];
struct fmcadc_operations *fa_op;
};
/*
* Generic Instance Descriptor
*/
struct fmcadc_gid {
const struct fmcadc_board_type *board;
};
/* Definition of board types */
extern struct fmcadc_board_type fmcadc_100ms_4ch_14bit;
/* Internal structure (ZIO specific, for ZIO drivers only) */
struct __fmcadc_dev_zio {
unsigned int cset;
int fdc;
int fdd;
uint32_t dev_id;
unsigned long flags;
char *devbase;
char *sysbase;
unsigned long samplesize;
unsigned long pagesize;
/* Mandatory field */
struct fmcadc_gid gid;
};
/* Note: bit 16 and up are passed by users, see fmcadc-lib.h */
#define FMCADC_FLAG_VERBOSE 0x00000001
#define FMCADC_FLAG_MALLOC 0x00000002 /* allocate data */
#define FMCADC_FLAG_MMAP 0x00000004 /* mmap data */
/* The board-specific functions are defined in fmc-adc-100m14b4cha.c */
struct fmcadc_dev *fmcadc_zio_open(const struct fmcadc_board_type *b,
unsigned int dev_id,
unsigned long totalsamples,
unsigned int nbuffer,
unsigned long flags);
int fmcadc_zio_close(struct fmcadc_dev *dev);
int fmcadc_zio_acq_start(struct fmcadc_dev *dev,
unsigned int flags, struct timeval *timeout);
int fmcadc_zio_acq_poll(struct fmcadc_dev *dev, unsigned int flags,
struct timeval *timeout);
int fmcadc_zio_acq_stop(struct fmcadc_dev *dev,
unsigned int flags);
struct fmcadc_buffer *fmcadc_zio_request_buffer(struct fmcadc_dev *dev,
int nsamples,
void *(*alloc)(size_t),
unsigned int flags);
int fmcadc_zio_fill_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
unsigned int flags,
struct timeval *timeout);
struct fmcadc_timestamp *fmcadc_zio_tstamp_buffer(struct fmcadc_buffer *buf,
struct fmcadc_timestamp *);
int fmcadc_zio_release_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
void (*free_fn)(void *));
/* The following functions are in config-zio.c */
int fmcadc_zio_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf);
int fmcadc_zio_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf);
int fmcadc_zio_set_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr);
int fmcadc_zio_get_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr);
int fa_zio_sysfs_set(struct __fmcadc_dev_zio *fa, char *name,
uint32_t *value);
#endif /* FMCADC_LIB_INT_H_ */
/*
* Copyright CERN 2013
* Author: Federico Vaga <federico.vaga@gmail.com>
*/
#ifndef FMCADC_LIB_H_
#define FMCADC_LIB_H_
#ifdef __cplusplus
#pragma GCC diagnostic ignored "-Wwrite-strings"
extern "C" {
#endif
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
/* Error codes start from 1024 to void conflicting with libc codes */
#define __FMCADC_ERRNO_START 1024
#define FMCADC_ENOP 1024
#define FMCADC_ENOCAP 1025
#define FMCADC_ENOCFG 1026
#define FMCADC_ENOGET 1027
#define FMCADC_ENOSET 1028
#define FMCADC_ENOCHAN 1029
#define FMCADC_ENOMASK 1030
#define FMCADC_EDISABLED 1031
struct fmcadc_dev;
enum fmcadc_supported_board {
FMCADC_100MS_4CH_14BIT,
__FMCADC_SUPPORTED_BOARDS_LAST_INDEX,
};
/* The buffer hosts data and metadata, plus informative fields */
struct fmcadc_buffer {
void *data;
void *metadata;
int samplesize;
int nsamples;
struct fmcadc_dev *dev;
void *mapaddr;
unsigned long maplen;
unsigned long flags; /* internal to the library */
};
/* This is exactly the zio_timestamp, there is no depency on zio here */
struct fmcadc_timestamp {
uint64_t secs;
uint64_t ticks;
uint64_t bins;
};
/* The following enum can be use to se the mask of valid configurations */
enum fmcadc_configuration_trigger {
FMCADC_CONF_TRG_SOURCE = 0,
FMCADC_CONF_TRG_SOURCE_CHAN,
FMCADC_CONF_TRG_THRESHOLD,
FMCADC_CONF_TRG_POLARITY,
FMCADC_CONF_TRG_DELAY,
FMCADC_CONF_TRG_THRESHOLD_FILTER,
__FMCADC_CONF_TRG_ATTRIBUTE_LAST_INDEX,
};
enum fmcadc_configuration_acquisition {
FMCADC_CONF_ACQ_N_SHOTS = 0,
FMCADC_CONF_ACQ_POST_SAMP,
FMCADC_CONF_ACQ_PRE_SAMP,
FMCADC_CONF_ACQ_DECIMATION,
FMCADC_CONF_ACQ_FREQ_HZ,
FMCADC_CONF_ACQ_N_BITS,
__FMCADC_CONF_ACQ_ATTRIBUTE_LAST_INDEX,
};
enum fmcadc_configuration_channel {
FMCADC_CONF_CHN_RANGE = 0,
FMCADC_CONF_CHN_TERMINATION,
FMCADC_CONF_CHN_OFFSET,
FMCADC_CONF_CHN_SATURATION,
__FMCADC_CONF_CHN_ATTRIBUTE_LAST_INDEX,
};
enum fmcadc_board_status {
FMCADC_CONF_BRD_STATUS = 0,
FMCADC_CONF_BRD_MAX_FREQ_HZ,
FMCADC_CONF_BRD_MIN_FREQ_HZ,
FMCADC_CONF_BRD_STATE_MACHINE_STATUS,
FMCADC_CONF_BRD_N_CHAN,
FMCADC_CONF_UTC_TIMING_BASE_S,
FMCADC_CONF_UTC_TIMING_BASE_T,
FMCADC_CONF_UTC_TIMING_BASE_B,
__FMCADC_CONF_BRD_ATTRIBUTE_LAST_INDEX,
};
enum fmcadc_configuration_type {
FMCADC_CONF_TYPE_TRG = 0, /* Trigger */
FMCADC_CONF_TYPE_ACQ, /* Acquisition */
FMCADC_CONF_TYPE_CHN, /* Channel */
FMCADC_CONF_TYPE_BRD, /* Board */
__FMCADC_CONF_TYPE_LAST_INDEX,
};
/* @deprecated: old typo, keep it for compatibility */
#define FMCADC_CONT_TYPE_BRD FMCADC_CONF_TYPE_BRD
#define __FMCADC_CONF_LEN 64 /* number of allocated items in each structure */
struct fmcadc_conf {
enum fmcadc_configuration_type type;
uint32_t dev_type;
uint32_t route_to;
uint32_t flags; /* how to identify invalid? */
uint64_t mask;
uint32_t value[__FMCADC_CONF_LEN];
};
static inline void fmcadc_set_conf_mask(struct fmcadc_conf *conf,
unsigned int conf_index)
{
conf->mask |= (1LL << conf_index);
}
/* assign a configuration item, and its mask */
static inline void fmcadc_set_conf(struct fmcadc_conf *conf,
unsigned int conf_index, uint32_t val)
{
conf->value[conf_index] = val;
fmcadc_set_conf_mask(conf, conf_index);
}
/* retieve a configuration item */
static inline int fmcadc_get_conf(struct fmcadc_conf *conf,
unsigned int conf_index,
uint32_t *val)
{
if (conf->mask & (1LL << conf_index)) {
*val = conf->value[conf_index];
return 0;
} else {
return -1;
}
}
/* Flags used in open/acq/config -- note: low-bits are used by lib-int.h */
#define FMCSDC_F_USERMASK 0xffff0000
#define FMCADC_F_FLUSH 0x00010000
#define FMCADC_F_VERBOSE 0x00020000
/*
* Actual functions follow
*/
extern int fmcadc_init(void);
extern void fmcadc_exit(void);
extern char *fmcadc_strerror(int errnum);
extern struct fmcadc_dev *fmcadc_open(char *name, unsigned int dev_id,
unsigned long totalsamples,
unsigned int nbuffer,
unsigned long flags);
extern struct fmcadc_dev *fmcadc_open_by_lun(char *name, int lun,
unsigned long totalsamples,
unsigned int nbuffer,
unsigned long flags);
extern int fmcadc_close(struct fmcadc_dev *dev);
extern int fmcadc_acq_start(struct fmcadc_dev *dev, unsigned int flags,
struct timeval *timeout);
extern int fmcadc_acq_poll(struct fmcadc_dev *dev, unsigned int flags,
struct timeval *timeout);
extern int fmcadc_acq_stop(struct fmcadc_dev *dev, unsigned int flags);
extern int fmcadc_reset_conf(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf);
extern int fmcadc_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf);
extern int fmcadc_retrieve_config(struct fmcadc_dev *dev,
struct fmcadc_conf *conf);
extern int fmcadc_get_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr);
extern int fmcadc_set_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr);
extern struct fmcadc_buffer *fmcadc_request_buffer(struct fmcadc_dev *dev,
int nsamples,
void *(*alloc_fn)(size_t),
unsigned int flags);
extern int fmcadc_fill_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
unsigned int flags,
struct timeval *timeout);
extern struct fmcadc_timestamp *fmcadc_tstamp_buffer(struct fmcadc_buffer *buf,
struct fmcadc_timestamp *);
extern int fmcadc_release_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
void (*free_fn)(void *));
extern char *fmcadc_get_driver_type(struct fmcadc_dev *dev);
/* libfmcadc version string */
extern const char * const libfmcadc_version_s;
/* zio version string used during compilation of libfmcadc */
extern const char * const libfmcadc_zio_version_s;
static inline int fmcadc_mshot_buf_max_size_get(struct fmcadc_dev *dev,
int *value)
{
return fmcadc_get_param(dev, "cset0/max-sample-mshot", NULL, value);
}
static inline int fmcadc_buffer_type_get(struct fmcadc_dev *dev, char *buf_type)
{
return fmcadc_get_param(dev, "cset0/current_buffer", buf_type, NULL);
}
static inline int fmcadc_buffer_maximum_size_get(struct fmcadc_dev *dev,
int *size)
{
char s[16];
int err;
err = fmcadc_buffer_type_get(dev, s);
if (err)
return -1;
if (!strcmp(s, "vmalloc")) {
return fmcadc_get_param(dev,
"cset0/chani/buffer/max-buffer-kb",
NULL, size);
} else if (!strcmp(s, "kmalloc")) {
return 4 * 1024; /* MiB => KiB */
}
return -1;
}
static inline int fmcadc_buffer_maximum_size_set(struct fmcadc_dev *dev,
int size)
{
char s[16];
int err;
err = fmcadc_buffer_type_get(dev, s);
if (err)
return -1;
if (!strcmp(s, "vmalloc")) {
return fmcadc_set_param(dev,
"cset0/chani/buffer/max-buffer-kb",
NULL, &size);
} else if (!strcmp(s, "kmalloc")) {
return -1; /* cannot be changed */
}
return -1;
}
/**
* Get the current software trigger enable status
* @param[in] dev adc device token
* @param[out] enable enable status
* @return 0 on success. -1 on error and errno is set appropriately
*/
static inline int fmcadc_trigger_sw_status(struct fmcadc_dev *dev,
unsigned int *enable)
{
return fmcadc_get_param(dev, "cset0/trigger/sw-trg-enable",
NULL, (int *)enable);
}
/**
* Set the current software trigger enable status
* @param[in] dev adc device token
* @param[in] enable 0 disable, 1 enable
* @return 0 on success. -1 on error and errno is set appropriately
*/
static inline int fmcadc_trigger_sw_enable(struct fmcadc_dev *dev,
unsigned int enable)
{
int value = !!enable;
return fmcadc_set_param(dev, "cset0/trigger/sw-trg-enable",
NULL, &value);
}
/**
* Execute a software trigger
* @param[in] dev adc device token
* @return 0 on success. -1 on error and errno is set appropriately
*/
static inline int fmcadc_trigger_sw_fire(struct fmcadc_dev *dev)
{
int value = 1;
return fmcadc_set_param(dev, "cset0/trigger/sw-trg-fire",
NULL, &value);
}
#ifdef __cplusplus
}
#endif
#endif /* FMCADC_LIB_H_ */
/*
* Copyright CERN 2013, GNU GPL 2 or later.
* Author: Alessandro Rubini
*/
#include "fmcadc-lib.h"
const char * const libfmcadc_version_s = "libfmcadc version: " GIT_VERSION;
const char * const libfmcadc_zio_version_s = "libfmcadc is using zio version: " ZIO_GIT_VERSION;
/* We currently do nothing in init/exit. We might check /proc/meminfo... */
int fmcadc_init(void)
{
return 0;
}
void fmcadc_exit(void)
{
return;
}
/*
* Initializing and cleaning up the fmc adc library
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.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.
*/
#include <string.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
/* * * * * * * * * * * * * * * * Utilities * * * * * * * * * * * * * * * * */
/*
* fmcadc_strerror
* @dev: device for which you want to know the meaning of the error
* @errnum: error number
*/
static struct fmcadc_errors {
int num;
char *str;
} fmcadc_errors[] = {
{ FMCADC_ENOP, "Operation not supported"},
{ FMCADC_ENOCAP, "Capabilities not supported"},
{ FMCADC_ENOCFG, "Configuration type not supported"},
{ FMCADC_ENOGET, "Cannot get capabilities information"},
{ FMCADC_ENOSET, "Cannot set capabilities information"},
{ FMCADC_ENOCHAN, "Invalid channel"},
{ FMCADC_ENOMASK, "Missing configuration mask"},
{ FMCADC_EDISABLED, "Trigger is disabled: I/O aborted"},
{ 0, }
};
char *fmcadc_strerror(int errnum)
{
struct fmcadc_errors *p;
if (errnum < __FMCADC_ERRNO_START)
return strerror(errnum);
for (p = fmcadc_errors; p->num; p++)
if (p->num == errnum)
return p->str;
return "Unknown error code";
}
/*
* fmcadc_get_driver_type
* @dev: device which want to know the driver type
*/
char *fmcadc_get_driver_type(struct fmcadc_dev *dev)
{
struct fmcadc_gid *b = (void *)dev;
return b->board->driver_type;
}
/*
* Routing public functions to device-specific code
*
* Copyright (C) 2013 CERN (www.cern.ch)
* Author: Federico Vaga <federico.vaga@gmail.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fmcadc-lib.h"
#include "fmcadc-lib-int.h"
int fmcadc_acq_start(struct fmcadc_dev *dev,
unsigned int flags,
struct timeval *timeout)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->acq_start(dev, flags, timeout);
}
int fmcadc_acq_poll(struct fmcadc_dev *dev, unsigned int flags,
struct timeval *timeout)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->acq_poll(dev, flags, timeout);
}
int fmcadc_acq_stop(struct fmcadc_dev *dev, unsigned int flags)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->acq_stop(dev, flags);
}
int fmcadc_apply_config(struct fmcadc_dev *dev, unsigned int flags,
struct fmcadc_conf *conf)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
uint64_t cap_mask;
if (!conf->mask) {
errno = FMCADC_ENOMASK;
return -1; /* Nothing to do */
}
cap_mask = b->capabilities[conf->type];
if ((cap_mask & conf->mask) != conf->mask) {
/* Unsupported capabilities */
errno = FMCADC_ENOCAP;
return -1;
}
return b->fa_op->apply_config(dev, flags, conf);
}
int fmcadc_retrieve_config(struct fmcadc_dev *dev, struct fmcadc_conf *conf)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
uint64_t cap_mask;
if (!conf->mask) {
errno = FMCADC_ENOMASK;
return -1; /* Nothing to do */
}
cap_mask = b->capabilities[conf->type];
if ((cap_mask & conf->mask) != conf->mask) {
/* Unsupported capabilities */
errno = FMCADC_ENOCAP;
return -1;
}
return b->fa_op->retrieve_config(dev, conf);
}
int fmcadc_get_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->get_param(dev, name, sptr, iptr);
}
int fmcadc_set_param(struct fmcadc_dev *dev, char *name,
char *sptr, int *iptr)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->set_param(dev, name, sptr, iptr);
}
struct fmcadc_buffer *fmcadc_request_buffer(struct fmcadc_dev *dev,
int nsamples,
void *(*alloc)(size_t),
unsigned int flags)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->request_buffer(dev, nsamples, alloc, flags);
}
int fmcadc_fill_buffer(struct fmcadc_dev *dev,
struct fmcadc_buffer *buf,
unsigned int flags,
struct timeval *timeout)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->fill_buffer(dev, buf, flags, timeout);
}
struct fmcadc_timestamp *fmcadc_tstamp_buffer(struct fmcadc_buffer *buf,
struct fmcadc_timestamp *ts)
{
struct fmcadc_gid *g = (struct fmcadc_gid *)buf->dev;
const struct fmcadc_board_type *b = g->board;
return b->fa_op->tstamp_buffer(buf, ts);
}
int fmcadc_release_buffer(struct fmcadc_dev *dev, struct fmcadc_buffer *buf,
void (*free)(void *))
{
struct fmcadc_gid *g = (struct fmcadc_gid *)dev;
const struct fmcadc_board_type *b = g->board;
if (!buf)
return 0;
return b->fa_op->release_buffer(dev, buf, free);
}
fald-simple-acq
fald-test
fald-simple-get-conf
fald-acq
fald-trg-cfg
fald-bad-clock
\ No newline at end of file
# If it exists includes Makefile.specific. In this Makefile, you should put
# specific Makefile code that you want to run before this. For example,
# build a particular environment.
-include Makefile.specific
# include parent_common.mk for buildsystem's defines
REPO_PARENT ?= ../..
-include $(REPO_PARENT)/parent_common.mk
DESTDIR ?= /usr/local
LIBADC = ../lib/
ZIO ?= ../zio
ZIO_ABS ?= $(abspath $(ZIO) )
GIT_VERSION := $(shell git describe --dirty --long --tags)
ZIO_GIT_VERSION := $(shell cd $(ZIO_ABS); git describe --dirty --long --tags)
CFLAGS = -Wall -g -ggdb -I$(LIBADC) -I$(ZIO_ABS)/include -I../kernel $(EXTRACFLAGS)
CFLAGS += -DGIT_VERSION="\"$(GIT_VERSION)\""
CFLAGS += -DZIO_GIT_VERSION="\"$(ZIO_GIT_VERSION)\""
LDFLAGS = -L$(LIBADC)
LDLIBS = -lfmcadc -lpthread -lrt
DEMOS := fald-simple-acq fald-acq fald-trg-cfg
DEMOS += fald-simple-get-conf
DEMOS += fald-test
DEMOS += fald-bad-clock
all: demo
demo: $(DEMOS)
install:
install -d $(DESTDIR)/bin
install -D $(DEMOS) $(DESTDIR)/bin
%: %.c $(LIBADC)/libfmcadc.a
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(LDLIBS)
# make nothing for modules_install, but avoid errors
modules_install:
clean:
rm -f $(DEMOS) *.o *~
.PHONY: all, clean
This diff is collapsed.
/*
* Copyright CERN 2014
* Author: Federico Vaga <federico.vaga@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <sys/time.h>
#include <linux/zio-user.h>
#include <fmcadc-lib.h>
#include <fmc-adc-100m14b4cha.h>
static char git_version[] = "version: " GIT_VERSION;
static char zio_git_version[] = "zio version: " ZIO_GIT_VERSION;
/* Subtract the `struct timespec' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */
int timespec_subtract (result, x, y)
struct timespec *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_nsec < y->tv_nsec) {
int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
y->tv_nsec -= 1000000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_nsec - y->tv_nsec > 1000000000) {
int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
y->tv_nsec += 1000000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_nsec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_nsec = x->tv_nsec - y->tv_nsec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}
static void fald_help()
{
printf("\nfald-bad-clock [OPTIONS] <devid>\n\n");
printf(" -i <seconds> observation interval\n\n");
printf(" -h show this help\n\n");
printf(" -V show version information\n\n");
exit(1);
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s %s\n", pname, zio_git_version);
printf("%s\n", libfmcadc_version_s);
printf("%s\n", libfmcadc_zio_version_s);
}
int main (int argc, char *argv[])
{
struct fmcadc_dev *adc;
struct fmcadc_conf brd_cfg;
struct timespec sys_start, sys_cur, adc_cur, dlt_ts, dlt_dlt_ts = {0, 0};
int err, devid, interval = 360;
uint32_t adc_sec, adc_ticks;
char c;
/* Prepare the board timing base configuration */
memset(&brd_cfg, 0, sizeof(brd_cfg));
brd_cfg.type = FMCADC_CONT_TYPE_BRD;
while ((c = getopt(argc, argv, "i:hV")) >= 0) {
switch (c) {
case 'i':
err = sscanf(optarg, "%d", &interval);
if (err != 1)
fald_help();
break;
case '?':
case 'h':
fald_help();
break;
case 'V':
print_version(argv[0]);
exit(0);
}
}
sscanf(argv[argc-1], "%x", &devid);
adc = fmcadc_open("fmc-adc-100m14b4cha", devid, 0, 0, FMCADC_F_FLUSH);
if (!adc) {
fprintf(stderr, "%s: cannot open device: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
do {
err = clock_gettime(CLOCK_REALTIME, &sys_start);
if (err) {
fprintf(stderr, "%s: cannot get real time: %s",
argv[0], strerror(errno));
exit(1);
}
} while (sys_start.tv_nsec > 1000);
/* Configure ADC internal clock */
adc_sec = sys_start.tv_sec;
adc_ticks = sys_start.tv_nsec / FA100M14B4C_UTC_CLOCK_NS;
fmcadc_set_conf(&brd_cfg, FMCADC_CONF_UTC_TIMING_BASE_T, adc_ticks);
fmcadc_set_conf(&brd_cfg, FMCADC_CONF_UTC_TIMING_BASE_S, adc_sec);
err = fmcadc_apply_config(adc, 0 , &brd_cfg);
if (err && errno != FMCADC_ENOMASK) {
fprintf(stderr, "%s: cannot configure board %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
fprintf(stdout,
"ADC clock configured: %010li s %010li ns ( %i %ins ticks)\n",
sys_start.tv_sec, sys_start.tv_nsec,
adc_ticks, FA100M14B4C_UTC_CLOCK_NS);
/* Measure how clock diverge */
while (interval--) {
/* Get the system clock */
err = clock_gettime(CLOCK_REALTIME, &sys_cur);
if (err) {
fprintf(stderr, "%s: cannot get real time: %s",
argv[0], strerror(errno));
exit(1);
}
/* Get the ADC clock */
err = fmcadc_retrieve_config(adc, &brd_cfg);
if (err) {
fprintf(stderr, "%s: cannot get trigger config: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
fmcadc_get_conf(&brd_cfg, FMCADC_CONF_UTC_TIMING_BASE_S,
&adc_sec);
fmcadc_get_conf(&brd_cfg, FMCADC_CONF_UTC_TIMING_BASE_T,
&adc_ticks);
adc_cur.tv_sec = adc_sec;
adc_cur.tv_nsec = adc_ticks * FA100M14B4C_UTC_CLOCK_NS;
/* Get the difference between system and ADC clock */
timespec_subtract(&dlt_ts, &sys_cur, &adc_cur);
/* How bad is? */
timespec_subtract(&dlt_dlt_ts, &dlt_ts, &dlt_dlt_ts);
/* Show time stamps and delta */
printf(" sys %ld.%.9ld s\n", sys_cur.tv_sec,
sys_cur.tv_nsec);
printf(" adc %ld.%.9ld s\n", adc_cur.tv_sec,
adc_cur.tv_nsec);
printf("|dlt| %ld.%.9ld s (%ld.%.9ld s)\n",
dlt_ts.tv_sec, dlt_ts.tv_nsec,
dlt_dlt_ts.tv_sec, dlt_dlt_ts.tv_nsec);
dlt_dlt_ts = dlt_ts;
if (dlt_ts.tv_sec) {
timespec_subtract(&dlt_dlt_ts, &sys_cur, &sys_start);
printf("Clock diverged of %ld.%.9ld s in %ld.%.9ld s\n",
dlt_ts.tv_sec, dlt_ts.tv_nsec,
dlt_dlt_ts.tv_sec, dlt_dlt_ts.tv_nsec);
break;
}
printf(" sleep 1 s\n");
sleep(1);
}
exit(0);
}
/* Copyright 2013 CERN
* Author: Federico Vaga <federico.vaga@gmail.comZ
* License: GPLv2
*
* This is a simple program to configure the FMC ADC trigger. It is not bug
* aware because it is only a demo program to show you how you can handle the
* trigger.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <linux/zio-user.h>
#include <fmcadc-lib.h>
static char git_version[] = "version: " GIT_VERSION;
static char zio_git_version[] = "zio version: " ZIO_GIT_VERSION;
static void fald_help()
{
printf("\nfald-simple-acq [OPTIONS] <DEVID>\n\n");
printf(" <DEVID>: hexadecimal identifier (e.g.: \"0x200\")\n");
printf(" --before|-b <num> number of pre samples\n");
printf(" --after|-a <num> n. of post samples (default: 16)\n");
printf(" --nshots|-n <num> number of trigger shots\n");
printf(" --delay|-d <num> delay sample after trigger\n");
printf(" --under-sample|-U <num> pick 1 sample every <num>\n");
printf(" --threshold|-t <num> internal trigger threshold\n");
printf(" --channel|-c <num> channel used as trigger (0..3)\n");
printf(" --tiemout|-T <millisec> timeout for acquisition\n");
printf(" --negative-edge internal trigger is falling edge\n");
printf(" --binary|-B <file> save binary to <file>\n");
printf(" --multi-binary|-M <file> save two files per shot: "
"<file>.0000.ctrl etc\n");
printf(" --dont-read|-N config-only, use with zio-dump\n");
printf(" --version|-V print version information\n");
printf(" --help|-h show this help\n\n");
}
static int trgval[__FMCADC_CONF_LEN]; /* FIXME: this is not used */
static struct option options[] = {
{"before", required_argument, 0, 'b'},
{"after", required_argument, 0, 'a'},
{"nshots", required_argument, 0, 'n'},
{"delay", required_argument, 0, 'd'},
{"under-sample",required_argument, 0, 'u'},
{"threshold", required_argument, 0, 't'},
{"channel", required_argument, 0, 'c'},
{"timeout", required_argument, 0, 'T'},
{"negative-edge", no_argument, &trgval[FMCADC_CONF_TRG_POLARITY], 1},
/* new options, to help stress-test */
{"binary", required_argument, 0, 'B'},
{"multi-binary",required_argument, 0, 'M'},
{"dont-read", no_argument, 0, 'N'},
/* backward-compatible options */
{"pre", required_argument, 0, 'p'},
{"post", required_argument, 0, 'P'},
{"decimation", required_argument, 0, 'D'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
#define GETOPT_STRING "b:a:n:d:u:t:c:T:B:M:Np:P:D:Vh"
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s %s\n", pname, zio_git_version);
printf("%s\n", libfmcadc_version_s);
printf("%s\n", libfmcadc_zio_version_s);
}
int main(int argc, char *argv[])
{
struct fmcadc_buffer *buf;
struct fmcadc_dev *adc;
struct fmcadc_conf trg, acq;
int i, c, err, opt_index, binmode = 0;
int nshots = 1, presamples = 0, postsamples = 16;
int timeout = -1;
unsigned int dev_id = 0;
char *basefile = NULL;
char fname[PATH_MAX];
FILE *f = NULL;
if (argc == 1) {
fald_help();
exit(1);
}
/* reset attributes and provide defaults */
memset(&trg, 0, sizeof(trg));
trg.type = FMCADC_CONF_TYPE_TRG;
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_SOURCE, 1); /* external */
memset(&acq, 0, sizeof(acq));
acq.type = FMCADC_CONF_TYPE_ACQ;
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_POST_SAMP, postsamples);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_N_SHOTS, nshots);
/* Parse options */
while ((c = getopt_long(argc, argv, GETOPT_STRING,
options, &opt_index)) >=0) {
switch (c) {
case 'b': case 'p': /* before */
presamples = atoi(optarg);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_PRE_SAMP,
presamples);
break;
case 'a': case 'P': /* after */
postsamples = atoi(optarg);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_POST_SAMP,
postsamples);
break;
case 'n':
nshots = atoi(optarg);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_N_SHOTS,
nshots);
break;
case 'd':
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_DELAY,
atoi(optarg));
break;
case 'u': case 'D':
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_DECIMATION,
atoi(optarg));
break;
case 't':
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_THRESHOLD,
atoi(optarg));
break;
case 'c':
/* set internal, and then the channel */
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_SOURCE, 0);
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_SOURCE_CHAN,
atoi(optarg));
break;
case 'T':
timeout = atoi(optarg);
break;
case 'B':
binmode = 1; /* do binary (default is 0) */
basefile = optarg;
break;
case 'M':
binmode = 2; /* do many binaries */
basefile = optarg;
break;
case 'N':
binmode = -1;
break;
case 'V':
print_version(argv[0]);
exit(0);
case 'h': case '?':
fald_help();
exit(1);
break;
}
}
if (optind != argc - 1) {
fprintf(stderr, "%s: DEVICE-ID is a mandatory argument\n",
argv[0]);
fald_help();
exit(1);
} else {
sscanf(argv[optind], "%x", &dev_id);
}
/* Open the ADC */
adc = fmcadc_open("fmc-adc-100m14b4cha", dev_id,
nshots * (presamples + postsamples),
nshots,
FMCADC_F_FLUSH);
if (!adc) {
fprintf(stderr, "%s: cannot open device: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
if (strcmp(fmcadc_get_driver_type(adc), "zio")) {
fprintf(stderr, "%s: not a zio driver, aborting\n", argv[0]);
exit(1);
}
/* If we save to a a file, open it now to error out soon */
if (binmode > 0) {
char *s;
s = basefile;
if (binmode == 2) {
sprintf(fname, "%s.000.ctrl", basefile);
s = fname;
}
f = fopen(s, "a");
if (!f) {
fprintf(stderr, "%s: %s: %s\n", argv[0], s,
strerror(errno));
exit(1);
}
if (binmode == 2)
fclose(f);
}
/* Configure trigger (pick trigger polarity from external array) */
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_POLARITY,
trgval[FMCADC_CONF_TRG_POLARITY]);
err = fmcadc_apply_config(adc, 0 , &trg);
if (err && errno != FMCADC_ENOMASK) {
fprintf(stderr, "%s: cannot configure trigger: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
/* Configure acquisition parameter */
err = fmcadc_apply_config(adc, 0 , &acq);
if (err && errno != FMCADC_ENOMASK) {
fprintf(stderr, "%s: cannot configure acquisition: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
if (timeout < 0) {
/* Start acquisition and wait until it completes */
err = fmcadc_acq_start(adc, 0 , NULL);
} else {
/* Start acquisition and don't wait. We use acq_poll() later */
struct timeval tv = {0, 0};
err = fmcadc_acq_start(adc, 0 , &tv);
}
if (err) {
fprintf(stderr, "%s: cannot start acquisition: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
/* Now, if a timeout was specified, use the poll method */
if (timeout >= 0) {
struct timeval tv = {timeout / 1000, timeout % 1000};
err = fmcadc_acq_poll(adc, 0 , &tv);
}
if (err) {
fprintf(stderr, "%s: timeout after %i ms: %s\n", argv[0],
timeout, strerror(errno));
exit(1);
}
/* Allocate a buffer in the default way */
buf = fmcadc_request_buffer(adc, presamples + postsamples,
NULL /* alloc */, 0);
if (!buf) {
fprintf(stderr, "Cannot allocate buffer (%s)\n",
fmcadc_strerror(errno));
exit(1);
}
/* Fill the buffer once for each shot */
for (i = 0; i < acq.value[FMCADC_CONF_ACQ_N_SHOTS]; ++i) {
struct zio_control *ctrl;
int j, ch;
int16_t *data;
if (binmode < 0) /* no data must be acquired */
break;
err = fmcadc_fill_buffer(adc, buf, 0, NULL);
if (err) {
fprintf(stderr, "%s: shot %i/%i: cannot fill buffer:"
" %s\n", argv[0], i + i,
acq.value[FMCADC_CONF_ACQ_N_SHOTS],
fmcadc_strerror(errno));
exit(1);
}
ctrl = buf->metadata;
data = buf->data;
fprintf(stderr, "Read %d samples from shot %i/%i\n",
ctrl->nsamples,
i + 1, acq.value[FMCADC_CONF_ACQ_N_SHOTS]);
if (binmode == 1) { /* append everything to a single file */
if (fwrite(ctrl, sizeof(*ctrl), 1, f) != 1)
err++;
if (fwrite(data, ctrl->ssize, ctrl->nsamples, f)
!= ctrl->nsamples)
err++;
if (err) {
fprintf(stderr, "%s: write(%s): short write\n",
argv[0], basefile);
exit(1);
}
continue; /* next shot please */
}
if (binmode == 2) { /* several files */
sprintf(fname, "%s.%03i.ctrl", basefile, i);
f = fopen(fname, "w");
if (!f) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], fname, strerror(errno));
exit(1);
}
if (fwrite(ctrl, sizeof(*ctrl), 1, f) != 1) {
fprintf(stderr, "%s: write(%s): short write\n",
argv[0], fname);
exit(1);
}
fclose(f);
sprintf(fname, "%s.%03i.data", basefile, i);
f = fopen(fname, "w");
if (!f) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], fname, strerror(errno));
exit(1);
}
if (fwrite(data, ctrl->ssize, ctrl->nsamples, f)
!= ctrl->nsamples) {
fprintf(stderr, "%s: write(%s): short write\n",
argv[0], fname);
exit(1);
}
fclose(f);
continue;
}
/*
* Finally, binmode = 0.
* We lazily know samplesize is 2 bytes and chcount is 4
*/
for (j = 0; j < ctrl->nsamples / 4; j++) {
printf("%5i ", j - presamples);
for (ch = 0; ch < 4; ch++)
printf("%7i", *(data++));
printf("\n");
}
}
if (binmode == 1)
fclose(f);
fmcadc_release_buffer(adc, buf, NULL);
fmcadc_close(adc);
exit(0);
}
/* Copyright 2013 CERN
* Author: Federico Vaga <federico.vaga@gmail.comZ
* License: GPLv2
*
* This is a simple program to configure the FMC ADC trigger. It is not bug
* aware because it is only a demo program to show you how you can handle the
* trigger.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/zio-user.h>
#include <fmcadc-lib.h>
static char git_version[] = "version: " GIT_VERSION;
static char zio_git_version[] = "zio version: " ZIO_GIT_VERSION;
static void fald_help()
{
printf("\nfald-simple-get-conf [OPTIONS] 0x<DEVICE ID>\n\n");
printf(" <DEVICE>: hexadecimal string which represent the device "
"identificator of an fmc-adc\n");
printf(" --version|-V: show version information\n");
printf(" --help|-h: show this help\n\n");
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s %s\n", pname, zio_git_version);
printf("%s\n", libfmcadc_version_s);
printf("%s\n", libfmcadc_zio_version_s);
}
int main(int argc, char *argv[])
{
struct fmcadc_dev *adc;
struct fmcadc_conf trg, acq, brd, chn;
static struct option options[] = {
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
int opt_index = 0, err = 0, i;
unsigned int dev_id = 0;
char c;
if (argc == 1) {
fald_help();
exit(1);
}
/* reset attribute's mask */
trg.mask = 0;
acq.mask = 0;
/* Parse options */
while((c = getopt_long(argc, argv, "hV", options, &opt_index)) >= 0) {
switch (c) {
case 'V':
print_version(argv[0]);
exit(0);
case 'h':
fald_help();
exit(1);
break;
}
}
if (optind != argc - 1) {
fprintf(stderr, "%s: DEVICE-ID is a mandatory argument\n",
argv[0]);
fald_help();
exit(1);
} else {
sscanf(argv[optind], "0x%x", &dev_id);
}
printf("Open ADC fmc-adc-100m14b4cha dev_id 0x%04x ...\n", dev_id);
/* Open the ADC */
adc = fmcadc_open("fmc-adc-100m14b4cha", dev_id,
/* no buffers expexted */ 0, 0,
/* no flush either */ 0);
if (!adc) {
fprintf(stderr, "%s: cannot open device: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
printf("Get Trigger Configuration ...\n");
/* Configure Trigger parameter to retrieve */
trg.type = FMCADC_CONF_TYPE_TRG;
fmcadc_set_conf_mask(&trg, FMCADC_CONF_TRG_SOURCE);
fmcadc_set_conf_mask(&trg, FMCADC_CONF_TRG_SOURCE_CHAN);
fmcadc_set_conf_mask(&trg, FMCADC_CONF_TRG_THRESHOLD);
fmcadc_set_conf_mask(&trg, FMCADC_CONF_TRG_POLARITY);
fmcadc_set_conf_mask(&trg, FMCADC_CONF_TRG_DELAY);
err = fmcadc_retrieve_config(adc, &trg);
if (err) {
fprintf(stderr, "%s: cannot get trigger config: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
printf(" source: %s\n",
trg.value[FMCADC_CONF_TRG_SOURCE] ? "external" : "internal");
printf(" channel: %d\n", trg.value[FMCADC_CONF_TRG_SOURCE_CHAN]);
printf(" threshold: %d\n", trg.value[FMCADC_CONF_TRG_THRESHOLD]);
printf(" polarity: %d\n", trg.value[FMCADC_CONF_TRG_POLARITY]);
printf(" delay: %d\n", trg.value[FMCADC_CONF_TRG_DELAY]);
printf("Get Acquisition Configuration ...\n");
/* Configure acquisition parameter */
acq.type = FMCADC_CONF_TYPE_ACQ;
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_N_SHOTS);
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_POST_SAMP);
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_PRE_SAMP);
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_DECIMATION);
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_FREQ_HZ);
fmcadc_set_conf_mask(&acq, FMCADC_CONF_ACQ_N_BITS);
err = fmcadc_retrieve_config(adc, &acq);
if (err) {
fprintf(stderr, "%s: cannot get acquisition config: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
printf(" n-shots: %d\n", acq.value[FMCADC_CONF_ACQ_N_SHOTS]);
printf(" post-sample: %d\n", acq.value[FMCADC_CONF_ACQ_POST_SAMP]);
printf(" pre-sample: %d\n", acq.value[FMCADC_CONF_ACQ_PRE_SAMP]);
printf(" decimation: %d\n", acq.value[FMCADC_CONF_ACQ_DECIMATION]);
printf(" frequency: %dHz\n", acq.value[FMCADC_CONF_ACQ_FREQ_HZ]);
printf(" n-bits: %d\n", acq.value[FMCADC_CONF_ACQ_N_BITS]);
printf("Get Board Configuration ...\n");
/* Configure acquisition parameter */
brd.type = FMCADC_CONT_TYPE_BRD;
fmcadc_set_conf_mask(&brd, FMCADC_CONF_BRD_STATE_MACHINE_STATUS);
fmcadc_set_conf_mask(&brd, FMCADC_CONF_BRD_N_CHAN);
err = fmcadc_retrieve_config(adc, &brd);
if (err) {
fprintf(stderr, "%s: cannot get board config: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
printf(" n-chan: %d\n", brd.value[FMCADC_CONF_BRD_N_CHAN]);
printf(" State Machine: %d\n",
brd.value[FMCADC_CONF_BRD_STATE_MACHINE_STATUS]);
for (i = 0; i < brd.value[FMCADC_CONF_BRD_N_CHAN]; ++i) {
printf("Get Channel %d Configuration ...\n", i);
/* Configure acquisition parameter */
chn.type = FMCADC_CONF_TYPE_CHN;
chn.route_to = i;
fmcadc_set_conf_mask(&chn, FMCADC_CONF_CHN_RANGE);
fmcadc_set_conf_mask(&chn, FMCADC_CONF_CHN_TERMINATION);
fmcadc_set_conf_mask(&chn, FMCADC_CONF_CHN_OFFSET);
err = fmcadc_retrieve_config(adc, &chn);
if (err) {
fprintf(stderr, "%s: cannot get channel config: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
printf(" range: %d\n", chn.value[FMCADC_CONF_CHN_RANGE]);
printf(" 50Ohm Termination: %s\n",
chn.value[FMCADC_CONF_CHN_TERMINATION] ? "yes" : "no");
printf(" offset: %d\n", chn.value[FMCADC_CONF_CHN_OFFSET]);
}
fmcadc_close(adc);
exit(0);
}
/* Copyright 2013 CERN
* Author: Federico Vaga <federico.vaga@gmail.com>
* License: GPLv2
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <linux/zio-user.h>
#include <fmcadc-lib.h>
/* Global configuration*/
#define N_CHAN 4
#define CARD_NAME "fmc-adc-100m14b4cha"
static char git_version[] = "version: " GIT_VERSION;
static char zio_git_version[] = "zio version: " ZIO_GIT_VERSION;
unsigned nshots = 1;
unsigned presamples = 10;
unsigned postsamples = 10;
int print_data = 1;
void print_buffer_content(struct fmcadc_buffer *buf);
int read_with_one_buffer(struct fmcadc_dev *dev);
int read_with_n_buffer(struct fmcadc_dev *dev);
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s %s\n", pname, zio_git_version);
printf("%s\n", libfmcadc_version_s);
printf("%s\n", libfmcadc_zio_version_s);
}
int main(int argc, char *argv[])
{
unsigned long totalsamples = nshots * (presamples + postsamples);
unsigned int dev_id, n_buffers = nshots;
struct fmcadc_conf acq, trg;
struct fmcadc_dev *dev;
int test = 0, err;
if ((argc >= 2) && (!strcmp(argv[1], "-V"))) {
print_version(argv[0]);
exit(0);
}
if (argc != 3) {
fprintf(stderr, "%s: Use \"%s [-V] <dev_id> <testnr>\n",
argv[0], argv[0]);
exit(1);
}
sscanf(argv[1], "%x", &dev_id);
sscanf(argv[2], "%i", &test);
/* Change parameters from environment */
if (getenv("FALD_TEST_NSHOTS"))
nshots = atoi(getenv("FALD_TEST_NSHOTS"));
if (getenv("FALD_TEST_PRE_S"))
presamples = atoi(getenv("FALD_TEST_PRE_S"));
if (getenv("FALD_TEST_POST_S"))
postsamples = atoi(getenv("FALD_TEST_POST_S"));
if (getenv("FALD_TEST_NOPRINT"))
print_data = 0;
fmcadc_init();
dev = fmcadc_open(CARD_NAME, dev_id, totalsamples, n_buffers,
FMCADC_F_FLUSH);
if (!dev) {
fprintf(stderr, "%s: fmcadc_open(%s, 0x%x): %s\n", argv[0],
CARD_NAME, dev_id, strerror(errno));
exit(1);
}
if (strcmp(fmcadc_get_driver_type(dev), "zio")) {
fprintf(stderr, "%s: not a zio driver, aborting\n", argv[0]);
exit(1);
}
if (0) { /* We can't change buffer, because chardevs are open */
err = fmcadc_set_param(dev, "cset0/current_buffer", argv[3], 0);
if (err) {
fprintf(stderr, "%s: cannot set '%s' as buffer: %s\n",
argv[0], argv[3], fmcadc_strerror(errno));
exit(1);
}
}
/* FIXME: use nshots to set cset0/chani/buffer/max-buffer-len */
/* FIXME: use maxsize to set cset0/chani/buffer/max-buffer-kb */
/* configure acquisition parameters */
memset(&acq, 0, sizeof(acq));
acq.type = FMCADC_CONF_TYPE_ACQ;
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_N_SHOTS, nshots);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_PRE_SAMP, presamples);
fmcadc_set_conf(&acq, FMCADC_CONF_ACQ_POST_SAMP, postsamples);
err = fmcadc_apply_config(dev, 0, &acq);
if (err) {
fprintf(stderr, "%s: apply_config(acq): %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
/* configure trigger parameters */
memset(&trg, 0, sizeof(trg));
trg.type = FMCADC_CONF_TYPE_TRG;
fmcadc_set_conf(&trg, FMCADC_CONF_TRG_SOURCE, 1); /* external */
err = fmcadc_apply_config(dev, 0, &trg);
if (err) {
fprintf(stderr, "%s: apply_config(trigger): %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
/* Start the acquisition */
err = fmcadc_acq_start(dev, 0 , NULL);
if (err) {
fprintf(stderr, "%s: cannot start acquisition: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
switch (test) {
case 0:
err = read_with_one_buffer(dev);
break;
case 1:
err = read_with_n_buffer(dev);
break;
}
if (err) {
fprintf(stderr, "%s: problem with read buffer: %s\n",
argv[0], fmcadc_strerror(errno));
exit(1);
}
/* Stop acquisition, close device and exit from library */
fmcadc_acq_stop(dev, 0);
fmcadc_close(dev);
fmcadc_exit();
exit(0);
}
/* Read all shots with a single buffer and then release it */
int read_with_one_buffer(struct fmcadc_dev *dev)
{
struct fmcadc_buffer *buf;
int err = 0, i;
buf = fmcadc_request_buffer(dev, presamples + postsamples, NULL, 0);
for (i = 0; i < nshots; ++i) {
err = fmcadc_fill_buffer(dev, buf, 0, NULL);
if (err)
break;
print_buffer_content(buf);
}
fmcadc_release_buffer(dev, buf, NULL);
return err;
}
/* Read all shots with a multiple buffer and then release them
* request, fill and release are separated in different loop to show that
* are not strictly consecutive operations
*/
int read_with_n_buffer(struct fmcadc_dev *dev)
{
struct fmcadc_buffer *buf[nshots] ;
int err = 0, i;
/* Allocate all buffers before the use */
for (i = 0; i < nshots; ++i)
buf[i] = fmcadc_request_buffer(dev,
presamples + postsamples, NULL, 0);
/* Fill all buffers */
for (i = 0; i < nshots; ++i) {
err = fmcadc_fill_buffer(dev, buf[i], 0, NULL);
if (err)
break;
print_buffer_content(buf[i]);
}
/* Release all buffers */
for (i = 0; i < nshots; ++i)
fmcadc_release_buffer(dev, buf[i], NULL);
return err;
}
void print_buffer_content(struct fmcadc_buffer *buf)
{
int16_t *data = buf->data; /* get data */
struct fmcadc_timestamp *ts;
int i, ch;
ts = fmcadc_tstamp_buffer(buf, NULL);
printf("timestamp %lli:%lli:%lli\n",
(long long)ts->secs,
(long long)ts->ticks,
(long long)ts->bins);
if (!print_data)
return;
for (i = 0; i < presamples + postsamples; i++) {
printf("%5i ", i - presamples);
for (ch = 0; ch < N_CHAN; ch++)
printf("%7i", *(data++));
printf("\n");
}
}
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define FALD_TRG_ARGC 2
static char git_version[] = "version: " GIT_VERSION;
static char zio_git_version[] = "zio version: " ZIO_GIT_VERSION;
void send_config(int fd, char *msg)
{
/* removing newline at the end */
if (msg[strlen(msg)-1] == '\n')
msg[strlen(msg)-1] = '\0';
if (strlen(msg)) {
write(fd, msg, strlen(msg));
fprintf(stdout, "New trig setting sent: %s(len: %d)\n",
msg, (int)strlen(msg));
} else {
fprintf(stdout, "Nothing sent due to an empty user input\n");
}
}
static void print_version(char *pname)
{
printf("%s %s\n", pname, git_version);
printf("%s %s\n", pname, zio_git_version);
}
int main(int argc, char *argv[])
{
int i, fd;
char adcfifo[128];
char msg[512], *ptr;
unsigned int devid;
if ((argc >= 2) && (!strcmp(argv[1], "-V"))) {
print_version(argv[0]);
exit(0);
}
if (argc < FALD_TRG_ARGC) {
fprintf(stderr, "\nUsage:\nfald-trg-cfg [-V] <dev_id> [options]\n");
return -1;
}
sscanf(argv[FALD_TRG_ARGC - 1], "%x", &devid);
if (access(adcfifo, F_OK) == -1) {
sprintf(adcfifo, "/tmp/adcfifo-%04x", devid);
/* create the FIFO (named pipe) */
mkfifo(adcfifo, 0666);
}
fd = open(adcfifo, O_WRONLY);
if (fd == -1) {
fprintf(stdout, "open %s failed errno:%d\n", adcfifo, errno);
exit(1);
}
/*
* If we have parameters from the command line, then send them
* immediately and close the program. This allow external program to
* invoke this one for the configuration instead of interactive input
*/
if (argc > FALD_TRG_ARGC) {
memset(msg, 0, 512);
for (i = 2; i < argc; ++i) {
strcat(msg, argv[i]);
strcat(msg, " ");
}
send_config(fd, msg);
close(fd);
return 0;
}
/* get user input */
while (1) {
memset(msg, 0, 512);
fprintf(stdout, "Change trig config using standard args: -a -b -c -n -e\n >>>: ");
ptr = fgets(msg, sizeof(msg), stdin);
if (!ptr) {
fprintf(stderr, "Error while reading options\n");
break;
}
send_config(fd, msg);
}
close(fd);
/* don't remove the FIFO to not break the reader side */
//unlink(adcfifo);
return 0;
}
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