From 769ee42b73d89a1225f71b4fa5f23fc861f5b9ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20F=C3=A4lt?= <faldt.mattias@gmail.com>
Date: Mon, 28 Aug 2017 20:10:39 +0200
Subject: [PATCH] Fixed buffer and comedi

---
 Examples/testLED.jl                  |  35 ++++++----
 src/BeagleBone/BeagleBone.jl         |   2 +-
 src/BeagleBone/precompile.jl         |   2 +
 src/Computer/10V.jl                  |  39 +++++++++++
 src/Computer/AbstractDevice.jl       |  53 ++++++++++++++
 src/Computer/BeagleBoneStream.jl     | 100 ++++++++++++++++++---------
 src/Computer/ComediStream.jl         |  56 +++++++++++++++
 src/Computer/Computer.jl             |  30 ++++----
 src/Computer/Device.jl               |  50 --------------
 src/Computer/LabStream.jl            |   9 +++
 src/Computer/SysLED.jl               |  11 +--
 src/Computer/comedi/Makefile         |  15 ++++
 src/Computer/comedi/comedi.c         |  57 +++++++++++++++
 src/Computer/comedi/comedi_bridge.o  | Bin 0 -> 4800 bytes
 src/Computer/comedi/comedi_bridge.so | Bin 0 -> 13064 bytes
 src/LabConnection.jl                 |   3 +-
 util/copyfoldertobb.sh               |   2 +-
 17 files changed, 340 insertions(+), 124 deletions(-)
 create mode 100644 src/Computer/10V.jl
 create mode 100644 src/Computer/AbstractDevice.jl
 create mode 100644 src/Computer/ComediStream.jl
 delete mode 100644 src/Computer/Device.jl
 create mode 100644 src/Computer/LabStream.jl
 create mode 100644 src/Computer/comedi/Makefile
 create mode 100644 src/Computer/comedi/comedi.c
 create mode 100644 src/Computer/comedi/comedi_bridge.o
 create mode 100755 src/Computer/comedi/comedi_bridge.so

diff --git a/Examples/testLED.jl b/Examples/testLED.jl
index ef13179..6a9740a 100644
--- a/Examples/testLED.jl
+++ b/Examples/testLED.jl
@@ -6,30 +6,39 @@
 using LabConnection.Computer
 
 stream = BeagleBoneStream(ip"192.168.7.2")
+led1 = SysLED(1)
 led2 = SysLED(2)
 led3 = SysLED(3)
+led4 = SysLED(4)
 
 # Send info to steam about which inputs/otputs to initialize
 # and adds a ref in motor and led to stream
-init_devices!(stream, led2, led3)
+init_devices!(stream, led1, led2, led3, led4)
 ledon = true
-for i = 1:10
-    set!(led2, ledon)
-    set!(led3, !ledon)
-    send!(stream) #Sends all the outputs to the stream in one atomic call
+for i = 1:50
+    set!(led1, ledon)
+    set!(led2, !ledon)
+    set!(led3, ledon)
+    set!(led4, !ledon)
+    send(stream) #Sends all the outputs to the stream in one atomic call
     #read(stream) #Sends request to read, reads all inputs
-    sleep(1)
+    sleep(0.1)
     ledon = !ledon
 end
-for i = 1:10
-    send!(led2, ledon)
-    sleep(0.5)
-    send!(led3, !ledon)
-    #read(stream) #Sends request to read, reads all inputs
-    sleep(0.5)
+for i = 1:40
+    send(led1, ledon)
+    sleep(0.03)
+    send(led2, ledon)
+    sleep(0.03)
+    send(led3, ledon)
+    sleep(0.03)
+    send(led4, ledon)
+    sleep(0.03)
     ledon = !ledon
 end
+set!(led1, false)
 set!(led2, false)
 set!(led3, false)
-send!(stream)
+set!(led4, false)
+send(stream)
 close(stream) #Tells BeagleBone to stop listening and close outputs
