1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

comedi: implement ADC and DAC directions, only DAC tested

The write / DAC direction has been tested with two output signals, see
etc/comedi.conf for reference. For now, the buffer size may not be
(considerably) smaller than 32kB, Comedi stops working for unknown
reasons. To compensate for the latency (always approx. one buffer size)
if only small sample rates are required, configure the path for
upsampling (sample-and-hold via rate parameter) at the same rate as
the out direction of the comedi node.
This commit is contained in:
Daniel Krebs 2018-06-15 15:42:46 +02:00
parent 79d5257408
commit fe302f9649
4 changed files with 948 additions and 123 deletions

84
etc/comedi.conf Normal file
View file

@ -0,0 +1,84 @@
/** Example configuration file for VILLASnode/comedi.
*
* The syntax of this file is similar to JSON.
* A detailed description of the format can be found here:
* http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files
*
* @author Daniel Krebs <github@daniel-krebs.net>
* @copyright 2018, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
nodes = {
pcie6259 = {
type = "comedi",
device = "/dev/comedi0",
in = {
subdevice = 0,
rate = 1000,
signals = (
# note: order in this array defines order in villas sample
{ channel = 0, range = 0, aref = 0, name = "temperature_int" },
{ channel = 1, range = 0, aref = 0, name = "loopback_ao0" },
{ channel = 2, range = 0, aref = 0, name = "loopback_ao1" },
{ channel = 3, range = 0, aref = 0, name = "bnc_ext" }
)
},
out = {
subdevice = 1,
# Note: buffer size and rate shouldn't be changed at the moment
# output sample rate
rate = 10000,
# comedi write buffer in kilobytes
bufsize = 32,
signals = (
# note: order in this array corresponds to order in villas sample
{ name = "ao0", channel = 0, range = 0, aref = 0 },
{ name = "ao1", channel = 1, range = 0, aref = 0 }
)
}
},
remote = {
type = "socket",
layer = "udp"
format = "protobuf",
local = "*:12000"
remote = "134.130.169.32:12000"
},
sine1 = {
type = "signal",
signal = "sine",
values = 1,
frequency = 50,
rate = 10000,
},
sine2 = {
type = "signal",
signal = "sine",
values = 1,
frequency = 100,
rate = 10000,
}
}
paths = (
{ in = ("sine1.data[0]", "sine2.data[0]"), out = "pcie6259", rate = 10000, mask = () }
)

View file

@ -55,30 +55,31 @@ extern "C" {
* To be or-ed with the debug level
*/
enum log_facilities {
LOG_POOL = (1L << 8),
LOG_QUEUE = (1L << 9),
LOG_POOL = (1L << 8),
LOG_QUEUE = (1L << 9),
LOG_CONFIG = (1L << 10),
LOG_HOOK = (1L << 11),
LOG_PATH = (1L << 12),
LOG_NODE = (1L << 13),
LOG_MEM = (1L << 14),
LOG_WEB = (1L << 15),
LOG_API = (1L << 16),
LOG_LOG = (1L << 17),
LOG_VFIO = (1L << 18),
LOG_PCI = (1L << 19),
LOG_XIL = (1L << 20),
LOG_TC = (1L << 21),
LOG_IF = (1L << 22),
LOG_ADVIO = (1L << 23),
LOG_HOOK = (1L << 11),
LOG_PATH = (1L << 12),
LOG_NODE = (1L << 13),
LOG_MEM = (1L << 14),
LOG_WEB = (1L << 15),
LOG_API = (1L << 16),
LOG_LOG = (1L << 17),
LOG_VFIO = (1L << 18),
LOG_PCI = (1L << 19),
LOG_XIL = (1L << 20),
LOG_TC = (1L << 21),
LOG_IF = (1L << 22),
LOG_ADVIO = (1L << 23),
/* Node-types */
LOG_SOCKET = (1L << 24),
LOG_FILE = (1L << 25),
LOG_FPGA = (1L << 26),
LOG_NGSI = (1L << 27),
LOG_FILE = (1L << 25),
LOG_FPGA = (1L << 26),
LOG_NGSI = (1L << 27),
LOG_WEBSOCKET = (1L << 28),
LOG_OPAL = (1L << 30),
LOG_OPAL = (1L << 30),
LOG_COMEDI = (1L << 31),
/* Classes */
LOG_NODES = LOG_NODE | LOG_SOCKET | LOG_FILE | LOG_FPGA | LOG_NGSI | LOG_WEBSOCKET | LOG_OPAL,

View file

@ -33,15 +33,33 @@
#include <villas/node.h>
#include <villas/list.h>
#include <villas/timing.h>
// whether to use read() or mmap() kernel interface
#define COMEDI_USE_READ (1)
//#define COMEDI_USE_READ (0)
struct comedi_chanspec {
unsigned int maxdata;
comedi_range *range;
};
struct comedi_direction {
double rate;
int subdevice; ///< Comedi subdevice
int buffer_size; ///< Comedi's kernel buffer size
int sample_size; ///< Size of a single measurement sample
int sample_rate_hz; ///< Sample rate in Hz
bool present; ///< Config present
bool enabled; ///< Card is started successfully
bool running; ///< Card is actively transfering samples
struct timespec started; ///< Timestamp when sampling started
int counter; ///< Number of villas samples transfered
struct comedi_chanspec *chanspecs; ///< Range and maxdata config of channels
unsigned *chanlist; ///< Channel list in comedi's packed format
size_t chanlist_len; ///< Number of channels for this direction
bool enabled;
int subdevice;
unsigned *chanlist;
size_t chanlist_len;
char* buffer;
char* bufptr;
};
struct comedi {
@ -49,7 +67,18 @@ struct comedi {
struct comedi_direction in, out;
comedi_t *it;
comedi_t *dev;
#if COMEDI_USE_READ
char* buf;
char* bufptr;
#else
char *map;
size_t bufpos;
size_t front;
size_t back;
#endif
};
/** @see node_type::print */

File diff suppressed because it is too large Load diff