diff --git a/README.md b/README.md
index fd1278ac68fa2ac91bcf8c0a5234885ce0672b5d..167743fc8ec94bba100bdb428a7229b16535e547 100644
--- a/README.md
+++ b/README.md
@@ -2,155 +2,4 @@
 [![coverage report](https://gitlab.control.lth.se/processes/LabProcesses.jl/badges/master/coverage.svg)](https://gitlab.control.lth.se/processes/LabProcesses.jl/commits/master)
 
 # LabProcesses
-This package contains an (programming- as well as connection-) interface to serve
-as a base for the implementation of lab-process software. The first example of
-an implementaiton of this interface is for the ball-and-beam process, which is
-used in Lab1 FRTN35: frequency response analysis of the beam. The lab is implemented
-in [BallAndBeam.jl](https://gitlab.control.lth.se/processes/BallAndBeam.jl), a
-package that makes use of `LabProcesses.jl` to handle the communication with
-the lab process and/or a simulated version thereof. This way, the code written
-for frequency response analysis of the beam can be run on another process
-implementing the same interface (or a simulated version) by changeing a single
-line of code :)
-
-## Installation
-1. Start julia by typing `julia` in a terminal, make sure the printed info says it's
-`v0.6+` running. If not, visit [julialang.org](https://julialang.org/downloads/)
-to get the latest release.
-2. Install LabProcesses.jl using command `Pkg.clone("https://gitlab.control.lth.se/processes/LabProcesses.jl.git")` Lots of packages will now be installed, this will take some time. If this is your first time using Julia, you might have to run `julia> Pkg.init()` before you install any packages.
-
-## How to implement a new process
-1. Locate the file [interface.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface.jl). When the package is installed, you find its directory under `~/.julia/v0.6/LabProcesses/`, if not, run `julia> Pkg.dir("LabProcesses")` to locate the directory.
-(Alternatively, you can copy all definitions from [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) instead. Maybe it's easier to work from an existing implementaiton.)
-2. Copy all function definitions.
-3. Create a new file under `/interface_implementations` where you paste all the
-copied definitions and implement them. See [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) for an example.
-4. Above all function implementations you must define the process type, e.g,
-    ```julia
-    struct BallAndBeam <: PhysicalProcess
-        h::Float64
-        bias::Float64
-    end
-    BallAndBeam() = BallAndBeam(0.01, 0.0) # Constructor with default value of sample time
-    ```
-Make sure you inherit from `PhysicalProcess` or `SimulatedProcess` as appropriate.
-This type must contains fields that hold information about everything that is
-relevant to a particular instance of the process. Different ballandbeam-process
-have different biases, hence this must be stored. A simulated process would have
-to keep track of its state etc. in order to implement the measure and control
-methods. See [Types in julia documentation](https://docs.julialang.org/en/stable/manual/types/#Composite-Types-1)
-for additional info regarding user defined types and (constructors)[https://docs.julialang.org/en/stable/manual/constructors/].
-5. Documentation of all interface functions is available in the file [interface_documentation.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_documentation.jl)
-
-## Control a process
-The interface `AbstractProcess` defines the functions `control(P, u)` and `measure(P)`.
-These functions can be used to implement your own control loops. A common loop
-with a feedback controller and a feedforward filter on the reference is implemented
-in the function [`run_control_2DOF`](@ref), where the user can supply $G_1$ and $G_4$
-in the diagram below, with the process $P=G_2$.
-![block diagram](docs/src/feedback4.png)
-
-The macro `@periodically` might come in handy if you want to implement your own loop.
-Consider the following example, in which the loop body will be run periodically
-with a sample time of `h` seconds.
-```julia
-for (i,t) = enumerate(0:h:duration)
-    @periodically h begin
-        y[i] = measure(P)
-        r[i] = reference(t)
-        u[i] = calc_control(y,r)
-        control(P, u[i])
-    end
-end
-```
-
-
-Often one finds the need to implement a stateful controller, i.e., a function
-that has a memory or state. To this end, the type [`SysFilter`](@ref) is
-provided. This type is used to implement control loops where a signal is
-filtered through a dynamical system, i.e., `U(z) = G1(z)E(z)`.
-Usage is demonstrated below, which is a simplified implementation of the block
-diagram above (transfer function- and signal names corresponds to the figure).
-First two `SysFilter` objects are created, these objects can now be used as
-functions of an input, and return the filtered output. The `SysFilter` type takes
-care of updating and remembering the state of the system when called.
-```julia
-G1f = SysFilter(G1)
-G4f = SysFilter(G4)
-function calc_control(y,r)
-    rf = G4f(r)
-    e  = rf-y
-    u  = G1f(e)
-end
-```
-`G1` and `G4` must here be represented by [`StateSpace`](http://juliacontrol.github.io/ControlSystems.jl/latest/lib/constructors/#ControlSystems.ss) types
-from [`ControlSystems.jl`](https://github.com/JuliaControl/ControlSystems.jl), e.g., `G1 = ss(A,B,C,D)`.
-`TransferFunction` types can easily be converted to a `StateSpace` by `Gss = ss(Gtf)`.
-Continuous time systems can be discretized using `Gd = c2d(Gc, h)[1]`. (The sample time of a process is available through `h = sampletime(P)`.)
-
-
-# How to implement a Simulated Process
-## Linear process
-This is very easy, just get a discrete time `StateSpace` model of your process
-(if you have a transfer function, `Gss = ss(Gtf)` will do the trick, if you have continuous time, `Gd = c2d(Gc,h)[1]` is your friend).
-
-You now have to implement the methods `control` and `measure` for your simulated type.
-The implementation for `BeamSimulator` is shown below
-```julia
-control(p::BeamSimulator, u) = p.Gf(u)
-measure(P) = vecdot(p.Gf.sys.C, p.Gf.state)
-```
-The `control` method accepts a control signal (`u`) and propagates the system state
-(`p.Gf.state`) forward using the statespace model (`p.Gf.sys`) of the beam. The object
-[`Gf::SysFilter`](@ref) is familiar from the "Control" section above. What it does
-is essentially (simplified)
-```julia
-function Gf(input)
-    sys       = Gf.sys
-	Gf.state .= sys.A*Gf.state + sys.B*input
-	output    = sys.C*Gf.state + sys.D*input
-end
-```
-hence, it just performs one iteration of
-```math
-x' = Ax + Bu
-```
-```math
-y  = Cx + Du
-```
-
-The `measure` method performs the computation `y = Cx`, the reason for the call
-to `vecdot` is that `vecdot` produces a scalar output, whereas `C*x` produces a
-1-element `Matrix`. A scalar output is preferred in this case since the `Beam`
-is SISO.
-
-It should now be obvious which fields are required in the `BeamSimulator` type.
-It must know which sample time it has been discretized with, as well as its
-discrete-time system model. It must also remember the current state of the system.
-This is not needed in a physical process since it kind of remembers its own state.
-The system model and its state is conveniently covered by the type [`SysFilter`](@ref),
-which handles filtering of a signal through an LTI system.
-The full type specification for `BeamSimulator` is given below
-```julia
-struct BeamSimulator <: SimulatedProcess
-    h::Float64
-    Gf::SysFilter
-    BeamSimulator() = new(0.01, SysFilter(beam_system, 0.01))
-    BeamSimulator(h::Real) = new(Float64(h), SysFilter(beam_system, h))
-end
-```
-It contains three fields and two inner constructors. The constructors initializes
-the system filter by creating a [`SysFilter`](@ref).
-The variable `beam_system` is already defined outside the type specification.
-One of the constructors provides a default value for the sample time, in case
-the user is unsure about a reasonable value.
-
-## Non-linear process
-Your first option is to linearize the process and proceed like above.
-Other options include
-1. Make `control` perform forward Euler, i.e., `x' = f(x,u)*h` for a general
-system model ``x' = f(x,u); y = g(x,u)`` and sample time ``h``.
-2. Integrate the system model using some fancy method like Runge-Kutta. See
-[DifferentialEquations.jl](http://docs.juliadiffeq.org/stable/types/discrete_types.html)
-for discrete-time solving of ODEs (don't be discuraged, this is almost as simple as
-forward Euler above).
+Documentation available at [Documentation](http://processes.gitlab.control.lth.se/documentation/labprocesses/)
diff --git a/docs/make.jl b/docs/make.jl
index efb13107f963e82390d7e6b4d4baf8267df0114c..7e696a5ee95816a6434206f9343a688e0c96a874 100644
--- a/docs/make.jl
+++ b/docs/make.jl
@@ -13,7 +13,6 @@ makedocs(
     sitename = "LabProcesses",
     pages = [
         "index.md",
-        "README.md"
     ]
 )
 
diff --git a/docs/src/README.md b/docs/src/README.md
deleted file mode 120000
index fe840054137e2ccda075344f21e728249a60a2fc..0000000000000000000000000000000000000000
--- a/docs/src/README.md
+++ /dev/null
@@ -1 +0,0 @@
-../../README.md
\ No newline at end of file
diff --git a/docs/src/index.md b/docs/src/index.md
index accbe8987b4f69562b568c23f0b3efea24c7edf1..25f067424734c09c59a5ff9095810eefe25ceb88 100644
--- a/docs/src/index.md
+++ b/docs/src/index.md
@@ -4,15 +4,164 @@
 Depth = 3
 ```
 
-# Installation
-Install `LabProcesses.jl` using command `Pkg.clone("https://gitlab.control.lth.se/processes/LabProcesses.jl.git")` Lots of packages will now be installed, this might take some time.
+This package contains an (programming- as well as connection-) interface to serve
+as a base for the implementation of lab-process software. The first example of
+an implementaiton of this interface is for the ball-and-beam process, which is
+used in Lab1 FRTN35: frequency response analysis of the beam. The lab is implemented
+in [BallAndBeam.jl](https://gitlab.control.lth.se/processes/BallAndBeam.jl), a
+package that makes use of `LabProcesses.jl` to handle the communication with
+the lab process and/or a simulated version thereof. This way, the code written
+for frequency response analysis of the beam can be run on another process
+implementing the same interface (or a simulated version) by changeing a single
+line of code :)
 
+## Installation
+1. Start julia by typing `julia` in a terminal, make sure the printed info says it's
+`v0.6+` running. If not, visit [julialang.org](https://julialang.org/downloads/)
+to get the latest release.
+2. Install LabProcesses.jl using command `Pkg.clone("https://gitlab.control.lth.se/processes/LabProcesses.jl.git")` Lots of packages will now be installed, this will take some time. If this is your first time using Julia, you might have to run `julia> Pkg.init()` before you install any packages.
+
+## How to implement a new process
+1. Locate the file [interface.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface.jl). When the package is installed, you find its directory under `~/.julia/v0.6/LabProcesses/`, if not, run `julia> Pkg.dir("LabProcesses")` to locate the directory.
+(Alternatively, you can copy all definitions from [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) instead. Maybe it's easier to work from an existing implementaiton.)
+2. Copy all function definitions.
+3. Create a new file under `/interface_implementations` where you paste all the
+copied definitions and implement them. See [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) for an example.
+4. Above all function implementations you must define the process type, e.g,
+    ```julia
+    struct BallAndBeam <: PhysicalProcess
+        h::Float64
+        bias::Float64
+    end
+    BallAndBeam() = BallAndBeam(0.01, 0.0) # Constructor with default value of sample time
+    ```
+Make sure you inherit from `PhysicalProcess` or `SimulatedProcess` as appropriate.
+This type must contains fields that hold information about everything that is
+relevant to a particular instance of the process. Different ballandbeam-process
+have different biases, hence this must be stored. A simulated process would have
+to keep track of its state etc. in order to implement the measure and control
+methods. See [Types in julia documentation](https://docs.julialang.org/en/stable/manual/types/#Composite-Types-1)
+for additional info regarding user defined types and (constructors)[https://docs.julialang.org/en/stable/manual/constructors/].
+5. Documentation of all interface functions is available in the file [interface_documentation.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_documentation.jl)
+
+## Control a process
+The interface `AbstractProcess` defines the functions `control(P, u)` and `measure(P)`.
+These functions can be used to implement your own control loops. A common loop
+with a feedback controller and a feedforward filter on the reference is implemented
+in the function [`run_control_2DOF`](@ref), where the user can supply $G_1$ and $G_4$
+in the diagram below, with the process $P=G_2$.
+![block diagram](feedback4.png)
+
+The macro `@periodically` might come in handy if you want to implement your own loop.
+Consider the following example, in which the loop body will be run periodically
+with a sample time of `h` seconds.
+```julia
+for (i,t) = enumerate(0:h:duration)
+    @periodically h begin
+        y[i] = measure(P)
+        r[i] = reference(t)
+        u[i] = calc_control(y,r)
+        control(P, u[i])
+    end
+end
+```
+
+
+Often one finds the need to implement a stateful controller, i.e., a function
+that has a memory or state. To this end, the type [`SysFilter`](@ref) is
+provided. This type is used to implement control loops where a signal is
+filtered through a dynamical system, i.e., `U(z) = G1(z)E(z)`.
+Usage is demonstrated below, which is a simplified implementation of the block
+diagram above (transfer function- and signal names corresponds to the figure).
+First two `SysFilter` objects are created, these objects can now be used as
+functions of an input, and return the filtered output. The `SysFilter` type takes
+care of updating and remembering the state of the system when called.
+```julia
+G1f = SysFilter(G1)
+G4f = SysFilter(G4)
+function calc_control(y,r)
+    rf = G4f(r)
+    e  = rf-y
+    u  = G1f(e)
+end
+```
+`G1` and `G4` must here be represented by [`StateSpace`](http://juliacontrol.github.io/ControlSystems.jl/latest/lib/constructors/#ControlSystems.ss) types
+from [`ControlSystems.jl`](https://github.com/JuliaControl/ControlSystems.jl), e.g., `G1 = ss(A,B,C,D)`.
+`TransferFunction` types can easily be converted to a `StateSpace` by `Gss = ss(Gtf)`.
+Continuous time systems can be discretized using `Gd = c2d(Gc, h)[1]`. (The sample time of a process is available through `h = sampletime(P)`.)
+
+
+# How to implement a Simulated Process
+## Linear process
+This is very easy, just get a discrete time `StateSpace` model of your process
+(if you have a transfer function, `Gss = ss(Gtf)` will do the trick, if you have continuous time, `Gd = c2d(Gc,h)[1]` is your friend).
+
+You now have to implement the methods `control` and `measure` for your simulated type.
+The implementation for `BeamSimulator` is shown below
+```julia
+control(p::BeamSimulator, u) = p.Gf(u)
+measure(P) = vecdot(p.Gf.sys.C, p.Gf.state)
+```
+The `control` method accepts a control signal (`u`) and propagates the system state
+(`p.Gf.state`) forward using the statespace model (`p.Gf.sys`) of the beam. The object
+`Gf` (of type [`SysFilter`](@ref)) is familiar from the "Control" section above. What it does
+is essentially (simplified)
+```julia
+function Gf(input)
+    sys       = Gf.sys
+	Gf.state .= sys.A*Gf.state + sys.B*input
+	output    = sys.C*Gf.state + sys.D*input
+end
+```
+hence, it just performs one iteration of
+```math
+x' = Ax + Bu
+```
+```math
+y  = Cx + Du
+```
+
+The `measure` method performs the computation `y = Cx`, the reason for the call
+to `vecdot` is that `vecdot` produces a scalar output, whereas `C*x` produces a
+1-element `Matrix`. A scalar output is preferred in this case since the `Beam`
+is SISO.
+
+It should now be obvious which fields are required in the `BeamSimulator` type.
+It must know which sample time it has been discretized with, as well as its
+discrete-time system model. It must also remember the current state of the system.
+This is not needed in a physical process since it kind of remembers its own state.
+The system model and its state is conveniently covered by the type [`SysFilter`](@ref),
+which handles filtering of a signal through an LTI system.
+The full type specification for `BeamSimulator` is given below
+```julia
+struct BeamSimulator <: SimulatedProcess
+    h::Float64
+    Gf::SysFilter
+    BeamSimulator() = new(0.01, SysFilter(beam_system, 0.01))
+    BeamSimulator(h::Real) = new(Float64(h), SysFilter(beam_system, h))
+end
+```
+It contains three fields and two inner constructors. The constructors initializes
+the system filter by creating a [`SysFilter`](@ref).
+The variable `beam_system` is already defined outside the type specification.
+One of the constructors provides a default value for the sample time, in case
+the user is unsure about a reasonable value.
+
+## Non-linear process
+Your first option is to linearize the process and proceed like above.
+Other options include
+1. Make `control` perform forward Euler, i.e., `x' = f(x,u)*h` for a general
+system model ``x' = f(x,u); y = g(x,u)`` and sample time ``h``.
+2. Integrate the system model using some fancy method like Runge-Kutta. See
+[DifferentialEquations.jl](http://docs.juliadiffeq.org/stable/types/discrete_types.html)
+for discrete-time solving of ODEs (don't be discouraged, this is almost as simple as
+forward Euler above).
 
 # Exported functions and types
 ```@autodocs
 Modules = [LabProcesses]
 Private = false
-Pages   = ["LabProcesses.jl"]
+Pages   = ["LabProcesses.jl", "controllers.jl", "reference_generators.jl", "utilities.jl"]
 ```
 
 
diff --git a/src/controllers.jl b/src/controllers.jl
index f0ef21e600431e4486121a4cd12bd37799808496..a6d21b1ae4fc42abe1ae2cdc7c2fac4f81468736 100644
--- a/src/controllers.jl
+++ b/src/controllers.jl
@@ -8,7 +8,7 @@ Perform control experiemnt on process where the feedback and feedforward control
 `reference` is a reference generating function that accepts a scalar `t` (time in seconds) and outputs a scalar `r`, default is `reference(t) = sign(sin(2π*t))`.
 
 The outputs `y,u,r` are the beam angle, control signal and reference respectively.
-![block diagram](docs/feedback4.png)
+![block diagram](feedback4.png)
 """
 function run_control_2DOF(P::AbstractProcess,sysFB, sysFF=nothing; duration = 10, reference = t->sign(sin(2π*t)))
 	nu = num_inputs(P)