diff --git a/src/BeagleBone/BeagleBone.jl b/src/BeagleBone/BeagleBone.jl
index 0799a05..e7d2e6e 100644
--- a/src/BeagleBone/BeagleBone.jl
+++ b/src/BeagleBone/BeagleBone.jl
@@ -1,4 +1,4 @@
-# Devices should define a type `T` with methods:
+# AbstractDevice should define a type `T` with methods:
 # write!(::T, identifier, val)
 # read(::T, identifier)
 
diff --git a/src/BeagleBone/precompile.jl b/src/BeagleBone/precompile.jl
index eb9b76e..bf714ec 100644
--- a/src/BeagleBone/precompile.jl
+++ b/src/BeagleBone/precompile.jl
@@ -28,6 +28,8 @@ function precompile_bb()
     write!(gpio, Int32(1), ("value", "1"), debug)
     #read(gpio, ind, args, debug)
 
+#TODO write/read
+
     try getdev("nonexistent")       catch end
     try bbparse("Invalid input")    catch end
     try bbparse(("Invalid input"))  catch end
diff --git a/src/Computer/10V.jl b/src/Computer/10V.jl
new file mode 100644
index 0000000..3da2a8b
--- /dev/null
+++ b/src/Computer/10V.jl
@@ -0,0 +1,39 @@
+export AnalogInput10V
+
+mutable struct AnalogInput10V <: AbstractDevice
+    i::Int32
+    stream::LabStream
+    AnalogInput10V(i::Int32) = new(i)
+end
+mutable struct AnalogOutput10V <: AbstractDevice
+    i::Int32
+    stream::LabStream
+    AnalogOutput10V(i::Int32) = new(i)
+end
+AnalogInput10V(i::Int64) = AnalogInput10V(convert(Int32, i))
+AnalogOutput10V(i::Int64) = AnalogOutput10V(convert(Int32, i))
+
+initialize(::AnalogInput10V) = nothing
+initialize(::AnalogOutput10V) = nothing
+
+close(::AnalogInput10V) = nothing
+close(input::AnalogOutput10V) = ccall(:comedi_write_zero, comedipath, Void, (Int32, Int32, Int32), 0, 1, input.i)
+
+getwritecommand(stream::LabStream, input::AnalogIntput10V, val) = error("Can't write to device $input")
+getreadcommand(stream::LabStream, output::AnalogOutput10V, val) = error("Can't read from device $output")
+
+function getwritecommand(stream::BeagleBoneStream, input::AnalogOutput10V, val::Float64)
+    abs(val) < 10 || error("Volatage $val not in range [-10,10]")
+    return ("analogin10", input.i, val)
+end
+function getreadcommand(stream::BeagleBoneStream, input::AnalogInput10V)
+    return ("analogin10", input.i, val)
+end
+
+function getwritecommand(stream::ComediStream, input::AnalogOutput10V, val::Float64)
+    abs(val) < 10 || error("Volatage $val not in range [-10,10]")
+    return (0,1,input.i,val)
+end
+function getreadcommand(stream::ComediStream, input::AnalogInput10V)
+    return (0,0,input.i)
+end
diff --git a/src/Computer/AbstractDevice.jl b/src/Computer/AbstractDevice.jl
new file mode 100644
index 0000000..f4d65c3
--- /dev/null
+++ b/src/Computer/AbstractDevice.jl
@@ -0,0 +1,53 @@
+export initialize, getstream, setstream!, send, set!
+
+###### Defaults for AbstractDevice
+#What to do when connecting
+initialize(::AbstractDevice) = nothing
+#What to do when disconnecting
+close(::AbstractDevice) = nothing
+#Which stream is the AbstractDevice connected to
+getstream(dev::AbstractDevice) = dev.stream
+#Set the stream the AbstractDevice is connected to
+setstream!(dev::AbstractDevice, stream::LabStream) = dev.stream = stream
+
+
+function safe_getwritecommand(dev::AbstractDevice, val)
+    stream = try getstream(dev) catch
+        error("Device $dev not connected to a stream")
+    end
+    cmd = try getwritecommand(stream, dev, val) catch
+        error("Device $dev with output val $val not supported on stream $stream")
+    end
+    return cmd, stream
+end
+function safe_getreadcommand(dev::AbstractDevice)
+    stream = try getstream(dev) catch
+        error("Device $dev not connected to a stream")
+    end
+    cmd = try getreadcommand(stream, dev) catch
+        error("Device $dev not supported  to read from on stream $stream")
+    end
+    return cmd, stream
+end
+
+function send(dev::AbstractDevice, val)
+    cmd, stream = safe_getwritecommand(dev, val)
+    send(stream, cmd)
+    return
+end
+function read(dev::AbstractDevice)
+    cmd, stream = safe_getreadcommand(dev)
+    return read(stream, cmd)
+end
+
+function set!(dev::AbstractDevice, val)
+    cmd, stream = safe_getwritecommand(dev, val)
+    push!(stream.sendbuffer,cmd)
+    return
+end
+
+function get(dev::AbstractDevice, val)
+    cmd, stream = safe_getreadcommand(dev, val)
+    push!(stream.readbuffer,cmd)
+    return
+end
diff --git a/src/Computer/BeagleBoneStream.jl b/src/Computer/BeagleBoneStream.jl
index 557da8f..24bd09f 100644
--- a/src/Computer/BeagleBoneStream.jl
+++ b/src/Computer/BeagleBoneStream.jl
@@ -1,19 +1,21 @@
-export BeagleBoneStream, init_devices!, send!
+export BeagleBoneStream, init_devices!
 
 struct BeagleBoneStream <: LabStream
