Created
November 11, 2014 17:00
-
-
Save electricimp/362263bbcf06c4b031ea to your computer and use it in GitHub Desktop.
Squirrel class to drive a character LCD driven Hitachi HD44780 controller via Adafruit I2C backpack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LCD | |
{ | |
// A Squirrel class to drive a 16 x 2 to 20 x 4 character LCD driven by a Hitachi HD44780 controller | |
// via an MCP23008 interface chip on an Adafruit I2C backpack [http://www.adafruit.com/product/292] | |
// Communicates with any imp I2C bus | |
// Written by Tony Smith (@smittytone) October 2014 | |
// Version 1.0 | |
MCP23008_ADDRESS = 0x20 | |
MCP23008_IODIR = "\x00" | |
MCP23008_GPIO = "\x09" | |
// HD44780 Commands | |
LCD_CLEARDISPLAY = 0x01 | |
LCD_RETURNHOME = 0x02 | |
LCD_ENTRYMODESET = 0x04 | |
LCD_DISPLAYCONTROL = 0x08 | |
LCD_CURSORSHIFT = 0x10 | |
LCD_FUNCTIONSET = 0x20 | |
LCD_SETCGRAMADDR = 0x40 | |
LCD_SETDDRAMADDR = 0x80 | |
// Flags for display entry mode | |
LCD_ENTRYRIGHT = 0x00 | |
LCD_ENTRYLEFT = 0x02 | |
LCD_ENTRYSHIFTINCREMENT = 0x01 | |
LCD_ENTRYSHIFTDECREMENT = 0x00 | |
// Flags for display on/off control | |
LCD_DISPLAYON = 0x04 | |
LCD_DISPLAYOFF = 0x00 | |
LCD_CURSORON = 0x02 | |
LCD_CURSOROFF = 0x00 | |
LCD_BLINKON = 0x01 | |
LCD_BLINKOFF = 0x00 | |
LCD_BACKLIGHT = 0x80 | |
// Flags for display/cursor shift | |
LCD_DISPLAYMOVE = 0x08 | |
LCD_CURSORMOVE = 0x00 | |
LCD_MOVERIGHT = 0x04 | |
LCD_MOVELEFT = 0x00 | |
// Flags for display mode | |
LCD_8BITMODE = 0x10 | |
LCD_4BITMODE = 0x00 | |
LCD_2LINE = 0x08 | |
LCD_1LINE = 0x00 | |
LCD_5x10DOTS = 0x04 | |
LCD_5x8DOTS = 0x00 | |
HIGH = 1 | |
LOW = 0 | |
_lcdWidth = 0 | |
_lcdHeight = 0 | |
_currentLine = 0 | |
_currentCol = 0 | |
_device = null | |
_devAddress = 0 | |
_displayControl = 0 | |
_displayFunction = 0 | |
_displayMode = 0 | |
constructor(impI2Cbus) | |
{ | |
// Constructor function takes chosen imp I2C bus | |
// Note: I2C address is fixed | |
_device = impI2Cbus | |
_devAddress = MCP23008_ADDRESS << 1 | |
_device.configure(CLOCK_SPEED_100_KHZ) | |
} | |
function init(cols = 16, rows = 2) | |
{ | |
// Initializes the display | |
// | |
// Parameters: | |
// 1. Integer value for the number of characters per line that the display supports (Default: 16) | |
// 2. Integer value for the number of lines that the display supports (Default: 2) | |
if (rows < 1) rows = 1 | |
if (cols < 1) cols = 1 | |
_lcdWidth = cols | |
_lcdHeight = rows | |
_displayFunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS | |
if (_lcdHeight > 1) _displayFunction = _displayFunction | LCD_2LINE | |
delay(5) | |
_device.write(_devAddress, MCP23008_IODIR + "\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00") | |
_device.write(_devAddress, MCP23008_IODIR + "\x00") | |
// Must write the next two lines two further times each | |
_device.write(_devAddress, MCP23008_GPIO + "\x9C") | |
_device.write(_devAddress, MCP23008_GPIO + "\x98") | |
_device.write(_devAddress, MCP23008_GPIO + "\x9C") | |
_device.write(_devAddress, MCP23008_GPIO + "\x98") | |
_device.write(_devAddress, MCP23008_GPIO + "\x9C") | |
_device.write(_devAddress, MCP23008_GPIO + "\x98") | |
_device.write(_devAddress, MCP23008_GPIO + "\x94") | |
_device.write(_devAddress, MCP23008_GPIO + "\x90") | |
delay(5) | |
sendCommand(LCD_FUNCTIONSET | _displayFunction) | |
delay(5) | |
sendCommand(LCD_FUNCTIONSET | _displayFunction) | |
delay(5) | |
displayOn() | |
clearScreen() | |
_displayMode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT | |
sendCommand(LCD_ENTRYMODESET | _displayMode) | |
setBacklight(HIGH) | |
} | |
function clearScreen() | |
{ | |
// Clear the display | |
sendCommand(LCD_CLEARDISPLAY) | |
delay(2) | |
} | |
function displayOn() | |
{ | |
// Power up and activate the display | |
_displayControl = _displayControl | LCD_DISPLAYON | |
sendCommand(LCD_DISPLAYCONTROL | _displayControl) | |
} | |
function displayOff() | |
{ | |
// Power down the display | |
_displayControl = _displayControl | LCD_DISPLAYOFF | |
sendCommand(LCD_DISPLAYCONTROL | _displayControl) | |
} | |
function setBacklight(setting) | |
{ | |
// Set the backlight | |
// | |
// Parameters: | |
// 1. Boolean value indicating whether the backlight should be on or off | |
// | |
// Note: Backlight intensity is not supported by HD44780 | |
if (setting == HIGH) | |
{ | |
_displayControl = _displayControl | 0x80 | |
_device.write(_devAddress, MCP23008_GPIO + "\x80") | |
} | |
else | |
{ | |
_displayControl = _displayControl & 0x7F | |
_device.write(_devAddress, MCP23008_GPIO + "\x00") | |
} | |
} | |
function setCursor(col, row) | |
{ | |
// Set the print cursor at the selected co-ordinates | |
// | |
// Parameters: | |
// 1. Integer for the column number | |
// 2. Integer for the row number | |
// | |
// Note: Column and row values begin at zero | |
local rowOffsets = [0x00, 0x40, 0x14, 0x54] | |
if (row < 0) row = 0 | |
if (row >= _lcdHeight) row = _lcdHeight - 1 | |
if (col < 0) col = 0 | |
if (col >= _lcdWidth) col = _lcdWidth - 1 | |
sendCommand(LCD_SETDDRAMADDR | (col + rowOffsets[row])) | |
_currentLine = col | |
_currentCol = col | |
} | |
function createCustomChar(charMatrix = [], asciiCode = 0) | |
{ | |
// Set one of the HD44780's eight custom 5 x 8 user-definable characters | |
if (asciiCode < 0 || asciiCode > 7) return | |
if (charMatrix.len() == 0 || charMatrix == null) return | |
sendCommand(LCD_SETCGRAMADDR | (asciiCode << 3)) | |
for (local i = 0 ; i < 8 ; i++) | |
{ | |
writeData(charMatrix[i]) | |
} | |
} | |
function print(stringToPrint = "") | |
{ | |
// Print a string at the current cursor location | |
// | |
// Parameters: | |
// 1. String value to be printed | |
if (stringToPrint == "" || stringToPrint == null) return | |
if (typeof stringToPrint != "string") return | |
for (local i = 0 ; i < stringToPrint.len() ; i++) | |
{ | |
writeData(stringToPrint[i]) | |
} | |
} | |
function printChar(ascii = 65) | |
{ | |
// Print a string at the current cursor location | |
// | |
// Parameters: | |
// 1. Integer value for the Ascii code of the character to be printed | |
if (ascii < 0) ascii = 32 | |
if (ascii > 7 && ascii < 32) ascii = 32 | |
if (ascii > 127) ascii = 32 | |
writeData(ascii) | |
} | |
function centerText(stringToPrint) | |
{ | |
// Returns a string formatted to be centred on the display, ie. it pads with spaces | |
// so the string can be printed at column 0 | |
// | |
// Parameters: | |
// 1. String value to be printed | |
if (stringToPrint == "" || stringToPrint == null) return | |
if (typeof stringToPrint != "string") return | |
local inset = stringToPrint.len() | |
if (inset > _lcdWidth) | |
{ | |
inset = inset - _lcdWidth | |
inset = inset / 2 | |
stringToPrint = stringToPrint.slice(inset, inset + _lcdWidth) | |
} | |
else if (inset < _lcdWidth) | |
{ | |
inset = _lcdWidth - inset | |
inset = inset / 2 | |
local spaces = " " | |
stringToPrint = spaces.slice(0, inset) + stringToPrint + spaces.slice(0, inset) | |
} | |
return stringToPrint | |
} | |
function sendCommand(command) | |
{ | |
// Send command to the HD77480 | |
send(command, LOW) | |
} | |
function writeData(dataByte) | |
{ | |
// Send data to the HD77480 | |
send(dataByte, HIGH) | |
} | |
function send(value, rsPinValue) | |
{ | |
// Generic send function to pass bytes to the HD74480 | |
// RS pin = bit 1 | |
// Enable pin = bit 2 | |
// Data pin 4 = bit 3 | |
// Data pin 5 = bit 4 | |
// Data pin 6 = bit 5 | |
// Data pin 7 = bit 6 | |
// Backlight = bit 7 | |
// Get passed value's upper four bits and shift down to bits 6-3 (data pins) | |
local buffer = (value & 0xF0) >> 1 | |
if (rsPinValue == HIGH) | |
{ | |
// Set E + RS bits | |
buffer = buffer | 0x06 | |
} | |
else | |
{ | |
// Set E bit | |
buffer = buffer | 0x04 | |
} | |
// Set backlight bit if its set in _displayControl | |
if (_displayControl & LCD_BACKLIGHT) | |
{ | |
buffer = buffer | 0x80 | |
} | |
else | |
{ | |
buffer = buffer & 0x7F | |
} | |
_device.write(_devAddress, MCP23008_GPIO + buffer.tochar()) | |
// clear the enable bit and send again | |
buffer = buffer & 0xFB | |
_device.write(_devAddress, MCP23008_GPIO + buffer.tochar()) | |
// Get the passed value's lower four bits, shifted to bits 6-3 | |
buffer = (value & 0x0F) << 3 | |
if (rsPinValue == HIGH) | |
{ | |
// Set E + RS bits | |
buffer = buffer | 0x06 | |
} | |
else | |
{ | |
// Set E bit | |
buffer = buffer | 0x04 | |
} | |
// Set backlight bit if its set in _displayControl | |
if (_displayControl & LCD_BACKLIGHT) | |
{ | |
buffer = buffer | 0x80 | |
} | |
else | |
{ | |
buffer = buffer & 0x7F | |
} | |
_device.write(_devAddress, MCP23008_GPIO + buffer.tochar()) | |
// clear the enable bit and send again | |
buffer = buffer & 0xFB | |
_device.write(_devAddress, MCP23008_GPIO + buffer.tochar()) | |
} | |
function delay(value) | |
{ | |
// Blocking delay for ‘value’ milliseconds | |
local a = hardware.millis() + value; | |
while (hardware.millis() < a) {} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment