-------------------------------------------------------------------------------
-- |
-- Module      :  System.Hardware.Arduino.SamplePrograms.Pulse
-- Copyright   :  (c) Levent Erkok
-- License     :  BSD3
-- Maintainer  :  erkokl@gmail.com
-- Stability   :  experimental
--
-- Demonstrates 'pulseIn_hostTiming' and 'pulseOut_hostTiming' functions, sending
-- and receiving pulses to/from the board.
-------------------------------------------------------------------------------

module System.Hardware.Arduino.SamplePrograms.Pulse where

import Control.Monad       (forever)
import Control.Monad.Trans (liftIO)

import System.Hardware.Arduino

-------------------------------------------------------------------------------
-- * Detecting pulses
-------------------------------------------------------------------------------

-- | Computes the amount of time a push-button is connected to
-- input pin 2 on the Arduino. We will wait for at most 5 seconds,
-- as a further demonstration of the time-out facility. Note that the
-- timing is done on the host side, so this measurement is inherently
-- inaccurate.
--
-- The wiring is straightforward: Simply put a push-button between
-- digital input 2 and +5V, guarded by a 10K resistor:
--
--  <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/PulseIn.png>>
pulseInDemo :: IO ()
pulseInDemo = withArduino False "/dev/cu.usbmodemFD131" $ do
               setPinMode pb INPUT
               go
 where pb = digital 2
       go = forever $ do
              liftIO $ putStr "Ready, push-and-hold for less than 5 seconds: "
              mbDur <- pulseIn_hostTiming pb True (Just 5000000)
              liftIO $ putStrLn $ case mbDur of
                Nothing -> "Time out!"
                Just d  -> "Button stayed high for: " ++ show d ++ " micro-seconds"

-------------------------------------------------------------------------------
-- * Sending pulses
-------------------------------------------------------------------------------

-- | Send pulses on a led as requested by the user. Note that the timing is computed
-- on the host side, thus the duration of the pulse is subject to some error due to
-- the Firmata communication overhead.
--
-- Wiring: Simply a led on pin 13:
--
--  <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/Blink.png>>
pulseOutDemo :: IO ()
pulseOutDemo = withArduino False "/dev/cu.usbmodemFD131" $ do
              setPinMode led  OUTPUT
              digitalWrite led False
              forever trigger
 where led  = digital 13
       trigger = do liftIO $ putStr "Pulse duration? (microseconds) "
                    d <- liftIO getLine
                    case reads d of
                     [(v, "")] -> pulseOut_hostTiming led True 0 v
                     _         -> liftIO $ putStrLn "Please enter a number."