-    devices::Array{Device,1}
+    devices::Array{AbstractDevice,1}
+    sendbuffer::Array{Tuple,1}
+    readbuffer::Array{Tuple,1}
     stream::TCPSocket
 end
 
 function BeagleBoneStream(addr::IPAddr, port::Int64=2001)
     clientside = connect(addr, port)
-    BeagleBoneStream(Device[], clientside)
+    BeagleBoneStream(AbstractDevice[], Tuple[], Tuple[], clientside)
 end
 
 #For BeagleBoneStream we can directly serialize the data, other streams might want to send binary data
 serialize(bbstream::BeagleBoneStream, cmd) = serialize(bbstream.stream, cmd)
 
-function init_devices!(bbstream::BeagleBoneStream, devs::Device...)
+function init_devices!(bbstream::BeagleBoneStream, devs::AbstractDevice...)
     for dev in devs
         if dev ∉ bbstream.devices
             setstream!(dev, bbstream)
@@ -26,37 +28,69 @@ function init_devices!(bbstream::BeagleBoneStream, devs::Device...)
     return
 end
 
-function send!(stream::BeagleBoneStream)
-    cmds = Tuple[]
-    for dev in stream.devices
-        val = getsetvalue(dev)
-        cmd, devstream = safe_getwritecommand(dev, val)
-        devstream == stream || error("Device $dev is connected to other stream $devstream")
-        push!(cmds, cmd)
-    end
-    ncmds = Int32(length(cmds))
-    if ncmds > 0
-        allcmds = (true, ncmds, cmds...)
-        println("Sending command: $allcmds")
-        serialize(stream, allcmds)
-    end
+function send(bbstream::BeagleBoneStream)
+    ncmds = length(bbstream.sendbuffer)
+    serialize(bbstream.stream, (true, ncmds, bbstream.sendbuffer))
+    empty!(bbstream.sendbuffer)
     return
 end
