refactoring to include port/pin library. Moved some examples to become tests within repo
parent
0fb62e2db1
commit
1a97705ab5
13
.jshglobals
13
.jshglobals
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"globals": {
|
|
||||||
"Debug" : true,
|
|
||||||
/* MOCHA */
|
|
||||||
"describe" : false,
|
|
||||||
"it" : false,
|
|
||||||
"xit" : false,
|
|
||||||
"before" : false,
|
|
||||||
"beforeEach" : false,
|
|
||||||
"after" : false,
|
|
||||||
"afterEach" : false
|
|
||||||
}
|
|
||||||
}
|
|
70
.jshintrc
70
.jshintrc
|
@ -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
|
|
||||||
}
|
|
8
index.js
8
index.js
|
@ -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);
|
|
|
@ -1,9 +1,9 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
const Device = require('uci-dev').Device,
|
const Device = require('@uci/i2c').Device,
|
||||||
Port = require('uci-gpio').Port,
|
Port = require('./lib/port-pin').Port, // classes for MCP port and pins
|
||||||
_u = require('uci-utils'),
|
pinConfigs = require('./lib/port-pin').configs, // for export so pinConfigs can be accessed at runtime
|
||||||
pause = _u.pPause,
|
_u = require('@uci/utils'),
|
||||||
aseq = _u.aSeq
|
pause = _u.pPause
|
||||||
|
|
||||||
class MCP23008 extends Device {
|
class MCP23008 extends Device {
|
||||||
constructor(busObj, i2cAddress, opts = {}) {
|
constructor(busObj, i2cAddress, opts = {}) {
|
||||||
|
@ -77,18 +77,18 @@ class MCP23008 extends Device {
|
||||||
out: 'DEC'
|
out: 'DEC'
|
||||||
})
|
})
|
||||||
return this.write(chip_config.cmd, byte)
|
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
|
// pin configurations should already be set before calling
|
||||||
writePinsCfg() {
|
writePinsCfg() {
|
||||||
// console.log(`writing mcp pins config ${this.id}`)
|
// console.log(`writing mcp pins config ${this.id}`)
|
||||||
let jobs = [];
|
let jobs = []
|
||||||
for (let port in this.ports) {
|
for (let port in this.ports) {
|
||||||
for (let setting in registers.pin_config) {
|
for (let setting in registers.pin_config) {
|
||||||
let reg = registers.pin_config[setting]
|
let reg = registers.pin_config[setting]
|
||||||
// TODO 0x10 should be based on chip config
|
// TODO 0x10 should be based on chip config
|
||||||
let byte = 0;
|
let byte = 0
|
||||||
let pins = this.ports[port].allPins
|
let pins = this.ports[port].allPins
|
||||||
for (let i = 0; i < 8; i++) {
|
for (let i = 0; i < 8; i++) {
|
||||||
let pin = pins[i]
|
let pin = pins[i]
|
||||||
|
@ -109,9 +109,9 @@ class MCP23008 extends Device {
|
||||||
// return u_.byteFormat(this.cur, { in: this.format, out: format })
|
// 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) {
|
if ('AB'.indexOf(port) === -1) {
|
||||||
cmd = port ? port : "gpio"
|
cmd = port ? port : 'gpio'
|
||||||
port = 'A'
|
port = 'A'
|
||||||
}
|
}
|
||||||
let result = await this.read(portReg(registers.pin_cmd[cmd], port))
|
let result = await this.read(portReg(registers.pin_cmd[cmd], port))
|
||||||
|
@ -126,13 +126,13 @@ class MCP23008 extends Device {
|
||||||
if (op !== 'force') {
|
if (op !== 'force') {
|
||||||
byte = this.ports[port].state.bwOp(byte, op)
|
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' })}`)
|
console.log(`byte to write \n ${_u.byteFormat(byte, { in: 'DEC', out: 'PLC' })}`)
|
||||||
|
|
||||||
await this.write(portReg(registers.pin_cmd.gpio, port), byte)
|
await this.write(portReg(registers.pin_cmd.gpio, port), byte)
|
||||||
//update the saved state
|
//update the saved state
|
||||||
this.ports[port].state.value = byte
|
this.ports[port].state.value = byte
|
||||||
console.log("\n\n")
|
console.log('\n\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
async on(pins, port, format) {
|
async on(pins, port, format) {
|
||||||
|
@ -188,8 +188,6 @@ class MCP23008 extends Device {
|
||||||
|
|
||||||
} // end 23008
|
} // end 23008
|
||||||
|
|
||||||
module.exports.MCP23008 = MCP23008
|
|
||||||
|
|
||||||
class MCP23017 extends MCP23008 {
|
class MCP23017 extends MCP23008 {
|
||||||
constructor(busObj, i2cAddress, opts) {
|
constructor(busObj, i2cAddress, opts) {
|
||||||
super(busObj, i2cAddress, opts)
|
super(busObj, i2cAddress, opts)
|
||||||
|
@ -223,9 +221,15 @@ class MCP23017 extends MCP23008 {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end MCP23017 Class
|
} // end MCP23017 Class
|
||||||
module.exports.MCP23017 = MCP23017
|
|
||||||
|
|
||||||
// ==============================
|
// EXPORTS
|
||||||
|
module.exports = {
|
||||||
|
MCP23008,
|
||||||
|
MCP23017,
|
||||||
|
pinConfigs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local Functions and Settings=============================
|
||||||
|
|
||||||
function portReg(reg, port) {
|
function portReg(reg, port) {
|
||||||
// TODO what to return for port B will depend on chip configuration
|
// TODO what to return for port B will depend on chip configuration
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "uci-mcp",
|
"name": "@uci/mcp",
|
||||||
|
"main": "lib/mcp23008-17.js",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "classes and functions for use the MCP chips",
|
"description": "classes and functions for use the MCP chips",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
@ -24,10 +25,7 @@
|
||||||
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
|
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"p-series": "^1.0.0",
|
"p-series": "^1.0.0",
|
||||||
"require-all": "git+https://github.com/dkebler/node-require-all.git#merge",
|
"@uci/utils": "0.0.1"
|
||||||
"uci-dev": "0.0.1",
|
|
||||||
"uci-gpio": "0.0.1",
|
|
||||||
"uci-utils": "0.0.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"chai": "^3.5.0",
|
"chai": "^3.5.0",
|
||||||
|
|
|
@ -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 }
|
||||||
|
// }
|
|
@ -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
|
||||||
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const expect = require('chai').expect,
|
const expect = require('chai').expect,
|
||||||
_u = require('uci-utils'),
|
_u = require('@uci/utils'),
|
||||||
MCP = require('../lib/mcp23008-17')
|
MCP = require('../lib/mcp23008-17')
|
||||||
|
|
||||||
const bus = {}
|
const bus = {}
|
||||||
|
@ -47,16 +47,16 @@
|
||||||
describe('MCP23017 Class - ', function () {
|
describe('MCP23017 Class - ', function () {
|
||||||
|
|
||||||
it('can set and get a single pin config on both ports', 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(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)
|
expect(mcp17.pin(8).cfg.dir, 'pin config getter failed').to.equal(1)
|
||||||
mcp17.pin(8).cfg.dir = 0
|
mcp17.pin(8).cfg.dir = 0
|
||||||
expect(mcp17.pin(8).cfg.dir, "pin address setter failed").to.equal(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)
|
expect(mcp17.pin(8, 'B').cfg.dir, 'pin address getter port B failed').to.equal(1)
|
||||||
mcp17.pin(8, 'B').cfg.dir = 0
|
mcp17.pin(8, 'B').cfg.dir = 0
|
||||||
expect(mcp17.pin(8, 'B').config.dir, "pin address setter failed").to.equal(0)
|
expect(mcp17.pin(8, 'B').config.dir, 'pin address setter failed').to.equal(0)
|
||||||
});
|
})
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
||||||
let mcp8 = new MCP.MCP23008(bus, 0x21, {
|
let mcp8 = new MCP.MCP23008(bus, 0x21, {
|
||||||
pin_cfg_default: 'toggle_switch',
|
pin_cfg_default: 'toggle_switch',
|
||||||
|
@ -66,15 +66,15 @@
|
||||||
describe('MCP23008 Class - ', function () {
|
describe('MCP23008 Class - ', function () {
|
||||||
|
|
||||||
it('can set and get a single pin config', 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(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.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.ivrt, 'pin address getter failed').to.equal(1)
|
||||||
expect(mcp8.pin(8).cfg.usedef, "pin address getter failed").to.equal(0)
|
expect(mcp8.pin(8).cfg.usedef, 'pin address getter failed').to.equal(0)
|
||||||
mcp8.pin(8).cfg.dir = 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.dir, 'pin address setter failed').to.equal(0)
|
||||||
expect(mcp8.pin(8).cfg.ivrt, "pin address getter failed").to.equal(1)
|
expect(mcp8.pin(8).cfg.ivrt, 'pin address getter failed').to.equal(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
|
@ -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))
|
|
@ -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 }
|
||||||
|
}
|
Loading…
Reference in New Issue