Adds working LCD driver
This commit is contained in:
parent
fef826f1d3
commit
1924f027c6
|
@ -1,5 +1,6 @@
|
||||||
import time
|
import time
|
||||||
from smbus import SMBus
|
from smbus import SMBus
|
||||||
|
from twisted.internet import reactor
|
||||||
|
|
||||||
ADDR = 0x20
|
ADDR = 0x20
|
||||||
BUS = 1
|
BUS = 1
|
||||||
|
@ -7,8 +8,8 @@ BUS = 1
|
||||||
LCD_DATA = 1
|
LCD_DATA = 1
|
||||||
LCD_CMD = 0
|
LCD_CMD = 0
|
||||||
|
|
||||||
LCD_LINE_ADDR = {0: 0x80,
|
LCD_LINE_ADDR = {0: 0x0,
|
||||||
1: 0xc0}
|
1: 0x40}
|
||||||
|
|
||||||
# Timing constants
|
# Timing constants
|
||||||
E_PULSE = 0.0005
|
E_PULSE = 0.0005
|
||||||
|
@ -36,7 +37,31 @@ DB7 = (1 << 6)
|
||||||
LCD_BACKLIGHT = (1 << 7)
|
LCD_BACKLIGHT = (1 << 7)
|
||||||
|
|
||||||
# HD44780 Commands
|
# 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):
|
class LCD(object):
|
||||||
def __init__(self, addr=ADDR):
|
def __init__(self, addr=ADDR):
|
||||||
|
@ -48,58 +73,71 @@ class LCD(object):
|
||||||
def _init_mcp(self):
|
def _init_mcp(self):
|
||||||
# Set MCP23008 pins as outputs
|
# Set MCP23008 pins as outputs
|
||||||
self._write_reg(IODIR, 0x00)
|
self._write_reg(IODIR, 0x00)
|
||||||
# Disable incrementing pointer
|
|
||||||
self._write_reg(IOCON, IOCON_SREAD)
|
|
||||||
# Enable Backlight
|
# Enable Backlight
|
||||||
self._write_reg(0x09, 1 << 7)
|
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):
|
def _init_hd44780(self):
|
||||||
# Initialize, set to 4bit mode
|
# 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._write4(DB5)
|
||||||
self.write_cmd((DB5 << 4) | DB7)
|
# Now we're in 4bit mode, move up to normal commands
|
||||||
self.write_cmd(1) # Clear Display
|
# Function Set
|
||||||
self.write_cmd(0 | (DB4 | DB5 | DB6 | DB7)) # Display ON, Cursor ON, Cursor Blinking
|
self.write_cmd(FUNC_SET | TWO_LINES | DATA_4BIT) # 2 lines, 4bit
|
||||||
self.write_cmd(0 | (DB5 | DB6)) # Entry Mode
|
# 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):
|
def _write_reg(self, reg, val):
|
||||||
self.bus.write_byte_data(self.addr, 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):
|
def _latch(self, bits):
|
||||||
time.sleep(E_DELAY)
|
|
||||||
self.bus.write_byte(self.addr, bits | ENABLE)
|
|
||||||
time.sleep(E_PULSE)
|
time.sleep(E_PULSE)
|
||||||
self.bus.write_byte(self.addr, (bits & ~ENABLE))
|
self._write_reg(GPIO, bits & ~ENABLE)
|
||||||
time.sleep(E_DELAY)
|
time.sleep(E_DELAY)
|
||||||
|
|
||||||
# def write(self, line, string):
|
def write(self, line, string):
|
||||||
# string = string.ljust(LCD_WIDTH, " ")[:LCD_WIDTH]
|
self.write_cmd(SET_ADDRESS | LCD_LINE_ADDR[line])
|
||||||
# self._write(line)
|
string = string.ljust(LCD_WIDTH, " ")[:LCD_WIDTH]
|
||||||
# for i in range(LCD_WIDTH):
|
for i in range(LCD_WIDTH):
|
||||||
# self.write_cmd(ord(string[i]) | RS)
|
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()
|
LCD_SINGLETON = LCD()
|
||||||
|
|
||||||
def lcd_write_status(status):
|
def lcd_write_status(status):
|
||||||
return
|
|
||||||
lines = status.split('\n')[:2]
|
lines = status.split('\n')[:2]
|
||||||
for i in range(len(lines)):
|
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