From 682e609ebeb4e66e68f106850a5beec94ac48bf9 Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Fri, 1 Mar 2019 09:47:36 +0100
Subject: [PATCH] comedi implemented

---
 Makefile                                     |  20 ++--
 moberg.c                                     |   7 --
 moberg.h                                     |   2 +-
 moberg_config.c                              |   1 -
 moberg_device.c                              |  82 +------------
 {modules => plugins}/comedi/Makefile         |   0
 {modules => plugins}/comedi/comedi.c         | 117 +++++++++++++++++--
 {modules => plugins}/serial2002/Makefile     |   0
 {modules => plugins}/serial2002/serial2002.c |   0
 9 files changed, 116 insertions(+), 113 deletions(-)
 rename {modules => plugins}/comedi/Makefile (100%)
 rename {modules => plugins}/comedi/comedi.c (81%)
 rename {modules => plugins}/serial2002/Makefile (100%)
 rename {modules => plugins}/serial2002/serial2002.c (100%)

diff --git a/Makefile b/Makefile
index 1eab439..1b8a069 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,17 @@
 LIBRARIES=libmoberg.so
 CCFLAGS+=-Wall -Werror -I$(shell pwd) -g
 LDFLAGS+=-L$(shell pwd)/build/ -lmoberg
-MODULES:=$(wildcard modules/*)
+PLUGINS:=$(wildcard plugins/*)
 export CCFLAGS LDFLAGS
 LDFLAGS_parse_config=-ldl
 #-export-dynamic
 
-all: $(LIBRARIES:%=build/%) $(MODULES) 
-	echo $(MODULES)
+all: $(LIBRARIES:%=build/%) $(PLUGINS)
+	echo $(PLUGINS)
 	echo $(CCFLAGS)
 
-build/libmoberg.so:	moberg.c Makefile | build
-	$(CC) -o $@ $(CCFLAGS) -shared -fPIC -I. $< \
+build/libmoberg.so: Makefile | build
+	$(CC) -o $@ $(CCFLAGS) -shared -fPIC -I. \
 		$(filter %.o,$^) -lxdg-basedir -ldl
 
 build/lib build:
@@ -27,25 +27,21 @@ build/lib/%.o:	%.c Makefile | build/lib
 	$(CC) $(CCFLAGS) -c -fPIC -o $@ $<
 
 
-.PHONY: $(MODULES)
-$(MODULES): 
+.PHONY: $(PLUGINS)
+$(PLUGINS): 
 	$(MAKE) -C $@
 
 
 .PHONY: test
 test: all
 	$(MAKE) -C test test
-#	LD_LIBRARY_PATH=build \
-#		valgrind ./parse_config test/*/*.conf
-#	LD_LIBRARY_PATH=build HOME=$$(pwd)/test \
-#		valgrind -q --error-exitcode=1 test/test_c
-
 
 clean:
 	find build -type f -delete
 	rm -f *~
 	make -C test clean
 
+build/libmoberg.so: build/lib/moberg.o
 build/libmoberg.so: build/lib/moberg_config.o
 build/libmoberg.so: build/lib/moberg_device.o
 build/libmoberg.so: build/lib/moberg_parser.o
diff --git a/moberg.c b/moberg.c
index 32437cd..e302fce 100644
--- a/moberg.c
+++ b/moberg.c
@@ -100,9 +100,7 @@ static void parse_config_at(
           if (read(fd, buf, statbuf.st_size) == statbuf.st_size) {
             buf[statbuf.st_size] = 0;
           }
-          printf("Parsing... %s %d %d\n", pathname, dirfd, fd);
           struct moberg_config *config = moberg_parse(moberg, buf);
-          printf("-> %p\n", config);
           if (config) {
             if (! moberg->config) {
               moberg->config = config;
@@ -151,7 +149,6 @@ static int install_channel(struct moberg *moberg,
                            struct moberg_device* device,
                            struct moberg_channel *channel)
 {
-  fprintf(stderr, "CHAN %p %d %d\n", channel, channel->kind, index);
   if (channel) {
     struct moberg_channel *old = NULL;
     switch (channel->kind) {
@@ -294,9 +291,7 @@ int moberg_analog_in_open(struct moberg *moberg,
   struct moberg_channel *channel = NULL;
   channel_list_get(&moberg->analog_in, index, &channel);
   if (channel) {
-    printf("Call open\n");
     channel->open(channel);
-    channel->up(channel);
     *analog_in = channel->action.analog_in;
     return 1;
   }
@@ -310,9 +305,7 @@ int moberg_analog_in_close(struct moberg *moberg,
   struct moberg_channel *channel = NULL;
   channel_list_get(&moberg->analog_in, index, &channel);
   if (channel && channel->action.analog_in.context == analog_in.context) {
-    printf("Call close\n");
     channel->close(channel);
-    channel->down(channel);
   }
   return 1;
 }
diff --git a/moberg.h b/moberg.h
index 062892a..1ffa2c3 100644
--- a/moberg.h
+++ b/moberg.h
@@ -21,7 +21,7 @@ struct moberg_analog_in {
 
 struct moberg_analog_out {
   struct moberg_channel_analog_out *context;
-  int (*write)(struct moberg_channel_analog_in *, double value);
+  int (*write)(struct moberg_channel_analog_out *, double value);
 };
 
 struct moberg_digital_in {
diff --git a/moberg_config.c b/moberg_config.c
index 879b6e8..6349bde 100644
--- a/moberg_config.c
+++ b/moberg_config.c
@@ -83,7 +83,6 @@ int moberg_config_install_channels(struct moberg_config *config,
     if (moberg_device_in_use(device->device)) {
       previous = &device->next;
     } else {
-      fprintf(stderr, "FREE\n");
       moberg_device_free(device->device);
       free(device);
       *previous = next;
diff --git a/moberg_device.c b/moberg_device.c
index e4f339b..a85c71b 100644
--- a/moberg_device.c
+++ b/moberg_device.c
@@ -86,8 +86,7 @@ void moberg_device_free(struct moberg_device *device)
     free(channel);
     channel = next;
   }
-  int use = device->driver.down(device->device_context);
-  fprintf(stderr, "USE: %d\n", use);
+  device->driver.down(device->device_context);
   free(device);
 }
 
@@ -95,7 +94,6 @@ int moberg_device_in_use(struct moberg_device *device)
 {
   device->driver.up(device->device_context);
   int use = device->driver.down(device->device_context);
-  fprintf(stderr, "IN_USE: %d\n", use);
   return use > 1;
 }
 
@@ -123,81 +121,6 @@ err:
   return 0;
 }
 
-int moberg_device_add_analog_in(struct moberg_device* device,
-                                struct moberg_channel_analog_in *channel)
-{
-  int result = 0;
-  
-  if (device->range->kind == chan_ANALOGIN &&
-      device->range->min <= device->range->max) {
-    printf("Mapping %d\n", device->range->min);
-    result = add_channel(device, device->range->kind, device->range->min,
-                         (union channel) { .analog_in=channel });
-    device->range->min++;
-  }
-  return result;
-}
-                            
-int moberg_device_add_analog_out(struct moberg_device* device,
-                                 struct moberg_channel_analog_out *channel)
-{
-  int result = 0;
-  
-  if (device->range->kind == chan_ANALOGOUT &&
-      device->range->min <= device->range->max) {
-    printf("Mapping %d\n", device->range->min);
-    result = add_channel(device, device->range->kind, device->range->min,
-                         (union channel) { .analog_out=channel });
-    device->range->min++;
-  }
-  return result;
-}
-                            
-int moberg_device_add_digital_in(struct moberg_device* device,
-                                struct moberg_channel_digital_in *channel)
-{
-  int result = 0;
-  
-  if (device->range->kind == chan_DIGITALIN &&
-      device->range->min <= device->range->max) {
-    printf("Mapping %d\n", device->range->min);
-    result = add_channel(device, device->range->kind, device->range->min,
-                         (union channel) { .digital_in=channel });
-    device->range->min++;
-  }
-  return result;
-}
-                            
-int moberg_device_add_digital_out(struct moberg_device* device,
-                                 struct moberg_channel_digital_out *channel)
-{
-  int result = 0;
-  
-  if (device->range->kind == chan_DIGITALOUT &&
-      device->range->min <= device->range->max) {
-    printf("Mapping %d\n", device->range->min);
-    result = add_channel(device, device->range->kind, device->range->min,
-                         (union channel) { .digital_out=channel });
-    device->range->min++;
-  }
-  return result;
-}
-                            
-int moberg_device_add_encoder_in(struct moberg_device* device,
-                                 struct moberg_channel_encoder_in *channel)
-{
-  int result = 0;
-  
-  if (device->range->kind == chan_ENCODERIN &&
-      device->range->min <= device->range->max) {
-    printf("Mapping %d\n", device->range->min);
-    result = add_channel(device, device->range->kind, device->range->min,
-                         (union channel) { .encoder_in=channel });
-    device->range->min++;
-  }
-  return result;
-}
-
 static int map(struct moberg_device* device,
                struct moberg_channel *channel)
 {
@@ -205,7 +128,6 @@ static int map(struct moberg_device* device,
  
   if (device->range->kind == channel->kind &&
       device->range->min <= device->range->max) {
-    printf("XX Mapping %d\n", device->range->min);
     result = add_channel(device, device->range->kind, device->range->min,
                          (union channel) { .channel=channel });
     device->range->min++;
@@ -236,7 +158,6 @@ int moberg_device_parse_map(struct moberg_device* device,
   result = device->driver.parse_map(device->device_context, parser,
                                     kind, &map_channel);
   device->range = NULL;
-  printf("RRR %d %d\n", r.min, r.max);
   return result;
 }
 
@@ -244,7 +165,6 @@ int moberg_device_install_channels(struct moberg_device *device,
                                    struct moberg_channel_install *install)
 {
   
-  printf("INSTALL\n");
   struct channel_list *channel = device->channel_head;
   while (channel) {
     struct channel_list *next;
diff --git a/modules/comedi/Makefile b/plugins/comedi/Makefile
similarity index 100%
rename from modules/comedi/Makefile
rename to plugins/comedi/Makefile
diff --git a/modules/comedi/comedi.c b/plugins/comedi/comedi.c
similarity index 81%
rename from modules/comedi/comedi.c
rename to plugins/comedi/comedi.c
index 32853eb..8af55cf 100644
--- a/modules/comedi/comedi.c
+++ b/plugins/comedi/comedi.c
@@ -73,16 +73,91 @@ struct moberg_channel_encoder_in {
 static int analog_in_read(struct moberg_channel_analog_in *analog_in,
                           double *value)
 {
+  if (! value) { goto err; }
   struct channel_descriptor descriptor = analog_in->channel_context.descriptor;
   lsampl_t data;
   comedi_data_read(analog_in->channel_context.device->comedi.handle,
                    descriptor.subdevice,
                    descriptor.subchannel,
                    0, 0, &data);
-        
   *value = descriptor.min + data * descriptor.delta;
-  fprintf(stderr, "Data: %d %f\n", data, *value);
   return 1;
+err:
+  return 0;
+}
+
+static int analog_out_write(struct moberg_channel_analog_out *analog_out,
+                            double value)
+{
+  if (! value) { goto err; }
+  struct channel_descriptor descriptor = analog_out->channel_context.descriptor;
+  lsampl_t data;
+  if (value < descriptor.min) {
+    data = 0;
+  } else if (value > descriptor.max) {
+    data = descriptor.maxdata;
+  } else {
+    data = (value - descriptor.min) / descriptor.delta;
+  }
+  if (data < 0) {
+    data = 0;
+  } else if (data > descriptor.maxdata) {
+    data = descriptor.maxdata;
+  }
+  comedi_data_write(analog_out->channel_context.device->comedi.handle,
+                   descriptor.subdevice,
+                   descriptor.subchannel,
+                   0, 0, data);
+  return 1;
+err:
+  return 0;
+}
+
+static int digital_in_read(struct moberg_channel_digital_in *digital_in,
+                           int *value)
+{
+  if (! value) { goto err; }
+  struct channel_descriptor descriptor = digital_in->channel_context.descriptor;
+  lsampl_t data;
+  comedi_data_read(digital_in->channel_context.device->comedi.handle,
+                   descriptor.subdevice,
+                   descriptor.subchannel,
+                   0, 0, &data);
+  *value = data;
+  return 1;
+err:
+  return 0;
+}
+
+static int digital_out_write(struct moberg_channel_digital_out *digital_out,
+                             int value)
+{
+  if (! value) { goto err; }
+  struct channel_descriptor descriptor = digital_out->channel_context.descriptor;
+  lsampl_t data = value==0?0:1;
+  comedi_data_write(digital_out->channel_context.device->comedi.handle,
+                   descriptor.subdevice,
+                   descriptor.subchannel,
+                   0, 0, data);
+  return 1;
+err:
+  return 0;
+}
+
+static int encoder_in_read(struct moberg_channel_encoder_in *encoder_in,
+                           long *value)
+{
+  if (! value) { goto err; }
+  struct channel_descriptor descriptor = encoder_in->channel_context.descriptor;
+  lsampl_t data;
+  comedi_data_read(encoder_in->channel_context.device->comedi.handle,
+                   descriptor.subdevice,
+                   descriptor.subchannel,
+                   0, 0, &data);
+  *value = data - descriptor.maxdata / 2;
+  return 1;
+err:
+  return 0;
 }
 
 static struct moberg_device_context *new_context(struct moberg *moberg,
@@ -186,10 +261,6 @@ static int channel_open(struct moberg_channel *channel)
 {
   channel_up(channel);
   if (! device_open(channel->context->device)) { goto err; }
-  fprintf(stderr, "Open %s[%d][%d]\n",
-          channel->context->device->name, 
-          channel->context->descriptor.subdevice, 
-          channel->context->descriptor.subchannel);
   lsampl_t maxdata;
   comedi_range *range;
           
@@ -219,6 +290,30 @@ static int channel_open(struct moberg_channel *channel)
   channel->context->descriptor.min = range->min;
   channel->context->descriptor.max = range->max;
   channel->context->descriptor.delta = (range->max - range->min) / maxdata;
+  if (channel->kind == chan_DIGITALIN) {
+    comedi_dio_config(channel->context->device->comedi.handle,
+                      channel->context->descriptor.subdevice,
+                      channel->context->descriptor.subchannel,
+                      0);
+  } else if (channel->kind == chan_DIGITALOUT) {
+    comedi_dio_config(channel->context->device->comedi.handle,
+                      channel->context->descriptor.subdevice,
+                      channel->context->descriptor.subchannel,
+                      1);
+  }
+  if (channel->context->descriptor.route != -1) {
+    comedi_insn insn;
+    lsampl_t data[2];
+    memset(&insn, 0, sizeof(comedi_insn));
+    insn.insn = INSN_CONFIG;
+    insn.subdev = channel->context->descriptor.subdevice;
+    insn.chanspec = channel->context->descriptor.subchannel;
+    insn.data = data;
+    insn.n = sizeof(data) / sizeof(data[0]);
+    data[0] = INSN_CONFIG_SET_ROUTING;
+    data[1] = channel->context->descriptor.route;
+    comedi_do_insn(channel->context->device->comedi.handle, &insn);
+  }
   return 1;
 err:
   return 0;
@@ -360,7 +455,7 @@ static int parse_map(struct moberg_device_context *device,
                      enum moberg_channel_kind kind,
                      struct moberg_channel_map *map)
 {
-  token_t min, max, route={ .u.integer.value=0 };
+  token_t min, max, route={ .u.integer.value=-1 };
 
   if (! acceptsym(c, tok_LBRACE, NULL)) { goto err; }
   for (;;) {
@@ -419,7 +514,7 @@ static int parse_map(struct moberg_device_context *device,
                          kind,
                          (union moberg_channel_action) {
                            .analog_out.context=channel,
-                           .analog_out.write=NULL });
+                           .analog_out.write=analog_out_write });
             map->map(map->device, &channel->channel);
           }
         } break;
@@ -436,7 +531,7 @@ static int parse_map(struct moberg_device_context *device,
                          kind,
                          (union moberg_channel_action) {
                            .digital_in.context=channel,
-                           .digital_in.read=NULL });
+                           .digital_in.read=digital_in_read });
             map->map(map->device, &channel->channel);
           }
         } break;
@@ -453,7 +548,7 @@ static int parse_map(struct moberg_device_context *device,
                          kind,
                          (union moberg_channel_action) {
                            .digital_out.context=channel,
-                           .digital_out.write=NULL });
+                           .digital_out.write=digital_out_write });
             map->map(map->device, &channel->channel);
           }
         } break;
@@ -470,7 +565,7 @@ static int parse_map(struct moberg_device_context *device,
                          kind,
                          (union moberg_channel_action) {
                            .encoder_in.context=channel,
-                           .encoder_in.read=NULL });
+                           .encoder_in.read=encoder_in_read });
             map->map(map->device, &channel->channel);
           }
         } break;
diff --git a/modules/serial2002/Makefile b/plugins/serial2002/Makefile
similarity index 100%
rename from modules/serial2002/Makefile
rename to plugins/serial2002/Makefile
diff --git a/modules/serial2002/serial2002.c b/plugins/serial2002/serial2002.c
similarity index 100%
rename from modules/serial2002/serial2002.c
rename to plugins/serial2002/serial2002.c
-- 
GitLab