Skip to content
Permalink
 
 
Cannot retrieve contributors at this time
'use strict';
const i2c = require('i2c-bus'),
EventEmitter = require('events');
const MPR121_I2CADDR_DEFAULT = 0x5A,
MPR121_TOUCHSTATUS_L = 0x00,
MPR121_TOUCHSTATUS_H = 0x01,
MPR121_FILTDATA_0L = 0x04,
MPR121_FILTDATA_0H = 0x05,
MPR121_BASELINE_0 = 0x1E,
MPR121_MHDR = 0x2B,
MPR121_NHDR = 0x2C,
MPR121_NCLR = 0x2D,
MPR121_FDLR = 0x2E,
MPR121_MHDF = 0x2F,
MPR121_NHDF = 0x30,
MPR121_NCLF = 0x31,
MPR121_FDLF = 0x32,
MPR121_NHDT = 0x33,
MPR121_NCLT = 0x34,
MPR121_FDLT = 0x35,
MPR121_TOUCHTH_0 = 0x41,
MPR121_RELEASETH_0 = 0x42,
MPR121_DEBOUNCE = 0x5B,
MPR121_CONFIG1 = 0x5C,
MPR121_CONFIG2 = 0x5D,
MPR121_CHARGECURR_0 = 0x5F,
MPR121_CHARGETIME_1 = 0x6C,
MPR121_ECR = 0x5E,
MPR121_AUTOCONFIG0 = 0x7B,
MPR121_AUTOCONFIG1 = 0x7C,
MPR121_UPLIMIT = 0x7D,
MPR121_LOWLIMIT = 0x7E,
MPR121_TARGETLIMIT = 0x7F,
MPR121_GPIODIR = 0x76,
MPR121_GPIOEN = 0x77,
MPR121_GPIOSET = 0x78,
MPR121_GPIOCLR = 0x79,
MPR121_GPIOTOGGLE = 0x7A,
MPR121_SOFTRESET = 0x80;
class MPR121 extends EventEmitter {
constructor(address, bus, interval) {
super();
this.address = address || MPR121_I2CADDR_DEFAULT;
this.bus = Number.isInteger(bus) ? bus : 1;
this.interval = interval || 100;
this.state = [false, false, false, false, false, false, false, false, false, false, false, false];
this.device = false;
this.ready = false;
this.timer = false;
this.init()
.then(this.reset.bind(this))
.then(this.configure.bind(this))
.then(this.startPolling.bind(this))
.catch((err) => this.emit('error', err));
}
init() {
return new Promise((resolve, reject) => {
this.device = i2c.open(this.bus, (err) => {
if(err) return reject(err);
resolve();
});
});
}
reset() {
return this.writeByte(MPR121_SOFTRESET, 0x63)
.then(() => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 100);
});
})
.then(() => this.writeByte(MPR121_ECR, 0x00));
}
configure() {
return this.setThresholds(12, 6)
.then(() => this.writeByte(MPR121_MHDR, 0x01))
.then(() => this.writeByte(MPR121_NHDR, 0x01))
.then(() => this.writeByte(MPR121_NCLR, 0x0E))
.then(() => this.writeByte(MPR121_FDLR, 0x00))
.then(() => this.writeByte(MPR121_MHDF, 0x01))
.then(() => this.writeByte(MPR121_NHDF, 0x05))
.then(() => this.writeByte(MPR121_NCLF, 0x01))
.then(() => this.writeByte(MPR121_FDLF, 0x00))
.then(() => this.writeByte(MPR121_NHDT, 0x00))
.then(() => this.writeByte(MPR121_NCLT, 0x00))
.then(() => this.writeByte(MPR121_FDLT, 0x00))
.then(() => this.writeByte(MPR121_DEBOUNCE, 0))
.then(() => this.writeByte(MPR121_CONFIG1, 0x10)) // default, 16uA charge current
.then(() => this.writeByte(MPR121_CONFIG2, 0x20)) // 0.5uS encoding, 1ms period
.then(() => this.writeByte(MPR121_ECR, 0x8F)) // start with first 5 bits of baseline tracking
.then(() => {
this.ready = true;
this.emit('ready');
});
}
setThresholds(touch, release) {
if(touch < 0 || touch > 255) return Promise.reject();
if(release < 0 || release > 255) return Promise.reject();
let promises = [];
for(let i = 0; i <= 12; i++) {
promises.push(this.writeByte(MPR121_TOUCHTH_0 + 2 * i, touch));
promises.push(this.writeByte(MPR121_RELEASETH_0 + 2 * i, release));
}
return Promise.all(promises);
}
startPolling() {
if(! this.ready) return this.on('ready', this.startPolling);
if(! this.interval) return;
this.timer = setInterval(() => {
this.touched().then(this.updateState.bind(this));
}, this.interval);
}
stopPolling() {
if(! this.timer) return;
clearInterval(this.timer);
this.timer = false;
}
updateState(touched) {
this.state.forEach((previous, i) => {
const current = (touched & (1 << i)) > 0;
if(previous === current) return;
this.state[i] = current;
// emit pin number for touch and release
if(current)
this.emit('touch', i);
else
this.emit('release', i);
// emit state on pin number
this.emit(i, current);
});
}
filteredData(pin) {
if(pin < 0 || pin >= 12) return Promise.reject();
return this.readWord(MPR121_FILTDATA_0L + (pin * 2));
}
baselineData(pin) {
if(pin < 0 || pin >= 12) return Promise.reject();
return this.readByte(MPR121_BASELINE_0 + pin)
.then((bl) => {
return Promise.resolve(bl << 2);
});
}
touched() {
return this.readWord(MPR121_TOUCHSTATUS_L).then((t) => Promise.resolve(t & 0x0FFF));
}
isTouched(pin) {
if(! this.ready) return false;
if(pin < 0 || pin >= 12) return false;
return this.state[pin];
}
readByte(reg) {
return new Promise((resolve, reject) => {
this.device.readByte(this.address, reg, (err, b) => {
if(err) return reject(err);
resolve(b);
});
});
}
readWord(reg) {
return new Promise((resolve, reject) => {
this.device.readWord(this.address, reg, (err, w) => {
if(err) return reject(err);
resolve(w);
});
});
}
writeByte(reg, value) {
return new Promise((resolve, reject) => {
this.device.writeByte(this.address, reg, value & 0xFF, (err) => {
if(err) return reject(err);
resolve();
});
});
}
}
exports = module.exports = MPR121;