### Create a TCA9554 driver instance Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Initializes the driver with an I2C peripheral and a specific device address. The driver takes ownership of the I2C bus. ```rust use tca9554::{Address, Tca9554}; // Create driver for standard TCA9554 variant (base address 0x20) let i2c = get_i2c_peripheral(); // Your platform-specific I2C let mut driver = Tca9554::new(i2c, Address::standard()); // Create driver for TCA9554A variant (base address 0x38) let i2c_alt = get_i2c_peripheral(); let mut driver_alt = Tca9554::new(i2c_alt, Address::alternate()); // Create driver with custom address pins A2, A1, A0 set to (true, false, true) // This gives address 0x20 | 0b101 = 0x25 for standard variant let i2c_custom = get_i2c_peripheral(); let address = Address::standard().with_selectable_bits((true, false, true)); let mut driver_custom = Tca9554::new(i2c_custom, address); ``` -------------------------------- ### Read input pin states Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Reads the current logic level of all 8 I/O pins and demonstrates how to check individual pin states. ```rust use tca9554::{Address, Tca9554}; async fn read_buttons(i2c: impl embedded_hal_async::i2c::I2c) -> Result<(), impl core::fmt::Debug> { let mut driver = Tca9554::new(i2c, Address::standard()); // Configure all pins as inputs driver.write_direction(0xFF).await?; // Read current state of all input pins let input_state = driver.read_input().await?; // Check individual pin states let pin0_high = (input_state & 0x01) != 0; let pin7_high = (input_state & 0x80) != 0; // Example: Check if button on P2 is pressed (active low) let button_pressed = (input_state & 0x04) == 0; Ok(()) } ``` -------------------------------- ### Check Default State Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Verifies if registers match power-on defaults, useful for detecting configuration changes. ```rust use tca9554::{Address, Tca9554}; async fn verify_chip_state(i2c: impl embedded_hal_async::i2c::I2c) -> Result { let mut driver = Tca9554::new(i2c, Address::standard()); // Check if chip is in power-on default state let is_default = driver.is_in_default_state().await?; if !is_default { // Chip has been configured - reset if needed driver.reset().await?; // Verify reset was successful let now_default = driver.is_in_default_state().await?; assert!(now_default); } Ok(is_default) } ``` -------------------------------- ### Configure pin direction Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Sets the direction of I/O pins using bitmasks, where 1 represents input and 0 represents output. ```rust use tca9554::{Address, Tca9554}; async fn configure_pins(i2c: impl embedded_hal_async::i2c::I2c) -> Result<(), impl core::fmt::Debug> { let mut driver = Tca9554::new(i2c, Address::standard()); // Set pins P0-P3 as outputs (0), P4-P7 as inputs (1) // Binary: 0b11110000 = 0xF0 driver.write_direction(0xF0).await?; // Read back current direction configuration let direction = driver.read_direction().await?; assert_eq!(direction, 0xF0); // Set all pins as outputs driver.write_direction(0x00).await?; // Set all pins as inputs (power-on default) driver.write_direction(0xFF).await?; Ok(()) } ``` -------------------------------- ### Reset to Power-On Defaults Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Resets all writable registers to their default state to ensure a known configuration. ```rust use tca9554::{Address, Tca9554}; async fn initialize_expander(i2c: impl embedded_hal_async::i2c::I2c) -> Result<(), impl core::fmt::Debug> { let mut driver = Tca9554::new(i2c, Address::standard()); // Reset to power-on defaults: // - Direction: 0xFF (all inputs) // - Polarity: 0x00 (no inversion) // - Output: 0xFF (all high) driver.reset().await?; // Verify chip is in default state let is_default = driver.is_in_default_state().await?; assert!(is_default); // Now configure for your application driver.write_direction(0x0F).await?; // P0-P3 outputs, P4-P7 inputs driver.write_output(0x00).await?; // All outputs low Ok(()) } ``` -------------------------------- ### Configure Polarity Inversion Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Inverts logic levels for input pins, useful for normalizing active-low signals. ```rust use tca9554::{Address, Tca9554}; async fn invert_inputs(i2c: impl embedded_hal_async::i2c::I2c) -> Result<(), impl core::fmt::Debug> { let mut driver = Tca9554::new(i2c, Address::standard()); // Configure all pins as inputs driver.write_direction(0xFF).await?; // Enable polarity inversion for P0-P3 (active-low buttons) // Now a low signal on these pins will read as 1 driver.write_polarity(0x0F).await?; // Read polarity configuration let polarity = driver.read_polarity().await?; assert_eq!(polarity, 0x0F); // Read input - inverted pins now show 1 when physically low let input = driver.read_input().await?; // Disable all polarity inversion (power-on default) driver.write_polarity(0x00).await?; Ok(()) } ``` -------------------------------- ### Configure I2C addresses Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Constructs addresses for TCA9554 variants and configures external address pins to support multiple devices on the same bus. ```rust use tca9554::Address; // Standard TCA9554 base address: 0x20 (7-bit) let addr_standard = Address::standard(); // Alternate TCA9554A base address: 0x38 (7-bit) let addr_alternate = Address::alternate(); // Configure address pins for multiple devices on the same bus // Device 0: A2=0, A1=0, A0=0 -> address 0x20 let device0 = Address::standard().with_selectable_bits((false, false, false)); // Device 1: A2=0, A1=0, A0=1 -> address 0x21 let device1 = Address::standard().with_selectable_bits((false, false, true)); // Device 2: A2=0, A1=1, A0=0 -> address 0x22 let device2 = Address::standard().with_selectable_bits((false, true, false)); // Device 7: A2=1, A1=1, A0=1 -> address 0x27 (maximum) let device7 = Address::standard().with_selectable_bits((true, true, true)); // Convert to raw 7-bit address if needed let raw_addr: u8 = device1.into(); assert_eq!(raw_addr, 0x21); ``` -------------------------------- ### Write and Read Output Pin States Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Controls logic levels of output pins and retrieves the current output register value. ```rust use tca9554::{Address, Tca9554}; async fn control_leds(i2c: impl embedded_hal_async::i2c::I2c) -> Result<(), impl core::fmt::Debug> { let mut driver = Tca9554::new(i2c, Address::standard()); // Configure P0-P3 as outputs for LEDs driver.write_direction(0xF0).await?; // Turn on LED on P0, others off driver.write_output(0x01).await?; // Read current output state let current = driver.read_output().await?; // Toggle P1 LED while keeping others unchanged driver.write_output(current ^ 0x02).await?; // Turn on all LEDs (P0-P3) driver.write_output(0x0F).await?; // Turn off all outputs driver.write_output(0x00).await?; Ok(()) } ``` -------------------------------- ### Handle I²C Errors with TCA9554 Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Demonstrates propagating I²C errors using the Result type and the question mark operator in an async context. ```rust use tca9554::{Address, Tca9554}; async fn robust_io_control(i2c: I2C) -> Result where I2C: embedded_hal_async::i2c::I2c, E: core::fmt::Debug, { let mut driver = Tca9554::new(i2c, Address::standard()); // Handle potential I2C errors match driver.write_direction(0xF0).await { Ok(()) => { // Direction configured successfully } Err(e) => { // Handle I2C error (NACK, bus error, timeout, etc.) return Err(e); } } // Chain operations with ? operator driver.write_output(0x00).await?; driver.write_polarity(0x00).await?; // Read and return input state let input = driver.read_input().await?; Ok(input) } ``` -------------------------------- ### Release I2C Bus Source: https://context7.com/ladvoc/tca9554-rs/llms.txt Returns ownership of the I2C peripheral to the caller, allowing bus sharing. ```rust use tca9554::{Address, Tca9554}; async fn use_and_release(i2c: I2C) -> I2C where I2C: embedded_hal_async::i2c::I2c, { let mut driver = Tca9554::new(i2c, Address::standard()); // Use the driver let _ = driver.write_direction(0xF0).await; let _ = driver.write_output(0x0F).await; // Get the address before releasing let _addr = driver.address(); // Release ownership of I2C peripheral for use elsewhere driver.release() } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.