content: -- Copyright (c) 2014 Contributors as noted in the AUTHORS file
  --
  -- This file is part of frp-arduino.
  --
  -- frp-arduino is free software: you can redistribute it and/or modify
  -- it under the terms of the GNU General Public License as published by
  -- the Free Software Foundation, either version 3 of the License, or
  -- (at your option) any later version.
  --
  -- frp-arduino is distributed in the hope that it will be useful,
  -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  -- GNU General Public License for more details.
  --
  -- You should have received a copy of the GNU General Public License
  -- along with frp-arduino.  If not, see <http://www.gnu.org/licenses/>.
  
  module Arduino.Library.Time
      ( accumulator
      , accumulatorConstLimit
      ) where
  
  import Arduino.DSL
  import Arduino.Library.Tuples
  import Prelude hiding (Word)
  
  -- | The snippet
  --
  -- @accumulator limitStream deltaStream@
  --
  -- creates a stream that produces a unit value every time the accumulated
  -- deltas have reached the limit.
  accumulator :: Stream Word -> Stream Word -> Stream ()
  accumulator limitStream deltaStream = unitStream
      where
          unitStream = mapS (const unit) wrappedStream
          wrappedStream = filterS2Tuple isWrap didWrapTotalStream
          didWrapTotalStream = foldpS accumulate (pack2 (0, 0)) limitDeltaStream
          limitDeltaStream = pack2Stream limitStream deltaStream
  
          accumulate :: Expression (Word, Word)
                     -> Expression (Word, Word)
                     -> Expression (Word, Word)
          accumulate limitDelta didWrapTotal =
              let (limit, delta) = unpack2 limitDelta
                  (didWrap, total) = unpack2 didWrapTotal
              in if_ (greater (total+delta) limit)
                     (pack2 (0, 0))
                     (pack2 (1, total+delta))
  
          isWrap :: (Expression Word, Expression Word) -> Expression Bool
          isWrap (didWrap, _) = isEqual didWrap 0
  
  accumulatorConstLimit :: Expression Word -> Stream Word -> Stream ()
  accumulatorConstLimit limit = accumulator (constStream limit)
  