Commit dfedced2 authored by Federico Vaga's avatar Federico Vaga

tools: remove unused oldtools

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 392a10dc
fd-raw-input
parport-burst
fd-raw-gettime
fd-raw-settime
fd-raw-output
fd-raw-perf
fdelay-list
fdelay-term
fdelay-board-time
fdelay-open-by-lun
fdelay-read
fdelay-fread
fdelay-pulse
fdelay-pulse-tom
# older user-space tools for spec-fine-delay
# 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
M = $(shell /bin/pwd)/../kernel
HOST_EXTRACFLAGS += -I$(M) -I../lib -I../zio/include -Wno-trigraphs -Wall -ggdb
HOSTCC ?= gcc
hostprogs-y := fd-raw-input
hostprogs-y += fd-raw-gettime
hostprogs-y += fd-raw-settime
hostprogs-y += parport-burst
hostprogs-y += fd-raw-output
hostprogs-y += fd-raw-perf
# programs that used to live in lib/
hostprogs-y += fdelay-list
hostprogs-y += fdelay-term
hostprogs-y += fdelay-board-time
hostprogs-y += fdelay-open-by-lun
hostprogs-y += fdelay-read
hostprogs-y += fdelay-fread
hostprogs-y += fdelay-pulse
hostprogs-y += fdelay-pulse-tom
# we are not in the kernel, so we need to piggy-back on "make modules"
all modules: $(hostprogs-y)
clean:
rm -f $(hostprogs-y) *.o *~
# make nothing for modules_install, but avoid errors
modules_install install:
# we need this as we are out of the kernel
%: %.c
$(HOSTCC) $(HOST_EXTRACFLAGS) -O2 -Wall $^ -L../lib -lfdelay -o $@
/*
* a tool to get the fdelay time from sysfs
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
#include "fdelay-raw.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
struct time_word {
uint32_t val;
char *name;
};
struct time_word words[] = {
{0, "utc-h"}, /* This must be first, as this forces hardware access */
{0, "utc-l"},
{0, "coarse"},
};
int main(int argc, char **argv)
{
char *sysnames[10];
char path[80];
int i, err;
i = fdelay_get_sysnames(sysnames);
if (!i) {
fprintf(stderr, "%s: no fine-delay devices\n", argv[0]);
exit(1);
}
if (i > 1) {
fprintf(stderr, "%s: several fine-delay devices, using %s\n",
argv[0], sysnames[0]);
}
for (i = 0, err = 0; i < ARRAY_SIZE(words); i++) {
sprintf(path, "%s/%s", sysnames[0], words[i].name);
if (fdelay_sysfs_get(path, &words[i].val) != 0)
err++;
}
if (err) {
fprintf(stderr, "%s: got %i errors reading %i attributes\n",
argv[0], err, ARRAY_SIZE(words));
}
printf("%i.%09li\n", words[1].val, (long)words[2].val * 8);
return 0;
}
/*
* an input tools that accesses the ZIO device
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
enum {
MODE_HEX = 1,
MODE_FLOAT = 2,
MODE_PICO = 4
};
int expect;
int show_time;
void event(uint32_t *a, char *name, int *seq, int modemask, long double *t1,
uint64_t *p1)
{
int sequence = a[FD_ATTR_TDC_SEQ];
long double t2;
int64_t p2, delta;
static int64_t guess;
if (*seq != -1) {
if (sequence != ((*seq + 1) & 0xffff)) {
printf("%s: LOST %i events\n", name,
(sequence - (*seq + 1)) & 0xffff);
*t1 = 0.0;
*p1 = 0LL;
}
}
*seq = sequence;
if (show_time) {
static struct timeval tv, otv;
int deltamicro;
gettimeofday(&tv, NULL);
if (otv.tv_sec) {
deltamicro = (tv.tv_sec - otv.tv_sec) * 1000 * 1000
+ tv.tv_usec - otv.tv_usec;
printf("+ %i.%06i:", deltamicro / 1000 / 1000,
deltamicro % (1000*1000));
} else {
printf("%03li.%06li:", tv.tv_sec % 1000, tv.tv_usec);
}
otv = tv;
} else {
/* time works with one file only, avoid the fname */
printf("%s:", name);
}
if (modemask & MODE_HEX) {
printf(" %08x %08x %08x %08x %08x\n",
a[FD_ATTR_TDC_UTC_H],
a[FD_ATTR_TDC_UTC_L],
a[FD_ATTR_TDC_COARSE],
a[FD_ATTR_TDC_FRAC],
a[FD_ATTR_TDC_SEQ]);
}
if (modemask & MODE_FLOAT) {
t2 = a[FD_ATTR_TDC_UTC_L] + a[FD_ATTR_TDC_COARSE]
* .000000008; /* 8ns */
if (*t1) {
printf(" %17.9Lf (delta %13.9Lf)\n",
t2, t2 - *t1);
} else {
printf(" %17.9Lf\n", t2);
}
*t1 = t2;
}
if (modemask & MODE_PICO) {
p2 = a[FD_ATTR_TDC_COARSE] * 8000LL
+ a[FD_ATTR_TDC_FRAC] * 8000LL / 4096;
delta = p2 - *p1;
if (delta < 0)
delta += 1000LL * 1000 * 1000 * 1000;
if (*p1) {
printf(" %012lli - delta %012lli", p2, delta);
if (expect) {
guess += expect;
if (guess > 1000LL * 1000 * 1000 * 1000)
guess -= 1000LL * 1000 * 1000 * 1000;
printf(" - error %6i", (int)(p2 - guess));
}
putchar('\n');
}
else {
printf(" %012lli\n", p2);
if (expect)
guess = p2;
}
*p1 = p2;
}
}
#define MAXFD 16
struct zio_control ctrl;
int main(int argc, char **argv)
{
glob_t glob_buf;
int i, j, tout = 0, maxfd = 0;
int fd[MAXFD], seq[MAXFD];
struct timeval tv, *tvp = NULL;
fd_set allset, curset;
int modemask = MODE_HEX;
long double t1[MAXFD] = {0.0,};
uint64_t p1[MAXFD] = {0LL,};
uint32_t *attrs;
if (getenv("FD_EXPECTED_RATE"))
expect = atoi(getenv("FD_EXPECTED_RATE"));
if (getenv("FD_SHOW_TIME"))
show_time = 1;
while ((i = getopt(argc, argv, "fprht:")) != -1) {
switch(i) {
case 'f':
modemask &= ~MODE_HEX;
modemask |= MODE_FLOAT;
break;
case 'p':
modemask &= ~MODE_HEX;
modemask |= MODE_PICO;
break;
case 'r':
case 'h':
modemask |= MODE_HEX;
break;
case 't':
tout = atoi(optarg);
break;
}
}
/* adjust for consumed arguments */
argv[optind - 1] = argv[0];
argc -= (optind - 1);
argv += (optind - 1);
if (argc < 2) {
/* rebuild argv using globbing */
glob_buf.gl_offs = 1;
/* "????" spits a trigraph warning: use "*" instead (bah!) */
glob("/dev/fd-*-0-0-ctrl", GLOB_DOOFFS, NULL, &glob_buf);
glob("/dev/zio/fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob_buf.gl_pathv[0] = argv[0];
argv = glob_buf.gl_pathv;
argc = glob_buf.gl_pathc + glob_buf.gl_offs;
}
if (argc == 1) {
fprintf(stderr, "%s: no arguments and no glob results\n",
argv[0]);
exit(1);
};
if (argc >= MAXFD) {
fprintf(stderr, "%s: too many file names\n", argv[0]);
exit(1);
};
FD_ZERO(&allset);
for (i = 1; i < argc; i++) {
fd[i] = open(argv[i], O_RDONLY);
if (fd[i] < 0) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1],
strerror(errno));
exit(1);
}
if (fd[i] > maxfd)
maxfd = fd[i];
FD_SET(fd[i], &allset);
seq[i] = -1;
}
if (tout == 0)
setlinebuf(stdout);
tvp = NULL;
/* Ok, now wait for each of them to spit a timestamp */
while (1) {
curset = allset;
switch(select(maxfd + 1, &curset, NULL, NULL, tvp)) {
case -1:
if (errno == EINTR)
continue;
fprintf(stderr, "%s: select: %s\n", argv[0],
strerror(errno));
exit(1);
case 0:
exit(0);
}
if (tout) {
/* prepare timeout for next time */
tv.tv_sec = tout / (1000 * 1000);
tv.tv_usec = tout % (1000 * 1000);
tvp = &tv;
}
for (i = 1; i < argc; i++) {
if (!FD_ISSET(fd[i], &curset))
continue;
/* Ok, it's there: read and decode */
j = read(fd[i], &ctrl, sizeof(ctrl));
if (j != sizeof(ctrl)) {
fprintf(stderr, "%s: read(): got %i not %i\n",
argv[0], j, sizeof(ctrl));
exit(1);
}
attrs = ctrl.attr_channel.ext_val;
event(attrs, argv[i], seq + i, modemask,
t1 + i, p1 + i);
}
}
return 0;
}
/*
* an output tools that accesses the ZIO device
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
int main(int argc, char **argv)
{
glob_t glob_buf;
struct zio_control ctrl;
int fdc;
char *s;
int i, j, val, ch;
uint32_t *attrs;
/* glob to find the device; use the first */
glob("/dev/fd-*-1-0-ctrl", 0, NULL, &glob_buf);
glob("/dev/zio/fd-*-1-0-ctrl", GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-1-0-ctrl", GLOB_APPEND, NULL, &glob_buf);
if (glob_buf.gl_pathc != 1) {
fprintf(stderr, "%s: found %i devices, need 1 only\n",
argv[0], glob_buf.gl_pathc);
exit(1);
}
s = glob_buf.gl_pathv[0];
if (getenv("CHAN")) {
/* Hack: change the channel */
ch = atoi(getenv("CHAN"));
if (ch)
s[strlen(s)-strlen("1-0-ctrl")] = '0' + ch;
}
fdc = open(s, O_WRONLY);
if (fdc < 0) {
fprintf(stderr, "%s: %s: %s\n", argv[0], s, strerror(errno));
exit(1);
}
memset(&ctrl, 0, sizeof(ctrl));
attrs = ctrl.attr_channel.ext_val;
for (i = 1; i < argc; i++) {
j = i - 1 + FD_ATTR_DEV__LAST;
if (sscanf(argv[i], "+%i", &val) == 1) {
val += time(NULL);
} else if (sscanf(argv[i], "%i", &val) != 1) {
fprintf(stderr, "%s: not a number \"%s\"\n", argv[0],
argv[i]);
exit(1);
}
attrs[j] = val;
}
/* we need to fill the nsample field of the control */
ctrl.attr_trigger.std_val[1] = 1;
ctrl.nsamples = 1;
ctrl.ssize = 4;
ctrl.nbits = 32;
write(fdc, &ctrl, sizeof(ctrl));
exit(0);
}
/*
* an input tool that measures performance
* (almost a copy of fd-raw-input, even if code repetition is BAD)
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
/*
* Lazily, we ignore the "seconds" part, and assume we run at 5Hz minimum
* so each picosecond count fits in 32 bits (0.4s)
*/
struct fd_perf {
/* sequence is 16-bits, do the same here */
uint16_t first, prev; /* sequence numbers: -1 == "not in a burst" */
struct timeval tv;
uint nev;
uint64_t pico_tot, micro_tot;
int64_t pico_prev, pico_min, pico_max, pico_avg;
uint32_t micro_prev, micro_min, micro_max, micro_avg;
int lost;
};
static void perf_clean(struct fd_perf *p)
{
p->pico_tot = p->micro_tot = 0;
p->pico_min = p->micro_min = ~0;
p->pico_max = p->micro_max = 0;
p->nev = p->lost = 0;
}
static void perf_one(struct fd_perf *p, uint32_t *a /* attrs */)
{
int64_t pico, micro, diff;
gettimeofday(&p->tv, NULL);
pico = a[FD_ATTR_TDC_COARSE] * 8000LL
+ (a[FD_ATTR_TDC_FRAC] << 12) / 8000;
micro = p->tv.tv_usec;
if (!p->nev) {
p->first = a[FD_ATTR_TDC_SEQ];
goto set_prev;
}
p->lost += (int16_t)(a[FD_ATTR_TDC_SEQ] - p->prev - 1);
/* count hardware-reported pico */
diff = pico - p->pico_prev;
if (0) {
printf("%lli = %f - %f\n", diff,
pico/1000000.0, p->pico_prev/1000000.0);
}
if (diff < 0)
diff += 1000LL * 1000 * 1000 * 1000;
if (diff < p->pico_min)
p->pico_min = diff;
if (diff > p->pico_max)
p->pico_max = diff;
p->pico_tot += diff;
/* count software-reported micro */
diff = micro - p->micro_prev;
if (diff < 0)
diff += 1000LL * 1000;
if (diff < p->micro_min)
p->micro_min = diff;
if (diff > p->micro_max)
p->micro_max = diff;
p->micro_tot += diff;
set_prev:
p->nev++;
p->prev = a[FD_ATTR_TDC_SEQ];
p->micro_prev = micro;
p->pico_prev = pico;
}
static void perf_report_clean(struct fd_perf *p)
{
if (p->prev < 0 || !p->nev)
return;
p->pico_avg = p->pico_tot / (p->nev - 1);
p->micro_avg = p->micro_tot / (p->nev - 1);
printf("%i pulses (%i lost)\n", p->nev, p->lost);
printf(" hw: %llips (%fkHz) -- min %lli max %lli delta %lli\n",
p->pico_avg, 1000.0 * 1000 * 1000 / p->pico_avg,
p->pico_min, p->pico_max, p->pico_max - p->pico_min);
printf(" sw: %ius (%fkHz) -- min %i max %i delta %i\n",
p->micro_avg, 1000.0 / p->micro_avg,
p->micro_min, p->micro_max, p->micro_max - p->micro_min);
printf("\n");
perf_clean(p);
}
#define MAXFD 16
struct zio_control ctrl;
int main(int argc, char **argv)
{
glob_t glob_buf;
int fd[MAXFD], seq[MAXFD];
int i, j, maxfd = 0;
fd_set allset, curset;
struct timeval tout;
struct fd_perf perf = {0,};
int floatmode = 0;
uint32_t *attrs;
int step = 0;
if (getenv("PERF_STEP"))
step = atoi(getenv("PERF_STEP"));
if (argc > 1 && !strcmp(argv[1], "-f")) {
floatmode = 1;
argv[1] = argv[0];
argv++, argc--;
}
if (argc < 2) {
/* rebuild argv using globbing */
glob_buf.gl_offs = 1;
/* "????" spits a trigraph warning: use "*" instead (bah!) */
glob("/dev/fd-*-0-0-ctrl", GLOB_DOOFFS, NULL, &glob_buf);
glob("/dev/zio/fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob("/dev/zio/zio-fd-*-0-0-ctrl",
GLOB_DOOFFS | GLOB_APPEND, NULL, &glob_buf);
glob_buf.gl_pathv[0] = argv[0];
argv = glob_buf.gl_pathv;
argc = glob_buf.gl_pathc + glob_buf.gl_offs;
}
if (argc == 1) {
fprintf(stderr, "%s: no arguments and no glob results\n",
argv[0]);
exit(1);
};
if (argc > 2) {
fprintf(stderr, "%s: too many devices, using only \"%s\"\n",
argv[0], argv[1]);
argc = 2;
/* So the loops below are unchanged from fd-raw-input */
};
FD_ZERO(&allset);
for (i = 1; i < 2; i++) {
fd[i] = open(argv[i], O_RDONLY);
if (fd[i] < 0) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1],
strerror(errno));
exit(1);
}
if (fd[i] > maxfd)
maxfd = fd[i];
FD_SET(fd[i], &allset);
seq[i] = -1;
}
/* Ok, now wait for each of them to spit a timestamp */
setlinebuf(stdout);
perf_clean(&perf);
while (1) {
curset = allset;
tout.tv_sec = 0;
tout.tv_usec = 300*1000; /* After 300ms the burst is over */
switch(select(maxfd + 1, &curset, NULL, NULL, &tout)) {
case -1:
if (errno == EINTR)
continue;
fprintf(stderr, "%s: select: %s\n", argv[0],
strerror(errno));
exit(1);
case 0:
perf_report_clean(&perf);
continue;
}
for (i = 1; i < argc; i++) {
if (!FD_ISSET(fd[i], &curset))
continue;
/* Ok, it's there: read and decode */
j = read(fd[i], &ctrl, sizeof(ctrl));
if (j != sizeof(ctrl)) {
fprintf(stderr, "%s: read(): got %i not %i\n",
argv[0], j, sizeof(ctrl));
exit(1);
}
attrs = ctrl.attr_channel.ext_val;
perf_one(&perf, attrs);
}
if (step && perf.nev) {
static time_t t;
/* don't make an extra system call, use perf.tv */
if (perf.nev == 1)
t = perf.tv.tv_sec;
else
if (perf.tv.tv_sec - t >= step)
perf_report_clean(&perf);
}
}
return 0;
}
/*
* a tool to set the fdelay time through sysfs
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
#include "fdelay-raw.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
struct time_word {
uint32_t val;
char *name;
};
struct time_word words[] = {
{0, "coarse"},
{0, "utc-l"},
{0, "utc-h"}, /* This must be last, as this forces hardware access */
};
int main(int argc, char **argv)
{
char *sysnames[10];
char path[80];
int i, err;
if (argc < 2 || argc > 3) {
fprintf(stderr, "%s: Use \"%s <sec> [<nsec>]\"\n",
argv[0], argv[0]);
exit(1);
}
i = fdelay_get_sysnames(sysnames);
if (!i) {
fprintf(stderr, "%s: no fine-delay devices\n", argv[0]);
exit(1);
}
if (i > 1) {
fprintf(stderr, "%s: several fine-delay devices, using %s\n",
argv[0], sysnames[0]);
}
words[0].val = 0;
words[1].val = atoi(argv[1]); /* FIXME: error check */
words[2].val = 0;
if (argc == 3)
words[0].val = atoi(argv[2]) / 8; /* FIXME: error check */
for (i = 0, err = 0; i < ARRAY_SIZE(words); i++) {
sprintf(path, "%s/%s", sysnames[0], words[i].name);
if (fdelay_sysfs_set(path, &words[i].val) != 0)
err++;
}
if (err) {
fprintf(stderr, "%s: got %i errors writing %i attributes\n",
argv[0], err, ARRAY_SIZE(words));
}
return 0;
}
/* Simple demo that acts on the time of the first board */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
struct fdelay_board *b;
int i, get = 0, host = 0, wr_on = 0, wr_off = 0;
struct fdelay_time t;
int dev = 0;
/* Parse, and kill "-i <devindex>" */
if (argc > 2 && !strcmp(argv[1], "-i")) {
dev = strtol(argv[2], NULL, 0);
argv[2] = argv[0];
argc -= 2;
}
if (argc != 2) {
fprintf(stderr,
"%s: Use \"%s [-i <devindex> \"get\"|\"host\"|\"local\"|\"wr\"|"
"<float-value>\"\n", argv[0], argv[0]);
exit(1);
}
/* Crappy parser */
if (!strcmp(argv[1], "get"))
get = 1;
else if (!strcmp(argv[1], "host"))
host = 1;
else if (!strcmp(argv[1], "wr"))
wr_on = 1;
else if (!strcmp(argv[1], "local"))
wr_off = 1;
else {
double nano;
long long sec;
memset(&t, 0, sizeof(t));
i = sscanf(argv[1], "%lli%lf\n", &sec, &nano);
if (i < 1) {
fprintf(stderr, "%s: Not a number \"%s\"\n",
argv[0], argv[1]);
exit(1);
}
t.utc = sec;
t.coarse = nano * 1000 * 1000 * 1000 / 8;
}
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
if (i != 1)
fprintf(stderr, "%s: found %i boards\n", argv[0], i);
b = fdelay_open(dev, -1);
if (!b) {
fprintf(stderr, "%s: fdelay_open(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i != 1)
fprintf(stderr, "%s: using board %d\n", argv[0], dev);
if (get) {
if (fdelay_get_time(b, &t) < 0) {
fprintf(stderr, "%s: fdelay_get_time(): %s\n", argv[0],
strerror(errno));
exit(1);
}
printf("%lli.%09li\n", (long long)t.utc, (long)t.coarse * 8);
fdelay_close(b);
fdelay_exit();
return 0;
}
if (host) {
if (fdelay_set_host_time(b) < 0) {
fprintf(stderr, "%s: fdelay_set_host_time(): %s\n",
argv[0], strerror(errno));
exit(1);
}
fdelay_close(b);
fdelay_exit();
return 0;
}
if (wr_on) {
printf("Locking the card to WR: ");
if (fdelay_wr_mode(b, 1) < 0) {
fprintf(stderr, "%s: fdelay_wr_mode(): %s\n",
argv[0], strerror(errno));
exit(1);
}
while (fdelay_check_wr_mode(b) != 0) {
printf(".");
sleep(1);
}
printf(" locked!\n");
fdelay_close(b);
fdelay_exit();
return 0;
}
if (wr_off) {
if (fdelay_wr_mode(b, 0) < 0) {
fprintf(stderr, "%s: fdelay_wr_mode(): %s\n",
argv[0], strerror(errno));
exit(1);
}
fdelay_close(b);
fdelay_exit();
return 0;
}
if (fdelay_set_time(b, &t) < 0) {
fprintf(stderr, "%s: fdelay_set_host_time(): %s\n",
argv[0], strerror(errno));
exit(1);
}
fdelay_close(b);
fdelay_exit();
return 0;
}
/* Simple demo that reads samples using the fread call */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
struct fdelay_board *b;
int i, j,npulses;
struct fdelay_time *t;
if (argc != 2) {
fprintf(stderr, "%s: Use \"%s <nsamples>\n", argv[0], argv[0]);
exit(1);
}
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
if (i != 1) {
fprintf(stderr, "%s: found %i boards, using first one\n",
argv[0], i);
}
b = fdelay_open(0, -1);
if (!b) {
fprintf(stderr, "%s: fdelay_open(): %s\n", argv[0],
strerror(errno));
exit(1);
}
npulses = atoi(argv[1]);
t = calloc(npulses, sizeof(*t));
if (!t) {
fprintf(stderr, "%s: calloc(): %s\n", argv[0],
strerror(errno));
exit(1);
}
fprintf(stderr, "%s: reading %i pulses using fread...",
argv[0], npulses);
i = fdelay_fread(b, t, npulses);
fprintf(stderr, " got %i of them\n", i);
for (j = 0; j < i; j++) {
printf("seq %5i: time %lli.%09li + %04x\n",
t[j].seq_id, (long long)t[j].utc,
(long)t[j].coarse * 8, t[j].frac);
}
if (i < 0) {
fprintf(stderr, "%s: fdelay_read: %s\n",
argv[0], strerror(errno));
exit(1);
}
fdelay_close(b);
fdelay_exit();
return 0;
}
/* Silly thing that lists installed fine-delay boards */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define FDELAY_INTERNAL /* hack... */
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
int i, j;
struct __fdelay_board *b;
struct fdelay_board *ub;
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
printf("%s: found %i boards\n", argv[0], i);
for (j = 0; j < i; j++) {
ub = fdelay_open(j, -1);
b = (typeof(b))ub;
printf(" dev_id %04x, %s, %s\n", b->dev_id, b->devbase,
b->sysbase);
}
fdelay_exit();
return 0;
}
/* Silly thing that lists installed fine-delay boards */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define FDELAY_INTERNAL /* hack... */
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
int i;
struct __fdelay_board *b;
struct fdelay_board *ub;
int lun;
char *endptr;
if (argc != 2)
goto usage;
lun = strtol(argv[1], &endptr, 0);
if (*endptr != 0)
goto usage;
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
printf("%s: found %i boards\n", argv[0], i);
ub = fdelay_open_by_lun(lun);
if (ub == NULL) {
fprintf(stderr, "could not open lun %d\n", lun);
exit(1);
}
b = (typeof(b))ub;
printf("lun:%d dev_id %04x, %s, %s\n", lun, b->dev_id, b->devbase,
b->sysbase);
fdelay_exit();
return 0;
usage:
printf("usage: %s lun\n", argv[0]);
return -1;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include "fdelay-lib.h"
static void help(int argc, char *argv[])
{
fprintf(stderr, "%s: Use \"%s [options]\n", argv[0], argv[0]);
fprintf(stderr, "\t Options are: \n");
fprintf(stderr,
"\t -d device : specify device index of hex busid (default: first card available)\n");
fprintf(stderr,
"\t -m mode : the mode: disable, pulse or delay (mandatory)\n");
fprintf(stderr,
"\t -o channel : the output channel, 1..4 (mandatory) \n");
fprintf(stderr,
"\t -a time : specify trigger absolute time (default: none)\n");
fprintf(stderr,
"\t -s time : specify trigger relative time (default: 1s in pulse generator mode and 0.5 us in delay mode).\n");
fprintf(stderr,
"\t -w time : specify output pulse width (default: 200 ns). \n");
fprintf(stderr, "\t -g time : specify output pulse spacing. \n");
fprintf(stderr,
"\t -t : wait for trigger before exiting (default: on) \n");
fprintf(stderr,
"\t -q count : number of pulses to generate (default: 1)\n");
fprintf(stderr,
"\t -c : generate infinite number of pulses (default: off)\n");
fprintf(stderr, "\t -p : generate PPS\n");
fprintf(stderr, "\t -1 : generate 10 MHz\n");
fprintf(stderr,
"Time format is a sum of times expressed in (full, milli, micro, nano, pico)seconds, for example:\n");
fprintf(stderr,
"1s+20u-100n is 1 sec, 19.9 us. Fractional numbers are NOT allowed.\n\n");
}
static struct fdelay_time ts_add(struct fdelay_time a, struct fdelay_time b)
{
a.frac += b.frac;
if (a.frac >= 4096) {
a.frac -= 4096;
a.coarse++;
}
a.coarse += b.coarse;
if (a.coarse >= 125000000) {
a.coarse -= 125000000;
a.utc++;
}
a.utc += b.utc;
return a;
}
static void parse_time(char *s, struct fdelay_time *t)
{
int64_t time_ps = 0;
int64_t extra_seconds = 0;
int64_t sign = 1;
int64_t term = 0;
int64_t scale = 1;
const int64_t one_second = 1000000000000LL;
char c, *buf = s;
while ((c = *buf++) != 0) {
switch (c) {
case '+':
if (scale == one_second)
extra_seconds += sign * term;
else
time_ps += sign * term * scale;
term = 0;
sign = 1;
break;
case '-':
if (scale == one_second)
extra_seconds += sign * term;
else
time_ps += sign * term * scale;
term = 0;
sign = -1;
break;
case 's':
scale = one_second;
break;
case 'm':
scale = 1000000000LL;
break;
case 'u':
scale = 1000000LL;
break;
case 'n':
scale = 1000LL;
break;
case 'p':
scale = 1LL;
break;
default:
if (isdigit(c)) {
term *= 10LL;
term += (int64_t) (c - '0');
break;
} else {
fprintf(stderr,
"Error while parsing time string '%s'\n",
s);
exit(-1);
}
}
}
if (scale == one_second)
extra_seconds += sign * term;
else
time_ps += sign * term * scale;
while (time_ps < 0) {
time_ps += one_second;
extra_seconds--;
}
fdelay_pico_to_time((uint64_t *) & time_ps, t);
t->utc += extra_seconds;
// printf("dbg: raw %lld, %lld, converted: %lld s %d ns %d ps\n", extra_seconds,time_ps, t->utc, t->coarse * 8, t->frac * 8000 / 4096);
}
void dump_ts(char *title, struct fdelay_time t)
{
printf("%s: secs %lld coarse %d frac %d\n", title, (long long)t.utc,
t.coarse, t.frac);
}
int main(int argc, char **argv)
{
struct fdelay_time t_start, t_delta, t_width;
int mode = -1;
int channel = -1;
int count = 1;
int wait_trigger = 0;
int opt;
int relative = 1;
int devid = 0;
int do_pps = 0, do_10m = 0;
uint64_t default_width = 250000;
fdelay_pico_to_time(&default_width, &t_width);
while ((opt = getopt(argc, argv, "p1hctd:m:o:a:s:w:g:q:")) != -1) {
switch (opt) {
case 'h':
help(argc, argv);
break;
case 'c':
count = -1;
break;
case 'q':
count = atoi(optarg);
break;
case 't':
wait_trigger = 1;
break;
case 'g':
parse_time(optarg, &t_delta);
break;
case 'w':
parse_time(optarg, &t_width);
break;
case 's':
parse_time(optarg, &t_start);
relative = 1;
break;
case 'a':
parse_time(optarg, &t_start);
relative = 0;
break;
case 'o':
channel = atoi(optarg);
if (channel < 1 || channel > 4) {
fprintf(stderr, "Invalid output channel.\n");
exit(1);
}
break;
case 'm':
if (!strcmp(optarg, "pulse"))
mode = FD_OUT_MODE_PULSE;
else if (!strcmp(optarg, "delay"))
mode = FD_OUT_MODE_DELAY;
else if (!strcmp(optarg, "disable"))
mode = FD_OUT_MODE_DISABLED;
else {
fprintf(stderr, "Invalid output mode.\n");
exit(1);
}
break;
case 'd':
sscanf(optarg, "%i", &devid);
break;
case 'p':
do_pps = 1;
break;
case '1':
do_10m = 1;
break;
}
}
struct fdelay_board *b;
struct fdelay_pulse p;
/* init before going on parsing */
int i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
b = fdelay_open(devid, -1);
if (!b)
b = fdelay_open(-1, devid);
if (!b) {
fprintf(stderr, "%s: fdelay_open(0x%x): %s\n", argv[0], devid,
strerror(errno));
exit(1);
}
if ((mode < 0 || channel < 0) && !do_pps && !do_10m) {
fprintf(stderr,
"You must specify the mode and the channel to generate pulses\n");
exit(1);
}
if (mode == FD_OUT_MODE_PULSE && relative) {
fdelay_get_time(b, &p.start);
p.start = ts_add(p.start, t_start);
} else {
p.start = t_start;
}
p.end = ts_add(p.start, t_width);
p.loop = t_delta;
p.rep = count;
p.mode = mode;
if (do_pps || do_10m) {
uint64_t width = do_pps ? 1000000 : 48000;
uint64_t delta = do_pps ? 1000000000000ULL : 100000ULL;
fdelay_pico_to_time(&width, &t_width);
fdelay_get_time(b, &p.start);
p.start.utc += 2;
p.start.coarse = 0;
p.start.frac = 0;
p.end = ts_add(p.start, t_width);
fdelay_pico_to_time(&delta, &p.loop);
p.rep = -1;
p.mode = FD_OUT_MODE_PULSE;
}
/* And finally work */
if (fdelay_config_pulse(b, channel - 1, &p) < 0) {
fprintf(stderr, "%s: fdelay_config_pulse(): %s\n",
argv[0], strerror(errno));
exit(1);
}
while (wait_trigger) {
usleep(10 * 1000);
i = fdelay_has_triggered(b, channel - 1);
if (i < 0) {
fprintf(stderr, "%s: waiting for trigger: %s\n",
argv[0], strerror(errno));
exit(1);
}
wait_trigger = !i;
}
fdelay_close(b);
fdelay_exit();
return 0;
}
/* Simple demo that acts on the time of the first board */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "fdelay-lib.h"
static int exiterr(int argc, char **argv)
{
fprintf(stderr, "%s: Use \"%s [<dev>] <mode> <ch> <rep> "
"<t1> <t2> <t3>\"\n", argv[0], argv[0]);
fprintf(stderr, "\t <dev> is index ([0..]) or hex busid\n");
fprintf(stderr, "\t <mode> is \"disable\",\"pulse\",\"delay\"\n");
fprintf(stderr, "\t <t> is <utc>.<us>[+<ps>]\"\n");
fprintf(stderr, "\t Note that <t2> and <t3> are relative to <t1>\n");
fprintf(stderr, "\t (if <utc> uses a leading + it's added to now)\n");
exit(1);
}
static int parse_time(struct fdelay_board *b, char *s, struct fdelay_time *t)
{
unsigned long u, m = 0, p = 0;
char smicro[32];
int i, relative = 0;
/*
* Hairy: if we scan "%ld%lf", the 0.009999 will become 9998 micro.
* Thus, scan as integer and string, so we can count leading zeros
*/
if (s[0] == '+') {
relative = 1;
s++;
}
if (sscanf(s, "%ld.%ld+%ld", &u, &m, &p) < 1) {
return -1;
}
if (m) { /* micro is not zero, check how long it is and scale*/
sscanf(s, "%ld.%[0-9]", &u, smicro);
i = strlen(smicro);
if (i > 6)
return -1;
while (i < 6) {
m *= 10;
i++;
}
}
t->utc = 0;
if (relative)
if (fdelay_get_time(b, t))
return -1;
t->utc += u;
t->coarse = m * 1000 / 8 + p / 8000;
t->frac = ((p % 8000) << 12) / 8000;
return 0;
}
int main(int argc, char **argv)
{
struct fdelay_board *b;
int i, devid, channel, needwait = 0;
struct fdelay_pulse p;
char *rest;
if (argc < 7)
exiterr(argc, argv);
/* Optional argv[1] is "-w" */
if (!strcmp(argv[1], "-w")) {
needwait++;
argv[1] = argv[0];
argv++;
argc--;
}
/* Next optional argv[1] is a number */
rest = strdup(argv[1]);
if (sscanf(argv[1], "%x%s", &devid, rest) != 1) {
devid = 0;
} else {
argv[1] = argv[0];
argv++;
argc--;
}
free(rest);
if (argc < 7) /* again: we ate some arguments */
exiterr(argc, argv);
/* Crappy parser */
if (!strcmp(argv[1], "disable"))
p.mode = FD_OUT_MODE_DISABLED;
else if (!strcmp(argv[1], "pulse"))
p.mode = FD_OUT_MODE_PULSE;
else if (!strcmp(argv[1], "delay"))
p.mode = FD_OUT_MODE_DELAY;
else {
fprintf(stderr, "%s: \"%s\": invalid\n",
argv[0], argv[1]);
exiterr(argc, argv);
}
rest = strdup(argv[2]);
if (sscanf(argv[2], "%i%s", &channel, rest) != 1) {
fprintf(stderr, "%s: channel \"%s\": not a number\n",
argv[0], argv[2]);
exiterr(argc, argv);
}
free(rest);
rest = strdup(argv[3]);
if (sscanf(argv[3], "%i%s", &p.rep, rest) != 1) {
fprintf(stderr, "%s: rep \"%s\": not a number\n",
argv[0], argv[2]);
exiterr(argc, argv);
}
free(rest);
/* init before going on parsing */
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
b = fdelay_open(devid, -1);
if (!b)
b = fdelay_open(-1, devid);
if (!b) {
fprintf(stderr, "%s: fdelay_open(0x%x): %s\n", argv[0], devid,
strerror(errno));
exit(1);
}
/* now we can ask current time: continue parsing */
if (parse_time(b, argv[4], &p.start)) {
fprintf(stderr, "%s: can't parse \"%s\"\n", argv[0], argv[4]);
exiterr(argc, argv);
}
if (parse_time(b, argv[5], &p.end)) {
fprintf(stderr, "%s: can't parse \"%s\"\n", argv[0], argv[5]);
exiterr(argc, argv);
}
if (parse_time(b, argv[6], &p.loop)) {
fprintf(stderr, "%s: can't parse \"%s\"\n", argv[0], argv[6]);
exiterr(argc, argv);
}
/* end is specified as relative but used as absolute */
p.end.frac += p.start.frac;
if (p.end.frac > 4096) {
p.end.frac -= 4096;
p.end.coarse++;
}
p.end.coarse += p.start.coarse;
if (p.end.coarse > 125 * 1000 * 1000) {
p.end.coarse -= 125 * 1000 * 1000;
p.end.utc++;
}
p.end.utc += p.start.utc;
/* And finally work */
if (fdelay_config_pulse(b, channel, &p) < 0) {
fprintf(stderr, "%s: fdelay_config_pulse(): %s\n",
argv[0], strerror(errno));
exit(1);
}
while (needwait) {
usleep(10 * 1000);
i = fdelay_has_triggered(b, channel);
if (i < 0) {
fprintf(stderr, "%s: waiting for trigger: %s\n",
argv[0], strerror(errno));
exit(1);
}
needwait = !i;
}
fdelay_close(b);
fdelay_exit();
return 0;
}
#include <stdio.h>
#include <glob.h>
#include <errno.h>
/* return an array of sysfs pathnames, array is preallocated. Returns count */
static inline int fdelay_get_sysnames(char *result[])
{
glob_t glob_buf = {0,};
int i;
glob("/sys/bus/zio/devices/fd-*", 0, NULL, &glob_buf);
glob("/sys/bus/zio/devices/zio-fd-*", GLOB_APPEND , NULL, &glob_buf);
for (i = 0; i < glob_buf.gl_pathc; i++)
result[i] = strdup(glob_buf.gl_pathv[i]);
globfree(&glob_buf);
return i;
}
static inline int fdelay_sysfs_get(char *path, uint32_t *resp)
{
FILE *f = fopen(path, "r");
if (!f)
return -1;
if (fscanf(f, "%i", resp) != 1) {
fclose(f);
errno = EINVAL;
return -1;
}
fclose(f);
return 0;
}
static inline int fdelay_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;
}
/* Simple demo that reads samples using the read call */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
struct fdelay_board *b;
int i, j,npulses;
struct fdelay_time *t;
if (argc != 2) {
fprintf(stderr, "%s: Use \"%s <nsamples>\n", argv[0], argv[0]);
exit(1);
}
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
if (i != 1) {
fprintf(stderr, "%s: found %i boards, using first one\n",
argv[0], i);
}
b = fdelay_open(0, -1);
if (!b) {
fprintf(stderr, "%s: fdelay_open(): %s\n", argv[0],
strerror(errno));
exit(1);
}
npulses = atoi(argv[1]);
t = calloc(npulses, sizeof(*t));
if (!t) {
fprintf(stderr, "%s: calloc(): %s\n", argv[0],
strerror(errno));
exit(1);
}
/* Read twice: first blocking then non-blocking */
fprintf(stderr, "%s: reading %i pulses in blocking mode...",
argv[0], npulses);
i = fdelay_read(b, t, npulses, 0);
fprintf(stderr, " got %i of them\n", i);
for (j = 0; j < i; j++) {
printf("seq %5i: time %lli.%09li + %04x\n",
t[j].seq_id, (long long)t[j].utc,
(long)t[j].coarse * 8, t[j].frac);
}
if (i < 0) {
fprintf(stderr, "%s: fdelay_read: %s\n",
argv[0], strerror(errno));
exit(1);
}
fprintf(stderr, "%s: reading %i pulses in non-blocking mode...",
argv[0], npulses);
i = fdelay_read(b, t, npulses, O_NONBLOCK);
fprintf(stderr, " got %i of them\n", i);
for (j = 0; j < i; j++) {
printf("seq %5i: time %lli.%09li + %04x\n",
t[j].seq_id, (long long)t[j].utc,
(long)t[j].coarse * 8, t[j].frac);
}
fdelay_close(b);
fdelay_exit();
return 0;
}
/* Simple demo that acts on the termination of the first board */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "fdelay-lib.h"
int main(int argc, char **argv)
{
struct fdelay_board *b;
int i, hwval, newval;
int dev = 0;
if (argc < 2) {
fprintf(stderr, "%s: Use %s <dev> 1|0\n", argv[0], argv[0]);
exit(1);
}
newval = -1;
if (argc > 2) {
dev = strtol(argv[1], NULL, 0);
if (!strcmp(argv[2], "0"))
newval = 0;
else if (!strcmp(argv[2], "1"))
newval = 1;
else {
fprintf(stderr, "%s: arg \"%s\" is not 0 nor 1\n",
argv[0], argv[2]);
exit(1);
}
}
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
if (i == 0) {
fprintf(stderr, "%s: no boards found\n", argv[0]);
exit(1);
}
if (i != 1) {
fprintf(stderr, "%s: found %i boards\n",
argv[0], i);
}
b = fdelay_open(dev, -1);
if (!b) {
fprintf(stderr, "%s: fdelay_open(): %s\n", argv[0],
strerror(errno));
exit(1);
}
fprintf(stderr, "%s: using board %d\n", argv[0], dev);
hwval = fdelay_get_config_tdc(b);
switch(newval) {
case 1:
hwval |= FD_TDCF_TERM_50;
break;
case 0:
hwval &= ~FD_TDCF_TERM_50;
break;
}
fdelay_set_config_tdc(b, hwval);
hwval = fdelay_get_config_tdc(b);
printf("%s: termination is %d %s\n", argv[0], hwval,
hwval & FD_TDCF_TERM_50 ? "on" : "off");
fdelay_close(b);
fdelay_exit();
return 0;
}
/*
* a simple output tool to make a burst on a parallel port
*
* Copyright (C) 2012 CERN (www.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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
/* Returns the numer of microsecond timer ticks (Tomasz Wlostowski) */
static int64_t get_tics()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_sec * 1000 * 1000 + tv.tv_usec;
}
/* Microsecond-accurate delay-to */
static void delay_to(int64_t until)
{
while (get_tics() < until)
;
}
int main(int argc, char **argv)
{
int fd, addr, count, usec;
int64_t tics;
if (argc != 4) {
fprintf(stderr,
"%s: Use \"%s <hexaddr> <count> <period-usec>\"\n",
argv[0], argv[0]);
exit(1);
}
if (sscanf(argv[1], "%x", &addr) != 1) {
fprintf(stderr, "%s: wrong hex \"%s\"\n", argv[0], argv[1]);
exit(1);
}
if (sscanf(argv[2], "%i", &count) != 1) {
fprintf(stderr, "%s: wrong count \"%s\"\n", argv[0], argv[2]);
exit(1);
}
if (sscanf(argv[3], "%i", &usec) != 1) {
fprintf(stderr, "%s: wrong period \"%s\"\n", argv[0], argv[3]);
exit(1);
}
fprintf(stderr, "%s: using port 0x%x, %i pulses, period %i us\n",
argv[0], addr, count, usec);
fd = open("/dev/port", O_RDWR);
if (fd < 0) {
fprintf(stderr, "%s: /dev/port: %s\n", argv[0],
strerror(errno));
exit(1);
}
tics = get_tics();
do {
char b[]={0x00, 0xff};
lseek(fd, addr, SEEK_SET);
write(fd, b + 1, 1);
lseek(fd, addr, SEEK_SET);
write(fd, b + 0, 1);
if (count > 1) {
tics += usec;
delay_to(tics);
}
} while (--count);
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