/// <summary>
        ///     Every n loops, issue the specified credit value
        /// </summary>
        /// <param name="loops">Count of loops between credits</param>
        /// <param name="count">Run this many times. -1 to loop forever.</param>
        /// <param name="creditIndices">Credits to issue</param>
        public T CreditEveryNLoops(int loops, int count, params byte[] creditIndices)
        {
            // Create a new validator so we have perfect control of the state
            var validator = new ApexValidator(Config);

            // Setup a semaphore to wait for this many polling loops
            var sem = new EmulationLoopSemaphore(_token)
            {
                SignalAt = loops * count
            };

            // Start in idling state
            _emulator.CurrentState  = Rs232State.Idling;
            _emulator.CurrentEvents = Rs232Event.None;

            var next = 0;

            _emulator.OnPollResponseSent += sem.LoopCallback;
            sem.OnLoopCalled             += (sender, args) =>
            {
                switch (_emulator.CurrentState)
                {
                case Rs232State.None:
                    _emulator.CurrentState  = Rs232State.Idling;
                    _emulator.CurrentEvents = Rs232Event.None;
                    break;

                case Rs232State.Idling:
                    if (sem.Iterations % loops == 0)
                    {
                        _emulator.CurrentState  = Rs232State.Accepting;
                        _emulator.CurrentEvents = Rs232Event.None;
                    }

                    break;

                case Rs232State.Accepting:
                    _emulator.CurrentState  = Rs232State.Stacking;
                    _emulator.CurrentEvents = Rs232Event.None;
                    break;

                case Rs232State.Stacking:
                    _emulator.CurrentState  = Rs232State.Idling;
                    _emulator.CurrentEvents = Rs232Event.Stacked;
                    _emulator.Credit        = creditIndices[next++ % creditIndices.Length];
                    break;
                }
            };

            validator.StartPollingLoop();

            // Wait for signal
            sem.Gate.WaitOne();

            // Cleanup
            validator.StopPollingLoop();
            _emulator.OnPollResponseSent -= sem.LoopCallback;

            return(_emulator);
        }
        /// <summary>
        ///     Runs polling loop this many times at a minimum.
        ///     Due to timing limitations, this is a minimum run count
        ///     and their may be 1 or more extra loops executed.
        /// </summary>
        /// <param name="loops">Loops to run</param>
        /// <returns></returns>
        public T RunIdleFor(int loops)
        {
            // Setup a semaphore to wait for this many polling loops
            var sem = new EmulationLoopSemaphore(_token)
            {
                SignalAt = loops
            };

            _emulator.OnPollResponseSent += sem.LoopCallback;
            sem.OnLoopCalled             += (sender, args) =>
            {
                // Always be idle
                _emulator.CurrentState = Rs232State.Idling;
            };

            // Create a new validator so we have perfect control of the state
            var validator = new ApexValidator(Config);

            validator.StartPollingLoop();

            // Wait for signal
            sem.Gate.WaitOne();

            // Cleanup
            validator.StopPollingLoop();
            _emulator.OnPollResponseSent -= sem.LoopCallback;

            return(_emulator);
        }