diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/Lambdaya.cabal b/Lambdaya.cabal
new file mode 100644
--- /dev/null
+++ b/Lambdaya.cabal
@@ -0,0 +1,77 @@
+-- Initial redpitaya.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+-- The name of the package.
+name:                Lambdaya
+
+-- The package version.  See the Haskell package versioning policy (PVP) 
+-- for standards guiding when and how versions should be incremented.
+-- http://www.haskell.org/haskellwiki/Package_versioning_policy
+-- PVP summary:      +-+------- breaking API changes
+--                   | | +----- non-breaking API additions
+--                   | | | +--- code changes with no API change
+version:             0.1.0.0
+
+-- A short (one-line) description of the package.
+synopsis: Library for RedPitaya         
+
+-- A longer description of the package.
+description: Native library for RedPitaya that runs on RedPitaya.
+
+
+-- The license under which the package is released.
+license:             LGPL-3
+
+-- The file containing the license text.
+license-file:        LICENSE
+
+-- The package author(s).
+author:              Luka Rahne
+
+-- An email address to which users can send suggestions, bug reports, and 
+-- patches.
+maintainer:          luka.rahne@gmail.com
+
+-- A copyright notice.
+-- copyright:           
+
+category:            System
+
+build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or a 
+-- README.
+-- extra-source-files:  
+
+-- Constraint on the version of Cabal needed to build this package.
+cabal-version:       >=1.10
+
+source-repository head
+  type:     git
+  location: https://github.com/ra1u/Lambdaya.git
+
+
+library
+  -- Modules exported by the library.
+  exposed-modules: System.RedPitaya.Fpga, System.RedPitaya.Tutorial
+  
+  -- Modules included in this library but not exported.
+  -- other-modules:  
+  
+  -- LANGUAGE extensions used by modules in this package.
+  -- other-extensions:    
+  
+  -- Other library packages from which modules are imported.
+  build-depends:    
+    base >= 3 && < 5, 
+    mtl >= 2 && < 3, 
+    unix >= 2 && < 3
+  
+  -- Directories containing source files.
+  hs-source-dirs:      src
+  
+  -- Base language which the package is written in.
+  default-language:    Haskell2010
+  
+  -- build-tools: c2hs 
+  -- include-dirs: include
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/src/System/RedPitaya/Fpga.hs b/src/System/RedPitaya/Fpga.hs
new file mode 100644
--- /dev/null
+++ b/src/System/RedPitaya/Fpga.hs
@@ -0,0 +1,680 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
+-- | 
+-- <http://redpitaya.com/ Red Pitaya> native library for accessing Fpga
+
+module System.RedPitaya.Fpga (
+    Fpga,
+    Registry,
+    Channel,
+    withOpenFpga,
+    -- * Housekeeping
+    -- | various housekeeping and Gpio functions
+    fpgaId,
+    dna,
+    setExpDirP,
+    getExpDirP,
+    setExpDirN,
+    getExpDirN,
+    setExpOutP,
+    setExpOutN,
+    getExpInP,
+    getExpInN,
+    -- single pin functions
+    GpioType(..),
+    GpioDirection(..),
+    PinNum,
+    setExpDir,
+    GpioValue(..),
+    setExpOut,
+    getExpOut,
+    setLed,
+    getLed,
+    -- * Oscilloscope
+    -- | functions for accessing oscilloscope features
+    resetWriteSM,
+    triggerNow,
+    TriggerSource(..),
+    setOscTrigger,
+    triggerDelayEnded,
+    setTreshold,
+    getTreshold,
+    setDelayAfterTrigger,
+    getDelayAfterTrigger,
+    setOscDecimationRaw,
+    getOscDecimationRaw,
+    OscDecimation(..),
+    setOscDecimation,
+    getOscWpCurrent,
+    getOscWpTrigger,
+    getOscHysteresis,
+    setOscHysteresis,
+    enableOscDecimationAvarage,
+    setEqualFilter,
+    getEqualFilter,
+    setAxiLowerAddress,
+    getAxiLowerAddress,
+    setAxiUpperAddress,
+    getAxiUpperAddress,
+    setAxiDelayAfterTrigger,
+    getAxiDelayAfterTrigger,
+    enableAxiMaster,
+    getAxiWritePtrTrigger,
+    getAxiWritePtrCurrent,
+    getOscBuffer,
+    -- * Arbitrary Signal Generator (ASG)
+    getAsgOption,
+    setAsgOption,
+    setAsgOptionBExtGatRep,
+    getAsgOptionBExtGatRep,
+    setAsgAmplitudeScale,
+    setAsgAmplitudeOffset,
+    setAsgCounterWrap,
+    setAsgCounterStartOffset,
+    setAsgCounterStep,
+    getAsgCounterReadPtr,
+    setAsgCounterReadPtr,
+    getAsgNumReadCycles,
+    setAsgNumReadCycles,
+    getAsgNumRepetitions,
+    setAsgNumRepetitions,
+    getAsgBurstDelay,
+    setAsgBurstDelay,
+    -- * Plumbing
+    -- | low level functions for direct Fpga access, used to extend interface
+    Page,
+    Offset,
+    fpgaRead,
+    fpgaWrite,
+    fpgaFmap,
+    pokeFpgaArray,
+    peekFpgaArray
+)   
+where
+
+import Foreign.C.Types
+import Foreign.Ptr
+import Foreign.Marshal.Array
+import System.Posix.IO
+import Data.Int
+import Data.Word
+import Data.Bits
+import Foreign.Storable
+
+import Control.Monad
+import Control.Applicative
+import Control.Monad.State  
+
+
+
+fpgaPageSize = 0x100000
+fpgaMapSize = 0x100000 * 8
+addrAms = 0x40000000
+
+type FpgaPtr = Ptr ()
+type FpgaState = FpgaPtr
+
+-- | type representing fpga memory offset from page
+type Offset = Int
+-- | type representing fpga memory page
+type Page = Int
+-- | type representing fpga registry
+type Registry = Word32
+-- | Fpga monad is hidden behind this type
+type StateMonad a = StateT FpgaState IO  a
+
+-- | Environment where one can read and write Fpga registries
+newtype Fpga a = Fpga (StateMonad a) 
+    deriving (Functor,Applicative, Monad,MonadIO, MonadFix, MonadPlus, Alternative)
+
+-- | Redpitaya Channel A or B.
+data Channel = A | B
+
+getStateType :: Fpga a -> StateMonad a
+getStateType (Fpga s) = s 
+
+-- Constructor
+fpgaState a = Fpga ( StateT a )
+
+runFpga :: Fpga a -> FpgaState -> IO (a,FpgaState) 
+runFpga (Fpga s) = runStateT s
+
+store ::  FpgaState -> Fpga ()
+store v = fpgaState $ \x -> ( return ((),v) )
+
+getState :: Fpga FpgaState
+getState = fpgaState $  \x -> ( return  (x,x) )
+
+getPtr :: Fpga FpgaPtr
+getPtr = getState
+
+
+-- | This function handles initialising Fpga memory mapping and
+-- evaluates 'Fpga' action.
+withOpenFpga :: Fpga a -> IO a
+withOpenFpga act = do
+    fd <- openFd  "/dev/mem" ReadWrite Nothing defaultFileFlags
+    setFdOption fd SynchronousWrites True
+    p <- mmap nullPtr fpgaMapSize (c'PROT_READ + c'PROT_WRITE ) c'MAP_SHARED (fromIntegral fd) addrAms
+    (r,s) <- runFpga act p
+    munmap p fpgaMapSize
+    return r
+
+
+-- | get raw pointer on fpga registry calculated from page, offset 
+-- and internal state that holds memory mapped pointer
+getOffsetPtr :: Page -> Offset -> Fpga (Ptr Registry)
+getOffsetPtr page offset = 
+    -- offset on getPtr 
+    (\memmap -> plusPtr memmap (page * fpgaPageSize + offset)) <$> getPtr
+
+
+-- | direct read from fpga registry
+fpgaRead :: Page -> Offset -> Fpga Registry
+fpgaRead page offset = do
+    p <- getOffsetPtr page offset
+    liftIO $ peek p
+
+-- | direct write in fpga registry
+fpgaWrite :: Page ->  Offset -> Registry -> Fpga ()
+fpgaWrite page offset reg = do
+    p <- getOffsetPtr page offset
+    liftIO $ poke p reg
+
+-- | apply transformation on fpga registry value 
+fpgaFmap :: Page ->  Offset -> (Registry -> Registry) -> Fpga ()
+fpgaFmap page offset f = do
+    reg <- fpgaRead page offset
+    fpgaWrite page offset (f reg)
+
+-- | write array in fpga memory
+pokeFpgaArray :: Page -> Offset -> [Registry] -> Fpga ()
+pokeFpgaArray page offset xs =  do
+    p <- getOffsetPtr page offset
+    liftIO $ pokeArray p xs
+
+-- | read array from fpga memory, passing page, offset and length
+peekFpgaArray :: Page -> Offset -> Int -> Fpga [Registry]
+peekFpgaArray page offset len = do
+    p <- getOffsetPtr page offset
+    liftIO $ peekArray len p
+
+
+
+---------------------------------------------------------
+-- * Housekeeping memory map
+
+-- | get ID ,  0 prototype , 1 release
+fpgaId :: Fpga Registry
+fpgaId = fpgaRead 0 0
+
+-- | get DNA
+dna :: Fpga Integer
+dna = do
+    dna1 <- fromIntegral <$> fpgaRead 0 4
+    dna2 <- fromIntegral <$> fpgaRead 0 8
+    return $ dna1 + (2^32)*dna2
+
+-- | set expansion connector direction P registry
+--
+-- 1 out , 0 in  
+setExpDirP :: Registry -> Fpga ()
+setExpDirP = fpgaWrite 0 0x10
+
+-- | get expansion connector direction P registry
+--
+-- 1 out , 0 in 
+getExpDirP :: Fpga Registry
+getExpDirP = fpgaRead 0 0x10
+
+-- | set expansion connector direction N registry
+--
+-- 1 out , 0 in 
+setExpDirN :: Registry -> Fpga ()
+setExpDirN = fpgaWrite 0 0x14
+
+-- | get expansion connector direction N registry
+--
+-- 1 out , 0 in 
+getExpDirN :: Fpga Registry
+getExpDirN = fpgaRead 0 0x14
+
+-- | expansion connector  P output registry value
+setExpOutP :: Registry -> Fpga ()
+setExpOutP = fpgaWrite 0 0x18
+
+-- | expansion connector  P output registry value
+getExpOutP :: Fpga Registry
+getExpOutP = fpgaRead 0 0x18
+
+-- | expansion connector  N output registry value
+setExpOutN :: Registry -> Fpga ()
+setExpOutN = fpgaWrite 0 0x1C
+
+-- | expansion connector  N output registry value
+getExpOutN :: Fpga Registry
+getExpOutN = fpgaRead 0 0x1C
+
+-- | expansion connector  P input registry value
+getExpInP :: Fpga Registry
+getExpInP =  fpgaRead 0 0x20
+
+-- | expansion connector  N input registry value
+getExpInN :: Fpga Registry
+getExpInN =  fpgaRead 0 0x24
+
+-- | type of gpio can be either P on N
+data GpioType =
+    -- | P gpio
+    P | 
+    -- | N gpio
+    N
+    deriving (Show)
+
+class ToBool b where 
+    toBool :: b -> Bool 
+
+setBitValue :: (Bits a,ToBool b) => b -> Int  -> a -> a
+setBitValue b
+    | toBool b = flip setBit
+    | otherwise = flip clearBit
+
+-- | represent gpio direction, that can be either Input or Output
+data GpioDirection =
+    Input | 
+    Output
+    deriving (Show)
+
+instance ToBool GpioDirection where
+    toBool Input = True
+    toBool Output = False
+
+
+-- | type representing pin number
+type PinNum = Int
+
+-- | Sets direction of pin
+setExpDir :: GpioType -> GpioDirection -> PinNum ->  Fpga ()
+setExpDir N d p = setBitValue d p <$> getExpDirN  >>= setExpDirN
+setExpDir P d p = setBitValue d p <$> getExpDirP  >>= setExpDirP
+
+
+-- | represent gpio value that can be either Hi or Low 
+data GpioValue =
+    Low | 
+    Hi
+    deriving (Show)
+
+instance ToBool GpioValue where
+    toBool Low = False
+    toBool Hi = True
+
+-- | Sets outout value of pin
+setExpOut :: GpioType -> GpioValue -> PinNum ->  Fpga ()
+-- read using getExpOutN , fmap over setBitValue and bind in setExpOutX
+setExpOut N v p = setBitValue v p <$> getExpOutN  >>= setExpOutN
+setExpOut P v p = setBitValue v p <$> getExpOutP  >>= setExpOutP
+
+
+toGpioValue :: Bool -> GpioValue
+toGpioValue True = Hi
+toGpioValue False = Low
+
+-- | Sets output value of single pin
+getExpOut :: GpioType  -> PinNum ->  Fpga GpioValue
+getExpOut N p = (\x -> toGpioValue ( testBit x p )) <$> getExpOutN
+getExpOut P p = (\x -> toGpioValue ( testBit x p )) <$> getExpOutP
+
+-- | write in led registry
+setLed :: Registry -> Fpga ()
+setLed = fpgaWrite 0 0x30
+
+-- | read in led registry
+getLed :: Fpga Registry
+getLed = fpgaRead 0 0x30
+
+---------------------------------------
+-- * Oscilloscope
+
+osciloscpeFpgaPage :: Int
+osciloscpeFpgaPage = 1
+
+fpgaWriteOsc = fpgaWrite osciloscpeFpgaPage
+fpgaReadOsc = fpgaRead osciloscpeFpgaPage
+
+
+-- | reset write state machine for oscilloscope
+resetWriteSM :: Fpga ()
+resetWriteSM = fpgaWriteOsc 0 2
+
+-- | start writing data into memory (ARM trigger).
+triggerNow :: Fpga ()
+triggerNow = fpgaWriteOsc 0 1
+
+-- | oscilloscope trigger selection
+data TriggerSource = 
+    -- | trig immediately
+    Immediately  
+    -- | ch A threshold positive edge
+    | ChAPositiveEdge 
+    -- | ch A threshold negative edge
+    | ChANegativeEdge 
+    -- | ch B threshold positive edge
+    | ChBPositiveEdge 
+    -- | ch B threshold negative edge
+    | ChBNegativeEdge 
+    -- | external trigger positive edge - DIO0_P pin
+    | ExtPositiveEdge 
+    -- | external trigger negative edge
+    | ExtNegaitveEdge 
+    -- | arbitrary wave generator application positive edge
+    | AWGPositiveEdge 
+    -- | arbitrary wave generator application negative edge
+    | AWGNegativeEdge 
+    deriving (Show)
+
+-- | set oscilloscope trigger
+setOscTrigger :: TriggerSource -> Fpga ()
+setOscTrigger Immediately     = setOscTriggerHelper 1
+setOscTrigger ChAPositiveEdge = setOscTriggerHelper 2
+setOscTrigger ChANegativeEdge = setOscTriggerHelper 3
+setOscTrigger ChBPositiveEdge = setOscTriggerHelper 4
+setOscTrigger ChBNegativeEdge = setOscTriggerHelper 5
+setOscTrigger ExtPositiveEdge = setOscTriggerHelper 6
+setOscTrigger ExtNegaitveEdge = setOscTriggerHelper 7
+setOscTrigger AWGPositiveEdge = setOscTriggerHelper 8
+setOscTrigger AWGNegativeEdge = setOscTriggerHelper 9
+
+
+setOscTriggerHelper :: Registry -> Fpga ()
+setOscTriggerHelper = fpgaWriteOsc 0x4
+
+
+-- | when trigger delay is value becomes 'True'
+triggerDelayEnded :: Fpga Bool
+triggerDelayEnded = (==0) <$> fpgaReadOsc 0x4
+
+-- | Ch x threshold, makes trigger when ADC value cross this value
+setTreshold :: Channel -> Registry -> Fpga ()
+setTreshold A = fpgaWriteOsc 0x8
+setTreshold B = fpgaWriteOsc 0xc
+
+-- | gets ch x threshold
+getTreshold :: Channel -> Fpga Registry
+getTreshold A = fpgaReadOsc 0x8
+getTreshold B = fpgaReadOsc 0xc
+
+-- | Number of decimated data after trigger written into memory
+setDelayAfterTrigger :: Registry -> Fpga ()
+setDelayAfterTrigger = fpgaWriteOsc 0x10
+
+-- | gets delay after trigger value
+getDelayAfterTrigger :: Fpga Registry
+getDelayAfterTrigger = fpgaReadOsc 0x10
+
+-- | sets oscilloscope decimation registry, allows only
+-- 1,8, 64,1024,8192,65536. If other value is written data will NOT be correct.
+setOscDecimationRaw :: Registry -> Fpga ()
+setOscDecimationRaw =  fpgaWriteOsc 0x14
+
+-- | oscilloscope decimation registry value
+getOscDecimationRaw :: Fpga Registry
+getOscDecimationRaw =  fpgaReadOsc 0x14
+
+-- | oscilloscope decimation
+data OscDecimation = 
+    OscDec1  
+    | OscDec8
+    | OscDec64 
+    | OscDec1024
+    | OscDec8192
+    | OscDec65536
+    deriving (Show)
+
+-- | set oscilloscope decimation
+setOscDecimation :: OscDecimation -> Fpga ()
+setOscDecimation OscDec1 = setOscDecimationRaw 1
+setOscDecimation OscDec8 = setOscDecimationRaw 8
+setOscDecimation OscDec64 = setOscDecimationRaw 64
+setOscDecimation OscDec1024 = setOscDecimationRaw 1024
+setOscDecimation OscDec8192 = setOscDecimationRaw 8192
+setOscDecimation OscDec65536 = setOscDecimationRaw 65536
+
+-- | write pointer - current
+getOscWpCurrent:: Fpga Registry
+getOscWpCurrent = fpgaReadOsc 0x18
+
+-- | write pointer - trigger
+getOscWpTrigger :: Fpga Registry
+getOscWpTrigger = fpgaReadOsc 0x1C
+
+-- | ch x hysteresis
+getOscHysteresis :: Channel -> Fpga Registry
+getOscHysteresis A = fpgaReadOsc 0x20
+getOscHysteresis B = fpgaReadOsc 0x24
+
+-- | set ch x hysteresis
+setOscHysteresis :: Channel -> Registry -> Fpga ()
+setOscHysteresis A = fpgaWriteOsc 0x20
+setOscHysteresis B = fpgaWriteOsc 0x24
+
+-- | Enable signal average at decimation True enables, False disables
+enableOscDecimationAvarage :: Bool -> Fpga ()
+enableOscDecimationAvarage True = fpgaWriteOsc 0x28 1
+enableOscDecimationAvarage False = fpgaWriteOsc 0x28 0
+
+-- | set ch A equalization filter, takes array with coefficients [AA,BB,KK,PP]
+setEqualFilter :: Channel -> [Registry] -> Fpga ()
+setEqualFilter A = pokeFpgaArray osciloscpeFpgaPage 0x30 . take 4
+setEqualFilter B = pokeFpgaArray osciloscpeFpgaPage 0x40 . take 4
+
+-- | get ch x equalization filter, return array with coefficients [AA,BB,KK,PP]
+getEqualFilter :: Channel -> Fpga [Registry]
+getEqualFilter A = peekFpgaArray osciloscpeFpgaPage 0x30 4
+getEqualFilter B = peekFpgaArray osciloscpeFpgaPage 0x40 4
+
+
+setAxiGeneric' :: Offset -> Channel -> Registry -> Fpga ()
+setAxiGeneric' offest A = fpgaWriteOsc offest
+setAxiGeneric' offest B = fpgaWriteOsc (offest+0x20)
+
+getAxiGeneric' :: Offset -> Channel -> Fpga Registry
+getAxiGeneric' offest A = fpgaReadOsc offest
+getAxiGeneric' offest B = fpgaReadOsc (offest+0x20)
+
+
+-- | starting writing address ch x - CH x AXI lower address
+setAxiLowerAddress :: Channel -> Registry -> Fpga ()
+setAxiLowerAddress = setAxiGeneric' 0x50
+
+-- | read - starting writing address ch x - CH x AXI lower address
+getAxiLowerAddress :: Channel ->  Fpga Registry
+getAxiLowerAddress = getAxiGeneric' 0x50
+
+-- | starting writing address ch x - CH x AXI lower address
+setAxiUpperAddress :: Channel ->  Registry -> Fpga ()
+setAxiUpperAddress = setAxiGeneric' 0x54
+
+-- | read - starting writing address ch x - CH x AXI lower address
+getAxiUpperAddress :: Channel ->  Fpga Registry
+getAxiUpperAddress = getAxiGeneric' 0x54
+
+-- | read - Number of decimated data after trigger written into memory
+getAxiDelayAfterTrigger :: Channel -> Fpga Registry
+getAxiDelayAfterTrigger = getAxiGeneric' 0x58
+
+-- | set umber of decimated data after trigger written into memory
+setAxiDelayAfterTrigger :: Channel -> Registry -> Fpga ()
+setAxiDelayAfterTrigger = setAxiGeneric' 0x58
+
+-- | Enable AXI master
+enableAxiMaster :: Channel -> Bool -> Fpga ()
+enableAxiMaster ch True = setAxiGeneric' 0x5c ch 1
+enableAxiMaster ch False = setAxiGeneric' 0x5c ch 0
+
+-- | Write pointer for ch x at time when trigger arrived
+getAxiWritePtrTrigger :: Channel -> Fpga Registry
+getAxiWritePtrTrigger = getAxiGeneric' 0x60
+
+-- | current write pointer for ch x
+getAxiWritePtrCurrent :: Channel -> Fpga Registry
+getAxiWritePtrCurrent = getAxiGeneric' 0x64
+
+
+-- | reads oscilloscope buffer for channel x from Fpga passing offset and length. 
+-- buffer should fit within 16k sampling range.
+-- Returns  less than requested data if trying to read over the bounds.
+getOscBuffer :: Channel -> Offset -> Int -> Fpga [Registry]
+getOscBuffer chan off len = peekFpgaArray osciloscpeFpgaPage (off' + (chOff chan)) len'
+                          where
+                            off' = max 0 off
+                            len' = min (0x10000 - off) len
+                            chOff A = 0x10000 
+                            chOff B = 0x20000
+
+--------------------------------------------------------------------
+
+-- ASG
+-- | Set registry with value passed as tuple of bit offests
+-- | setBits (fromBit,toBit) value rin = ..
+setBits :: (Int,Int) -> Registry -> Registry -> Registry
+setBits (fromBit,toBit) value rin = valueShift .|. hole
+    where 
+        ones = complement 0 :: Registry
+        maskShift = xor (shiftL ones fromBit) (shiftL ones (toBit+1))  
+        hole = complement maskShift .&. rin
+        valueShift = ( shiftL value fromBit ) .&. maskShift
+
+-- | read bits  range from registy
+getBits :: (Int,Int) -> Registry -> Registry
+getBits (fromBit,toBit) value = shiftR andV fromBit
+    where
+        ones = complement 0 :: Registry
+        maskShift = xor (shiftL ones fromBit) (shiftL ones (toBit+1))  
+        andV = maskShift .&. value
+
+
+type FpgaSet = Registry -> Fpga ()
+type FpgaGet = Fpga Registry 
+
+asgFpgaPage = 2
+
+
+fpgaWriteAsg :: Offset -> Registry -> Fpga ()
+fpgaWriteAsg = fpgaWrite asgFpgaPage
+
+fpgaReadAsg :: Offset -> Fpga Registry
+fpgaReadAsg = fpgaRead asgFpgaPage
+
+fpgaFmapAsg :: Offset -> (Registry -> Registry) -> Fpga ()
+fpgaFmapAsg = fpgaFmap asgFpgaPage
+
+fpgaWriteAsgChannel :: Offset -> Channel -> Registry -> Fpga ()
+fpgaWriteAsgChannel offset A = fpgaWriteAsg   offset
+fpgaWriteAsgChannel offset B = fpgaWriteAsg ( offset + 0x20)
+
+fpgaReadAsgChannel :: Offset -> Channel -> Fpga Registry
+fpgaReadAsgChannel offset A = fpgaReadAsg   offset
+fpgaReadAsgChannel offset B = fpgaReadAsg ( offset + 0x20)
+
+fpgaFmapAsgChannel :: Offset -> (Registry -> Registry) -> Channel -> Fpga ()
+fpgaFmapAsgChannel offset f A = fpgaFmapAsg   offset f
+fpgaFmapAsgChannel offset f B = fpgaFmapAsg ( offset + 0x20) f
+
+
+-- | get ASGoption registry
+getAsgOption :: Fpga Registry
+getAsgOption = fpgaReadAsg 0x0
+
+-- | set ASG option registry
+setAsgOption :: Registry -> Fpga ()
+setAsgOption = fpgaWriteAsg 0x0
+
+
+-- | ch B external gated repetitions, 
+-- registry can be either 0x0 or 0x1
+setAsgOptionBExtGatRep :: Registry -> Fpga ()
+setAsgOptionBExtGatRep reg = fpgaFmapAsg 0 ( setBits (24,24) reg)
+
+-- | get ch B external gated repetitions, 
+-- registry can be either 0x0 or 0x1
+getAsgOptionBExtGatRep :: Fpga Registry
+getAsgOptionBExtGatRep =  getBits (24,24) <$> getAsgOption
+
+-- | TODO others
+
+-- | todo other registries
+
+-- | Ch x amplitude scale (14 bist) - out = (data*scale)/0x2000 + offset
+setAsgAmplitudeScale :: Channel -> Registry -> Fpga ()
+setAsgAmplitudeScale ch reg = fpgaFmapAsgChannel 0x4 ( setBits (16,29) reg ) ch
+
+-- | Ch x amplitude offset (14 bits) - out  = (data*scale)/0x2000 + offset 
+setAsgAmplitudeOffset :: Channel -> Registry -> Fpga ()
+setAsgAmplitudeOffset ch reg = fpgaFmapAsgChannel 0x4 ( setBits (0,13) reg ) ch
+
+-- | Ch x counter wrap - Value where counter wraps around. Depends on SM wrap setting. 
+-- If it is 1 new value is  get by wrap, if value is 0 counter goes to offset value.
+-- 16 bits for decimals.
+setAsgCounterWrap :: Channel -> Registry -> Fpga ()
+setAsgCounterWrap = fpgaWriteAsgChannel  0x8
+
+
+-- | Ch x Counter start offset. Start offset when trigger arrives. 16 bits for decimals.
+setAsgCounterStartOffset :: Channel -> Registry -> Fpga ()
+setAsgCounterStartOffset = fpgaWriteAsgChannel 0xc
+
+-- | Ch x counter step. 16 bits for decimals.
+setAsgCounterStep :: Channel -> Registry -> Fpga ()
+setAsgCounterStep = fpgaWriteAsgChannel 0x10
+
+-- | get ch x buffer current read pointer
+getAsgCounterReadPtr :: Channel -> Fpga Registry
+getAsgCounterReadPtr = fpgaReadAsgChannel 0x14
+
+-- | set ch x buffer current read pointer
+setAsgCounterReadPtr :: Channel -> Registry -> Fpga ()
+setAsgCounterReadPtr = fpgaWriteAsgChannel 0x14
+
+-- | get ch x number of read cycles in one burst
+getAsgNumReadCycles :: Channel -> Fpga Registry
+getAsgNumReadCycles = fpgaReadAsgChannel 0x18
+
+-- | set ch x number of read cycles in one burst
+setAsgNumReadCycles :: Channel -> Registry -> Fpga ()
+setAsgNumReadCycles = fpgaWriteAsgChannel 0x18
+
+-- | get ch x number of read cycles in one burst
+getAsgNumRepetitions :: Channel -> Fpga Registry
+getAsgNumRepetitions = fpgaReadAsgChannel  0x1a
+
+-- | set ch x number of read cycles in one burst
+setAsgNumRepetitions :: Channel -> Registry -> Fpga ()
+setAsgNumRepetitions = fpgaWriteAsgChannel 0x1a
+
+-- | get ch x delay between burst repetitions, granularity=1us
+getAsgBurstDelay :: Channel -> Fpga Registry
+getAsgBurstDelay = fpgaReadAsgChannel 0x20
+
+-- | set ch x delay between burst repetitions, granularity=1us
+setAsgBurstDelay :: Channel -> Registry -> Fpga ()
+setAsgBurstDelay = fpgaWriteAsgChannel 0x20
+
+---------- mmap bindings
+
+foreign import ccall "mmap" mmap
+  :: Ptr () -> CSize -> CInt -> CInt-> CInt-> CInt -> IO (Ptr ())
+
+foreign import ccall "munmap" munmap
+  :: Ptr () -> CSize -> IO CInt
+
+c'PROT_EXEC = 4
+c'PROT_NONE = 0
+c'PROT_READ = 1
+c'PROT_WRITE = 2
+c'MAP_FIXED = 16
+c'MAP_PRIVATE = 2
+c'MAP_SHARED = 1
+c'MAP_FAILED = wordPtrToPtr 4294967295
+
+        
diff --git a/src/System/RedPitaya/Tutorial.hs b/src/System/RedPitaya/Tutorial.hs
new file mode 100644
--- /dev/null
+++ b/src/System/RedPitaya/Tutorial.hs
@@ -0,0 +1,130 @@
+
+
+-- | 
+module System.RedPitaya.Tutorial (
+{-| 
+== tutorial for System.Readpitaya Libraray
+#tutorial-for-system.readpitaya-libraray#
+
+System.Readpitaya is native haskell library for
+<http://redpitaya.com/ redpitaya> that enables direct bindings on
+<https://github.com/RedPitaya/RedPitaya/blob/master/fpga/doc/RedPitaya_HDL_memory_map.odt?raw=true FPGA>.
+This library is aimed to run on redpitaya and is inteded for use with
+crosscompiler.
+
+To build and run code and examples you need cross-ghc compiler for armel
+processor.
+
+Here it is simpel an minimal example to use library
+
+> import System.RedPitaya.Fpga
+>
+> main = withOpenFpga (setLed 0x55) 
+
+withOpenFpga is function, that takes Fpga operation and executes it. It
+handels opening and closing of FPGA resources so it is advisable that
+that all operation are executed inside and @withOpenFpga@ gets called
+only once.
+
+If you take look of prototype setLed you can see that it has protype
+@setLed :: Registry -> Fpga ()@ And that can be understand that it takes
+@Registy@ (that is 32 bit unsigned integer) and returns @Fpga ()@.
+@Fpga a@ is type that can run in @withOpenFpga@ function. @()@ is empty
+or void value that is retured after @setLed@ gets called. What @setLed@
+does it takes writes registry value at apropriate addres in fpga
+registry map described in document FPGA metioned in first section.
+
+In our next example we will build program that displays value that is
+written in this registry using function @getLed@
+
+> import System.RedPitaya.Fpga
+> import Numeric (showHex)
+>
+> main = do
+>     reg <- withOpenFpga getLed
+>     putStrLn ( show reg)
+
+here @reg@ is value can get \"get\" from @withOpenFpga@. Function
+@withOpenFpga@ has prototype of \'Fpga a -> IO a\'. That mean that
+returns same value as it is returned from executing last command
+executed in block. In our case that is just function @getLed@. Since
+@getLed :: Fpga Registry@ that mean that ir returns @Fpga Registry@
+type.
+
+@IO Registry@ (@a@ in definition of @withOpenFpga@ becomes @Registry@).
+We haven\'t mentioned @IO a@ before but that is type one can execute
+commands like @putStrLn@ with.
+
+> import System.RedPitaya.Fpga
+> import Numeric (showHex)
+>
+> main = do
+>     reg <- withOpenFpga ( do
+>                             setLed 0x44
+>                             r <- getLed
+>                             return r
+>                         )
+>     putStrLn ( show reg )
+
+This code runs two @do@ blocks. One handles IO type where types @IO a@
+are running and other do block with type \'Fpga a\'. If one needs to run
+IO types inside Fpga block he\/she needs to change IO type to Fpga type
+using function liftIO.
+
+> import System.RedPitaya.Fpga
+> import Numeric (showHex)
+> import Control.Monad.IO.Class (liftIO)
+>
+> main = do
+>     withOpenFpga $ do
+>             setLed 0x44
+>             reg <- getLed 
+>             liftIO $ putStrLn $ show reg
+>     putStrLn "done"
+
+In this example we also use build in operator @$@ that works as a
+brackets to to the end.
+
+> liftIO $ putStrLn $ showHex reg "" 
+> -- is same as
+> liftIO ( putStrLn ( showHex reg "" ))
+
+If you like to know more about operator @$@ or any other standard
+functions used, you can use invaluable search engine
+<https://www.haskell.org/hoogle/?hoogle=%24 Hoogle> where is link on
+haddock manuals with description and link to source code. Similar search
+engines are also availabe at <http://hayoo.fh-wedel.de/ Hayoo!> and
+<https://www.stackage.org/ Stackage>.
+
+Lets do some more tricks with diodes and using standard
+
+> import System.RedPitaya.Fpga
+> import Control.Concurrent (threadDelay)
+> import Data.Bits
+> import Control.Monad.IO.Class (liftIO)
+>
+> knightRider n = do
+>     let ledn = 1 + abs ((mod n 12) - 6) -- 6,5,4,3,2,1,2,3,4,5,6,7,6,5,4,3,2,1,2,3,4,5,6,7,6,5...
+>     setLed ( shiftL 1 ledn )
+>     liftIO ( threadDelay (30000) )
+>     knightRider (n + 1)
+>
+> main = withOpenFpga (knightRider 0)
+
+@knightRider@ is function that gets caled each time with next
+integer.@ledn@ in generated in way that provides numbering in apropriate
+order. shiftL function . Next @threadDelay@ delays execution, by 30000
+microseconds and since @nightRider@ runs inside @withOpenFpga@ we have
+to use @liftIO@ just to make type compatible. Finaly we call
+@nightRider@ with next number and whole procees repeats.
+
+So far we covered lot if of stuff on how to use this library. Even
+though all examples were reading and writing to led registry you can be
+sure that all function provided by library that has type signature
+@Registry -> Fpga ()@ works and can be used just like @setLed@ and all
+functions with type signature @Fpga Registry@ works like getLed.
+
+-} 
+)
+where
+import System.RedPitaya.Fpga
