diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,5 @@
+Copyright (c) 2013, Levent Erkok (erkokl@gmail.com)
+All rights reserved.
+
+The usbArduino program is distributed with the BSD3 license. See the LICENSE file
+for details.
diff --git a/INSTALL b/INSTALL
new file mode 100644
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,9 @@
+The usbArduino library can be installed simply by issuing cabal install
+like this:
+
+     cabal install sbv
+
+The package depends on the usb library itself, which in turn relies on
+the availability of the libusb package on your platform. See notes
+at https://github.com/basvandijk/bindings-libusb for details on how
+to get the latter.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+usbArduino: Communicate with your Arduino board over USB
+
+Copyright (c) 2013, Levent Erkok (erkokl@gmail.com)
+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 the developer (Levent Erkok) nor the
+      names of its 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 LEVENT ERKOK 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 b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,1 @@
+Please see http://leventerkok.github.com/hArduino.
diff --git a/RELEASENOTES b/RELEASENOTES
new file mode 100644
--- /dev/null
+++ b/RELEASENOTES
@@ -0,0 +1,11 @@
+Hackage: http://hackage.haskell.org/package/hArduino
+GitHub:  http://leventerkok.github.com/hArduino 
+
+Latest Hackage released version: 0.1
+
+======================================================================
+Version 0.1, 2013-01-14
+
+ - Initial design
+ - Blink example operational
+ - Home page at: http://leventerkok.github.com/hArduino 
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/System/Hardware/Arduino.hs b/System/Hardware/Arduino.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino.hs
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- (The hArduino library is hosted at <http://leventerkok.github.com/hArduino/>.
+-- Comments, bug reports, and patches are always welcome.)
+--
+-- hArduino: Control Arduino from Haskell, using the Firmata protocol.
+--
+-- The hArduino library allows construction of Haskell programs that control
+-- Arduino boards that are running the (freely available) Firmata program. Note
+-- that hArduino does /not/ allow you to run arbitrary Haskell code on the
+-- Arduino! It simply allows you to control a board from Haskell, where you
+-- can exchange information with the board, send/receive commands from other
+-- peripherals connected, etc.
+-------------------------------------------------------------------------------
+module System.Hardware.Arduino (
+  -- * Running the controller
+  withArduino, Arduino
+  -- * Programming the Arduino
+  -- ** Basic handshake with the board
+  , queryFirmware
+  -- ** Controlling the pins
+  , setPinMode
+  -- ** Reading and Writing digital values
+  , digitalRead, digitalWrite
+  -- ** Misc utilities
+  , delay
+  -- * Hardware components on the board
+  -- ** Pins
+  , pin, PinMode(..)
+ )
+ where
+
+import System.Hardware.Arduino.Data
+import System.Hardware.Arduino.Comm
+import System.Hardware.Arduino.Firmata
+import System.Hardware.Arduino.Parts
diff --git a/System/Hardware/Arduino/Comm.hs b/System/Hardware/Arduino/Comm.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Comm.hs
@@ -0,0 +1,84 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Comm
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Basic serial communication routines
+-------------------------------------------------------------------------------
+
+{-# LANGUAGE NamedFieldPuns #-}
+module System.Hardware.Arduino.Comm where
+
+import Control.Monad.State (modify, runStateT, when)
+
+import qualified Data.ByteString            as B (pack, unpack, concat, length)
+import qualified System.Hardware.Serialport as S (withSerial, defaultSerialSettings, CommSpeed(CS57600), commSpeed, recv, send)
+
+import System.Hardware.Arduino.Data
+import System.Hardware.Arduino.Utils
+import System.Hardware.Arduino.Protocol
+import System.Hardware.Arduino.Firmata
+
+-- | Run the Haskell program to control the board:
+--
+--    * The file path argument should point to the device file that is
+--      associated with the board. ('COM1' on Windows,
+--      '/dev/cu.usbmodemfd131' on Mac, etc.)
+--
+--    * The boolean argument controls verbosity. It should remain
+--      'False' unless you have communication issues. The print-out
+--      is typically less-than-useful, but it might point to the root
+--      cause of the problem.
+--
+-- See "System.Hardware.Arduino.Examples.Blink" for a simple example.
+withArduino :: Bool       -- ^ If 'True', debugging info will be printed
+            -> FilePath   -- ^ Path to the USB port
+            -> Arduino () -- ^ The Haskell controller program to run
+            -> IO ()
+withArduino verbose fp program =
+        do debugger <- mkDebugPrinter verbose
+           debugger $ "Accessing arduino located at: " ++ show fp
+           let Arduino controller = do (v1, v2, m) <- queryFirmware
+                                       modify (\b -> b{firmataID = "Firmware v" ++ show v1 ++ "." ++ show v2 ++ "(" ++ m ++ ")"})
+                                       program
+           S.withSerial fp S.defaultSerialSettings{S.commSpeed = S.CS57600} $ \port -> do
+                _ <- runStateT controller (mkState debugger port)
+                return ()
+ where mkState debugger port = ArduinoState debugger port "ID: Uninitialized" (Just (ArduinoChannel recvChan recvNChan sendChan))
+        where extract b = do let resp = unpackage b
+                             debugger $ "Received: " ++ show resp
+                             return resp
+              recvChan = do debugger "Waiting for a Sysex response.."
+                            let skip = do b <- S.recv port 1
+                                          case B.unpack b of
+                                            []     -> skip
+                                            [0xF0] -> return ()
+                                            bs     -> do debugger $ "Skipping bytes <" ++ unwords (map showByte bs) ++ ">"
+                                                         skip
+                                collect sofar = do b <- S.recv port 1
+                                                   let rmsg = b : sofar
+                                                   if b == B.pack [0xF7] -- end message
+                                                      then return $ reverse rmsg
+                                                      else collect rmsg
+                            skip
+                            chunks <- collect [B.pack [0xF0]]
+                            extract $ B.concat chunks
+              recvNChan n = do debugger $ "Waiting for a non-Sysex response of " ++ show n ++ " bytes"
+                               let go need sofar
+                                    | need <= 0  = return sofar
+                                    | True       = do b <- S.recv port need
+                                                      case B.length b of
+                                                        0 -> go need sofar
+                                                        l -> do when (need < l) $ debugger $ "Received partial response: <" ++ unwords (map showByte (B.unpack b)) ++ ">"
+                                                                go (need - l) (b : sofar)
+                               chunks <- go n []
+                               extract $ B.concat $ reverse chunks
+              sendChan msg = do let p  = package msg
+                                    lp = B.length p
+                                debugger $ "Sending: " ++ show msg ++ " <" ++ unwords (map showByte (B.unpack p)) ++ ">"
+                                sent <- S.send port p
+                                when (sent /= lp)
+                                     (debugger $ "Send failed. Tried: " ++ show lp ++ "bytes, reported: " ++ show sent)
diff --git a/System/Hardware/Arduino/Data.hs b/System/Hardware/Arduino/Data.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Data.hs
@@ -0,0 +1,65 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Data
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Underlying data structures
+-------------------------------------------------------------------------------
+
+{-# LANGUAGE DeriveFunctor               #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving  #-}
+{-# LANGUAGE NamedFieldPuns              #-}
+module System.Hardware.Arduino.Data where
+
+import Control.Monad.State              (StateT, MonadIO, MonadState, gets, liftIO)
+import Data.Maybe                       (fromMaybe)
+import System.Hardware.Serialport       (SerialPort)
+
+import System.Hardware.Arduino.Protocol
+
+-- | Basic communication channel with the board.
+data ArduinoChannel = ArduinoChannel {
+                  recvChan  :: IO Response              -- ^ Receive a sys-ex response.
+                , recvNChan :: Int -> IO Response       -- ^ Receive a non-sys-ex response that has /n/ bytes in it
+                , sendChan  :: Request -> IO ()         -- ^ Send a request down to Arduino
+                }
+
+-- | State of the board and other machinery.
+data ArduinoState = ArduinoState {
+                message       :: String -> IO ()        -- ^ Current debugging routine
+              , port          :: SerialPort             -- ^ Port we are communicating on
+              , firmataID     :: String                 -- ^ The ID of the board (as identified by the Board itself)
+              , deviceChannel :: Maybe ArduinoChannel   -- ^ Communication channel
+              }
+
+-- | The Arduino monad.
+newtype Arduino a = Arduino (StateT ArduinoState IO a)
+                  deriving (Functor, Monad, MonadIO, MonadState ArduinoState)
+
+-- | Retrieve the current channel.
+getChannel :: Arduino ArduinoChannel
+getChannel = fromMaybe die `fmap` gets deviceChannel
+  where die = error "Cannot communicate with the board!"
+
+-- | Send down a request.
+send :: Request -> Arduino ()
+send r = do ArduinoChannel{sendChan} <- getChannel
+            liftIO $ sendChan r
+
+-- | Receive a sys-ex response.
+recv :: Arduino Response
+recv = do ArduinoChannel{recvChan} <- getChannel
+          liftIO recvChan
+
+-- | Receive a non-sys-ex response, that has /n/ bytes
+recvN :: Int -> Arduino Response
+recvN n = do ArduinoChannel{recvNChan} <- getChannel
+             liftIO $ recvNChan n
+
+-- | Debugging only: print it on stdout.
+debug :: String -> Arduino ()
+debug s = do f <- gets message
+             liftIO $ f s
diff --git a/System/Hardware/Arduino/Examples/Blink.hs b/System/Hardware/Arduino/Examples/Blink.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Examples/Blink.hs
@@ -0,0 +1,33 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Examples.Blink
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- The /hello world/ of the arduino world, blinking the led.
+-------------------------------------------------------------------------------
+
+module System.Hardware.Arduino.Examples.Blink where
+
+import Control.Monad           (forever)
+import Control.Monad.Trans     (liftIO)
+import System.Hardware.Arduino
+
+-- | Blink the led connected to port 13 on the Arduino UNO board.
+-- The blinking will synchronize with the printing of a dot on stdout.
+--
+-- Depending on your set-up, you will need to change the path to the
+-- USB board. If you have problems, try changing the first argument
+-- to 'True' in the call to 'withArduino', which will hopefully print
+-- a useful diagnostic message.
+blink :: IO ()
+blink = withArduino False "/dev/cu.usbmodemfd131" $ do
+           let led = pin 13
+           setPinMode led OUTPUT
+           forever $ do liftIO $ putStr "."
+                        digitalWrite led True
+                        delay 1000
+                        digitalWrite led False
+                        delay 1000
diff --git a/System/Hardware/Arduino/Firmata.hs b/System/Hardware/Arduino/Firmata.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Firmata.hs
@@ -0,0 +1,16 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Firmata
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- The Firmata protocol, as implemented in Haskell.
+-- See: www.firmata.org
+-------------------------------------------------------------------------------
+module System.Hardware.Arduino.Firmata
+  (module System.Hardware.Arduino.Firmata.Basics)
+  where
+
+import System.Hardware.Arduino.Firmata.Basics
diff --git a/System/Hardware/Arduino/Firmata/Basics.hs b/System/Hardware/Arduino/Firmata/Basics.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Firmata/Basics.hs
@@ -0,0 +1,65 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Firmata.Basics
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Basic components of the firmata protocol
+-------------------------------------------------------------------------------
+
+{-# LANGUAGE NamedFieldPuns #-}
+module System.Hardware.Arduino.Firmata.Basics where
+
+import Control.Monad.Trans (liftIO)
+import Data.Word           (Word8)
+import Data.Bits           (shiftL)
+
+import System.Hardware.Arduino.Data
+import System.Hardware.Arduino.Parts
+import System.Hardware.Arduino.Protocol
+import qualified System.Hardware.Arduino.Utils as U
+
+-- | Retrieve the Firmata firmware version running on the Arduino. The first
+-- component is the major, second is the minor. The final value is a human
+-- readable identifier for the particular board.
+queryFirmware :: Arduino (Word8, Word8, String)
+queryFirmware = do
+        send QueryFirmware
+        r <- recv
+        case r of
+          Firmware v1 v2 m -> return (v1, v2, m)
+          _                -> error $ "Got unexpected response for query firmware call: " ++ show r
+
+-- | Delay the computaton for a given number of milli-seconds.
+delay :: Int -> Arduino ()
+delay = liftIO . U.delay
+
+-- | Set the mode on a particular pin on the board.
+setPinMode :: Pin -> PinMode -> Arduino ()
+setPinMode p m = send $ SetPinMode p m
+
+-- | Read the value of a pin in digital mode.
+digitalRead :: Pin -> Arduino (PinMode, Bool)
+digitalRead p = do
+        send $ DigitalRead p
+        r <- recv
+        case r of
+          DigitalPinState p' m b -> if p == p'
+                                    then return (m, b)
+                                    else error $ "Got unexpected response for " ++ show p' ++ " instead of " ++ show p
+          _                -> error $ "Got unexpected response for query DigitalRead: " ++ show r
+
+-- | Set or clear a particular digital pin on the board.
+digitalWrite :: Pin -> Bool -> Arduino ()
+digitalWrite p v = do
+        let (port, idx) = pinPort p
+            dr n
+             | n > 2 && n < 14 = digitalRead (pin n)
+             | True            = return (OUTPUT, False)
+        oldVal <- map snd `fmap` mapM dr [port * 8 + i | i <- [0 .. 7]]
+        let [b0, b1, b2, b3, b4, b5, b6, b7] = [if i == idx then v else old | (old, i) <- zip oldVal [0 ..]]
+            lsb = sum [1 `shiftL` i | (True, i) <- zip [b0, b1, b2, b3, b4, b5, b6, False] [0 .. 7]]
+            msb = if b7 then 1 else 0
+        send $ DigitalPortWrite port lsb msb
diff --git a/System/Hardware/Arduino/Parts.hs b/System/Hardware/Arduino/Parts.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Parts.hs
@@ -0,0 +1,45 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Firmata.Parts
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Basic Arduino hardware abstractions, pins etc.
+-------------------------------------------------------------------------------
+
+module System.Hardware.Arduino.Parts(PinMode(..), Pin, pin, pinNo, pinPort) where
+
+-- | A pin on the Arduino
+data Pin = Pin { pinNo :: Int   -- ^ The pin number
+               }
+         deriving Eq
+
+instance Show Pin where
+  show p | i < 10 = "Pin0" ++ show i
+         | True   = "Pin"  ++ show i
+   where i = pinNo p
+
+-- | Smart constructor for a pin. The input should be between 1 and 13:
+--
+--     * Pins 0-1 are reserved for TX/RX; so can't be directly used.
+--
+--     * 13 pins is UNO specific, we will need to expand this definition if
+--       we start supporting other boards.
+pin :: Int -> Pin
+pin i | i < 2 || i > 13 = error $ "Invalid pin number: " ++ show i
+      | True            = Pin i
+
+-- | On the Arduino, pins are grouped into banks of 8.
+-- Given a pin, this function determines which port/index it belongs to
+pinPort :: Pin -> (Int, Int)
+pinPort p = pinNo p `quotRem` 8
+
+-- | The mode for a pin.
+data PinMode = INPUT
+             | OUTPUT
+             | ANALOG
+             | PWM
+             | SERVO
+             deriving (Show, Enum)
diff --git a/System/Hardware/Arduino/Protocol.hs b/System/Hardware/Arduino/Protocol.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Protocol.hs
@@ -0,0 +1,97 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Protocol
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Internal representation of the firmata protocol.
+-------------------------------------------------------------------------------
+
+module System.Hardware.Arduino.Protocol(Request(..), Response(..), package, unpackage) where
+
+import Data.Bits ((.|.), (.&.), shiftL)
+import Data.Char (chr)
+import Data.List (intercalate)
+import Data.Word (Word8, Word16)
+
+import qualified Data.ByteString as B
+
+import System.Hardware.Arduino.Parts
+import System.Hardware.Arduino.Utils
+
+-- | A request, as sent to Arduino
+data Request = QueryFirmware                     -- ^ Query the Firmata version installed
+             | SetPinMode      Pin PinMode       -- ^ Set a pin to a particular mode
+             | DigitalRead     Pin               -- ^ Read the value of a given pin
+             | DigitalPortWrite Int Word8 Word8  -- ^ Write the values of pins on the given port; 2 bytes lo/hi
+
+instance Show Request where
+   show QueryFirmware            = "QueryFirmWare"
+   show (SetPinMode p m)         = "SetPinMode "   ++ show p ++ " to " ++ show m
+   show (DigitalRead p)          = "DigitalRead "  ++ show p
+   show (DigitalPortWrite p l h) = "DigitalWrite " ++ show p ++ " to " ++ showBin l ++ "_" ++ showBin h
+
+-- | A response, as returned from the Arduino
+data Response = Firmware  Word8 Word8 String       -- ^ Firmware version (maj/min and indentifier
+              | DigitalPinState Pin PinMode Bool   -- ^ State of a given pin
+              | DigitalPortState Int Word16        -- ^ State of a given port
+              | Unknown [Word8]                    -- ^ Represents messages currently unsupported
+
+instance Show Response where
+  show (Firmware majV minV n)  = "Firmware v" ++ show majV ++ "." ++ show minV ++ " (" ++ n ++ ")"
+  show (DigitalPinState p m v) = "DigitalPinState " ++ show p ++ "(" ++ show m ++ ") = " ++ if v then "HIGH" else "LOW"
+  show (DigitalPortState p w)  = "DigitalPortState " ++ show p ++ " = " ++ show w
+  show (Unknown bs)            = "Unknown [" ++ intercalate ", " (map showByte bs) ++ "]"
+
+-- | Marker for the start of a sys-ex message
+cdStart :: Word8
+cdStart = 0xf0
+
+-- | Marker for the end of a sys-ex message
+cdEnd :: Word8
+cdEnd   = 0xf7
+
+-- | Wrap a sys-ex message to be sent to the board
+sysEx :: [Word8] -> B.ByteString
+sysEx bs = B.pack $ cdStart : bs ++ [cdEnd]
+
+-- | Package a request as a sequence of bytes to be sent to the board
+-- using the Firmata protocol.
+package :: Request -> B.ByteString
+package QueryFirmware            = sysEx  [0x79]
+package (SetPinMode p m)         = B.pack [0xf4, fromIntegral (pinNo p), fromIntegral (fromEnum m)]
+package (DigitalRead p)          = sysEx  [0x6d, fromIntegral (pinNo p)]
+package (DigitalPortWrite p l m) = B.pack [0x90 .|. fromIntegral p, l, m]
+
+-- | Unpackage a series of bytes as received from the board into a Response
+unpackage :: B.ByteString -> Response
+unpackage inp
+  | length bs < 2 || head bs /= cdStart || last bs /= cdEnd
+  = Unknown bs
+  | True
+  = getResponse (init (tail bs))
+  where bs = B.unpack inp
+
+-- | Parse a response message. TBD: Use a proper (cereal based?) parser.
+getResponse :: [Word8] -> Response
+getResponse (rf : majV : minV : rest)
+  | rf == 0x79
+  = Firmware majV minV (getString rest)
+getResponse (pr : curPin : pinMode : pinState : [])
+  | pr == 0x6e
+  = DigitalPinState (pin (fromIntegral curPin)) (toEnum (fromIntegral pinMode)) (pinState /= 0)
+getResponse (dpr : vL : vH : [])
+  | dpr .&. 0xF0 == 0x90
+  = let port = fromIntegral (dpr .&. 0x0F)
+        w    = fromIntegral ((vH .&. 0x7F) `shiftL` 8) .|. fromIntegral (vL .&. 0x7F)
+    in DigitalPortState port w
+getResponse bs = Unknown bs
+
+-- | Turn a lo/hi encoded Arduino string constant into a Haskell string
+getString :: [Word8] -> String
+getString []         = ""
+getString [a]        = [chr (fromIntegral a)]  -- shouldn't happen, but no need to error out either
+getString (l:h:rest) = c : getString rest
+  where c = chr $ fromIntegral $ h `shiftL` 8 .|. l
diff --git a/System/Hardware/Arduino/Utils.hs b/System/Hardware/Arduino/Utils.hs
new file mode 100644
--- /dev/null
+++ b/System/Hardware/Arduino/Utils.hs
@@ -0,0 +1,52 @@
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  System.Hardware.Arduino.Utils
+-- Copyright   :  (c) Levent Erkok
+-- License     :  BSD3
+-- Maintainer  :  erkokl@gmail.com
+-- Stability   :  experimental
+--
+-- Internal utilities
+-------------------------------------------------------------------------------
+module System.Hardware.Arduino.Utils where
+
+import Control.Concurrent (threadDelay)
+import Control.Monad      (void)
+import Data.Char          (isAlphaNum, isAscii, isSpace, chr)
+import Data.IORef         (newIORef, readIORef, writeIORef)
+import Data.Word          (Word8)
+import System.Process     (system)
+import System.Info        (os)
+import Numeric            (showHex, showIntAtBase, showFFloat)
+
+-- | Delay (wait) for the given number of milli-seconds
+-- NB. The 'threadDelay' function is broken on Mac, see <http://hackage.haskell.org/trac/ghc/ticket/7299>
+-- Until there's a new GHC release that fixes this issue, we temporarily use system/sleep on Mac.
+delay :: Int -> IO ()
+delay n
+  | os == "darwin"
+  = void $ system $ "sleep " ++ showFFloat (Just 2) (fromIntegral n / (1000 :: Double)) ""
+  | True
+  = threadDelay (n*1000)
+
+-- | A simple printer that can keep track of sequence numbers. Used for debugging purposes.
+mkDebugPrinter :: Bool -> IO (String -> IO ())
+mkDebugPrinter False = return (const (return ()))
+mkDebugPrinter True  = do
+        cnt <- newIORef (1::Int)
+        let f s = do i <- readIORef cnt
+                     writeIORef cnt (i+1)
+                     putStrLn $ "[" ++ show i ++ "] hArduino: " ++ s
+        return f
+
+-- | Show a byte in a visible format.
+showByte :: Word8 -> String
+showByte i | isVisible = [c]
+           | i <= 0xf  = '0' : showHex i ""
+           | True      = showHex i ""
+  where c = chr $ fromIntegral i
+        isVisible = isAscii c && isAlphaNum c && isSpace c
+
+-- | Show a number as a binary value
+showBin :: (Integral a, Show a) => a -> String
+showBin n = showIntAtBase 2 (head . show) n ""
diff --git a/hArduino.cabal b/hArduino.cabal
new file mode 100644
--- /dev/null
+++ b/hArduino.cabal
@@ -0,0 +1,45 @@
+Name:          hArduino
+Version:       0.1
+Category:      Hardware
+Synopsis:      Control your Arduino board from Haskell.
+Description:   Control Arduino from Haskell, using the Firmata protocol.
+               .
+               The hArduino library allows construction of Haskell programs that control
+               Arduino boards that are running the (freely available) Firmata program. Note
+               that hArduino does /not/ allow you to run arbitrary Haskell code on the
+               Arduino! It simply allows you to control a board from Haskell, where you
+               can exchange information with the board, send/receive commands from other
+               peripherals connected, etc.
+               .
+               hArduino is work-in-progress. Comments, bug-reports, and patches are welcome.
+Copyright:     Levent Erkok, 2013
+License:       BSD3
+License-file:  LICENSE
+Stability:     Experimental
+Author:        Levent Erkok
+Homepage:      http://leventerkok.github.com/hArduino
+Bug-reports:   http://github.com/LeventErkok/hArduino/issues
+Maintainer:    Levent Erkok (erkokl@gmail.com)
+Build-Type:    Simple
+Cabal-Version: >= 1.14
+Extra-Source-Files: INSTALL, README, COPYRIGHT, RELEASENOTES
+
+source-repository head
+    type:       git
+    location:   git://github.com/LeventErkok/hArduino.git
+
+Library
+  default-language: Haskell2010
+  ghc-options     : -Wall
+-- NB. process is only needed for "sleep", since
+-- threaddelay is broken on Mac. See: http://hackage.haskell.org/trac/ghc/ticket/7299
+  Build-depends   : base  >= 4 && < 5, serialport, bytestring, mtl, process
+  Exposed-modules : System.Hardware.Arduino
+                  , System.Hardware.Arduino.Examples.Blink
+  Other-modules   : System.Hardware.Arduino.Comm
+                  , System.Hardware.Arduino.Data
+                  , System.Hardware.Arduino.Firmata
+                  , System.Hardware.Arduino.Firmata.Basics
+                  , System.Hardware.Arduino.Protocol
+                  , System.Hardware.Arduino.Parts
+                  , System.Hardware.Arduino.Utils
