uci-mcp/src/mcp230xxi.js

113 lines
4.2 KiB
JavaScript
Raw Normal View History

import MCP230XX from './mcp230xx'
import { byteFormat } from '@uci/utils/src/byte'
2018-05-16 07:19:03 -07:00
import logger from '@uci/logger'
let log = {}
// if opts.iport not set then will be generated based on pin number
export default class MCP230XXi extends MCP230XX {
constructor(pins,opts) {
if (typeof opts.iport ==='number' || opts.ipath) {
if (typeof opts.iport ==='number') {
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>t'
opts.inter = {port:opts.iport}
opts.inter.host = opts.ihost || opts.host
}
if (opts.ipath) {
opts.inter = { path: opts.ipath || 'interrupt'}
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>n'
}
}
else {
pins.forEach( (pin,index) => {
let ipin = 'i'+pin
opts[ipin] = opts[pin] || {}
if (index===1) opts[ipin].mport = opts[ipin].mort || 'B'
delete(opts[pin])
if (opts[ipin].port || opts.iport !=='number') {
opts[ipin].port = opts[ipin].port || opts.iport
if (typeof opts[ipin].port !=='number') opts[ipin].port = 9000 + pin
opts[ipin].host = opts[ipin].host || opts.ihost || opts.host
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + ipin +'#c>t'
}
// either on the same host as bus and interrupt or not - no need for both
else {
opts[pin].path = opts[pin].path || opts.ipath
if(!opts[pin].path) Object.assign(opts[pin],{path:'interrupt:'+pin})
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + pin+'#c>n'
}
})
}
super(opts)
log = logger({file:'src/mcp230xxi.js',class:'MCP230XXi',name:'mcp',id:this.id})
log.info({opts:opts},'mcp interrupt options after calling super() on base')
pins.forEach(pin => {
this[pin] = opts['i'+pin] || {}
})
this.pins = pins
Object.assign(this.commands.pin, this.bindFuncs(ipincommands)) // add interrupt pin commands to base set in "command.js"
this.addNamespace('commands','c')
this._interruptProcess = null
this.ready = false
log.info({opts:opts, pins:pins}, 'options for mcp interrupt processor')
}
async init(){
await super.init()
this.pins.forEach(async pin => {
let cfg = {port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'}
await this.pin.cfg(cfg)
log.info('resetting mcp port for corresponding gpio pin')
await this.pin.interrupt.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(this.id)
console.dir(details)
} else this._interruptProcess(details)
})
}
interruptProcessor(func) {this._interruptProcess = func}
} // end of MCP230XX Class
// commands to be added to pin command functions
const ipincommands= { interrupt: {
reset: async function (port) {
log.info(`resetting interrupt for port ${port || 'A'},${this.id}`)
return await this.bus.read(port!=='B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register
},
// 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 hash packet
if(this.ready){ // protects tripped interrupt before it's fully initialized and reset
log.info({packet:inter},'finding mcp pin which caused interrupt')
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')
await this.pin.interrupt.reset(packet.port)
if (!res.status) return {error:'no pin associated with interrupt'}
let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' })
res.pin = pin[0]
packet.pins = pin[0]
packet.reg = null
res.state = (await this.pin.status(packet)).status.pins[0][1]
res.port = packet.port
res.count = inter.count
res.inter = inter.pin
delete res.status
this.emit('interrupt',res)
return res
}
}
}
}