diff --git a/Language/Atom.hs b/Language/Atom.hs
--- a/Language/Atom.hs
+++ b/Language/Atom.hs
@@ -1,24 +1,68 @@
 {- |
-  Atom is a Haskell DSL for designing hard realtime embedded software.
-  Based on guarded atomic actions (similar to STM), Atom enables highly
-  concurrent programming without the need for mutex locking.
-  In addition, Atom performs compile-time task scheduling and generates code
-  with deterministic execution time and constant memory use, simplifying the
-  process of timing verification and memory consumption in hard realtime
-  applications. Without mutex locking and run-time task scheduling,
-  Atom eliminates the need and overhead of RTOSs for many embedded applications.
+Module: Atom
+Description: Top-level Atom module
+Copyright: (c) 2013 Tom Hawkins & Lee Pike
+
+Atom is a Haskell DSL for designing hard realtime embedded software.
+
+Based on guarded atomic actions (similar to STM), Atom enables highly
+concurrent programming without the need for mutex locking.
+In addition, Atom performs compile-time task scheduling and generates code
+with deterministic execution time and constant memory use, simplifying the
+process of timing verification and memory consumption in hard realtime
+applications. Without mutex locking and run-time task scheduling,
+Atom eliminates the need and overhead of RTOSes for many embedded applications.
 -}
 
 module Language.Atom
