------------------------------------------------------------------------------------------------- -- | -- Module : System.Hardware.Arduino.Parts.ShiftRegisters -- Copyright : (c) Levent Erkok -- License : BSD3 -- Maintainer : erkokl@gmail.com -- Stability : experimental -- -- Abstractions for shift-register IC parts. ------------------------------------------------------------------------------------------------- {-# LANGUAGE NamedFieldPuns #-} module System.Hardware.Arduino.Parts.ShiftRegisters( -- * Shift register abstraction ShiftRegister(..) -- * Supported shift-registers -- ** Texas Instruments 7HC595 , SR_74HC595(..) ) where import Data.Foldable (forM_) import System.Hardware.Arduino import System.Hardware.Arduino.Data (die) -- | A shift-register class as supported by the hArduino library. class ShiftRegister a where -- | Capacity size :: a -> Int -- | Display name name :: a -> String -- | Data sheet (typically a URL) dataSheet :: a -> String -- | Initialize the shift-register initialize :: a -> Arduino () -- | Disable the output, putting it into high-impedance state disable :: a -> Arduino () -- | Enable the output, getting it out of the high-impedance state enable :: a -> Arduino () -- | Clear the contents clear :: a -> Arduino () -- | Push a single bit down the shift-register push :: a -> Bool -> Arduino () -- | Store the pushed-in values in the storage register store :: a -> Arduino () -- | Read the current value stored read :: a -> Arduino [Bool] -- | The Texas-Instruments 74HC595 8-bit shift register with 3-state -- outputs. Data sheet: . -- -- This is a versatile 8-bit shift-register with separate serial and register -- clocks, allowing shifting to be done while the output remains untouched. We -- model all control pins provided. Note that the enable and clear lines are -- negated. data SR_74HC595 = SR_74HC595 { serial :: Pin -- ^ Chip Pin: 14: Serial input , nEnable :: Pin -- ^ Chip Pin: 13: Negated output-enable , rClock :: Pin -- ^ Chip Pin: 12: Register clock, positive triggered , sClock :: Pin -- ^ Chip Pin: 11: Serial clock, positive triggered , nClear :: Pin -- ^ Chip Pin: 10: Negated clear-data , mbBits :: Maybe [Pin] -- ^ Chip Pins: 15, 1-7, and 8: Sequence of output bits, connect only if reading is necessary } instance ShiftRegister SR_74HC595 where size _ = 8 name _ = "TI SR_74HC595" dataSheet _ = "http://www.ti.com/lit/ds/symlink/sn74hc595.pdf" initialize sr@SR_74HC595{nEnable, serial, rClock, sClock, nClear, mbBits} = do mapM_ (`setPinMode` OUTPUT) [nEnable, nClear, serial, rClock, sClock] clear sr enable sr forM_ mbBits (mapM_ (`setPinMode` INPUT)) disable SR_74HC595{nEnable} = digitalWrite nEnable True enable SR_74HC595{nEnable} = digitalWrite nEnable False clear SR_74HC595{nClear} = do digitalWrite nClear False digitalWrite nClear True push SR_74HC595{serial, sClock} b = fallingEdge sClock $ digitalWrite serial b store SR_74HC595{rClock} = fallingEdge rClock (return ()) read sr@SR_74HC595{mbBits} = case mbBits of Nothing -> die (name sr ++ ": Not configured for bit-reading") [ "Datasheet: " ++ dataSheet sr , "Make sure to set the `bits' field when configuring" ] Just pins -> mapM digitalRead pins -- | Execute action, followed by a simulated falling edge on the given clock fallingEdge :: Pin -> Arduino a -> Arduino a fallingEdge clk action = do r <- action digitalWrite clk True digitalWrite clk False return r