using System;
using Microsoft.SPOT;

namespace CPF_Test
{
    class Observer
    {
        private enum ObserverStates { OutOfTolerance, InTolerance, Settled };

        public Observer(double desired, double tolerance, UInt32 settlingTimeInTicks)
        {
            m_desired               = desired;
            m_upperLimit            = desired + tolerance;
            m_lowerLimit            = desired - tolerance;
            m_settlingTimeInTicks   = settlingTimeInTicks;
            m_currentState          = ObserverStates.OutOfTolerance;
        }

        bool Tick(double observed)
        {
            if ((observed < m_lowerLimit) || (observed > m_upperLimit))
            {
                m_currentState = ObserverStates.OutOfTolerance;
                m_timeRemaining = m_settlingTimeInTicks;
                return false;
            }
            switch (m_currentState)
            {
                case ObserverStates.OutOfTolerance:
                    if ((m_lowerLimit <= observed) && (observed <= m_upperLimit))
                        m_currentState = ObserverStates.InTolerance;
                    return false;
                case ObserverStates.InTolerance:
                    if (m_timeRemaining-- == 0)
                        m_currentState = ObserverStates.Settled;
                    return false;
                case ObserverStates.Settled:
                    return true;
            }
            return false;
        }

        private ObserverStates  m_currentState;
        private double          m_desired;
        private double          m_upperLimit;
        private double          m_lowerLimit;
        private UInt32          m_timeRemaining;
        private UInt32          m_settlingTimeInTicks;
    }
}
