/// <summary> /// Read the given pins with the given pin numbers. /// </summary> /// <param name="pinValuePairs">The pin/value pairs to read.</param> public void Read(Span <PinValuePair> pinValuePairs) { for (int i = 0; i < pinValuePairs.Length; i++) { pinValuePairs[i] = new PinValuePair(pinValuePairs[i].PinNumber, Read(pinValuePairs[i].PinNumber)); } }
/// <summary> /// Reads the value of a set of pins /// </summary> protected void Read(Span <PinValuePair> pinValuePairs) { (uint pins, _) = new PinVector32(pinValuePairs); if ((pins >> PinCount) > 0) { ThrowBadPin(nameof(pinValuePairs)); } ushort result; if (pins < 0xFF + 1) { // Only need to get the first 8 pins (PortA) result = InternalReadByte(Register.GPIO, Port.PortA); } else if ((pins & 0xFF) == 0) { // Only need to get the second 8 pins (PortB) result = (ushort)(InternalReadByte(Register.GPIO, Port.PortB) << 8); } else { // Need to get both result = InternalReadUInt16(Register.GPIO); } for (int i = 0; i < pinValuePairs.Length; i++) { int pin = pinValuePairs[i].PinNumber; pinValuePairs[i] = new PinValuePair(pin, result & (1 << pin)); } }
public void WriteSpan() { _mockedGpioDriver.Setup(x => x.OpenPinEx(1)); _mockedGpioDriver.Setup(x => x.OpenPinEx(2)); _mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(1, PinMode.Output)).Returns(true); _mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(2, PinMode.Output)).Returns(true); _mockedGpioDriver.Setup(x => x.GetPinModeEx(1)).Returns(PinMode.Output); _mockedGpioDriver.Setup(x => x.GetPinModeEx(2)).Returns(PinMode.Output); _mockedGpioDriver.Setup(x => x.WriteEx(1, PinValue.High)); _mockedGpioDriver.Setup(x => x.WriteEx(2, PinValue.Low)); _mockedGpioDriver.Setup(x => x.ClosePinEx(1)); _mockedGpioDriver.Setup(x => x.ClosePinEx(2)); var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); Assert.NotNull(ctrl); ctrl.OpenPin(1, PinMode.Output); ctrl.OpenPin(2, PinMode.Output); Assert.True(ctrl.IsPinOpen(1)); Span <PinValuePair> towrite = stackalloc PinValuePair[2]; towrite[0] = new PinValuePair(1, PinValue.High); towrite[1] = new PinValuePair(2, PinValue.Low); ctrl.Write(towrite); ctrl.ClosePin(1); ctrl.ClosePin(2); Assert.False(ctrl.IsPinOpen(1)); }
public void Read(Span <PinValuePair> pinValues) { for (int i = 0; i < pinValues.Length; i++) { int pin = pinValues[i].PinNumber; pinValues[i] = new PinValuePair(pin, Read(pin)); } }
public void Read(Span <PinValuePair> pinValuePairs) { WriteLine($"{nameof(Read)}(pinValuePairs):"); for (int i = 0; i < pinValuePairs.Length; i++) { var pair = pinValuePairs[i]; pinValuePairs[i] = new PinValuePair(pair.PinNumber, Read(pair.PinNumber)); } }
/// <summary> /// Reads multiple pins from the device /// </summary> /// <param name="pinValues">Pins and values to be read</param> public void Read(Span <PinValuePair> pinValues) { (uint pins, _) = new PinVector32(pinValues); if (pins >> PinCount > 0) { ThrowInvalidPin(nameof(pinValues)); } if ((pins & _pinModes) != 0) { // One of the specified pins was set to output (1) throw new InvalidOperationException("Cannot read from output pins."); } ushort data = PinCount == 8 ? ReadByte() : InternalReadUInt16(); for (int i = 0; i < pinValues.Length; i++) { int pin = pinValues[i].PinNumber; pinValues[i] = new PinValuePair(pin, (data >> pin) & 1); } }
public void ReadSpan() { _mockedGpioDriver.Setup(x => x.OpenPinEx(1)); _mockedGpioDriver.Setup(x => x.OpenPinEx(2)); _mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(1, PinMode.Input)).Returns(true); _mockedGpioDriver.Setup(x => x.IsPinModeSupportedEx(2, PinMode.Input)).Returns(true); _mockedGpioDriver.Setup(x => x.ReadEx(1)).Returns(PinValue.Low); _mockedGpioDriver.Setup(x => x.ReadEx(2)).Returns(PinValue.High); _mockedGpioDriver.Setup(x => x.ClosePinEx(1)); _mockedGpioDriver.Setup(x => x.ClosePinEx(2)); var ctrl = new GpioController(PinNumberingScheme.Logical, _mockedGpioDriver.Object); Assert.NotNull(ctrl); ctrl.OpenPin(1, PinMode.Input); ctrl.OpenPin(2, PinMode.Input); Assert.True(ctrl.IsPinOpen(1)); // Invalid usage (we need to prefill the array) // Was this the intended use case? Assert.Throws <InvalidOperationException>(() => { Span <PinValuePair> wrongArg = stackalloc PinValuePair[2]; ctrl.Read(wrongArg); }); Span <PinValuePair> toread = stackalloc PinValuePair[2]; toread[0] = new PinValuePair(1, PinValue.Low); toread[1] = new PinValuePair(2, PinValue.Low); ctrl.Read(toread); Assert.Equal(1, toread[0].PinNumber); Assert.Equal(2, toread[1].PinNumber); Assert.Equal(PinValue.Low, toread[0].PinValue); Assert.Equal(PinValue.High, toread[1].PinValue); ctrl.ClosePin(1); ctrl.ClosePin(2); Assert.False(ctrl.IsPinOpen(1)); }
private void WriteBits(byte bits, int count) { int changedCount = 0; for (int i = 0; i < count; i++) { int newBit = (bits >> i) & 1; if (!_useLastByte) { _pinBuffer[changedCount++] = new PinValuePair(_dataPins[i], newBit); } else { // Each bit change takes ~23μs, so only change what we have to // This is particularly impactful when using all 8 data lines. int oldBit = (_lastByte >> i) & 1; if (oldBit != newBit) { _pinBuffer[changedCount++] = new PinValuePair(_dataPins[i], newBit); } } } if (changedCount > 0) { _controller.Write(new ReadOnlySpan <PinValuePair>(_pinBuffer, 0, changedCount)); } _useLastByte = true; _lastByte = bits; // Enable pin needs to be high for at least 450ns when running on 3V // and 230ns on 5V. (PWeh on page 49/52 and Figure 25 on page 58) _controller.Write(_enablePin, PinValue.High); DelayHelper.DelayMicroseconds(1, allowThreadYield: false); _controller.Write(_enablePin, PinValue.Low); }