fix bad comment

master
David Kebler 2017-10-18 17:34:34 -07:00
parent a46e9501eb
commit 35605352bf
2 changed files with 239 additions and 239 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "@uci/mcp", "name": "@uci/mcp",
"main": "src/mcp23008-17.js", "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", "description": "Classes and Helper Functions for using the MCP chip on I2C Bus",
"scripts": { "scripts": {
"test": "./node_modules/.bin/mocha --reporter list --timeout 30000", "test": "./node_modules/.bin/mocha --reporter list --timeout 30000",

View File

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