/// <summary> /// Gets the mapped address for a register. /// </summary> /// <param name="register">The register.</param> /// <param name="port">The bank of I/O ports used with the register.</param> /// <param name="bankStyle">The bank style that determines how the register addresses are grouped.</param> /// <returns>The byte address of the register for the given port bank and bank style.</returns> private byte GetMappedAddress(Register register, Port port = Port.PortA, BankStyle bankStyle = BankStyle.Sequential) { if (port != Port.PortA && port != Port.PortB) { throw new ArgumentOutOfRangeException(nameof(port)); } if (bankStyle != BankStyle.Separated && bankStyle != BankStyle.Sequential) { throw new ArgumentOutOfRangeException(nameof(bankStyle)); } byte address = (byte)register; // There is no mapping for 8 bit expanders if (PinCount == 8) { return(address); } if (bankStyle == BankStyle.Sequential) { // Registers for each bank are sequential // (IODIRA = 0x00, IODIRB = 0x01, IPOLA = 0x02, IPOLB = 0x03, ...) address += address; return(port == Port.PortA ? address : ++address); } // Registers for each bank are separated // (IODIRA = 0x00, ... OLATA = 0x0A, IODIRB = 0x10, ... OLATB = 0x1A) return(port == Port.PortA ? address : address += 0x10); }
public void Get_Mapped_Address(Register register, Port port, BankStyle bankStyle, byte expectedMappedAddress) { TestMappedBus bus = new TestMappedBus(); McpMock mock = new McpMock(bus, bankStyle); mock.Write(register, port); Assert.Equal(expectedMappedAddress, bus.LastAddress); }
public void Get_Mapped_Address(Register register, Port port, BankStyle bankStyle, byte expectedMappedAddress) { SpiDeviceMock spiDeviceMock = new SpiDeviceMock(ports: 2); BankStyleMock mock = new BankStyleMock(spiDeviceMock, bankStyle); mock.Read(register, port); // Reads are full duplex- commands go to "Write" Assert.Equal(expectedMappedAddress, spiDeviceMock.DeviceMock.LastWriteBuffer[0]); }
/// <summary> /// A general purpose parallel I/O expansion for I2C or SPI applications. /// </summary> /// <param name="bus">The bus the device is connected to.</param> /// <param name="reset">The output pin number that is connected to the hardware reset.</param> /// <param name="interruptA">The input pin number that is connected to the interrupt for Port A (INTA).</param> /// <param name="interruptB">The input pin number that is connected to the interrupt for Port B (INTB).</param> /// <param name="masterController"> /// The controller for the reset and interrupt pins. If not specified, the default controller will be used. /// </param> /// <param name="bankStyle"> /// The current bank style of the ports. This does not set the bank style- it tells us what the bank style is. /// It is *highly* recommended not to change the bank style from the default as there is no direct way to /// detect what style the chip is in and most apps will fail if the chip is not set to defaults. This setting /// has no impact on 8-bit expanders. /// </param> /// <param name="shouldDispose">True to dispose the Gpio Controller</param> protected Mcp23xxx(BusAdapter bus, int reset = -1, int interruptA = -1, int interruptB = -1, GpioController masterController = null, BankStyle bankStyle = BankStyle.Sequential, bool shouldDispose = true) { _bus = bus; _bankStyle = bankStyle; _shouldDispose = masterController == null ? true : shouldDispose; _reset = reset; _interruptA = interruptA; _interruptB = interruptB; // Only need master controller if there are external pins provided. if (_reset != -1 || _interruptA != -1 || _interruptB != -1) { _masterGpioController = masterController ?? new GpioController(); if (_interruptA != -1) { _masterGpioController.OpenPin(_interruptA, PinMode.Input); } if (_interruptB != -1) { _masterGpioController.OpenPin(_interruptB, PinMode.Input); } if (_reset != -1) { _masterGpioController.OpenPin(_reset, PinMode.Output); Disable(); } } if (!_disabled) { // Set all of the pins to input, GPIO outputs to low, and set input polarity to match the input. // This is the normal power-on / reset state of the Mcp23xxx chips. if (PinCount == 8) { InternalWriteByte(Register.IODIR, 0xFF, Port.PortA); InternalWriteByte(Register.GPIO, 0x00, Port.PortA); InternalWriteByte(Register.IPOL, 0x00, Port.PortA); } else { InternalWriteUInt16(Register.IODIR, 0xFFFF); InternalWriteUInt16(Register.GPIO, 0x0000); InternalWriteUInt16(Register.IPOL, 0x0000); } } }
/// <summary> /// Disables the device by setting the reset pin low. /// </summary> public void Disable() { if (_reset == -1) { throw new InvalidOperationException("No reset pin configured."); } _masterGpioController.Write(_reset, PinValue.Low); // Registers will all be reset when re-enabled _bankStyle = BankStyle.Sequential; _increments = true; _disabled = true; }
public BankStyleMock(SpiDevice device, BankStyle bankStyle) : base(new SpiAdapter(device, 0x20), bankStyle: bankStyle) { }
public McpMock(IBusDevice device, BankStyle bankStyle) : base(device, 0x20, bankStyle: bankStyle) { }