UNPKG

lcdi2c

Version:

I2C LCD character display driver for Raspberry Pi using PCF8574 port expander.

310 lines (267 loc) 9.26 kB
//lcdi2c.js - Add I2C LCD character display using PCF8574 I2C port expander. // https://github.com/wilberforce/lcd-pcf8574 but replaced calls to i2c library with // calls to i2c-bus. Currently, only works in synchronous output mode. Asynch mode does not work. // LCD i2c interface via PCF8574P // http://dx.com/p/lcd1602-adapter-board-w-iic-i2c-interface-black-works-with-official-arduino-boards-216865 // https://gist.github.com/chrisnew/6725633 // http://www.espruino.com/HD44780 // http://www.espruino.com/LCD1602 var i2c = require('i2c-bus'); var sleep = require('sleep'); var displayPorts = { RS : 0x01, E : 0x04, D4 : 0x10, D5 : 0x20, D6 : 0x40, D7 : 0x80, CHR : 1, CMD : 0, backlight : 0x08, RW : 0x20 // not used }; var buffer = new Buffer(3); //Required for printlnBuffer. //LCD() - Initialize LCD object. // device: I2C bus number; 0 for rev. 1 boards, 1 for rev. 2+ boards. // address: Address of device (use i2cdetect to determine this) // cols: columns supported by display (e.g. 16 or 20) // rows: rows supported by display (e.g. 2 or 4 ) var LCD = function (device, address, cols, rows ) { //this.i2c = new i2c(address, { // device : device // }); this.device = device; this.address = address; this.cols = cols; this.rows = rows; this.error = null; this.i2c = i2c.open( device, function( err ) { if ( err ) { console.log( 'Unable to open I2C port on device ' + device + ' ERROR: ' + err ); console.log( this ); this.error = err; return this }; }); //console.log( 'Opened I2C port on bus ' + device + ' for LCD at address 0x' + address.toString( 16 ) + '.' ); this._sleep(1000); this.write4( 0x33, displayPorts.CMD); //initialization this._sleep(200); this.write4(0x32, displayPorts.CMD); //initialization this._sleep(100); this.write4( 0x06, displayPorts.CMD); //initialization this._sleep(100); this.write4( 0x28, displayPorts.CMD); //initialization this._sleep(100); this.write4( 0x01, displayPorts.CMD); //initialization this._sleep(100); this.write4(LCD.FUNCTIONSET | LCD._4BITMODE | LCD._2LINE | LCD._5x10DOTS, displayPorts.CMD); //4 bit - 2 line 5x7 matrix this._sleep(10); this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON, displayPorts.CMD); //turn cursor off 0x0E to enable cursor this._sleep(10); this.write( LCD.ENTRYMODESET | LCD.ENTRYLEFT, displayPorts.CMD); //shift cursor right this._sleep(10); this.write( LCD.CLEARDISPLAY, displayPorts.CMD); // LCD clear this.write( displayPorts.backlight, displayPorts.CHR ); //Turn on backlight. return this; }; // 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; //# flags for display/cursor shift LCD.DISPLAYMOVE = 0x08; LCD.CURSORMOVE = 0x00; LCD.MOVERIGHT = 0x04; LCD.MOVELEFT = 0x00; //# flags for function set LCD._8BITMODE = 0x10; LCD._4BITMODE = 0x00; LCD._2LINE = 0x08; LCD._1LINE = 0x00; LCD._5x10DOTS = 0x04; LCD._5x8DOTS = 0x00; //Line addresses. LCD.LINEADDRESS = []; LCD.LINEADDRESS[1] = 0x80; LCD.LINEADDRESS[2] = 0xC0; LCD.LINEADDRESS[3] = 0x94; LCD.LINEADDRESS[4] = 0xD4; LCD.prototype._sleep = function (milli) { sleep.usleep(milli * 1000); }; LCD.prototype.write4 = function( x, c) { try { var a = (x & 0xF0); // Use upper 4 bit nibble this.i2c.sendByteSync(this.address, a | displayPorts.backlight | c ); this.i2c.sendByteSync(this.address, a | displayPorts.E | displayPorts.backlight | c); this.i2c.sendByteSync(this.address, a | displayPorts.backlight | c ); } catch ( err ) { this.error = err; }; this._sleep(2); } LCD.prototype.write4Async = function( x, c) { var a = (x & 0xF0); // Use upper 4 bit nibble this.i2c.sendByte(this.address, 1, a | displayPorts.backlight | c, function( err ) { if ( err ) { this.error = err; }; this.i2c.sendByte(this.address, 1, a | displayPorts.E | displayPorts.backlight | c, function( err ) { if ( err ) { this.error = err; }; this.i2c.sendByte(this.address, 1, a | displayPorts.backlight | c, function( err ) { if ( err ) { this.error = err; }; }); }); }); //this._sleep(1); }; LCD.prototype.write4Block = function( x, c ) { var a = (x & 0xF0 ); //var buffer = new Buffer(3); buffer[0] = a | displayPorts.backlight | c; buffer[1] = a | displayPorts.E | displayPorts.backlight | c; buffer[2] = a | displayPorts.backlight | c; this.i2c.writeI2cBlockSync( this.address, 1, buffer.length, buffer ); this._sleep(2); }; LCD.prototype.write = function ( x, c) { this.write4(x, c); this.write4(x << 4, c); //this._sleep(2); return this; } LCD.prototype.writeBlock = function( x, c ) { this.write4Block( x, c ); this.write4Block( x << 4, c ); return this; }; LCD.prototype.clear = function () { return this.write(LCD.CLEARDISPLAY, displayPorts.CMD); } LCD.prototype.print = function ( str ) { if (typeof str == 'string') { for (var i = 0; i < str.length; i++) { var c = str[i].charCodeAt(0); this.write( c, displayPorts.CHR ); this._sleep(2); }; }; return this; } LCD.prototype.printBlock = function( str ) { if (typeof str == 'string' ) { for (var i = 0; i < str.length; i++) { var c = str[i].charCodeAt(0); this.writeBlock( c, displayPorts.CHR ); this._sleep(2); }; }; }; LCD.prototype.println = function ( str, line ) { if (typeof str == 'string') { //Set cursor to correct line. if ( line > 0 && line <= this.rows ) { this.write( LCD.LINEADDRESS[line], displayPorts.CMD ); }; this.print( str.substring(0, this.cols ) ); }; return this; }; //LCD.printlnBlock: println function, but uses writeI2CBlockSync method to speed up transfers. LCD.prototype.printlnBlock = function( str, line ) { if (typeof str == 'string' ) { if (line > 0 ) { this.write( LCD.LINEADDRESS[line], displayPorts.CMD ); }; //Now, write block to i2c. this.printBlock( str.substring( 0, this.cols ) ); }; return this; } /** flashing block for the current cursor */ LCD.prototype.cursorFull = function () { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSORON | LCD.BLINKON, displayPorts.CMD); } /** small line under the current cursor */ LCD.prototype.cursorUnder = function ( ) { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSORON | LCD.BLINKOFF, displayPorts.CMD); } /** set cursor pos, top left = 0,0 */ LCD.prototype.setCursor = function ( x, y) { var l = [0x00, 0x40, 0x14, 0x54]; return this.write(LCD.SETDDRAMADDR | (l[y] + x), displayPorts.CMD); } /** set cursor to 0,0 */ LCD.prototype.home = function () { var l = [0x00, 0x40, 0x14, 0x54]; return this.write(LCD.SETDDRAMADDR | 0x00, displayPorts.CMD); } /** Turn underline cursor off */ LCD.prototype.blinkOff = function () { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSOROFF | LCD.BLINKOFF, displayPorts.CMD); } /** Turn underline cursor on */ LCD.prototype.blinkOn = function () { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSORON | LCD.BLINKOFF, displayPorts.CMD); } /** Turn block cursor off */ LCD.prototype.cursorOff = function () { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSOROFF | LCD.BLINKON, displayPorts.CMD); } /** Turn block cursor on */ LCD.prototype.cursorOn = function () { return this.write( LCD.DISPLAYCONTROL | LCD.DISPLAYON | LCD.CURSORON | LCD.BLINKON, displayPorts.CMD); } /** setBacklight */ LCD.prototype.setBacklight = function (val) { if (val > 0) { displayPorts.backlight = 0x08; } else { displayPorts.backlight = 0x00; } return this.write(LCD.DISPLAYCONTROL, displayPorts.CMD); } /** setContrast stub */ LCD.prototype.setContrast = function (val) { return this.write(LCD.DISPLAYCONTROL, displayPorts.CMD); } /** Turn display off */ LCD.prototype.off = function () { displayPorts.backlight = 0x00; return this.write(LCD.DISPLAYCONTROL | LCD.DISPLAYOFF, displayPorts.CMD); } /** Turn display on */ LCD.prototype.on = function () { displayPorts.backlight = 0x08; return this.write(LCD.DISPLAYCONTROL | LCD.DISPLAYON, displayPorts.CMD); } /** set special character 0..7, data is an array(8) of bytes, and then return to home addr */ LCD.prototype.createChar = function (ch, data) { this.write(LCD.SETCGRAMADDR | ((ch & 7) << 3), displayPorts.CMD); for (var i = 0; i < 8; i++) this.write(data[i], displayPorts.CHR); return this.write(LCD.SETDDRAMADDR, displayPorts.CMD); } module.exports = LCD;