diff --git a/adaptors/julia/AnalogIn.jl b/adaptors/julia/AnalogIn.jl
new file mode 100644
index 0000000000000000000000000000000000000000..ac4d4a140885f3bbf98ad91611184ea5522ab1a3
--- /dev/null
+++ b/adaptors/julia/AnalogIn.jl
@@ -0,0 +1,38 @@
+mutable struct AnalogInChannel
+    context::Ptr{Nothing}
+    read::Ptr{Nothing}
+end
+
+mutable struct AnalogIn
+    moberg::Moberg
+    index::UInt32
+    channel::AnalogInChannel
+    AnalogIn(moberg::Moberg, index::Unsigned) = (
+        channel = AnalogInChannel(0,0);
+        checkOK(ccall((:moberg_analog_in_open, "libmoberg"),
+                       Status,
+                       (Moberg, Cint, Ref{AnalogInChannel}),
+                       moberg, index, channel));
+        self = new(moberg, index, channel);
+        finalizer(close, self);
+        self
+    )
+end
+
+function close(ain::AnalogIn)
+    # println("closing $(ain)")
+    checkOK(ccall((:moberg_analog_in_close, "libmoberg"),
+                  Status,
+                  (Moberg, Cint, AnalogInChannel),
+                  ain.moberg, ain.index, ain.channel))
+end
+
+function read(ain::AnalogIn)
+    result = Ref{Cdouble}(0.0)
+    checkOK(ccall(ain.channel.read,
+                  Status,
+                  (Ptr{Nothing}, Ptr{Cdouble}),
+                  ain.channel.context, result))
+    return result[]
+end
+
diff --git a/adaptors/julia/AnalogOut.jl b/adaptors/julia/AnalogOut.jl
new file mode 100644
index 0000000000000000000000000000000000000000..534960ff0f85f7ddbf6a0774e66f07ab07e58ffb
--- /dev/null
+++ b/adaptors/julia/AnalogOut.jl
@@ -0,0 +1,35 @@
+mutable struct AnalogOutChannel
+    context::Ptr{Nothing}
+    write::Ptr{Nothing}
+end
+
+mutable struct AnalogOut
+    moberg::Moberg
+    index::UInt32
+    channel::AnalogOutChannel
+    AnalogOut(moberg::Moberg, index::Unsigned) = (
+        channel = AnalogOutChannel(0,0);
+        checkOK(ccall((:moberg_analog_out_open, "libmoberg"),
+                       Status,
+                       (Moberg, Cint, Ref{AnalogOutChannel}),
+                       moberg, index, channel));
+        self = new(moberg, index, channel);
+        finalizer(close, self);
+        self
+    )
+end
+
+function close(aout::AnalogOut)
+    # println("closing $(aout)")
+    checkOK(ccall((:moberg_analog_out_close, "libmoberg"),
+                  Status,
+                  (Moberg, Cint, AnalogOutChannel),
+                  aout.moberg, aout.index, aout.channel))
+end;
+
+function write(aout::AnalogOut, value::Cdouble)
+    checkOK(ccall(aout.channel.write,
+                  Status,
+                  (Ptr{Nothing}, Cdouble),
+                  aout.channel.context, value))
+end
diff --git a/adaptors/julia/DigitalIn.jl b/adaptors/julia/DigitalIn.jl
new file mode 100644
index 0000000000000000000000000000000000000000..74c455d4968dff9c5e594a45db9318ee53c3149f
--- /dev/null
+++ b/adaptors/julia/DigitalIn.jl
@@ -0,0 +1,38 @@
+mutable struct DigitalInChannel
+    context::Ptr{Nothing}
+    read::Ptr{Nothing}
+end
+
+mutable struct DigitalIn
+    moberg::Moberg
+    index::UInt32
+    channel::DigitalInChannel
+    DigitalIn(moberg::Moberg, index::Unsigned) = (
+        channel = DigitalInChannel(0,0);
+        checkOK(ccall((:moberg_digital_in_open, "libmoberg"),
+                       Status,
+                       (Moberg, Cint, Ref{DigitalInChannel}),
+                       moberg, index, channel));
+        self = new(moberg, index, channel);
+        finalizer(close, self);
+        self
+    )
+end
+
+function close(din::DigitalIn)
+    # println("closing $(din)")
+    checkOK(ccall((:moberg_digital_in_close, "libmoberg"),
+                  Status,
+                  (Moberg, Cint, DigitalInChannel),
+                  din.moberg, din.index, din.channel))
+end
+
+function read(din::DigitalIn)
+    result = Ref{Cint}(0)
+    checkOK(ccall(din.channel.read,
+                  Status,
+                  (Ptr{Nothing}, Ptr{Cint}),
+                  din.channel.context, result))
+    return result[] != 0
+end
+
diff --git a/adaptors/julia/DigitalOut.jl b/adaptors/julia/DigitalOut.jl
new file mode 100644
index 0000000000000000000000000000000000000000..7dc18b7f939b894ef4514e59f6eacebbc3c2d978
--- /dev/null
+++ b/adaptors/julia/DigitalOut.jl
@@ -0,0 +1,35 @@
+mutable struct DigitalOutChannel
+    context::Ptr{Nothing}
+    write::Ptr{Nothing}
+end
+
+mutable struct DigitalOut
+    moberg::Moberg
+    index::UInt32
+    channel::DigitalOutChannel
+    DigitalOut(moberg::Moberg, index::Unsigned) = (
+        channel = DigitalOutChannel(0,0);
+        checkOK(ccall((:moberg_digital_out_open, "libmoberg"),
+                       Status,
+                       (Moberg, Cint, Ref{DigitalOutChannel}),
+                       moberg, index, channel));
+        self = new(moberg, index, channel);
+        finalizer(close, self);
+        self
+    )
+end
+
+function close(dout::DigitalOut)
+    # println("closing $(dout)")
+    checkOK(ccall((:moberg_digital_out_close, "libmoberg"),
+                  Status,
+                  (Moberg, Cint, DigitalOutChannel),
+                  dout.moberg, dout.index, dout.channel))
+end;
+
+function write(dout::DigitalOut, value::Bool)
+    checkOK(ccall(dout.channel.write,
+                  Status,
+                  (Ptr{Nothing}, Cint),
+                  dout.channel.context, value ? 1 : 0))
+end
diff --git a/adaptors/julia/EncoderIn.jl b/adaptors/julia/EncoderIn.jl
new file mode 100644
index 0000000000000000000000000000000000000000..b45046f5b1f258c30476442db36be2137a044c61
--- /dev/null
+++ b/adaptors/julia/EncoderIn.jl
@@ -0,0 +1,38 @@
+mutable struct EncoderInChannel
+    context::Ptr{Nothing}
+    read::Ptr{Nothing}
+end
+
+mutable struct EncoderIn
+    moberg::Moberg
+    index::UInt32
+    channel::EncoderInChannel
+    EncoderIn(moberg::Moberg, index::Unsigned) = (
+        channel = EncoderInChannel(0,0);
+        checkOK(ccall((:moberg_encoder_in_open, "libmoberg"),
+                       Status,
+                       (Moberg, Cint, Ref{EncoderInChannel}),
+                       moberg, index, channel));
+        self = new(moberg, index, channel);
+        finalizer(close, self);
+        self
+    )
+end
+
+function close(ein::EncoderIn)
+    # println("closing $(ein)")
+    checkOK(ccall((:moberg_encoder_in_close, "libmoberg"),
+                  Status,
+                  (Moberg, Cint, EncoderInChannel),
+                  ein.moberg, ein.index, ein.channel))
+end
+
+function read(ein::EncoderIn)
+    result = Ref{Clong}(0)
+    checkOK(ccall(ein.channel.read,
+                  Status,
+                  (Ptr{Nothing}, Ptr{Clong}),
+                  ein.channel.context, result))
+    return result[]
+end
+
diff --git a/adaptors/julia/Makefile b/adaptors/julia/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..1263948fb882b8c4fd639b01e17969c825e79619
--- /dev/null
+++ b/adaptors/julia/Makefile
@@ -0,0 +1 @@
+all:
diff --git a/adaptors/julia/MobergIO.jl b/adaptors/julia/MobergIO.jl
new file mode 100644
index 0000000000000000000000000000000000000000..ec35eeb34e858a0ef4dc2ddc4ffc5a66008d634b
--- /dev/null
+++ b/adaptors/julia/MobergIO.jl
@@ -0,0 +1,35 @@
+module MobergIO
+
+
+struct Status
+    result::Clong
+end
+
+function checkOK(status::Status)
+    if status.result != 0
+        error("Moberg call failed with errno $(status.result)")
+    end
+end
+
+mutable struct Moberg
+    handle::Ptr{Nothing}
+end
+
+function Moberg() 
+    handle = ccall((:moberg_new, "libmoberg"), Ptr{Moberg}, ())
+    m = Moberg(handle)
+    finalizer(close, m)
+    m
+end
+
+function close(h::Moberg)
+    ccall((:moberg_free, "libmoberg"), Nothing, (Moberg,), h)
+end
+
+include("AnalogIn.jl")
+include("AnalogOut.jl")
+include("DigitalIn.jl")
+include("DigitalOut.jl")
+include("EncoderIn.jl")
+
+end
diff --git a/adaptors/julia/moberg.jl b/adaptors/julia/moberg.jl
new file mode 100755
index 0000000000000000000000000000000000000000..e45888a2b7d500e01666cb0b0e43d23bd4431c2f
--- /dev/null
+++ b/adaptors/julia/moberg.jl
@@ -0,0 +1,126 @@
+#!/usr/bin/julia
+
+struct moberg_status
+    result::Clong
+end
+
+function check_OK(status::moberg_status)
+    if status.result != 0
+        error("Moberg call failed with errno $(status.result)")
+    end
+end
+
+mutable struct moberg
+    handle::Ptr{Nothing}
+end
+
+function moberg() 
+    handle = ccall((:moberg_new, "libmoberg"), Ptr{Nothing}, ())
+    println(handle)
+    m = moberg(handle)
+    function close(h::moberg)
+        println(h)
+        ccall((:moberg_free, "libmoberg"), Nothing, (Ptr{Nothing},),
+              h.handle)
+    end
+    finalizer(close, m)
+    m
+end
+
+mutable struct moberg_analog_in
+    context::Ptr{Nothing}
+    do_read::Ptr{Nothing}
+    handle::moberg
+    moberg_analog_in(m::moberg, index::Unsigned) = (
+        self = new();
+        check_OK(ccall((:moberg_analog_in_open, "libmoberg"),
+                       moberg_status,
+                       (Ptr{Nothing}, Cint, Ref{moberg_analog_in}),
+                       m.handle, index, self));
+        self.handle = m;
+        function close(channel::moberg_analog_in)
+            println(channel)
+            ccall((:moberg_analog_in_close, "libmoberg"),
+                  moberg_status,
+                  (Ptr{Nothing}, Cint, moberg_analog_in),
+                  channel.handle.handle, index, self)
+        end;
+        finalizer(close, self);
+        self
+    )
+end
+
+mutable struct moberg_analog_out
+    context::Ptr{Nothing}
+    do_write::Ptr{Nothing}
+    handle::moberg
+    moberg_analog_out(m::moberg, index::Unsigned) = (
+        self = new();
+        check_OK(ccall((:moberg_analog_out_open, "libmoberg"),
+                       moberg_status,
+                       (Ptr{Nothing}, Cint, Ref{moberg_analog_out}),
+                       m.handle, index, self));
+        self.handle = m;
+        function close(channel::moberg_analog_out)
+            println(channel)
+            ccall((:moberg_analog_out_close, "libmoberg"),
+                  moberg_status,
+                  (Ptr{Nothing}, Cint, moberg_analog_out),
+                  channel.handle.handle, index, self)
+        end;
+        finalizer(close, self);
+        self
+    )
+end
+
+function read(ain::moberg_analog_in)
+    result = Ref{Cdouble}(0.0)
+    check_OK(ccall(ain.do_read,
+                   moberg_status,
+                   (Ptr{Nothing}, Ptr{Cdouble}),
+                   ain.context, result))
+    return result[]
+end
+
+function write(aout::moberg_analog_out, value::Cdouble)
+    check_OK(ccall(aout.do_write,
+                   moberg_status,
+                   (Ptr{Nothing}, Cdouble),
+                   aout.context, value))
+end
+
+function test()
+    m = moberg()
+    println(m)
+    
+    for v in -10.0:2.0:10 
+        for i in 30:31
+            try
+                aout = moberg_analog_out(m, Unsigned(i))
+                value = v + i - 32;
+                write(aout, value)
+                print("$value ")
+            catch
+                println("analog_out $i does not exist")
+            end
+        end
+        println()
+        sleep(0.1)
+        for j in 30:33
+            try
+                ain = moberg_analog_in(m, Unsigned(j))
+                println(read(ain))
+            catch
+                println("analog_in $j does not exist")
+            end
+        end
+        println()
+        GC.gc()
+    end
+end
+
+test()
+
+println("DONE")
+GC.gc()
+println("Really DONE")
diff --git a/adaptors/julia/test_moberg.jl b/adaptors/julia/test_moberg.jl
new file mode 100644
index 0000000000000000000000000000000000000000..3f3a22dcb0fe9a9e74cabe7cbb18749d5180689c
--- /dev/null
+++ b/adaptors/julia/test_moberg.jl
@@ -0,0 +1,66 @@
+#!/usr/bin/julia
+
+push!(LOAD_PATH, ".")
+
+using MobergIO
+import MobergIO: read, write
+
+function test()
+    m = MobergIO.Moberg()
+    println(m)
+    
+    for v in -10.0:2.0:10 
+        for i in 30:31
+            try
+                aout = MobergIO.AnalogOut(m, Unsigned(i))
+                value = v + i - 32;
+                write(aout, value)
+                print("$value ")
+            catch ex
+                println("analog_out $i does not exist $(ex)")
+            end
+        end
+        println()
+        sleep(0.01)
+        for j in 30:33
+            try
+                ain = MobergIO.AnalogIn(m, Unsigned(j))
+                println(read(ain))
+            catch ex
+                println("analog_in $j does not exist $(ex)")
+            end
+        end
+        println()
+#        GC.gc()
+    end
+    for v in false:true
+        for i in 30:36
+            try
+                dout = MobergIO.DigitalOut(m, Unsigned(i))
+                value = xor(v, isodd(i))
+                write(dout, value)
+                print("$value ")
+            catch ex
+                println("digital_out $i does not exist $(ex)")
+            end
+        end
+        println()
+        for i in 30:36
+            try
+                din = MobergIO.DigitalIn(m, Unsigned(i))
+                print("$(read(din)) ")
+            catch ex
+                println("digital_out $i does not exist $(ex)")
+            end
+        end
+        println()
+        println()
+        sleep(0.01)
+    end
+end
+
+test()
+
+println("DONE")
+GC.gc()
+println("Really DONE")