Browse Source

Added basic types that will be used to manage the digital clock

master
Peter J. Jones 4 years ago
parent
commit
95800766ce
4 changed files with 147 additions and 2 deletions
  1. 2
    0
      .gitignore
  2. 7
    2
      clockdown.cabal
  3. 67
    0
      src/Clockdown/Core/Digital/Display.hs
  4. 71
    0
      src/Clockdown/Core/Digital/Indicator.hs

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
/default.nix
/result

+ 7
- 2
clockdown.cabal View File

@@ -25,7 +25,10 @@ flag maintainer

--------------------------------------------------------------------------------
library
-- exposed-modules:
exposed-modules:
Clockdown.Core.Digital.Display
Clockdown.Core.Digital.Indicator

default-language: Haskell2010
hs-source-dirs: src
ghc-options: -Wall -fwarn-incomplete-uni-patterns
@@ -35,4 +38,6 @@ library
ghc-prof-options: -prof -auto-all

build-depends: base >= 4.7 && < 5.0
, hscurses >= 1.4 && < 1.5
, time >= 1.5 && < 1.6

-- , hscurses >= 1.4 && < 1.5

+ 67
- 0
src/Clockdown/Core/Digital/Display.hs View File

@@ -0,0 +1,67 @@
{-

This file is part of the package clockdown. It is subject to the
license terms in the LICENSE file found in the top-level directory of
this distribution and at git://pmade.com/clockdown/LICENSE. No part of
the clockdown package, including this file, may be copied, modified,
propagated, or distributed except according to the terms contained in
the LICENSE file.

-}

--------------------------------------------------------------------------------
-- | A digital display containing four seven-segment indicators.
module Clockdown.Core.Digital.Display
( Display (..)
, clock
, countDown
) where

--------------------------------------------------------------------------------
-- Library imports:
import Data.Time.LocalTime

--------------------------------------------------------------------------------
-- Local imports:
import Clockdown.Core.Digital.Indicator

--------------------------------------------------------------------------------
-- | Indicators are numbered from left to right.
data Display = Display
{ indicator0 :: Indicator
, indicator1 :: Indicator
, indicator2 :: Indicator
, indicator3 :: Indicator
}

--------------------------------------------------------------------------------
-- | Create a display suitable for showing a clock consisting of hours
-- and minutes. The indicators will read from left to right: @H H M M@.
clock :: TimeOfDay -> Display
clock t = display (todHour t) (todMin t)

--------------------------------------------------------------------------------
-- | Create a display to show the number of seconds remaining in a
-- count down timer. When there are more than sixth minutes remaining
-- the display will show hours and minutes. Otherwise it will show
-- minutes and seconds.
countDown :: Int -> Display
countDown n = if hh > 0 then display hh mm else display mm ss
where
hh = n `div` 3600
mm = (n `div` 60) - (hh * 60)
ss = n - (hh * 3600) - (mm * 60)

--------------------------------------------------------------------------------
-- | Generic display creator.
display :: Int -> Int -> Display
display l r = Display (indicator lTens) (indicator lOnes)
(indicator rTens) (indicator rOnes)
where
(lTens, lOnes) = splitNumber l
(rTens, rOnes) = splitNumber r

--------------------------------------------------------------------------------
-- | Split a number so that it can be displayed on two indicators.
splitNumber :: Int -> (Int, Int)
splitNumber n = (n `div` 10, n `mod` 10)

+ 71
- 0
src/Clockdown/Core/Digital/Indicator.hs View File

@@ -0,0 +1,71 @@
{-

This file is part of the package clockdown. It is subject to the
license terms in the LICENSE file found in the top-level directory of
this distribution and at git://pmade.com/clockdown/LICENSE. No part of
the clockdown package, including this file, may be copied, modified,
propagated, or distributed except according to the terms contained in
the LICENSE file.

-}

--------------------------------------------------------------------------------
-- | A single seven-segment indicator for a digital clock.
module Clockdown.Core.Digital.Indicator
( Indicator
, Segment (..)
, indicator
, testSegment
) where

--------------------------------------------------------------------------------
-- Library imports:
import Data.Bits
import Data.Word

--------------------------------------------------------------------------------
-- | An indicator (seven-segment display) is made up of segments
-- which "light up" in different arrangements in order to display a
-- single digit.
data Indicator = Indicator Word8 deriving (Show)

--------------------------------------------------------------------------------
-- | A segment represents a single bar (light) on a seven-segment
-- display. The segments are given names from characters A through G.
--
-- @
-- -- A --
-- | |
-- F B
-- | |
-- -- G --
-- | |
-- E C
-- | |
-- -- D --
-- @
data Segment = A | B | C | D | E | F | G deriving (Eq, Enum)

--------------------------------------------------------------------------------
-- | Create an indicator that represents the given integer. Only the numbers
-- 0 through 9 can be displayed. Numbers outside that range will be
-- drawn as an underscore.
indicator :: Int -> Indicator
indicator n =
Indicator $ case n of
0 -> 0x3f
1 -> 0x06
2 -> 0x5b
3 -> 0x4f
4 -> 0x66
5 -> 0x6d
6 -> 0x7d
7 -> 0x07
8 -> 0x7f
9 -> 0x6f
_ -> 0x10

--------------------------------------------------------------------------------
-- | Test to see if an indicator should be lit up.
testSegment :: Indicator -> Segment -> Bool
testSegment (Indicator bits) = testBit bits . fromEnum

Loading…
Cancel
Save