fuyu-gpio-0.1.0.0: examples/02-button.hs
-- In this example we will learn how to handle a GPIO input line with edge event detection.
-- We configure internal pull-up bias, line debounce filtering, and edge detection (Rising & Falling),
-- using a user-space event buffer with 'userBufferCapacity 1' to read button press events.
module Main where
-- High-level resource brackets & exception handling.
-- I recommend a qualified import of 'Fuyu.GPIO.EdgeEvent', for example as Edge.
import Fuyu.GPIO
import qualified Fuyu.GPIO.EdgeEvent as Edge
-- Base & third-party libraries.
-- To have a clean output when we press Ctrl+c.
import Control.Exception (catch, throwIO, AsyncException(UserInterrupt))
import Control.Monad (forever)
myChipPath :: FilePath
myChipPath = "/dev/gpiochip0"
-- This constant defines the maximum duration 'waitEvents' will wait for an event.
-- (This timeout can also be configured as infinite or immediate).
fiveSecondsNs :: Edge.Timeout
fiveSecondsNs = Edge.Nanoseconds 5000000000
-- Do not confuse this with kernel ring buffer capacity. 'Capacity' refers to the user-space event buffer.
-- It is clamped between 1 and 1024, and must be constructed via 'userBufferCapacity'
-- (passing 0 defaults to 64).
myBufferCapacity :: Edge.Capacity
myBufferCapacity = Edge.userBufferCapacity 1
buttonOffset :: Offset
buttonOffset = Offset 257
buttonSettings :: Settings -> IO ()
buttonSettings stgs = do
setDirection stgs DirInput -- Configure line as input mode
setBias stgs BiasPullUp -- Enable internal pull-up resistor
-- (the physical button connects GND when pressed, driving the line to Inactive)
setDebouncePeriodUs stgs 20000 -- 20ms debounce period to filter out mechanical contact bounce without threadDelay
setEdgeDetection stgs EdgeBoth -- Listen for both Rising and Falling edge transitions
buttonWorker :: Request -> Edge.Buffer -> IO ()
buttonWorker req buf = do
res <- Edge.waitEvents req fiveSecondsNs
case res of
Edge.EventReady readyReq -> do
events <- Edge.readEvents readyReq buf -- Read events from user buffer (configured with capacity 1)
print events
Edge.TimeoutResult -> putStrLn "Timeout: No event was read" -- Printed after the 5-second wait timeout expires
main :: IO ()
main = runApp `catch` \exc -> case exc of
UserInterrupt -> putStrLn "\nLoop terminated successfully!"
other -> throwIO other
runApp :: IO ()
runApp = do
withChip myChipPath $ \chip -> do
withSettings $ \settings -> do
buttonSettings settings
withConfig $ \config -> do
addSettings config [buttonOffset] settings
withRequest chip Nothing config $ \request -> do
Edge.withBuffer myBufferCapacity $ \buffer -> do
putStrLn "Loop started: Press the button to generate events or Ctrl+C to exit"
forever (buttonWorker request buffer)