BoneScript
Demo: SeeedStudio Grove LCD RGB Backlight
The LCD RGB Backlight provides a simple I2C-based character LCD with various backlight colors to rapidly display status for your project.
Example
var b = require('bonescript');
var status = {};
function mydebug(x) {
console.log(x);
}
exports = (function(){
var exports = {};
// based on https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight
// Device I2C address
var LCD_ADDRESS = 0x7c>>1;
var RGB_ADDRESS = 0xc4>>1;
// color define
var WHITE = 0;
var RED = 1;
var GREEN = 2;
var BLUE = 3;
var REG_RED = 0x04; // pwm2
var REG_GREEN = 0x03; // pwm1
var REG_BLUE = 0x02; // pwm0
var REG_MODE1 = 0x00;
var REG_MODE2 = 0x01;
var REG_OUTPUT = 0x08;
// commands
var LCD_CLEARDISPLAY = 0x01;
var LCD_RETURNHOME = 0x02;
var LCD_ENTRYMODESET = 0x04;
var LCD_DISPLAYCONTROL = 0x08;
var LCD_CURSORSHIFT = 0x10;
var LCD_FUNCTIONSET = 0x20;
var LCD_SETCGRAMADDR = 0x40;
var LCD_SETDDRAMADDR = 0x80;
// flags for display entry mode
var LCD_ENTRYRIGHT = 0x00;
var LCD_ENTRYLEFT = 0x02;
var LCD_ENTRYSHIFTINCREMENT = 0x01;
var LCD_ENTRYSHIFTDECREMENT = 0x00;
// flags for display on/off control
var LCD_DISPLAYON = 0x04;
var LCD_DISPLAYOFF = 0x00;
var LCD_CURSORON = 0x02;
var LCD_CURSOROFF = 0x00;
var LCD_BLINKON = 0x01;
var LCD_BLINKOFF = 0x00;
// flags for display/cursor shift
var LCD_DISPLAYMOVE = 0x08;
var LCD_CURSORMOVE = 0x00;
var LCD_MOVERIGHT = 0x04;
var LCD_MOVELEFT = 0x00;
// flags for function set
var LCD_8BITMODE = 0x10;
var LCD_4BITMODE = 0x00;
var LCD_2LINE = 0x08;
var LCD_1LINE = 0x00;
var LCD_5x10DOTS = 0x04;
var LCD_5x8DOTS = 0x00;
var lcd;
var rgb;
exports.groveLCDOpen = function(port, col, lines, dotsize, callback) {
lcd = [port, LCD_ADDRESS];
rgb = [port, RGB_ADDRESS];
b.i2cOpen(lcd, {}, onLCDOpen);
mydebug("Open issued");
function onLCDOpen(x) {
mydebug(x);
status = {
'ready': true,
port: port,
numlines: lines,
displayfunction: 0,
displaycontrol: 0,
displaymode: 0,
currline: 0
};
if(lines > 1) status.displayfunction |= LCD_2LINE;
if ((dotsize != 0) && (lines == 1)) {
status.displayfunction |= LCD_5x10DOTS;
}
b.i2cOpen(rgb, {}, onRGBOpen);
}
function onRGBOpen(x) {
mydebug(x);
setTimeout(onWait1, 50);
}
// Send function set command sequence
function onWait1() {
exports.groveLCDCommand(LCD_FUNCTIONSET | status.displayfunction, onInit1);
}
// wait more than 4.1ms
function onInit1(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
setTimeout(onWait2, 5);
}
// second try
function onWait2() {
exports.groveLCDCommand(LCD_FUNCTIONSET | status.displayfunction, onInit2);
}
function onInit2(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
setTimeout(onWait3, 1);
}
// third go
function onWait3() {
exports.groveLCDCommand(LCD_FUNCTIONSET | status.displayfunction, onInit3);
}
// finally, set # lines, font size, etc.
function onInit3(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
exports.groveLCDCommand(LCD_FUNCTIONSET | status.displayfunction, onInit4);
}
// turn the display on with no cursor or blinking default
function onInit4(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
status.displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
exports.groveLCDDisplay(onInit5);
}
// clear it off
function onInit5(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
exports.groveLCDClear(onInit6);
}
// Initialize to default text direction (for romance languages)
function onInit6(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
status.displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
exports.groveLCDCommand(LCD_ENTRYMODESET | status.displaymode, onInit7);
}
// backlight init
function onInit7(x) {if(x.err) mydebug(JSON.stringify(x)); setReg(0, 0, onInit8);}
function onInit8(x) {if(x.err) mydebug(JSON.stringify(x)); setReg(1, 0, onInit9);}
function onInit9(x) {if(x.err) mydebug(JSON.stringify(x)); setReg(0x08, 0xAA, onInit10); }
function onInit10(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
exports.groveLCDSetColorWhite(onDone);
}
function onDone(x) {
if(x.err && x.err != {}) mydebug(JSON.stringify(x));
if(callback) callback(status);
}
};
exports.groveLCDPrint = function(string, callback) {
var err;
var i2cport = lcd[0]+',0x'+lcd[1].toString(16);
if(!status || !status.ready) {
return({'error':'Not ready'});
}
mydebug('LCD print: ' + string);
var data = [];
for(var i=0; i<string.length; i++) {
data[i] = string.charAt(i);
}
var c = 0;
mydebug('i2c write: ' + i2cport + ': 0x40 <- ' + data[c].toString(16));
b.i2cWriteBytes(lcd, 0x40, [data[c]], mycallback);
c++;
function mycallback(x) {
var err;
if(x.event == 'callback') {
if(x.err) {
err = x.err;
mydebug('writeBytes returned: ' + JSON.stringify(x));
if(callback) callback({err:err});
}
if(c < string.length) {
mydebug('i2c write: ' + i2cport + ': 0x40 <- ' + data[c].toString(16));
b.i2cWriteBytes(lcd, 0x40, [data[c]], mycallback);
c++;
} else {
callback();
}
}
}
};
exports.groveLCDCommand = function(command, callback) {
var i2cport = lcd[0]+',0x'+lcd[1].toString(16);
mydebug('LCD command: 0x' + command.toString(16));
//if(callback) callback();
mydebug('i2c write: ' + i2cport + ': 0x80 <- 0x' + command.toString(16));
b.i2cWriteBytes(lcd, 0x80, [command], mycallback);
function mycallback(x) {
mydebug('writeBytes returned: ' + JSON.stringify(x));
if(x.event == 'callback') {
if(callback) callback(x);
}
}
};
exports.groveLCDDisplay = function(callback) {
status.displaycontrol |= LCD_DISPLAYON;
exports.groveLCDCommand(LCD_DISPLAYCONTROL | status.displaycontrol, callback);
};
exports.groveLCDNoDisplay = function(callback) {
status.displaycontrol &= ~LCD_DISPLAYON;
exports.groveLCDCommand(LCD_DISPLAYCONTROL | status.displaycontrol, callback);
};
exports.groveLCDClear = function(callback) {
var mycallback = callback ? onWrite : undefined;
// clear display, set cursor position to zero
exports.groveLCDCommand(LCD_CLEARDISPLAY, mycallback);
function onWrite(x) {
if(x.err) {
callback(x);
return;
}
// this command takes a long time!
setTimeout(onWait, 2);
}
function onWait() {
callback({});
}
};
exports.groveLCDSetColorWhite = function(callback) {
exports.groveLCDSetRGB(255, 255, 255, callback);
};
exports.groveLCDSetRGB = function(r, g, b, callback) {
setReg(REG_RED, r, setGreen);
function setGreen() {setReg(REG_GREEN, g, setBlue); }
function setBlue() {setReg(REG_BLUE, b, callback); }
};
function setReg(addr, data, callback) {
var err;
var i2cport = rgb[0]+',0x'+rgb[1].toString(16);
mydebug('i2c write: ' + i2cport + ': ' + addr.toString(16) + ' <- 0x' + data.toString(16));
//if(callback) callback();
b.i2cWriteBytes(rgb, addr, [data], mycallback);
function mycallback(x) {
if(x.err) err = x.err;
mydebug('writeBytes returned: ' + JSON.stringify(x));
if(x.event == 'callback') {
if(callback) callback({err:err});
}
}
}
return(exports);
})();
// Start test code
exports.groveLCDOpen('/dev/i2c-2', 16, 2, 0, onLCDOpen);
function onLCDOpen(x) {
console.log(x);
exports.groveLCDPrint("Hello, world!", onLCDPrint);
}
function onLCDPrint(x) {
console.log(x);
}
var colorIndex = 0;
var colors = [[255,0,0], [0,255,0], [0,0,255]];
function rotateColor() {
var r = colors[colorIndex][0];
var g = colors[colorIndex][1];
var b = colors[colorIndex][2];
exports.groveLCDSetRGB(r, g, b);
colorIndex++;
if(colorIndex >= 3) colorIndex=0;
}
setInterval(rotateColor, 2000);
