Skip to content

Commit

Permalink
Improved reading/polling
Browse files Browse the repository at this point in the history
Signed-off-by: Rick Waldron <waldron.rick@gmail.com>
  • Loading branch information
rwaldron committed Apr 20, 2016
1 parent 6cf47ad commit 886cca9
Show file tree
Hide file tree
Showing 2 changed files with 294 additions and 141 deletions.
208 changes: 101 additions & 107 deletions lib/tessel.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require("../lib/array-includes-shim");

var os = require("os");
var util = require("util");
var Emitter = require("events").EventEmitter;
var tessel;
var factory;
Expand All @@ -14,7 +15,6 @@ if (process.env.IS_TEST_ENV) {

var priv = new Map();
var tessels = [];
var reporting = [];

var modes = Object.freeze({
INPUT: 0,
Expand Down Expand Up @@ -71,7 +71,6 @@ var pinModes = [
{ modes: [1] },
];


var A = "A";
var B = "B";
var L = "L";
Expand Down Expand Up @@ -206,42 +205,7 @@ function ToI2CBusPort(value) {
return undefined;
}

var samplingInterval = 5;

function read() {
if (read.interval) {
return;
}

read.interval = global.setInterval(() => {
var board;

if (tessels.length && reporting.length) {
board = tessels[0];

reporting.forEach(function(report, gpio) {
board.pins[report.index].read(function(value) {
processRead(board, report, value);
});
});
}
}, samplingInterval);
}

function processRead(board, report, value) {
value = +value;

if (Number.isNaN(value)) {
value = 0;
}

if (report.scale) {
value = report.scale(value);
}

board.pins[report.index].value = value;
board.emit(report.event, value);
}
var samplingInterval = 10;

function Port() {}

Expand Down Expand Up @@ -273,72 +237,88 @@ Port.REPLY = {
};

function Pin(options) {
Emitter.call(this);
// options.port
// options.index

var pin = options.port === "L" ?
var pin = options.port === L ?
tessel.led[options.index] : tessel.port[options.port].pin[options.index];
var state = {
board: options.board,
isAnalogInput: false,
isInverted: options.index === 0 || options.index === 1,
isPwm: false,
isServo: false,
pin: pin,
index: ports.byPortName[options.port].offset + options.index,
mode: undefined
mode: undefined,
pin: pin,
value: options.port === L ? undefined : 0,
};

Object.assign(this, options.capabilities);

priv.set(this, state);

Object.defineProperties(this, {
isInterrupt: {
get: () => {
return pin.interruptSupported;
}
},
supportedModes: {
value: options.modes
},
value: {
get: function() {
get: () => {
return state.value;
},
set: function(value) {
set: (value) => {
state.value = value;
// pin.write(value);
}
},
mode: {
get: function() {
get: () => {
return state.mode;
},
set: function(value) {
if (value === 0 || value === 2) {
set: (mode) => {
if (mode === 0 || mode === 2) {
// TODO: Make sure this doesn't
// interfere with analogRead.
pin.input();
}

if (value === 1 || value === 3 || value === 4) {
if (mode === 1 || mode === 3 || mode === 4) {
// TODO: Make sure this doesn't
// interfere with pwmWrite
if (options.port !== L) {
pin.output();
}
}

state.isAnalogInput = value === 2;
state.isPwm = value === 3 || value === 4;
state.isServo = value === 4;
state.mode = value;
state.isAnalogInput = mode === 2;
state.isPwm = mode === 3 || mode === 4;
state.isServo = mode === 4;
state.mode = mode;
}
}
});

// Don't mess with the error or warning leds...
if (options.port !== L) {
// But otherwise, set all pins to OUTPUT and LOW
this.mode = 1;
this.value = 0;
this.mode = undefined;
this.write(0);
}

this.on("newListener", (event, handler) => {
if (event === "change") {
pin.on(event, handler);
}
});
}

util.inherits(Pin, Emitter);

Pin.prototype.write = function(value) {
var state = priv.get(this);

Expand All @@ -358,40 +338,50 @@ Pin.prototype.write = function(value) {
Pin.prototype.read = function(callback) {
var state = priv.get(this);
var index = state.pin.pin;
var handler = function(error, data) {
var value;
var cmd = state.isAnalogInput ? Port.CMD.ANALOG_READ : Port.CMD.GPIO_IN;
var size = state.isAnalogInput ? 2 : 0;
var start = Date.now();

if (error) {
throw new Error(error);
}
var poll = _ => {
state.pin._port.cork();
state.pin._port.sock.write(new Buffer([cmd, index]));
state.pin._port.enqueue({
size: size,
callback: (error, data) => {
var value;

if (state.isAnalogInput) {
value = data.readUInt16LE(0) >> 2;
} else {
value = data === Port.REPLY.HIGH ? 1 : 0;
}
if (error) {
throw new Error(error);
}

callback(value);
};
if (state.isAnalogInput) {
if (Buffer.isBuffer(data)) {
value = data.readUInt16LE(0) >> 2;
}
} else {
value = data === Port.REPLY.HIGH ? 1 : 0;
}

if (state.isAnalogInput) {
state.pin._port.sock.write(new Buffer([Port.CMD.ANALOG_READ, index]));
// TODO: Change to enqeue api
state.pin._port.enqueue({
size: 2,
callback: handler,
});
} else {
state.pin._port.cork();
state.pin._port.sock.write(new Buffer([Port.CMD.GPIO_IN, index]));
state.pin._port.enqueue({
size: 0,
callback: handler,
callback(value);

var now = Date.now();
var diff = timeout(start, now);

setTimeout(poll, diff);
start = now;
},
});
state.pin._port.uncork();
}
};

poll();
};

function timeout(a, b) {
var diff = samplingInterval - (b - a);
return constrain(diff, 0, samplingInterval);
}

function Tessel(options) {
Emitter.call(this);

Expand All @@ -412,7 +402,7 @@ function Tessel(options) {
bus: ToPortI2CBus(options.i2c !== undefined ? options.i2c.bus : 4),
devices: {

}
},
},
uart: {}
};
Expand Down Expand Up @@ -456,7 +446,9 @@ function Tessel(options) {
});
}

Tessel.prototype = Object.create(Emitter.prototype, {
util.inherits(Tessel, Emitter);

Object.defineProperties(Tessel.prototype, {
constructor: {
value: Tessel
},
Expand All @@ -473,8 +465,6 @@ Tessel.prototype = Object.create(Emitter.prototype, {

Tessel.prototype.setSamplingInterval = function(ms) {
samplingInterval = Math.min(Math.max(ms, 5), 65535);
global.clearInterval(read.interval);
read();
};

Tessel.prototype.getSamplingInterval = function() {
Expand All @@ -499,18 +489,27 @@ Tessel.prototype.pinMode = function(pin, value) {
return this;
};

Tessel.prototype.digitalRead = function(pin, handler) {
Tessel.prototype.digitalRead = function(pin, callback) {
var pinIndex = ToPinIndex(pin);
var event = "digital-read-" + pinIndex;
var handler = (value) => {
if (this.pins[pinIndex].value !== value) {
this.pins[pinIndex].value = value;
this.emit(event, value);
}
};
this.on(event, callback);

reporting.push({
event: event,
index: pinIndex,
scale: null
});
/*
// This was working well earlier, why is it now failing?
if (this.pins[pinIndex].isInterrupt) {
this.pins[pinIndex].on("change", handler);
} else {
this.pins[pinIndex].read(handler);
}
*/

this.on(event, handler);
read();
this.pins[pinIndex].read(handler);

return this;
};
Expand All @@ -520,18 +519,16 @@ Tessel.prototype.digitalWrite = function(pin, value) {
return this;
};

Tessel.prototype.analogRead = function(pin, handler) {
Tessel.prototype.analogRead = function(pin, callback) {
var pinIndex = ToPinIndex(pin);
var event = "analog-read-" + pinIndex;

reporting.push({
event: event,
index: pinIndex,
scale: null
});
this.on(event, callback);

this.on(event, handler);
read();
this.pins[pinIndex].read(value => {
this.pins[pinIndex].value = value;
this.emit(event, value);
});

return this;
};
Expand Down Expand Up @@ -693,17 +690,17 @@ Tessel.prototype.i2cRead = function(address, register, bytesToRead, callback) {
callback = typeof callback === "function" ? callback : function() {};

var start = Date.now();
var continuousRead = _ => {
var poll = _ => {
this.i2cReadOnce(address, register, bytesToRead, (bytes) => {
callback(bytes);
var now = Date.now();
var diff = now - start;
setTimeout(continuousRead, samplingInterval - diff);
var diff = timeout(start, now);
setTimeout(poll, diff);
start = now;
});
};

continuousRead();
poll();

return this;
};
Expand Down Expand Up @@ -837,13 +834,10 @@ if (process.env.IS_TEST_ENV) {
Tessel.ToPortI2CBus = ToPortI2CBus;
Tessel.ToI2CBusPort = ToI2CBusPort;
Tessel.Pin = Pin;
Tessel.read = read;
Tessel.processRead = processRead;
Tessel.tessel = tessel;
Tessel.purge = function() {
tessels.length = 0;
};
// ...
}

// These are exposed to allow direct access as needed.
Expand Down
Loading

0 comments on commit 886cca9

Please sign in to comment.