-function read(stream::BeagleBoneStream)
-    cmds = Tuple[]
-    for dev in stream.devices
-        cmd, devstream = safe_getreadcommand(dev)
-        devstream == stream || error("Device $dev is connected to other stream $devstream")
-        push!(cmds, cmd)
-    end
-    ncmds = Int32(length(cmds))
-    if ncmds > 0
-        allcmds = (false, ncmds, cmds...)
-        println("Sending command: $allcmds")
-        serialize(stream, allcmds)
-        #TODO save values in dev
-        # update_read_vale!(dev, val)
-    end
+function read(comedistream::BeagleBoneStream)
+    ncmds = length(bbstream.readbuffer)
+    serialize(bbstream.stream, (false, ncmds, bbstream.sendbuffer))
+    #TODO wait for answer
+    vals = nothing
+    empty!(bbstream.sendbuffer)
+    return vals
+end
+# 
+# function send(stream::BeagleBoneStream)
+#     cmds = Tuple[]
+#     for dev in stream.devices
+#         val = getsetvalue(dev)
+#         cmd, devstream = safe_getwritecommand(dev, val)
+#         devstream == stream || error("Device $dev is connected to other stream $devstream")
+#         push!(cmds, cmd)
+#     end
+#     ncmds = Int32(length(cmds))
+#     if ncmds > 0
+#         allcmds = (true, ncmds, cmds...)
+#         println("Sending command: $allcmds")
+#         serialize(stream, allcmds)
+#     end
+#     return
+# end
+# function read(stream::BeagleBoneStream)
+#     cmds = Tuple[]
+#     for dev in stream.devices
+#         cmd, devstream = safe_getreadcommand(dev)
+#         devstream == stream || error("Device $dev is connected to other stream $devstream")
+#         push!(cmds, cmd)
+#     end
+#     ncmds = Int32(length(cmds))
+#     if ncmds > 0
+#         allcmds = (false, ncmds, cmds...)
+#         println("Sending command: $allcmds")
+#         serialize(stream, allcmds)
+#         #TODO save values in dev
+#         # update_read_vale!(dev, val)
+#     end
+#     return
+# end
+
+
+#Maybe rethink a bit to support IObox
+function send(bbstream::BeagleBoneStream, cmd)
+    allcmds = (true, Int32(1), cmd)
+    println("Sending single command: $allcmds")
+    serialize(stream, allcmds)
+    return
+end
+function read(bbstream::BeagleBoneStream, cmd)
+    cmd, stream = safe_getreadcommand(dev)
+    allcmds = (false, Int32(1), cmd)
+    println("Sending single command: $allcmds")
+    serialize(stream, allcmds)
+    #TODO get, wait for and return response
     return
 end
 
diff --git a/src/Computer/ComediStream.jl b/src/Computer/ComediStream.jl
new file mode 100644
index 0000000..a89fab3
--- /dev/null
+++ b/src/Computer/ComediStream.jl
@@ -0,0 +1,56 @@
+export ComediStream, init_devices!
+
+const comedipath = joinpath(@__DIR__,"comedi","comedi_bridge.so")
+const comediname = "/dev/comedi0"
+const SendTuple = Tuple{Int32,Int32,Int32,Float64}
+const ReadTuple = Tuple{Int32,Int32,Int32}
+
+struct ComediStream <: LabStream
+    devices::Array{AbstractDevice,1}
+    sendbuffer::Array{SendTuple,1}
+    readbuffer::Array{ReadTuple,1}
+end
+
+function ComediStream()
+    ccall((:comedi_start, comedipath),Int32,(Ptr{UInt8},), comediname)
+    ComediStream(AbstractDevice[], SendTuple[], ReadTuple[])
+end
+
+function init_devices!(stream::ComediStream, devs::AbstractDevice...)
+    for dev in devs
+        if dev ∉ comedistream.devices
+            setstream!(dev, comedistream)
+            push!(comedistream.devices, dev)
+            initialize(dev)
+        else
+            warn("Device $dev already added to the stream")
+        end
+    end
+    return
+end
+
+function send(comedistream::ComediStream, cmd::SendTuple)
+    ccall((:comedi_write, comedipath),Int32,(Int32,Int32,Int32,Float64), cmd[1], cmd[2], cmd[3], cmd[4])
+    return
+end
+function read(comedistream::ComediStream, cmd::ReadTuple)
+    ccall((:comedi_read, comedipath),Int32,(Int32,Int32,Int32), cmd[1], cmd[2], cmd[3])
+    return
+end
+
+function send(comedistream::ComediStream)
+    map(cmd -> send(comedistream, cmd), comedistream.sendbuffer)
+    empty!(comedistream.readbuffer)
+    return
+end
+function read(comedistream::ComediStream)
+    vals = map(cmd -> read(comedistream, cmd), comedistream.sendbuffer)
+    empty!(comedistream.readbuffer)
+    return vals
+end
+
+function close(stream::ComediStream)
+    foreach(close, stream.devices)
+    ccall((:comedi_stop, comedipath),Int32,(Int32,), 0)
+    return
+end
diff --git a/src/Computer/Computer.jl b/src/Computer/Computer.jl
index eeb58a6..c494e99 100644
--- a/src/Computer/Computer.jl
+++ b/src/Computer/Computer.jl
@@ -1,35 +1,35 @@
-abstract type LabStream end
-abstract type Device end
+abstract type AbstractDevice end
 
