public void WaitForEventFallingEdgeTest() { TimeoutHelper.CompletesInTime(() => { using (GpioController controller = new GpioController(GetTestNumberingScheme(), GetTestDriver())) { CancellationTokenSource tokenSource = new CancellationTokenSource(); controller.OpenPin(InputPin, PinMode.Input); controller.OpenPin(OutputPin, PinMode.Output); controller.Write(OutputPin, PinValue.Low); Task.Run(() => { controller.Write(OutputPin, PinValue.High); Thread.Sleep(WaitMilliseconds); controller.Write(OutputPin, PinValue.Low); }); WaitForEventResult result = controller.WaitForEvent(InputPin, PinEventTypes.Falling, tokenSource.Token); Assert.False(result.TimedOut); Assert.Equal(PinEventTypes.Falling, result.EventTypes); } }, TimeSpan.FromSeconds(30)); }
public void ThrowsIfWaitingOnClosedPin() { using (GpioController controller = new GpioController(GetTestNumberingScheme(), GetTestDriver())) { Assert.Throws <InvalidOperationException>(() => controller.WaitForEvent(InputPin, PinEventTypes.Falling, CancellationToken.None)); } }
public HallEffectSensor() { var gpioController = new GpioController(PinNumberingScheme.Logical, new SysFsDriver()); gpioController.RegisterCallbackForPinValueChangedEvent(4, PinEventTypes.Falling | PinEventTypes.Rising, this.PinValueChanged); gpioController.WaitForEvent(3, PinEventTypes.Falling, CancellationToken.None); }
/// <summary> /// Reads previous reading and prepares next reading for specified channel /// </summary> /// <param name="channelToCharge">Channel to prepare</param> /// <returns>10 bit value corresponding to relative voltage level on channel</returns> public int ReadPreviousAndChargeChannel(Channel channelToCharge) { if (!IsValidChannel(channelToCharge)) { throw new ArgumentOutOfRangeException(nameof(channelToCharge)); } Span <byte> readBuffer = stackalloc byte[2]; Span <byte> writeBuffer = stackalloc byte[2]; writeBuffer[0] = (byte)((int)channelToCharge << 1); _spiDevice.TransferFullDuplex(writeBuffer, readBuffer); int previousReading = ((readBuffer[0] & 0b11111) << 5) | (readBuffer[1] & 0b11111); if (_endOfConversion != -1) { // Wait for ADC to report end of conversion or timeout at max conversion time _controller.WaitForEvent(_endOfConversion, PinEventTypes.Rising, _conversionTime); } else { // Max conversion time (21us) as seen in table on page 10 in TLC1543 documentation DelayHelper.Delay(_conversionTime, false); } return(previousReading); }
public void WaitForEventBothEdgesTest() { using (GpioController controller = new GpioController(GetTestNumberingScheme(), GetTestDriver())) { CancellationTokenSource tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(2000); controller.OpenPin(InputPin, PinMode.Input); controller.OpenPin(OutputPin, PinMode.Output); controller.Write(OutputPin, PinValue.High); // Wait for any events that happen because of the initialization controller.WaitForEvent(InputPin, PinEventTypes.Falling | PinEventTypes.Rising, tokenSource.Token); tokenSource.Dispose(); var task = Task.Run(() => { controller.Write(OutputPin, PinValue.High); Thread.Sleep(WaitMilliseconds); controller.Write(OutputPin, PinValue.Low); Thread.Sleep(WaitMilliseconds); controller.Write(OutputPin, PinValue.High); }); tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(WaitMilliseconds * 4); // First event is falling, second is rising WaitForEventResult result = controller.WaitForEvent(InputPin, PinEventTypes.Falling | PinEventTypes.Rising, tokenSource.Token); Assert.False(result.TimedOut); Assert.Equal(PinEventTypes.Falling, result.EventTypes); result = controller.WaitForEvent(InputPin, PinEventTypes.Falling | PinEventTypes.Rising, tokenSource.Token); Assert.False(result.TimedOut); Assert.Equal(PinEventTypes.Rising, result.EventTypes); Assert.True(task.Wait(TimeSpan.FromSeconds(30))); // Should end long before that tokenSource.Dispose(); } }
[Trait("SkipOnTestRun", "Windows_NT")] // The windows driver is returning none as the event type. public void WaitForEventCancelAfter10MillisecondsTest() { using (GpioController controller = new GpioController(GetTestNumberingScheme(), GetTestDriver())) { CancellationTokenSource tokenSource = new CancellationTokenSource(WaitMilliseconds); controller.OpenPin(InputPin, PinMode.Input); controller.OpenPin(OutputPin, PinMode.Output); controller.Write(OutputPin, PinValue.Low); WaitForEventResult result = controller.WaitForEvent(InputPin, PinEventTypes.Falling, tokenSource.Token); Assert.True(result.TimedOut); Assert.Equal(PinEventTypes.Falling, result.EventTypes); } }
public void WaitForEventSuccess() { var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); _mockedGpioDriver.Setup(x => x.OpenPinEx(1)); _mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(1, PinMode.Input)).Returns(true); _mockedGpioDriver.Setup(x => x.WaitForEventEx(1, PinEventTypes.Rising | PinEventTypes.Falling, It.IsAny <CancellationToken>())) .Returns(new WaitForEventResult() { EventTypes = PinEventTypes.Falling, TimedOut = false }); Assert.NotNull(ctrl); ctrl.OpenPin(1, PinMode.Input); var result = ctrl.WaitForEvent(1, PinEventTypes.Falling | PinEventTypes.Rising, TimeSpan.FromSeconds(0.01)); Assert.False(result.TimedOut); Assert.Equal(PinEventTypes.Falling, result.EventTypes); }
public WaitForEventResult WaitForEvent(int pinNumber, PinEventTypes eventTypes, TimeSpan timeout) { return(_controller.WaitForEvent(pinNumber, eventTypes, timeout)); }
/// <summary> /// The CCS811 sensor constructor /// </summary> /// <param name="i2cDevice">A valid I2C device</param> /// <param name="gpioController">An optional controller, either the default one will be used, either none will be created if any pin is used</param> /// <param name="pinWake">An awake pin, it is optional, this pin can be set to the ground if the sensor is always on</param> /// <param name="pinInterruption">An interruption pin when a measurement is ready, best use when you specify a threshold</param> /// <param name="pinReset">An optional hard reset pin</param> /// <param name="shouldDispose">Should the GPIO controller be disposed at the end</param> public Ccs811Sensor(I2cDevice i2cDevice, GpioController gpioController = null, int pinWake = -1, int pinInterruption = -1, int pinReset = -1, bool shouldDispose = true) { _i2cDevice = i2cDevice; _pinWake = pinWake; _pinInterruption = pinInterruption; _pinReset = pinReset; _shouldDispose = shouldDispose; // We need a GPIO controller only if we are using any of the pin if ((_pinInterruption >= 0) || (_pinReset >= 0) || (_pinWake >= 0)) { _shouldDispose = _shouldDispose || gpioController == null; _controller = gpioController ?? new GpioController(); } if (_pinWake >= 0) { _controller.OpenPin(_pinWake, PinMode.Output); _controller.Write(_pinWake, PinValue.High); } if (_pinReset >= 0) { _controller.OpenPin(_pinReset, PinMode.Output); _controller.Write(_pinReset, PinValue.Low); // Delays from documentation CCS811-Datasheet.pdf page 8 // 15 micro second DelayHelper.DelayMicroseconds(15, true); _controller.Write(_pinReset, PinValue.High); // Need to wait at least 2 milliseconds before executing anything I2C Thread.Sleep(2); } // Initialization flow page 29 // https://www.sciosense.com/wp-content/uploads/2020/01/CCS811-Application-Note-Programming-and-interfacing-guide.pdf // do a soft reset Span <byte> toReset = stackalloc byte[4] { 0x11, 0xE5, 0x72, 0x8A }; WriteRegister(Register.SW_RESET, toReset); // Wait 2 milliseconds as per documentation Thread.Sleep(2); if (HardwareIdentification != 0x81) { throw new IOException($"CCS811 does not have a valid ID: {HardwareIdentification}. ID must be 0x81."); } if ((HardwareVersion & 0xF0) != 0x10) { throw new IOException($"CCS811 does not have a valid version: {HardwareVersion}, should be 0x1X where any X is valid."); } // Read status if (!Status.HasFlag(Status.APP_VALID)) { throw new IOException($"CCS811 has no application firmware loaded."); } // Switch to app mode and wait 1 millisecond according to doc WriteRegister(Register.APP_START); Thread.Sleep(1); if (!Status.HasFlag(Status.FW_MODE)) { throw new IOException($"CCS811 is not in application mode."); } // Set interrupt if the interruption pin is valid if (_pinInterruption >= 0) { _controller.OpenPin(_pinInterruption, PinMode.Input); byte mode = 0b0000_1000; WriteRegister(Register.MEAS_MODE, mode); _controller.RegisterCallbackForPinValueChangedEvent(_pinInterruption, PinEventTypes.Falling, InterruptReady); _running = true; // Start a new thread to monitor the events new Thread(() => { _isRunning = true; while (_running) { var res = _controller.WaitForEvent(_pinInterruption, PinEventTypes.Falling, new TimeSpan(0, 0, 0, 0, 50)); if ((!res.TimedOut) && (res.EventTypes != PinEventTypes.None)) { InterruptReady(_controller, new PinValueChangedEventArgs(res.EventTypes, _pinInterruption)); // We know we won't get any new measurement in next 250 milliseconds at least // Waiting to make sure the sensor will have time to remove the interrupt pin Thread.Sleep(50); } } _isRunning = false; }).Start(); } }