Skip to content

Commit

Permalink
Merge pull request #73 from BiffoBear/add_typing
Browse files Browse the repository at this point in the history
Added typing and made an edit to fix a typing issue (non-breaking)
  • Loading branch information
tekktrik committed Nov 10, 2022
2 parents 6876522 + 2d4683e commit d11d147
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 74 deletions.
144 changes: 80 additions & 64 deletions adafruit_character_lcd/character_lcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
"""
try:
from typing import Union, Optional, List, Sequence
from circuitpython_typing import pwmio
except ImportError:
pass

import time
import digitalio
Expand Down Expand Up @@ -73,7 +78,7 @@
_LCD_ROW_OFFSETS = (0x00, 0x40, 0x14, 0x54)


def _set_bit(byte_value, position, val):
def _set_bit(byte_value: int, position: int, val: bool) -> int:
# Given the specified byte_value set the bit at position to the provided
# boolean value val and return the modified byte.
ret = None
Expand All @@ -84,7 +89,9 @@ def _set_bit(byte_value, position, val):
return ret


def _map(xval, in_min, in_max, out_min, out_max):
def _map(
xval: float, in_min: float, in_max: float, out_min: float, out_max: float
) -> float:
# Affine transfer/map with constrained output.
outrange = float(out_max - out_min)
inrange = float(in_max - in_min)
Expand All @@ -106,16 +113,26 @@ class Character_LCD:
: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 int columns: The columns on the charLCD
:param int lines: The lines on the charLCD
"""

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):
def __init__(
self,
rs: digitalio.DigitalInOut,
en: digitalio.DigitalInOut,
d4: digitalio.DigitalInOut,
d5: digitalio.DigitalInOut,
d6: digitalio.DigitalInOut,
d7: digitalio.DigitalInOut,
columns: int,
lines: int,
) -> None:

self.columns = columns
self.lines = lines
Expand Down Expand Up @@ -147,7 +164,6 @@ def __init__(self, rs, en, d4, d5, d6, d7, columns, lines):
# Set entry mode
self._write8(_LCD_ENTRYMODESET | self.displaymode)
self.clear()

self._message = None
self._enable = None
self._direction = None
Expand All @@ -159,12 +175,12 @@ def __init__(self, rs, en, d4, d5, d6, d7, columns, lines):

# pylint: enable-msg=too-many-arguments

def home(self):
def home(self) -> None:
"""Moves the cursor "home" to position (0, 0)."""
self._write8(_LCD_RETURNHOME)
time.sleep(0.003)

def clear(self):
def clear(self) -> None:
"""Clears everything displayed on the LCD.
The following example displays, "Hello, world!", then clears the LCD.
Expand All @@ -186,21 +202,21 @@ def clear(self):
time.sleep(0.003)

@property
def column_align(self):
def column_align(self) -> bool:
"""If True, message text after '\\n' starts directly below start of first
character in message. If False, text after '\\n' starts at column zero.
"""
return self._column_align

@column_align.setter
def column_align(self, enable):
def column_align(self, enable: bool):
if isinstance(enable, bool):
self._column_align = enable
else:
raise ValueError("The column_align value must be either True or False")

@property
def cursor(self):
def cursor(self) -> bool:
"""True if cursor is visible. False to stop displaying the cursor.
The following example shows the cursor after a displayed message:
Expand All @@ -222,19 +238,19 @@ def cursor(self):
return self.displaycontrol & _LCD_CURSORON == _LCD_CURSORON

@cursor.setter
def cursor(self, show):
def cursor(self, show: bool) -> None:
if show:
self.displaycontrol |= _LCD_CURSORON
else:
self.displaycontrol &= ~_LCD_CURSORON
self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol)

def cursor_position(self, column, row):
def cursor_position(self, column: int, row: int) -> None:
"""Move the cursor to position ``column``, ``row`` for the next
message only. Displaying a message resets the cursor position to (0, 0).
:param column: column location
:param row: row location
:param int column: column location
:param int row: row location
"""
# Clamp row to the last row of the display
if row >= self.lines:
Expand All @@ -249,7 +265,7 @@ def cursor_position(self, column, row):
self.column = column

@property
def blink(self):
def blink(self) -> bool:
"""
Blink the cursor. True to blink the cursor. False to stop blinking.
Expand All @@ -272,15 +288,15 @@ def blink(self):
return self.displaycontrol & _LCD_BLINKON == _LCD_BLINKON

@blink.setter
def blink(self, blink):
def blink(self, blink: bool) -> None:
if blink:
self.displaycontrol |= _LCD_BLINKON
else:
self.displaycontrol &= ~_LCD_BLINKON
self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol)

@property
def display(self):
def display(self) -> bool:
"""
Enable or disable the display. True to enable the display. False to disable the display.
Expand All @@ -302,15 +318,15 @@ def display(self):
return self.displaycontrol & _LCD_DISPLAYON == _LCD_DISPLAYON

@display.setter
def display(self, enable):
def display(self, enable: bool) -> None:
if enable:
self.displaycontrol |= _LCD_DISPLAYON
else:
self.displaycontrol &= ~_LCD_DISPLAYON
self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol)

