1
0
Fork 0

Adds working LCD driver

This commit is contained in:
Shawn Nock 2017-01-13 17:44:02 +00:00
parent fef826f1d3
commit 1924f027c6
1 changed files with 75 additions and 37 deletions

View File

@ -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)