--------------------------------------------------------------------------------------------------- |-- 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 #-}moduleSystem.Hardware.Arduino.Parts.ShiftRegisters(-- * Shift register abstractionShiftRegister (..)-- * Supported shift-registers-- ** Texas Instruments 7HC595,SR_74HC595 (..))whereimportData.Foldable(forM_)importSystem.Hardware.Arduino importSystem.Hardware.Arduino.Data (die )-- | A shift-register class as supported by the hArduino library.classShiftRegister a where-- | Capacitysize ::a ->Int-- | Display namename ::a ->String-- | Data sheet (typically a URL)dataSheet ::a ->String-- | Initialize the shift-registerinitialize ::a ->Arduino ()-- | Disable the output, putting it into high-impedance statedisable ::a ->Arduino ()-- | Enable the output, getting it out of the high-impedance stateenable ::a ->Arduino ()-- | Clear the contentsclear ::a ->Arduino ()-- | Push a single bit down the shift-registerpush ::a ->Bool->Arduino ()-- | Store the pushed-in values in the storage registerstore ::a ->Arduino ()-- | Read the current value storedread ::a ->Arduino [Bool]-- | The Texas-Instruments 74HC595 8-bit shift register with 3-state-- outputs. Data sheet: <http://www.ti.com/lit/ds/symlink/sn74hc595.pdf>.---- 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.dataSR_74HC595 =SR_74HC595 {SR_74HC595 -> Pin serial ::Pin -- ^ Chip Pin: 14: Serial input,SR_74HC595 -> Pin nEnable ::Pin -- ^ Chip Pin: 13: Negated output-enable,SR_74HC595 -> Pin rClock ::Pin -- ^ Chip Pin: 12: Register clock, positive triggered,SR_74HC595 -> Pin sClock ::Pin -- ^ Chip Pin: 11: Serial clock, positive triggered,SR_74HC595 -> Pin nClear ::Pin -- ^ Chip Pin: 10: Negated clear-data,SR_74HC595 -> Maybe [Pin] mbBits ::Maybe[Pin ]-- ^ Chip Pins: 15, 1-7, and 8: Sequence of output bits, connect only if reading is necessary}instanceShiftRegister SR_74HC595 wheresize :: SR_74HC595 -> Int size SR_74HC595 _=Int 8name :: SR_74HC595 -> String name SR_74HC595 _=String "TI SR_74HC595"dataSheet :: SR_74HC595 -> String dataSheet SR_74HC595 _=String "http://www.ti.com/lit/ds/symlink/sn74hc595.pdf"initialize :: SR_74HC595 -> Arduino () initialize sr :: SR_74HC595 sr @SR_74HC595 {Pin nEnable :: Pin nEnable :: SR_74HC595 -> Pin nEnable ,Pin serial :: Pin serial :: SR_74HC595 -> Pin serial ,Pin rClock :: Pin rClock :: SR_74HC595 -> Pin rClock ,Pin sClock :: Pin sClock :: SR_74HC595 -> Pin sClock ,Pin nClear :: Pin nClear :: SR_74HC595 -> Pin nClear ,Maybe [Pin] mbBits :: Maybe [Pin] mbBits :: SR_74HC595 -> Maybe [Pin] mbBits }=doforall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_(Pin -> PinMode -> Arduino () `setPinMode` PinMode OUTPUT )[Pin nEnable ,Pin nClear ,Pin serial ,Pin rClock ,Pin sClock ]forall a. ShiftRegister a => a -> Arduino () clear SR_74HC595 sr forall a. ShiftRegister a => a -> Arduino () enable SR_74HC595 sr forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => t a -> (a -> m b) -> m () forM_Maybe [Pin] mbBits (forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_(Pin -> PinMode -> Arduino () `setPinMode` PinMode INPUT ))disable :: SR_74HC595 -> Arduino () disable SR_74HC595 {Pin nEnable :: Pin nEnable :: SR_74HC595 -> Pin nEnable }=Pin -> Bool -> Arduino () digitalWrite Pin nEnable Bool Trueenable :: SR_74HC595 -> Arduino () enable SR_74HC595 {Pin nEnable :: Pin nEnable :: SR_74HC595 -> Pin nEnable }=Pin -> Bool -> Arduino () digitalWrite Pin nEnable Bool Falseclear :: SR_74HC595 -> Arduino () clear SR_74HC595 {Pin nClear :: Pin nClear :: SR_74HC595 -> Pin nClear }=doPin -> Bool -> Arduino () digitalWrite Pin nClear Bool FalsePin -> Bool -> Arduino () digitalWrite Pin nClear Bool Truepush :: SR_74HC595 -> Bool -> Arduino () push SR_74HC595 {Pin serial :: Pin serial :: SR_74HC595 -> Pin serial ,Pin sClock :: Pin sClock :: SR_74HC595 -> Pin sClock }Bool b =forall a. Pin -> Arduino a -> Arduino a fallingEdge Pin sClock forall a b. (a -> b) -> a -> b $Pin -> Bool -> Arduino () digitalWrite Pin serial Bool b store :: SR_74HC595 -> Arduino () store SR_74HC595 {Pin rClock :: Pin rClock :: SR_74HC595 -> Pin rClock }=forall a. Pin -> Arduino a -> Arduino a fallingEdge Pin rClock (forall (m :: * -> *) a. Monad m => a -> m a return())read :: SR_74HC595 -> Arduino [Bool] read sr :: SR_74HC595 sr @SR_74HC595 {Maybe [Pin] mbBits :: Maybe [Pin] mbBits :: SR_74HC595 -> Maybe [Pin] mbBits }=caseMaybe [Pin] mbBits ofMaybe [Pin] Nothing->forall a. String -> [String] -> Arduino a die (forall a. ShiftRegister a => a -> String name SR_74HC595 sr forall a. [a] -> [a] -> [a] ++String ": Not configured for bit-reading")[String "Datasheet: "forall a. [a] -> [a] -> [a] ++forall a. ShiftRegister a => a -> String dataSheet SR_74HC595 sr ,String "Make sure to set the `bits' field when configuring"]Just[Pin] pins ->forall (t :: * -> *) (m :: * -> *) a b. (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) mapMPin -> Arduino Bool digitalRead [Pin] pins -- | Execute action, followed by a simulated falling edge on the given clockfallingEdge ::Pin ->Arduino a ->Arduino a fallingEdge :: forall a. Pin -> Arduino a -> Arduino a fallingEdge Pin clk Arduino a action =doa r <-Arduino a action Pin -> Bool -> Arduino () digitalWrite Pin clk Bool TruePin -> Bool -> Arduino () digitalWrite Pin clk Bool Falseforall (m :: * -> *) a. Monad m => a -> m a returna r