-include("Device.jl")
+include("LabStream.jl")
+include("AbstractDevice.jl")
 
 ##### General interface for LabStream
 ## A stream of type T <: LabStream should define the methods
 # serialize(::T, cmd)                   # Send data `cmd`
-# init_devices!(::T, devs::Device...)   # Initialize devices and connect them to stream
-# send!(::T)                            # Send set! commands for all devices to stream, using getwritecommand(stream::LabStream, dev::Device, getsetvalue(dev::Device))
-# read(::T)                             # Send read commands for all devices to stream, sing get(dev::Device)
-# init_devices!                         # Initialize all connected devises, using initialize(::Device)
-# close                                # Close connection, call close(::Device) on all connected devices
+# init_devices!(::T, devs::AbstractDevice...)   # Initialize devices and connect them to stream
+# send(::T)                            # Send set! commands for all devices to stream, using getwritecommand(stream::LabStream, dev::AbstractDevice, getsetvalue(dev::AbstractDevice))
+# read(::T)                             # Send read commands for all devices to stream, sing get(dev::AbstractDevice)
+# init_devices!                         # Initialize all connected devises, using initialize(::AbstractDevice)
+# close                                # Close connection, call close(::AbstractDevice) on all connected devices
 
 #Include the stream definitions
+include("ComediStream.jl")
 include("BeagleBoneStream.jl")
 
 
 ##### General interface for devices
-## A device to type T<:Device should define the methods
-# set!(dev::T, val)    # Remember val for next send!(::LabStream) command
-# getsetvalue(dev::T)  # Get the value that was saved to send
+## A device to type T<:AbstractDevice should define the methods
+# set!(dev::T, val)    # Remember val for next send(::LabStream) command
 # get(dev::T)          # Get val from last next read(::LabStream) command
 
 # getwritecommand(stream::LabStream, dev::T, val)   #Get canonlical representation of send command
 # getreadcommand(stream::LabStream, dev::T)         #Get canonlical representation of read command
 
 ## Default methods:
-# initialize(::Device) = nothing    #What to do when initializing
-# close(::Device) = nothing          #What to do when disconnecting
-# getstream(dev::Device) = dev.stream #Which stream is the Device connected to
-# setstream!(dev::Device, stream::LabStream) = dev.stream = stream #Set the stream the Device is connected to
+# initialize(::AbstractDevice) = nothing    #What to do when initializing
+# close(::AbstractDevice) = nothing          #What to do when disconnecting
+# getstream(dev::AbstractDevice) = dev.stream #Which stream is the Device connected to
+# setstream!(dev::AbstractDevice, stream::LabStream) = dev.stream = stream #Set the stream the Device is connected to
 ##### END General interface for devices
 
 #Include the device definitions
