Last active
August 29, 2015 14:26
-
-
Save TooTallNate/8111001d7abe21220ccc to your computer and use it in GitHub Desktop.
Touchscreen class for the PiTFT screen for Raspberry Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require('fs'); | |
var Struct = require('ref-struct'); | |
var inherits = require('util').inherits; | |
var EventEmitter = require('events').EventEmitter; | |
// https://www.kernel.org/doc/Documentation/input/event-codes.txt | |
// https://www.kernel.org/doc/Documentation/input/input.txt | |
// /usr/include/linux/input.h | |
/* | |
* Event types | |
*/ | |
var EV_SYN = 0x00; | |
var EV_KEY = 0x01; | |
var EV_ABS = 0x03; | |
/* | |
* Absolute axes | |
*/ | |
var ABS_X = 0x00; | |
var ABS_Y = 0x01; | |
var ABS_PRESSURE = 0x18; | |
/* | |
* Keys and buttons | |
*/ | |
var BTN_TOUCH = 0x14a; | |
// struct input_event { | |
// struct timeval time; | |
// unsigned short type; | |
// unsigned short code; | |
// unsigned int value; | |
// }; | |
var time_t = 'long'; | |
var suseconds_t = 'long'; | |
var timeval = Struct({ | |
tv_sec: time_t, | |
tv_usec: suseconds_t | |
}) | |
var input_event = Struct({ | |
time: timeval, | |
type: 'ushort', | |
code: 'ushort', | |
value: 'uint' | |
}); | |
// Expose as a nice JavaScript API | |
function Touchscreen (filename) { | |
this.onOpen = this.onOpen.bind(this); | |
this.onRead = this.onRead.bind(this); | |
this.input = new input_event; | |
this.buffer = this.input.ref(); | |
this.filename = filename || '/dev/input/touchscreen'; | |
this.touch = { | |
identifier: 1, | |
timeStamp: 0, | |
type: 'touchstart', | |
screenX: 0, | |
screenY: 0, | |
force: 0, | |
}; | |
fs.open(this.filename, 'r', this.onOpen); | |
} | |
inherits(Touchscreen, EventEmitter); | |
Touchscreen.prototype.onOpen = function (err, fd) { | |
if (err) return this.emit('error', err); | |
this.fd = fd; | |
this.emit('open'); | |
this.startRead(); | |
}; | |
Touchscreen.prototype.startRead = function () { | |
fs.read(this.fd, this.buffer, 0, input_event.size, null, this.onRead); | |
}; | |
Touchscreen.prototype.onRead = function (err, bytesRead) { | |
if (err) return this.emit('error', err); | |
if (bytesRead !== input_event.size) { | |
return this.emit('error', new Error('only read ' + | |
bytesRead + ' bytes, expected ' + input_event.size)); | |
} | |
switch (this.input.type) { | |
case EV_SYN: | |
this.touch.timeStamp = (this.input.time.tv_sec * 1000) + ((this.input.time.tv_usec / 1000) | 0); | |
this.emit(this.touch.type, this.touch); | |
if (this.touch.type === 'touchstart') { | |
this.touch.type = 'touchmove'; | |
} | |
break; | |
case EV_KEY: | |
switch (this.input.code) { | |
case BTN_TOUCH: | |
if (this.input.value) { | |
// finger down | |
this.touch.type = 'touchstart'; | |
} else { | |
// finger up | |
this.touch.type = 'touchend'; | |
} | |
break; | |
default: | |
return this.emit('error', new Error('bad EV_KEY code! ' + this.input.code)); | |
} | |
break; | |
case EV_ABS: | |
switch (this.input.code) { | |
// X and Y axes are rotated 90 degrees on PiTFT, so | |
// ABS_X is really the Y-axis and ABS_Y is the X-axis | |
// (when the PiTFT is rotated horizontally) | |
case ABS_X: | |
this.touch.screenY = (this.input.value / 4095) * 240; | |
break; | |
case ABS_Y: | |
// X axis origin is to the right for some reason, so we have to | |
// swap the value to begin on the left side by taking 320 - value | |
this.touch.screenX = 320 - ((this.input.value / 4095) * 320); | |
break; | |
case ABS_PRESSURE: | |
this.touch.force = this.input.value / 255; | |
break; | |
default: | |
return this.emit('error', new Error('bad EV_ABS code! ' + this.input.code)); | |
} | |
break; | |
default: | |
console.error(this.input); | |
break; | |
} | |
if (this.fd) this.startRead(); | |
}; | |
Touchscreen.prototype.close = function (callback) { | |
fs.close(this.fd, callback); | |
this.fd = undefined; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sample usage | |
var ts = new Touchscreen(); | |
ts.once('open', function () { | |
console.log('Touch me!'); | |
}); | |
ts.on('touchstart', console.log.bind(console, 'touchstart')); | |
ts.on('touchmove', console.log.bind(console, 'touchmove')); | |
ts.on('touchend', console.log.bind(console, 'touchend')); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment