hArduino-0.4: System/Hardware/Arduino/Parts/ShiftRegisters.hs
-------------------------------------------------------------------------------------------------
-- |
-- 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: <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.
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