initial
commit
4c08f12300
|
@ -0,0 +1,2 @@
|
||||||
|
/node_modules/
|
||||||
|
/coverage/
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"globals": {
|
||||||
|
"Debug" : true,
|
||||||
|
/* MOCHA */
|
||||||
|
"describe" : false,
|
||||||
|
"it" : false,
|
||||||
|
"xit" : false,
|
||||||
|
"before" : false,
|
||||||
|
"beforeEach" : false,
|
||||||
|
"after" : false,
|
||||||
|
"afterEach" : false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
tests/
|
||||||
|
test/
|
||||||
|
*.test.js
|
||||||
|
testing/
|
|
@ -0,0 +1,14 @@
|
||||||
|
language: node_js
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- '4.0'
|
||||||
|
- '5.0'
|
||||||
|
- '6.0'
|
||||||
|
- 'node'
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script: npm test
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash) || echo "Codecov did not collect coverage reports"
|
|
@ -0,0 +1,8 @@
|
||||||
|
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);
|
|
@ -0,0 +1,146 @@
|
||||||
|
'use strict'
|
||||||
|
const Device = require('./device').Device,
|
||||||
|
Port = require('./gpio').Port,
|
||||||
|
_u = require('uci-utils')
|
||||||
|
|
||||||
|
const pSeries = require('p-series');
|
||||||
|
|
||||||
|
class MCP23008 extends Device {
|
||||||
|
constructor(busObj, i2cAddress, opts) {
|
||||||
|
super(busObj, i2cAddress, opts)
|
||||||
|
// opts could pass in array of custom pin config, or single for all, or anything
|
||||||
|
// this.registers = registers // load in register database
|
||||||
|
this.ports = {}
|
||||||
|
opts.portID = 'A'
|
||||||
|
this.ports.A = new Port(opts)
|
||||||
|
// if not specified there RPi is not managing the interrupt
|
||||||
|
// pin number on RPi that is connected to and services the interrupt. 4/17/27/22 = 7/11/13/15
|
||||||
|
this.ports.A.interPin = opts.interPin
|
||||||
|
} // end constructor
|
||||||
|
|
||||||
|
init() {
|
||||||
|
console.log('chip ', chip_config.cmd, chipSetByte())
|
||||||
|
return this.write(chip_config.cmd, chipSetByte()) // configure chip
|
||||||
|
.then(this.writePinsCfg())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pin(id) { return this.ports.A.pin(id) } // get a reference to a particular pin's object
|
||||||
|
|
||||||
|
// pin configurations should already be set before calling
|
||||||
|
writePinsCfg() {
|
||||||
|
let jobs = [];
|
||||||
|
for (let port in this.ports) {
|
||||||
|
for (let setting in registers.pin_config) {
|
||||||
|
let reg = registers.pin_config[setting]
|
||||||
|
if (port === 'B') { reg = reg + 16 }
|
||||||
|
let byte = 0;
|
||||||
|
let pins = this.ports[port].allPins
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
let pin = pins[i]
|
||||||
|
byte += pin.address.toFmt('DEC') * pin.cfg[setting]
|
||||||
|
}
|
||||||
|
// console.log(`port ${port} - setting ${setting} - reg ${reg} - byte ${byte}`)
|
||||||
|
jobs.push(
|
||||||
|
() => this.write(reg, byte) // .then((resp)=>console.log(`done writing config ${resp}`))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pSeries(jobs)
|
||||||
|
} // end writePinsCfg
|
||||||
|
|
||||||
|
pinRead(id, opts) {
|
||||||
|
let mcpdev = this;
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
let cmd = opts.cmd ? opts.cmd : 'gpio'
|
||||||
|
let reg = registers.pin_cmd[cmd]
|
||||||
|
let gpio = mcpdev.pin(id, opts.port)
|
||||||
|
if (!gpio) {
|
||||||
|
reject('no pin found for given id')
|
||||||
|
}
|
||||||
|
if (gpio.port === 'B') {
|
||||||
|
reg = reg + 16
|
||||||
|
}
|
||||||
|
// call device class read
|
||||||
|
console.log('port - reg', gpio.port, reg)
|
||||||
|
return mcpdev.read(reg).then(resp => {
|
||||||
|
resp = _u.byteFormat(resp, { in: 'DEC',
|
||||||
|
out: 'ARY'
|
||||||
|
})
|
||||||
|
let addr = gpio.pin.address.toFmt('ARY')
|
||||||
|
console.log(addr)
|
||||||
|
console.log(resp)
|
||||||
|
resolve(_u.sum(_u.and(addr, resp))) // resolve 1 or 0
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(state => console.log(`pin state ${state}`))
|
||||||
|
.catch(err => console.log(err)) // end Promise
|
||||||
|
} // end pinRead
|
||||||
|
|
||||||
|
} // end 23008
|
||||||
|
module.exports.MCP23008 = MCP23008
|
||||||
|
|
||||||
|
class MCP23017 extends MCP23008 {
|
||||||
|
constructor(busObj, i2cAddress, opts) {
|
||||||
|
super(busObj, i2cAddress, opts)
|
||||||
|
// add a second port
|
||||||
|
|
||||||
|
opts.portID = 'B'
|
||||||
|
this.ports.B = new Port(opts)
|
||||||
|
this.ports.A.interPin = opts.interPin // if not specified the RPi is not managing the interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
pin(id, port) {
|
||||||
|
if (!port) {
|
||||||
|
return this.ports.A.pin(id) ? this.ports.A.pin(id) : this.ports.B.pin(id)
|
||||||
|
}
|
||||||
|
return this.ports[port].pin(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end MCP23017 Class
|
||||||
|
module.exports.MCP23017 = MCP23017
|
||||||
|
|
||||||
|
/* ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf
|
||||||
|
* or see MCP23017.pdf and MCP 23008.pdf in /docs
|
||||||
|
* see table 1.5 and details in sections 1.6.x following
|
||||||
|
* !!! for 23017 MUST initialize with bit 7 "BANK" of IOCON = 1 for the addresses below
|
||||||
|
* then for all registers add 16 (0x10) to each reg address to talk to PortB pins
|
||||||
|
* this will make reg addresses be equilvant for 23008 and PortA of 23017
|
||||||
|
* reg addresses in the config objects are all in Hexidecminal
|
||||||
|
*/
|
||||||
|
// Chip cConfiguration to be used with Register
|
||||||
|
let chip_config = {
|
||||||
|
// byte: ['NULL','INTPOL','ODR','HAEN','DISSLW','SEQOP','MIRROR','BANK'] // see page 18 of 23017 datasheet for 8 setting details
|
||||||
|
cmd: 0x0A, // IOCON
|
||||||
|
default: {
|
||||||
|
val: '10000000', // int pins connected, port A + 0x10 = Port B -- ignored by 23008
|
||||||
|
fmt: 'STR'
|
||||||
|
},
|
||||||
|
twoints: {
|
||||||
|
val: '00000001', // int pins separate, port A + 0x10 = Port B -- ignored by 23008
|
||||||
|
fmt: 'STR'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chipSetByte(setting = 'default') {
|
||||||
|
setting = chip_config[setting]
|
||||||
|
return _u.byteFormat(setting.val, { in: setting.fmt,
|
||||||
|
out: 'DEC'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let registers = {
|
||||||
|
pin_config: {
|
||||||
|
dir: 0,
|
||||||
|
ivrt: 1,
|
||||||
|
pullup: 6,
|
||||||
|
intr: 2,
|
||||||
|
usedef: 4,
|
||||||
|
defval: 3,
|
||||||
|
},
|
||||||
|
pin_cmd: {
|
||||||
|
intf: 7, // readonly
|
||||||
|
intcap: 8, // readonly
|
||||||
|
gpio: 9, // read/write
|
||||||
|
olat: 10 // read only
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "uci-mcp",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "classes and functions for use the MCP chips",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"testw": "./node_modules/.bin/mocha --reporter list --recursive --watch",
|
||||||
|
"test": "istanbul cover ./node_modules/.bin/_mocha test/ --report lcovonly -- -R spec --recursive && codecov || true"
|
||||||
|
},
|
||||||
|
"author": "David Kebler",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/uCOMmandIt/uci-mcp.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node.js",
|
||||||
|
"microchip",
|
||||||
|
"i2c"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/uCOMmandIt/uci-mcp/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/uCOMmandIt/uci-mcp#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"require-all": "git+https://github.com/dkebler/node-require-all.git#merge"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "^3.5.0",
|
||||||
|
"codecov": "^1.0.1",
|
||||||
|
"istanbul": "^0.4.5",
|
||||||
|
"mocha": "^3.2.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
# uCOMmandIt MCP - Micro Chip Library
|
||||||
|
|
||||||
|
[![Build Status](https://img.shields.io/travis/uCOMmandIt/uci-mcp.svg?branch=master)](https://travis-ci.org/uCOMmandIt/uci-mcp)
|
||||||
|
[![Inline docs](http://inch-ci.org/github/uCOMmandIt/uci-mcp.svg?branch=master)](http://inch-ci.org/github/uCOMmandIt/uci-mcp)
|
||||||
|
[![Dependencies](https://img.shields.io/david/uCOMmandIt/uci-mcp.svg)](https://david-dm.org/uCOMmandIt/uci-mcp)
|
||||||
|
[![devDependencies](https://img.shields.io/david/dev/uCOMmandIt/uci-mcp.svg)](https://david-dm.org/uCOMmandIt/uci-mcp?type=dev)
|
||||||
|
[![codecov](https://img.shields.io/codecov/c/github/uCOMmandIt/uci-mcp/master.svg)](https://codecov.io/gh/uCOMmandIt/uci-mcp)
|
||||||
|
|
||||||
|
**Classes and Library to Support Microchip corporation chips**
|
||||||
|
|
||||||
|
http://www.microchip.com/wwwproducts/en/mcp23017
|
||||||
|
http://www.microchip.com/wwwproducts/en/mcp23008
|
|
@ -0,0 +1,73 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const expect = require('chai').expect,
|
||||||
|
i2c = require('../class'),
|
||||||
|
_u = require('uci-utils')
|
||||||
|
|
||||||
|
let bus1 = new i2c.Bus(1)
|
||||||
|
|
||||||
|
// console.log(bus1)
|
||||||
|
// bus1.scan((devs)=>{console.log('devices: ', devs)})
|
||||||
|
//bus1.scan().then(results=>console.log(results))
|
||||||
|
|
||||||
|
describe('I2C Device Classes - ', function () {
|
||||||
|
|
||||||
|
let mcp17 = new i2c.MCP.MCP23017(bus1, 0x20, {
|
||||||
|
name: 'switches 1-16'
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('MCP23017 Class - ', function () {
|
||||||
|
|
||||||
|
it('can set and get a single pin config', function () {
|
||||||
|
expect(mcp17.pin(8).cfg.dir, "pin address getter failed").to.equal(0)
|
||||||
|
mcp17.portA.pin(8).cfg.dir = 1
|
||||||
|
console.log(mcp17.pin(8).cfg.dir)
|
||||||
|
|
||||||
|
// expect(mcp17.pin(8).config.dir, "pin address setter failed").to.equal(1)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a pin can access device methods when attached to a device', function () {
|
||||||
|
expect(mcp17.portA.pin(8).device.address.val).to.equal(mcp17.address.val)
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
let mcp8 = new i2c.MCP.MCP23008(bus1, 0x21, {
|
||||||
|
cfgDefault: 'output',
|
||||||
|
name: 'relay 1-8'
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('MCP23008 Class - ', function () {
|
||||||
|
|
||||||
|
mcp8.pin(8).dir = 1
|
||||||
|
it('can set and get a single pin config', function () {
|
||||||
|
expect(mcp8.port.pin(8).dir, "pin address getter failed").to.equal(1)
|
||||||
|
mcp8.port.pin(8).dir = 0
|
||||||
|
expect(mcp8.port.pin(8).dir, "pin address getter failed").to.equal(0)
|
||||||
|
expect(mcp8.port.pin(8).itr, "pin address getter failed").to.equal(Boolean(0))
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a pin can access device methods when attached to a device', function () {
|
||||||
|
expect(mcp17.portA.pin(8).device.address.val).to.equal(mcp17.address.val)
|
||||||
|
})
|
||||||
|
|
||||||
|
// console.log(bus1.bus.writeI2cBlock_p)
|
||||||
|
// mcp8.func()
|
||||||
|
|
||||||
|
const ADDR = 0x21,
|
||||||
|
DIR = 0x00,
|
||||||
|
RW = 0x09,
|
||||||
|
ALLPINS = 0x40,
|
||||||
|
NOPINS = 0x00
|
||||||
|
|
||||||
|
mcp8.write(DIR, 0x00).then(() =>
|
||||||
|
mcp8.write(RW, ALLPINS).then(() =>
|
||||||
|
mcp8.read(RW, ALLPINS).then((resp) => {
|
||||||
|
console.log('relays on', resp)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue