From e85378168e33ddc851beac6b7a503593da027143 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sat, 20 May 2017 22:21:07 -0700 Subject: [PATCH] total refactoring using pigpio library instead of epoll --- lib/interrupt.js | 174 +++++++++++++---------------------------------- package.json | 7 +- 2 files changed, 50 insertions(+), 131 deletions(-) diff --git a/lib/interrupt.js b/lib/interrupt.js index 7197b6f..ab3a60f 100644 --- a/lib/interrupt.js +++ b/lib/interrupt.js @@ -1,150 +1,74 @@ "use strict"; -const fs = require('mz/fs'), - exec = require('mz/child_process').exec, - EventEmitter = require('events'), - Epoll = require('epoll').Epoll, - _ = require('uci-utils') - -const pWaitFor = require('p-wait-for') -const pathExists = require('path-exists'); -const debounce = require('debounce'); - -const GPIO_ROOT_PATH = '/sys/class/gpio/' +const + pigpio = require('pigpio'), + Gpio = pigpio.Gpio, + EventEmitter = require('events') + //,_ = require('uci-utils') + //const debounce = require('debounce'); class Interrupt extends EventEmitter { - // bus is i2c-bus bus object - constructor(pin_number, opts = {}) { + constructor(pin_number, handler, opts = {}) { super() - this.num = pin_number; - this.hook = opts.hook // will be passed back with the emit - this.path = GPIO_ROOT_PATH + 'gpio' + this.num + '/' - this.edge = opts.edge // default 'both' - this.delay = opts.delay // default = 50 - this.pull = opts.pull // default = pu - this.puller = opts.puller ? opts.puller : (num, state) => { return `raspi-gpio set ${num} ${state}` } // default rpi using raspi-gpio - // this.puller = (num, state) => { return `raspi-gpio set ${num} ${state}` } - this.dbt = opts.debounce ? opts.debounce : 200 - this.poller = new Epoll( - debounce((err, fd, events) => { - if (err) { this.emit('error', err) } else { - // this.clear().then(this.emit('fired', this.hook)) - this.emit('fired', this.hook) - } - }, this.dbt, true) // true = leading + this.pin_number = pin_number + this.handler = handler + this.mode = Gpio.INPUT + this.pull = opts.pull ? opts.pull : Gpio.PUD_DOWN + this.edge = opts.edge ? opts.edge : Gpio.RISING_EDGE + this.sbc_interrupt = new Gpio( + this.pin_number, { + mode: this.mode, + pullUpDown: this.pull, + // edge: this.edge // don't set edge here as it will start the emitter -- see pigio js + } ) } init() { + // console.log(`initialize interrupt ${this.pin_number}`) + return Promise.resolve() + + } + + get pin() { + return this.pin_number + } + + async start() { + + console.log(`starting interrupt on pin ${ this.pin_number}`) + + // for cntrl-c exit of interrupt process.on('SIGINT', () => { - this.exit().then((resp) => console.log("\n", resp)) // unexport on cntrl-c - .catch(err => console.log("error:", err)) + this.exit().then((resp) => console.log("\n", resp)) // unexport on cntrl-c + .catch(err => console.log("error:", err)) + }) + // There are two interrupts here. One on the I2c mcp board and one on the sbc/rpi + // The mcp interrupt trips the sbc interrupt which emits an event to run handler attached to the mcp class interrupt + let interrupt = this // scope `this` for use in the listener for each interrupt + console.log(`interrupt listener set for rpi ${interrupt.pin_number}`) + this.sbc_interrupt.on('interrupt', function () { + console.log(`rpi interrupt tripped by rpi pin ${interrupt.pin_number}`) + interrupt.emit('fired') }) - return _.pSeries([ - this.exit(), - this._pull(this.num, this.pull), - this._export(this.num), - this._direction('in', this.delay), - () => this._edge(this.edge), // TODO determine why these need additional function - () => this._fd() - ]) + // rock n roll!!, turn on the pigpio interrupt + this.sbc_interrupt.enableInterrupt(this.edge) + // return Promise.resolve("interrupt on pin listener") } // manual firing for testing fire(name = 'fired') { - this.emit(name, this.hook) - } - - clear() { - let buffer = Buffer.from([0x00]) - return fs.read(this.valuefd, buffer, 0, 1, 0).then(() => { return Promise.resolve('interrupt cleared') }) + console.log('firing interrupt handler', this.handler) + this.emit(name, this.handler) } exit() { - return new Promise((resolve, reject) => { - pathExists(this.path) - .then((exists) => { - if (exists) { - fs.writeFile(GPIO_ROOT_PATH + 'unexport', this.num) - .then(() => { - if (this.valuefd) { - this.stop() - fs.close(this.valuefd) - } - this._pull(this.num, 'pn') - }) - .then(resolve('unexported and exited')) - } else { - resolve('already unexported') - } - }) - .catch(err => resolve(err)) - }) + pigpio.terminate() + return Promise.reject(`keyboard termination...terminating interrupt on pin ${this.pin_number}`) } - - start() { - // this.inter(port).on('fired', () => { - // console.log(`interrupt port ${port} hook me \n ${relays}`) - // // hook.bind(this)(port) - // - // }) - return this.clear().then(() => this.poller.add(this.valuefd, Epoll.EPOLLPRI | Epoll.EPOLLONESHOT)); - } - - reset() { - return this.clear().then(() => this.poller.modify(this.valuefd, Epoll.EPOLLPRI | Epoll.EPOLLONESHOT)); - } - - stop() { - this.poller.remove(this.valuefd).close(); - } - - /*******private methods*********/ - - _pull(num, state = 'pu') { - if (this.puller === 'external') { return Promise.resolve('pull must be set externally') } else { - return exec(this.puller(num, state)) - .then(() => { return Promise.resolve(`pull set ${state}`) }) - } - } - - _fd() { - return fs.open(this.path + 'value', 'r+') - .then(fd => { - this.valuefd = fd - return Promise.resolve(`value fd set ${fd}`) - }) - } - - _export(num) { - return new Promise(function (resolve, reject) { - fs.writeFile(GPIO_ROOT_PATH + 'export', num) - .then(() => { return resolve('exported') }) - .catch((err) => { return reject(err) }) - }) - } - - _direction(dir = 'in', delay = 50) { - return pWaitFor(() => pathExists(this.path + 'direction')) - .then(_.pDelay(delay)) - .then(() => { - return fs.writeFile(dir + 'direction', dir) - .then(() => { - return Promise.resolve(`direction set ${dir}`) - }) - }) - } - - _edge(edge = 'both') { - return fs.writeFile(this.path + 'edge', edge) - .then(() => { - return Promise.resolve(`edge set ${edge}`) - }) - } - } module.exports = { diff --git a/package.json b/package.json index 50b9e3d..f543b1b 100644 --- a/package.json +++ b/package.json @@ -30,13 +30,8 @@ }, "homepage": "https://github.com/uCOMmandIt/uci-interrrupt#readme", "dependencies": { - "debounce": "^1.0.0", - "epoll": "^0.1.20", - "mz": "^2.6.0", - "p-wait-for": "^1.0.0", - "path-exists": "^3.0.0", "require-all": "git+https://github.com/dkebler/node-require-all.git#merge", - "uci-utils": "0.0.1" + "pigpio": "^0.x" }, "devDependencies": { "chai": "^3.5.0",