diff --git a/package.json b/package.json index ecc23a6..309f692 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@uci/mcp", "main": "src", - "version": "0.1.20", + "version": "0.1.21", "description": "Classes and Helper Functions for using the MCP chip on I2C Bus", "scripts": { "relays": "node -r esm examples/relays", diff --git a/src/commands.js b/src/commands.js index 023a5b1..1343197 100644 --- a/src/commands.js +++ b/src/commands.js @@ -1,5 +1,9 @@ import * as _ from '@uci-utils/byte' import { CHIP, PIN } from './config' +import logger from '@uci-utils/logger' + +let log = {file:'/src/commands.js', package:'@uci/mcp'} + // TODO add uci debug logging @@ -21,12 +25,15 @@ export default { let byte = _.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' }) if (byte < 128) byte += 128 // make sure BANK=1 remains on let reg = this.chip17 ? 0x0A : 0x05 - // console.log(this.chip17, reg, this.id, this.address) + log.debug ({msg:'writing chip configuration', chip17:this.chip17, register:reg, id:this.id, address:this.address}) bus = await this.bus.write(reg,byte) if (bus.error) return bus bus = await this.bus.read(0x05) if (bus.error) return bus - return { cmd:'reply', response:_.byteFormat(bus.response,{in:'DEC',out:'STR'}) } + if (!this.chip17) bus.response = bus.response - 127 + let res = _.byteFormat(bus.response,{in:'DEC',out:'STR'}) + if (res !== setting.val) return { cmd:'reply', error:`chip configuration failed ${res} != ${setting.val} (${cfg})`} + return { cmd:'reply', response:res } } }, @@ -43,6 +50,7 @@ export default { else cfg = PIN.cfgset[packet.cfg] for(let name of Object.keys(PIN.setting)) { let op = cfg[name] ? 'on' : 'off' + console.log({msg:'setting pin register', operation:op, registerName:name, resgisterNum:PIN.setting[name]}) let busreply = await this.pin._state(packet,op,PIN.setting[name]) if (busreply.error) return busreply reply.status[name] = busreply.status @@ -71,7 +79,7 @@ export default { }, _state: async function(packet,op,reg){ reg = (reg!==undefined)? reg : PIN.cmd.gpio - // console.log('_state change request', op, reg, packet) + log.debug({msg:'_state change request', operation:op, register:reg, packet:packet}) let reply = { cmd:'reply'} let pins = parsePins(packet.pins) let state = new _.Byte() @@ -83,6 +91,7 @@ export default { bus = await this.bus.read(sreg(reg,packet.port)) if (bus.error) return bus state.value = bus.response + log.debug({msg:'after setting pin state', prev:state.prv, new:state.value}) reply.status = state.bwOp(pins.value,'check',{in:'PLC', out:'PLC'}) return reply }, diff --git a/src/config.js b/src/config.js index 675dc07..daab9e5 100644 --- a/src/config.js +++ b/src/config.js @@ -9,9 +9,17 @@ export const CHIP = { val: '10100010', // Split Banks port A + 0x10 = Port B,(ignored by 23008), Sequential operation disabled, active high=pulldown fmt: 'STR' }, - oneint: { + oneInt: { val: '11100100', // same as default execpt interupt pins of port A and B are connected fmt: 'STR' + }, + intPullup: { + val: '10100000', // same as default execpt interupt pins active=low means pullup (high and go low on trip) + fmt: 'STR' + }, + intPullupOneInt: { + val: '10100000', // same as intPullup and oneInt combined + fmt: 'STR' } } diff --git a/src/mcp230xx.js b/src/mcp230xx.js index 2595455..f11260e 100644 --- a/src/mcp230xx.js +++ b/src/mcp230xx.js @@ -15,6 +15,7 @@ class MCP230XX extends Device { id: this.id }) this.chip17 = opts.chip17 + this.chipCfg = opts.chipCfg || 'default' this.commands = this.bindFuncs(commands) this.addNamespace('commands', 's') // allow access to commands via socket/server this.pin = this.commands.pin // add a simplier reference for local access @@ -23,10 +24,10 @@ class MCP230XX extends Device { async init() { await super.init() - let res = await this.chipcfg({}) - let cfg = this.chip17 ? '10100010' : '00100010' - if (res.response !== cfg) - throw `could not configure mcp chip at ${this.address}/${this.address.toString(16)}` + let res = await this.chipcfg({cfg:this.chipCfg}) + log.fatal({msg:'unable to configure mcp chip',cfg:this.chipCfg, address:this.address}) + if (res.error) + throw `${res.error} at address ${this.address}/${this.address.toString(16)}` } } // end of MCP230XX Class diff --git a/src/mcp230xxi.js b/src/mcp230xxi.js index 48a2060..23ab2a4 100644 --- a/src/mcp230xxi.js +++ b/src/mcp230xxi.js @@ -4,16 +4,23 @@ import { byteFormat } from '@uci-utils/byte' import logger from '@uci-utils/logger' let log = {} +log = logger({ + file: 'src/mcp230xxi.js', + class: 'MCP230XXi', + name: 'mcp-interrupt', +}) + // if opts.iport not set then will be generated based on pin number class MCP230XXi extends MCP230XX { constructor(pins, options={}) { - if (!Array.isArray(pins)) { options = pins; pins = options.interrupt.pins} // if pins sent via .interrupt.pins - let opts = Object.assign({},options) // don't allow options to mutate - if (opts.interrupt) delete opts.interrupt.pins // if .interrupt is passed then .pins must be removed - delete opts.sockets // .sockets is used by uci base so clear it was sent by mistake - // console.log('options as ready for mcp',pins, opts) + if (!Array.isArray(pins)) { options = pins; pins = options.interrupt.pins} // if pins sent via .interrupt.pins + let opts = Object.assign({},options) // don't allow passed options to mutate + if (opts.interrupt) delete opts.interrupt.pins // if .interrupt was passed then .pins must be removed + delete opts.sockets // .sockets is used by uci base so clear it if was used by enduser and sent by mistake + log.debug({msg:'passed options before setting',options:opts}) + // if iport or ipath is set then all interrupts have a single consolidating socket if (typeof opts.iport === 'number' || opts.ipath) { if (typeof opts.iport === 'number') { @@ -29,11 +36,11 @@ class MCP230XXi extends MCP230XX { // otherwise each pin will have its own socket so make a client for each pins.forEach((pin, index) => { let ipin = 'i' + pin - opts[ipin] = opts[pin] || opts.interrupt || {} + opts[ipin] = opts[pin] || Object.assign({},opts.interrupt) || {} if (index === 1) opts[ipin].mport = opts[ipin].mport || 'B' delete opts[pin] if (opts[ipin].host) { - opts[ipin].port = opts[ipin].port ? opts[ipin].port + +pin : 9000 + +pin + opts[ipin].port = opts[ipin].port ? opts[ipin].port + +pin : 9000 + parseInt(pin) opts[ipin].host = opts[ipin].host opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + ipin + '#c>t' } @@ -45,16 +52,16 @@ class MCP230XXi extends MCP230XX { }) } super(opts) + log = logger({ file: 'src/mcp230xxi.js', class: 'MCP230XXi', - name: 'mcp', + name: 'mcp-interrupt', id: this.id }) - log.info( - { opts: opts }, - 'mcp interrupt options after calling super() on base' - ) + + log.info({ opts: opts, msg:'mcp interrupt options after calling super() on base'}) + pins.forEach(pin => { this[pin] = opts['i' + pin] || {} }) @@ -68,7 +75,7 @@ class MCP230XXi extends MCP230XX { async init() { await super.init() - this.pins.forEach(async pin => { + for (let pin of this.pins) { let cfg = { port: this[pin].mport || 'A', pins: this[pin].pins || 'all', @@ -76,16 +83,16 @@ class MCP230XXi extends MCP230XX { } // this will set default type to internal pullup, only need to to change indivial pins to external if desired await this.pin.cfg(cfg) - // shouldn't need this as reset is pushed upon connection to interrupt socket - // log.info('initial resetting of mcp interrupt port for corresponding sbc gpio pin') - // await this._reset(this[pin].mport) + log.info('initial resetting of mcp interrupt port for corresponding sbc gpio pin') + await this._reset(this[pin].mport) this.ready = true - }) + } this.on('interrupt', function(details) { details.id = this.id if (!this._interruptProcess) { console.log('----default interrupt processor for mcp instance----') + console.log('create your own function and register it with .interruptProcess(function)') console.log(this.id) console.dir(details) } else this._interruptProcess(details) @@ -94,7 +101,7 @@ class MCP230XXi extends MCP230XX { async _reset(port) { // local non-packet hidden command - console.log(`resetting interrupt for port ${port || 'A'},${this.id} arg ${port !== 'B' ? 0x08 : 0x1}`) + log.debug(`resetting interrupt for port ${port || 'A'},${this.id} arg ${port !== 'B' ? 0x08 : 0x18}`) return await this.bus.read(port !== 'B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register } @@ -121,15 +128,14 @@ const ipincommands = { // given a gpio interrupt then push a packet with cmd: 'pin.interrupt.find' and pin: the gpio pin number find: async function(inter) { // inter is a UCI packet - console.log('packet from interrupt to interpret',inter) + if (this.ready) { // protects tripped interrupt before it's fully initialized, or interrupt requests arriving before porcessing is complete this.ready = false - log.info({ packet: inter }, 'finding mcp pin which caused interrupt') + log.debug({msg:'raw packet from interrupt, will now find the pin that caused interrupt', inter:inter}) let packet = { pins: 'all', reg: 'intf' } packet.port = inter.port || this[inter.pin].mport || 'A' let res = await this.pin.status(packet) - log.info('found pin now resetting mcp port interrupt') if (!res.status) return { error: 'no pin associated with interrupt' } let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' }) res.pin = pin[0] @@ -143,6 +149,7 @@ const ipincommands = { res.inter = inter.pin delete res.status this.emit('interrupt', res) + log.debug({msg:'found pin now resetting mcp port interrupt', response:res}) } await this._reset(packet.port) this.ready = true