-  ( module Language.Atom.Code
-  , module Language.Atom.Compile
-  , module Language.Atom.Common
-  , module Language.Atom.Language
-  -- , module Language.Atom.Unit
+  ( -- * Code 
+    -- | Module: "Language.Atom.Code" 
+    Config (..), defaults, Clock (..), defaultClock, writeC, cType, RuleCoverage,
+    -- * Compilation
+    -- | Module: "Language.Atom.Compile"
+    compile, reportSchedule, Schedule,
+    -- * Common
+    -- | Module: "Language.Atom.Common"
+    Timer, timer, startTimer, startTimerIf, timerDone, oneShotRise,
+    oneShotFall, debounce, lookupTable, linear, hysteresis, Channel (..),
+    channel, writeChannel, readChannel,
+    -- ** Signal fading
+    -- | Module: "Language.Atom.Common.Fader"
+    Fader, FaderInit (..), fader, fadeToA, fadeToB, fadeToCenter,
+    -- ** Thresholds
+    -- | Module: "Language.Atom.Common.Threshold"
+    boolThreshold, doubleThreshold,
+    -- ** Valid/Invalid data
+    -- | Module: "Language.Atom.Common.ValidData"
+    ValidData, validData, getValidData, whenValid, whenInvalid,
+    -- * Language & EDSL
+    -- | Module: "Language.Atom.Language"
+    Atom, atom, period, getPeriod, phase, exactPhase, getPhase, cond,
+    Assign (..), incr, decr, var, var', array, array', bool, bool', int8,
+    int8', int16, int16', int32, int32', int64, int64', word8, word8', word16,
+    word16', word32, word32', word64, word64', float, float', double, double',
+    action, call, probe, probes, assert, cover, assertImply, Name, liftIO,
+    path, clock, nextCoverage,
+    -- * Expressions
+    -- | Module: "Language.Atom.Expressions"
+    E(..), V(..), UE(..), UV(..), A(..), UA(..), Expr(..), Expression(..),
+    Variable(..), Type(..), Const(..), Width(..), TypeOf(..), bytes, ue, uv,
+    NumE, IntegralE, FloatingE, EqE, OrdE, true, false,
+    value, not_, (&&.), (||.), and_, or_, any_, all_, imply, (.&.), complement,
+    (.|.), xor, (.<<.), (.>>.), rol, ror, bitSize, isSigned, (==.), (/=.),
+    (<.), (<=.), (>.), (>=.), min_, minimum_, max_, maximum_, limit, div_,
+    div0_, mod_, mod0_, mux, (!), (!.), ubool, unot, uand, uor, ueq, umux,
+    -- * Testing
+    -- | Module: "Language.Atom.Unit"
+    Test(..), defaultTest, Random (..), runTests, printStrLn, printIntegralE,
+    printFloatingE, printProbe
   ) where
 
 import Language.Atom.Code
 import Language.Atom.Compile
 import Language.Atom.Common
+import Language.Atom.Common.Fader
+import Language.Atom.Common.Threshold
+import Language.Atom.Common.ValidData
 import Language.Atom.Language
--- import Language.Atom.Unit
+import Language.Atom.Unit
diff --git a/Language/Atom/Analysis.hs b/Language/Atom/Analysis.hs
--- a/Language/Atom/Analysis.hs
+++ b/Language/Atom/Analysis.hs
@@ -1,3 +1,8 @@
+-- | 
+-- Module: Analysis
+-- Description: -
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+
 module Language.Atom.Analysis
   ( topo
   , ruleComplexity
diff --git a/Language/Atom/Code.hs b/Language/Atom/Code.hs
--- a/Language/Atom/Code.hs
+++ b/Language/Atom/Code.hs
@@ -1,4 +1,10 @@
--- | Atom C code generation.
+-- | 
+-- Module: Code
+-- Description: C code configuration and generation
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Atom C code configuration and generation
+
 module Language.Atom.Code
   ( Config (..)
   , Clock (..)
@@ -24,57 +30,57 @@
 
 -- | C code configuration parameters.
 data Config = Config
-
-  { cFuncName     :: String -- ^ Alternative primary function name.  Leave empty
-                            -- to use compile name.
-  , cStateName    :: String -- ^ Name of state variable structure.  Default: state
-
-  , cCode         :: [Name] -> [Name] -> [(Name, Type)]
-                      -> (String, String)  -- ^ Custom C code to insert above
-                                           -- and below the functions, given
-                                           -- assertion names, coverage names,
-                                           -- and probe names and types.
-  , hCode         :: [Name] -> [Name] -> [(Name, Type)]
-                      -> (String, String)  -- ^ Custom C code to insert above
-                                           -- and below the state definition
-                                           -- in the header file, given assertion
-                                           -- names, coverage names, and probe names
-                                           -- and types.
-  , cRuleCoverage :: Bool -- ^ Enable rule coverage tracking.
-  , cAssert       :: Bool -- ^ Enable assertions and functional coverage.
-  , cAssertName   :: String -- ^ Name of assertion function.  Type: void
-                            -- assert(int, bool, uint64_t);
-  , cCoverName    :: String -- ^ Name of coverage function.  Type: void
-                            -- cover(int, bool, uint64_t);
-  , hardwareClock :: Maybe Clock -- ^ Do we use a hardware counter to schedule
-                                 -- rules?
+  { -- | Alternative primary function name.  If this is empty, then it will
+    -- default to the name passed to 'Language.Atom.Compile.compile'.
+    cFuncName     :: String
+    -- | Name of state variable structure. Default: @state@
+  , cStateName    :: String
+    -- | Custom C code to insert above and below the functions, given
+    -- assertion names, coverage names, and probe names and types.
+  , cCode         :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
+    -- | Custom C code to insert above and below the state definition in the
+    -- header file, given assertion names, coverage names, and probe names and
+    -- types.
+  , hCode         :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
+    -- | Enable rule coverage tracking.
+  , cRuleCoverage :: Bool
+    -- | Enable assertions and functional coverage.
+  , cAssert       :: Bool
+    -- | Name of assertion function. Prototype:
+    -- @void assert(int, bool, uint64_t);@
+  , cAssertName   :: String
+    -- | Name of coverage function. Prototype:
+    -- @void cover(int, bool, uint64_t);@
+  , cCoverName    :: String
+    -- | Hardware counter to schedule rules, or 'Nothing' (the default).
+  , hardwareClock :: Maybe Clock
   }
 
 -- | Data associated with sampling a hardware clock.  For the clock to work
--- correctly, you MUST assign @__global_clock@ the current time (accoring to
+-- correctly, you MUST assign @__global_clock@ the current time (according to
 -- @clockName@) the first time you enter the main Atom-generated function
 -- calling your rules.
 data Clock = Clock
-
-  { clockName  :: String        -- ^ C function to sample the clock.  The
-                                -- funciton is assumed to have the prototype
-                                -- @clockType clockName(void)@.
-  , clockType  :: Type          -- ^ Clock type.  Assumed to be one of Word8,
-                                -- Word16, Word32, or Word64.  It is permissible
-                                -- for the clock to rollover.
-  , delta      :: Integer       -- ^ Number of ticks in a phase.  Must be greater than 0.
-  , delay      :: String        -- ^ C function to delay/sleep.  The function is
-                                -- assumed to have the prototype @void
-                                -- delay(clockType i)@, where @i@ is the
-                                -- duration of delay/sleep.
-  , err        :: Maybe String  -- ^ Nothing or a user-defined error-reporting
-                                -- function if the period duration is violated;
-                                -- e.g., the execution time was greater than
-                                -- @delta@.  Assumed to have prototype @void
-                                -- err(void)@.
+  { -- | C function to sample the clock.  The function is assumed to have the
+    -- prototype: @clockType clockName(void)@.
+    clockName  :: String
+    -- | Clock type.  Assumed to be one of 'Word8', 'Word16', 'Word32', or
+    -- 'Word64'.  It is permissible for the clock to roll over.
+  , clockType  :: Type
+    -- | Number of ticks in a phase.  Must be greater than 0.
+  , delta      :: Integer
+    -- | C function to delay/sleep.  The function is assumed to have the
+    -- prototype: @void delay(clockType i)@, where @i@ is the duration of
+    -- delay/sleep.
+  , delay      :: String
+    -- | 'Nothing', or a user-defined error-reporting function if the period
+    -- duration is violated, e.g., the execution time was greater than @delta@.
+    -- Assumed to have prototype: @void err(void)@.
+  , err        :: Maybe String
   }
 
--- | Default C code configuration parameters (default function name, no pre/post code, ANSI C types).
+-- | Default C code configuration parameters (default function name, no
+-- pre/post code, ANSI C types).
 defaults :: Config
 defaults = Config
   { cFuncName     = ""
@@ -88,8 +94,15 @@
   , hardwareClock = Nothing
   }
 
+-- | Default hardware clock parameters (name "@clk@", Word64, delta 1, delay
+-- function is "@delay@", no error function).
 defaultClock :: Clock
-defaultClock = Clock "clk" Word64 1 "delay" Nothing
+defaultClock = Clock { clockName = "clk"
+                     , clockType = Word64
+                     , delta = 1
+                     , delay = "delay"
+                     , err = Nothing
+                     }
 
 showConst :: Const -> String
 showConst c = case c of
@@ -397,7 +410,8 @@
 codeIf a b = if a then b else ""
 
 declState :: Bool -> StateHierarchy -> String
-declState define a' =
+declState define a' = if isHierarchyEmpty a' then ""
+  else
      (if define then "" else "extern ") ++ init (init (f1 "" a'))
   ++ (if define then " =\n" ++ f2 "" a' else "") ++ ";\n"
   where
@@ -417,6 +431,11 @@
     StateArray     name c     ->
          i ++ "/* " ++ name ++ " */\n" ++ i ++ "{ "
       ++ intercalate ("\n" ++ i ++ ", ") (map showConst c) ++ "\n" ++ i ++ "}"
+
+  isHierarchyEmpty h = case h of
+    StateHierarchy n i -> if null i then True else and $ map isHierarchyEmpty i
+    StateVariable n c -> False
+    StateArray n c -> False
 
 codeRule :: UeMap -> Config -> Rule -> String
 codeRule mp config rule@(Rule _ _ _ _ _ _ _) =
diff --git a/Language/Atom/Common.hs b/Language/Atom/Common.hs
--- a/Language/Atom/Common.hs
+++ b/Language/Atom/Common.hs
@@ -1,4 +1,10 @@
--- | Common Atom functions.
+-- | 
+-- Module: Common
+-- Description: Common functions.
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Common Atom functions
+
 module Language.Atom.Common
   (
   -- * Timers
@@ -17,6 +23,11 @@
   , linear
   -- * Hysteresis
   , hysteresis
+  -- * Channels
+  , Channel (..)
+  , channel
+  , writeChannel
+  , readChannel
   ) where
 
 import Data.Word
@@ -33,18 +44,23 @@
   return $ Timer timer'
 
 -- | Starts a Timer.  A timer can be restarted at any time.
-startTimer :: Timer -> E Word64 -> Atom ()
+startTimer :: Timer -- ^ Timer to start
+           -> E Word64 -- ^ Number of clock ticks the timer shall run
+           -> Atom ()
 startTimer t = startTimerIf t true
 
 -- | Conditionally start a Timer.
-startTimerIf :: Timer -> E Bool -> E Word64 -> Atom ()
+startTimerIf :: Timer -- ^ Timer to start conditionally
+             -> E Bool -- ^ Condition for starting the timer
+             -> E Word64 -- ^ Number of ticks the timer shall run
+             -> Atom ()
 startTimerIf (Timer t) a time = t <== mux a (clock + time) (value t)
 
--- | 'True' when a timer has completed.
+-- | 'True' when a timer has completed. Note that this remains 'True' until
+-- the timer is restarted.
 timerDone :: Timer -> E Bool
 timerDone (Timer t) = value t <=. clock
 
-
 -- | One-shot on a rising transition.
 oneShotRise :: E Bool -> Atom (E Bool)
 oneShotRise a = do
@@ -56,9 +72,13 @@
 oneShotFall :: E Bool -> Atom (E Bool)
 oneShotFall = oneShotRise . not_
 
-
 -- | Debounces a boolean given an on and off time (ticks) and an initial state.
-debounce :: Name -> E Word64 -> E Word64 -> Bool -> E Bool -> Atom (E Bool)
+debounce :: Name -- ^ Name of the resulting atom
+         -> E Word64 -- ^ On time in ticks
+         -> E Word64 -- ^ Off time in ticks
+         -> Bool -- ^ Initial value
+         -> E Bool -- ^ The boolean to debounce
+         -> Atom (E Bool) -- ^ Resulting debounced boolean
 debounce name onTime offTime init' a = atom name $ do
   lst  <- bool "last" init'
   out   <- bool "out"  init'
@@ -77,10 +97,11 @@
     out <== value lst
   return $ value out
 
-
--- | 1-D lookup table.  X values out of table range are clipped at end Y values.
---   Input table must be monotonically increasing in X.
-lookupTable :: FloatingE a => [(E a, E a)] -> E a -> E a
+-- | 1-D lookup table.  @x@ values out of table range are clipped at end @y@
+-- values.  Input table must be monotonically increasing in @x@.
+lookupTable :: FloatingE a => [(E a, E a)] -- ^ (@x@, @y@) lookup table
+               -> E a -- ^ Input @x@ value
+               -> E a -- ^ Output @y@ value
 lookupTable table x = mux (x >=. x1) y1 $ foldl f y0 table'
   where
   (_,  y0) = head table
@@ -92,19 +113,23 @@
     interp = (x - a0) * slope + b0
 
 -- | Linear extrapolation and interpolation on a line with 2 points.
---   The two x points must be different to prevent a divide-by-zero.
-linear :: FloatingE a => (E a, E a) -> (E a, E a) -> E a -> E a
+-- The two @x@ points must be different to prevent a divide-by-zero.
+linear :: FloatingE a => (E a, E a) -- ^ First point, (x1, y1)
+          -> (E a, E a) -- ^ Second point, (x2, y2)
+          -> E a -- ^ Input @x@ value
+          -> E a -- ^ Interpolated/extrapolated @y@ value
 linear (x1, y1) (x2, y2) a = slope * a + inter
   where
   slope = (y2 - y1) / (x2 - x1)
   inter = y1 - slope * x1
 
 -- | Hysteresis returns 'True' when the input exceeds @max@ and 'False' when
---   the input is less than @min@.  The state is held when the input is between
---   @min@ and @max@.
---
--- > hysteresis name min max input
-hysteresis :: OrdE a => E a -> E a -> E a -> Atom (E Bool)
+-- the input is less than @min@.  The state is held when the input is between
+-- @min@ and @max@.
+hysteresis :: OrdE a => E a -- ^ min
+              -> E a -- ^ max
+              -> E a -- ^ Input
+              -> Atom (E Bool)
 hysteresis a b u = do
   s <- bool "s" False
   s <== (mux (u >. max') true $ mux (u <. min') false $ value s)
@@ -113,94 +138,32 @@
   min' = min_ a b
   max' = max_ a b
 
-{-
-
--- | A channel is a uni-directional communication link that ensures one read for every write.
+-- | A channel is a uni-directional communication link that ensures one read
+-- for every write.
 data Channel a = Channel a (V Bool)
 
 -- | Creates a new channel, with a given name and data.
 channel :: a -> Atom (Channel a)
 channel a = do
-  hasData <- bool False
+  hasData <- bool "hasData" False
   return $ Channel a hasData
 
--- | Write data to a 'Channel'.  A write will only suceed if the 'Channel' is empty.
-writeChannel :: Channel a -> Action ()
+-- | Write data to a 'Channel'.  A write will only suceed if the 'Channel' is
+-- empty.
+writeChannel :: Channel a -> Atom ()
 writeChannel (Channel _ hasData) = do
-  when $ not_ $ value hasData
+  cond $ not_ $ value hasData
   hasData <== true
 
--- | Read data from a 'Channel'.  A read will only suceed if the 'Channel' has data to be read.
-readChannel :: Channel a -> Action a
+-- | Read data from a 'Channel'.  A read will only suceed if the 'Channel' has
+-- data to be read.
+readChannel :: Channel a -> Atom a
 readChannel (Channel a hasData) = do
-  when $ value hasData
+  cond $ value hasData
   hasData <== false
   return a
 
--- | Fades one signal to another.
-module Language.Atom.Common.Fader
-  ( Fader
-  , FaderInit (..)
-  , fader
-  , fadeToA
-  , fadeToB
-  , fadeToCenter
-  ) where
-
-import Language.Atom
-
--- | Fader object.
-data Fader = Fader (V Int)
-
--- | Fader initalization.
-data FaderInit = OnA | OnB | OnCenter
-
-toA = 0
-toB = 1
-toCenter = 2
-
--- | Fader construction.  Name, fade rate, fader init, and signal A and B.
-fader :: Name -> Double -> FaderInit -> E Double -> E Double -> Atom (Fader, E Double)
-fader name rate init a b = scope name $ do
-  --assert "positiveRate" $ rate >= 0
-
-  target <- int (case init of {OnA -> toA; OnB -> toB; OnCenter -> toCenter})
-  perA <- double (case init of {OnA -> 1;   OnB -> 0;   OnCenter -> 0.5})
-
-  rule "toA" $ do
-    when $ value target ==. intC toA
-    when $ value perA <. 1
-    perA <== mux (1 - value perA <. doubleC rate) 1 (value perA + doubleC rate)
-
-  rule "toB" $ do
-    when $ value target ==. intC toB
-    when $ value perA >. 0
-    perA <== mux (value perA <. doubleC rate) 0 (value perA - doubleC rate)
-
-  rule "toCenterFrom0" $ do
-    when $ value target ==. intC toCenter
-    when $ value perA <. 0.5
-    perA <== mux (0.5 - value perA <. doubleC rate) 0.5 (value perA + doubleC rate)
-
-  rule "toCenterFrom1" $ do
-    when $ value target ==. intC toCenter
-    when $ value perA >. 0.5
-    perA <== mux (value perA - 0.5 <. doubleC rate) 0.5 (value perA - doubleC rate)
-
-  return (Fader target, (a * value perA + b * (1 - value perA)) / 2)
-
--- | Fade to signal A.
-fadeToA :: Fader -> Action ()
-fadeToA (Fader target) = target <== intC toA
-
--- | Fade to signal B.
-fadeToB :: Fader -> Action ()
-fadeToB (Fader target) = target <== intC toB
-
--- | Fade to center, ie average of signal A and B.
-fadeToCenter :: Fader -> Action ()
-fadeToCenter (Fader target) = target <== intC toCenter
-
+{-
 module Language.Atom.Common.Process
   ( Process (..)
   , process
@@ -217,93 +180,4 @@
 
 process :: Name -> Process -> Atom ()
 
--- | Time integrated threshold functions typically used in condition monitoring.
-module Language.Atom.Common.Threshold
-  ( boolThreshold
-  , floatingThreshold
-  ) where
-
-import Language.Atom
-
-
--- | Boolean thresholding over time.  Output is set when internal counter hits limit, and cleared when counter is 0.
-boolThreshold :: Name -> Int -> Bool -> E Bool -> Atom (E Bool)
-boolThreshold name num init input = scope name $ do
-  --assert "positiveNumber" $ num >= 0
-
-  state <- bool init
-  count <- int  (if init then num else 0)
-
-  rule "update" $ do
-    when $ value count >. 0 &&. value count <. num
-    count <== value count + mux input 1 (-1)
-
-  rule "low" $ do
-    when $ value count ==. 0
-    state <== false
-
-  rule "high" $ do
-    when $ value count ==. intC num
-    state <== true
-
-  return $ value state
-
--- | Integrating threshold.  Output is set with integral reaches limit, and cleared when integral reaches 0.
-doubleThreshold :: Name -> Double -> E Double -> Atom (E Bool)
-doubleThreshold name lim input = scope name $ do
-  --assert "positiveLimit" $ lim >= 0
-
-  state <- bool False
-  sum <- double 0
-
-  (high,low) <- priority
-
-  rule "update"
-    sum <== value sum + input
-    low
-
-  rule "clear" $ do
-    when $ value sum <=. 0
-    state <== false
-    sum <== 0
-    high
-
-  rule "set" $ do
-    when $ value sum >=. doubleC lim
-    state <== true
-    sum <== doubleC lim
-    high
-
-  return  $ value state
-
--- | Capturing data that can either be valid or invalid.
-module Language.Atom.Common.ValidData
-  ( ValidData
-  , validData
-  , getValidData
-  , whenValid
-  , whenInvalid
-  ) where
-
-import Language.Atom
-
--- | 'ValidData' captures the data and its validity condition.
---   'ValidData' is abstract to prevent rules from using invalid data.
-data ValidData a = ValidData a (E Bool)
-
--- | Create 'ValidData' given the data and validity condition.
-validData :: a -> E Bool -> ValidData a
-validData = ValidData
-
--- | Get a valid data.  Action is disabled if data is invalid.
-getValidData :: ValidData a -> Action a
-getValidData (ValidData a v) = cond v >> return a
-
--- | Action enabled if 'ValidData' is valid.
-whenValid :: ValidData a -> Action ()
-whenValid (ValidData _ v) = cond v
-
--- | Action enabled if 'ValidData' is not valid.
-whenInvalid :: ValidData a -> Action ()
-whenInvalid (ValidData _ v) = cond $ not_ v
 -}
diff --git a/Language/Atom/Common/Fader.hs b/Language/Atom/Common/Fader.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Common/Fader.hs
@@ -0,0 +1,83 @@
+-- | 
+-- Module: Fader
+-- Description: Fades one signal to another
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Fades one signal to another.
+
+module Language.Atom.Common.Fader
+  ( Fader
+  , FaderInit (..)
+  , fader
+  , fadeToA
+  , fadeToB
+  , fadeToCenter
+  ) where
+
+import Language.Atom.Expressions
+import Language.Atom.Language
+import Data.Int (Int32)
+
+-- | Fader object.
+data Fader = Fader (V Int32)
+
+-- | Fader initalization.
+data FaderInit = OnA -- ^ Start at signal A
+               | OnB -- ^ Start at signal B
+               | OnCenter -- ^ Start at average of A and B
+
+toA, toB, toCenter :: Int32
+toA = 0
+toB = 1
+toCenter = 2
+
+-- | Fader construction
+fader :: Name -- ^ Name
+         -> Double -- ^ Fade rate
+         -> FaderInit -- ^ Initialization
+         -> E Double -- ^ Signal A
+         -> E Double -- ^ Signal B
+         -> Atom (Fader, E Double)
+fader name_ rate init_ a b = atom name_ $ do
+  --assert "positiveRate" $ rate >= 0
+
+  target <- int32 "target" $ case init_ of OnA -> toA
+                                           OnB -> toB
+                                           OnCenter -> toCenter
+  perA <- double "perA" $ case init_ of OnA -> 1
+                                        OnB -> 0
+                                        OnCenter -> 0.5
+
+  atom "toA" $ do
+    cond $ value target ==. Const toA
+    cond $ value perA <. 1
+    perA <== mux (1 - value perA <. Const rate) 1 (value perA + Const rate)
+
+  atom "toB" $ do
+    cond $ value target ==. Const toB
+    cond $ value perA >. 0
+    perA <== mux (value perA <. Const rate) 0 (value perA - Const rate)
+
+  atom "toCenterFrom0" $ do
+    cond $ value target ==. Const toCenter
+    cond $ value perA <. 0.5
+    perA <== mux (0.5 - value perA <. Const rate) 0.5 (value perA + Const rate)
+
+  atom "toCenterFrom1" $ do
+    cond $ value target ==. Const toCenter
+    cond $ value perA >. 0.5
+    perA <== mux (value perA - 0.5 <. Const rate) 0.5 (value perA - Const rate)
+
+  return (Fader target, (a * value perA + b * (1 - value perA)) / 2)
+
+-- | Fade to signal A.
+fadeToA :: Fader -> Atom ()
+fadeToA (Fader target) = target <== Const toA
+
+-- | Fade to signal B.
+fadeToB :: Fader -> Atom ()
+fadeToB (Fader target) = target <== Const toB
+
+-- | Fade to center, i.e. average of signal A and B.
+fadeToCenter :: Fader -> Atom ()
+fadeToCenter (Fader target) = target <== Const toCenter
diff --git a/Language/Atom/Common/Threshold.hs b/Language/Atom/Common/Threshold.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Common/Threshold.hs
@@ -0,0 +1,67 @@
+-- | 
+-- Module: Threshold
+-- Description: Time integrated threshold functions
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Time integrated threshold functions typically used in condition monitoring.
+module Language.Atom.Common.Threshold
+  ( boolThreshold
+  , doubleThreshold
+  ) where
+
+import Language.Atom.Expressions
+import Language.Atom.Language
+import Data.Int (Int32)
+  
+-- | Boolean thresholding over time.  Output is set when internal counter hits
+-- limit, and cleared when counter is 0.
+boolThreshold :: Name -> Int32 -> Bool -> E Bool -> Atom (E Bool)
+boolThreshold name_ num init_ input = atom name_ $ do
+  --assert "positiveNumber" $ num >= 0
+
+  state <- bool "state" init_
+  count <- int32 "count" (if init_ then num else 0)
+
+  atom "update" $ do
+    cond $ value count >. Const 0 &&. value count <. Const num
+    count <== value count + mux input (Const 1) (Const (-1))
+
+  atom "low" $ do
+    cond $ value count ==. Const 0
+    state <== false
+
+  atom "high" $ do
+    cond $ value count ==. Const num
+    state <== true
+
+  return $ value state
+
+-- | Integrating threshold.  Output is set with integral reaches limit, and
+-- cleared when integral reaches 0.
+doubleThreshold :: Name -> Double -> E Double -> Atom (E Bool)
+doubleThreshold name_ lim input = atom name_ $ do
+  --assert "positiveLimit" $ lim >= 0
+
+  state <- bool "state" False
+  sum_ <- double "sum" 0
+
+  -- TODO: Figure out what the below translates to in the newer library
+  -- (high,low) <- priority
+
+  atom "update" $ do
+    sum_ <== value sum_ + input
+    -- low
+
+  atom "clear" $ do
+    cond $ value sum_ <=. 0
+    state <== false
+    sum_ <== 0
+    -- high
+
+  atom "set" $ do
+    cond $ value sum_ >=. Const lim
+    state <== true
+    sum_ <== Const lim
+    -- high
+
+  return  $ value state
diff --git a/Language/Atom/Common/ValidData.hs b/Language/Atom/Common/ValidData.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Common/ValidData.hs
@@ -0,0 +1,36 @@
+-- | 
+-- Module: ValidData
+-- Description: Capturing data that can either be valid or invalid
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Capturing data that can either be valid or invalid.
+module Language.Atom.Common.ValidData
+  ( ValidData
+  , validData
+  , getValidData
+  , whenValid
+  , whenInvalid
+  ) where
+
+import Language.Atom.Expressions
+import Language.Atom.Language
+
+-- | 'ValidData' captures the data and its validity condition.
+--   'ValidData' is abstract to prevent rules from using invalid data.
+data ValidData a = ValidData a (E Bool)
+
+-- | Create 'ValidData' given the data and validity condition.
+validData :: a -> E Bool -> ValidData a
+validData = ValidData
+
+-- | Get a valid data.  Action is disabled if data is invalid.
+getValidData :: ValidData a -> Atom a
+getValidData (ValidData a v) = cond v >> return a
+
+-- | Action enabled if 'ValidData' is valid.
+whenValid :: ValidData a -> Atom ()
+whenValid (ValidData _ v) = cond v
+
+-- | Action enabled if 'ValidData' is not valid.
+whenInvalid :: ValidData a -> Atom ()
+whenInvalid (ValidData _ v) = cond $ not_ v
diff --git a/Language/Atom/Compile.hs b/Language/Atom/Compile.hs
--- a/Language/Atom/Compile.hs
+++ b/Language/Atom/Compile.hs
@@ -1,4 +1,10 @@
--- | Atom compilation.
+-- | 
+-- Module: Compile
+-- Description: Compilation functions
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Atom compilation functions
+
 module Language.Atom.Compile
   ( compile
   , reportSchedule
@@ -17,23 +23,24 @@
 
 -- | Compiles an atom description to C.
 compile :: Name -> Config -> Atom () 
-        -> IO (Schedule, RuleCoverage, [Name], [Name], [(Name, Type)])
+           -> IO (Schedule, RuleCoverage, [Name], [Name], [(Name, Type)])
 compile name config atom' = do
   res <- elaborate emptyMap name atom'
   case res of
-    Nothing -> putStrLn "ERROR: Design rule checks failed." >> exitWith (ExitFailure 1)
-    Just (st,(state, rules, assertionNames, coverageNames, probeNames)) -> do
-      let schedule' = schedule rules st
-      ruleCoverage <- writeC name config state rules schedule' assertionNames
-                             coverageNames probeNames
-      when (isJust $ hardwareClock config) (putStrLn hwClockWarning)
-      return (schedule', ruleCoverage, assertionNames, coverageNames, probeNames)
+   Nothing -> putStrLn "ERROR: Design rule checks failed." >>
+              exitWith (ExitFailure 1)
+   Just (st,(state, rules, assertionNames, coverageNames, probeNames)) -> do
+     let schedule' = schedule rules st
+     ruleCoverage <- writeC name config state rules schedule' assertionNames
+                     coverageNames probeNames
+     when (isJust $ hardwareClock config) (putStrLn hwClockWarning)
+     return (schedule', ruleCoverage, assertionNames, coverageNames, probeNames)
 
 hwClockWarning :: String
 hwClockWarning = unlines
  [ ""
- , "*** Atom WARNING: you are configuring to use a harware clock.  Please remember to set"
- , "    the \"__phase_start_time\" variable to the time at which the first phase should be"
- , "    run before you enter the main Atom-generated function the first time."
- , ""
+ , "*** Atom WARNING: you are configuring to use a hardware clock.  Please remember"
+ , "    to set the \"__phase_start_time\" variable to the time at which the first"
+ , "    phase should be run before you enter the main Atom-generated function the"
+ , "    first time."
  ]
diff --git a/Language/Atom/Elaboration.hs b/Language/Atom/Elaboration.hs
--- a/Language/Atom/Elaboration.hs
+++ b/Language/Atom/Elaboration.hs
@@ -1,3 +1,8 @@
+-- | 
+-- Module: Elaboration
+-- Description: -
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+
 module Language.Atom.Elaboration
   (
 --    UeStateT
@@ -25,6 +30,8 @@
   , allUEs
   ) where
 
+import Control.Applicative (Applicative, pure, (<*>))
+import Control.Monad (ap)
 import Control.Monad.Trans
 import Data.Function (on)
 import Data.List
@@ -205,6 +212,13 @@
 
 -- | The Atom monad holds variable and rule declarations.
 data Atom a = Atom (AtomSt -> IO (a, AtomSt))
+
+instance Applicative Atom where
+  pure = return
+  (<*>) = ap
+
+instance Functor Atom where
+  fmap = S.liftM
 
 instance Monad Atom where
   return a = Atom (\ s -> return (a, s))
diff --git a/Language/Atom/Example.hs b/Language/Atom/Example.hs
deleted file mode 100644
--- a/Language/Atom/Example.hs
+++ /dev/null
@@ -1,72 +0,0 @@
--- | An example atom design.
-module Language.Atom.Example
-  ( compileExample
-  , example
-  ) where
-
-import Language.Atom
-
--- | Invoke the atom compiler.
-compileExample :: IO ()
-compileExample = do
-  (schedule, _, _, _, _) <- compile "example" defaults { cCode = prePostCode } example
-  putStrLn $ reportSchedule schedule
-
-prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
-prePostCode _ _ _ =
-  ( unlines
-    [ "#include <stdlib.h>"
-    , "#include <stdio.h>"
-    , "unsigned long int a;"
-    , "unsigned long int b;"
-    , "unsigned long int x;"
-    , "unsigned char running = 1;"
-    ]
-  , unlines
-    [ "int main(int argc, char* argv[]) {"
-    , "  if (argc < 3) {"
-    , "    printf(\"usage: gcd <num1> <num2>\\n\");"
-    , "  }"
-    , "  else {"
-    , "    a = atoi(argv[1]);"
-    , "    b = atoi(argv[2]);"
-    , "    printf(\"Computing the GCD of %lu and %lu...\\n\", a, b);"
-    , "    while(running) {"
-    , "      example();"
-    , "      printf(\"iteration:  a = %lu  b = %lu\\n\", a, b);"
-    , "    }"
-    , "    printf(\"GCD result: %lu\\n\", a);"
-    , "  }"
-    , "  return 0;"
-    , "}"
-    ]
-  )
-
--- | An example design that computes the greatest common divisor.
-example :: Atom ()
-example = do
-
-  -- External reference to value A.
-  let a = word32' "a"
-
-  -- External reference to value B.
-  let b = word32' "b"
-
-  -- The external running flag.
-  let running = bool' "running"
-
-  -- A rule to modify A.
-  atom "a_minus_b" $ do
-    cond $ value a >. value b
-    a <== value a - value b
-
-  -- A rule to modify B.
-  atom "b_minus_a" $ do
-    cond $ value b >. value a
-    b <== value b - value a
-
-  -- A rule to clear the running flag.
-  atom "stop" $ do
-    cond $ value a ==. value b
-    running <== false
-
diff --git a/Language/Atom/Example/External.hs b/Language/Atom/Example/External.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Example/External.hs
@@ -0,0 +1,57 @@
+{- |
+Module: External
+Description: Example of referencing external variables and functions in Atom
+Copyright: (c) 2015 Chris Hodapp
+
+This demonstrates the use of 'word16'' to reference an external variable, and
+the use of 'call' to call an external function.
+
+-}
+module Language.Atom.Example.External where
+
+import Language.Atom
+
+-- | Invoke the Atom compiler
+main :: IO ()
+main = do
+  let atomCfg = defaults { cCode = prePostCode , cRuleCoverage = False }
+  (sched, _, _, _, _) <- compile "extern_example" atomCfg extern
+  putStrLn $ reportSchedule sched
+
+-- | Top-level rule
+extern :: Atom ()
+extern = do
+
+  -- External reference to a variable 'g_random' which is a uint16:
+  let rng = word16' "g_random"
+
+  atom "update" $ do
+    -- Call external function 'new_random' which updates g_random:
+    call "new_random"
+    printIntegralE "g_random" $ value rng
+
+prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
+prePostCode _ _ _ =
+  ( unlines [ "// ---- This source is automatically generated by Atom ----"
+            , "#include <stdio.h>"
+            , "#include <stdlib.h>"
+            , "#include <unistd.h>"
+            , ""
+              -- Declarations of what we reference above:
+            , "static uint16_t g_random = 0;"
+            , "void new_random(void);"
+            ]
+  , unlines [ "int main(void) {"
+            , "    while (true) {"
+            , "        extern_example();"
+            , "        usleep(1000);"
+            , "    }"
+            , "    return 0;"
+            , "}"
+            , ""
+              -- And the function definition:
+            , "void new_random(void) {"
+            , "    g_random = rand();"
+            , "}"
+            , "// ---- End automatically-generated source ----"
+            ])
diff --git a/Language/Atom/Example/Gcd.hs b/Language/Atom/Example/Gcd.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Example/Gcd.hs
@@ -0,0 +1,77 @@
+-- | 
+-- Module: Gcd
+-- Description: Example design which computes GCD (greatest-common divisor)
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+
+module Language.Atom.Example.Gcd
+  ( compileExample
+  , example
+  ) where
+
+import Language.Atom
+
+-- | Invoke the Atom compiler
+compileExample :: IO ()
+compileExample = do
+  (schedule, _, _, _, _) <- compile "example" defaults { cCode = prePostCode } example
+  putStrLn $ reportSchedule schedule
+
+prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
+prePostCode _ _ _ =
+  ( unlines
+    [ "#include <stdlib.h>"
+    , "#include <stdio.h>"
+    , "unsigned long int a;"
+    , "unsigned long int b;"
+    , "unsigned long int x;"
+    , "unsigned char running = 1;"
+    ]
+  , unlines
+    [ "int main(int argc, char* argv[]) {"
+    , "  if (argc < 3) {"
+    , "    printf(\"usage: gcd <num1> <num2>\\n\");"
+    , "  }"
+    , "  else {"
+    , "    a = atoi(argv[1]);"
+    , "    b = atoi(argv[2]);"
+    , "    printf(\"Computing the GCD of %lu and %lu...\\n\", a, b);"
+    , "    while(running) {"
+    , "      example();"
+    , "      printf(\"iteration:  a = %lu  b = %lu\\n\", a, b);"
+    , "    }"
+    , "    printf(\"GCD result: %lu\\n\", a);"
+    , "  }"
+    , "  return 0;"
+    , "}"
+    ]
+  )
+
+-- | An example design that computes the greatest common divisor.
+example :: Atom ()
+example = do
+
+  -- External reference to value A.
+  let a = word32' "a"
+
+  -- External reference to value B.
+  let b = word32' "b"
+
+  -- The external running flag.
+  let running = bool' "running"
+
+  -- A rule to modify A.
+  atom "a_minus_b" $ do
+    cond $ value a >. value b
+    a <== value a - value b
+
+  -- A rule to modify B.
+  atom "b_minus_a" $ do
+    cond $ value b >. value a
+    b <== value b - value a
+
+  -- A rule to clear the running flag.
+  atom "stop" $ do
+    cond $ value a ==. value b
+    running <== false
+
diff --git a/Language/Atom/Example/Probes.hs b/Language/Atom/Example/Probes.hs
new file mode 100644
--- /dev/null
+++ b/Language/Atom/Example/Probes.hs
@@ -0,0 +1,81 @@
+{- |
+Module: Probes
+Description: Example usage of probes in Atom
+Copyright: (c) 2015 Chris Hodapp
+
+This demonstrates the usage of Atom's probe functionality. In this case, it
+simply uses @printf@ to log a probe's value. Most POSIX systems should be able
+to build and run the generated C code.
+
+-}
+module Language.Atom.Example.Probes where
+
+import Data.Word
+import Language.Atom
+
+-- | Invoke the Atom compiler
+main :: IO ()
+main = do
+  let atomCfg = defaults { cCode = prePostCode , cRuleCoverage = False }
+  (sched, _, _, _, _) <- compile "probe_example" atomCfg example
+  putStrLn $ reportSchedule sched
+
+-- | Generate a code comment about the given probe.
+probeStr :: (Name, Type) -> String
+probeStr (n, t) = "// Probe: " ++ n ++ ", type: " ++ show t
+
+-- | Use 'action' to call @PROBE_PRINTF@ on a probe given as (name, value).
+-- This will work only on integer-valued probes.
+logProbe :: (String, UE) -> Atom ()
+logProbe (str, ue_) = action probeFn [ue_]
+  where probeFn v = "PROBE_PRINTF(\"%u, " ++ str ++
+                    ": %i\\n\", __global_clock, " ++ head v ++ ")"
+
+-- | Top-level rule
+example :: Atom ()
+example = do
+
+  -- Include in the once-per-second clock:
+  sec <- tickSecond
+
+  -- Compute minutes and hours as well (probes take arbitrary expressions):
+  probe "Minutes" $ (value sec) `div_` 60
+  probe "Hours" $ (value sec) `div_` 3600
+
+  -- At 1/200 of our base rate (~ 5 seconds), we call 'logProbe' on all of the
+  -- probes that are in use.
+  period 200 $ atom "monitor" $ do
+    mapM_ logProbe =<< probes
+
+prePostCode :: [Name] -> [Name] -> [(Name, Type)] -> (String, String)
+prePostCode _ _ probeList =
+  ( unlines $ [ "// ---- This source is automatically generated by Atom ----"
+              , "#define PROBE_PRINTF printf"
+              , "#include <stdio.h>"
+              , "#include <stdlib.h>"
+              , "#include <unistd.h>"
+              ] ++ map probeStr probeList
+    -- Basic stub to call with a 1 millisecond delay (do not attempt anything like
+    -- this in production - use an interrupt):
+  , unlines [ "int main(void) {"
+            , "    while (true) {"
+            , "        probe_example();"
+            , "        usleep(1000);"
+            , "    }"
+            , "    return 0;"
+            , "}"
+            , "// ---- End automatically-generated source ----"
+            ])
+
+-- | Count up seconds of runtime, assuming our base rate is 1 millisecond:
+tickSecond :: Atom (V Word64)
+tickSecond = do
+  
+  sec <- word64 "seconds" 0
+
+  -- Add a probe to the clock:
+  probe "Seconds" $ value sec
+  
+  period 1000 $ exactPhase 0 $ atom "second" $ incr sec
+  
+  return sec
diff --git a/Language/Atom/Expressions.hs b/Language/Atom/Expressions.hs
--- a/Language/Atom/Expressions.hs
+++ b/Language/Atom/Expressions.hs
@@ -1,3 +1,9 @@
+-- | 
+-- Module: Expressions
+-- Description: Definitions for expressions, variables, and types
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Definitions for Atom expressions, variables, and types
 {-# LANGUAGE GADTs, DeriveDataTypeable #-}
 
 module Language.Atom.Expressions
@@ -117,6 +123,7 @@
   | Double
   deriving (Show, Read, Eq, Ord, Enum, Data, Typeable)
 
+-- | Typed constant
 data Const
   = CBool   Bool
   | CInt8   Int8
@@ -146,6 +153,7 @@
     CFloat  c -> show c
     CDouble c -> show c
 
+-- | Typed expression
 data Expression
   = EBool   (E Bool)
   | EInt8   (E Int8)
@@ -159,6 +167,7 @@
   | EFloat  (E Float)
   | EDouble (E Double)
 
+-- | Typed variable
 data Variable
   = VBool   (V Bool)
   | VInt8   (V Int8)
@@ -172,7 +181,6 @@
   | VFloat  (V Float)
   | VDouble (V Double) deriving Eq
 
-
 -- | Variables updated by state transition rules.
 data V a = V UV deriving Eq
 
@@ -284,9 +292,12 @@
   | UAtanh    UE
   deriving (Show, Eq, Ord, Data, Typeable)
 
+-- | Types with a defined width in bits
 class Width a where
+  -- | The width of a type, in number of bits
   width :: a -> Int
 
+-- | The number of bytes that an object occupies
 bytes :: Width a => a -> Int
 bytes a = div (width a) 8 + if mod (width a) 8 == 0 then 0 else 1
 
@@ -310,7 +321,10 @@
 instance Width UE              where width = width . typeOf
 instance Width UV              where width = width . typeOf
 
-class TypeOf a where typeOf :: a -> Type
+-- | Types which have a defined 'Type'
+class TypeOf a where
+  -- | The corresponding 'Type' of the given object
+  typeOf :: a -> Type
 
 instance TypeOf Const where
   typeOf a = case a of
@@ -388,7 +402,7 @@
 instance Expr a => TypeOf (E a) where
   typeOf = eType
 
-
+-- | Typed expression:
 class Eq a => Expr a where
   eType      :: E a -> Type
   constant   :: a -> Const
@@ -473,7 +487,7 @@
   variable   = VDouble
   rawBits    = D2B
 
-
+-- | Expression of numerical type
 class (Num a, Expr a, EqE a, OrdE a) => NumE a
 instance NumE Int8
 instance NumE Int16
@@ -486,7 +500,11 @@
 instance NumE Float
 instance NumE Double
 
-class (NumE a, Integral a) => IntegralE a where signed :: E a -> Bool
+-- | Expression of integral type
+class (NumE a, Integral a) => IntegralE a where
+  -- | Returns True if expression is signed, and False if unsigned.
+  signed :: E a -> Bool
+
 instance IntegralE Int8   where signed _ = True
 instance IntegralE Int16  where signed _ = True
 instance IntegralE Int32  where signed _ = True
@@ -496,6 +514,7 @@
 instance IntegralE Word32 where signed _ = False
 instance IntegralE Word64 where signed _ = False
 
+-- | Expressions which can be compared for equality
 class (Eq a, Expr a) => EqE a
 instance EqE Bool
 instance EqE Int8
@@ -509,6 +528,7 @@
 instance EqE Float
 instance EqE Double
 
+-- | Expressions which can be ordered
 class (Eq a, Ord a, EqE a) => OrdE a
 instance OrdE Int8
 instance OrdE Int16
@@ -521,6 +541,7 @@
 instance OrdE Float
 instance OrdE Double
 
+-- | Floating-point typed expression
 class (RealFloat a, NumE a, OrdE a) => FloatingE a
 instance FloatingE Float
 instance FloatingE Double
@@ -641,8 +662,10 @@
 any_ :: (a -> E Bool) -> [a] -> E Bool
 any_ f a = or_ $ map f a
 
--- Logical implication (if a then b).
-imply :: E Bool -> E Bool -> E Bool
+-- | Logical implication (if a then b).
+imply :: E Bool -- ^ a
+         -> E Bool -- ^ b
+         -> E Bool
 imply a b = not_ a ||. b
 
 -- | Equal.
@@ -790,20 +813,24 @@
   where
   tt = eType t
 
+-- | Convert a typed variable to an untyped one
 uv :: V a -> UV
 uv (V v) = v
 
 -- XXX A future smart constructor for numeric type casting.
 -- ucast :: Type -> UE -> UE
 
+-- | Produced an untyped expression from a constant 'Bool'
 ubool :: Bool -> UE
 ubool = UConst . CBool
 
+-- | Logical NOT of an untyped expression
 unot :: UE -> UE
 unot (UConst (CBool a)) = ubool $ not a
 unot (UNot a) = a
 unot a = UNot a
 
+-- | Logical AND of two untyped expressions
 uand :: UE -> UE -> UE
 uand a b | a == b                   = a
 uand a@(UConst (CBool False)) _     = a
@@ -843,9 +870,11 @@
 -- collect, sort, and return
 reduceAnd terms = UAnd $ sort $ nub terms
 
+-- | Logical OR of two untyped expressions
 uor :: UE -> UE -> UE
 uor a b = unot (uand (unot a) (unot b))
 
+-- | Check equality on two untyped expressions
 ueq :: UE -> UE -> UE
 ueq a b | a == b = ubool True
 ueq (UConst (CBool   a)) (UConst (CBool   b)) = ubool $ a == b
@@ -861,7 +890,10 @@
 ueq (UConst (CDouble a)) (UConst (CDouble b)) = ubool $ a == b
 ueq a b = UEq a b
 
-ult :: UE -> UE -> UE
+-- | Less-than inequality on two untyped expressions
+ult :: UE -- ^ a
+       -> UE -- ^ b
+       -> UE -- ^ a < b
 ult a b | a == b = ubool False
 ult (UConst (CBool   a)) (UConst (CBool   b)) = ubool $ a < b
 ult (UConst (CInt8   a)) (UConst (CInt8   b)) = ubool $ a < b
@@ -876,7 +908,12 @@
 ult (UConst (CDouble a)) (UConst (CDouble b)) = ubool $ a < b
 ult a b = ULt a b
 
-umux :: UE -> UE -> UE -> UE
+-- | 2-to-1 multiplexer. If selector is true, this returns input 1; if
+-- selector is false, this returns input 2.
+umux :: UE -- ^ Selector
+        -> UE -- ^ Input 1
+        -> UE -- ^ Input 2
+        -> UE
 umux _ t f | t == f = f
 umux b t f | typeOf t == Bool = uor (uand b t) (uand (unot b) f)
 umux (UConst (CBool b)) t f = if b then t else f
diff --git a/Language/Atom/Language.hs b/Language/Atom/Language.hs
--- a/Language/Atom/Language.hs
+++ b/Language/Atom/Language.hs
@@ -1,4 +1,10 @@
--- | The Atom language.
+-- | 
+-- Module: Language
+-- Description: Definitions for the language/EDSL itself
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Definitions for the Atom EDSL itself
+
 module Language.Atom.Language
   (
     module Language.Atom.Expressions
@@ -78,20 +84,21 @@
 -- | The Atom monad captures variable and transition rule declarations.
 type Atom = E.Atom
 
--- | Creates a hierarchical node, where each node could be a atomic rule.
+-- | Creates a hierarchical node, where each node could be an atomic rule.
 atom :: Name -> Atom a -> Atom a
 atom name design = do
   name' <- addName name
   (st1, (g1, parent)) <- get
-  (a, (st2, (g2, child))) <- liftIO $ buildAtom st1 g1 { gState = [] } name' design
+  (a, (st2, (g2, child))) <- liftIO $
+                             buildAtom st1 g1 { gState = [] } name' design
   put (st2, ( g2 { gState = gState g1 ++ [StateHierarchy name $ gState g2] }
             , parent { atomSubs = atomSubs parent ++ [child] }))
   return a
 
--- | Defines the period of execution of sub rules as a factor of the base rate of the system.
---   Rule period is bound by the closest period assertion.  For example:
---
---   > period 10 $ period 2 a   -- Rules in 'a' have a period of 2, not 10.
+-- | Defines the period of execution of sub-rules as a factor of the base rate
+-- of the system.  Rule period is bound by the closest period assertion.  For
+-- example:
+-- > period 10 $ period 2 a   -- Rules in 'a' have a period of 2, not 10.
 period :: Int -> Atom a -> Atom a
 period n _ | n <= 0 = error "ERROR: Execution period must be greater than 0."
 period n atom' = do
@@ -240,21 +247,32 @@
 double' :: Name -> V Double
 double' name = var' name Double
 
--- | Declares an action.
-action :: ([String] -> String) -> [UE] -> Atom ()
+-- | Declares an action, which executes C code that is optionally passed
+-- some parameters.
+action :: ([String] -> String) -- ^ A function which receives a list of
+                               -- C parameters, and returns C code that
+                               -- should be executed.
+          -> [UE] -- ^ A list of expressions; the supplied functions receive
+                  -- parameters which correspond to these expressions.
+          -> Atom ()
 action f ues = do
   (st, (g, a)) <- get
-  let (st', hashes) = foldl' (\(accSt,hs) ue' -> let (h,accSt') = newUE ue' accSt in
-                                                (accSt',h:hs))
-                             (st,[]) ues
+  let (st', hashes) =
+        foldl' (\(accSt,hs) ue' ->
+                 let (h,accSt') = newUE ue' accSt in (accSt',h:hs))
+        (st,[]) ues
   put (st', (g, a { atomActions = atomActions a ++ [(f, hashes)] }))
 
 -- | Calls an external C function of type 'void f(void)'.
-call :: Name -> Atom ()
+call :: Name -- ^ Function @f@
+        -> Atom ()
 call n = action (\ _ -> n ++ "()") []
 
--- | Declares a probe.
-probe :: Expr a => Name -> E a -> Atom ()
+-- | Declares a probe. A probe allows inspecting any expression, remotely to
+-- its context, at any desired rate.
+probe :: Expr a => Name -- ^ Human-readable probe name
+         -> E a -- ^ Expression to inspect
+         -> Atom ()
 probe name a = do
   (st, (g, atom')) <- get
   let (h,st') = newUE (ue a) st
@@ -262,7 +280,9 @@
     then error $ "ERROR: Duplicated probe name: " ++ name
     else put (st', (g { gProbes = (name, h) : gProbes g }, atom'))
 
--- | Fetches all declared probes to current design point.
+-- | Fetches all declared probes to current design point.  The list contained
+-- therein is (probe name, untyped expression).
+-- See 'Language.Atom.Unit.printProbe'.
 probes :: Atom [(String, UE)]
 probes = do
   (st, (g, _)) <- get
@@ -270,11 +290,11 @@
   let g' = zip strs (map (recoverUE st) hs)
   return g'
 
--- | Increments a NumE 'V'.
+-- | Increments a 'NumE' 'V'.
 incr :: (Assign a, NumE a) => V a -> Atom ()
 incr a = a <== value a + 1
 
--- | Decrements a NumE 'V'.
+-- | Decrements a 'NumE' 'V'.
 decr :: (Assign a, NumE a) => V a -> Atom ()
 decr a = a <== value a - 1
 
@@ -321,7 +341,7 @@
   return (value $ word32' "__coverage_index", value $ word32' "__coverage[__coverage_index]")
 
 
--- | An assertions checks that an E Bool is true.  Assertions are checked
+-- | An assertions checks that an 'E Bool' is true.  Assertions are checked
 -- between the execution of every rule.  Parent enabling conditions can
 -- disable assertions, but period and phase constraints do not.  Assertion
 -- names should be globally unique.
@@ -333,15 +353,16 @@
   let (chk,st') = newUE (ue check) st
   put (st', (g, atom' { atomAsserts = (name, chk) : atomAsserts atom' }))
 
--- | Implication assertions.  Creates an implicit coverage point for the precondition.
+-- | Implication assertions.  Creates an implicit coverage point for the
+-- precondition.
 assertImply :: Name -> E Bool -> E Bool -> Atom ()
 assertImply name a b = do
   assert name $ imply a b
   cover (name ++ "Precondition") a
 
 -- | A functional coverage point tracks if an event has occured (true).
---   Coverage points are checked at the same time as assertions.
---   Coverage names should be globally unique.
+-- Coverage points are checked at the same time as assertions.
+-- Coverage names should be globally unique.
 cover :: Name -> E Bool -> Atom ()
 cover name check = do
   (st, (g, atom')) <- get
diff --git a/Language/Atom/Scheduling.hs b/Language/Atom/Scheduling.hs
--- a/Language/Atom/Scheduling.hs
+++ b/Language/Atom/Scheduling.hs
@@ -1,4 +1,10 @@
--- | Atom rule scheduling.
+-- | 
+-- Module: Scheduling
+-- Description: Rule scheduling
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Algorithms for scheduling rules in Atom
+
 module Language.Atom.Scheduling
   ( schedule
   , Schedule
@@ -12,7 +18,8 @@
 import Language.Atom.Elaboration
 import Language.Atom.UeMap
 
-type Schedule = (UeMap, [(Int, Int, [Rule])])  -- (period, phase, rules)
+-- | Schedule expressed as a 'UeMap' and a list of (period, phase, rules).
+type Schedule = (UeMap, [(Int, Int, [Rule])])
 
 schedule :: [Rule] -> UeMap -> Schedule
 schedule rules' mp = (mp, concatMap spread periods)
@@ -90,6 +97,7 @@
   grow ((a, bs):rest) (a', b) | a' == a   = (a, b : bs) : rest
                               | otherwise = (a, bs) : grow rest (a', b)
 
+-- | Generate a rule scheduling report for the given schedule.
 reportSchedule :: Schedule -> String
 reportSchedule (mp, schedule_) = concat
   [ "Rule Scheduling Report\n\n"
@@ -107,7 +115,6 @@
   ]
   where
   rules = concat $ [ r | (_, _, r) <- schedule_ ]
-
 
 reportPeriod :: UeMap -> (Int, Int, [Rule]) -> String
 reportPeriod mp (period, phase, rules) = concatMap reportRule rules
diff --git a/Language/Atom/UeMap.hs b/Language/Atom/UeMap.hs
--- a/Language/Atom/UeMap.hs
+++ b/Language/Atom/UeMap.hs
@@ -1,4 +1,10 @@
--- | Sharing for UEs, based on IntMaps.  The idea is to share subexpressions of 'UE's.
+-- | 
+-- Module: UeMap
+-- Description: Sharing for UEs, based on IntMaps.
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Sharing for 'UE's, based on IntMaps.  The idea is to share subexpressions
+-- of 'UE's.
 
 module Language.Atom.UeMap
   ( UeElem (..)
diff --git a/Language/Atom/Unit.hs b/Language/Atom/Unit.hs
--- a/Language/Atom/Unit.hs
+++ b/Language/Atom/Unit.hs
@@ -1,3 +1,10 @@
+-- | 
+-- Module: Unit
+-- Description: Unit testing, coverage, reporting & debugging
+-- Copyright: (c) 2013 Tom Hawkins & Lee Pike
+--
+-- Unit testing, coverage, reporting & debugging for Atom
+
 module Language.Atom.Unit
   (
   -- * Types and Classes
@@ -10,6 +17,7 @@
   , printStrLn
   , printIntegralE
   , printFloatingE
+  , printProbe
   ) where
 
 import Control.Monad
@@ -27,19 +35,24 @@
 
 import Prelude hiding (id)
 
--- | Data constructor:Test
+-- | Parameters for a test simulation
 data Test = Test
-  { name      :: String
-  , cycles    :: Int
-  , testbench :: Atom ()
-  , modules   :: [FilePath]
-  , includes  :: [FilePath]
-  , declCode  :: String
-  , initCode  :: String
-  , loopCode  :: String
-  , endCode   :: String
+  { name      :: String -- ^ Name for test (used in log file, state name,
+                 -- and output)
+  , cycles    :: Int -- ^ Number of simulation cycles to run
+  , testbench :: Atom () -- ^ Atom specification to test
+  , modules   :: [FilePath] -- ^ Other C files to build in
+  , includes  :: [FilePath] -- ^ Other C headers to include
+  , declCode  :: String -- ^ C declarations and definitions inserted prior to
+                 -- the @main@ function
+  , initCode  :: String -- ^ C code executed inside the @main@ function, prior
+                 -- to 'loopCode'
+  , loopCode  :: String -- ^ C code executed inside the loop running the test
+  , endCode   :: String -- ^ C code executed after that loop, but still in
+                 -- @main@
   }
 
+-- | Default test parameters
 defaultTest :: Test
 defaultTest = Test
   { name      = "test"
@@ -53,34 +66,47 @@
   , endCode   = ""
   }
 
-
--- | Running TestList
-runTests :: Int -> [IO Test] -> IO ()
+-- | Run a list of tests, output a report on test passes and coverage.
+runTests :: Int -- ^ Random seed
+            -> [IO Test] -- ^ List of tests to run
+            -> IO ()
 runTests seed tests = do
   testResults <- mapM (runTest seed) tests
   let totalTests    = length testResults
       passingTests  = length $ filter (\ (_, p, _, _, _) -> p) testResults
       totalCoverage = nub $ concat [ a | (_, _, _, a, _) <- testResults ]
-      unHitCoverage = sort $ totalCoverage \\ (nub $ concat [ a | (_, _, _, _, a) <- testResults ])
+      unHitCoverage = sort $
+                      totalCoverage \\
+                      (nub $ concat [ a | (_, _, _, _, a) <- testResults ])
       totalCycles   = sum [ c | (_, _, c, _, _) <- testResults ]
       maxNameLen    = maximum [ length n | (n, _, _, _, _) <- testResults ]
   mapM_ (reportResult maxNameLen) testResults
   putStrLn ""
-  putStrLn $ "Total Passing Tests     : " ++ show passingTests ++ " / " ++ show totalTests
-  putStrLn $ "Total Simulation Cycles : " ++ show totalCycles
-  putStrLn $ "Total Function Coverage : " ++ show (length totalCoverage - length unHitCoverage) ++ " / " ++ show (length totalCoverage)
+  putStrLn $ "Total Passing Tests     : " ++
+    show passingTests ++ " / " ++ show totalTests
+  putStrLn $ "Total Simulation Cycles : " ++
+    show totalCycles
+  putStrLn $ "Total Function Coverage : " ++
+    show (length totalCoverage - length unHitCoverage) ++ " / " ++
+    show (length totalCoverage)
   when (not $ null unHitCoverage) $ do
     putStrLn ""
     putStrLn "  Missed Coverage Points:"
     putStrLn ""
     mapM_ (putStrLn . ("    " ++)) unHitCoverage
   putStrLn ""
-  putStrLn $ (if passingTests /= totalTests then "RED" else if not $ null unHitCoverage then "YELLOW" else "GREEN") ++ " LIGHT"
+  putStrLn $ (if passingTests /= totalTests
+              then "RED"
+              else if not $ null unHitCoverage
+                   then "YELLOW" else "GREEN") ++ " LIGHT"
   putStrLn ""
   when (passingTests /= totalTests) $ exitWith $ ExitFailure 2
   when (not $ null unHitCoverage)   $ exitWith $ ExitFailure 1
 
-reportResult :: Int -> (Name, Bool, Int, a, b) -> IO ()
+-- | Report results on a particular test
+reportResult :: Int -- ^ Max name length
+                -> (Name, Bool, Int, a, b) -- ^ (name, pass, cycles, _, _)
+                -> IO ()
 reportResult m (name', pass, cycles', _, _) =
       printf "%s:  %s    cycles = %7i  %s\n"
         (if pass then "pass" else "FAIL")
@@ -88,13 +114,27 @@
         cycles'
         (if pass then "" else "    (see " ++ name' ++ ".log)")
 
-runTest :: Int -> IO Test -> IO (Name, Bool, Int, [Name], [Name])
+-- | Run a single test with the given random seed. This will generate code,
+-- compile it with GCC, execute it, and collect its output.
+runTest :: Int -- ^ Random seed
+           -> IO Test -- ^ Test to run
+           -- | (name, pass status, cycles run, all coverage names,
+           -- names covered)
+           -> IO (Name, Bool, Int, [Name], [Name])
 runTest seed test' = do
   test <- test'
+  let config = defaults { cStateName = name test
+                        , cCode = prePostCode test
+                        , cRuleCoverage = False }
   putStrLn $ "running test " ++ name test ++ " ..."
   hFlush stdout
-  (_, _, _, coverageNames, _) <- compile "atom_unit_test" defaults { cStateName = name test, cCode = prePostCode test, cRuleCoverage = False } $ testbench test
-  (exit, out, err) <- readProcessWithExitCode "gcc" (["-Wall", "-g", "-o", "atom_unit_test"] ++ [ "-I" ++ i | i <- includes test ] ++ modules test ++ ["atom_unit_test.c"]) ""
+  (_, _, _, coverageNames, _) <-
+    compile "atom_unit_test" config $ testbench test
+  (exit, out, err) <- readProcessWithExitCode "gcc"
+                      (["-Wall", "-g", "-o", "atom_unit_test"] ++
+                       [ "-I" ++ i | i <- includes test ] ++
+                       modules test ++
+                       ["atom_unit_test.c"]) ""
   let file = name test ++ ".log"
   case exit of 
     ExitFailure _ -> do
@@ -103,7 +143,8 @@
     ExitSuccess -> do
       log_ <- readProcess "./atom_unit_test" [] ""
       let pass = not $ elem "FAILURE:" $ words log_
-          covered = [ words line !! 1 | line <- lines log_, isPrefixOf "covered:" line ]
+          covered = [ words line !! 1 |
+                      line <- lines log_, isPrefixOf "covered:" line ]
       writeFile file $ out ++ err ++ log_
       hFlush stdout
       return (name test, pass, cycles test, coverageNames, covered)
@@ -114,15 +155,28 @@
       [ "#include <stdio.h>"
       , "#include <stdlib.h>"
       , "void assert (int id, unsigned char check, unsigned long long clock) {"
-      , "  static unsigned char failed[" ++ show (length assertionNames) ++ "] = {" ++ intercalate "," (replicate (length assertionNames) "0") ++ "};"
+      , "  static unsigned char failed[" ++
+        show (length assertionNames) ++
+        "] = {" ++ intercalate "," (replicate (length assertionNames) "0") ++
+        "};"
       , "  if (! check) {"
-      , "    " ++ intercalate "\n    else " [ "if (id == " ++ show id ++ ") { if (! failed[id]) { printf(\"ASSERTION FAILURE: " ++ name' ++ " at time %lli\\n\", clock); failed[id] = 1; } }" | (name', id) <- zip assertionNames [0::Int ..] ]
+      , "    " ++ intercalate "\n    else "
+        [ "if (id == " ++ show id ++
+          ") { if (! failed[id]) { printf(\"ASSERTION FAILURE: " ++ name' ++
+          " at time %lli\\n\", clock); failed[id] = 1; } }" |
+          (name', id) <- zip assertionNames [0::Int ..] ]
       , "  }"
       , "}"
       , "void cover  (int id, unsigned char check, unsigned long long clock) {"
-      , "  static unsigned char covered[" ++ show (length coverageNames) ++ "] = {" ++ intercalate "," (replicate (length coverageNames) "0") ++ "};"
+      , "  static unsigned char covered[" ++
+        show (length coverageNames) ++ "] = {" ++
+        intercalate "," (replicate (length coverageNames) "0") ++ "};"
       , "  if (check) {"
-      , "    " ++ intercalate "\n    else " [ "if (id == " ++ show id ++ ") { if (! covered[id]) { printf(\"covered: " ++ name' ++ " at time %lli\\n\", clock); covered[id] = 1; } }" | (name', id) <- zip coverageNames [0::Int ..] ]
+      , "    " ++ intercalate "\n    else "
+        [ "if (id == " ++ show id ++
+          ") { if (! covered[id]) { printf(\"covered: " ++ name' ++
+          " at time %lli\\n\", clock); covered[id] = 1; } }" |
+          (name', id) <- zip coverageNames [0::Int ..] ]
       , "  }"
       , "}"
       ] ++ declCode test
@@ -140,32 +194,60 @@
       , "  return 0;"
       , "}"
       ]
-  
 
-
-
--- | Printing strings in C using printf.
+-- | Print a string in C using @printf@, appending a newline.
 printStrLn :: String -> Atom ()
 printStrLn s = action (\ _ -> "printf(\"" ++ s ++ "\\n\")") []
 
--- | Print integral values.
-printIntegralE :: IntegralE a => String -> E a -> Atom ()
+-- | Print an integral value in C using @printf@.
+printIntegralE :: IntegralE a =>
+                  String -- ^ Prefix for printed value
+                  -> E a -- ^ Integral value to print
+                  -> Atom ()
 printIntegralE name' value' = 
-  action (\ v' -> "printf(\"" ++ name' ++ ": %i\\n\", " ++ head v' ++ ")") [ue value']
+  action (\ v' -> "printf(\"" ++ name' ++ ": %i\\n\", " ++ head v' ++ ")")
+  [ue value']
 
--- | Print floating point values.
-printFloatingE :: FloatingE a => String -> E a -> Atom ()
+-- | Print a floating point value in C using @printf@.
+printFloatingE :: FloatingE a =>
+                  String -- ^ Prefix for printed value
+                  -> E a -- ^ Floating point value to print
+                  -> Atom ()
 printFloatingE name' value' = 
-  action (\ v' -> "printf(\"" ++ name' ++ ": %f\\n\", " ++ head v' ++ ")") [ue value']
+  action (\ v' -> "printf(\"" ++ name' ++ ": %f\\n\", " ++ head v' ++ ")")
+  [ue value']
 
+-- TODO: Factor out common code in the above - which is all of it, except
+-- for a single character (%i vs. %f)
 
-class Expr a => Random a where random :: E a
+-- | Print the value of a probe to the console (along with its name).
+printProbe :: (String, UE) -> Atom ()
+printProbe (str, ue_) = case typeOf ue_ of
+  Bool   -> printIntegralE str (ruInt   :: E Int8)
+  Int8   -> printIntegralE str (ruInt   :: E Int8)
+  Int16  -> printIntegralE str (ruInt   :: E Int16)
+  Int32  -> printIntegralE str (ruInt   :: E Int32)
+  Int64  -> printIntegralE str (ruInt   :: E Int64)
+  Word8  -> printIntegralE str (ruInt   :: E Word8)
+  Word16 -> printIntegralE str (ruInt   :: E Word16)
+  Word32 -> printIntegralE str (ruInt   :: E Word32)
+  Word64 -> printIntegralE str (ruInt   :: E Word64)
+  Double -> printFloatingE str (ruFloat :: E Double)
+  Float  -> printFloatingE str (ruFloat :: E Float)
+  where ruInt :: IntegralE a => E a
+        ruInt = Retype ue_
+        ruFloat :: FloatingE a => E a
+        ruFloat = Retype ue_
 
+class Expr a => Random a where
+  random :: E a
+
 instance Random Bool   where random = (1 .&. random32) ==. 1
 instance Random Word8  where random = Cast random32
 instance Random Word16 where random = Cast random32
 instance Random Word32 where random = Cast random32
-instance Random Word64 where random = Cast random32 .|. shiftL (Cast random32) 32
+instance Random Word64 where
+  random = Cast random32 .|. shiftL (Cast random32) 32
 instance Random Int8   where random = Cast random32
 instance Random Int16  where random = Cast random32
 instance Random Int32  where random = Cast random32
diff --git a/atom.cabal b/atom.cabal
--- a/atom.cabal
+++ b/atom.cabal
@@ -1,21 +1,22 @@
 name:    atom
-version: 1.0.12
+version: 1.0.13
 
 category: Language, Embedded
 
-synopsis: A DSL for embedded hard realtime applications.
+synopsis: An EDSL for embedded hard realtime applications.
 
 description:
-    Atom is a Haskell DSL for designing hard realtime embedded software.
+    Atom is a Haskell EDSL for designing hard realtime embedded software.
     Based on guarded atomic actions (similar to STM), Atom enables
     highly concurrent programming without the need for mutex locking.
 
     In addition, Atom performs compile-time task scheduling and generates code
     with deterministic execution time and constant memory use, simplifying the
-    process of timing verification and memory consumption in hard realtime applications.
+    process of timing verification and memory consumption in hard realtime
+    applications.
 
     Without mutex locking and run-time task scheduling, Atom eliminates
-    the need and overhead of RTOSs for many embedded applications.
+    the need and overhead of RTOSes for many embedded applications.
 
 author:     Tom Hawkins <tomahawkins@gmail.com>
 maintainer: Tom Hawkins <tomahawkins@gmail.com>, Lee Pike <leepike@gmail.com>
@@ -45,9 +46,14 @@
         Language.Atom.Analysis
         Language.Atom.Code
         Language.Atom.Common
+        Language.Atom.Common.Fader
+        Language.Atom.Common.Threshold
+        Language.Atom.Common.ValidData
         Language.Atom.Compile
-        Language.Atom.Elaboration
-        Language.Atom.Example
+        Language.Atom.Elaboration 
+        Language.Atom.Example.External
+        Language.Atom.Example.Gcd
+        Language.Atom.Example.Probes
         Language.Atom.Expressions
         Language.Atom.Language
         Language.Atom.Scheduling
