Commit 6932e996 authored by Alessandro Rubini's avatar Alessandro Rubini

lib: completed output API and wrote sample prog

parent 0a5250ae
......@@ -14,6 +14,7 @@ DEMOSRC += fdelay-board-time.c
DEMOSRC += fdelay-term.c
DEMOSRC += fdelay-read.c
DEMOSRC += fdelay-fread.c
DEMOSRC += fdelay-pulse.c
DEMOS := $(DEMOSRC:.c=)
......
......@@ -45,8 +45,72 @@ void fdelay_time_to_pico(struct fdelay_time *time, uint64_t *pico)
*pico = p;
}
extern int fdelay_config_pulse(struct fdelay_board *b,
int channel, struct fdelay_pulse *pulse);
static int __fdelay_get_ch_fd(struct __fdelay_board *b,
int channel, int *fdc, int *fdd)
{
int ch14 = channel + 1;
char fname[128];
if (channel < 0 || channel > 3) {
errno = -EINVAL;
return -1;
}
if (b->fdc[ch14] <= 0) {
sprintf(fname, "%s-%i-0-ctrl", b->devbase, ch14);
b->fdc[ch14] = open(fname, O_WRONLY | O_NONBLOCK);
if (b->fdc[ch14] < 0)
return -1;
}
if (b->fdd[ch14] <= 0) {
sprintf(fname, "%s-%i-0-data", b->devbase, ch14);
b->fdd[ch14] = open(fname, O_WRONLY | O_NONBLOCK);
if (b->fdd[ch14] < 0)
return -1;
}
*fdc = b->fdc[ch14];
*fdd = b->fdd[ch14];
return 0;
}
extern int fdelay_config_pulse(struct fdelay_board *userb,
int channel, struct fdelay_pulse *pulse)
{
__define_board(b, userb);
struct zio_control ctrl = {0,};
uint32_t *a;
int fdc, fdd;
if (__fdelay_get_ch_fd(b, channel, &fdc, &fdd) < 0)
return -1; /* errno already set */
a = ctrl.attr_channel.ext_val;
a[FD_ATTR_OUT_MODE] = pulse->mode;
a[FD_ATTR_OUT_REP] = pulse->rep;
a[FD_ATTR_OUT_START_H] = pulse->start.utc >> 32;
a[FD_ATTR_OUT_START_L] = pulse->start.utc;
a[FD_ATTR_OUT_START_COARSE] = pulse->start.coarse;
a[FD_ATTR_OUT_START_FINE] = pulse->start.frac;
a[FD_ATTR_OUT_END_H] = pulse->end.utc >> 32;
a[FD_ATTR_OUT_END_L] = pulse->end.utc;
a[FD_ATTR_OUT_END_COARSE] = pulse->end.coarse;
a[FD_ATTR_OUT_END_FINE] = pulse->end.frac;
a[FD_ATTR_OUT_DELTA_L] = pulse->loop.utc; /* only 0..f */
a[FD_ATTR_OUT_DELTA_COARSE] = pulse->loop.coarse; /* only 0..f */
a[FD_ATTR_OUT_DELTA_FINE] = pulse->loop.frac; /* only 0..f */
/* 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));
write(fdd, "1234", 4); /* we need to write data to push it out */
return 0;
}
/* The "pulse_ps" function relies on the previous one */
int fdelay_config_pulse_ps(struct fdelay_board *b,
......
/* Simple demo that acts on the time of the first board */
#include <stdio.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;
double d = 0.0;
int relative = 0;
if (sscanf(s, "+%ld%lf+%ld", &u, &d, &p) > 0) {
relative = 1;
} else if (sscanf(s, "%ld%lf+%ld", &u, &d, &p) < 1) {
return -1;
}
m = d * 1000 * 1000; /* turn float to micro */
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;
struct fdelay_pulse p;
char *rest;
if (argc < 7)
exiterr(argc, argv);
/* 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);
/* 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_cofig_pulse(): %s\n",
argv[0], strerror(errno));
exit(1);
}
fdelay_close(b);
fdelay_exit();
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