Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
"target_name": "i2c",
"sources": [ "src/i2c.cc" ],
"include_dirs" : [
"<!(node -e \"require('nan')\")"
"<!(node -e \"require('nan')\")",
"<!(node -e \"console.log(require('node-addon-api').include.replace(/\\\"/g, ''))\")"
],
"cflags": [
"-fno-exceptions"
],
"cflags_cc": [
"-fno-exceptions"
],
"defines": [
"NAPI_DISABLE_CPP_EXCEPTIONS"
]
}
]
Expand Down
86 changes: 39 additions & 47 deletions examples/accelerometer/accel.js
Original file line number Diff line number Diff line change
@@ -1,72 +1,64 @@
const Wire = require('../../main');

// for AK8975
// info: https://github.com/jrowberg/i2cdevlib/blob/master/Arduino/AK8975/AK8975.cpp
// http://stackoverflow.com/questions/4768933/read-two-bytes-into-an-integer

const RANGE_BWIDTH = 0x14;
const RANGE_BIT = 0x04;
const RANGE_LENGTH = 0x02;
const RANGE_2G = 0x00;
const BANDWIDTH_BIT = 0x02;
const BANDWIDTH_LENGTH = 0x03;
const BW_25HZ = 0x00;
const GET_ID = 0x00;
const RANGE_BWIDTH = 0x14;
const RANGE_BIT = 0x04;
const RANGE_LENGTH = 0x02;
const RANGE_2G = 0x00;
const BANDWIDTH_BIT = 0x02;
const BANDWIDTH_LENGTH = 0x03;
const BW_25HZ = 0x00;
const GET_ID = 0x00;

