use embedded_hal::blocking::delay::{DelayMs, DelayUs}; use embedded_hal::blocking::i2c::Write; use crate::{bus::DataBus, error::Result}; /// This module supports I2C backpacks with a MCP23008 IC, like /// the one from adafruit. /// Connections as follows: /// /// /// /// /// /// /// /// /// /// /// ///
MCP23008 pinnameLCD pin
0N/C
1RS4
2E6
3DB411
4DB512
5DB613
6DB714
7Backlight
pub struct I2CMCP23008Bus { i2c_bus: I2C, address: u8, } const REG_IODIR : u8 = 0x00; const REG_GPIO : u8 = 0x09; impl I2CMCP23008Bus { /// Create a new instance of the MCP23008 I2C driver. The address of those /// devices is 0b010_0xxx where x is configured by bootstrap pins. pub fn new(i2c_bus: I2C, address: u8) -> Result> { let mut mcp23008 = I2CMCP23008Bus { i2c_bus, address }; // Set to reset values according to datasheet mcp23008.write_reg(REG_IODIR, 0b1111_1111)?; for reg in 0x01usize..0x0A { mcp23008.write_reg(reg as u8, 0)?; } // Configure pins 1..=7 as outputs, see pin mapping above mcp23008.write_reg(REG_IODIR, 0b0000_0001)?; Ok(mcp23008) } fn write_reg(&mut self, reg: u8, value: u8) -> Result<()> { let data = [reg, value]; self.i2c_bus.write(self.address, &data) .map_err(|_| crate::error::Error) } fn set_pins(&mut self, pins: u8) -> Result<()> { self.write_reg(REG_GPIO, pins) } } impl DataBus for I2CMCP23008Bus { fn write + DelayMs>( &mut self, byte: u8, data: bool, delay: &mut D, ) -> Result<()> { let rs = if data { 0b10 } else { 0b00 }; let en = 0b0000_0100; let backlight = 0b1000_0000; // always enable backlight let upper_nibble = (byte & 0xF0) >> 4; let lower_nibble = byte & 0x0F; // upper nibble: [d7 d6 d5 d4] // Pulse EN // lower nibble: [d3 d2 d1 d0] // Pulse EN let pins = rs | backlight | (upper_nibble << 3); self.set_pins(pins)?; delay.delay_ms(1); let pins = rs | en | backlight | (upper_nibble << 3); self.set_pins(pins)?; delay.delay_ms(1); let pins = rs | backlight | (lower_nibble << 3); self.set_pins(pins)?; delay.delay_ms(1); let pins = rs | en | backlight | (lower_nibble << 3); self.set_pins(pins)?; delay.delay_ms(1); let pins = backlight | (lower_nibble << 3); self.set_pins(pins)?; Ok(()) } }