diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,3 @@
+# Changelog for csound-controllers
+
+## Unreleased changes
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Author name here (c) 2018
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Author name here nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,1 @@
+# csound-controllers
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/csound-controllers.cabal b/csound-controllers.cabal
new file mode 100644
--- /dev/null
+++ b/csound-controllers.cabal
@@ -0,0 +1,43 @@
+name:           csound-controllers
+version:        0.1.1.0
+description:    Please see the README on GitHub at <https://github.com/githubuser/csound-controllers#readme>
+homepage:       https://github.com/githubuser/csound-controllers#readme
+bug-reports:    https://github.com/githubuser/csound-controllers/issues
+author:         Author name here
+maintainer:     example@example.com
+copyright:      2018 Author name here
+license:        BSD3
+license-file:   LICENSE
+build-type:     Simple
+cabal-version:  >= 1.22
+extra-source-files:
+    ChangeLog.md
+    README.md
+
+source-repository head
+  type: git
+  location: https://github.com/githubuser/csound-controllers
+
+library
+  exposed-modules:
+      Csound.Control.Midi.LaunchKey
+  hs-source-dirs:
+      src
+  build-depends:
+        base >=4.7 && <5,
+        csound-expression >= 5.3.4
+  default-language: Haskell2010
+
+test-suite csound-controllers-test
+  type: exitcode-stdio-1.0
+  main-is: Spec.hs
+  other-modules:
+      Paths_csound_controllers
+  hs-source-dirs:
+      test
+  ghc-options: -threaded -rtsopts -with-rtsopts=-N
+  build-depends:
+      base >=4.7 && <5
+    , csound-controllers
+    , csound-expression >= 5.3.4
+  default-language: Haskell2010
diff --git a/src/Csound/Control/Midi/LaunchKey.hs b/src/Csound/Control/Midi/LaunchKey.hs
new file mode 100644
--- /dev/null
+++ b/src/Csound/Control/Midi/LaunchKey.hs
@@ -0,0 +1,88 @@
+-- | Functions to play with Novation LaunchKey midi-controller
+module Csound.Control.Midi.LaunchKey(
+    LkChn(..)
+  , knob
+  , knobs
+  , idKnobs
+  , knob'
+  , knobs'
+  , idKnobs'
+  , tapBtn
+  , tapBtns
+  , tapBtnRow
+  , tapBtnRowSig
+  , toggleBtn
+  , toggleBtns
+) where
+
+import Control.Monad
+import Csound.Base hiding (knob, knob')
+
+-- | Midi channel
+newtype LkChn = LkChn Int
+
+instance Default LkChn where
+  def = LkChn 9
+
+-- | Knob get unipolar value of the LK8 knob
+--
+-- > knob knobId initVal
+--
+-- knobId - [1, 16]
+knob' :: LkChn -> Int -> D -> SE Sig
+knob' (LkChn chn) n initValue = umidiCtrl (int chn) (getKnobId n) initValue
+
+knobs' :: LkChn -> [D] -> SE [Sig]
+knobs' chn = idKnobs' chn [1..]
+
+idKnobs' :: LkChn -> [Int] -> [D] -> SE [Sig]
+idKnobs' chn ids initVals = mapM (uncurry $ knob' chn) $ zip ids initVals
+
+knob :: Int -> D -> SE Sig
+knob = knob' def
+
+knobs :: [D] -> SE [Sig]
+knobs = knobs' def
+
+idKnobs :: [Int] -> [D] -> SE [Sig]
+idKnobs = idKnobs' def
+
+getKnobId :: Int -> D
+getKnobId n
+  | 1 <= n && n <= 8  = int $ 20 + n
+  | 9 <= n && n <= 16 = int $ 40 + (n - 8)
+  | otherwise         = error "LK8 has only 16 knobs"
+
+--------------------------
+
+tapBtn :: LkChn -> Int -> SE Tick
+tapBtn (LkChn n) idx = fmap (fmap $ const unit) $ midiKeyOn (Chn n) (getBtnNote idx)
+
+tapBtns :: LkChn -> SE [Tick]
+tapBtns chn = mapM (tapBtn chn) [1..8]
+
+tapBtnRow :: LkChn -> SE (Evt D)
+tapBtnRow chn = do
+  evts <- tapBtns chn
+  return $ mconcat $ zipWith (\n ev -> fmap (const n) ev) (fmap int [1..]) evts
+
+tapBtnRowSig :: LkChn -> SE Sig
+tapBtnRowSig = stepper 0 . fmap sig <=< tapBtnRow
+
+getBtnNote :: Int -> D
+getBtnNote n
+  | 1 <= n && n <= 4 = int $ 8 + n
+  | 5 <= n && n <= 8 = int $ 20 + n
+  | otherwise        = error "LK8 has only 8 buttons"
+
+toggleBtn :: LkChn -> Int -> SE (Evt D)
+toggleBtn chn idx = fmap toTog $ tapBtn chn idx
+
+toggleBtns :: LkChn -> SE [Evt D]
+toggleBtns chn = mapM (toggleBtn chn) [1..8]
+
+
+-- pressBtn :: Chn -> Int -> Evt Bool
+
+-- pressBtnSig :: Chn -> Int -> SE Sig
+-- toggleBtnSig :: Chn -> Int -> SE Sig
diff --git a/test/Spec.hs b/test/Spec.hs
new file mode 100644
--- /dev/null
+++ b/test/Spec.hs
@@ -0,0 +1,2 @@
+main :: IO ()
+main = putStrLn "Test suite not yet implemented"
