basic commands working
configure chip ack chip cfg pin change state of pin (on,off,toggle)master
parent
71bd508a0c
commit
8a9950459a
|
@ -15,11 +15,45 @@ const delay = time => new Promise(res=>setTimeout(()=>res(),time))
|
||||||
|
|
||||||
await mcpclient.init()
|
await mcpclient.init()
|
||||||
console.log('=============sending============')
|
console.log('=============sending============')
|
||||||
let packet = {cmd:'pin.test'}
|
// let packet = {cmd:'chip.ack'}
|
||||||
console.dir(packet)
|
// console.dir(packet)
|
||||||
await mcpclient.send(packet)
|
// for (let i=0;i<20;i++){
|
||||||
|
// await delay(100)
|
||||||
|
// packet.num = i
|
||||||
|
// console.log('--------->',i)
|
||||||
|
// mcpclient.send(packet)
|
||||||
|
// }
|
||||||
|
|
||||||
await delay(3000)
|
let packet = {cmd:'chip.cfg'}
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
await delay(1000)
|
||||||
|
// packet = {cmd:'pin.cfg', pin:2, cfg:'toggle_switch'}
|
||||||
|
packet = {cmd:'pin.cfg', pin:2}
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
await delay(1000)
|
||||||
|
packet = {cmd:'pin.state.off', pin:2, }
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
await delay(1000)
|
||||||
|
packet = {cmd:'pin.state.on', pin:2, }
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
await delay(1000)
|
||||||
|
packet = {cmd:'pin.state.toggle', pin:2, }
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
await delay(1000)
|
||||||
|
packet = {cmd:'pin.state.toggle', pin:2, }
|
||||||
|
console.dir(packet)
|
||||||
|
mcpclient.send(packet)
|
||||||
|
// packet = {cmd:'pin.cfg', pin:3}
|
||||||
|
// console.dir(packet)
|
||||||
|
// mcpclient.send(packet)
|
||||||
|
|
||||||
|
|
||||||
|
await delay(10000)
|
||||||
process.kill(process.pid, 'SIGTERM')
|
process.kill(process.pid, 'SIGTERM')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import MCP230XX from '../src/mcp230xx-packet'
|
||||||
;
|
;
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
||||||
let mcp_chip = new MCP230XX({id:'mcp23008-27', address:'0x27', bus:{host:'sbc'} })
|
let mcp_chip = new MCP230XX({id:'mcp23008-27', address:0x27, bus:{host:'sbc'} })
|
||||||
|
|
||||||
await mcp_chip.init()
|
await mcp_chip.init()
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uci/i2c": "^0.1.0",
|
"@uci/i2c": "^0.1.0",
|
||||||
"@uci/utils": "^0.1.0",
|
"@uci/utils": "^0.1.0",
|
||||||
"aggregation": "^1.2.0"
|
"aggregation": "^1.2.0",
|
||||||
|
"bitwise": "^1.3.0"
|
||||||
},
|
},
|
||||||
"@std/esm": "cjs",
|
"@std/esm": "cjs",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
// import _ from '@uci/utils/src/byte'
|
||||||
|
import _ from '../../archive/uci-utils/src/byte'
|
||||||
|
import { CHIP, PIN } from './config'
|
||||||
|
|
||||||
|
export const chip = {
|
||||||
|
ack: async function(packet){
|
||||||
|
// process packet based on command and any other props into a bus packet
|
||||||
|
let bus_packet = { cmd:'scan'}
|
||||||
|
// console.log(packet.num)
|
||||||
|
let bus_reply = await this.busSend(bus_packet)
|
||||||
|
if (bus_reply.error) return bus_reply
|
||||||
|
let res = { cmd:'reply', _req:packet, _reqBus:bus_packet, ack: false, address:this.address}
|
||||||
|
if (bus_reply.response.indexOf(parseInt(this.address,16))!=-1) res.ack = true
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
cfg: async function(packet){
|
||||||
|
let setting = {}
|
||||||
|
let cfg = packet.cfg || 'default'
|
||||||
|
if (cfg === 'custom') setting = {val:packet.setting, fmt:packet.fmt || 'STR'}
|
||||||
|
else {
|
||||||
|
if (CHIP[cfg]) setting = CHIP[cfg]
|
||||||
|
else return {error:`no chip settings for ${cfg}`}
|
||||||
|
}
|
||||||
|
let byte = _.byteFormat(setting.val, { in: setting.fmt, out: 'DEC' })
|
||||||
|
let bus_packet = { cmd:'write', args: {address:this.address, cmd:CHIP.cmd, byte:byte}}
|
||||||
|
// console.log ('writing mcp chip config', bus_packet)
|
||||||
|
let bus_reply = await this.busSend(bus_packet)
|
||||||
|
if (bus_reply.error) return bus_reply
|
||||||
|
let res = { cmd:'reply', _req:packet, _reqBus:bus_packet , response:bus_reply.response}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Individual Pin Configurations
|
||||||
|
// set is for cfg: 'custom' assume a setting is zero unless given
|
||||||
|
// packet = { pin:, port:, cfg: , set:{dir: 0, ivrt: 0, pullup: 0, intr: 0, usedef: 0,defval: 0} }
|
||||||
|
// first get the current byte (pin) state for that setting
|
||||||
|
export const pin = {
|
||||||
|
cfg: async function(packet){
|
||||||
|
let shift = 0
|
||||||
|
let cfg = {}
|
||||||
|
let reply = { cmd:'reply', _req:packet, response:{} }
|
||||||
|
if (packet.port === 'B') shift= 0x10 // TODO check on shift amount
|
||||||
|
packet.cfg = packet.cfg || 'output'
|
||||||
|
if (packet.cfg==='custom') cfg = packet.set
|
||||||
|
else cfg = PIN.cfgset[packet.cfg]
|
||||||
|
let pin = new _.Byte([packet.pin],'PLC')
|
||||||
|
let state = new _.Byte()
|
||||||
|
for(let name of Object.keys(PIN.setting)) {
|
||||||
|
let bus_packet = { cmd:'read', args: {address:this.address, cmd:PIN.setting[name]+shift } }
|
||||||
|
let bus = await this.busSend(bus_packet)
|
||||||
|
if (bus.error) return bus
|
||||||
|
state.value = bus.response
|
||||||
|
let op = cfg[name] ? 'on' : 'off'
|
||||||
|
bus_packet = { cmd:'write', args: {address:this.address, cmd:PIN.setting[name]+shift, byte:state.bwOp(pin.value,op,{in:'PLC', out:'DEC'}) } }
|
||||||
|
bus = await this.busSend(bus_packet)
|
||||||
|
if (bus.error) return bus
|
||||||
|
bus_packet = { cmd:'read', args: {address:this.address, cmd:PIN.setting[name]+shift } }
|
||||||
|
bus = await this.busSend(bus_packet)
|
||||||
|
if (bus.error) return bus
|
||||||
|
state.value = bus.response
|
||||||
|
reply.response[name] = state.bwOp(pin.value,'check',{in:'PLC', out:'PLC'})[0]===packet.pin ? 'on':'off'
|
||||||
|
}
|
||||||
|
return reply
|
||||||
|
},
|
||||||
|
|
||||||
|
// state is equivalent to read
|
||||||
|
status: packet => {
|
||||||
|
},
|
||||||
|
// threse three only for output pins
|
||||||
|
state : {
|
||||||
|
on: async function (packet) {
|
||||||
|
return state.bind(this)(packet,'on')
|
||||||
|
},
|
||||||
|
off: async function (packet) {
|
||||||
|
return state.bind(this)(packet,'off')
|
||||||
|
},
|
||||||
|
toggle: async function (packet) {
|
||||||
|
return state.bind(this)(packet,'toggle')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// // will create packet to determin pin caused interrupt, packet will come from interrupt module
|
||||||
|
// interrupt: {
|
||||||
|
// find: packet =>{},
|
||||||
|
// report: packet=>{} // come here after determining which pin to report to requester
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = async function(packet,op){
|
||||||
|
console.log(op)
|
||||||
|
let shift = 0
|
||||||
|
let reply = { cmd:'reply', _req:packet}
|
||||||
|
if (packet.port === 'B') shift= 0x10 // TODO check on shift amount
|
||||||
|
let pin = new _.Byte([packet.pin],'PLC')
|
||||||
|
let state = new _.Byte()
|
||||||
|
let bus_packet = { cmd:'read', args: {address:this.address, cmd:PIN.cmd.gpio+shift} }
|
||||||
|
let bus = await this.busSend(bus_packet)
|
||||||
|
state.value = bus.response
|
||||||
|
bus_packet = { cmd:'write', args: {address:this.address, cmd:PIN.cmd.gpio+shift, byte:state.bwOp(pin.value,op,{in:'PLC', out:'DEC'}) } }
|
||||||
|
bus = await this.busSend(bus_packet)
|
||||||
|
if (bus.error) return bus
|
||||||
|
bus_packet = { cmd:'read', args: {address:this.address, cmd:PIN.cmd.gpio+shift} }
|
||||||
|
bus = await this.busSend(bus_packet)
|
||||||
|
if (bus.error) return bus
|
||||||
|
state.value = bus.response
|
||||||
|
reply.status = state.bwOp(pin.value,'check',{in:'PLC', out:'PLC'})[0]===packet.pin ? 'on':'off'
|
||||||
|
return reply
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
|
||||||
|
export const CHIP = {
|
||||||
|
// The consifuration byte is ['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 us
|
||||||
|
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 interupt pins of port A and B are connected
|
||||||
|
fmt: 'STR'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PIN = {
|
||||||
|
setting: { // these are the mcp registers = command for each setting
|
||||||
|
dir: 0,
|
||||||
|
ivrt: 1,
|
||||||
|
pullup: 6,
|
||||||
|
intr: 2,
|
||||||
|
usedef: 4,
|
||||||
|
defval: 3,
|
||||||
|
},
|
||||||
|
cfgset:{
|
||||||
|
output: {
|
||||||
|
dir: 0, // 0 output,1 input
|
||||||
|
ivrt: 0,
|
||||||
|
pullup: 0,
|
||||||
|
intr: 0, // if intr = 0 usedef,deval not used
|
||||||
|
usedef: 0, // if usedef = 0 defval not used
|
||||||
|
defval: 0
|
||||||
|
},
|
||||||
|
toggle_switch: {
|
||||||
|
dir: 1, // 0 output,1 input
|
||||||
|
ivrt: 1, // for reading let 1 be zero and vice versa
|
||||||
|
pullup: 1,
|
||||||
|
intr: 1, // if intr = 0 usedef,deval not used
|
||||||
|
usedef: 0, // if usedef = 0 defval not used
|
||||||
|
defval: 0
|
||||||
|
},
|
||||||
|
momentary_switch: {
|
||||||
|
dir: 1, // 0 output,1 input
|
||||||
|
ivrt: 1, // for reading let 1 be zero and vice versa
|
||||||
|
pullup: 1,
|
||||||
|
intr: 1, // if intr = 0 usedef,deval not used
|
||||||
|
usedef: 1, // if usedef = 0 defval not used
|
||||||
|
defval: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cmd: {
|
||||||
|
intf: 7, // readonly
|
||||||
|
intcap: 8, // readonly
|
||||||
|
gpio: 9, // read/write
|
||||||
|
olat: 10 // read only
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
// import Base from '@uci/base'
|
// import Base from '@uci/base'
|
||||||
import Base from '../../uci-base/src/base'
|
import Base from '../../uci-base/src/base'
|
||||||
import pin from './pin'
|
import { pin, chip } from './commands'
|
||||||
import _ from '@uci/utils/src/byte'
|
|
||||||
|
|
||||||
import logger from '../../uci-logger/src/logger'
|
import logger from '../../uci-logger/src/logger'
|
||||||
let log = {}
|
let log = {}
|
||||||
|
@ -34,6 +33,7 @@ export default class MCP230XX extends Base {
|
||||||
if (!opts.address) log.fatal({opts:opts},'no i2c bus address supplied' )
|
if (!opts.address) log.fatal({opts:opts},'no i2c bus address supplied' )
|
||||||
this.address = opts.address
|
this.address = opts.address
|
||||||
this.pin = pin
|
this.pin = pin
|
||||||
|
this.chip = chip
|
||||||
this.busSend = this.busSend.bind(this)
|
this.busSend = this.busSend.bind(this)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -42,13 +42,25 @@ export default class MCP230XX extends Base {
|
||||||
await super.init()
|
await super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
async busSend(packet) {
|
|
||||||
return await this.socket.bus.send(packet)}
|
|
||||||
|
|
||||||
reply (packet) {
|
// this services the reply from the bus
|
||||||
console.log('in bus reply', packet)
|
reply (bus_packet) {
|
||||||
// this.emit('bus', packet)
|
this.emit(bus_packet.id, bus_packet)
|
||||||
this.emit(packet.id, packet)
|
}
|
||||||
|
|
||||||
|
async busSend(packet) {
|
||||||
|
return new Promise( async (resolve) => {
|
||||||
|
setTimeout(() => {resolve({error:'no response from bus in 10sec'})},10000)
|
||||||
|
packet.id = Math.random().toString().slice(2)
|
||||||
|
// console.log('sending to bus', packet.id)
|
||||||
|
this.socket.bus.send(packet)
|
||||||
|
this.on(packet.id,function(bus_reply){
|
||||||
|
// console.log('reply emitted',bus_reply)
|
||||||
|
this.removeAllListeners(bus_reply.id)
|
||||||
|
delete bus_reply.id
|
||||||
|
resolve(bus_reply)
|
||||||
|
}) //end listener
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// setBusListener(packet) {
|
// setBusListener(packet) {
|
||||||
|
|
56
src/pin.mjs
56
src/pin.mjs
|
@ -1,56 +0,0 @@
|
||||||
// All the pin functions for corresponding packet cmd:'pin'
|
|
||||||
// every function should return a packet ready to send to the i2c-bus socket
|
|
||||||
// export {pin}
|
|
||||||
|
|
||||||
const pin = {
|
|
||||||
cfg: function(packet){
|
|
||||||
return new Promise( async (resolve) => {
|
|
||||||
console.log(packet)
|
|
||||||
return resolve()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
test: function(packet){
|
|
||||||
return new Promise( async (resolve, reject) => {
|
|
||||||
setTimeout(() => {reject({error:'no response from bus in 2000ms'})},2000)
|
|
||||||
let id = Math.random().toString().slice(2)
|
|
||||||
let buspacket = {cmd:'scan', id:id}
|
|
||||||
console.log('packet for bus', buspacket)
|
|
||||||
this.busSend(buspacket)
|
|
||||||
this.on(buspacket.id,function(busreply){
|
|
||||||
console.log('reply emitted',busreply)
|
|
||||||
this.removeAllListeners(busreply.id)
|
|
||||||
let res = { cmd:'reply', _req:packet, _reqBus:buspacket}
|
|
||||||
if (busreply.response.indexOf(parseInt(this.address,16))!=-1) res.ready = true
|
|
||||||
res.address = this.address
|
|
||||||
console.log(res)
|
|
||||||
resolve(res)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
status: function(packet){
|
|
||||||
return new Promise( async (resolve) => {
|
|
||||||
console.log(packet)
|
|
||||||
return resolve()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// // state is equivalent to read
|
|
||||||
// status: packet => {
|
|
||||||
// },
|
|
||||||
// // threse three only for output pins
|
|
||||||
// state : {
|
|
||||||
// on: packet => {
|
|
||||||
// },
|
|
||||||
// off: packet => {
|
|
||||||
// },
|
|
||||||
// toggle: packet => {
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// // will create packet to determin pin caused interrupt, packet will come from interrupt module
|
|
||||||
// interrupt: {
|
|
||||||
// find: packet =>{},
|
|
||||||
// report: packet=>{} // come here after determining which pin to report to requester
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
export default pin
|
|
Loading…
Reference in New Issue