From 35605352bf6a6cc91d82741b5e5bf0810951808b Mon Sep 17 00:00:00 2001 From: David Kebler Date: Wed, 18 Oct 2017 17:34:34 -0700 Subject: [PATCH] fix bad comment --- package.json | 2 +- src/mcp23008-17.js | 476 ++++++++++++++++++++++----------------------- 2 files changed, 239 insertions(+), 239 deletions(-) diff --git a/package.json b/package.json index 09575e9..cca0d65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@uci/mcp", "main": "src/mcp23008-17.js", - "version": "0.1.1", + "version": "0.1.2", "description": "Classes and Helper Functions for using the MCP chip on I2C Bus", "scripts": { "test": "./node_modules/.bin/mocha --reporter list --timeout 30000", diff --git a/src/mcp23008-17.js b/src/mcp23008-17.js index 8ee9ba7..a4db9fc 100644 --- a/src/mcp23008-17.js +++ b/src/mcp23008-17.js @@ -1,267 +1,267 @@ 'use strict' const Device = require('@uci/i2c').Device, - portpin = require('./port-pin'), // classes for MCP port and pins - EventEmitter = require('events'), - _ = require('@uci/utils'), - aggregate = require("aggregation/es6") + portpin = require('./port-pin'), // classes for MCP port and pins + EventEmitter = require('events'), + _ = require('@uci/utils'), + aggregate = require('aggregation/es6') const - Port = portpin.Port, - pinConfigs = portpin.configs, // for export so pinConfigs can be accessed at runtime - pause = _.pPause, - debug = _.debug('mcp:23008-17') + Port = portpin.Port, + pinConfigs = portpin.configs, // for export so pinConfigs can be accessed at runtime + pause = _.pPause, + debug = _.debug('mcp:23008-17') class MCP23008 extends aggregate(Device, EventEmitter) { - constructor(busObj, i2cAddress, opts = {}) { - super(busObj, i2cAddress, opts) - // opts could include options passed on to ports and pin including custom pin config, pin ids...see gpio.js - this.chip_config = opts.chip_config // TODO allow opts.chip_config to be a byte instead of a string pointer - this.ports = {} - opts.portID = 'A' - opts.pids = opts.pids ? opts.pids : opts.pidsA - this.ports.A = new Port(opts) - this.ports.A.state = new _.Byte(opts.stateA) - this.ports.A.interrupt = opts.interruptA ? opts.interruptA : opts.interrupt - } // end constructor + constructor(busObj, i2cAddress, opts = {}) { + super(busObj, i2cAddress, opts) + // opts could include options passed on to ports and pin including custom pin config, pin ids...see gpio.js + this.chip_config = opts.chip_config // TODO allow opts.chip_config to be a byte instead of a string pointer + this.ports = {} + opts.portID = 'A' + opts.pids = opts.pids ? opts.pids : opts.pidsA + this.ports.A = new Port(opts) + this.ports.A.state = new _.Byte(opts.stateA) + this.ports.A.interrupt = opts.interruptA ? opts.interruptA : opts.interrupt + } // end constructor - // helpers - pin(id) { return this.ports.A.pin(id) } // get a reference to a particular pin's object + // helpers + pin(id) { return this.ports.A.pin(id) } // get a reference to a particular pin's object - pid(address) { return this.ports.A.pid(address) } // return pin id for a given address on a port + pid(address) { return this.ports.A.pid(address) } // return pin id for a given address on a port - pid(num) { return this.ports.A.pins[num - 1].id } + pid(num) { return this.ports.A.pins[num - 1].id } - portByPin(id) { - if (this.ports.A.pin(id)) { return 'A' } - return false - } + portByPin(id) { + if (this.ports.A.pin(id)) { return 'A' } + return false + } - state(port = 'A') { - return this.ports[port].state.value - } + state(port = 'A') { + return this.ports[port].state.value + } - // get a handle to the ports interrupt - inter(port = 'A') { - return this.ports[port].interrupt - } + // get a handle to the ports interrupt + inter(port = 'A') { + return this.ports[port].interrupt + } - // Must call after instantiating. + // Must call after instantiating. - async init() { - debug.L1(`\n=======\nInitializing ${this.id}`) - await this.writeChipCfg(this.chip_config) // chip settings - await this.writePinsCfg() - // write out any initial state(s) - for (let port in this.ports) { - if (this.state(port)) { - debug.L1(`writing initial port state ${port} ${this.state(port)}`) - await this.writePort(this.state(port), 'force', port) - } - } - } + async init() { + debug.L1(`\n=======\nInitializing ${this.id}`) + await this.writeChipCfg(this.chip_config) // chip settings + await this.writePinsCfg() + // write out any initial state(s) + for (let port in this.ports) { + if (this.state(port)) { + debug.L1(`writing initial port state ${port} ${this.state(port)}`) + await this.writePort(this.state(port), 'force', port) + } + } + } - // must call after init if using interrupts - async start() { - debug.L1(`starting ${ this.id }`) - for (let port in this.ports) { - // if there are interrupts being used then start them and listeners - if (this.inter(port)) { - this.startInterrupt(port) - } - } - } + // must call after init if using interrupts + async start() { + debug.L1(`starting ${ this.id }`) + for (let port in this.ports) { + // if there are interrupts being used then start them and listeners + if (this.inter(port)) { + this.startInterrupt(port) + } + } + } - async startInterrupt(port) { - await this.interruptReset(port) - debug.L1(`starting interrupt on port ${ port }`) - await this.inter(port).start() - let chip = this // scope `this` for use in the listener below - // bind handler to the chip so handler can read/write to chip/bank when interrupt is emitted - debug.L3('handler', this.inter(port).handler) - let ihandler = this.inter(port).handler.bind(this) - // inside the listener `this` is the interrupt not the chip/bank - this.inter(port).on('fired', async function () { - debug.L1(`interrupt from ${this.pin_number}`) - let data = await ihandler(port) - debug.L2(`port interrupt event 'fired' data => ${data.bank} on port ${data.port} pin# ${data.pin} pid ${data.pid}`) - chip.emit('fired', data) // emit up the class chain - }) + async startInterrupt(port) { + await this.interruptReset(port) + debug.L1(`starting interrupt on port ${ port }`) + await this.inter(port).start() + let chip = this // scope `this` for use in the listener below + // bind handler to the chip so handler can read/write to chip/bank when interrupt is emitted + debug.L3('handler', this.inter(port).handler) + let ihandler = this.inter(port).handler.bind(this) + // inside the listener `this` is the interrupt not the chip/bank + this.inter(port).on('fired', async function () { + debug.L1(`interrupt from ${this.pin_number}`) + let data = await ihandler(port) + debug.L2(`port interrupt event 'fired' data => ${data.bank} on port ${data.port} pin# ${data.pin} pid ${data.pid}`) + chip.emit('fired', data) // emit up the class chain + }) - } + } - async interruptReset(port = 'A') { - await this.read(portReg(0x08, port)) - await pause(100) // give enough time for mcp to reset its interupt - debug.L1(`interrupt reset on ${this.id} port ${port}`) - } + async interruptReset(port = 'A') { + await this.read(portReg(0x08, port)) + await pause(100) // give enough time for mcp to reset its interupt + debug.L1(`interrupt reset on ${this.id} port ${port}`) + } - async interruptPin(port, format) { - if ('AB'.indexOf(port) === -1) { - format = port ? port : null - port = 'A' - } - let result = await this.read(portReg(0x07, port)) - return format ? _.byteFormat(result, { in: 'DEC', out: format }) : result + async interruptPin(port, format) { + if ('AB'.indexOf(port) === -1) { + format = port ? port : null + port = 'A' + } + let result = await this.read(portReg(0x07, port)) + return format ? _.byteFormat(result, { in: 'DEC', out: format }) : result - } + } - async writeChipCfg(cfg = 'default') { - let setting = chip_config[cfg] - let byte = _.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' }) - debug.L1(`writing mcp chip config ${setting.val}`) - await this.write(chip_config.cmd, byte) - } + async writeChipCfg(cfg = 'default') { + let setting = chip_config[cfg] + let byte = _.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' }) + debug.L1(`writing mcp chip config ${setting.val}`) + await this.write(chip_config.cmd, byte) + } - // pin configurations should already be set before calling - async writePinsCfg() { - debug.L1(`writing mcp pins config`) - for (let port in this.ports) { - for (let setting in registers.pin_config) { - let reg = registers.pin_config[setting] - // TODO 0x10 should be based on chip config - let byte = 0 - for (let pin of this.ports[port].pins) { - byte += pin.address * pin.cfg[setting] - debug.L3(`port: ${ port } pin: ${pin.id} setting: ${ setting } reg: ${ reg } byte: ${ byte }`) - } - await this.write(portReg(reg, port), byte) - } - } - debug.L1(`done writing mcp pins config`) - } // end writePinsCfg + // pin configurations should already be set before calling + async writePinsCfg() { + debug.L1('writing mcp pins config') + for (let port in this.ports) { + for (let setting in registers.pin_config) { + let reg = registers.pin_config[setting] + // TODO 0x10 should be based on chip config + let byte = 0 + for (let pin of this.ports[port].pins) { + byte += pin.address * pin.cfg[setting] + debug.L3(`port: ${ port } pin: ${pin.id} setting: ${ setting } reg: ${ reg } byte: ${ byte }`) + } + await this.write(portReg(reg, port), byte) + } + } + debug.L1('done writing mcp pins config') + } // end writePinsCfg - async readPort(port, opts = {}) { - if ('AB'.indexOf(port) === -1) { - opts = port ? port : {} - port = 'A' - } - let cmd = opts.cmd ? opts.cmd : 'gpio' - let result = await this.read(portReg(registers.pin_cmd[cmd], port)) - debug.L2('read prev ', this.ports[port].state.toFmtPrev('ARY')) - debug.L2('read result', _.byteFormat(result, { in: 'DEC', out: 'ARY' })) - debug.L2('read state ', this.ports[port].state.toFmt('ARY')) - // if port pins changed without a write then update state - if (_.bitChanges(_.byteFormat(result, { in: 'DEC', out: 'ARY' }), this.ports[port].state.toFmt('ARY'))) { - this.ports[port].state.value = result - } - return opts.format ? this.ports[port].state.toFmt(opts.format) : result - } + async readPort(port, opts = {}) { + if ('AB'.indexOf(port) === -1) { + opts = port ? port : {} + port = 'A' + } + let cmd = opts.cmd ? opts.cmd : 'gpio' + let result = await this.read(portReg(registers.pin_cmd[cmd], port)) + debug.L2('read prev ', this.ports[port].state.toFmtPrev('ARY')) + debug.L2('read result', _.byteFormat(result, { in: 'DEC', out: 'ARY' })) + debug.L2('read state ', this.ports[port].state.toFmt('ARY')) + // if port pins changed without a write then update state + if (_.bitChanges(_.byteFormat(result, { in: 'DEC', out: 'ARY' }), this.ports[port].state.toFmt('ARY'))) { + this.ports[port].state.value = result + } + return opts.format ? this.ports[port].state.toFmt(opts.format) : result + } - async readPin(pin, port, opts = {}) { - if ('AB'.indexOf(port) === -1) { - opts = port ? port : {} - port = 'A' - } - await this.readPort(port, opts) - TODO return just true or false not the decimal of pin - will need new version on npm - return this.ports[port].state.bwOp(Math.pow(2, pin - 1), 'check') ? true : false - } + async readPin(pin, port, opts = {}) { + if ('AB'.indexOf(port) === -1) { + opts = port ? port : {} + port = 'A' + } + await this.readPort(port, opts) + // TODO return just true or false not the decimal of pin - will need new version on npm + return this.ports[port].state.bwOp(Math.pow(2, pin - 1), 'check') ? true : false + } - async writePort(byte, op, port = 'A') { - // byte MUST be a decimal - debug.L2(`port:${port}, op:${op}, current pins state\n ${this.ports[port].state.toFmt('PLC') }`) - debug.L2(`byte passed \n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC'})}]:${byte}`) - if (op !== 'force') { - byte = this.ports[port].state.bwOp(byte, op) - } - debug.L2(`byte to write\n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC' })}]:${byte}\n=======`) - await this.write(portReg(registers.pin_cmd.gpio, port), byte) - //update to the saved state - this.ports[port].state.value = byte - } + async writePort(byte, op, port = 'A') { + // byte MUST be a decimal + debug.L2(`port:${port}, op:${op}, current pins state\n ${this.ports[port].state.toFmt('PLC') }`) + debug.L2(`byte passed \n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC'})}]:${byte}`) + if (op !== 'force') { + byte = this.ports[port].state.bwOp(byte, op) + } + debug.L2(`byte to write\n [${ _.byteFormat(byte, { in: 'DEC', out: 'PLC' })}]:${byte}\n=======`) + await this.write(portReg(registers.pin_cmd.gpio, port), byte) + //update to the saved state + this.ports[port].state.value = byte + } - async pinsOn(pins, port, format) { - if ('AB'.indexOf(port) === -1) { - format = port - port = 'A' - } - if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } - await this.writePort(pins, 'on', port) - } + async pinsOn(pins, port, format) { + if ('AB'.indexOf(port) === -1) { + format = port + port = 'A' + } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } + await this.writePort(pins, 'on', port) + } - async allOn(port = 'A') { - let pins = 255 - await this.writePort(pins, 'force', port) - } + async allOn(port = 'A') { + let pins = 255 + await this.writePort(pins, 'force', port) + } - async pinsOff(pins, port, format) { - if ('AB'.indexOf(port) === -1) { - format = port - port = 'A' - } - if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } - await this.writePort(pins, 'off', port) - } + async pinsOff(pins, port, format) { + if ('AB'.indexOf(port) === -1) { + format = port + port = 'A' + } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } + await this.writePort(pins, 'off', port) + } - async allOff(port = 'A') { - let pins = 0 - await this.writePort(pins, 'force', port) - } + async allOff(port = 'A') { + let pins = 0 + await this.writePort(pins, 'force', port) + } - async toggle(pins, port, format) { - if ('AB'.indexOf(port) === -1) { - format = port - port = 'A' - } - if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } - await this.writePort(pins, 'toggle', port) - } + async toggle(pins, port, format) { + if ('AB'.indexOf(port) === -1) { + format = port + port = 'A' + } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } + await this.writePort(pins, 'toggle', port) + } - async allToggle(port = 'A') { - let pins = 255 - await this.writePort(pins, 'toggle', port) - } + async allToggle(port = 'A') { + let pins = 255 + await this.writePort(pins, 'toggle', port) + } - async force(pins, port, format) { - if ('AB'.indexOf(port) === -1) { - format = port - port = 'A' - } - if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } - await this.writePort(pins, 'force', port) - } + async force(pins, port, format) { + if ('AB'.indexOf(port) === -1) { + format = port + port = 'A' + } + if (format) { pins = _.byteFormat(pins, { in: format, out: 'DEC' }) } + await this.writePort(pins, 'force', port) + } } // end 23008 class MCP23017 extends MCP23008 { - constructor(busObj, i2cAddress, opts = {}) { - super(busObj, i2cAddress, opts) - // add a second port - opts.portID = 'B' - opts.pids = opts.pidsB - this.ports.B = new Port(opts) - this.ports.B.state = new _.Byte(opts.stateB) - this.ports.B.interrupt = opts.interruptB ? opts.interruptB : opts.interrupt - } + constructor(busObj, i2cAddress, opts = {}) { + super(busObj, i2cAddress, opts) + // add a second port + opts.portID = 'B' + opts.pids = opts.pidsB + this.ports.B = new Port(opts) + this.ports.B.state = new _.Byte(opts.stateB) + this.ports.B.interrupt = opts.interruptB ? opts.interruptB : opts.interrupt + } - pin(id, port) { - if (!port) { - return this.ports.A.pin(id) ? this.ports.A.pin(id) : this.ports.B.pin(id) - } - return this.ports[port].pin(id) - } + pin(id, port) { + if (!port) { + return this.ports.A.pin(id) ? this.ports.A.pin(id) : this.ports.B.pin(id) + } + return this.ports[port].pin(id) + } - pid(num, port) { + pid(num, port) { console.log('pin for pid',this.ports[port].pins[num - 1]) - return this.ports[port].pins[num - 1].id - } + return this.ports[port].pins[num - 1].id + } } // end MCP23017 Class // EXPORTS module.exports = { - MCP23008, - MCP23017, - pinConfigs + MCP23008, + MCP23017, + pinConfigs } // Local Functions and Settings============================= function portReg(reg, port) { - // TODO check chip configuartion to know what to add for port B. CUrrenly assume IOCON=1 - // index 0,1 ==== 'A','B' - if ((port === 'B') || (port === 1)) { return reg += 0x10 } else { return reg } + // TODO check chip configuartion to know what to add for port B. CUrrenly assume IOCON=1 + // index 0,1 ==== 'A','B' + if ((port === 'B') || (port === 1)) { return reg += 0x10 } else { return reg } } /* ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf @@ -274,31 +274,31 @@ function portReg(reg, port) { */ // Chip Configuration to be used with Register See Page 18 of 23017 doc let chip_config = { - // byte: ['NULL','INTPOL','ODR','HAEN','DISSLW','SEQOP','MIRROR','BANK'] // see page 18 of 23017 datasheet for 8 setting details - cmd: 0x0A, // IOCON.BANK=0 (msb) at powerup so need to use 0x0A, if set to 1 then use - default: { - val: '10100010', // Split Banks port A + 0x10 = Port B,(ignored by 23008), Sequential operation disabled, active high=pulldown - fmt: 'STR' - }, - oneint: { - val: '11100100', // same as default execpt int pins connected - fmt: 'STR' - } + // byte: ['NULL','INTPOL','ODR','HAEN','DISSLW','SEQOP','MIRROR','BANK'] // see page 18 of 23017 datasheet for 8 setting details + cmd: 0x0A, // IOCON.BANK=0 (msb) at powerup so need to use 0x0A, if set to 1 then use + default: { + val: '10100010', // Split Banks port A + 0x10 = Port B,(ignored by 23008), Sequential operation disabled, active high=pulldown + fmt: 'STR' + }, + oneint: { + val: '11100100', // same as default execpt int pins connected + fmt: 'STR' + } } let registers = { - pin_config: { - dir: 0, - ivrt: 1, - pullup: 6, - intr: 2, - usedef: 4, - defval: 3, - }, - pin_cmd: { - intf: 7, // readonly - intcap: 8, // readonly - gpio: 9, // read/write - olat: 10 // read only - } + pin_config: { + dir: 0, + ivrt: 1, + pullup: 6, + intr: 2, + usedef: 4, + defval: 3, + }, + pin_cmd: { + intf: 7, // readonly + intcap: 8, // readonly + gpio: 9, // read/write + olat: 10 // read only + } }