@property
def message(self):
def message(self) -> Optional[str]:
"""Display a string of text on the character LCD.
Start position is (0,0) if cursor_position is not set.
If cursor_position is set, message starts at the set
Expand All @@ -335,7 +351,7 @@ def message(self):
return self._message

@message.setter
def message(self, message):
def message(self, message: str):
self._message = message
# Set line to match self.row from cursor_position()
line = self.row
Expand Down Expand Up @@ -377,7 +393,7 @@ def message(self, message):
# reset column and row to (0,0) after message is displayed
self.column, self.row = 0, 0

def move_left(self):
def move_left(self) -> None:
"""Moves displayed text left one column.
The following example scrolls a message to the left off the screen.
Expand All @@ -400,7 +416,7 @@ def move_left(self):
"""
self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVELEFT)

def move_right(self):
def move_right(self) -> None:
"""Moves displayed text right one column.
The following example scrolls a message to the right off the screen.
Expand All @@ -424,7 +440,7 @@ def move_right(self):
self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVERIGHT)

@property
def text_direction(self):
def text_direction(self) -> Optional[int]:
"""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``.
Expand All @@ -448,33 +464,33 @@ def text_direction(self):
return self._direction

@text_direction.setter
def text_direction(self, direction):
def text_direction(self, direction: int) -> None:
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):
def _left_to_right(self) -> None:
# Displays text from left to right on the LCD.
self.displaymode |= _LCD_ENTRYLEFT
self._write8(_LCD_ENTRYMODESET | self.displaymode)

def _right_to_left(self):
def _right_to_left(self) -> None:
# 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):
def create_char(self, location: int, pattern: Sequence[int]) -> None:
"""
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
:param int location: Integer in range(8) to store the created character.
:param Sequence[int] pattern: len(8) describes created character.
"""
# only position 0..7 are allowed
Expand All @@ -483,9 +499,9 @@ def create_char(self, location, pattern):
for i in range(8):
self._write8(pattern[i], char_mode=True)

def _write8(self, value, char_mode=False):
def _write8(self, value: int, char_mode: bool = False) -> None:
# Sends 8b ``value`` in ``char_mode``.
# :param value: bytes
# :param value: int
# :param char_mode: character/data mode selector. False (default) for
# data only, True for character bits.
# one ms delay to prevent writing too quickly.
Expand All @@ -506,7 +522,7 @@ def _write8(self, value, char_mode=False):
self.dl7.value = ((value >> 3) & 1) > 0
self._pulse_enable()

def _pulse_enable(self):
def _pulse_enable(self) -> None:
# Pulses (lo->hi->lo) to send commands.
self.enable.value = False
# 1microsec pause
Expand All @@ -530,8 +546,8 @@ class Character_LCD_Mono(Character_LCD):
: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 int columns: The columns on the charLCD
:param int 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
Expand All @@ -542,16 +558,16 @@ class Character_LCD_Mono(Character_LCD):
# pylint: disable-msg=too-many-arguments
def __init__(
self,
rs,
en,
db4,
db5,
db6,
db7,
columns,
lines,
backlight_pin=None,
backlight_inverted=False,
rs: digitalio.DigitalInOut,
en: digitalio.DigitalInOut,
db4: digitalio.DigitalInOut,
db5: digitalio.DigitalInOut,
db6: digitalio.DigitalInOut,
db7: digitalio.DigitalInOut,
columns: int,
lines: int,
backlight_pin: Optional[digitalio.DigitalInOut] = None,
backlight_inverted: bool = False,
):

# Backlight pin and inversion
Expand All @@ -567,7 +583,7 @@ def __init__(
# pylint: enable-msg=too-many-arguments

@property
def backlight(self):
def backlight(self) -> Optional[bool]:
"""Enable or disable backlight. True if backlight is on. False if backlight is off.
The following example turns the backlight off, then displays, "Hello, world?", then turns
Expand All @@ -594,7 +610,7 @@ def backlight(self):
return self._enable

@backlight.setter
def backlight(self, enable):
def backlight(self, enable: bool) -> None:
self._enable = enable
if enable:
self.backlight_pin.value = not self.backlight_inverted
Expand All @@ -611,8 +627,8 @@ class Character_LCD_RGB(Character_LCD):
: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 int columns: The columns on the charLCD
:param int lines: The lines on the charLCD
:param ~pwmio.PWMOut,~digitalio.DigitalInOut red: Red RGB Anode
:param ~pwmio.PWMOut,~digitalio.DigitalInOut green: Green RGB Anode
:param ~pwmio.PWMOut,~digitalio.DigitalInOut blue: Blue RGB Anode
Expand All @@ -624,19 +640,19 @@ class Character_LCD_RGB(Character_LCD):
# pylint: disable-msg=too-many-arguments
def __init__(
self,
rs,
en,
db4,
db5,
db6,
db7,
columns,
lines,
red,
green,
blue,
read_write=None,
):
rs: digitalio.DigitalInOut,
en: digitalio.DigitalInOut,
db4: digitalio.DigitalInOut,
db5: digitalio.DigitalInOut,
db6: digitalio.DigitalInOut,
db7: digitalio.DigitalInOut,
columns: int,
lines: int,
red: Union[pwmio.PWMOut, digitalio.DigitalInOut],
green: Union[pwmio.PWMOut, digitalio.DigitalInOut],
blue: Union[pwmio.PWMOut, digitalio.DigitalInOut],
read_write: Optional[digitalio.DigitalInOut] = None,
) -> None:

# Define read_write (rw) pin
self.read_write = read_write
Expand All @@ -662,7 +678,7 @@ def __init__(
super().__init__(rs, en, db4, db5, db6, db7, columns, lines)

@property
def color(self):
def color(self) -> List[int]:
"""
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
Expand Down Expand Up @@ -693,7 +709,7 @@ def color(self):
return self._color

@color.setter
def color(self, color):
def color(self, color: Union[List[float], int]) -> None:
if isinstance(color, int):
if color >> 24:
raise ValueError("Integer color value must be positive and 24 bits max")
Expand Down

0 comments on commit d11d147

Please sign in to comment.