Adds working LCD driver
This commit is contained in:
parent
fef826f1d3
commit
1924f027c6
|
@ -1,5 +1,6 @@
|
|||
import time
|
||||
from smbus import SMBus
|
||||
from twisted.internet import reactor
|
||||
|
||||
ADDR = 0x20
|
||||
BUS = 1
|
||||
|
@ -7,8 +8,8 @@ BUS = 1
|
|||
LCD_DATA = 1
|
||||
LCD_CMD = 0
|
||||
|
||||
LCD_LINE_ADDR = {0: 0x80,
|
||||
1: 0xc0}
|
||||
LCD_LINE_ADDR = {0: 0x0,
|
||||
1: 0x40}
|
||||
|
||||
# Timing constants
|
||||
E_PULSE = 0.0005
|
||||
|
@ -36,7 +37,31 @@ DB7 = (1 << 6)
|
|||
LCD_BACKLIGHT = (1 << 7)
|
||||
|
||||
# HD44780 Commands
|
||||
LCD_CLEAR = 1
|
||||
|
||||
LCD_HOME = (1 << 1)
|
||||
|
||||
LCD_ENTRY_MODE = (1 << 2)
|
||||
CURSOR_INCR = (1 << 1)
|
||||
CURSOR_DECR = (0 << 1)
|
||||
SHIFT_ENABLE = (1 << 0)
|
||||
SHIFT_DISABLE = (0 << 0)
|
||||
|
||||
DISPLAY_CTRL = (1 << 3)
|
||||
DISPLAY_ON = (1 << 2)
|
||||
DISPLAY_OFF = (0 << 2)
|
||||
CURSOR_ON = (1 << 1)
|
||||
CURSOR_OFF = (0 << 1)
|
||||
BLINK_ON = (1 << 0)
|
||||
BLINK_OFF = (0 << 0)
|
||||
|
||||
FUNC_SET = (1 << 4)
|
||||
DATA_4BIT = (1 << 3)
|
||||
DATA_8BIT = (0 << 3)
|
||||
TWO_LINES = (1 << 2)
|
||||
ONE_LINE = (0 << 2)
|
||||
|
||||
SET_ADDRESS = (1 << 7)
|
||||
|
||||
class LCD(object):
|
||||
def __init__(self, addr=ADDR):
|
||||
|
@ -48,58 +73,71 @@ class LCD(object):
|
|||
def _init_mcp(self):
|
||||
# Set MCP23008 pins as outputs
|
||||
self._write_reg(IODIR, 0x00)
|
||||
# Disable incrementing pointer
|
||||
self._write_reg(IOCON, IOCON_SREAD)
|
||||
# Enable Backlight
|
||||
self._write_reg(0x09, 1 << 7)
|
||||
|
||||
def _write4(self, bits):
|
||||
message = (bits << 3) | LCD_BACKLIGHT
|
||||
self.bus.write_byte(self.addr, message)
|
||||
self._latch(message)
|
||||
|
||||
def write_cmd(self, byte):
|
||||
self._write4((byte & 0xf0) >> 4)
|
||||
self._write4((byte & 0x0f))
|
||||
|
||||
def _init_hd44780(self):
|
||||
# Initialize, set to 4bit mode
|
||||
self._write4(DB4|DB5)
|
||||
# Again, this time with feeling!
|
||||
self._write4(DB4|DB5)
|
||||
# Again, this time with feeling!
|
||||
self._write4(DB4|DB5)
|
||||
self._write4(DB5)
|
||||
self.write_cmd((DB5 << 4) | DB7)
|
||||
self.write_cmd(1) # Clear Display
|
||||
self.write_cmd(0 | (DB4 | DB5 | DB6 | DB7)) # Display ON, Cursor ON, Cursor Blinking
|
||||
self.write_cmd(0 | (DB5 | DB6)) # Entry Mode
|
||||
# Now we're in 4bit mode, move up to normal commands
|
||||
# Function Set
|
||||
self.write_cmd(FUNC_SET | TWO_LINES | DATA_4BIT) # 2 lines, 4bit
|
||||
# Clear Display
|
||||
self.write_cmd(LCD_CLEAR) # Clear Display
|
||||
self.write_cmd(LCD_HOME) # Home Display
|
||||
self.write_cmd(DISPLAY_CTRL | DISPLAY_ON) # Display ON
|
||||
self.write_cmd(LCD_ENTRY_MODE | CURSOR_INCR) # Entry Mode
|
||||
|
||||
def _write4(self, bits, data=False):
|
||||
# No shift, use DB* macros
|
||||
message = bits | LCD_BACKLIGHT
|
||||
if data:
|
||||
message |= RS
|
||||
else:
|
||||
message &= ~RS
|
||||
self._write_reg(GPIO, message | ENABLE)
|
||||
self._latch(message)
|
||||
|
||||
def write_cmd(self, byte, data=False):
|
||||
# Shifts the bytes up, DB* macros don't work
|
||||
high = (byte & 0xf0) >> 4
|
||||
low = byte & 0x0f
|
||||
assert byte == (high << 4) | low
|
||||
self._write4(high << 3, data)
|
||||
self._write4(low << 3, data)
|
||||
|
||||
def _write_data(self, byte):
|
||||
self.write_cmd(byte, data=True)
|
||||
|
||||
def _write_reg(self, reg, val):
|
||||
self.bus.write_byte_data(self.addr, reg, val)
|
||||
|
||||
# def _write(self, byte, backlight=LCD_BACKLIGHT_ON, mode=0):
|
||||
# bits_high = (mode << 1) | ((byte & 0xF0) << 3) | backlight
|
||||
# bits_low = (mode << 1) | ((byte & 0xf) << 3) | backlight
|
||||
|
||||
# self.bus.write(self.addr, bits_high)
|
||||
# self._latch(bits_high)
|
||||
|
||||
# self.bus.write(self.addr, bits_low)
|
||||
# self._latch(bits_low)
|
||||
|
||||
def _latch(self, bits):
|
||||
time.sleep(E_DELAY)
|
||||
self.bus.write_byte(self.addr, bits | ENABLE)
|
||||
time.sleep(E_PULSE)
|
||||
self.bus.write_byte(self.addr, (bits & ~ENABLE))
|
||||
self._write_reg(GPIO, bits & ~ENABLE)
|
||||
time.sleep(E_DELAY)
|
||||
|
||||
# def write(self, line, string):
|
||||
# string = string.ljust(LCD_WIDTH, " ")[:LCD_WIDTH]
|
||||
# self._write(line)
|
||||
# for i in range(LCD_WIDTH):
|
||||
# self.write_cmd(ord(string[i]) | RS)
|
||||
def write(self, line, string):
|
||||
self.write_cmd(SET_ADDRESS | LCD_LINE_ADDR[line])
|
||||
string = string.ljust(LCD_WIDTH, " ")[:LCD_WIDTH]
|
||||
for i in range(LCD_WIDTH):
|
||||
self._write_data(ord(string[i]))
|
||||
|
||||
def shutdown(self):
|
||||
self.write_cmd(DISPLAY_CTRL|DISPLAY_OFF)
|
||||
self._write_reg(GPIO, 0) # Turn off backlight
|
||||
|
||||
LCD_SINGLETON = LCD()
|
||||
|
||||
def lcd_write_status(status):
|
||||
return
|
||||
lines = status.split('\n')[:2]
|
||||
for i in range(len(lines)):
|
||||
LCD_SINGLETON.write(LCD_LINE_ADDR[i], lines[i])
|
||||
LCD_SINGLETON.write(i, lines[i])
|
||||
|
||||
reactor.addSystemEventTrigger('before', 'shutdown',
|
||||
LCD_SINGLETON.shutdown)
|
||||
|
|
Loading…
Reference in New Issue