public override void SetupComponent() { if (_pin == Cpu.Pin.GPIO_NONE || _pin < 0) { throw new Exception("The GpioPort has an invalid pin."); } if ((_modesExpected & _modesAllowed) != _modesExpected) { throw new InvalidOperationException("All modes expected have to be allowed: expected = " + _modesExpected.ToString() + "; allowed = " + _modesAllowed.ToString()); } _isReserved = false; _mode = GpioPortMode.None; _state = false; _stateInitialized = false; _interruptMode = GpioInterruptMode.None; _resistorMode = GpioResistorMode.Disabled; _debounceMode = DebounceMode.None; }
internal void DeviceEnableAsInputPort(bool glitchFilter, GpioResistorMode resistorMode, GpioInterruptMode interruptMode, IntPtr isr, IntPtr isrParam) { if ((_modesExpected & GpioPortMode.InputPort) == 0) { if ((this is GpioPortNull) == false) // We put an warning about accessing a non-existing port in DeviceGet already { Trace.WriteLine("Attempt to initialize GPIO Port " + Pin + " as an input port when it's expecting " + _modesExpected.ToString()); } return; } if (_mode != GpioPortMode.None) { // return the port to a Disabled state first if it wasn't previously disabled. DeviceDisablePort(); } _interruptMode = interruptMode; _isr = isr; _isrParam = isrParam; _resistorMode = resistorMode; if (glitchFilter) { _debounceMode = (this.Emulator.GpioPorts.HardwareDebounceSupported) ? DebounceMode.HardwareDebounce : DebounceMode.SoftwareDebounce; } else { _debounceMode = DebounceMode.None; } _mode = GpioPortMode.InputPort; if (_stateInitialized == false) { // Since the pullup/pulldown are meant for as a way to avoid floating values, we shouldn't count the state as initialized. // We just simply set the state appropriately. if (_resistorMode == GpioResistorMode.PullUp) { _state = true; } else if (_resistorMode == GpioResistorMode.PullDown) { _state = false; } } if (_interruptMode != GpioInterruptMode.None) { if (isr.Equals(IntPtr.Zero)) { Debug.Assert(false, "Invalid ISR."); Trace.WriteLine("Error: Interrupt port " + _pin + " has an invalid ISR."); return; } if ((interruptMode == GpioInterruptMode.LevelHigh && _state == true) || (interruptMode == GpioInterruptMode.LevelLow && _state == false)) { HandleDebounce(true); // Note that HandleDebounce will make this function re-entrant if it's a level interrupt. return; } } else { _isr = IntPtr.Zero; _isrParam = IntPtr.Zero; } }
public Action <T1> Debounce <T1>(Action <DebounceMode, T1> function, TimeSpan wait, DebounceMode mode = DebounceMode.Trailing) { var cancellationTokenSource = new CancellationTokenSource(); var leadCancellationTokenSource = new CancellationTokenSource(); var leadCancelled = false; var lockObject = new object(); var leadLockObject = new object(); return((t1) => { lock (lockObject) { cancellationTokenSource.Cancel(); cancellationTokenSource = new CancellationTokenSource(); } Task.Delay(wait, cancellationTokenSource.Token) .ContinueWith(task => { if (mode > DebounceMode.Leading && !task.IsCanceled) { leadCancelled = false; function(DebounceMode.Trailing, t1); } }); if (mode < DebounceMode.Trailing && !leadCancelled) { leadCancelled = true; Task.Delay(wait, leadCancellationTokenSource.Token) .ContinueWith(task => { if (!task.IsCanceled) { lock (leadLockObject) { leadCancellationTokenSource.Cancel(); leadCancellationTokenSource = new CancellationTokenSource(); } } }); function(DebounceMode.Leading, t1); } }); }