/// <summary> /// Called when a single infrared sensor pulse becomes available. /// </summary> /// <param name="pulse">The pulse.</param> private void OnInfraredSensorPulseAvailable(InfraRedPulse pulse) { PulseAvailable?.Invoke(this, new InfraRedSensorPulseEventArgs(pulse)); }
/// <summary> /// Initializes a new instance of the <see cref="InfraRedSensorPulseEventArgs" /> class. /// </summary> /// <param name="pulse">The pulse.</param> internal InfraRedSensorPulseEventArgs(InfraRedPulse pulse) : base() { 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 Native.HighResolutionTimer(); var idleTimer = new Native.HighResolutionTimer(); var pulseBuffer = new List <InfraRedPulse>(MaxPulseCount); var syncLock = new object(); var idleChecker = default(Timer); idleChecker = new Timer((s) => { if (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.RisingAndFallingEdges, () => { IsInReadInterrupt = true; lock (syncLock) { idleTimer.Restart(); idleChecker.Change(IdleCheckIntervalMilliSecs, IdleCheckIntervalMilliSecs); var currentLength = pulseTimer.ElapsedMicroseconds; var currentValue = InputPin.Read(); var pulse = new InfraRedPulse(currentValue, currentLength.Clamp(MinElapsedMicroseconds, MaxElapsedMicroseconds)); // Restart for the next bit coming in pulseTimer.Restart(); // 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); }