content: -------------------------------------------------------------------------------
  -- |
  -- Module      :  System.Hardware.Arduino.SamplePrograms.Counter
  -- Copyright   :  (c) Levent Erkok
  -- License     :  BSD3
  -- Maintainer  :  erkokl@gmail.com
  -- Stability   :  experimental
  --
  -- Demonstrates using two push-buttons to count up and down.
  -------------------------------------------------------------------------------
  
  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
  
  module System.Hardware.Arduino.SamplePrograms.Counter where
  
  import Control.Monad.Trans (liftIO)
  
  import System.Hardware.Arduino
  
  -- | Two push-button switches, controlling a counter value. We will increment
  -- the counter if the first one (@bUp@) is pressed, and decrement the value if the
  -- second one (@bDown@) is pressed. We also have a led connected to pin 13 (either use
  -- the internal or connect an external one), that we light up when the counter value
  -- is 0.
  --
  -- Wiring is very simple: Up-button connected to pin 4, Down-button connected
  -- to pin 2, and a led on pin 13.
  --
  --  <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/Counter.png>>
  counter :: IO ()
  counter = withArduino False "/dev/cu.usbmodemFD131" $ do
              setPinMode led   OUTPUT
              setPinMode bUp   INPUT
              setPinMode bDown INPUT
              update (0::Int)
   where bUp   = digital 4
         bDown = digital 2
         led   = digital 13
         update curVal = do
                  liftIO $ print curVal
                  digitalWrite led (curVal == 0)
                  ~[up, down] <- waitAnyHigh [bUp, bDown]
                  let newVal = case (up, down) of
                                 (True,  True)  -> curVal    -- simultaneous press
                                 (True,  False) -> curVal+1
                                 (False, True)  -> curVal-1
                                 (False, False) -> curVal    -- can't happen
                  update newVal
  