chip-io
Advanced tools
Comparing version 2.1.0 to 2.1.1
@@ -0,1 +1,7 @@ | ||
## Version 2.1.1 | ||
* Added new on-board button and status LED example. ([@norgeous](https://github.com/norgeous)) | ||
* Switch to `i2c-bus` module for I2C layer. ([@fivdi](https://github.com/fivdi)) | ||
* Throw exception for `pingRead`. | ||
## Version 2.1.0 | ||
@@ -2,0 +8,0 @@ |
var events = require('events'); | ||
var util = require('util'); | ||
var i2cBus = require('i2c-bus'); | ||
var I2C = require('./i2c'); | ||
var BUTTON_REGISTER = 0x4a; | ||
var INT_TEMP_MSB_REGISTER = 0x5e; | ||
var INT_TEMP_LSB_REGISTER = 0x5f; | ||
var BAT_VOLT_MSB_REGISTER = 0x78; | ||
var BAT_VOLT_LSB_REGISTER = 0x79; | ||
var BAT_ADC_REGISTER = 0x82; | ||
@@ -15,4 +12,5 @@ var GPIO2_REGISTER = 0x93; | ||
function AXP209(bus, address) { | ||
this._i2c = new I2C(bus, address); | ||
this._bus = bus; | ||
this._address = address; | ||
this._i2c = null; | ||
this._reads = {}; | ||
@@ -24,3 +22,3 @@ } | ||
AXP209.prototype.open = function() { | ||
this._i2c.open(); | ||
this._i2c = i2cBus.openSync(this._bus, {forceAccess: true}); | ||
}; | ||
@@ -48,42 +46,81 @@ | ||
AXP209.prototype.tick = function() { | ||
AXP209.prototype.tick = function(callback) { | ||
var readsRunning = 0; | ||
var afterRead = function() { | ||
readsRunning -= 1; | ||
if (readsRunning === 0) { | ||
callback(); | ||
} | ||
}; | ||
if (this._reads.BAT) { | ||
var batVolt = this._readBatVolt(); | ||
readsRunning += 1; | ||
this.emit('analog-read', 'BAT', batVolt); | ||
this._readBatVolt(function(err, batVolt) { | ||
if (!err) { | ||
this.emit('analog-read', 'BAT', batVolt); | ||
} | ||
afterRead(); | ||
}.bind(this)); | ||
} | ||
if (this._reads.INTTEMP) { | ||
var intTemp = this._readIntTemp(); | ||
readsRunning += 1; | ||
this.emit('analog-read', 'INTTEMP', intTemp); | ||
this._readIntTemp(function(err, intTemp) { | ||
if (!err) { | ||
this.emit('analog-read', 'INTTEMP', intTemp); | ||
} | ||
afterRead(); | ||
}.bind(this)); | ||
} | ||
if (this._reads.BTN) { | ||
var button = this._readButton(); | ||
readsRunning += 1; | ||
this.emit('digital-read', 'BTN', button); | ||
this._readButton(function(err, button) { | ||
if (!err) { | ||
this.emit('digital-read', 'BTN', button); | ||
} | ||
afterRead(); | ||
}.bind(this)); | ||
} | ||
// if there's nothing to do the callback also needs to be called | ||
if (readsRunning === 0) { | ||
process.nextTick(callback); | ||
} | ||
}; | ||
AXP209.prototype.close = function() { | ||
this._i2c.close(); | ||
this._i2c.closeSync(); | ||
}; | ||
AXP209.prototype._readIntTemp = function() { | ||
return this._readAdc(INT_TEMP_MSB_REGISTER, INT_TEMP_LSB_REGISTER); | ||
AXP209.prototype._readIntTemp = function(callback) { | ||
this._readAdc(INT_TEMP_MSB_REGISTER, callback); | ||
}; | ||
AXP209.prototype._readBatVolt = function() { | ||
return this._readAdc(BAT_VOLT_MSB_REGISTER, BAT_VOLT_LSB_REGISTER); | ||
AXP209.prototype._readBatVolt = function(callback) { | ||
this._readAdc(BAT_VOLT_MSB_REGISTER, callback); | ||
}; | ||
AXP209.prototype._readButton = function() { | ||
var value = (this._i2c.readRegister(BUTTON_REGISTER, 1)[0] & 0x02) !== 0; | ||
AXP209.prototype._readButton = function(callback) { | ||
this._i2c.readByte(this._address, BUTTON_REGISTER, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (value) { | ||
this._i2c.writeRegister(BUTTON_REGISTER, new Buffer([0x02])); | ||
} | ||
var value = (data & 0x02) !== 0; | ||
return (value ? 1 : 0); | ||
if (value) { | ||
this._i2c.writeByteSync(this._address, BUTTON_REGISTER, 0x02); | ||
} | ||
callback(null, value ? 1 : 0); | ||
}.bind(this)); | ||
}; | ||
@@ -93,16 +130,23 @@ | ||
// force ADC enable for battery voltage and current | ||
return this._i2c.writeRegister(BAT_ADC_REGISTER, new Buffer([0xc3])); | ||
this._i2c.writeByteSync(this._address, BAT_ADC_REGISTER, 0xc3); | ||
}; | ||
AXP209.prototype._writeGpio2 = function(value) { | ||
this._i2c.writeRegister(GPIO2_REGISTER, new Buffer([value])); | ||
this._i2c.writeByteSync(this._address, GPIO2_REGISTER, value); | ||
}; | ||
AXP209.prototype._readAdc = function(msbRegister, lsbRegister) { | ||
msbData = this._i2c.readRegister(msbRegister, 1); | ||
lsbData = this._i2c.readRegister(lsbRegister, 1); | ||
AXP209.prototype._readAdc = function(msbRegister, callback) { | ||
var adcData = new Buffer(2); | ||
return ((msbData[0] << 4) | (lsbData[0] & 0x0f)); | ||
this._i2c.readI2cBlock(this._address, msbRegister, 2, adcData, function(err, bytesRead, adcData) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var value = (adcData[0] << 4) | (adcData[1] & 0x0f); | ||
callback(null, value); | ||
}); | ||
}; | ||
module.exports = AXP209; |
@@ -5,4 +5,4 @@ var util = require('util'); | ||
var debug = require('debug')('chip-io'); | ||
var i2cBus = require('i2c-bus'); | ||
var I2C = require('./i2c'); | ||
var AllwinnnerR8 = require('./allwinner-r8'); | ||
@@ -15,2 +15,3 @@ var AXP209 = require('./axp209'); | ||
var TICK_INTERVAL = 19; | ||
var DEFAULT_BUS = 2; | ||
var addressToBus = {}; | ||
@@ -54,3 +55,3 @@ | ||
this._i2cReads = []; | ||
this._i2cBuses = {}; | ||
@@ -182,47 +183,64 @@ this._chips = { | ||
// options.address is _always_ sent by all I2C component | ||
// classes in Johnny-Five. | ||
// If a bus was sent, then we need to associate the address to the bus. | ||
if (options.bus && !addressToBus.hasOwnProperty(options.address)) { | ||
addressToBus[options.address] = options.bus; | ||
// note that there's a design flaw here | ||
// two devices with the same address on different buses doesn't work | ||
// see https://github.com/rwaldron/io-plugins/issues/13 | ||
// options.address is _always_ sent by all I2C component classes in | ||
// Johnny-Five | ||
var address = options.address; | ||
// options.bus is optional | ||
var bus = typeof(options.bus) !== 'undefined' ? options.bus : DEFAULT_BUS; | ||
// associate the address to the bus | ||
if (!addressToBus.hasOwnProperty(address)) { | ||
addressToBus[address] = bus; | ||
} | ||
// create an i2c-bus object for the I2C bus | ||
if (!this._i2cBuses.hasOwnProperty(bus)) { | ||
this._i2cBuses[bus] = i2cBus.openSync(bus); | ||
} | ||
return this; | ||
}; | ||
ChipIO.prototype.i2cWrite = function(address, register, data) { | ||
if (arguments.length === 2) { | ||
data = register; | ||
register = null; | ||
} | ||
ChipIO.prototype.i2cWrite = function(address, cmdRegOrData, inBytes) { | ||
debug('i2cWrite', address, cmdRegOrData, inBytes); | ||
debug('i2cWrite', address, register, data); | ||
var i2c = this._i2cBuses[addressToBus[address]]; | ||
var bus = typeof(addressToBus[address]) !== 'undefined' ? addressToBus[address] : 2; | ||
var i2c = new I2C(bus, address); | ||
// if i2cWrite was used for an i2cWriteReg call... | ||
if (arguments.length === 3 && | ||
!Array.isArray(cmdRegOrData) && | ||
!Array.isArray(inBytes)) { | ||
return this.i2cWriteReg(address, cmdRegOrData, inBytes); | ||
} | ||
if (typeof(data) === 'number') { | ||
data = [data]; | ||
// fix arguments if called with Firmata.js API | ||
if (arguments.length === 2) { | ||
if (Array.isArray(cmdRegOrData)) { | ||
inBytes = cmdRegOrData.slice(); | ||
cmdRegOrData = inBytes.shift(); | ||
} else { | ||
inBytes = []; | ||
} | ||
} | ||
data = new Buffer(data); | ||
var buffer = new Buffer([cmdRegOrData].concat(inBytes)); | ||
i2c.open(); | ||
if (register !== null) { | ||
i2c.writeRegister(register, data); | ||
} else { | ||
i2c.write(data); | ||
// only write if bytes provided | ||
if (buffer.length) { | ||
i2c.i2cWriteSync(address, buffer.length, buffer); | ||
} | ||
i2c.close(); | ||
return this; | ||
}; | ||
ChipIO.prototype.i2cWriteReg = function(address, register, data) { | ||
debug('i2cWriteReg', address, register, data); | ||
ChipIO.prototype.i2cWriteReg = function(address, register, byte) { | ||
debug('i2cWriteReg', address, register, byte); | ||
this.i2cWrite(address, register, data); | ||
var i2c = this._i2cBuses[addressToBus[address]]; | ||
i2c.writeByteSync(address, register, byte); | ||
return this; | ||
@@ -234,4 +252,11 @@ }; | ||
this._i2cReads.push(arguments); | ||
var continuousRead = function() { | ||
this.i2cReadOnce(address, register, size, function(bytes) { | ||
handler(bytes); | ||
setTimeout(continuousRead, TICK_INTERVAL); | ||
}); | ||
}.bind(this); | ||
continuousRead(); | ||
return this; | ||
@@ -241,3 +266,6 @@ }; | ||
ChipIO.prototype.i2cReadOnce = function(address, register, size, handler) { | ||
if (arguments.length === 3) { | ||
// fix arguments if called with Firmata.js API | ||
if (arguments.length === 3 && | ||
typeof register === "number" && | ||
typeof size === "function") { | ||
handler = size; | ||
@@ -250,39 +278,48 @@ size = register; | ||
var bus = typeof(addressToBus[address]) !== 'undefined' ? addressToBus[address] : 2; | ||
var i2c = new I2C(bus, address); | ||
var event; | ||
var data; | ||
var event = "I2C-reply" + address + "-" + (register !== null ? register : 0); | ||
i2c.open(); | ||
var afterRead = function (err, bytesRead, buffer) { | ||
if (err) { | ||
return this.emit("error", err); | ||
} | ||
// convert buffer to an Array before emit | ||
this.emit(event, Array.prototype.slice.call(buffer)); | ||
}.bind(this); | ||
if (typeof handler === "function") { | ||
this.once(event, handler); | ||
} | ||
var i2c = this._i2cBuses[addressToBus[address]]; | ||
var data = new Buffer(size); | ||
if (register !== null) { | ||
event = 'I2C-reply-' + address + '-' + register; | ||
data = i2c.readRegister(register, size); | ||
i2c.readI2cBlock(address, register, size, data, afterRead); | ||
} else { | ||
event = 'I2C-reply-' + address; | ||
data = i2c.read(size); | ||
i2c.i2cRead(address, size, data, afterRead); | ||
} | ||
i2c.close(); | ||
this.once(event, handler); | ||
process.nextTick(function(event, data) { | ||
this.emit(event, data); | ||
}.bind(this, event, data)); | ||
return this; | ||
}; | ||
ChipIO.prototype.pingRead = function() { | ||
throw new Error('pingRead is not supported! Please use an I2C backpack: http://johnny-five.io/examples/proximity-hcsr04-i2c/'); | ||
}; | ||
ChipIO.prototype._tick = function() { | ||
this._chips.AXP209.tick(); | ||
this._chips.PCF8574A.tick(); | ||
this._chips.R8.tick(); | ||
var asyncTicksRunning = 2; | ||
for (var j = 0; j < this._i2cReads.length; j++) { | ||
this.i2cReadOnce.apply(this, this._i2cReads[j]); | ||
} | ||
var afterTick = function() { | ||
asyncTicksRunning -= 1; | ||
// schedule next tick | ||
this._tickTimeout = setTimeout(this._tick.bind(this), TICK_INTERVAL); | ||
if (asyncTicksRunning === 0) { | ||
// schedule next tick | ||
this._tickTimeout = setTimeout(this._tick.bind(this), TICK_INTERVAL); | ||
} | ||
}.bind(this); | ||
this._chips.AXP209.tick(afterTick); | ||
this._chips.PCF8574A.tick(afterTick); | ||
this._chips.R8.tick(); | ||
}; | ||
@@ -289,0 +326,0 @@ |
var events = require('events'); | ||
var util = require('util'); | ||
var i2cBus = require('i2c-bus'); | ||
var I2C = require('./i2c'); | ||
function PCF8574A(bus, address) { | ||
this._i2c = new I2C(bus, address); | ||
this._bus = bus; | ||
this._address = address; | ||
this._i2c = null; | ||
this._writeMask = 0; | ||
@@ -15,6 +15,6 @@ this._readMask = 0; | ||
PCF8574A.prototype.open = function(callback) { | ||
this._i2c.open(); | ||
PCF8574A.prototype.open = function() { | ||
this._i2c = i2cBus.openSync(this._bus, {forceAccess: true}); | ||
this._i2c.write(0x00); | ||
this._i2c.sendByteSync(this._address, 0x00); | ||
}; | ||
@@ -45,3 +45,3 @@ | ||
this._i2c.write(new Buffer([~this._readMask & this._writeMask & 0xff])); | ||
this._i2c.sendByteSync(this._address, ~this._readMask & this._writeMask & 0xff); | ||
}; | ||
@@ -53,13 +53,19 @@ | ||
PCF8574A.prototype.tick = function() { | ||
if (this._readMask) { | ||
var value = this._read(); | ||
PCF8574A.prototype.tick = function(callback) { | ||
if (!this._readMask) { | ||
// if there's nothing to do the callback also needs to be called | ||
process.nextTick(callback); | ||
} else { | ||
this._i2c.receiveByte(this._address, function(err, value) { | ||
if (!err) { | ||
for (var i = 0; i < 8; i++) { | ||
var pinMask = (1 << i); | ||
for (var i = 0; i < 8; i++) { | ||
var pinMask = (1 << i); | ||
if (this._readMask & pinMask) { | ||
this.emit('digital-read', 'XIO-P' + i, (value & pinMask) ? 1 : 0); | ||
if (this._readMask & pinMask) { | ||
this.emit('digital-read', 'XIO-P' + i, (value & pinMask) ? 1 : 0); | ||
} | ||
} | ||
} | ||
} | ||
callback(); | ||
}.bind(this)); | ||
} | ||
@@ -69,11 +75,5 @@ }; | ||
PCF8574A.prototype.close = function() { | ||
this._i2c.close(); | ||
this._i2c.closeSync(); | ||
}; | ||
PCF8574A.prototype._read = function() { | ||
var value = this._i2c.read(1); | ||
return value[0]; | ||
}; | ||
module.exports = PCF8574A; |
{ | ||
"name": "chip-io", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "Johnny-Five IO Plugin for the Next Thing Co. C.H.I.P.", | ||
@@ -33,4 +33,4 @@ "main": "index.js", | ||
"debug": "^2.2.0", | ||
"errno": "^0.1.4", | ||
"ffi": "^2.0.0", | ||
"i2c-bus": "^1.2.0", | ||
"ref": "^1.3.2" | ||
@@ -37,0 +37,0 @@ }, |
204373
1665
1
33
+ Addedi2c-bus@^1.2.0
+ Addedbindings@1.3.1(transitive)
+ Addedi2c-bus@1.2.5(transitive)
+ Addednan@2.8.0(transitive)
- Removederrno@^0.1.4
- Removederrno@0.1.8(transitive)
- Removedprr@1.0.1(transitive)