diff --git a/src/Computer/Device.jl b/src/Computer/Device.jl
deleted file mode 100644
index 96c299c..0000000
--- a/src/Computer/Device.jl
+++ /dev/null
@@ -1,50 +0,0 @@
-export initialize, getstream, setstream!, send!, set!, getsetvalue
-
-###### Defaults for Device
-#What to do when connecting
-initialize(::Device) = nothing
-#What to do when disconnecting
-close(::Device) = nothing
-#Which stream is the Device connected to
-getstream(dev::Device) = dev.stream
-#Set the stream the Device is connected to
-setstream!(dev::Device, stream::LabStream) = dev.stream = stream
-
-
-function safe_getwritecommand(dev::Device, val)
-    stream = try getstream(dev) catch
-        error("Device $dev not connected to a stream")
-    end
-    cmd = try getwritecommand(stream, dev, val) catch
-        error("Device $dev with output val $val not supported on stream $stream")
-    end
-    return cmd, stream
-end
-function safe_getreadcommand(dev::Device)
-    stream = try getstream(dev) catch
-        error("Device $dev not connected to a stream")
-    end
-    cmd = try getreadcommand(stream, dev) catch
-        error("Device $dev not supported  to read from on stream $stream")
-    end
-    return cmd, stream
-end
-
-#Maybe rethink a bit to support IObox
-function send!(dev::Device, val)
-    cmd, stream = safe_getwritecommand(dev, val)
-    #TODO This is not very general
-    allcmds = (true, Int32(1), cmd)
-    println("Sending single command: $allcmds")
-    serialize(stream, allcmds)
-    return
-end
-function read(dev::Device)
-    cmd, stream = safe_getreadcommand(dev)
-    allcmds = (false, Int32(1), cmd)
-    println("Sending single command: $allcmds")
-    serialize(stream, allcmds)
-
-    #TODO get, wait for and return response
-    return
-end
diff --git a/src/Computer/LabStream.jl b/src/Computer/LabStream.jl
new file mode 100644
index 0000000..3856de7
--- /dev/null
+++ b/src/Computer/LabStream.jl
@@ -0,0 +1,9 @@
+abstract type LabStream end
+
+function close(stream::LabStream)
+    for dev in stream.devices
+        close(dev)
+    end
+    close(stream.stream)
+    return
+end
diff --git a/src/Computer/SysLED.jl b/src/Computer/SysLED.jl
index 94a6962..2d0837a 100644
--- a/src/Computer/SysLED.jl
+++ b/src/Computer/SysLED.jl
@@ -1,21 +1,12 @@
 export SysLED
 
-mutable struct SysLED <: Device
+mutable struct SysLED <: AbstractDevice
     i::Int32
-    nextout::Bool
-    latestread::Bool
     stream::LabStream
     SysLED(i::Int32) = new(i, false, false)
 end
 SysLED(i::Int64) = SysLED(convert(Int32, i))
 
-#Save value to send later
-set!(led::SysLED, val::Bool) = led.nextout = val
-#Get the value from set! back for use
-getsetvalue(led::SysLED) = led.nextout
-#Get value that was read erlier
-get(led::SysLED) = led.latestread
-
 #No definition for IOBox since there are no LEDs
 #Stream specific methods
 function getwritecommand(stream::BeagleBoneStream, led::SysLED, val::Bool)
