/// <summary>
        /// Move focuser by a number of steps
        /// </summary>
        /// <param name="val">val is the number of steps, + or -, + means out, - means in</param>        
        public void Move(int val)
        {

            GeminiHardware.Instance.Trace.Enter("IF:Move", val.ToString());                

            if (m_State != FocuserState.None) Halt();


            if (GeminiHardware.Instance.AbsoluteFocuser)
                val = val * GeminiHardware.Instance.StepSize - m_Position; // how far to move from current position
            else
                val = val * GeminiHardware.Instance.StepSize;

            val /= GeminiHardware.Instance.StepSize;



            // limit the move to max increment setting
            if (Math.Abs(val) > GeminiHardware.Instance.MaxIncrement)
                val = GeminiHardware.Instance.MaxIncrement * Math.Sign(val);

            GeminiHardware.Instance.Trace.Info(3, "Move Value", val.ToString());

            if (val == 0)
            {
                GeminiHardware.Instance.Trace.Exit("IF:Move", tmrFocus.Enabled);
                return;
            }

            if (GeminiHardware.Instance.BacklashDirection != 0 && Math.Sign(GeminiHardware.Instance.BacklashDirection) == Math.Sign(val))
            {
                m_State = FocuserState.Backlash;
                m_PreviousMove = val;

                if ((val > 0 && !GeminiHardware.Instance.ReverseDirection) || (val < 0 && GeminiHardware.Instance.ReverseDirection))
                    GeminiHardware.Instance.DoCommand(":F+",false);
                else
                    GeminiHardware.Instance.DoCommand(":F-", false);

                tmrFocus.Interval = (GeminiHardware.Instance.StepSize * GeminiHardware.Instance.BacklashSize);
                GeminiHardware.Instance.Trace.Info(3, "Setting Backlash", tmrFocus.Interval.ToString());

                tmrFocus.Start();
            }
            else
            {
                m_State = FocuserState.Focusing;
                m_PreviousMove = val;
                if ((val > 0 && !GeminiHardware.Instance.ReverseDirection) || (val < 0 && GeminiHardware.Instance.ReverseDirection))
                    GeminiHardware.Instance.DoCommand(":F+", false);
                else
                    GeminiHardware.Instance.DoCommand(":F-", false);

                tmrFocus.Interval = (GeminiHardware.Instance.StepSize * Math.Abs(val));
                GeminiHardware.Instance.Trace.Info(3, "Focuser", tmrFocus.Interval.ToString());
                tmrFocus.Start();

            }
            GeminiHardware.Instance.Trace.Exit("IF:Move", tmrFocus.Enabled);                 
        }
        /// <summary>
        /// Executed on a timer when waiting to complete a focuser move
        /// </summary>
        void tmrFocus_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            tmrFocus.Stop();
            int val = m_PreviousMove;

            GeminiHardware.Instance.Trace.Enter("Focuser:Timer", m_State.ToString(), m_PreviousMove, m_Position);

            // if we were taking up backlash prior to this,
            // move on to actual focusing command:
            if (m_State == FocuserState.Backlash)
            {
                m_State = FocuserState.Focusing;

                if ((val > 0 && !GeminiHardware.Instance.ReverseDirection) || (val < 0 && GeminiHardware.Instance.ReverseDirection))
                    GeminiHardware.Instance.DoCommand(":F+", false);
                else
                    GeminiHardware.Instance.DoCommand(":F-", false);
                tmrFocus.Interval = (GeminiHardware.Instance.StepSize * Math.Abs(val));
                tmrFocus.Start();
                GeminiHardware.Instance.Trace.Exit("Focuser:Timer", m_State.ToString(), m_PreviousMove, m_Position);
                return;
            }
            // if we are done with focusing, check if braking is enabled
            // and execute a break maneuver (move in the opposite direction for a bit)
            else if (m_State == FocuserState.Focusing)
            {
                if (GeminiHardware.Instance.BrakeSize > 0)
                {
                    // move in the opposite direction for specified step*interval
                    if ((val > 0 && !GeminiHardware.Instance.ReverseDirection) || (val < 0 && GeminiHardware.Instance.ReverseDirection))
                        GeminiHardware.Instance.DoCommand(":F-", false);
                    else
                        GeminiHardware.Instance.DoCommand(":F+", false);

                    tmrFocus.Interval = (GeminiHardware.Instance.StepSize * GeminiHardware.Instance.BrakeSize);
                    tmrFocus.Start();
                    GeminiHardware.Instance.Trace.Exit("Focuser:Timer", m_State.ToString(), m_PreviousMove, m_Position);
                    return;
                }
            }

            // at this point, we're done focusing!
            Halt();
            m_Position += m_PreviousMove * GeminiHardware.Instance.StepSize;  // new position 
            GeminiHardware.Instance.Trace.Exit("Foc:Timer", m_State.ToString(), m_PreviousMove, m_Position);
        }
        /// <summary>
        /// Stop focusing
        /// </summary>
        public void Halt()
        {
            GeminiHardware.Instance.Trace.Enter("Foc:Halt", m_State.ToString());
            tmrFocus.Stop();
            m_State = FocuserState.None;

            GeminiHardware.Instance.DoCommand(":FQ", false);
        }