hArduino-1.2: System/Hardware/Arduino/SamplePrograms/SevenSegment.hs
-------------------------------------------------------------------------------
-- |
-- Module : System.Hardware.Arduino.SamplePrograms.SevenSegment
-- Copyright : (c) Levent Erkok
-- License : BSD3
-- Maintainer : erkokl@gmail.com
-- Stability : experimental
--
-- Control a single seven-segment display, echoing user's key presses
-- on it verbatim. We use a shift-register to reduce the number of
-- pins we need on the Arduino to control the display.
-------------------------------------------------------------------------------
module System.Hardware.Arduino.SamplePrograms.SevenSegment where
import Control.Monad (forever)
import Control.Monad.Trans (liftIO)
import Data.Bits (testBit)
import Data.Word (Word8)
import System.IO (hSetBuffering, stdin, BufferMode(NoBuffering))
import System.Hardware.Arduino
import System.Hardware.Arduino.Parts.ShiftRegisters
import System.Hardware.Arduino.Parts.SevenSegmentCodes
-- | Connections for the Texas Instruments 74HC595 shift-register. Datasheet: <http://www.ti.com/lit/ds/symlink/sn74hc595.pdf>.
-- In our circuit, we merely use pins 8 thru 12 on the Arduino to control the 'serial', 'enable', 'rClock', 'sClock', and 'nClear'
-- lines, respectively. Since we do not need to read the output of the shift-register, we leave the 'mbBits' field unconnected.
sr :: SR_74HC595
sr = SR_74HC595 { serial = digital 8
, nEnable = digital 9
, rClock = digital 10
, sClock = digital 11
, nClear = digital 12
, mbBits = Nothing
}
-- | Seven-segment display demo. For each key-press, we display an equivalent pattern
-- on the connected 7-segment-display. Note that most characters are not-mappable, so
-- we use approximations if available. We use a shift-register to reduce the pin
-- requirements on the Arduino, setting the bits serially.
--
-- Parts:
--
-- * The seven-segment digit we use is a common-cathode single-digit display, such as
-- TDSG5150 (<http://www.vishay.com/docs/83126/83126.pdf>), or Microvity's IS121,
-- but almost any such digit would do. Just pay attention to the line-connections,
-- and do not forget the limiting resistors: 220 ohm's should do nicely.
--
-- * The shift-register is Texas-Instruments 74HC595: <http://www.ti.com/lit/ds/symlink/sn74hc595.pdf>.
-- Make sure to connect the register output lines to the seven-segment displays with the corresponding
-- letters. That is, shift-registers @Q_A@ (Chip-pin 15) should connect to segment @A@; @Q_B@ (Chip-pin 1)
-- to segment @B@, and so on. We do not use the shift-register @Q_H'@ (Chip-pin 9) in this design.
--
-- <<http://github.com/LeventErkok/hArduino/raw/master/System/Hardware/Arduino/SamplePrograms/Schematics/SevenSegment.png>>
sevenSegment :: IO ()
sevenSegment = withArduino False "/dev/cu.usbmodemFD131" $ do
initialize sr
liftIO $ do hSetBuffering stdin NoBuffering
putStrLn "Seven-Segment-Display demo."
putStrLn "For each key-press, we will try to display it as a 7-segment character."
putStrLn "If there is no good mapping (which is common), we'll just display a dot."
putStrLn ""
putStrLn "Press-keys to be shown on the display, Ctrl-C to quit.."
forever repl
where pushWord w = do mapM_ (push sr) [w `testBit` i | i <- [0..7]]
store sr
repl = do c <- liftIO getChar
case char2SS c of
Just w -> pushWord w
Nothing -> pushWord (0x01::Word8) -- the dot, which also nicely covers the '.'