class Accelerometer {

constructor(address) {
this.address = address;
this.wire = new Wire(this.address);

this.setRange();
this.setBandwidth();

this.wire.on('data', (data) => {
console.log(data);
});
}

setRange() {
this.wire.writeBytes(RANGE_BWIDTH, [RANGE_BIT, RANGE_LENGTH, RANGE_2G], null);
async init() {
await this.wire.open();
await this.setRange();
await this.setBandwidth();
}

testConnection(callback) {
this.getDeviceID((err, data) => {
callback(data[0] === 0b010);
});
async setRange() {
await this.wire.writeBlock(RANGE_BWIDTH, Buffer.from([RANGE_BIT, RANGE_LENGTH, RANGE_2G]));
}

getDeviceID(callback) {
this.wire.readBytes(GET_ID, 1, callback);
async testConnection() {
const data = await this.getDeviceID();
return data[0] === 0b010;
}

setBandwidth() {
this.wire.writeBytes(RANGE_BWIDTH, [BANDWIDTH_BIT, BANDWIDTH_LENGTH, BW_25HZ], null);
async getDeviceID() {
return this.wire.readBlock(GET_ID, 1);
}

getHeading() {
this.wire.writeBytes(0x0A, [0x1], (err) => {
if (err) console.error(err);
});
async setBandwidth() {
await this.wire.writeBlock(RANGE_BWIDTH, Buffer.from([BANDWIDTH_BIT, BANDWIDTH_LENGTH, BW_25HZ]));
}

setTimeout(() => {
this.wire.readBytes(0x03, 6, (err, buffer) => {
if (err) return console.error(err);
const pos = {
x: ((buffer[1]) << 8) | buffer[0],
y: ((buffer[3]) << 8) | buffer[2],
z: ((buffer[5]) << 8) | buffer[4]
};
console.log(pos);
});
}, 10);
async getHeading() {
await this.wire.writeBlock(0x0A, Buffer.from([0x1]));
await new Promise(resolve => setTimeout(resolve, 10));
const buffer = await this.wire.readBlock(0x03, 6);
const pos = {
x: ((buffer[1]) << 8) | buffer[0],
y: ((buffer[3]) << 8) | buffer[2],
z: ((buffer[5]) << 8) | buffer[4]
};
console.log(pos);
}

getMotion() {
this.wire.on('data', console.log);
this.wire.stream(0x02, 6, 100);
}
}

const accel = new Accelerometer(56);
accel.getHeading();
(async () => {
const accel = new Accelerometer(56);
await accel.init();
await accel.getHeading();
accel.getMotion();
})();
173 changes: 67 additions & 106 deletions lib/i2c.js
Original file line number Diff line number Diff line change
@@ -1,145 +1,106 @@
const wire = require('../build/Release/i2c');
const { EventEmitter } = require('events');
const tick = setImmediate || process.nextTick;
const wire = require('../build/Release/i2c.node');

function wrap(fn) {
return (...args) => new Promise((resolve, reject) => {
try {
resolve(fn(...args));
} catch (err) {
reject(err);
}
});
}

class i2c extends EventEmitter {
const open = wrap(wire.open);
const close = wrap(wire.close);
const scan = wrap(wire.scan);
const setAddress = wrap(wire.setAddress);
const read = wrap(wire.read);
const readByte = wrap(wire.readByte);
const readBlock = wrap(wire.readBlock);
const write = wrap(wire.write);
const writeByte = wrap(wire.writeByte);
const writeBlock = wrap(wire.writeBlock);
const writeWord = wrap(wire.writeWord);

constructor(address, options) {
class i2c extends EventEmitter {
constructor(address, options = {}) {
super();
this.address = address;
this.options = {
debug: false,
device: "/dev/i2c-1",
...(options || {})
device: '/dev/i2c-1',
...options
};
this.history = [];

if (this.options.debug) {
require('repl').start({
prompt: "i2c > "
}).context.wire = this;
process.stdin.emit('data', ''); // trigger repl
}

process.on('exit', () => this.close());

this.on('data', (data) => {
this.history.push(data);
});

this.on('error', (err) => {
console.log(`Error: ${err}`);
});
}

this.open(this.options.device, (err) => {
if (!err) {
this.setAddress(this.address);
}
});
async open() {
await open(this.options.device);
}

scan(callback) {
wire.scan((err, data) => {
tick(() => {
// data is an Array from C++
callback(err, data.filter((num) => num >= 0));
});
});
async close() {
await close();
}

setAddress(address) {
wire.setAddress(address);
this.address = address;
async scan() {
return scan();
}

open(device, callback) {
wire.open(device, (err) => {
tick(() => {
if (callback) callback(err);
});
});
async setAddress() {
await setAddress(this.address);
}

close() {
wire.close();
async read(len) {
await this.setAddress();
return read(len);
}

write(buf, callback) {
this.setAddress(this.address);
if (!Buffer.isBuffer(buf)) {
buf = Buffer.from(buf);
}
wire.write(buf, (err) => {
tick(() => {
if (callback) callback(err);
});
});
async readByte() {
await this.setAddress();
return readByte();
}

writeByte(byte, callback) {
this.setAddress(this.address);
wire.writeByte(byte, (err) => {
tick(() => {
if (callback) callback(err);
});
});
async readBlock(cmd, len) {
await this.setAddress();
return readBlock(cmd, len);
}

writeBytes(cmd, buf, callback) {
this.setAddress(this.address);
if (!Buffer.isBuffer(buf)) {
buf = Buffer.from(buf);
}
wire.writeBlock(cmd, buf, (err) => {
tick(() => {
if (callback) callback(err);
});
});
async write(buf) {
await this.setAddress();
return write(buf);
}

read(len, callback) {
this.setAddress(this.address);
wire.read(len, (err, data) => {
tick(() => {
if (callback) callback(err, data);
});
});
async writeByte(byte) {
await this.setAddress();
return writeByte(byte);
}

readByte(callback) {
this.setAddress(this.address);
wire.readByte((err, data) => {
tick(() => {
if (callback) callback(err, data);
});
});
async writeBlock(cmd, buf) {
await this.setAddress();
return writeBlock(cmd, buf);
}

readBytes(cmd, len, callback) {
this.setAddress(this.address);
wire.readBlock(cmd, len, null, (err, actualBuffer) => {
tick(() => {
if (callback) callback(err, actualBuffer);
});
});
async writeWord(cmd, word) {
await this.setAddress();
return writeWord(cmd, word);
}

stream(cmd, len, delay) {
if (delay == null) delay = 100;
this.setAddress(this.address);
wire.readBlock(cmd, len, delay, (err, data) => {
if (err) {
this.emit('error', err);
} else {
stream(cmd, len, delay = 100) {
const streamNext = async () => {
try {
const data = await this.readBlock(cmd, len);
this.emit('data', {
address: this.address,
data: data,
cmd: cmd,
data,
cmd,
length: len,
timestamp: Date.now()
});
setTimeout(streamNext, delay);
} catch (err) {
this.emit('error', err);
}
});
};
streamNext();
}
}

Expand Down
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"license": "BSD-3-Clause-Attribution",
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.24.0"
"nan": "^2.24.0",
"node-addon-api": "^1.1.0"
},
"engine": "node >= 18.0.0"
}
Loading