mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
comedi: started implementation
This commit is contained in:
parent
e3d6dfc8cd
commit
79d5257408
2 changed files with 192 additions and 6 deletions
|
@ -34,9 +34,21 @@
|
|||
#include <villas/node.h>
|
||||
#include <villas/list.h>
|
||||
|
||||
struct comedi_direction {
|
||||
double rate;
|
||||
|
||||
bool enabled;
|
||||
int subdevice;
|
||||
|
||||
unsigned *chanlist;
|
||||
size_t chanlist_len;
|
||||
};
|
||||
|
||||
struct comedi {
|
||||
char *device;
|
||||
|
||||
struct comedi_direction in, out;
|
||||
|
||||
comedi_t *it;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,153 @@
|
|||
#include <villas/utils.h>
|
||||
#include <villas/io_format.h>
|
||||
|
||||
static int comedi_parse_direction(struct comedi_direction *d, json_t *cfg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
json_t *json_chans;
|
||||
json_error_t err;
|
||||
|
||||
d->subdevice = -1;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s: o, s: F }",
|
||||
"subdevice", &d->subdevice,
|
||||
"channels", &json_chans,
|
||||
"rate", &d->rate
|
||||
);
|
||||
if (ret)
|
||||
jerror(&err, "Failed to parse configuration");
|
||||
|
||||
if (!json_is_array(json_chans))
|
||||
return -1;
|
||||
|
||||
size_t i;
|
||||
json_t *json_chan;
|
||||
|
||||
json_array_foreach(json_chans, i, json_chan) {
|
||||
if (!json_is_integer(json_chan))
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int comedi_start_in(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
struct comedi_direction *d = &c->in;
|
||||
|
||||
if (d->subdevice >= 0) {
|
||||
|
||||
}
|
||||
else {
|
||||
d->subdevice = comedi_find_subdevice_by_type(c->it, COMEDI_SUBD_AI, 0);
|
||||
if (d->subdevice < 0)
|
||||
error("Cannot find analog input device for node '%s'", node_name(n));
|
||||
}
|
||||
|
||||
/* Check if subdevice is usable */
|
||||
ret = comedi_get_subdevice_type(c->it, d->subdevice);
|
||||
if (ret != COMEDI_SUBD_AI)
|
||||
error("Input subdevice of node '%s' is not an analog input", node_name(n));
|
||||
|
||||
ret = comedi_get_subdevice_flags(c->it, d->subdevice);
|
||||
if (ret )
|
||||
|
||||
ret = comedi_lock(c->it, d->subdevice);
|
||||
if (ret)
|
||||
error("Failed to lock subdevice %d for node '%s'", d->subdevice, node_name(n));
|
||||
|
||||
#if 0
|
||||
comedi_cmd cmd = {
|
||||
.subdev = d->subdevice,
|
||||
.flags = CMDF_READ,
|
||||
.start_src = TRIG_INT,
|
||||
.start_arg = 0,
|
||||
.scan_begin_src = TRIG_TIMER,
|
||||
.scan_begin_arg = 1e9 / c->in.rate,
|
||||
.convert_src = TRIG_NOW,
|
||||
.convert_arg = 0,
|
||||
.scan_end_src = TRIG_COUNT,
|
||||
.scan_end_arg = c->in.chanlist_len,
|
||||
.stop_src = TRIG_NONE,
|
||||
.stop_arg = 0,
|
||||
.chanlist = c->in.chanlist,
|
||||
.chanlist_len = c->in.chanlist_len,
|
||||
};
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int comedi_start_out(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
struct comedi_direction *d = &c->out;
|
||||
|
||||
ret = comedi_get_subdevice_type(c->it, d->subdevice);
|
||||
if (ret != COMEDI_SUBD_AO)
|
||||
error("Output subdevice of node '%s' is not an analog output", node_name(n));
|
||||
|
||||
ret = comedi_get_subdevice_flags(c->it, d->subdevice);
|
||||
if (ret )
|
||||
|
||||
ret = comedi_lock(c->it, d->subdevice);
|
||||
if (ret)
|
||||
error("Failed to lock subdevice %d for node '%s'", d->subdevice, node_name(n));
|
||||
|
||||
#if 0
|
||||
comedi_cmd cmd = {
|
||||
.subdev = c->out.subdevice,
|
||||
.flags = CMDF_WRITE,
|
||||
.start_src = TRIG_INT,
|
||||
.start_arg = 0,
|
||||
.scan_begin_src = TRIG_TIMER,
|
||||
.scan_begin_arg = 1e9 / c->out.rate,
|
||||
.convert_src = TRIG_NOW,
|
||||
.convert_arg = 0,
|
||||
.scan_end_src = TRIG_COUNT,
|
||||
.scan_end_arg = c->out.chanlist_len,
|
||||
.stop_src = TRIG_NONE,
|
||||
.stop_arg = 0,
|
||||
.chanlist = c->out.chanlist,
|
||||
.chanlist_len = c->out.chanlist_len,
|
||||
};
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int comedi_stop_in(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
struct comedi_direction *d = &c->in;
|
||||
|
||||
ret = comedi_unlock(c->it, d->subdevice);
|
||||
if (ret)
|
||||
error("Failed to lock subdevice %d for node '%s'", d->subdevice, node_name(n));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int comedi_stop_out(struct node *n)
|
||||
{
|
||||
int ret;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
struct comedi_direction *d = &c->out;
|
||||
|
||||
ret = comedi_unlock(c->it, d->subdevice);
|
||||
if (ret)
|
||||
error("Failed to lock subdevice %d for node '%s'", d->subdevice, node_name(n));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int comedi_parse(struct node *n, json_t *cfg)
|
||||
{
|
||||
int ret;
|
||||
|
@ -34,14 +181,30 @@ int comedi_parse(struct node *n, json_t *cfg)
|
|||
|
||||
const char *device;
|
||||
|
||||
json_t *json_in = NULL;
|
||||
json_t *json_out = NULL;
|
||||
json_error_t err;
|
||||
|
||||
ret = json_unpack_ex(cfg, &err, 0, "{ s: s }",
|
||||
"device", &device
|
||||
"device", &device,
|
||||
"in", &json_in,
|
||||
"out", &json_out
|
||||
);
|
||||
if (ret)
|
||||
jerror(&err, "Failed to parse configuration of node %s", node_name(n));
|
||||
|
||||
if (json_in) {
|
||||
ret = comedi_parse_direction(&c->in, json_in);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (json_out) {
|
||||
ret = comedi_parse_direction(&c->out, json_out);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->device = strdup(device);
|
||||
|
||||
return 0;
|
||||
|
@ -53,7 +216,10 @@ char * comedi_print(struct node *n)
|
|||
|
||||
char *buf = NULL;
|
||||
|
||||
strcatf(&buf, "device=%s", c->device);
|
||||
const char *board = comedi_get_board_name(c->it);
|
||||
const char *driver = comedi_get_driver_name(c->it);
|
||||
|
||||
strcatf(&buf, "board=%s, driver=%s, device=%s", board, driver, c->device);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -68,6 +234,9 @@ int comedi_start(struct node *n)
|
|||
error("Failed to open device: %s", err);
|
||||
}
|
||||
|
||||
comedi_start_in(n);
|
||||
comedi_start_out(n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -76,6 +245,9 @@ int comedi_stop(struct node *n)
|
|||
int ret;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
|
||||
comedi_stop_in(n);
|
||||
comedi_stop_out(n);
|
||||
|
||||
ret = comedi_close(c->it);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -85,23 +257,23 @@ int comedi_stop(struct node *n)
|
|||
|
||||
int comedi_read(struct node *n, struct sample *smps[], unsigned cnt)
|
||||
{
|
||||
//struct comedi *c = (struct comedi *) n->_vd;
|
||||
// struct comedi *c = (struct comedi *) n->_vd;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int comedi_write(struct node *n, struct sample *smps[], unsigned cnt)
|
||||
{
|
||||
//struct comedi *c = (struct comedi *) n->_vd;
|
||||
// struct comedi *c = (struct comedi *) n->_vd;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int comedi_fd(struct node *n)
|
||||
{
|
||||
//struct comedi *c = (struct comedi *) n->_vd;
|
||||
struct comedi *c = (struct comedi *) n->_vd;
|
||||
|
||||
return -1;
|
||||
return comedi_fileno(c->it);
|
||||
}
|
||||
|
||||
static struct plugin p = {
|
||||
|
@ -117,6 +289,8 @@ static struct plugin p = {
|
|||
.stop = comedi_stop,
|
||||
.read = comedi_read,
|
||||
.write = comedi_write,
|
||||
// .create = comedi_create,
|
||||
// .destroy = comedi_destroy,
|
||||
.fd = comedi_fd
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue