/// <summary> /// Called when a single infrared sensor pulse becomes available. /// </summary> /// <param name="pulse">The pulse.</param> private void OnInfraredSensorPulseAvailable(InfraredPulse pulse) { if (_isDisposed || PulseAvailable == null) { return; } var args = new InfraredSensorPulseEventArgs(pulse); ThreadPool.QueueUserWorkItem(a => { PulseAvailable?.Invoke(this, a as InfraredSensorPulseEventArgs); }, args); }
/// <summary> /// Initializes a new instance of the <see cref="InfraredSensorPulseEventArgs" /> class. /// </summary> /// <param name="pulse">The pulse.</param> internal InfraredSensorPulseEventArgs(InfraredPulse pulse) { Value = pulse.Value; DurationUsecs = pulse.DurationUsecs; }
/// <summary> /// Reads the interrupt do work. /// </summary> private void ReadInterruptDoWork() { // Define some constants const long gapUsecs = 5000; const long maxElapsedMicroseconds = 250000; const long minElapsedMicroseconds = 50; const int idleCheckIntervalMilliSecs = 32; const int maxPulseCount = 128; // Setup the input pin InputPin.PinMode = GpioPinDriveMode.Input; InputPin.InputPullMode = GpioPinResistorPullMode.PullUp; // Get the timers started! var pulseTimer = new HighResolutionTimer(); var idleTimer = new HighResolutionTimer(); var pulseBuffer = new List <InfraredPulse>(maxPulseCount); var syncLock = new object(); _idleChecker = new Timer(s => { if (_isDisposed || _isInReadInterrupt) { return; } lock (syncLock) { if (idleTimer.ElapsedMicroseconds < gapUsecs || idleTimer.IsRunning == false || pulseBuffer.Count <= 0) { return; } OnInfraredSensorRawDataAvailable(pulseBuffer.ToArray(), ReceiverFlushReason.Idle); pulseBuffer.Clear(); idleTimer.Reset(); } }); InputPin.RegisterInterruptCallback(EdgeDetection.FallingAndRisingEdge, () => { if (_isDisposed) { return; } _isInReadInterrupt = true; lock (syncLock) { idleTimer.Restart(); _idleChecker.Change(idleCheckIntervalMilliSecs, idleCheckIntervalMilliSecs); var currentLength = pulseTimer.ElapsedMicroseconds; var pulse = new InfraredPulse( IsActiveLow ? !_currentValue : _currentValue, currentLength.Clamp(minElapsedMicroseconds, maxElapsedMicroseconds)); // Restart for the next bit coming in pulseTimer.Restart(); // For the next value _currentValue = InputPin.Read(); // Do not add an idling pulse if (pulse.DurationUsecs < maxElapsedMicroseconds) { pulseBuffer.Add(pulse); OnInfraredSensorPulseAvailable(pulse); } if (pulseBuffer.Count >= maxPulseCount) { OnInfraredSensorRawDataAvailable(pulseBuffer.ToArray(), ReceiverFlushReason.Overflow); pulseBuffer.Clear(); } } _isInReadInterrupt = false; }); // Get the timers started pulseTimer.Start(); idleTimer.Start(); _idleChecker.Change(0, idleCheckIntervalMilliSecs); }