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