node-blinkt
Version:
A Node.js Library to Interact With the Raspberry Pi Blinkt! LED Hat.
193 lines (167 loc) • 5.28 kB
JavaScript
const wpi = require("node-wiring-pi"),
DAT = 23,
CLK = 24;
class Blinkt {
brightnessMask = 0x1F; // 0b11111
significantBitsMask = 0xE0; //0b11100000
/**
* Connects to the GPIO and sets the GPIO pin modes. Must be called
* before any other commands. All pixels will start off white at
* full brightness by default.
* @param {Number} dat The data pin number.
* @param {Number} clk The clock pin number.
* @returns {undefined} Nothing.
*/
setup = (dat, clk) => {
// Set WPI to GPIO mode
wpi.setup("gpio");
if(Boolean(dat) && isNaN(dat)){
//if dat has value and is not a number
throw new Error("The dat value must be a pin number");
}
if(Boolean(clk) && isNaN(clk)){
//if clk has value and is not a number
throw new Error("The clk value must be a pin number");
}
this._dat = dat || DAT;
this._clk = clk || CLK;
// Set pin mode to output
wpi.pinMode(this._dat, wpi.OUTPUT);
wpi.pinMode(this._clk, wpi.OUTPUT);
this._numPixels = 8;
this._pixels = [];
// Init pixels
for (let i = 0; i < this._numPixels; i++) {
this.setPixel(i, 255, 255, 255, 1.0);
}
};
/**
* Sets all pixels to the passed RGB and brightness values.
* @param {Number} r The pixel red value between 0 and 255.
* @param {Number} g The pixel green value between 0 and 255.
* @param {Number} b The pixel blue value between 0 and 255.
* @param {Number} a The pixel brightness value between 0.0 and 1.0.
* @returns {undefined} Nothing.
*/
setAllPixels = (r, g, b, a) => {
for (let i = 0; i < this._numPixels; i++) {
this.setPixel(i, r, g, b, a);
}
};
/**
* Sets the specified pixel to the passed rgb and brightness level.
* The pixelNum is an integer between 0 and 7 to indicate the pixel
* to change.
* @param {Number} pixelNum The pixel to set RGB and brightness for.
* An integer value between 0 and 7. Zero is the first pixel, 7 is
* the last one.
* @param {Number} r The pixel red value between 0 and 255.
* @param {Number} g The pixel green value between 0 and 255.
* @param {Number} b The pixel blue value between 0 and 255.
* @param {Number=} a The pixel brightness value between 0.0 and 1.0.
* @returns {undefined} Nothing.
*/
setPixel = (pixelNum, r, g, b, a) => {
if (a === undefined) {
if (this._pixels[pixelNum]) {
// Set a to current level or 1.0 if none exists
a = this._pixels[pixelNum][3] !== undefined ? this._pixels[pixelNum][3] : 1.0;
}
} else {
a = Math.floor(31.0 * a) & this.brightnessMask; // jshint ignore:line
}
this._pixels[pixelNum] = [
Math.floor(r) & 255, // jshint ignore:line
Math.floor(g) & 255, // jshint ignore:line
Math.floor(b) & 255, // jshint ignore:line
a
];
};
/**
* Sets the brightness of the pixel specified by pixelNum.
* @param {Number} pixelNum The pixel to set RGB and brightness for.
* An integer value between 0 and 7. Zero is the first pixel, 7 is
* the last one.
* @param {Number} brightness The pixel brightness value between 0.0
* and 1.0.
* @returns {undefined} Nothing.
*/
setBrightness = (pixelNum, brightness) => {
this._pixels[pixelNum][3] = Math.floor(31.0 * brightness) & this.brightnessMask; // jshint ignore:line
};
/**
* Clears the pixel buffer.
* This is the same as setting all pixels to black.
* You must also call sendUpdate() if you want to turn Blinkt! off.
* @returns {undefined} Nothing.
*/
clearAll = () => {
for (let i = 0; i < this._numPixels; i++) {
this.clear(i);
}
};
/**
* Clears the pixel .
* This is the same as setting this pixels to black.
* You must also call sendUpdate() if you want to turn Blinkt! off.
* @param {Number} led index to clear.
* @returns {undefined} Nothing.
*/
clear = (led) => {
this.setPixel(led, 0, 0, 0);
};
/**
* Sends the current pixel settings to the Blinkt! device. Once you
* have set each pixel RGB and brightness, you MUST call this for the
* pixels to change on the Blinkt! device.
* @returns {undefined} Nothing.
*/
sendUpdate = () => {
let i,
pixel;
for (i = 0; i < 4; i++) {
this._writeByte(0);
}
for (i = 0; i < this._numPixels; i++) {
pixel = this._pixels[i];
// Brightness
this._writeByte(this.significantBitsMask | pixel[3]); // jshint ignore:line
// Blue
this._writeByte(pixel[2]);
// Green
this._writeByte(pixel[1]);
// Red
this._writeByte(pixel[0]);
}
this._writeByte(0xff);
this._latch();
};
/**
* Writes byte data to the GPIO pins.
* @param {Number} byte The byte value to write.
* @returns {undefined} Nothing.
* @private
*/
_writeByte = (byte) => {
let bit;
for (let i = 0 ; i < this._numPixels; i++) {
bit = ((byte & (1 << (7 - i))) > 0) ? wpi.HIGH : wpi.LOW; // jshint ignore:line
wpi.digitalWrite(this._dat, bit);
wpi.digitalWrite(this._clk, 1);
wpi.digitalWrite(this._clk, 0);
}
};
/**
* Emit exactly enough clock pulses to latch the small dark die APA102s which are weird.
* @returns {undefined} Nothing.
* @private
*/
_latch = () => {
wpi.digitalWrite(this._dat, 0);
for (let i = 0 ; i < 36; i++) {
wpi.digitalWrite(this._clk, 1);
wpi.digitalWrite(this._clk, 0);
}
};
}
module.exports = Blinkt;