diff --git a/src/Computer/comedi/Makefile b/src/Computer/comedi/Makefile
new file mode 100644
index 0000000..2983d11
--- /dev/null
+++ b/src/Computer/comedi/Makefile
@@ -0,0 +1,15 @@
+CC=gcc 
+
+CFLAGS=-c -Wall -fPIC
+
+SOURCES=comedi_bridge.c 
+OBJECTS=$(SOURCES:.c=.o)
+
+.c.o:
+	$(CC) $(CFLAGS) $< -o $@ 
+
+lib: $(OBJECTS)
+	$(CC) -shared -fPIC -lcomedi -lm -o comedi_bridge.so $(OBJECTS)
+
+clean:
+	rm *.o *.so
diff --git a/src/Computer/comedi/comedi.c b/src/Computer/comedi/comedi.c
new file mode 100644
index 0000000..27cc729
--- /dev/null
+++ b/src/Computer/comedi/comedi.c
@@ -0,0 +1,57 @@
+/* This is a bridge between Julia and Comedi, written by Martin Karlsson
+ * and Jacob Mejvik at Dept. Automatic Control, Lund University.*/
+
+#include <stdio.h>      /* for printf() */
+#include <comedilib.h>
+
+
+int range = 0;
+int aref = AREF_GROUND;
+comedi_t *device;
+comedi_range * range_info;
+lsampl_t maxdata;
+
+int comedi_write(int comediNbr, int subdev, int chan, double physical_value) {
+	static int comedi_value;
+	static int retval;
+	range_info = comedi_get_range(device, subdev, chan, range);
+	maxdata = comedi_get_maxdata(device, subdev, chan);
+	comedi_value = comedi_from_phys(physical_value, range_info, maxdata);
+	retval = comedi_data_write(device, subdev, chan, range, aref, comedi_value);
+    return retval;
+}
+
+double comedi_read(int comediNbr, int subdev, int chan) {
+	static double physical_value;
+	lsampl_t comedi_value;
+	comedi_data_read(device, subdev, chan, range, aref, &comedi_value);
+	range_info = comedi_get_range(device, subdev, chan, range);
+	maxdata = comedi_get_maxdata(device, subdev, chan);
+	physical_value = comedi_to_phys(comedi_value, range_info, maxdata);
+	return physical_value;
+}
+
+// comedi_path example: "/dev/comedi0"
+int comedi_start(char* comedi_name) {
+	device = comedi_open(comedi_name);
+		if(device == NULL)
+	{
+		comedi_perror("comedi_open_error");
+		return -1;
+	}
+	comedi_set_global_oor_behavior(COMEDI_OOR_NUMBER);
+	return 0;
+}
+
+void comedi_write_zero(int comediNbr, int subdev, int chan) {
+	static double physical_value_zero = 0.0;
+	static lsampl_t comedi_value;
+	range_info = comedi_get_range(device, subdev, chan, range);
+	maxdata = comedi_get_maxdata(device, subdev, chan);
+	comedi_value = comedi_from_phys(physical_value_zero, range_info, maxdata);
+	comedi_data_write(device, subdev, chan, range, aref, comedi_value);
+}
+
+void comedi_stop(int comediNbr) {
+	comedi_close(device);
+}
diff --git a/src/Computer/comedi/comedi_bridge.o b/src/Computer/comedi/comedi_bridge.o
new file mode 100644
index 0000000000000000000000000000000000000000..91d8dd79812bcd5cc4888231b243e8f5ab44ab9e
GIT binary patch
literal 4800
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
U{Su(Uhk=115uyxEq8Y~k0M{|GQUCw|

literal 0
HcmV?d00001

diff --git a/src/Computer/comedi/comedi_bridge.so b/src/Computer/comedi/comedi_bridge.so
new file mode 100755
index 0000000000000000000000000000000000000000..0526f55afaf161f8fb3d8f6c7d73eaddfae02472
GIT binary patch
literal 13064
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
Dh&GI+

literal 0
HcmV?d00001

diff --git a/src/LabConnection.jl b/src/LabConnection.jl
index f231905..18cd878 100644
--- a/src/LabConnection.jl
+++ b/src/LabConnection.jl
@@ -1,3 +1,4 @@
+__precompile__()
 module LabConnection
 
     module BeagleBone
@@ -12,7 +13,7 @@ module LabConnection
     end
 
     module Computer
-        import Base: read, close, get, serialize
+        import Base: read, send, close, get, serialize
         println("Initializing Computer")
         include(joinpath("Computer","Computer.jl"))
     end
diff --git a/util/copyfoldertobb.sh b/util/copyfoldertobb.sh
index a38f4cc..1bf6138 100755
--- a/util/copyfoldertobb.sh
+++ b/util/copyfoldertobb.sh
@@ -8,7 +8,7 @@ printf "${BLUE}Updating project${NC}\n..."
 
 codeHost=gitlab.control.lth.se
 codeUser=labdev
-projects=(LabConnection)
+projects=LabConnection
 flag=false
 
 printf "${BLUE}Initializing Transferring files to BBB${NC}\n"
-- 
GitLab