/// <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> /// Runs the decoder thread. /// </summary> /// <param name="inputBuffer">Buffer from which new PWM values are read.</param> /// <param name="inputTrigger">Trigger which is fired by the caller when new data arrives.</param> /// <param name="outputBuffer">Buffer into which decoded PWM frames are written.</param> /// <param name="outputTrigger">Trigger which is fired by this decoder when new data has been decoded.</param> /// <param name="stop">Signals when the decoder should stop.</param> public void DecodePulse(ConcurrentQueue <PwmValue> inputBuffer, AutoResetEvent inputTrigger, ConcurrentQueue <PwmFrame> outputBuffer, AutoResetEvent outputTrigger, CancellationToken stop) { // Decode until stopped... while (!stop.IsCancellationRequested) { // Wait for value in queue... PwmValue value; if (!inputBuffer.TryDequeue(out value)) { inputTrigger.WaitOne(PwmSyncLengthMinium * 2); continue; } // Decode values into cycles... var time = value.Time; if (value.Level) { // Low -> high (mid-cycle) _cycle.HighTime = time; _cycle.LowLength = time - _cycle.LowTime; } else { // High -> low (end of cycle) _cycle.HighLength = time - _cycle.HighTime; // Prepare next value var cycle = _cycle; _cycle = new PwmCycle(time); // Decode cycles into frames... var frame = DecodeCycle(cycle); if (frame != null) { // Output frame when decoding complete outputBuffer.Enqueue(frame); outputTrigger.Set(); } } } }
/// <summary> /// Runs the decoder thread. /// </summary> /// <param name="inputBuffer">Buffer from which new PWM values are read.</param> /// <param name="inputTrigger">Trigger which is fired by the caller when new data arrives.</param> /// <param name="outputBuffer">Buffer into which decoded PWM frames are written.</param> /// <param name="outputTrigger">Trigger which is fired by this decoder when new data has been decoded.</param> /// <param name="stop">Signals when the decoder should stop.</param> public void DecodePulse(ConcurrentQueue<PwmValue> inputBuffer, AutoResetEvent inputTrigger, ConcurrentQueue<PwmFrame> outputBuffer, AutoResetEvent outputTrigger, CancellationToken stop) { // Decode until stopped... while (!stop.IsCancellationRequested) { // Wait for value in queue... PwmValue value; if (!inputBuffer.TryDequeue(out value)) { inputTrigger.WaitOne(PwmSyncLengthMinium * 2); continue; } // Decode values into cycles... var time = value.Time; if (value.Level) { // Low -> high (mid-cycle) _cycle.HighTime = time; _cycle.LowLength = time - _cycle.LowTime; } else { // High -> low (end of cycle) _cycle.HighLength = time - _cycle.HighTime; // Prepare next value var cycle = _cycle; _cycle = new PwmCycle(time); // Decode cycles into frames... var frame = DecodeCycle(cycle); if (frame != null) { // Output frame when decoding complete outputBuffer.Enqueue(frame); outputTrigger.Set(); } } } }
/// <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; }