SWBtn hardened and commented in preparation for publishing as a module.
This is a Request For Comments (RFC). Feedback for code fixes and comment/wording and functional enhancements are very much appreciated.
/* Copyright (c) 2014 allObjects. See the file LICENSE for copying permission. */
/*
Software Buttons - Many buttons from just one hardware button
SWBtn class - instances of SWBtn makes many buttons out of
just one hardware button by detecting sequences of short and
long presses and passing them on to a user defined, dispatching
callback function.
For example, one long press turns LED1 on, and one long and
one short turn it off. Two long presses and two long presses
followd by a short one do the same to LED2, etc.
Each detected sequence is passed in form of a string of "S"s
and "L"s to the user provided callback function. The callback
function uses the string as a key to call assigned functions
like dispatcher.
Usage example:
require("SWBtn");
var mySWBtn = new SWBtn(function(k){
console.log("BTN1 detected " + k); // log and/or dispatch
});
*/
/**
SWBtn - SoftWare Butten 'class'
- constructor - accepts these arguments:
- fnc - (optional) anonymous, one argument accepting dispatching callback function
- btn - (optional) button/pin id - default is BTN1
- d - (optional) boolean interpreted disable flag - default false
Allows button to be creted in disabled state in order
for (other) initializations to complete before being
enabled with .disable(0) / .disable(false) / .disable()
method invocation.
- instance properties:
- f - storex passed or set dispatching callback function
- b - storex button / pin id
- d - stores disabled (status) of button
- t - xgofdx timeout for sequence end / pause detection
- k - stores build-up key store holding on to the "S"s and "L"s of a squence
- w - stores hold on to the watch set with setWatch()
*/
function SWBtn(fnc,btn,d) {
this.f = (fnc) ? fnc : function(){};
this.b = (btn) ? btn : BTN1;
this.t = null;
this.k = null;
this.w = null;
this.disable(d);
}
/**
.C - Constants / Configuration - defining the timings
- shared by all instances of SWBtn:
- B - integer - debounce [ms]
- L - float - min Long press [s]
- P - integer - min Pause [ms]
- D - integer - delay of fnc function invocation [ms]
Pressing a button / keeping a pin low for .C.L seconds or more is detected
as a long press when unpressed / released / pin turns high and and adds an
"L" to .k key (press sequnce) - otherwise a short press is detected and an
"S" is adde - and the .t timeout is set with .C.P Pause time and .e() ended
call back for press sequence end detection and processing (invocation of
user defined - ,k key decoding dispatch - function).
*/
SWBtn.prototype.C =
{ B: 20
, L: 0.250
, P: 220
, D: 10
};
/**
.disable(b) - disables/enables button
- method - accepts one argument
- b - boolean - (optional) boolean interpreted disable flag - default false
Used to (temporarily) disable the button (also used in constructor).
It clears/sets the hardware / pin watch using clearWatch() / setWatch() functions.
NOTE1: When button is disabled while press sequence is going on, sequence end is
not detected, but partial sequence is still stored in .k key property (but does
not include an ongoing press / pin low).
NOTE2: The .k key propery is cleared (set to "") when button is (re-)enabled.
NOTE3: any passed parameter that evaluates to false in an 'if (parameter)' and
omission of parameter enable the button: .disable(false), .disable(0),
.disable(""), .disable(''), .disable(null), .disable(undefined), and .disable(),
all these invocations enable the button... ;)
*/
SWBtn.prototype.disable = function(b) {
if (b) {
if (this.w) {
this.d = true;
clearWatch(this.w);
this.w = null;
if (this.t) {
clearTimeout(this.t);
this.t = null;
}
}
} else {
if (!this.w) {
this.d = false;
this.k = "";
var _this = this;
this.w = setWatch(function(e){ _this.c(e); }, this.b
, { repeat:true, edge:"both", debounce:_this.C.B });
}
}
};
/**
.c(e) - button/pin button/pin state change callback - invoked by Espruino
- method - accepts one e event argument (object)
Espruino reference for .setWatch() defines e event object as:
- time - float - time of this state change [s]
- lastTime - float - time of last such state change [s]
- state - boolean - current state of the button / pin
Notes button/pin status and - on unpress/release state -
appends "L"(ong) or "S"(short) to .k key (sequence) and
sets .t timeout to .C.P Pause for sequence end detection
*/
SWBtn.prototype.c = function(e){ // change of state - called by set watch
if (e.state) {
if (this.t) {
clearTimeout(this.t);
this.t = null;
}
} else {
this.k = this.k + ((e.time - e.lastTime < this.C.L) ? "S" :"L");
var _this = this;
this.t = setTimeout(function(){ _this.e(); }, this.C.P);
}
};
/**
.e() - sequence ended timeout callback - invoked by .t timout set in .c(e)
= method = accepts no arguments
Marks detected end of press sequence and invekes user provided .f
callback function in a setTimeout() with .C.D delay.
*/
SWBtn.prototype.e = function() {
this.t = null;
var _k = this.k;
if (_k.length > 0) {
this.k = "";
var _this = this;
setTimeout(function(){ _this.f(_k); },this.C.D);
}
};
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
SWBtn hardened and commented in preparation for publishing as a module.
This is a Request For Comments (RFC). Feedback for code fixes and comment/wording and functional enhancements are very much appreciated.