diff --git a/.jshglobals b/.jshglobals deleted file mode 100644 index db4fe74..0000000 --- a/.jshglobals +++ /dev/null @@ -1,13 +0,0 @@ -{ -"globals": { - "Debug" : true, - /* MOCHA */ -"describe" : false, -"it" : false, -"xit" : false, -"before" : false, -"beforeEach" : false, -"after" : false, -"afterEach" : false - } -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index 29bdf7a..0000000 --- a/.jshintrc +++ /dev/null @@ -1,70 +0,0 @@ -{ - // https://gist.github.com/connor/1597131 - - // Globals - import repo spectific globals - - "extends": "./.jshglobals", - - // Settings - "passfail" : false, // Stop on first error. - "maxerr" : 100, // Maximum error before stopping. - - // Predefined globals whom JSHint will ignore. - "browser" : true, // Standard browser globals e.g. `window`, `document`. - "node" : true, - "rhino" : false, - "couch" : false, - "wsh" : true, // Windows Scripting Host. - - "jquery" : true, - "prototypejs" : false, - "mootools" : false, - "dojo" : false, - - - // Development. - "debug" : false, // Allow debugger statements e.g. browser breakpoints. - "devel" : true, // Allow developments statements e.g. `console.log();`. - - - // ECMAScript - "esversion" : 6, //use this in new version of jshint - "strict" : false, // Require `use strict` pragma in every file. - "globalstrict" : false, // Allow global "use strict" (also enables 'strict'). - - - // The Good Parts. - "asi" : true, // Tolerate Automatic Semicolon Insertion (no semicolons). - "laxbreak" : true, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. - "bitwise" : true, // Allow bitwise operators (&, |, ^, etc.). - "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. - "curly" : true, // Require {} for every new block or scope. - "eqeqeq" : true, // Require triple equals i.e. `===`. - "eqnull" : false, // Tolerate use of `== null`. - "evil" : false, // Tolerate use of `eval`. - "expr" : false, // Tolerate `ExpressionStatement` as Programs. - "forin" : false, // Tolerate `for in` loops without `hasOwnPrototype`. - "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` - "latedef" : false, // Prohipit variable use before definition. - "loopfunc" : false, // Allow functions to be defined within loops. - "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. - "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions. - "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`. - "scripturl" : true, // Tolerate script-targeted URLs. - "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. - "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. - "undef" : true, // Require all non-global variables be declared before they are used. - - - // Personal styling preferences. - "newcap" : false, // Require capitalization of all constructor functions e.g. `new F()`. - "noempty" : true, // Prohibit use of empty blocks. - "nonew" : true, // Prohibit use of constructors for side-effects. - "nomen" : true, // Prohibit use of initial or trailing underbars in names. - "onevar" : false, // Allow only one `var` statement per function. - "plusplus" : false, // Prohibit use of `++` & `--`. - "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. - "trailing" : true, // Prohibit trailing whitespaces. - "white" : false, // Check against strict whitespace and indentation rules. - "indent" : 2 // Specify indentation spacing -} diff --git a/index.js b/index.js deleted file mode 100644 index 90ae21c..0000000 --- a/index.js +++ /dev/null @@ -1,8 +0,0 @@ -let opts = { - dirname: __dirname + '/lib', - // http://stackoverflow.com/questions/2078915/a-regular-expression-to-exclude-a-word-string - filter: /^(?!index)([^\.].*)\.js?$/, - recursive: false, - merge: true // remove or comment to have each file in /lib be a prop/key in library...see node-require-all -} -module.exports = require('require-all')(opts); diff --git a/lib/mcp23008-17.js b/lib/mcp23008-17.js index 594d810..4efcbb3 100644 --- a/lib/mcp23008-17.js +++ b/lib/mcp23008-17.js @@ -1,9 +1,9 @@ 'use strict' -const Device = require('uci-dev').Device, - Port = require('uci-gpio').Port, - _u = require('uci-utils'), - pause = _u.pPause, - aseq = _u.aSeq +const Device = require('@uci/i2c').Device, + Port = require('./lib/port-pin').Port, // classes for MCP port and pins + pinConfigs = require('./lib/port-pin').configs, // for export so pinConfigs can be accessed at runtime + _u = require('@uci/utils'), + pause = _u.pPause class MCP23008 extends Device { constructor(busObj, i2cAddress, opts = {}) { @@ -77,18 +77,18 @@ class MCP23008 extends Device { out: 'DEC' }) return this.write(chip_config.cmd, byte) - .then(() => Promise.resolve(`mcp chip config: reg $ { chip_config.cmd } byte $ { byte } written `)) + .then(() => Promise.resolve('mcp chip config: reg $ { chip_config.cmd } byte $ { byte } written ')) } // pin configurations should already be set before calling writePinsCfg() { // console.log(`writing mcp pins config ${this.id}`) - let jobs = []; + let jobs = [] 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; + let byte = 0 let pins = this.ports[port].allPins for (let i = 0; i < 8; i++) { let pin = pins[i] @@ -109,9 +109,9 @@ class MCP23008 extends Device { // return u_.byteFormat(this.cur, { in: this.format, out: format }) // } - async readPort(port, cmd = "gpio") { + async readPort(port, cmd = 'gpio') { if ('AB'.indexOf(port) === -1) { - cmd = port ? port : "gpio" + cmd = port ? port : 'gpio' port = 'A' } let result = await this.read(portReg(registers.pin_cmd[cmd], port)) @@ -126,13 +126,13 @@ class MCP23008 extends Device { if (op !== 'force') { byte = this.ports[port].state.bwOp(byte, op) } - console.log("byte to write decimal \n", byte) + console.log('byte to write decimal \n', byte) console.log(`byte to write \n ${_u.byteFormat(byte, { in: 'DEC', out: 'PLC' })}`) await this.write(portReg(registers.pin_cmd.gpio, port), byte) //update the saved state this.ports[port].state.value = byte - console.log("\n\n") + console.log('\n\n') } async on(pins, port, format) { @@ -188,8 +188,6 @@ class MCP23008 extends Device { } // end 23008 -module.exports.MCP23008 = MCP23008 - class MCP23017 extends MCP23008 { constructor(busObj, i2cAddress, opts) { super(busObj, i2cAddress, opts) @@ -223,9 +221,15 @@ class MCP23017 extends MCP23008 { } } // end MCP23017 Class -module.exports.MCP23017 = MCP23017 -// ============================== +// EXPORTS +module.exports = { + MCP23008, + MCP23017, + pinConfigs +} + +// Local Functions and Settings============================= function portReg(reg, port) { // TODO what to return for port B will depend on chip configuration diff --git a/lib/port-pin.js b/lib/port-pin.js new file mode 100644 index 0000000..b3f9f57 --- /dev/null +++ b/lib/port-pin.js @@ -0,0 +1,176 @@ +'use strict' + +const _ = require('@uci/utils') + +class Pin { + + constructor(address, opts = {}) { + // at a minimum address is required + this.address = new _.Byte(address, opts.fmt) + // a unique pin id MUST be supplied in opts or it must be set afterwards! + this.id = opts.pid + // a custom pin configuration can be passed or choosen from one of the sets, if neither than the default output config is chosen + if (opts.pin_cfg_default) { + if (_.keyExists(config_sets, opts.pin_cfg_default)) { + this.config = _.clone(config_sets[opts.pin_cfg_default]) + } else { + console.log(`WARNING config set ${opts.pin_cfg_default} not found using default output set`) + this.config = _.clone(config_sets.output) + } + } else { + this.config = _.clone(config_sets.output) + } + // after setting a default overwrite part or all of pin config with custom + if (opts.pinConfig) { + this.config = Object.assign(this.config, opts.pinConfig) + } + // this.cfgSet = false // set to true when for sure the configuration has been written, changed to false when config is changed. + } + + //getters and setters + get adr() { + return this.address + } + + set adr(add) { + if (Number.isInteger(add)) { + this.address.reset(add) + } else { + this.address.reset(add.val, add.fmt) + } + } + + get pid() { return this.id } + + set pid(pid) { this.id = pid } + + // config getters and setters + get cfg() { + return this.config + } + set cfg(config) { + this.config = _.merge(this.config, config) // this merges partial changes + // write the config here. + } + + show() { + console.log(`=====Pin ${this.id} =====\nAddress ${this.address.toFmt('HEX')}`) + console.log('Conifguration: ', this.config) + + } + +} // End GPIO Pin + +//====================== + +// A port of 8 GPIO pins +class Port { + + constructor(opts) { + + if (opts) { + this.reverse = opts.reverse ? opts.reverse : false + this.id = opts.portID ? opts.portID : '' + this.desc = opts.portDesc ? opts.portDesc : '' + } else { + opts = {} + this.reverse = false + } + // Create group of 8 pins for port + this.pins = new Array(8) + let pid = '' + for (let i = 0; i < 8; i++) { + if (opts.pids) { + pid = opts.pids[i] + } else { + pid = this.reverse ? 8 - i : i + 1 + } + // using default decimal for pin addresses + this.pins[i] = new Pin(Math.pow(2, i), _.merge(opts, { pid: pid })) + // console.log(`\n\n====PORT ${this.id} =====`) + // this.pins[i].show() + } + } + // return a handle to all pins on a port + get allPins() { + return this.pins + } + + // return handle to a port's pin from id + pin(id) { + for (let i = 0; i < 8; i++) { + + if (this.pins[i].id === id) { + return this.pins[i] + } + } + return false + } + // return pin's id on a port from address + pid(address) { + if (Number.isInteger(address)) { address = new _.Byte(address) } + let i = address.toFmt('PLC')[0] - 1 + return this.pins[i].id + } + +} // end GPIO Port CLass + +//==================== + +// needs to take current pin and pick out details and make a call the contstructor. +// clone(adr, alias) { +// let newPin = _.clone(this) +// newPin.address = adr +// newPin.alias = alias +// return newPin +// } + +// return list of all pin configs, handle to particular config or adding of custom pin configuration at runtime +function configs(cfg) { + if (_.isString(cfg)) { + if (cfg === 'list') { + return Object.keys(config_sets) + } + if (_.keyExists(config_sets, cfg)) { + return config_sets[cfg] + } + return 'configuration no found' + } + _.merge(config_sets, cfg) + // console.log(config_sets) + return `pin configuration ${Object.keys(cfg)} added to configuration set` +} + +module.exports = { + Port, + Pin, + configs +} + +let config_sets = { + + 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 + } +} diff --git a/package.json b/package.json index d42ede4..7ba10d5 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { - "name": "uci-mcp", + "name": "@uci/mcp", + "main": "lib/mcp23008-17.js", "version": "0.0.1", "description": "classes and functions for use the MCP chips", "main": "index.js", @@ -24,10 +25,7 @@ "homepage": "https://github.com/uCOMmandIt/uci-mcp#readme", "dependencies": { "p-series": "^1.0.0", - "require-all": "git+https://github.com/dkebler/node-require-all.git#merge", - "uci-dev": "0.0.1", - "uci-gpio": "0.0.1", - "uci-utils": "0.0.1" + "@uci/utils": "0.0.1" }, "devDependencies": { "chai": "^3.5.0", diff --git a/test/cntrl.js b/test/cntrl.js new file mode 100644 index 0000000..ffd5ca7 --- /dev/null +++ b/test/cntrl.js @@ -0,0 +1,148 @@ +const Bus = require('@uci/i2c').Bus, + MCP = require('@uci/mcp'), + Interrupt = require('@uci/interrupt').Interrupt, + _ = require('@uci/utils'), + pause = _.pPause, + aseq = _.aSeq + +let bus = new Bus() + +// let itrProcess = function (port) { +// return this.read(portReg(0x07, port)).then(resp => { +// console.log(`port ${port} resp ${resp}`) +// let sw = this.pid(resp, port) +// console.log('switch fired', sw) +// this.pinRead(sw, { cmd: 'intcap' }).then((state) => { +// console.log('switch state at interrupt', state) +// return Promise.all([ +// updateRelays(sw, state), +// this.read(portReg(0x07, port)).then(_.pDelay(100)).then(() => { return this.inter(port).reset() }) +// ]) +// }) +// }) +// } + +let itrProcess1 = function (port) { + console.log(`handler1 fired for ${this.id} on port ${port}`) + this.interruptReset(port) + return Promise.resolve("handler fired promise returned") +} + +let itrProcess2 = function (port) { + console.log(`handler2 fired for ${this.id} on port ${port}`) + this.interruptReset(port) + return Promise.resolve("handler fired promise returned") +} + +let LOAD_BANKS = [ + { id: 'lb1', address: 0x24, desc: 'left cabinet lower bank' }, + { id: 'lb3', address: 0x25, desc: 'left cabinet upper bank' }, + { id: 'lb2', address: 0x26, desc: 'right cabinet lower bank' }, + { id: 'lb4', address: 0x27, desc: 'right cabinet upper bank' } +] + +let loadBanks = LOAD_BANKS.map((bank) => { + return new MCP.MCP23017(bus, bank.address, { + pin_cfg_default: 'output', + id: bank.id, + desc: bank.desc ? bank.desc : "" + }) +}) + +// loadBanks.forEach(bank => console.log(bank.id, bank.desc)) + +let SWITCH_BANKS = [ + { id: 'sb4', address: 0x23, desc: 'bottom left', interruptA: 19, interruptB: 26 }, // red, orange + { id: 'sb1', address: 0x20, desc: 'upper right', interruptA: 12, interruptB: 16 }, // purple, blue + { id: 'sb2', address: 0x21, desc: 'upper left', interruptA: 20, interruptB: 21 }, // yellow, orange + { id: 'sb3', address: 0x22, desc: 'bottom right', interruptA: 6, interruptB: 13 } //black, brown + +] + +let switchBanks = SWITCH_BANKS.map((bank) => { + return new MCP.MCP23017(bus, bank.address, { + pin_cfg_default: 'toggle_switch', + id: bank.id, + desc: bank.desc ? bank.desc : "", + interrupt: bank.interrupt ? new Interrupt(bank.interrupt, bank) : null, + interruptA: bank.interruptA ? new Interrupt(bank.interruptA, itrProcess1) : null, + interruptB: bank.interruptB ? new Interrupt(bank.interruptB, itrProcess2) : null, + pidsA: ['sw1', 'sw2', 'sw3', 'sw4', 'sw5', 'sw6', 'sw7', 'sw8'], + pidsB: ['sw9', 'sw10', 'sw11', 'sw12', 'sw13', 'sw14', 'sw15', 'sw16'] + // chip_config: 'oneint' + }) +}) + +// switchBanks.forEach(bank => console.log(bank.id, bank.desc, bank.inter('A').pin, bank.inter('B').pin)) + +async function init(bank) { + await bank.init() + console.log(`${bank.id} ${bank.desc} is initialized`) + // if (bank.id.charAt(0) === 's') { + // console.log(`bank ${bank.id} pi interrupt set for port A: on rpi pin ${bank.inter('A').pin_number}, for port B on rpi pin ${bank.inter('A').pin_number}`) + // console.log(`rpi pin mode port A ${bank.inter('A').sbc_interrupt.getMode()}`) + // } +} + +async function start(bank) { + await bank.start() +} + +async function go() { + await aseq(loadBanks.concat(switchBanks), init) + await aseq(loadBanks.concat(switchBanks), start) +} + +go().catch(err => console.log(err)) + +// init relay board +// bus.qAdd(relays.init() +// // .then((resp) => { console.log('relays back from init', resp) }) +// .catch((err) => console.log('====error====\n', err)) +// ) + +// init switch board +// bus.qAdd(sw1_16.init() +// .then((resp) => { +// console.log('switch initilized finished\n', resp) +// return sw1_16.start() +// // .then(resp => console.log(resp)) +// }) +// // .then(console.log(sw1_16.inter().fire())) +// .catch((err) => console.log('====error switch ====\n', err)) +// ) + +// +// let test = async(function () { +// return await (delay()) +// }) +// +// console.log(test()) + +// function temp() { return Promise.resolve('test') } + +// let resp = await relays.init() +// console.log("relays ready", resp ) +// console.log( await delay(5000) ) + +// sw1_16.inter('A').on('fired', (hook) => { +// console.log('interrupt fired', hook) +// process.bind(sw1_16)('A') +// .catch(err => console.log("error:", err)) +// }) +// +// sw1_16.inter('B').on('fired', (hook) => { +// console.log('interrupt fired', hook) +// process.bind(sw1_16)('B') +// .catch(err => console.log("error:", err)) +// }) + +// function updateRelays(sid, state) { +// console.log(`sw ${sid} state ${state}`) +// return bus.qAdd(relays.write(0x09, 0x03 * state)) +// // return _.pDelay(100).then((resp) => { console.log('relays updated') }) +// } +// +// function portReg(reg, port) { +// if (port === 'B') { return reg += 0x10 } else { return reg } +// } diff --git a/test/gpio.test.js b/test/gpio.test.js new file mode 100644 index 0000000..10d1d5f --- /dev/null +++ b/test/gpio.test.js @@ -0,0 +1,63 @@ +'use strict' + +const expect = require('chai').expect, + gpio = require('../lib/gpio') + +let pin = new gpio.Pin(128) + +describe('GPIO Pin Class - ', function () { + + it('Verify getter and setter ', function () { + expect(pin.cfg, 'config getter failed').to.deep.equal(gpio.configs('output')) + expect(pin.cfg.intr, 'config get subkeys failed').to.equal(0) + + pin.cfg = gpio.configs('toggle_switch') + expect(pin.cfg, 'config setter failed').to.deep.equal(gpio.configs('toggle_switch')) + expect(pin.adr.value, 'pin address getter failed').to.equal(128) + expect(pin.adr.fmt, 'pin address format getter failed').to.equal('DEC') + expect(pin.id, 'pin id default from address failed').to.equal(8) + pin.adr = { + 'val': 20, + 'fmt': 'HEX' + } + expect(pin.adr.value, 'pin address setter failed').to.equal(20) + expect(pin.adr.fmt, 'pin address format setter failed').to.equal('HEX') + pin.id = 2 + expect(pin.id, 'pin id setter failed').to.equal(2) + pin.adr = 32 + expect(pin.adr.value, 'pin address setter failed').to.equal(32) + expect(pin.adr.fmt, 'pin address format setter failed').to.equal('DEC') + }) + + it('should merge partial config change', function () { + pin.cfg = gpio.configs('output') + pin.cfg = { dir: 15 } + let merged = { dir: 15, ivrt: 0, pullup: 0, intr: 0, usedef: 0, defval: 0 } + expect(pin.cfg, 'single config value change failed').to.deep.equal(merged) + }) + + // TODO waiting on new clone function + // it('should clone a new Pin with change of address', function () { + // expect(newPin.adr.val, "clone pin failed").to.equal(4) + // expect(newPin.cfg.dir, "clone pin failed").to.equal(15) + // }) + +}) + +let port = new gpio.Port({ portID: 'A1' }) + +describe('GPIO Port Class - ', function () { + + it('should set the pin ids and addresses by default', function () { + expect(port.pin(7).id, 'a pin\'s id failed').to.equal(7) + expect(port.pin(7).adr.value, 'id and address don\'t match').to.equal(64) + }) + + let port2 = new gpio.Port({ reverse: true }) + + it('reversing pin number order should work', function () { + expect(port2.pin(2).adr.value, 'reversing pin numbers failed').to.equal(64) + }) + + //TODO add a pin map for the port so pins could be arranged in any order +}) diff --git a/test/mcp.test.js b/test/mcp.test.js index cd60249..81de301 100644 --- a/test/mcp.test.js +++ b/test/mcp.test.js @@ -1,80 +1,80 @@ - 'use strict' +'use strict' - const expect = require('chai').expect, - _u = require('uci-utils'), - MCP = require('../lib/mcp23008-17') +const expect = require('chai').expect, + _u = require('@uci/utils'), + MCP = require('../lib/mcp23008-17') - const bus = {} +const bus = {} - const config_sets = { - 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 - } - } +const config_sets = { + 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 + } +} - // console.log(bus1) - // bus1.scan((devs)=>{console.log('devices: ', devs)}) - //bus1.scan().then(results=>console.log(results)) +// console.log(bus1) +// bus1.scan((devs)=>{console.log('devices: ', devs)}) +//bus1.scan().then(results=>console.log(results)) - describe('I2C Device Classes - ', function () { +describe('I2C Device Classes - ', function () { - let mcp17 = new MCP.MCP23017(bus, 0x20, { - pin_cfg_default: 'momentary_switch', - name: 'switches 1-16' - }) + let mcp17 = new MCP.MCP23017(bus, 0x20, { + pin_cfg_default: 'momentary_switch', + name: 'switches 1-16' + }) - describe('MCP23017 Class - ', function () { + describe('MCP23017 Class - ', function () { - it('can set and get a single pin config on both ports', function () { - expect(mcp17.pin(1).cfg, "pin configs getter failed").to.deep.equal(config_sets.momentary_switch) - expect(mcp17.pin(8).cfg.dir, "pin config getter failed").to.equal(1) - mcp17.pin(8).cfg.dir = 0 - expect(mcp17.pin(8).cfg.dir, "pin address setter failed").to.equal(0) - expect(mcp17.pin(8, 'B').cfg.dir, "pin address getter port B failed").to.equal(1) - mcp17.pin(8, 'B').cfg.dir = 0 - expect(mcp17.pin(8, 'B').config.dir, "pin address setter failed").to.equal(0) - }); + it('can set and get a single pin config on both ports', function () { + expect(mcp17.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.momentary_switch) + expect(mcp17.pin(8).cfg.dir, 'pin config getter failed').to.equal(1) + mcp17.pin(8).cfg.dir = 0 + expect(mcp17.pin(8).cfg.dir, 'pin address setter failed').to.equal(0) + expect(mcp17.pin(8, 'B').cfg.dir, 'pin address getter port B failed').to.equal(1) + mcp17.pin(8, 'B').cfg.dir = 0 + expect(mcp17.pin(8, 'B').config.dir, 'pin address setter failed').to.equal(0) + }) - }); + }) - let mcp8 = new MCP.MCP23008(bus, 0x21, { - pin_cfg_default: 'toggle_switch', - name: 'test 1-8' - }) + let mcp8 = new MCP.MCP23008(bus, 0x21, { + pin_cfg_default: 'toggle_switch', + name: 'test 1-8' + }) - describe('MCP23008 Class - ', function () { + describe('MCP23008 Class - ', function () { - it('can set and get a single pin config', function () { - expect(mcp8.pin(1).cfg, "pin configs getter failed").to.deep.equal(config_sets.toggle_switch) - expect(mcp8.pin(8).cfg.dir, "pin address getter failed").to.equal(1) - expect(mcp8.pin(8).cfg.ivrt, "pin address getter failed").to.equal(1) - expect(mcp8.pin(8).cfg.usedef, "pin address getter failed").to.equal(0) - mcp8.pin(8).cfg.dir = 0 - expect(mcp8.pin(8).cfg.dir, "pin address setter failed").to.equal(0) - expect(mcp8.pin(8).cfg.ivrt, "pin address getter failed").to.equal(1) - }); + it('can set and get a single pin config', function () { + expect(mcp8.pin(1).cfg, 'pin configs getter failed').to.deep.equal(config_sets.toggle_switch) + expect(mcp8.pin(8).cfg.dir, 'pin address getter failed').to.equal(1) + expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1) + expect(mcp8.pin(8).cfg.usedef, 'pin address getter failed').to.equal(0) + mcp8.pin(8).cfg.dir = 0 + expect(mcp8.pin(8).cfg.dir, 'pin address setter failed').to.equal(0) + expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1) + }) - }); + }) - }); +}) diff --git a/test/relays.js b/test/relays.js new file mode 100644 index 0000000..53b1f42 --- /dev/null +++ b/test/relays.js @@ -0,0 +1,44 @@ +const Bus = require('@uci/i2c').Bus, + MCP = require('../lib/mcp'), + pause = require('@uci/utils').pPause + +let bus = new Bus() + +let ADDRS = [0x24, 0x25, 0x26, 0x27] + +let relayBanks = ADDRS.map(devAddr => { + return new MCP.MCP23017(bus, devAddr, { + pin_cfg_default: 'output', + desc: `relays at i2c address ${devAddr.toString(16)}`, + stateB: 255, // should be read from persistant state file for when power goes out + stateA: 255 + }) +}) + +async function go(port = 'A') { + let time = 1 + await relayBanks[0].init() + await pause(time * 1000) + await relayBanks[0].allOff(port) + await pause(time * 1000) + await relayBanks[0].on([1, 5, 8], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].on([1, 2, 5, 7, 8], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].off([1, 3, 5, 8], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].off([1, 3, 5, 8, 7, 2], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].toggle([1, 5, 7], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].toggle([1, 5, 8], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].toggle([8], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].force([3, 4], port, 'PLC') + await pause(time * 1000) + await relayBanks[0].allOn(port) +} + +go('B') // .then(resp => console.log(resp)) + .catch(reason => console.error(reason)) diff --git a/test/test-relays.js b/test/test-relays.js new file mode 100644 index 0000000..4761eba --- /dev/null +++ b/test/test-relays.js @@ -0,0 +1,85 @@ +const Bus = require('@uci/i2c').Bus, + MCP = require('@uci/mcp'), + _ = require('@uci/utils'), + pause = _.pPause, + pSeries = require('p-series') +const a = require('awaiting') + +let bus = new Bus() + +let ADDRS = [0x24, 0x25, 0x26, 0x27], + W = 0x09, + R = 0x0A, + WAIT = 1000 + +let relayBanks = ADDRS.map(devAddr => { + return new MCP.MCP23017(bus, devAddr, { + pin_cfg_default: 'output', + desc: `relays at i2c address ${devAddr.toString(16)}` + }) +}) + +async function testbank(bank) { + await bank.init() + console.log(`initialized ${bank.desc}...now testing device write and read`) + for (let port in bank.ports) { + let pinAddr = 0 + console.log(`Testing bank:${bank.desc} port:${port}`) + for (let i = 0; i < 8; i++) { + pinAddr = pinAddr + Math.pow(2, i) + let addr = pinAddr + await bank.write(portReg(W, port), pinAddr) + console.log(`Turning Port ${port} Pin(s) ${_.byteFormat(addr, { in: 'DEC', out: 'PLC' })} on`) + let resp = await bank.read(portReg(R, port), pinAddr) + // await pause(100) + console.log(`Port ${port} Pin(s) ${_.byteFormat(resp, { in: 'DEC', out: 'PLC' })} is/are on`) + await pause(100) + resp = await bank.write(portReg(W, port), 0x00) + console.log(`Clearing Relays On Port ${port} ${bank.desc}`) + await pause(500) + } + } + return `done ${bank.desc}` +} + +// function seq(list, fn) { +// return async function () { +// await a.map(list, 1, fn) +// } +// } + +async function aseq(list, fn) { + const resps = [] + for (const item of list) { + let resp = await fn(item); + resps.push(resp) + } + return resps +} + +async function testall() { + let resp = await aseq(relayBanks, testbank) + return resp +} + +// testall() +// .then(resp => console.log("All done", resp)) +// .catch(reason => console.error(reason)); + +async function readport(bank, port = 'A') { + let resp = await relayBanks[bank].readPins(port, { format: 'ARY', cmd: "olat" }) + return resp +} + +let bank = 1 +readport(bank, 'A') + .then(resp => { + console.log(`Reading Bank ${bank} pins ${resp.value} are on`) + }) + .catch(reason => console.error(reason)); + +//=========== + +function portReg(reg, port) { + if (port === 'B') { return reg += 0x10 } else { return reg } +}