Contains data and definitions of an RC input PWM frame.
Used as a standard variable container for both "PWM" (single channel) and other multi-channel protocols such as CPPM (a.k.a. PPM-Sum).
        /// <summary>
        /// Updates the display when the <see cref="Device"/> channels change.
        /// </summary>
        private void OnChannelsChanged(object sender, PwmFrame frame)
        {
            // Dump statistics to output
            WriteOutput(frame.ToString());

            // Update display
            DoPropertyChanged(nameof(Device));
        }
        /// <summary>
        /// Decodes the incoming PWM signal (each complete cycle) using the CPPM protocol.
        /// </summary>
        /// <param name="cycle">PWM cycle to decode.</param>
        /// <returns>
        /// <see cref="PwmFrame"/> when complete else null whilst decoding or skipping invalid cycles.
        /// </returns>
        private PwmFrame DecodeCycle(PwmCycle cycle)
        {
            // Validate
            if (!cycle.IsValid() || cycle.LowLength >= PwmLowLimit)
            {
                // Discard frame
                _channel = null;
                return(null);
            }

            // Detect start frame
            if (cycle.HighLength >= PwmSyncLengthMinium)
            {
                // Start decoding from channel 0 at next pulse
                _channel = 0;
                _frame   = new PwmFrame(cycle.LowTime, new int[ChannelCount]);
                return(null);
            }

            // Do nothing when not decoding
            if (!_channel.HasValue)
            {
                return(null);
            }
            var decodeIndex = _channel.Value;

            // Store channel value whilst decoding
            if (decodeIndex < ChannelCount)
            {
                // Store channel value
                _frame.Channels[decodeIndex] = (int)cycle.Length;

                // Wait for next channel...
                _channel = decodeIndex + 1;

                // Complete frame when all channels decoded...
                if (decodeIndex == ChannelCount - 1)
                {
                    var frame = _frame;
                    _frame = null;
                    return(frame);
                }
            }

            // Continue...
            return(null);
        }
 /// <summary>
 /// Receives updates when new PWM frames arrive.
 /// </summary>
 private void OnChannelsChanged(object sender, PwmFrame frame)
 {
     // Write contents to the debug output
     Debug.WriteLine(frame);
 }
        /// <summary>
        /// Decodes the incoming PWM signal (each complete cycle) using the CPPM protocol.
        /// </summary>
        /// <param name="cycle">PWM cycle to decode.</param>
        /// <returns>
        /// <see cref="PwmFrame"/> when complete else null whilst decoding or skipping invalid cycles.
        /// </returns>
        private PwmFrame DecodeCycle(PwmCycle cycle)
        {
            // Validate
            if (!cycle.IsValid() || cycle.LowLength >= PwmLowLimit)
            {
                // Discard frame
                _channel = null;
                return null;
            }

            // Detect start frame
            if (cycle.HighLength >= PwmSyncLengthMinium)
            {
                // Start decoding from channel 0 at next pulse
                _channel = 0;
                _frame = new PwmFrame(cycle.LowTime, new int[ChannelCount]);
                return null;
            }

            // Do nothing when not decoding
            if (!_channel.HasValue)
                return null;
            var decodeIndex = _channel.Value;

            // Store channel value whilst decoding
            if (decodeIndex < ChannelCount)
            {
                // Store channel value
                _frame.Channels[decodeIndex] = (int)cycle.Length;

                // Wait for next channel...
                _channel = decodeIndex + 1;

                // Complete frame when all channels decoded...
                if (decodeIndex == ChannelCount - 1)
                {
                    var frame = _frame;
                    _frame = null;
                    return frame;
                }
            }

            // Continue...
            return null;
        }