diff --git a/README.rst b/README.rst index 03efd7d..409a8f4 100644 --- a/README.rst +++ b/README.rst @@ -19,8 +19,6 @@ This library is compatible with standard Character LCDs such as: * `Adafruit RGB backlight negative LCD 16x2 `_ * `Adafruit RGB backlight negative LCD 20x4 `_ -Compatible with CircuitPython Versions: 2.x - Dependencies ============= This driver depends on: @@ -42,20 +40,23 @@ The ``Character_LCD`` class interfaces a predefined Character LCD display with C .. code-block:: python - import adafruit_character_lcd + import board + import digitalio + import adafruit_character_lcd.character_lcd as character_lcd You must define the data pins (``RS``, ``EN``, ``D4``, ``D5``, ``D6``, ``D7``) in your code before using the ``Character_LCD`` class. -If you want to have on/off ``backlight`` functionality, you can also define your backlight as ``lcd_backlight``. Otherwise, the backlight will always remain on. An example of this is below +If you want to have on/off ``backlight`` functionality, you can also define your backlight as ``lcd_backlight``. Otherwise, the backlight +will always remain on. The following is an example setup. .. code-block:: python - lcd_rs = digitalio.DigitalInOut(D7) - lcd_en = digitalio.DigitalInOut(D8) - lcd_d7 = digitalio.DigitalInOut(D12) - lcd_d6 = digitalio.DigitalInOut(D11) - lcd_d5 = digitalio.DigitalInOut(D10) - lcd_d4 = digitalio.DigitalInOut(D9) - lcd_backlight = digitalio.DigitalInOut(D13) + lcd_rs = digitalio.DigitalInOut(board.D7) + lcd_en = digitalio.DigitalInOut(board.D8) + lcd_d7 = digitalio.DigitalInOut(board.D12) + lcd_d6 = digitalio.DigitalInOut(board.D11) + lcd_d5 = digitalio.DigitalInOut(board.D10) + lcd_d4 = digitalio.DigitalInOut(board.D9) + lcd_backlight = digitalio.DigitalInOut(board.D13) You must also define the size of the CharLCD by specifying its ``lcd_columns`` and ``lcd_rows``: @@ -68,17 +69,17 @@ After you have set up your LCD, we can make the device by calling it .. code-block:: python - lcd = adafruit_character_lcd.Character_LCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows, lcd_backlight) + lcd = character_lcd.Character_LCD_Mono(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, lcd_rows, lcd_backlight) To verify that your pins are correct, print a hello message to the CharLCD: .. code-block:: python - lcd.message('hello\ncircuitpython') + lcd.message = "Hello\nCircuitPython" -Custom character example with create_char() is provided within /examples/ +Custom character example with ``create_char()`` is provided within /examples/ Contributing @@ -143,4 +144,4 @@ Now, once you have the virtual environment activated: This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to -locally verify it will pass. \ No newline at end of file +locally verify it will pass. diff --git a/adafruit_character_lcd/__init__.py b/adafruit_character_lcd/__init__.py deleted file mode 100644 index 6596c7e..0000000 --- a/adafruit_character_lcd/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -"""include all classes""" -from adafruit_character_lcd.character_lcd import Character_LCD, Character_LCD_I2C, Character_LCD_SPI -from adafruit_character_lcd.character_lcd_rgb import Character_LCD_RGB diff --git a/adafruit_character_lcd/character_lcd.py b/adafruit_character_lcd/character_lcd.py old mode 100644 new mode 100755 index 4b5abd9..c663fa1 --- a/adafruit_character_lcd/character_lcd.py +++ b/adafruit_character_lcd/character_lcd.py @@ -1,6 +1,7 @@ # The MIT License (MIT) # # Copyright (c) 2017 Brent Rubell for Adafruit Industries +# Copyright (c) 2018 Kattni Rembor for Adafruit Industries # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -25,19 +26,19 @@ Module for interfacing with monochromatic character LCDs -* Author(s): Brent Rubell, Asher Lieber, Tony DiCola (original python charLCD library) +* Author(s): Kattni Rembor, Brent Rubell, Asher Lieber, + Tony DiCola (original python charLCD library) Implementation Notes -------------------- **Hardware:** -* Adafruit `Character LCDs - `_ +"* `Adafruit Character LCDs `_" **Software and Dependencies:** -* Adafruit CircuitPython firmware (2.2.0+) for the ESP8622 and M0-based boards: +* Adafruit CircuitPython firmware: https://github.com/adafruit/circuitpython/releases * Adafruit's Bus Device library (when using I2C/SPI): https://github.com/adafruit/Adafruit_CircuitPython_BusDevice @@ -51,67 +52,44 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CharLCD.git" -#pylint: disable-msg=bad-whitespace +# pylint: disable-msg=bad-whitespace # Commands -LCD_CLEARDISPLAY = const(0x01) -LCD_RETURNHOME = const(0x02) -LCD_ENTRYMODESET = const(0x04) -LCD_DISPLAYCONTROL = const(0x08) -LCD_CURSORSHIFT = const(0x10) -LCD_FUNCTIONSET = const(0x20) -LCD_SETCGRAMADDR = const(0x40) -LCD_SETDDRAMADDR = const(0x80) +_LCD_CLEARDISPLAY = const(0x01) +_LCD_RETURNHOME = const(0x02) +_LCD_ENTRYMODESET = const(0x04) +_LCD_DISPLAYCONTROL = const(0x08) +_LCD_CURSORSHIFT = const(0x10) +_LCD_FUNCTIONSET = const(0x20) +_LCD_SETCGRAMADDR = const(0x40) +_LCD_SETDDRAMADDR = const(0x80) # Entry flags -LCD_ENTRYRIGHT = const(0x00) -LCD_ENTRYLEFT = const(0x02) -LCD_ENTRYSHIFTINCREMENT = const(0x01) -LCD_ENTRYSHIFTDECREMENT = const(0x00) +_LCD_ENTRYLEFT = const(0x02) +_LCD_ENTRYSHIFTDECREMENT = const(0x00) # Control flags -LCD_DISPLAYON = const(0x04) -LCD_DISPLAYOFF = const(0x00) -LCD_CURSORON = const(0x02) -LCD_CURSOROFF = const(0x00) -LCD_BLINKON = const(0x01) -LCD_BLINKOFF = const(0x00) +_LCD_DISPLAYON = const(0x04) +_LCD_CURSORON = const(0x02) +_LCD_CURSOROFF = const(0x00) +_LCD_BLINKON = const(0x01) +_LCD_BLINKOFF = const(0x00) # Move flags -LCD_DISPLAYMOVE = const(0x08) -LCD_CURSORMOVE = const(0x00) -LCD_MOVERIGHT = const(0x04) -LCD_MOVELEFT = const(0x00) +_LCD_DISPLAYMOVE = const(0x08) +_LCD_MOVERIGHT = const(0x04) +_LCD_MOVELEFT = const(0x00) # Function set flags -LCD_8BITMODE = const(0x10) -LCD_4BITMODE = const(0x00) -LCD_2LINE = const(0x08) -LCD_1LINE = const(0x00) -LCD_5X10DOTS = const(0x04) -LCD_5X8DOTS = const(0x00) +_LCD_4BITMODE = const(0x00) +_LCD_2LINE = const(0x08) +_LCD_1LINE = const(0x00) +_LCD_5X8DOTS = const(0x00) # Offset for up to 4 rows. -LCD_ROW_OFFSETS = (0x00, 0x40, 0x14, 0x54) - -# MCP23008 I2C backpack pin mapping from LCD logical pin to MCP23008 pin. -_MCP23008_LCD_RS = const(1) -_MCP23008_LCD_EN = const(2) -_MCP23008_LCD_D4 = const(3) -_MCP23008_LCD_D5 = const(4) -_MCP23008_LCD_D6 = const(5) -_MCP23008_LCD_D7 = const(6) -_MCP23008_LCD_BACKLIGHT = const(7) - -# 74HC595 SPI backpack pin mapping from LCD logical pin to 74HC595 pin. -_74HC595_LCD_RS = const(1) -_74HC595_LCD_EN = const(2) -_74HC595_LCD_D4 = const(6) -_74HC595_LCD_D5 = const(5) -_74HC595_LCD_D6 = const(4) -_74HC595_LCD_D7 = const(3) -_74HC595_LCD_BACKLIGHT = const(7) - -#pylint: enable-msg=bad-whitespace +_LCD_ROW_OFFSETS = (0x00, 0x40, 0x14, 0x54) + +# pylint: enable-msg=bad-whitespace + def _set_bit(byte_value, position, val): # Given the specified byte_value set the bit at position to the provided @@ -121,33 +99,43 @@ def _set_bit(byte_value, position, val): ret = byte_value | (1 << position) else: ret = byte_value & ~(1 << position) + return ret + +def _map(xval, in_min, in_max, out_min, out_max): + # Affine transfer/map with constrained output. + outrange = float(out_max - out_min) + inrange = float(in_max - in_min) + ret = (xval - in_min) * (outrange / inrange) + out_min + if out_max > out_min: + ret = max(min(ret, out_max), out_min) + else: + ret = max(min(ret, out_min), out_max) return ret -#pylint: disable-msg=too-many-instance-attributes -class Character_LCD(object): - """ - Interfaces with a character LCD + +# pylint: disable-msg=too-many-instance-attributes +class Character_LCD: + """Base class for character LCD. + :param ~digitalio.DigitalInOut rs: The reset data line :param ~digitalio.DigitalInOut en: The enable data line :param ~digitalio.DigitalInOut d4: The data line 4 :param ~digitalio.DigitalInOut d5: The data line 5 :param ~digitalio.DigitalInOut d6: The data line 6 :param ~digitalio.DigitalInOut d7: The data line 7 - :param cols: The columns on the charLCD + :param columns: The columns on the charLCD :param lines: The lines on the charLCD - :param ~digitalio.DigitalInOut backlight: The backlight pin, usually - the last pin. Check with your datasheet """ - #pylint: disable-msg=too-many-arguments - def __init__(self, rs, en, d4, d5, d6, d7, cols, lines, - backlight=None #, - #enable_pwm = False, - #initial_backlight = 1.0 + LEFT_TO_RIGHT = const(0) + RIGHT_TO_LEFT = const(1) + + # pylint: disable-msg=too-many-arguments + def __init__(self, rs, en, d4, d5, d6, d7, columns, lines ): - self.cols = cols + self.columns = columns self.lines = lines # save pin numbers self.reset = rs @@ -156,114 +144,321 @@ def __init__(self, rs, en, d4, d5, d6, d7, cols, lines, self.dl5 = d5 self.dl6 = d6 self.dl7 = d7 - # backlight pin - self.backlight = backlight - # self.pwn_enabled = enable_pwm + # set all pins as outputs for pin in(rs, en, d4, d5, d6, d7): pin.direction = digitalio.Direction.OUTPUT - # Setup backlight - if backlight is not None: - self.backlight.direction = digitalio.Direction.OUTPUT - self.backlight.value = 0 # turn backlight on - # initialize the display + + # Initialise the display self._write8(0x33) self._write8(0x32) - # init. display control - self.displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF - # init display function - self.displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_2LINE | LCD_5X8DOTS - # init display mode - self.displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT - # write to display control - self._write8(LCD_DISPLAYCONTROL | self.displaycontrol) - # write displayfunction - self._write8(LCD_FUNCTIONSET | self.displayfunction) - # set the entry mode - self._write8(LCD_ENTRYMODESET | self.displaymode) + # Initialise display control + self.displaycontrol = _LCD_DISPLAYON | _LCD_CURSOROFF | _LCD_BLINKOFF + # Initialise display function + self.displayfunction = _LCD_4BITMODE | _LCD_1LINE | _LCD_2LINE | _LCD_5X8DOTS + # Initialise display mode + self.displaymode = _LCD_ENTRYLEFT | _LCD_ENTRYSHIFTDECREMENT + # Write to displaycontrol + self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) + # Write to displayfunction + self._write8(_LCD_FUNCTIONSET | self.displayfunction) + # Set entry mode + self._write8(_LCD_ENTRYMODESET | self.displaymode) self.clear() - #pylint: enable-msg=too-many-arguments + + self._message = None + self._enable = None + self._direction = None + # pylint: enable-msg=too-many-arguments def home(self): - """Moves the cursor back home pos(1,1)""" - self._write8(LCD_RETURNHOME) + """Moves the cursor "home" to position (1, 1).""" + self._write8(_LCD_RETURNHOME) time.sleep(0.003) def clear(self): - """Clears the LCD""" - self._write8(LCD_CLEARDISPLAY) - time.sleep(0.003) + """Clears everything displayed on the LCD. + + The following example displays, "Hello, world!", then clears the LCD. - def show_cursor(self, show): + .. code-block:: python + + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.message = "Hello, world!" + time.sleep(5) + lcd.clear() """ - Show or hide the cursor + self._write8(_LCD_CLEARDISPLAY) + time.sleep(0.003) + + @property + def cursor(self): + """True if cursor is visible. False to stop displaying the cursor. + + The following example shows the cursor after a displayed message: + + .. code-block:: python + + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd - :param show: True to show cursor, False to hide + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.cursor = True + lcd.message = "Cursor! " + time.sleep(5) """ + return self.displaycontrol & _LCD_CURSORON == _LCD_CURSORON + + @cursor.setter + def cursor(self, show): if show: - self.displaycontrol |= LCD_CURSORON + self.displaycontrol |= _LCD_CURSORON else: - self.displaycontrol &= ~LCD_DISPLAYON - self._write8(LCD_DISPLAYCONTROL | self.displaycontrol) - - def set_cursor(self, col, row): - """ - Sets the cursor to ``row`` and ``col`` + self.displaycontrol &= ~_LCD_CURSORON + self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) - :param col: column location - :param row: row location + def cursor_position(self, column, row): + """Move the cursor to position ``column``, ``row`` + :param column: column location + :param row: row location """ # Clamp row to the last row of the display if row > self.lines: row = self.lines - 1 # Set location - self._write8(LCD_SETDDRAMADDR | (col + LCD_ROW_OFFSETS[row])) + self._write8(_LCD_SETDDRAMADDR | (column + _LCD_ROW_OFFSETS[row])) + + @property + def blink(self): + """ + Blink the cursor. True to blink the cursor. False to stop blinking. + + The following example shows a message followed by a blinking cursor for five seconds. + .. code-block:: python + + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.blink = True + lcd.message = "Blinky cursor!" + time.sleep(5) + lcd.blink = False + """ + return self.displaycontrol & _LCD_BLINKON == _LCD_BLINKON + + @blink.setter def blink(self, blink): + if blink: + self.displaycontrol |= _LCD_BLINKON + else: + self.displaycontrol &= ~_LCD_BLINKON + self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) + + @property + def display(self): """ - Blinks the cursor if blink = true. + Enable or disable the display. True to enable the display. False to disable the display. + + The following example displays, "Hello, world!" on the LCD and then turns the display off. - :param blink: True to blink, False no blink + .. code-block:: python + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.message = "Hello, world!" + time.sleep(5) + lcd.display = False """ - if blink is True: - self.displaycontrol |= LCD_BLINKON + return self.displaycontrol & _LCD_DISPLAYON == _LCD_DISPLAYON + + @display.setter + def display(self, enable): + if enable: + self.displaycontrol |= _LCD_DISPLAYON else: - self.displaycontrol &= ~LCD_BLINKON - self._write8(LCD_DISPLAYCONTROL | self.displaycontrol) + self.displaycontrol &= ~_LCD_DISPLAYON + self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) + + @property + def message(self): + """Display a string of text on the character LCD. + + The following example displays, "Hello, world!" on the LCD. + + .. code-block:: python + + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.message = "Hello, world!" + time.sleep(5) + """ + return self._message + + @message.setter + def message(self, message): + self._message = message + line = 0 + # Track times through iteration, to act on the initial character of the message + initial_character = 0 + # iterate through each character + for character in message: + # If this is the first character in the string: + if initial_character == 0: + # Start at (1, 1) unless direction is set right to left, in which case start + # on the opposite side of the display. + col = 0 if self.displaymode & _LCD_ENTRYLEFT > 0 else self.columns - 1 + self.cursor_position(col, line) + initial_character += 1 + # If character is \n, go to next line + if character == '\n': + line += 1 + # Start the second line at (1, 1) unless direction is set right to left in which + # case start on the opposite side of the display. + col = 0 if self.displaymode & _LCD_ENTRYLEFT > 0 else self.columns - 1 + self.cursor_position(col, line) + # Write string to display + else: + self._write8(ord(character), True) def move_left(self): - """Moves display left one position""" - self._write8(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT) + """Moves displayed text left one column. + + The following example scrolls a message to the left off the screen. + + .. code-block:: python + + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + scroll_message = "<-- Scroll" + lcd.message = scroll_message + time.sleep(2) + for i in range(len(scroll_message)): + lcd.move_left() + time.sleep(0.5) + """ + self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVELEFT) def move_right(self): - """Moves display right one position""" - self._write8(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT) + """Moves displayed text right one column. + + The following example scrolls a message to the right off the screen. - def set_left_to_right(self): - """Set direction of text to read from left to right""" - self.displaymode |= LCD_ENTRYLEFT - self._write8(LCD_ENTRYMODESET | self.displaymode) + .. code-block:: python - def set_right_to_left(self): - """Set direction of text to read from right to left""" - self.displaymode |= LCD_ENTRYLEFT - self._write8(LCD_ENTRYMODESET | self.displaymode) + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd - def enable_display(self, enable): + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + scroll_message = "Scroll -->" + lcd.message = scroll_message + time.sleep(2) + for i in range(len(scroll_message) + 16): + lcd.move_right() + time.sleep(0.5) """ - Enable or disable the display. + self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVERIGHT) + + @property + def text_direction(self): + """The direction the text is displayed. To display the text left to right beginning on the + left side of the LCD, set ``text_direction = LEFT_TO_RIGHT``. To display the text right + to left beginning on the right size of the LCD, set ``text_direction = RIGHT_TO_LEFT``. + Text defaults to displaying from left to right. + + The following example displays "Hello, world!" from right to left. + + .. code-block:: python - :param enable: True to enable display, False to disable + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd + i2c = busio.I2C(board.SCL, board.SDA) + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.text_direction = lcd.RIGHT_TO_LEFT + lcd.message = "Hello, world!" + time.sleep(5) """ - if enable: - self.displaycontrol |= LCD_DISPLAYON - else: - self.displaycontrol &= ~LCD_DISPLAYON - self._write8(LCD_DISPLAYCONTROL | self.displaycontrol) + return self._direction + + @text_direction.setter + def text_direction(self, direction): + self._direction = direction + if direction == self.LEFT_TO_RIGHT: + self._left_to_right() + elif direction == self.RIGHT_TO_LEFT: + self._right_to_left() + + def _left_to_right(self): + # Displays text from left to right on the LCD. + self.displaymode |= _LCD_ENTRYLEFT + self._write8(_LCD_ENTRYMODESET | self.displaymode) + + def _right_to_left(self): + # Displays text from right to left on the LCD. + self.displaymode &= ~_LCD_ENTRYLEFT + self._write8(_LCD_ENTRYMODESET | self.displaymode) + + def create_char(self, location, pattern): + """ + Fill one of the first 8 CGRAM locations with custom characters. + The location parameter should be between 0 and 7 and pattern should + provide an array of 8 bytes containing the pattern. E.g. you can easily + design your custom character at http://www.quinapalus.com/hd44780udg.html + To show your custom character use, for example, ``lcd.message = "\x01"`` + + :param location: integer in range(8) to store the created character + :param ~bytes pattern: len(8) describes created character + + """ + # only position 0..7 are allowed + location &= 0x7 + self._write8(_LCD_SETCGRAMADDR | (location << 3)) + for i in range(8): + self._write8(pattern[i], char_mode=True) def _write8(self, value, char_mode=False): # Sends 8b ``value`` in ``char_mode``. @@ -297,170 +492,162 @@ def _pulse_enable(self): time.sleep(0.0000001) self.enable.value = False time.sleep(0.0000001) +# pylint: enable-msg=too-many-instance-attributes + + +# pylint: disable-msg=too-many-instance-attributes +class Character_LCD_Mono(Character_LCD): + """Interfaces with monochromatic character LCDs. + + :param ~digitalio.DigitalInOut rs: The reset data line + :param ~digitalio.DigitalInOut en: The enable data line + :param ~digitalio.DigitalInOut d4: The data line 4 + :param ~digitalio.DigitalInOut d5: The data line 5 + :param ~digitalio.DigitalInOut d6: The data line 6 + :param ~digitalio.DigitalInOut d7: The data line 7 + :param columns: The columns on the charLCD + :param lines: The lines on the charLCD + :param ~digitalio.DigitalInOut backlight_pin: The backlight pin + :param bool backlight_inverted: ``False`` if LCD is not inverted, i.e. backlight pin is + connected to common anode. ``True`` if LCD is inverted i.e. backlight pin is connected + to common cathode. - def set_backlight(self, lighton): - """ - Set lighton to turn the charLCD backlight on. + """ + # pylint: disable-msg=too-many-arguments + def __init__(self, rs, en, db4, db5, db6, db7, columns, lines, + backlight_pin=None, backlight_inverted=False): - :param lighton: True to turn backlight on, False to turn off + # Backlight pin and inversion + self.backlight_pin = backlight_pin + self.backlight_inverted = backlight_inverted - """ - if lighton: - self.backlight.value = 0 - else: - self.backlight.value = 1 + # Setup backlight + if backlight_pin is not None: + self.backlight_pin.direction = digitalio.Direction.OUTPUT + self.backlight = True + super().__init__(rs, en, db4, db5, db6, db7, columns, lines) + # pylint: enable-msg=too-many-arguments + @property + def backlight(self): + """Enable or disable backlight. True if backlight is on. False if backlight is off. - def message(self, text): - """ - Write text to display. Can include ``\\n`` for newline. + The following example turns the backlight off, then displays, "Hello, world?", then turns + the backlight on and displays, "Hello, world!" - :param text: text string to display - """ - line = 0 - # iterate thru each char - for char in text: - # if character is \n, go to next line - if char == '\n': - line += 1 - # move to left/right depending on text direction - col = 0 if self.displaymode & LCD_ENTRYLEFT > 0 else self.cols-1 - self.set_cursor(col, line) - # Write character to display - else: - self._write8(ord(char), True) + .. code-block:: python - def create_char(self, location, pattern): - """ - Fill one of the first 8 CGRAM locations with custom characters. - The location parameter should be between 0 and 7 and pattern should - provide an array of 8 bytes containing the pattern. E.g. you can easyly - design your custom character at http://www.quinapalus.com/hd44780udg.html - To show your custom character use eg. lcd.message('\x01') + import time + import board + import busio + import adafruit_character_lcd.character_lcd_i2c as character_lcd - :param location: integer in range(8) to store the created character - :param ~bytes pattern: len(8) describes created character + i2c = busio.I2C(board.SCL, board.SDA) + + lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) + + lcd.backlight = False + lcd.message = "Hello, world?" + time.sleep(5) + lcd.backlight = True + lcd.message = "Hello, world!" + time.sleep(5) """ - # only position 0..7 are allowed - location &= 0x7 - self._write8(LCD_SETCGRAMADDR | (location << 3)) - for i in range(8): - self._write8(pattern[i], char_mode=True) + return self._enable -#pylint: enable-msg=too-many-instance-attributes + @backlight.setter + def backlight(self, enable): + self._enable = enable + if enable: + self.backlight_pin.value = not self.backlight_inverted + else: + self.backlight_pin.value = self.backlight_inverted + + +class Character_LCD_RGB(Character_LCD): + """Interfaces with RGB character LCDs. + + :param ~digitalio.DigitalInOut rs: The reset data line + :param ~digitalio.DigitalInOut en: The enable data line + :param ~digitalio.DigitalInOut db4: The data line 4 + :param ~digitalio.DigitalInOut db5: The data line 5 + :param ~digitalio.DigitalInOut db6: The data line 6 + :param ~digitalio.DigitalInOut db7: The data line 7 + :param columns: The columns on the charLCD + :param lines: The lines on the charLCD + :param ~pulseio.PWMOut, ~digitalio.DigitalInOut red: Red RGB Anode + :param ~pulseio.PWMOut, ~digitalio.DigitalInOut green: Green RGB Anode + :param ~pulseio.PWMOut, ~digitalio.DigitalInOut blue: Blue RGB Anode + :param ~digitalio.DigitalInOut read_write: The rw pin. Determines whether to read to or + write from the display. Not necessary if only writing to the display. Used on shield. -class Character_LCD_I2C(Character_LCD): - """Character LCD connected to I2C/SPI backpack using its I2C connection. - This is a subclass of Character_LCD and implements all of the same - functions and functionality. """ - - def __init__(self, i2c, cols, lines): - """Initialize character LCD connectedto backpack using I2C connection - on the specified I2C bus and of the specified number of columns and - lines on the display. + # pylint: disable-msg=too-many-arguments + def __init__(self, rs, en, db4, db5, db6, db7, columns, lines, + red, green, blue, read_write=None): + + # Define read_write (rw) pin + self.read_write = read_write + + # Setup rw pin if used + if read_write is not None: + self.read_write.direction = digitalio.Direction.OUTPUT + + # define color params + self.rgb_led = [red, green, blue] + + for pin in self.rgb_led: + if hasattr(pin, 'direction'): + # Assume a digitalio.DigitalInOut or compatible interface: + pin.direction = digitalio.Direction.OUTPUT + elif not hasattr(pin, 'duty_cycle'): + raise TypeError( + 'RGB LED objects must be instances of digitalio.DigitalInOut' + ' or pulseio.PWMOut, or provide a compatible interface.' + ) + + self._color = [0, 0, 0] + super().__init__(rs, en, db4, db5, db6, db7, columns, lines) + + @property + def color(self): """ - # Import the MCP23008 module here when the class is used - # to keep memory usage low. If you attempt to import globally at the - # top of this file you WILL run out of memory on the M0, even with - # MPY files. The amount of code and classes implicitly imported - # by all the SPI and I2C code is too high. Thus import on demand. - import adafruit_character_lcd.mcp23008 as mcp23008 - self._mcp = mcp23008.MCP23008(i2c) - # Setup pins for I2C backpack, see diagram: - # https://learn.adafruit.com/assets/35681 - reset = self._mcp.DigitalInOut(_MCP23008_LCD_RS, self._mcp) - enable = self._mcp.DigitalInOut(_MCP23008_LCD_EN, self._mcp) - dl4 = self._mcp.DigitalInOut(_MCP23008_LCD_D4, self._mcp) - dl5 = self._mcp.DigitalInOut(_MCP23008_LCD_D5, self._mcp) - dl6 = self._mcp.DigitalInOut(_MCP23008_LCD_D6, self._mcp) - dl7 = self._mcp.DigitalInOut(_MCP23008_LCD_D7, self._mcp) - backlight = self._mcp.DigitalInOut(_MCP23008_LCD_BACKLIGHT, self._mcp) - # Call superclass initializer with MCP23008 pins. - super().__init__(reset, enable, dl4, dl5, dl6, dl7, cols, lines, - backlight=backlight) + The color of the display. Provide a list of three integers ranging 0 - 100, ``[R, G, B]``. + ``0`` is no color, or "off". ``100`` is maximum color. For example, the brightest red would + be ``[100, 0, 0]``, and a half-bright purple would be, ``[50, 0, 50]``. - def _write8(self, value, char_mode=False): - # Optimize a command write by changing all GPIO pins at once instead - # of letting the super class try to set each one invidually (far too - # slow with overhead of I2C communication). - gpio = self._mcp.gpio - # Make sure enable is low. - gpio = _set_bit(gpio, _MCP23008_LCD_EN, False) - # Set character/data bit. (charmode = False). - gpio = _set_bit(gpio, _MCP23008_LCD_RS, char_mode) - # Set upper 4 bits. - gpio = _set_bit(gpio, _MCP23008_LCD_D4, ((value >> 4) & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D5, ((value >> 5) & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D6, ((value >> 6) & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D7, ((value >> 7) & 1) > 0) - self._mcp.gpio = gpio - # Send command. - self._pulse_enable() - # Now repeat for lower 4 bits. - gpio = self._mcp.gpio - gpio = _set_bit(gpio, _MCP23008_LCD_EN, False) - gpio = _set_bit(gpio, _MCP23008_LCD_RS, char_mode) - gpio = _set_bit(gpio, _MCP23008_LCD_D4, (value & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D5, ((value >> 1) & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D6, ((value >> 2) & 1) > 0) - gpio = _set_bit(gpio, _MCP23008_LCD_D7, ((value >> 3) & 1) > 0) - self._mcp.gpio = gpio - self._pulse_enable() + If PWM is unavailable, ``0`` is off, and non-zero is on. For example, ``[1, 0, 0]`` would + be red. + The following example turns the LCD red and displays, "Hello, world!". -class Character_LCD_SPI(Character_LCD): - """Character LCD connected to I2C/SPI backpack using its SPI connection. - This is a subclass of Character_LCD and implements all of the same - functions and functionality. - """ + .. code-block:: python - def __init__(self, spi, latch, cols, lines): - """Initialize character LCD connectedto backpack using SPI connection - on the specified SPI bus and latch line with the specified number of - columns and lines on the display. - """ - # See comment above on I2C class for why this is imported here: - import adafruit_character_lcd.shift_reg_74hc595 as shift_reg_74hc595 - self._sr = shift_reg_74hc595.ShiftReg74HC595(spi, latch) - # Setup pins for SPI backpack, see diagram: - # https://learn.adafruit.com/assets/35681 - reset = self._sr.DigitalInOut(_74HC595_LCD_RS, self._sr) - enable = self._sr.DigitalInOut(_74HC595_LCD_EN, self._sr) - dl4 = self._sr.DigitalInOut(_74HC595_LCD_D4, self._sr) - dl5 = self._sr.DigitalInOut(_74HC595_LCD_D5, self._sr) - dl6 = self._sr.DigitalInOut(_74HC595_LCD_D6, self._sr) - dl7 = self._sr.DigitalInOut(_74HC595_LCD_D7, self._sr) - backlight = self._sr.DigitalInOut(_74HC595_LCD_BACKLIGHT, self._sr) - # Call superclass initializer with shift register pins. - super().__init__(reset, enable, dl4, dl5, dl6, dl7, cols, lines, - backlight=backlight) + import time + import board + import busio + import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd - def _write8(self, value, char_mode=False): - # Optimize a command write by changing all GPIO pins at once instead - # of letting the super class try to set each one invidually (far too - # slow with overhead of SPI communication). - gpio = self._sr.gpio - # Make sure enable is low. - gpio = _set_bit(gpio, _74HC595_LCD_EN, False) - # Set character/data bit. (charmode = False). - gpio = _set_bit(gpio, _74HC595_LCD_RS, char_mode) - # Set upper 4 bits. - gpio = _set_bit(gpio, _74HC595_LCD_D4, ((value >> 4) & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D5, ((value >> 5) & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D6, ((value >> 6) & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D7, ((value >> 7) & 1) > 0) - self._sr.gpio = gpio - # Send command. - self._pulse_enable() - # Now repeat for lower 4 bits. - gpio = self._sr.gpio - gpio = _set_bit(gpio, _74HC595_LCD_EN, False) - gpio = _set_bit(gpio, _74HC595_LCD_RS, char_mode) - gpio = _set_bit(gpio, _74HC595_LCD_D4, (value & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D5, ((value >> 1) & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D6, ((value >> 2) & 1) > 0) - gpio = _set_bit(gpio, _74HC595_LCD_D7, ((value >> 3) & 1) > 0) - self._sr.gpio = gpio - self._pulse_enable() + i2c = busio.I2C(board.SCL, board.SDA) + + lcd = character_lcd.Character_LCD_RGB_I2C(i2c, 16, 2) + + lcd.color = [100, 0, 0] + lcd.message = "Hello, world!" + time.sleep(5) + """ + return self._color + + @color.setter + def color(self, color): + self._color = color + for number, pin in enumerate(self.rgb_led): + if hasattr(pin, 'duty_cycle'): + # Assume a pulseio.PWMOut or compatible interface and set duty cycle: + pin.duty_cycle = int(_map(color[number], 0, 100, 65535, 0)) + elif hasattr(pin, 'value'): + # If we don't have a PWM interface, all we can do is turn each color + # on / off. Assume a DigitalInOut (or compatible interface) and write + # 0 (on) to pin for any value greater than 0, or 1 (off) for 0: + pin.value = not color[number] > 1 diff --git a/adafruit_character_lcd/character_lcd_i2c.py b/adafruit_character_lcd/character_lcd_i2c.py new file mode 100644 index 0000000..ec5d8a6 --- /dev/null +++ b/adafruit_character_lcd/character_lcd_i2c.py @@ -0,0 +1,84 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Kattni Rembor for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`adafruit_character_lcd.character_lcd_i2c` +==================================================== + +Module for using I2C with I2C/SPI character LCD backpack + +* Author(s): Kattni Rembor + +Implementation Notes +-------------------- + +**Hardware:** + +"* `I2C / SPI character LCD backpack `_" + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware: + https://github.com/adafruit/circuitpython/releases +* Adafruit's Bus Device library (when using I2C/SPI): + https://github.com/adafruit/Adafruit_CircuitPython_BusDevice + +""" + +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 Character_LCD_I2C(Character_LCD_Mono): + # pylint: disable=too-few-public-methods + """Character LCD connected to I2C/SPI backpack using its I2C connection. + This is a subclass of Character_LCD and implements all of the same + functions and functionality. + + To use, import and initialise as follows: + + .. code-block:: python + + import board + import busio + from adafruit_character_lcd.character_lcd_i2c import Character_LCD_I2C + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = Character_LCD_I2C(i2c, 16, 2) + """ + def __init__(self, i2c, columns, lines, backlight_inverted=False): + """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. + """ + import adafruit_mcp230xx + self._mcp = adafruit_mcp230xx.MCP23008(i2c) + reset = self._mcp.get_pin(1) + enable = self._mcp.get_pin(2) + db4 = self._mcp.get_pin(3) + db5 = self._mcp.get_pin(4) + db6 = self._mcp.get_pin(5) + db7 = self._mcp.get_pin(6) + backlight_pin = self._mcp.get_pin(7) + super().__init__(reset, enable, db4, db5, db6, db7, columns, lines, + backlight_pin=backlight_pin, backlight_inverted=backlight_inverted) diff --git a/adafruit_character_lcd/character_lcd_rgb.py b/adafruit_character_lcd/character_lcd_rgb.py deleted file mode 100755 index d0e4fa6..0000000 --- a/adafruit_character_lcd/character_lcd_rgb.py +++ /dev/null @@ -1,305 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2017 Brent Rubell for Adafruit Industries -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -""" -`adafruit_character_lcd.character_lcd_rgb` -==================================================== - -Character_LCD - module for interfacing with RGB character LCDs - -* Author(s): - -Brent Rubell - -Asher Lieber - -Tony DiCola for the original python charLCD library - -Implementation Notes --------------------- - -**Hardware:** - -* Adafruit `Character LCDs - `_ - -**Software and Dependencies:** - -* Adafruit CircuitPython firmware (2.2.0+) for the ESP8622 and M0-based boards: - https://github.com/adafruit/circuitpython/releases -* Adafruit's Bus Device library (when using I2C/SPI): - https://github.com/adafruit/Adafruit_CircuitPython_BusDevice - -""" -import time -import digitalio -from micropython import const - -#pylint: disable-msg=bad-whitespace -# Commands -_LCD_CLEARDISPLAY = const(0x01) -_LCD_RETURNHOME = const(0x02) -_LCD_ENTRYMODESET = const(0x04) -_LCD_DISPLAYCONTROL = const(0x08) -_LCD_CURSORSHIFT = const(0x10) -_LCD_FUNCTIONSET = const(0x20) -_LCD_SETCGRAMADDR = const(0x40) -_LCD_SETDDRAMADDR = const(0x80) - -# Entry flags -_LCD_ENTRYRIGHT = const(0x00) -_LCD_ENTRYLEFT = const(0x02) -_LCD_ENTRYSHIFTINCREMENT = const(0x01) -_LCD_ENTRYSHIFTDECREMENT = const(0x00) - -# Control flags -_LCD_DISPLAYON = const(0x04) -_LCD_DISPLAYOFF = const(0x00) -LCD_CURSORON = const(0x02) -_LCD_CURSOROFF = const(0x00) -_LCD_BLINKON = const(0x01) -_LCD_BLINKOFF = const(0x00) - -# Move flags -_LCD_DISPLAYMOVE = const(0x08) -_LCD_CURSORMOVE = const(0x00) -_LCD_MOVERIGHT = const(0x04) -_LCD_MOVELEFT = const(0x00) - -# Function set flags -_LCD_8BITMODE = const(0x10) -_LCD_4BITMODE = const(0x00) -_LCD_2LINE = const(0x08) -_LCD_1LINE = const(0x00) -_LCD_5X10DOTS = const(0x04) -_LCD_5X8DOTS = const(0x00) - -# Offset for up to 4 rows. -LCD_ROW_OFFSETS = (0x00, 0x40, 0x14, 0x54) - -#pylint: enable-msg=bad-whitespace - -def _map(xval, in_min, in_max, out_min, out_max): - # Affine transfer/map with constrained output. - outrange = float(out_max - out_min) - inrange = float(in_max - in_min) - ret = (xval - in_min) * (outrange / inrange) + out_min - if out_max > out_min: - ret = max(min(ret, out_max), out_min) - else: - ret = max(min(ret, out_min), out_max) - return ret - - -#pylint: disable-msg=too-many-instance-attributes -class Character_LCD_RGB: - """ Interfaces with a character LCD - :param ~digitalio.DigitalInOut rs: The reset data line - :param ~digitalio.DigitalInOut en: The enable data line - :param ~digitalio.DigitalInOut d4: The data line 4 - :param ~digitalio.DigitalInOut d5: The data line 5 - :param ~digitalio.DigitalInOut d6: The data line 6 - :param ~digitalio.DigitalInOut d7: The data line 7 - :param cols: The columns on the charLCD - :param lines: The lines on the charLCD - :param ~pulseio.PWMOut, ~digitalio.DigitalInOut red: Red RGB Anode - :param ~pulseio.PWMOut, ~digitalio.DigitalInOut green: Green RGB Anode - :param ~pulseio.PWMOut, ~digitalio.DigitalInOut blue: Blue RGB Anode - :param ~digitalio.DigitalInOut backlight: The backlight pin, usually the last pin. - Consult the datasheet. Note that Pin value 0 means backlight is lit. - - """ - #pylint: disable-msg=too-many-arguments - def __init__(self, rs, en, d4, d5, d6, d7, cols, lines, - red, - green, - blue, - backlight=None - ): - self.cols = cols - self.lines = lines - - # define pin params - self.reset = rs - self.enable = en - self.dl4 = d4 - self.dl5 = d5 - self.dl6 = d6 - self.dl7 = d7 - - # define backlight pin - self.backlight = backlight - - # set all pins as outputs - for pin in(rs, en, d4, d5, d6, d7): - pin.direction = digitalio.Direction.OUTPUT - - # setup backlight - if backlight is not None: - self.backlight.direction = digitalio.Direction.OUTPUT - self.backlight.value = 0 # turn backlight on - - # define color params - self.red = red - self.green = green - self.blue = blue - self.rgb_led = [red, green, blue] - - for pin in self.rgb_led: - if hasattr(pin, 'direction'): - # Assume a digitalio.DigitalInOut or compatible interface: - pin.direction = digitalio.Direction.OUTPUT - elif not hasattr(pin, 'duty_cycle'): - raise TypeError( - 'RGB LED objects must be instances of digitalio.DigitalInOut' - ' or pulseio.PWMOut, or provide a compatible interface.' - ) - - # initialize the display - self._write8(0x33) - self._write8(0x32) - # init. display control - self.displaycontrol = _LCD_DISPLAYON | _LCD_CURSOROFF | _LCD_BLINKOFF - # init display function - self.displayfunction = _LCD_4BITMODE | _LCD_1LINE | _LCD_2LINE | _LCD_5X8DOTS - # init display mode - self.displaymode = _LCD_ENTRYLEFT | _LCD_ENTRYSHIFTDECREMENT - # write to display control - self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) - # write displayfunction - self._write8(_LCD_FUNCTIONSET | self.displayfunction) - # set the entry mode - self._write8(_LCD_ENTRYMODESET | self.displaymode) - self.clear() - #pylint: enable-msg=too-many-arguments - - def home(self): - """Moves the cursor back home pos(1,1)""" - self._write8(_LCD_RETURNHOME) - time.sleep(0.003) - - def clear(self): - """Clears the LCD""" - self._write8(_LCD_CLEARDISPLAY) - time.sleep(0.003) - - def show_cursor(self, show): - """Show or hide the cursor""" - if show: - self.displaycontrol |= LCD_CURSORON - else: - self.displaycontrol &= ~_LCD_DISPLAYON - self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) - - def set_cursor(self, col, row): - """Sets the cursor to ``row`` and ``col`` - :param col: column location - :param row: row location - """ - # Clamp row to the last row of the display - if row > self.lines: - row = self.lines - 1 - # Set location - self._write8(_LCD_SETDDRAMADDR | (col + LCD_ROW_OFFSETS[row])) - - def enable_display(self, enable): - """Enable or disable the display. - :param enable: True to enable display, False to disable - """ - if enable: - self.displaycontrol |= _LCD_DISPLAYON - else: - self.displaycontrol &= ~_LCD_DISPLAYON - self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) - - def _write8(self, value, char_mode=False): - # Sends 8b ``value`` in ``char_mode``. - # :param value: bytes - # :param char_mode: character/data mode selector. False (default) for - # data only, True for character bits. - # one ms delay to prevent writing too quickly. - time.sleep(0.001) - # set character/data bit. (charmode = False) - self.reset.value = char_mode - # WRITE upper 4 bits - self.dl4.value = ((value >> 4) & 1) > 0 - self.dl5.value = ((value >> 5) & 1) > 0 - self.dl6.value = ((value >> 6) & 1) > 0 - self.dl7.value = ((value >> 7) & 1) > 0 - # send command - self._pulse_enable() - # WRITE lower 4 bits - self.dl4.value = (value & 1) > 0 - self.dl5.value = ((value >> 1) & 1) > 0 - self.dl6.value = ((value >> 2) & 1) > 0 - self.dl7.value = ((value >> 3) & 1) > 0 - self._pulse_enable() - - def _pulse_enable(self): - # Pulses (lo->hi->lo) to send commands. - self.enable.value = False - # 1microsec pause - time.sleep(0.0000001) - self.enable.value = True - time.sleep(0.0000001) - self.enable.value = False - time.sleep(0.0000001) - - def set_backlight(self, lighton): - """ Set lighton to turn the charLCD backlight on. - :param lighton: True to turn backlight on, False to turn off - """ - if lighton: - self.backlight.value = 0 - else: - self.backlight.value = 1 - - def set_color(self, color): - """Method to set the duty cycle or the on/off value of the RGB LED - :param color: list of 3 integers in range(100). ``[R,G,B]`` 0 is no - color, 100 is maximum color. If PWM is unavailable, 0 is off and - non-zero is on. - """ - for number, pin in enumerate(self.rgb_led): - if hasattr(pin, 'duty_cycle'): - # Assume a pulseio.PWMOut or compatible interface and set duty cycle: - pin.duty_cycle = int(_map(color[number], 0, 100, 65535, 0)) - elif hasattr(pin, 'value'): - # If we don't have a PWM interface, all we can do is turn each color - # on / off. Assume a DigitalInOut (or compatible interface) and write - # 0 (on) to pin for any value greater than 0, or 1 (off) for 0: - pin.value = 0 if color[number] > 0 else 1 - - def message(self, text): - """Write text to display, can include \n for newline - :param text: string to display - """ - line = 0 - # iterate thru each char - for char in text: - # if character is \n, go to next line - if char == '\n': - line += 1 - # move to left/right depending on text direction - col = 0 if self.displaymode & _LCD_ENTRYLEFT > 0 else self.cols-1 - self.set_cursor(col, line) - # Write character to display - else: - self._write8(ord(char), True) - -#pylint: enable-msg=too-many-instance-attributes diff --git a/adafruit_character_lcd/character_lcd_rgb_i2c.py b/adafruit_character_lcd/character_lcd_rgb_i2c.py new file mode 100644 index 0000000..7cdd068 --- /dev/null +++ b/adafruit_character_lcd/character_lcd_rgb_i2c.py @@ -0,0 +1,95 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Kattni Rembor for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`adafruit_character_lcd.character_lcd_i2c` +==================================================== + +Module for using I2C with I2C RGB LCD Shield or I2C RGB LCD Pi Plate + +* Author(s): Kattni Rembor + +Implementation Notes +-------------------- + +**Hardware:** + +"* `RGB LCD Shield Kit w/ 16x2 Character Display - Negative Display +`_" +"* `RGB LCD Shield Kit w/ 16x2 Character Display - Positive Display +`_" +"* `Adafruit RGB Negative 16x2 LCD+Keypad Kit for Raspberry Pi +`_" +"* `Adafruit RGB Positive 16x2 LCD+Keypad Kit for Raspberry Pi +`_" + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware: + https://github.com/adafruit/circuitpython/releases +* Adafruit's Bus Device library (when using I2C/SPI): + https://github.com/adafruit/Adafruit_CircuitPython_BusDevice + +""" + +from adafruit_character_lcd.character_lcd import Character_LCD_RGB + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CharLCD.git" + + +class Character_LCD_RGB_I2C(Character_LCD_RGB): + """RGB Character LCD connected to I2C shield or Pi plate using I2C connection. + This is a subclass of Character_LCD_RGB and implements all of the same + functions and functionality. + + To use, import and initialise as follows: + + .. code-block:: python + + import board + import busio + from adafruit_character_lcd.character_lcd_rgb_i2c import Character_LCD_RGB_I2C + + i2c = busio.I2C(board.SCL, board.SDA) + lcd = Character_LCD_RGB_I2C(i2c, 16, 2) + + """ + def __init__(self, i2c, columns, lines): + # pylint: disable=too-many-locals + """Initialize RGB character LCD connected to shield using I2C connection + on the specified I2C bus with the specified number of columns and lines + on the display. + """ + import adafruit_mcp230xx + self._mcp = adafruit_mcp230xx.MCP23017(i2c) + reset = self._mcp.get_pin(15) + read_write = self._mcp.get_pin(14) + enable = self._mcp.get_pin(13) + db4 = self._mcp.get_pin(12) + db5 = self._mcp.get_pin(11) + db6 = self._mcp.get_pin(10) + db7 = self._mcp.get_pin(9) + red = self._mcp.get_pin(6) + green = self._mcp.get_pin(7) + blue = self._mcp.get_pin(8) + super().__init__(reset, enable, db4, db5, db6, db7, columns, lines, red, green, blue, + read_write) diff --git a/adafruit_character_lcd/character_lcd_spi.py b/adafruit_character_lcd/character_lcd_spi.py new file mode 100644 index 0000000..c6a8458 --- /dev/null +++ b/adafruit_character_lcd/character_lcd_spi.py @@ -0,0 +1,89 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Kattni Rembor for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`adafruit_character_lcd.character_lcd_spi` +==================================================== + +Module for using SPI with I2C/SPI character LCD backpack + +* Author(s): Kattni Rembor + +Implementation Notes +-------------------- + +**Hardware:** + +"* `I2C / SPI character LCD backpack `_" + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware: + https://github.com/adafruit/circuitpython/releases +* Adafruit's Bus Device library (when using I2C/SPI): + https://github.com/adafruit/Adafruit_CircuitPython_BusDevice + +""" + +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 Character_LCD_SPI(Character_LCD_Mono): + """Character LCD connected to I2C/SPI backpack using its SPI connection. + This is a subclass of Character_LCD and implements all of the same + functions and functionality. + + To use, import and initialise as follows: + + .. code-block:: python + + import board + import busio + import digitalio + import adafruit_character_lcd.character_lcd_mono as character_lcd + + spi = busio.SPI(board.SCK, MOSI=board.MOSI) + latch = digitalio.DigitalInOut(board.D5) + lcd = character_lcd.Character_LCD_SPI(spi, latch, 16, 2) + """ + + def __init__(self, spi, latch, columns, lines, backlight_inverted=False): + # pylint: disable=too-many-arguments + """Initialize character LCD connected to backpack using SPI connection + on the specified SPI bus and latch line with the specified number of + columns and lines on the display. Optionally specify if backlight is + inverted. + """ + # pylint: enable=too-many-arguments + import adafruit_74hc595 + self._shift_register = adafruit_74hc595.ShiftRegister74HC595(spi, latch) + reset = self._shift_register.get_pin(1) + enable = self._shift_register.get_pin(2) + db4 = self._shift_register.get_pin(6) + db5 = self._shift_register.get_pin(5) + db6 = self._shift_register.get_pin(4) + db7 = self._shift_register.get_pin(3) + backlight_pin = self._shift_register.get_pin(7) + super().__init__(reset, enable, db4, db5, db6, db7, columns, lines, + backlight_pin=backlight_pin, backlight_inverted=backlight_inverted) diff --git a/adafruit_character_lcd/mcp23008.py b/adafruit_character_lcd/mcp23008.py deleted file mode 100644 index e777121..0000000 --- a/adafruit_character_lcd/mcp23008.py +++ /dev/null @@ -1,169 +0,0 @@ -""" -`adafruit_character_lcd.mcp23008` -========================================= - -MCP23008 I2C GPIO Extender Driver -Bare-bones driver for the MCP23008 driver, as used by the character LCD -backpack. This exposes the MCP2308 and its pins as standard CircuitPython -digitalio pins. Currently this is integrated in the character LCD class for -simplicity and reduction in dependent imports, but it could be broken out -into a standalone library later. - -* Author: Tony DiCola - -""" -import digitalio - -import adafruit_bus_device.i2c_device as i2c_device - -from micropython import const - -#pylint: disable-msg=bad-whitespace -# Registers and other constants: -_MCP23008_ADDRESS = const(0x20) -_MCP23008_IODIR = const(0x00) -_MCP23008_IPOL = const(0x01) -_MCP23008_GPINTEN = const(0x02) -_MCP23008_DEFVAL = const(0x03) -_MCP23008_INTCON = const(0x04) -_MCP23008_IOCON = const(0x05) -_MCP23008_GPPU = const(0x06) -_MCP23008_INTF = const(0x07) -_MCP23008_INTCAP = const(0x08) -_MCP23008_GPIO = const(0x09) -_MCP23008_OLAT = const(0x0A) - -#pylint: enable-msg=bad-whitespace - - -class MCP23008: - - """Class-level buffer for reading and writing registers with the device. - This reduces memory allocations but makes the code non-reentrant/thread- - safe!""" - _BUFFER = bytearray(2) - - class DigitalInOut: - """Digital input/output of the MCP23008. The interface is exactly the - same as the digitalio.DigitalInOut class (however the MCP23008 does not - support pull-down resistors and an exception will be thrown - attempting to set one). - """ - - def __init__(self, pin_number, mcp23008): - """Specify the pin number of the MCP23008 (0...7) and MCP23008 - instance. - """ - self._pin = pin_number - self._mcp = mcp23008 - - # kwargs in switch functions below are _necessary_ for compatibility - # with DigitalInout class (which allows specifying pull, etc. which - # is unused by this class). Do not remove them, instead turn off pylint - # in this case. - #pylint: disable=unused-argument - def switch_to_output(self, value=False, **kwargs): - """DigitalInOut switch_to_output""" - self.direction = digitalio.Direction.OUTPUT - self.value = value - - def switch_to_input(self, pull=None, **kwargs): - """DigitalInOut switch_to_input""" - self.direction = digitalio.Direction.INPUT - self.pull = pull - #pylint: enable=unused-argument - - @property - def value(self): - """Get ot Set pin value: True or False""" - gpio = self._mcp.gpio - return bool(gpio & (1 << self._pin)) - - @value.setter - def value(self, val): - gpio = self._mcp.gpio - if val: - gpio |= (1 << self._pin) - else: - gpio &= ~(1 << self._pin) - self._mcp.gpio = gpio - - @property - def direction(self): - """Set or Get pin Directtion INPUT or OUTPUT""" - iodir = self._mcp.read_u8(_MCP23008_IODIR) - if iodir & (1 << self._pin) > 0: - return digitalio.Direction.INPUT - - return digitalio.Direction.OUTPUT - - @direction.setter - def direction(self, val): - iodir = self._mcp.read_u8(_MCP23008_IODIR) - if val == digitalio.Direction.INPUT: - iodir |= (1 << self._pin) - elif val == digitalio.Direction.OUTPUT: - iodir &= ~(1 << self._pin) - else: - raise ValueError('Expected INPUT or OUTPUT direction!') - self._mcp.write_u8(_MCP23008_IODIR, iodir) - - @property - def pull(self): - """Set or Get Pull UP state: only digitalio.Pull.UP is supported""" - gppu = self._mcp.read_u8(_MCP23008_GPPU) - if gppu & (1 << self._pin) > 0: - return digitalio.Pull.UP - - return None - - @pull.setter - def pull(self, val): - gppu = self._mcp.read_u8(_MCP23008_GPPU) - if val is None: - gppu &= ~(1 << self._pin) # Disable pull-up - elif val == digitalio.Pull.UP: - gppu |= (1 << self._pin) - elif val == digitalio.Pull.DOWN: - raise ValueError('Pull-down resistors are not supported!') - else: - raise ValueError('Expected UP, DOWN, or None for pull state!') - self._mcp.write_u8(_MCP23008_GPPU, gppu) - - def __init__(self, i2c, address=_MCP23008_ADDRESS): - """Initialize MCP23008 instance on specified I2C bus and optionally - at the specified I2C address. - """ - self._device = i2c_device.I2CDevice(i2c, address) - # Reset device state to all pins as inputs (safest option). - with self._device as device: - # Write to MCP23008_IODIR register 0xFF followed by 9 zeros - # for defaults of other registers. - device.write('\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00') - - def read_u8(self, register): - """Read an unsigned 8 bit value from the specified 8-bit register.""" - with self._device as i2c: - self._BUFFER[0] = register & 0xFF - i2c.write(self._BUFFER, end=1, stop=False) - i2c.readinto(self._BUFFER, end=1) - return self._BUFFER[0] - - def write_u8(self, register, val): - """Write an 8 bit value to the specified 8-bit register.""" - with self._device as i2c: - self._BUFFER[0] = register & 0xFF - self._BUFFER[1] = val & 0xFF - i2c.write(self._BUFFER) - - @property - def gpio(self): - """Get and set the raw GPIO output register. Each bit represents the - output value of the associated pin (0 = low, 1 = high), assuming that - pin has been configured as an output previously. - """ - return self.read_u8(_MCP23008_GPIO) - - @gpio.setter - def gpio(self, val): - self.write_u8(_MCP23008_GPIO, val) diff --git a/adafruit_character_lcd/shift_reg_74hc595.py b/adafruit_character_lcd/shift_reg_74hc595.py deleted file mode 100644 index 292edae..0000000 --- a/adafruit_character_lcd/shift_reg_74hc595.py +++ /dev/null @@ -1,110 +0,0 @@ -""" -`adafruit_character_led.shift_reg_74hc595` -=============================================== - -74HC595 Serial to Paralllel Shift Register Driver -Bare-bones driver for the 74HC595, as used by the character LCD -backpack. This exposes the 74HC595 and its pins as standard CircuitPython -digitalio pins. Currently this is integrated in the character LCD class for -simplicity and reduction in dependent imports, but it could be broken out -into a standalone library later. - -* Author: Tony DiCola -""" -import digitalio - -import adafruit_bus_device.spi_device as spi_device - - -#pylint: disable-msg=too-few-public-methods -#pylint: disable-msg=no-self-use -class ShiftReg74HC595: - """Shift Register 74LS95 driver class""" - class DigitalInOut: - """Digital input/output of the 74HC595. The interface is exactly the - same as the digitalio.DigitalInOut class, however note that by design - this device is OUTPUT ONLY! Attempting to read inputs or set - direction as input will raise an exception. - """ - - def __init__(self, pin_number, shift_reg_74ls595): - """Specify the pin number of the shift register (0...7) and - ShiftReg74HC595 instance. - """ - self._pin = pin_number - self._sr = shift_reg_74ls595 - - # kwargs in switch functions below are _necessary_ for compatibility - # with DigitalInout class (which allows specifying pull, etc. which - # is unused by this class). Do not remove them, instead turn off pylint - # in this case. - #pylint: disable=unused-argument - def switch_to_output(self, value=False, **kwargs): - """DigitalInOut switch_to_output""" - self.direction = digitalio.Direction.OUTPUT - self.value = value - - def switch_to_input(self, **kwargs): - """do not call switch_to_input""" - raise RuntimeError('Unable to use 74HC595 as digital input!') - #pylint: enable=unused-argument - - @property - def value(self): - """do not call value""" - raise RuntimeError('Unable to use 74HC595 as digital input!') - - @value.setter - def value(self, val): - # Only supported operation, writing a digital output. - gpio = self._sr.gpio - if val: - gpio |= (1 << self._pin) - else: - gpio &= ~(1 << self._pin) - self._sr.gpio = gpio - - @property - def direction(self): - """ALWAYS an output!""" - return digitalio.Direction.OUTPUT - - @direction.setter - def direction(self, val): - """Can only be set as OUTPUT!""" - if val != digitalio.Direction.OUTPUT: - raise RuntimeError('Unable to use 74HC595 as digital input!') - - @property - def pull(self): - """Pull-up/down not supported, return NonLiberty e for no pull-up/down.""" - return None - - @pull.setter - def pull(self, val): - """Only supports null/no pull state.""" - if val is not None: - raise RuntimeError('Unable to set 74HC595 pull!') - - - def __init__(self, spi, latch): - self._device = spi_device.SPIDevice(spi, latch, baudrate=1000000) - self._gpio = bytearray(1) - self._gpio[0] = 0x00 - - @property - def gpio(self): - """Get and set the raw GPIO output register. Each bit represents the - output value of the associated pin (0 = low, 1 = high). - """ - return self._gpio[0] - - @gpio.setter - def gpio(self, val): - self._gpio[0] = val & 0xFF - with self._device as spi: - # pylint: disable=no-member - spi.write(self._gpio) - -#pylint: enable-msg=no-self-use -#pylint: enable-msg=too-few-public-methods diff --git a/docs/api.rst b/docs/api.rst index fdb9d6c..60afe08 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2,4 +2,13 @@ .. If you created a package, create one automodule per module in the package. .. automodule:: adafruit_character_lcd.character_lcd - :members: \ No newline at end of file + :members: + +.. automodule:: adafruit_character_lcd.character_lcd_i2c + :members: + +.. automodule:: adafruit_character_lcd.character_lcd_spi + :members: + +.. automodule:: adafruit_character_lcd.character_lcd_rgb_i2c + :members: diff --git a/docs/examples.rst b/docs/examples.rst index 9237e45..fc7c555 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -11,10 +11,10 @@ Ensure your device works with this simple test. :caption: examples/charlcd_rgb_simpletest.py :linenos: -.. literalinclude:: ../examples/charlcd_I2C_simpletest.py - :caption: examples/charlcd_I2C_simpletest.py +.. literalinclude:: ../examples/charlcd_i2c_mono_simpletest.py + :caption: examples/charlcd_i2c_mono_simpletest.py :linenos: -.. literalinclude:: ../examples/charlcd_SPI_simpletest.py - :caption: examples/charlcd_SPI_simpletest.py - :linenos: \ No newline at end of file +.. literalinclude:: ../examples/charlcd_spi_mono_simpletest.py + :caption: examples/charlcd_spi_mono_simpletest.py + :linenos: diff --git a/examples/charlcd_I2C_simpletest.py b/examples/charlcd_I2C_simpletest.py deleted file mode 100644 index 6b30f07..0000000 --- a/examples/charlcd_I2C_simpletest.py +++ /dev/null @@ -1,50 +0,0 @@ -# Hello World using 16x2 character lcd and an MCP23008 I2C LCD backpack. -import time - -import board -import busio - -import adafruit_character_lcd - - -# Character LCD Config: -# modify this if you have a different sized charlcd -lcd_columns = 16 -lcd_rows = 2 - -# Initialize I2C bus. -i2c = busio.I2C(board.SCL, board.SDA) - -# Init the lcd class -lcd = adafruit_character_lcd.Character_LCD_I2C(i2c, lcd_columns, lcd_rows) - -# Print a 2x line message -lcd.message('hello\ncircuitpython') -# Wait 5s -time.sleep(5) -# Demo showing cursor -lcd.clear() -lcd.show_cursor(True) -lcd.message('showing cursor ') -# Wait 5s -time.sleep(5) -# Demo showing the blinking cursor -lcd.clear() -lcd.blink(True) -lcd.message('Blinky Cursor!') -# Wait 5s -time.sleep(5) -lcd.blink(False) -# Demo scrolling message LEFT -lcd.clear() -scroll_msg = 'Scroll' -lcd.message(scroll_msg) -# Scroll to the left -for i in range(lcd_columns - len(scroll_msg)): - time.sleep(0.5) - lcd.move_left() -# Demo turning backlight off -lcd.clear() -lcd.message("going to sleep\ncya later!") -lcd.set_backlight(False) -time.sleep(2) diff --git a/examples/charlcd_SPI_simpletest.py b/examples/charlcd_SPI_simpletest.py deleted file mode 100644 index f7c9302..0000000 --- a/examples/charlcd_SPI_simpletest.py +++ /dev/null @@ -1,57 +0,0 @@ -# Hello World using 16x2 character lcd and an 74LS595 SPI LCD backpack. -import time - -import board -import busio -import digitalio - -import adafruit_character_lcd - - -# Character LCD Config: -# modify this if you have a different sized charlcd -lcd_columns = 16 -lcd_rows = 2 - -# Backpack connection configuration: -clk = board.SCK # Pin connected to backpack CLK. -data = board.MOSI # Pin connected to backpack DAT/data. -latch = board.D5 # Pin connected to backpack LAT/latch. - -# Initialize SPI bus. -spi = busio.SPI(clk, MOSI=data) - -# Init the lcd class -latch = digitalio.DigitalInOut(latch) -lcd = adafruit_character_lcd.Character_LCD_SPI(spi, latch, lcd_columns, lcd_rows) - -# Print a 2x line message -lcd.message('hello\ncircuitpython') -# Wait 5s -time.sleep(5) -# Demo showing cursor -lcd.clear() -lcd.show_cursor(True) -lcd.message('showing cursor ') -# Wait 5s -time.sleep(5) -# Demo showing the blinking cursor -lcd.clear() -lcd.blink(True) -lcd.message('Blinky Cursor!') -# Wait 5s -time.sleep(5) -lcd.blink(False) -# Demo scrolling message LEFT -lcd.clear() -scroll_msg = 'Scroll' -lcd.message(scroll_msg) -# Scroll to the left -for i in range(lcd_columns - len(scroll_msg)): - time.sleep(0.5) - lcd.move_left() -# Demo turning backlight off -lcd.clear() -lcd.message("going to sleep\ncya later!") -lcd.set_backlight(False) -time.sleep(2) diff --git a/examples/custom_character_nyan_cat.py b/examples/charlcd_custom_character_nyan_cat.py similarity index 67% rename from examples/custom_character_nyan_cat.py rename to examples/charlcd_custom_character_nyan_cat.py index 5c676be..019f815 100755 --- a/examples/custom_character_nyan_cat.py +++ b/examples/charlcd_custom_character_nyan_cat.py @@ -1,19 +1,25 @@ +"""Use custom characters to display Nyan cat""" import time -from board import D7, D8, D9, D10, D11, D12, D13 +import board import digitalio -import adafruit_character_lcd +import adafruit_character_lcd.character_lcd as characterlcd +# Modify this if you have a different sized character LCD lcd_columns = 16 lcd_rows = 2 -lcd_rs = digitalio.DigitalInOut(D7) -lcd_en = digitalio.DigitalInOut(D8) -lcd_d7 = digitalio.DigitalInOut(D12) -lcd_d6 = digitalio.DigitalInOut(D11) -lcd_d5 = digitalio.DigitalInOut(D10) -lcd_d4 = digitalio.DigitalInOut(D9) -lcd_backlight = digitalio.DigitalInOut(D13) -lcd = adafruit_character_lcd.Character_LCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, - lcd_d7, lcd_columns, lcd_rows, lcd_backlight) + +# Metro M0/M4 Pin Config: +lcd_rs = digitalio.DigitalInOut(board.D7) +lcd_en = digitalio.DigitalInOut(board.D8) +lcd_d7 = digitalio.DigitalInOut(board.D12) +lcd_d6 = digitalio.DigitalInOut(board.D11) +lcd_d5 = digitalio.DigitalInOut(board.D10) +lcd_d4 = digitalio.DigitalInOut(board.D9) +lcd_backlight = digitalio.DigitalInOut(board.D13) + +# Initialise the LCD class +lcd = characterlcd.Character_LCD_Mono(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, + lcd_d7, lcd_columns, lcd_rows, lcd_backlight) head = [31, 17, 27, 17, 17, 21, 17, 31] @@ -65,21 +71,10 @@ lcd.clear() -body_width = 3 lcd.move_right() -for i in range(4): - lcd.message('\x02') -lcd.message('\x01') -for i in range(body_width): - lcd.message('\x00') -lcd.message('\x06') -lcd.message('\n') -lcd.message('\x02\x02\x02') -lcd.message('\x07') -lcd.message('\x03') -for i in range(body_width): - lcd.message('\x04') -lcd.message('\x05') +lcd.message = "\x02\x02\x02\x02\x01\x00\x00\x00\x06\n\x02\x02\x02\x07\x03\x04\x04\x04\x05" + +lcd.backlight = True while True: lcd.create_char(4, bot_body2) diff --git a/examples/charlcd_customcharacter.py b/examples/charlcd_customcharacter.py new file mode 100644 index 0000000..7810802 --- /dev/null +++ b/examples/charlcd_customcharacter.py @@ -0,0 +1,25 @@ +"""Display a custom character""" +import board +import digitalio +import adafruit_character_lcd.character_lcd as characterlcd + +# Modify this if you have a different sized character LCD +lcd_columns = 16 +lcd_rows = 2 + +# Metro M0/M4 Pin Config: +lcd_rs = digitalio.DigitalInOut(board.D7) +lcd_en = digitalio.DigitalInOut(board.D8) +lcd_d7 = digitalio.DigitalInOut(board.D12) +lcd_d6 = digitalio.DigitalInOut(board.D11) +lcd_d5 = digitalio.DigitalInOut(board.D10) +lcd_d4 = digitalio.DigitalInOut(board.D9) +lcd_backlight = digitalio.DigitalInOut(board.D13) + +# Initialise the LCD class +lcd = characterlcd.Character_LCD_Mono(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, + lcd_d7, lcd_columns, lcd_rows, lcd_backlight) + +checkmark = bytes([0x0, 0x0, 0x1, 0x3, 0x16, 0x1c, 0x8, 0x0]) +lcd.clear() +lcd.message = "\x00" diff --git a/examples/charlcd_i2c_mono_simpletest.py b/examples/charlcd_i2c_mono_simpletest.py new file mode 100644 index 0000000..365575a --- /dev/null +++ b/examples/charlcd_i2c_mono_simpletest.py @@ -0,0 +1,57 @@ +"""Simple test for 16x2 character lcd connected to an MCP23008 I2C LCD backpack.""" +import time +import board +import busio +import adafruit_character_lcd.character_lcd_i2c as character_lcd + +# Modify this if you have a different sized Character LCD +lcd_columns = 16 +lcd_rows = 2 + +# Initialise I2C bus. +i2c = busio.I2C(board.SCL, board.SDA) + +# Initialise the lcd class +lcd = character_lcd.Character_LCD_I2C(i2c, lcd_columns, lcd_rows) + +# Turn backlight on +lcd.backlight = True +# Print a two line message +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +lcd.clear() +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor +lcd.clear() +lcd.cursor = True +lcd.message = "Cursor! " +# Wait 5s +time.sleep(5) +# Display blinking cursor +lcd.clear() +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll message to the left +for i in range(len(scroll_msg)): + time.sleep(0.5) + lcd.move_left() +lcd.clear() +lcd.message = "Going to sleep\nCya later!" +time.sleep(5) +# Turn backlight off +lcd.backlight = False +time.sleep(2) diff --git a/examples/charlcd_i2c_rgb_simpletest.py b/examples/charlcd_i2c_rgb_simpletest.py new file mode 100644 index 0000000..8362cf3 --- /dev/null +++ b/examples/charlcd_i2c_rgb_simpletest.py @@ -0,0 +1,69 @@ +"""Simple test for I2C RGB character LCD shield kit""" +import time +import board +import busio +import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd + +# Modify this if you have a different sized Character LCD +lcd_columns = 16 +lcd_rows = 2 + +# Initialise I2C bus. +i2c = busio.I2C(board.SCL, board.SDA) + +# Initialise the LCD class +lcd = character_lcd.Character_LCD_RGB_I2C(i2c, lcd_columns, lcd_rows) + +lcd.clear() +# Set LCD color to red +lcd.color = [100, 0, 0] +time.sleep(1) +# Print two line message +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Set LCD color to blue +lcd.color = [0, 100, 0] +time.sleep(1) +# Set LCD color to green +lcd.color = [0, 0, 100] +time.sleep(1) +# Set LCD color to purple +lcd.color = [50, 0, 50] +time.sleep(1) +lcd.clear() +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor +lcd.clear() +lcd.cursor = True +lcd.message = "Cursor! " +# Wait 5s +time.sleep(5) +# Display blinking cursor +lcd.clear() +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll to the left +for i in range(len(scroll_msg)): + time.sleep(0.5) + lcd.move_left() +lcd.clear() +time.sleep(1) +lcd.message = "Going to sleep\nCya later!" +time.sleep(5) +# Turn off LCD backlights and clear text +lcd.color = [0, 0, 0] +lcd.clear() diff --git a/examples/charlcd_mono_simpletest.py b/examples/charlcd_mono_simpletest.py index 9ae6394..9a47104 100644 --- a/examples/charlcd_mono_simpletest.py +++ b/examples/charlcd_mono_simpletest.py @@ -1,14 +1,14 @@ +"""Simple test for monochromatic character LCD""" import time import board import digitalio -import adafruit_character_lcd +import adafruit_character_lcd.character_lcd as characterlcd -# Character LCD Config: # Modify this if you have a different sized character LCD lcd_columns = 16 lcd_rows = 2 -# Metro M0 Pin Config: +# Metro M0/M4 Pin Config: lcd_rs = digitalio.DigitalInOut(board.D7) lcd_en = digitalio.DigitalInOut(board.D8) lcd_d7 = digitalio.DigitalInOut(board.D12) @@ -17,37 +17,48 @@ lcd_d4 = digitalio.DigitalInOut(board.D9) lcd_backlight = digitalio.DigitalInOut(board.D13) -# Init the LCD class -lcd = adafruit_character_lcd.Character_LCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, - lcd_d7, lcd_columns, lcd_rows, lcd_backlight) +# Initialise the LCD class +lcd = characterlcd.Character_LCD_Mono(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, + lcd_d7, lcd_columns, lcd_rows, lcd_backlight) -# Print a 2x line message -lcd.message('hello\ncircuitpython') +# Turn backlight on +lcd.backlight = True +# Print a two line message +lcd.message = "Hello\nCircuitPython" # Wait 5s time.sleep(5) -# Demo showing cursor lcd.clear() -lcd.show_cursor(True) -lcd.message('showing cursor ') +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" # Wait 5s time.sleep(5) -# Demo showing the blinking cursor +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor lcd.clear() -lcd.blink(True) -lcd.message('Blinky Cursor!') +lcd.cursor = True +lcd.message = "Cursor! " # Wait 5s time.sleep(5) -lcd.blink(False) -# Demo scrolling message LEFT +# Display blinking cursor lcd.clear() -scroll_msg = 'Scroll' -lcd.message(scroll_msg) -# Scroll to the left -for i in range(lcd_columns - len(scroll_msg)): +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll message to the left +for i in range(len(scroll_msg)): time.sleep(0.5) lcd.move_left() -# Demo turning backlight off lcd.clear() -lcd.message("going to sleep\ncya later!") -lcd.set_backlight(False) +lcd.message = "Going to sleep\nCya later!" +time.sleep(3) +# Turn backlight off +lcd.backlight = False time.sleep(2) diff --git a/examples/charlcd_rgb_simpletest.py b/examples/charlcd_rgb_simpletest.py index 1a60aa8..55f0dbc 100644 --- a/examples/charlcd_rgb_simpletest.py +++ b/examples/charlcd_rgb_simpletest.py @@ -1,43 +1,79 @@ +"""Simple test for RGB character LCD""" import time import board import digitalio -import adafruit_character_lcd import pulseio +import adafruit_character_lcd.character_lcd as characterlcd -# Character LCD Config: # Modify this if you have a different sized character LCD lcd_columns = 16 lcd_rows = 2 -# Metro M0 Pin Config: +# Metro M0/M4 Pin Config: lcd_rs = digitalio.DigitalInOut(board.D7) lcd_en = digitalio.DigitalInOut(board.D8) lcd_d7 = digitalio.DigitalInOut(board.D12) lcd_d6 = digitalio.DigitalInOut(board.D11) lcd_d5 = digitalio.DigitalInOut(board.D10) lcd_d4 = digitalio.DigitalInOut(board.D9) -lcd_backlight = digitalio.DigitalInOut(board.D13) red = pulseio.PWMOut(board.D3) green = pulseio.PWMOut(board.D5) blue = pulseio.PWMOut(board.D6) -# Init the LCD class -lcd = adafruit_character_lcd.Character_LCD_RGB(lcd_rs, lcd_en, lcd_d4, lcd_d5, - lcd_d6, lcd_d7, lcd_columns, lcd_rows, - red, green, blue, lcd_backlight) +# Initialise the LCD class +lcd = characterlcd.Character_LCD_RGB(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, + lcd_rows, red, green, blue) - -RED = [100, 0, 0] -GREEN = [0, 100, 0] -BLUE = [0, 0, 100] - - -while True: - lcd.clear() - lcd.message('CircuitPython\nRGB Test') - lcd.set_color(RED) - time.sleep(1) - lcd.set_color(GREEN) - time.sleep(1) - lcd.set_color(BLUE) - time.sleep(1) +lcd.clear() +# Set LCD color to red +lcd.color = [100, 0, 0] +time.sleep(1) +# Print two line message +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Set LCD color to blue +lcd.color = [0, 100, 0] +time.sleep(1) +# Set LCD color to green +lcd.color = [0, 0, 100] +time.sleep(1) +# Set LCD color to purple +lcd.color = [50, 0, 50] +time.sleep(1) +lcd.clear() +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor +lcd.clear() +lcd.cursor = True +lcd.message = "Cursor! " +# Wait 5s +time.sleep(5) +# Display blinking cursor +lcd.clear() +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll to the left +for i in range(len(scroll_msg)): + time.sleep(0.5) + lcd.move_left() +lcd.clear() +time.sleep(1) +lcd.message = "Going to sleep\nCya later!" +time.sleep(5) +# Turn off LCD backlights and clear text +lcd.color = [0, 0, 0] +lcd.clear() diff --git a/examples/charlcd_rpi_mono_simpletest.py b/examples/charlcd_rpi_mono_simpletest.py new file mode 100644 index 0000000..697c1d1 --- /dev/null +++ b/examples/charlcd_rpi_mono_simpletest.py @@ -0,0 +1,63 @@ +"""Simple test for monochromatic character LCD on Raspberry Pi""" +import time +import board +import digitalio +import adafruit_character_lcd.character_lcd as characterlcd + +# Modify this if you have a different sized character LCD +lcd_columns = 16 +lcd_rows = 2 + +# Raspberry Pi Pin Config: +lcd_rs = digitalio.DigitalInOut(board.D26) +lcd_en = digitalio.DigitalInOut(board.D19) +lcd_d7 = digitalio.DigitalInOut(board.D27) +lcd_d6 = digitalio.DigitalInOut(board.D22) +lcd_d5 = digitalio.DigitalInOut(board.D24) +lcd_d4 = digitalio.DigitalInOut(board.D25) +lcd_backlight = digitalio.DigitalInOut(board.D4) + +# Initialise the lcd class +lcd = characterlcd.Character_LCD_Mono(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, + lcd_d7, lcd_columns, lcd_rows, lcd_backlight) + +# Turn backlight on +lcd.backlight = True +# Print a two line message +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +lcd.clear() +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor +lcd.clear() +lcd.cursor = True +lcd.message = "Cursor! " +# Wait 5s +time.sleep(5) +# Display blinking cursor +lcd.clear() +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll message to the left +for i in range(len(scroll_msg)): + time.sleep(0.5) + lcd.move_left() +lcd.clear() +lcd.message = "Going to sleep\nCya later!" +# Turn backlight off +lcd.backlight = False +time.sleep(2) diff --git a/examples/rpi_charlcd_rgb_simpletest.py b/examples/charlcd_rpi_rgb_simpletest.py similarity index 57% rename from examples/rpi_charlcd_rgb_simpletest.py rename to examples/charlcd_rpi_rgb_simpletest.py index 3acadd2..1ed91bf 100644 --- a/examples/rpi_charlcd_rgb_simpletest.py +++ b/examples/charlcd_rpi_rgb_simpletest.py @@ -1,10 +1,10 @@ +"""Simple test for RGB character LCD on Raspberry Pi""" import time import board import digitalio -import adafruit_character_lcd +import adafruit_character_lcd.character_lcd as characterlcd -# Character LCD Config: -# modify this if you have a different sized charlcd +# Modify this if you have a different sized character LCD lcd_columns = 16 lcd_rows = 2 @@ -21,10 +21,9 @@ green = digitalio.DigitalInOut(board.D12) blue = digitalio.DigitalInOut(board.D18) -# Init the lcd class -lcd = adafruit_character_lcd.Character_LCD_RGB(lcd_rs, lcd_en, lcd_d4, lcd_d5, - lcd_d6, lcd_d7, lcd_columns, lcd_rows, - red, green, blue, lcd_backlight) +# Initialise the LCD class +lcd = characterlcd.Character_LCD_RGB(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_columns, + lcd_rows, red, green, blue, lcd_backlight) RED = [1, 0, 0] GREEN = [0, 1, 0] @@ -32,16 +31,16 @@ while True: lcd.clear() - lcd.message('CircuitPython\nRGB Test: RED') - lcd.set_color(RED) + lcd.message = 'CircuitPython\nRGB Test: RED' + lcd.color = RED time.sleep(1) lcd.clear() - lcd.message('CircuitPython\nRGB Test: GREEN') - lcd.set_color(GREEN) + lcd.message = 'CircuitPython\nRGB Test: GREEN' + lcd.color = GREEN time.sleep(1) lcd.clear() - lcd.message('CircuitPython\nRGB Test: BLUE') - lcd.set_color(BLUE) + lcd.message = 'CircuitPython\nRGB Test: BLUE' + lcd.color = BLUE time.sleep(1) diff --git a/examples/charlcd_spi_mono_simpletest.py b/examples/charlcd_spi_mono_simpletest.py new file mode 100644 index 0000000..55fbcb5 --- /dev/null +++ b/examples/charlcd_spi_mono_simpletest.py @@ -0,0 +1,63 @@ +"""Simple test for 16x2 character LCD connected to 74HC595 SPI LCD backpack.""" +import time +import board +import busio +import digitalio +import adafruit_character_lcd.character_lcd_spi as character_lcd + +# Modify this if you have a different sized character LCD +lcd_columns = 16 +lcd_rows = 2 + +# Backpack connection configuration: +clk = board.SCK # Pin connected to backpack CLK. +data = board.MOSI # Pin connected to backpack DAT/data. +latch = board.D5 # Pin connected to backpack LAT/latch. + +# Initialise SPI bus. +spi = busio.SPI(clk, MOSI=data) + +# Initialise the LCD class +latch = digitalio.DigitalInOut(latch) +lcd = character_lcd.Character_LCD_SPI(spi, latch, lcd_columns, lcd_rows) + +# Turn backlight on +lcd.backlight = True +# Print a two line message +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +lcd.clear() +# Print two line message right to left +lcd.text_direction = lcd.RIGHT_TO_LEFT +lcd.message = "Hello\nCircuitPython" +# Wait 5s +time.sleep(5) +# Return text direction to left to right +lcd.text_direction = lcd.LEFT_TO_RIGHT +# Display cursor +lcd.clear() +lcd.cursor = True +lcd.message = "Cursor! " +# Wait 5s +time.sleep(5) +# Display blinking cursor +lcd.clear() +lcd.blink = True +lcd.message = "Blinky Cursor!" +# Wait 5s +time.sleep(5) +lcd.blink = False +lcd.clear() +# Create message to scroll +scroll_msg = '<-- Scroll' +lcd.message = scroll_msg +# Scroll message to the left +for i in range(len(scroll_msg)): + time.sleep(0.5) + lcd.move_left() +lcd.clear() +lcd.message = "Going to sleep\nCya later!" +# Turn backlight off +lcd.backlight = False +time.sleep(2) diff --git a/examples/customcharacter.py b/examples/customcharacter.py deleted file mode 100644 index e6c81c8..0000000 --- a/examples/customcharacter.py +++ /dev/null @@ -1,19 +0,0 @@ -import digitalio -from board import D7, D8, D9, D10, D11, D12, D13 -import adafruit_character_lcd - - -lcd_columns = 16 -lcd_rows = 2 -lcd_rs = digitalio.DigitalInOut(D7) -lcd_en = digitalio.DigitalInOut(D8) -lcd_d7 = digitalio.DigitalInOut(D12) -lcd_d6 = digitalio.DigitalInOut(D11) -lcd_d5 = digitalio.DigitalInOut(D10) -lcd_d4 = digitalio.DigitalInOut(D9) -lcd_backlight = digitalio.DigitalInOut(D13) -lcd = adafruit_character_lcd.Character_LCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, - lcd_d7, lcd_columns, lcd_rows, lcd_backlight) -checkmark = bytes([0x0, 0x0, 0x1, 0x3, 0x16, 0x1c, 0x8, 0x0]) -lcd.clear() -lcd.message('\x00') diff --git a/examples/rpi_charlcd_mono_simpletest.py b/examples/rpi_charlcd_mono_simpletest.py deleted file mode 100644 index 8ac95f4..0000000 --- a/examples/rpi_charlcd_mono_simpletest.py +++ /dev/null @@ -1,53 +0,0 @@ -import time -import board -import digitalio -import adafruit_character_lcd - -# Character LCD Config: -# Modify this if you have a different sized character LCD -lcd_columns = 16 -lcd_rows = 2 - -# Raspberry Pi Pin Config: -lcd_rs = digitalio.DigitalInOut(board.D26) -lcd_en = digitalio.DigitalInOut(board.D19) -lcd_d7 = digitalio.DigitalInOut(board.D27) -lcd_d6 = digitalio.DigitalInOut(board.D22) -lcd_d5 = digitalio.DigitalInOut(board.D24) -lcd_d4 = digitalio.DigitalInOut(board.D25) -lcd_backlight = digitalio.DigitalInOut(board.D4) - -# Init the lcd class -lcd = adafruit_character_lcd.Character_LCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, - lcd_d7, lcd_columns, lcd_rows, lcd_backlight) - -# Print a 2x line message -lcd.message('hello\ncircuitpython') -# Wait 5s -time.sleep(5) -# Demo showing cursor -lcd.clear() -lcd.show_cursor(True) -lcd.message('showing cursor ') -# Wait 5s -time.sleep(5) -# Demo showing the blinking cursor -lcd.clear() -lcd.blink(True) -lcd.message('Blinky Cursor!') -# Wait 5s -time.sleep(5) -lcd.blink(False) -# Demo scrolling message LEFT -lcd.clear() -scroll_msg = 'Scroll' -lcd.message(scroll_msg) -# Scroll to the left -for i in range(lcd_columns - len(scroll_msg)): - time.sleep(0.5) - lcd.move_left() -# Demo turning backlight off -lcd.clear() -lcd.message("going to sleep\ncya later!") -lcd.set_backlight(False) -time.sleep(2) diff --git a/requirements.txt b/requirements.txt index 4dab381..bb4227b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ adafruit-circuitpython-busdevice -Adafruit-Blinka \ No newline at end of file +Adafruit-Blinka +adafruit-circuitpython-mcp230xx +adafruit-circuitpython-74hc595 \ No newline at end of file