|
| 1 | +/* Copyright (c) 2018 Andrew Nicolaou. See the file LICENSE for copying permission. */ |
| 2 | +/* |
| 3 | + Module for Adafruit CAP1188 8-Key Capacitive Touch Sensor Breakout |
| 4 | + Only I2C is supported. |
| 5 | +
|
| 6 | + See: https://www.adafruit.com/products/1602 |
| 7 | + A port of the same library for Espruino: |
| 8 | + http://www.espruino.com/CAP1188 |
| 9 | +*/ |
| 10 | +var C = { |
| 11 | + ADDRESS_DEFAULT: 0x29 |
| 12 | +}; |
| 13 | + |
| 14 | +/* Register addresses*/ |
| 15 | +var R = { |
| 16 | + MAIN_CONTROL: 0x00, |
| 17 | + SENSOR_INPUT_STATUS: 0x03, |
| 18 | + MULTI_TOUCH_CONFIG: 0x2a, |
| 19 | + STANDBY_CONFIG: 0x41, |
| 20 | + SENSOR_INPUT_LINKING: 0x72, |
| 21 | + LED_OUTPUT_CONTROL: 0x74 |
| 22 | +}; |
| 23 | + |
| 24 | +/* Bits within register for functions */ |
| 25 | +var B = { |
| 26 | + MAIN_CONTROL_INT: 0x0 |
| 27 | +}; |
| 28 | + |
| 29 | +function CAP1188(_i2c, _opts) { |
| 30 | + _opts = _opts == null ? {} : _opts; |
| 31 | + this.i2c = _i2c; |
| 32 | + |
| 33 | + // Support old API where second param was _addr |
| 34 | + if (typeof _opts === 'number') { |
| 35 | + this.addr = _opts; |
| 36 | + } else { |
| 37 | + this.addr = _opts.address || C.ADDRESS_DEFAULT; |
| 38 | + this.resetPin = _opts.resetPin || null; |
| 39 | + } |
| 40 | + |
| 41 | + this.initialize(); |
| 42 | +} |
| 43 | + |
| 44 | +/* Initialize the chip */ |
| 45 | +CAP1188.prototype.initialize = function() { |
| 46 | + this.linkLedsToSensors(); |
| 47 | + this.multipleTouches(true); |
| 48 | + // "Speed up a bit" |
| 49 | + // this.i2c.writeTo(this.addr, [R.STANDBY_CONFIG, 0x30]); |
| 50 | + this.i2c.writeSync(this.addr, R.STANDBY_CONFIG, Buffer.from([0x30])); |
| 51 | +}; |
| 52 | + |
| 53 | +/* Reset the chip if a reset pin has been specified */ |
| 54 | +CAP1188.prototype.reset = function(callback) { |
| 55 | + throw new Error('Reset not currently supported'); |
| 56 | + |
| 57 | + var delay = 100, |
| 58 | + pin = this.resetPin, |
| 59 | + self = this; |
| 60 | + |
| 61 | + if (pin == null) { |
| 62 | + throw new Error('CAP1188 reset called but no resetPin given'); |
| 63 | + } |
| 64 | + |
| 65 | + pin.write(0); |
| 66 | + setTimeout(function() { |
| 67 | + pin.write(1); |
| 68 | + setTimeout(function() { |
| 69 | + pin.write(0); |
| 70 | + setTimeout(function() { |
| 71 | + self.initialize(); |
| 72 | + if (callback) { |
| 73 | + callback(); |
| 74 | + } |
| 75 | + }, delay); |
| 76 | + }, delay); |
| 77 | + }, delay); |
| 78 | +}; |
| 79 | + |
| 80 | +/* How many simultaneous touches to allow */ |
| 81 | +CAP1188.prototype.multipleTouches = function(enable) { |
| 82 | + // 1 will block multiple touches |
| 83 | + this.writeBit(R.MULTI_TOUCH_CONFIG, 7, enable ? 0 : 1); |
| 84 | +}; |
| 85 | + |
| 86 | +/* Link the LED to corresponding sensor */ |
| 87 | +CAP1188.prototype.linkLedsToSensors = function() { |
| 88 | + for (var i = 0; i < 8; i++) { |
| 89 | + this.linkLedToSensor(i, 1); |
| 90 | + } |
| 91 | +}; |
| 92 | + |
| 93 | +/* Link LED pin to sensor */ |
| 94 | +CAP1188.prototype.linkLedToSensor = function(num, enable) { |
| 95 | + this.writeBit(R.SENSOR_INPUT_LINKING, num, enable); |
| 96 | +}; |
| 97 | + |
| 98 | +/* Read state of all sensors */ |
| 99 | +CAP1188.prototype.readTouches = function() { |
| 100 | + var touches = [], |
| 101 | + raw; |
| 102 | + |
| 103 | + // this.i2c.writeTo(this.addr, R.SENSOR_INPUT_STATUS); |
| 104 | + this.i2c.writeSync(this.addr, Buffer.from([R.SENSOR_INPUT_STATUS])); |
| 105 | + |
| 106 | + // raw = this.i2c.readFrom(this.addr, 1)[0]; |
| 107 | + raw = this.i2c.readSync(this.addr, 1)[0]; |
| 108 | + |
| 109 | + if (raw) { |
| 110 | + // Clear interrupt to be able to read again |
| 111 | + this.writeBit(R.MAIN_CONTROL, B.MAIN_CONTROL_INT, 0); |
| 112 | + } |
| 113 | + |
| 114 | + for (var i = 0; i < 8; i++) { |
| 115 | + touches[i] = this.getBit(raw, i); |
| 116 | + } |
| 117 | + |
| 118 | + return touches; |
| 119 | +}; |
| 120 | + |
| 121 | +/* */ |
| 122 | +CAP1188.prototype.getBit = function(byt, position) { |
| 123 | + return 1 == ((byt >> position) & 1); |
| 124 | +}; |
| 125 | + |
| 126 | +/* Set a single bit in a register */ |
| 127 | +CAP1188.prototype.writeBit = function(reg, bit, val) { |
| 128 | + // this.i2c.writeTo(this.addr, reg); |
| 129 | + this.i2c.writeSync(this.addr, Buffer.from([reg])); |
| 130 | + |
| 131 | + // var b = this.i2c.readFrom(this.addr, 1)[0]; |
| 132 | + var b = this.i2c.readSync(this.addr, 1)[0]; |
| 133 | + |
| 134 | + b = val !== 0 ? b | (1 << bit) : b & ~(1 << bit); |
| 135 | + |
| 136 | + // this.i2c.writeTo(this.addr, [reg, b]); |
| 137 | + this.i2c.writeSync(this.addr, reg, Buffer.from([b])); |
| 138 | +}; |
| 139 | + |
| 140 | +/* Set more bits in a register */ |
| 141 | +CAP1188.prototype.writeBits = function(reg, shift, val) { |
| 142 | + // this.i2c.writeTo(this.addr, reg); |
| 143 | + this.i2c.writeSync(this.addr, Buffer.from([reg])); |
| 144 | + // var b = this.i2c.readFrom(this.addr, 1)[0]; |
| 145 | + var b = this.i2c.readSync(this.addr, 1)[0]; |
| 146 | + |
| 147 | + b = b | (val << shift); |
| 148 | + // this.i2c.writeTo(this.addr, [reg, b]); |
| 149 | + this.i2c.writeSync(this.addr, reg, Buffer.from([b])); |
| 150 | +}; |
| 151 | + |
| 152 | +exports.connect = function(_i2c, _addr) { |
| 153 | + return new CAP1188(_i2c, _addr); |
| 154 | +}; |
0 commit comments