-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathi2c_pcf8574_interface.py
95 lines (72 loc) · 3.4 KB
/
i2c_pcf8574_interface.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Copyright (C) 2017 Dan Halbert
# Adapted from https://github.com/dbrgn/RPLCD, Copyright (C) 2013-2016 Danilo Bargen
# 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.
"""Low-level interface to PCF8574."""
import busio
import board
import microcontroller
from adafruit_bus_device.i2c_device import I2CDevice
from lcd import LCD_4BITMODE, LCD_BACKLIGHT, LCD_NOBACKLIGHT, PIN_ENABLE
class I2CPCF8574Interface:
# Bit values to turn backlight on/off. Indexed by a boolean.
_BACKLIGHT_VALUES = (LCD_NOBACKLIGHT, LCD_BACKLIGHT)
def __init__(self, i2c, address):
"""
CharLCD via PCF8574 I2C port expander.
Pin mapping::
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
D7 | D6 | D5 | D4 | BL | EN | RW | RS
:param address: The I2C address of your LCD.
"""
self.address = address
self._backlight_pin_state = LCD_BACKLIGHT
self.i2c = i2c
self.i2c_device = I2CDevice(self.i2c, self.address)
self.data_buffer = bytearray(1)
def deinit(self):
self.i2c.deinit()
@property
def data_bus_mode(self):
return LCD_4BITMODE
@property
def backlight(self):
return self._backlight_pin_state == LCD_BACKLIGHT
@backlight.setter
def backlight(self, value):
self._backlight_pin_state = self._BACKLIGHT_VALUES[value]
with self.i2c_device:
self._i2c_write(self._backlight_pin_state)
# Low level commands
def send(self, value, rs_mode):
"""Send the specified value to the display in 4-bit nibbles.
The rs_mode is either ``_RS_DATA`` or ``_RS_INSTRUCTION``."""
self._write4bits(rs_mode | (value & 0xF0) | self._backlight_pin_state)
self._write4bits(rs_mode | ((value << 4) & 0xF0) | self._backlight_pin_state)
def _write4bits(self, value):
"""Pulse the `enable` flag to process value."""
with self.i2c_device:
self._i2c_write(value & ~PIN_ENABLE)
# This 1us delay is probably unnecessary, given the time needed
# to execute the statements.
microcontroller.delay_us(1)
self._i2c_write(value | PIN_ENABLE)
microcontroller.delay_us(1)
self._i2c_write(value & ~PIN_ENABLE)
# Wait for command to complete.
microcontroller.delay_us(100)
def _i2c_write(self, value):
self.data_buffer[0] = value
self.i2c_device.write(self.data_buffer)