UNPKG

johnny-five

Version:

The JavaScript Arduino Programming Framework.

158 lines (127 loc) 3.37 kB
var Board = require("../lib/board.js"), __ = require("../lib/fn.js"), events = require("events"), util = require("util"); // Button instance private data var priv = new Map(), aliases = { down: ["down", "press", "tap", "impact", "hit"], up: ["up", "release"] }, // Create a 5 ms debounce boundary on event triggers // this avoids button events firing on // press noise and false positives trigger = __.debounce(function(key) { aliases[key].forEach(function(type) { this.emit(type, null); }, this); }, 7); /** * Button * @constructor * * five.Button(); * * five.Button({ * pin: 10 * }); * * * @param {Object} opts [description] * */ function Button(opts) { if (!(this instanceof Button)) { return new Button(opts); } var timeout; // Initialize a Device instance on a Board Board.Device.call( this, opts = Board.Options(opts) ); // Set the pin to INPUT mode this.mode = this.io.MODES.INPUT; // Option to enable the built-in pullup resistor this.isPullup = opts.isPullup || false; this.io.pinMode(this.pin, this.mode); // Enable the pullup resistor after setting pin mode if (this.isPullup) { this.io.digitalWrite(this.pin, this.io.HIGH); } // Turns out some button circuits will send // 0 for up and 1 for down, and some the inverse, // so we can invert our function with this option. // Default to invert in pullup mode, but use opts.invert // if explicitly defined (even if false) this.invert = typeof opts.invert !== "undefined" ? opts.invert : (this.isPullup || false); this.downValue = this.invert ? 0 : 1; this.upValue = this.invert ? 1 : 0; // Button instance properties this.holdtime = opts && opts.holdtime || 500; // Create a "state" entry for privately // storing the state of the button priv.set(this, { isDown: false }); // Analog Read event loop this.io.digitalRead(this.pin, function(data) { var err = null; // data = upValue, this.isDown = true // indicates that the button has been released // after previously being pressed if (data === this.upValue && this.isDown) { if (timeout) { clearTimeout(timeout); } priv.get(this).isDown = false; trigger.call(this, "up"); } // data = downValue, this.isDown = false // indicates that the button has been pressed // after previously being released if (data === this.downValue && !this.isDown) { // Update private data priv.get(this).isDown = true; // Call debounced event trigger for given "key" // This will trigger all event aliases assigned // to "key" trigger.call(this, "down" /* key */ ); timeout = setTimeout(function() { if (this.isDown) { this.emit("hold", err); } }.bind(this), this.holdtime); } }.bind(this)); Object.defineProperties(this, { isDown: { get: function() { return priv.get(this).isDown; } } }); } util.inherits(Button, events.EventEmitter); /** * Fired when the button is pressed down * * @event * @name down * @memberOf Button */ /** * Fired when the button is held * * @event * @name hold * @memberOf Button */ /** * Fired when the button is released * * @event * @name up * @memberOf Button */ module.exports = Button;