parent
16cea2ef02
commit
54a2c237f3
|
@ -30,7 +30,7 @@
|
||||||
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
|
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uci/i2c-device": "^0.1.4",
|
"@uci/i2c-device": "^0.1.4",
|
||||||
"@uci/logger": "0.0.4",
|
"@uci/logger": "0.0.6",
|
||||||
"@uci/utils": "^0.1.1"
|
"@uci/utils": "^0.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -5,22 +5,31 @@ import commands from './commands'
|
||||||
import logger from '@uci/logger'
|
import logger from '@uci/logger'
|
||||||
let log = {}
|
let log = {}
|
||||||
|
|
||||||
export default class MCP230XX extends Device {
|
class MCP230XX extends Device {
|
||||||
constructor(opts) {
|
constructor(opts) {
|
||||||
super(opts)
|
super(opts)
|
||||||
log = logger({file:'src/mcp230xx.js',class:'MCP230XX',name:'mcp',id:this.id})
|
log = logger({
|
||||||
|
file: 'src/mcp230xx.js',
|
||||||
|
class: 'MCP230XX',
|
||||||
|
name: 'mcp',
|
||||||
|
id: this.id
|
||||||
|
})
|
||||||
this.chip17 = opts.chip17
|
this.chip17 = opts.chip17
|
||||||
this.commands = this.bindFuncs(commands)
|
this.commands = this.bindFuncs(commands)
|
||||||
this.addNamespace('commands','s') // allow access to commands via socket/server
|
this.addNamespace('commands', 's') // allow access to commands via socket/server
|
||||||
this.pin = this.commands.pin // add a simplier reference for local access
|
this.pin = this.commands.pin // add a simplier reference for local access
|
||||||
this.chipcfg = this.commands.chip.cfg // add a simplier reference for local access
|
this.chipcfg = this.commands.chip.cfg // add a simplier reference for local access
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(){
|
async init() {
|
||||||
await super.init()
|
await super.init()
|
||||||
let res = await this.chipcfg({})
|
let res = await this.chipcfg({})
|
||||||
let cfg = this.chip17 ?'10100010':'00100010'
|
let cfg = this.chip17 ? '10100010' : '00100010'
|
||||||
if (res.response !==cfg ) throw `could not configure mcp chip at ${this.address}=0x${this.address.toString(16)}`
|
if (res.response !== cfg)
|
||||||
|
throw `could not configure mcp chip at ${
|
||||||
|
this.address
|
||||||
|
}=0x${this.address.toString(16)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of MCP230XX Class
|
} // end of MCP230XX Class
|
||||||
|
|
||||||
|
export default MCP230XX
|
||||||
|
|
116
src/mcp230xxi.js
116
src/mcp230xxi.js
|
@ -6,66 +6,78 @@ let log = {}
|
||||||
|
|
||||||
// if opts.iport not set then will be generated based on pin number
|
// if opts.iport not set then will be generated based on pin number
|
||||||
|
|
||||||
export default class MCP230XXi extends MCP230XX {
|
class MCP230XXi extends MCP230XX {
|
||||||
constructor(pins,opts) {
|
constructor(pins, opts) {
|
||||||
if (typeof opts.iport ==='number' || opts.ipath) {
|
if (typeof opts.iport === 'number' || opts.ipath) {
|
||||||
if (typeof opts.iport ==='number') {
|
if (typeof opts.iport === 'number') {
|
||||||
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>t'
|
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'inter#c>t'
|
||||||
opts.inter = {port:opts.iport}
|
opts.inter = { port: opts.iport }
|
||||||
opts.inter.host = opts.ihost || opts.host
|
opts.inter.host = opts.ihost || opts.host
|
||||||
}
|
}
|
||||||
if (opts.ipath) {
|
if (opts.ipath) {
|
||||||
opts.inter = { path: opts.ipath || 'interrupt'}
|
opts.inter = { path: opts.ipath || 'interrupt' }
|
||||||
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + 'inter#c>n'
|
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + 'inter#c>n'
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
pins.forEach((pin, index) => {
|
||||||
pins.forEach( (pin,index) => {
|
let ipin = 'i' + pin
|
||||||
let ipin = 'i'+pin
|
|
||||||
opts[ipin] = opts[pin] || {}
|
opts[ipin] = opts[pin] || {}
|
||||||
if (index===1) opts[ipin].mport = opts[ipin].mort || 'B'
|
if (index === 1) opts[ipin].mport = opts[ipin].mort || 'B'
|
||||||
delete(opts[pin])
|
delete opts[pin]
|
||||||
if (opts[ipin].port || opts.iport !=='number') {
|
if (opts[ipin].port || opts.iport !== 'number') {
|
||||||
opts[ipin].port = opts[ipin].port || opts.iport
|
opts[ipin].port = opts[ipin].port || opts.iport
|
||||||
if (typeof opts[ipin].port !=='number') opts[ipin].port = 9000 + pin
|
if (typeof opts[ipin].port !== 'number') opts[ipin].port = 9000 + pin
|
||||||
opts[ipin].host = opts[ipin].host || opts.ihost || opts.host
|
opts[ipin].host = opts[ipin].host || opts.ihost || opts.host
|
||||||
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + ipin +'#c>t'
|
opts.sockets =
|
||||||
|
(opts.sockets ? opts.sockets + ',' : '') + ipin + '#c>t'
|
||||||
}
|
}
|
||||||
// either on the same host as bus and interrupt or not - no need for both
|
// either on the same host as bus and interrupt or not - no need for both
|
||||||
else {
|
else {
|
||||||
opts[pin].path = opts[pin].path || opts.ipath
|
opts[pin].path = opts[pin].path || opts.ipath
|
||||||
if(!opts[pin].path) Object.assign(opts[pin],{path:'interrupt:'+pin})
|
if (!opts[pin].path)
|
||||||
opts.sockets = (opts.sockets ? (opts.sockets + ',') : '') + pin+'#c>n'
|
Object.assign(opts[pin], { path: 'interrupt:' + pin })
|
||||||
|
opts.sockets = (opts.sockets ? opts.sockets + ',' : '') + pin + '#c>n'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
super(opts)
|
super(opts)
|
||||||
log = logger({file:'src/mcp230xxi.js',class:'MCP230XXi',name:'mcp',id:this.id})
|
log = logger({
|
||||||
log.info({opts:opts},'mcp interrupt options after calling super() on base')
|
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 => {
|
pins.forEach(pin => {
|
||||||
this[pin] = opts['i'+pin] || {}
|
this[pin] = opts['i' + pin] || {}
|
||||||
})
|
})
|
||||||
this.pins = pins
|
this.pins = pins
|
||||||
Object.assign(this.commands.pin, this.bindFuncs(ipincommands)) // add interrupt pin commands to base set in "command.js"
|
Object.assign(this.commands.pin, this.bindFuncs(ipincommands)) // add interrupt pin commands to base set in "command.js"
|
||||||
this.addNamespace('commands','c')
|
this.addNamespace('commands', 'c')
|
||||||
this._interruptProcess = null
|
this._interruptProcess = null
|
||||||
this.ready = false
|
this.ready = false
|
||||||
log.info({opts:opts, pins:pins}, 'options for mcp interrupt processor')
|
log.info({ opts: opts, pins: pins }, 'options for mcp interrupt processor')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(){
|
async init() {
|
||||||
await super.init()
|
await super.init()
|
||||||
this.pins.forEach(async pin => {
|
this.pins.forEach(async pin => {
|
||||||
let cfg = {port:this[pin].mport||'A',pins:this[pin].pins||'all', cfg:this[pin].type ||'toggle_switch'}
|
let cfg = {
|
||||||
|
port: this[pin].mport || 'A',
|
||||||
|
pins: this[pin].pins || 'all',
|
||||||
|
cfg: this[pin].type || 'toggle_switch'
|
||||||
|
}
|
||||||
await this.pin.cfg(cfg)
|
await this.pin.cfg(cfg)
|
||||||
// shouldn't need this as reset is pushed upon connection to interrupt socket
|
// 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')
|
// log.info('initial resetting of mcp interrupt port for corresponding sbc gpio pin')
|
||||||
// await this._reset(this[pin].mport)
|
// await this._reset(this[pin].mport)
|
||||||
this.ready=true
|
this.ready = true
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('interrupt', function (details) {
|
this.on('interrupt', function(details) {
|
||||||
details.id = this.id
|
details.id = this.id
|
||||||
if (!this._interruptProcess) {
|
if (!this._interruptProcess) {
|
||||||
console.log('----default interrupt processor for mcp instance----')
|
console.log('----default interrupt processor for mcp instance----')
|
||||||
|
@ -73,51 +85,63 @@ export default class MCP230XXi extends MCP230XX {
|
||||||
console.dir(details)
|
console.dir(details)
|
||||||
} else this._interruptProcess(details)
|
} else this._interruptProcess(details)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _reset(port) { // local non-packet hidden command
|
async _reset(port) {
|
||||||
|
// local non-packet hidden command
|
||||||
log.info(`resetting interrupt for port ${port || 'A'},${this.id}`)
|
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
|
return await this.bus.read(port !== 'B' ? 0x08 : 0x18) // 0x08 is intcap interrupt capture register
|
||||||
}
|
}
|
||||||
|
|
||||||
interruptProcessor(func) {this._interruptProcess = func}
|
interruptProcessor(func) {
|
||||||
|
this._interruptProcess = func
|
||||||
|
}
|
||||||
|
} // end of MCP230XXi Class
|
||||||
|
|
||||||
} // end of MCP230XX Class
|
export default MCP230XXi
|
||||||
|
|
||||||
// commands to be added to pin packet command functions
|
// commands to be added to pin packet command functions
|
||||||
const ipincommands= { interrupt: {
|
const ipincommands = {
|
||||||
reset: async function (packet) {
|
interrupt: {
|
||||||
log.info({packet:packet},`'socket has push requested a reset of mcp interrupt port for gpio pin ${packet.pin}`)
|
reset: async function(packet) {
|
||||||
|
log.info(
|
||||||
|
{ packet: packet },
|
||||||
|
`'socket has push requested a reset of mcp interrupt port for gpio pin ${
|
||||||
|
packet.pin
|
||||||
|
}`
|
||||||
|
)
|
||||||
let port = this[packet.pin].mport || 'A'
|
let port = this[packet.pin].mport || 'A'
|
||||||
await this._reset(port)
|
await this._reset(port)
|
||||||
},
|
},
|
||||||
// given a gpio interrupt then push a packet with cmd: 'pin.interrupt.find' and pin: the gpio pin number
|
// 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
|
find: async function(inter) {
|
||||||
if(this.ready){ // protects tripped interrupt before it's fully initialized, or interrupt requests arriving before porcessing is complete
|
// inter is a UCI packet
|
||||||
|
if (this.ready) {
|
||||||
|
// protects tripped interrupt before it's fully initialized, or interrupt requests arriving before porcessing is complete
|
||||||
this.ready = false
|
this.ready = false
|
||||||
log.info({packet:inter},'finding mcp pin which caused interrupt')
|
log.info({ packet: inter }, 'finding mcp pin which caused interrupt')
|
||||||
let packet = {pins:'all',reg:'intf'}
|
let packet = { pins: 'all', reg: 'intf' }
|
||||||
packet.port = inter.port || this[inter.pin].mport || 'A'
|
packet.port = inter.port || this[inter.pin].mport || 'A'
|
||||||
let res = await this.pin.status(packet)
|
let res = await this.pin.status(packet)
|
||||||
log.info('found pin now resetting mcp port interrupt')
|
log.info('found pin now resetting mcp port interrupt')
|
||||||
if (!res.status) return {error:'no pin associated with interrupt'}
|
if (!res.status) return { error: 'no pin associated with interrupt' }
|
||||||
let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' })
|
let pin = byteFormat(res.status.port, { in: 'ARY', out: 'PLC' })
|
||||||
res.pin = pin[0]
|
res.pin = pin[0]
|
||||||
packet.pins = pin[0]
|
packet.pins = pin[0]
|
||||||
packet.reg = null
|
packet.reg = null
|
||||||
if (packet.pins) { // avoid bad interrupt (i.e. no pin caused interrupt)
|
if (packet.pins) {
|
||||||
|
// avoid bad interrupt (i.e. no pin caused interrupt)
|
||||||
res.state = (await this.pin.status(packet)).status.pins[0][1]
|
res.state = (await this.pin.status(packet)).status.pins[0][1]
|
||||||
res.port = packet.port
|
res.port = packet.port
|
||||||
res.count = inter.count
|
res.count = inter.count
|
||||||
res.inter = inter.pin
|
res.inter = inter.pin
|
||||||
delete res.status
|
delete res.status
|
||||||
this.emit('interrupt',res)
|
this.emit('interrupt', res)
|
||||||
}
|
}
|
||||||
await this._reset(packet.port)
|
await this._reset(packet.port)
|
||||||
this.ready=true
|
this.ready = true
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue