From 8a9950459a07726e0d266299ba4d5d254fd08e2e Mon Sep 17 00:00:00 2001 From: David Kebler Date: Sat, 10 Feb 2018 15:28:51 -0800 Subject: [PATCH] basic commands working configure chip ack chip cfg pin change state of pin (on,off,toggle) --- examples/ipc-test.mjs | 42 +++++++++++-- examples/mcp.mjs | 2 +- package.json | 3 +- src/commands.mjs | 128 ++++++++++++++++++++++++++++++++++++++++ src/config.mjs | 58 ++++++++++++++++++ src/mcp230xx-packet.mjs | 28 ++++++--- src/pin.mjs | 56 ------------------ 7 files changed, 247 insertions(+), 70 deletions(-) create mode 100644 src/commands.mjs create mode 100644 src/config.mjs delete mode 100644 src/pin.mjs diff --git a/examples/ipc-test.mjs b/examples/ipc-test.mjs index d84ffa4..1bea959 100644 --- a/examples/ipc-test.mjs +++ b/examples/ipc-test.mjs @@ -15,11 +15,45 @@ const delay = time => new Promise(res=>setTimeout(()=>res(),time)) await mcpclient.init() console.log('=============sending============') - let packet = {cmd:'pin.test'} - console.dir(packet) - await mcpclient.send(packet) + // let packet = {cmd:'chip.ack'} + // console.dir(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') diff --git a/examples/mcp.mjs b/examples/mcp.mjs index df98a52..f21a1d0 100644 --- a/examples/mcp.mjs +++ b/examples/mcp.mjs @@ -8,7 +8,7 @@ import MCP230XX from '../src/mcp230xx-packet' ; (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() diff --git a/package.json b/package.json index 02f7a7d..b67cb39 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "dependencies": { "@uci/i2c": "^0.1.0", "@uci/utils": "^0.1.0", - "aggregation": "^1.2.0" + "aggregation": "^1.2.0", + "bitwise": "^1.3.0" }, "@std/esm": "cjs", "devDependencies": { diff --git a/src/commands.mjs b/src/commands.mjs new file mode 100644 index 0000000..d7af162 --- /dev/null +++ b/src/commands.mjs @@ -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 +} diff --git a/src/config.mjs b/src/config.mjs new file mode 100644 index 0000000..133352f --- /dev/null +++ b/src/config.mjs @@ -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 + } +} diff --git a/src/mcp230xx-packet.mjs b/src/mcp230xx-packet.mjs index ecc49df..14a25c6 100644 --- a/src/mcp230xx-packet.mjs +++ b/src/mcp230xx-packet.mjs @@ -1,7 +1,6 @@ // import Base from '@uci/base' import Base from '../../uci-base/src/base' -import pin from './pin' -import _ from '@uci/utils/src/byte' +import { pin, chip } from './commands' import logger from '../../uci-logger/src/logger' let log = {} @@ -34,6 +33,7 @@ export default class MCP230XX extends Base { if (!opts.address) log.fatal({opts:opts},'no i2c bus address supplied' ) this.address = opts.address this.pin = pin + this.chip = chip this.busSend = this.busSend.bind(this) } @@ -42,13 +42,25 @@ export default class MCP230XX extends Base { await super.init() } - async busSend(packet) { - return await this.socket.bus.send(packet)} - reply (packet) { - console.log('in bus reply', packet) - // this.emit('bus', packet) - this.emit(packet.id, packet) + // this services the reply from the bus + reply (bus_packet) { + this.emit(bus_packet.id, bus_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) { diff --git a/src/pin.mjs b/src/pin.mjs deleted file mode 100644 index f37758d..0000000 --- a/src/pin.mjs +++ /dev/null @@ -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