Skip to content

Character_LCD_I2C: add support for PCF8574 I2C expander backpack #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ This driver depends on:
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
* `Adafruit CircuitPython BusDevice <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_
* `Adafruit CircuitPython MCP230xx <https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx>`_
* `Adafruit CircuitPython PCF8574 <https://github.com/adafruit/Adafruit_CircuitPython_PCF8574>`_
* `Adafruit CircuitPython 74HC595 <https://github.com/adafruit/Adafruit_CircuitPython_74HC595>`_

I2C & SPI displays also depend on:
Expand Down
131 changes: 92 additions & 39 deletions adafruit_character_lcd/character_lcd_i2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,23 @@
pass

from adafruit_mcp230xx.mcp23008 import MCP23008
from adafruit_pcf8574 import PCF8574
from adafruit_character_lcd.character_lcd import Character_LCD_Mono

__version__ = "0.0.0+auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CharLCD.git"


class I2C_Expander:
# pylint: disable=too-few-public-methods
"""
I2C Expander ICs
"""

MCP23008 = "MCP23008"
PCF8574 = "PCF8574"


class Character_LCD_I2C(Character_LCD_Mono):
# pylint: disable=too-few-public-methods
"""Character LCD connected to I2C/SPI backpack using its I2C connection.
Expand All @@ -67,28 +78,50 @@ def __init__(
lines: int,
address: Optional[int] = None,
backlight_inverted: bool = False,
expander: I2C_Expander = I2C_Expander.MCP23008,
) -> None:
"""Initialize character LCD connected to backpack using I2C connection
on the specified I2C bus with the specified number of columns and
lines on the display. Optionally specify if backlight is inverted.
"""

if address:
self.mcp = MCP23008(i2c, address=address)
else:
self.mcp = MCP23008(i2c)
super().__init__(
self.mcp.get_pin(1), # reset
self.mcp.get_pin(2), # enable
self.mcp.get_pin(3), # data line 4
self.mcp.get_pin(4), # data line 5
self.mcp.get_pin(5), # data line 6
self.mcp.get_pin(6), # data line 7
columns,
lines,
backlight_pin=self.mcp.get_pin(7),
backlight_inverted=backlight_inverted,
)
if expander == I2C_Expander.MCP23008:
if address:
self.expander = MCP23008(i2c, address=address)
else:
self.expander = MCP23008(i2c)

super().__init__(
self.expander.get_pin(1), # reset
self.expander.get_pin(2), # enable
self.expander.get_pin(3), # data line 4
self.expander.get_pin(4), # data line 5
self.expander.get_pin(5), # data line 6
self.expander.get_pin(6), # data line 7
columns,
lines,
backlight_pin=self.expander.get_pin(7),
backlight_inverted=backlight_inverted,
)

elif expander == I2C_Expander.PCF8574:
if address:
self.expander = PCF8574(i2c, address=address)
else:
self.expander = PCF8574(i2c)

super().__init__(
self.expander.get_pin(0), # reset
self.expander.get_pin(2), # enable
self.expander.get_pin(4), # data line 4
self.expander.get_pin(5), # data line 5
self.expander.get_pin(6), # data line 6
self.expander.get_pin(7), # data line 7
columns,
lines,
backlight_pin=self.expander.get_pin(3),
backlight_inverted=backlight_inverted,
)

def _write8(self, value: int, char_mode: bool = False) -> None:
# Sends 8b ``value`` in ``char_mode``.
Expand All @@ -98,27 +131,47 @@ def _write8(self, value: int, char_mode: bool = False) -> None:
# one ms delay to prevent writing too quickly.
time.sleep(0.001)

# bits are, MSB (7) to LSB (0)
# backlight: bit 7
# data line 7: bit 6
# data line 6: bit 5
# data line 5: bit 4
# data line 4: bit 3
# enable: bit 2
# reset: bit 1
# (unused): bit 0

reset_bit = int(char_mode) << 1
backlight_bit = int(self.backlight ^ self.backlight_inverted) << 7

# Write char_mode and upper 4 bits of data, shifted to the correct position.
self.mcp.gpio = reset_bit | backlight_bit | ((value & 0xF0) >> 1)

# do command
self._pulse_enable()

# Write char_mode and lower 4 bits of data, shifted to the correct position.
self.mcp.gpio = reset_bit | backlight_bit | ((value & 0x0F) << 3)

# do command
if isinstance(self.expander, MCP23008):
# bits are, MSB (7) to LSB (0)
# backlight: bit 7
# data line 7: bit 6
# data line 6: bit 5
# data line 5: bit 4
# data line 4: bit 3
# enable: bit 2
# reset: bit 1
# (unused): bit 0

reset_bit = int(char_mode) << 1
backlight_bit = int(self.backlight ^ self.backlight_inverted) << 7

# Write char_mode and upper 4 bits of data, shifted to the correct position.
self.__write_command(reset_bit | backlight_bit | ((value & 0xF0) >> 1))
self.__write_command(reset_bit | backlight_bit | ((value & 0x0F) << 3))

elif isinstance(self.expander, PCF8574):
# bits are, MSB (7) to LSB (0)
# data line 7: bit 7
# data line 6: bit 6
# data line 5: bit 5
# data line 4: bit 4
# backlight: bit 3
# enable: bit 2
# write/read: bit 1
# reset: bit 0
reset_bit = int(char_mode)
backlight_bit = int(self.backlight ^ self.backlight_inverted) << 3

# Write char_mode and upper 4 bits of data, shifted to the correct position.
self.__write_command(reset_bit | backlight_bit | (value & 0xF0))
self.__write_command(reset_bit | backlight_bit | (value << 4))

def __write_command(self, value: int) -> None:
# Write command bits to expander.
if isinstance(self.expander, MCP23008):
self.expander.gpio = value
elif isinstance(self.expander, PCF8574):
self.expander.write_gpio(value)

# execute command
self._pulse_enable()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Adafruit-Blinka
adafruit-circuitpython-mcp230xx
adafruit-circuitpython-pcf8574
adafruit-circuitpython-busdevice
adafruit-circuitpython-74hc595
adafruit-circuitpython-typing~=1.5