johnny-five-electron
Version:
Temporary fork to support Electron (to be deprecated)
258 lines (214 loc) • 5.98 kB
JavaScript
var Board = require("../lib/board");
var EVS = require("../lib/evshield");
var within = require("./mixins/within");
var __ = require("./fn");
var Emitter = require("events").EventEmitter;
var util = require("util");
var priv = new Map();
var int16 = __.int16;
function analogHandler(opts, dataHandler) {
this.io.pinMode(this.pin, this.io.MODES.ANALOG);
this.io.analogRead(this.pin, function(data) {
dataHandler.call(this, data);
}.bind(this));
}
var Controllers = {
DEFAULT: {
initialize: {
value: analogHandler
},
toIntensityLevel: {
value: function(raw) {
// TODO: Scale to percentage
return raw;
}
}
},
EVS_EV3: {
initialize: {
value: function(opts, dataHandler) {
var state = priv.get(this);
if (opts.mode) {
opts.mode = opts.mode.toUpperCase();
}
state.mode = opts.mode === "REFLECTED" ? EVS.Type_EV3_LIGHT_REFLECTED : EVS.Type_EV3_LIGHT;
state.shield = EVS.shieldPort(opts.pin);
state.ev3 = new EVS(Object.assign(opts, { io: this.io }));
state.ev3.setup(state.shield, EVS.Type_EV3);
state.ev3.write(state.shield, 0x81 + state.shield.offset, state.mode);
state.ev3.read(state.shield, EVS.Light, EVS.Light_Bytes, function(data) {
var value = data[0] | (data[1] << 8);
dataHandler(value);
});
}
},
toIntensityLevel: {
value: function(raw) {
return raw;
}
}
},
EVS_NXT: {
initialize: {
value: function(opts, dataHandler) {
var state = priv.get(this);
if (opts.mode) {
opts.mode = opts.mode.toUpperCase();
}
state.mode = opts.mode === "REFLECTED" ? EVS.Type_NXT_LIGHT_REFLECTED : EVS.Type_NXT_LIGHT;
state.shield = EVS.shieldPort(opts.pin);
state.ev3 = new EVS(Object.assign(opts, { io: this.io }));
state.ev3.setup(state.shield, state.mode);
state.ev3.read(state.shield, state.shield.analog, EVS.Analog_Bytes, function(data) {
var value = data[0] | (data[1] << 8);
dataHandler(value);
});
}
},
toIntensityLevel: {
value: function(raw) {
return __.scale(raw, 0, 1023, 100, 0);
}
}
},
TSL2561: {
ADDRESSES: {
value: [ 0x29, 0x39, 0x49 ]
},
REGISTER: {
value: {
CONTROL: 0x00,
TIMING: 0x01,
READ: 0x8C,
}
},
initialize: {
value: function(opts, dataHandler) {
var address = opts.address || 0x39;
// var read = (address & 0x0F) | 0x80;
var gain = opts.gain || 0;
var time = opts.time || 0;
var iMs = [ 13.7, 101, 402 ][ time ];
// Default value of timing register
// http://www.adafruit.com/datasheets/TSL2561.pdf
// Page 15
var timing = 0x02;
// gain [ 0 => 1X, 1 => 16X]
if (gain) {
timing |= 0x10;
} else {
timing &= ~0x10;
}
// time [ 0 => 13.7, 1 => 101, 2 => 402 ] ms
timing &= ~0x03;
timing |= (time & 0x03);
this.io.i2cConfig();
// Write the "power on" byte to the control register
this.io.i2cWriteReg(address, this.REGISTER.CONTROL, 0x03);
// Configure the timing and gain
this.io.i2cWriteReg(address, this.REGISTER.TIMING, timing);
this.io.i2cRead(address, this.REGISTER.READ, 4, function(data) {
var ch0 = int16(data[1], data[0]);
var ch1 = int16(data[3], data[2]);
var value = 0;
var ratio = 0;
// http://www.adafruit.com/datasheets/TSL2561.pdf
// Page 23
if (ch0 === 0xFFFF || ch1 === 0xFFFF) {
value = 0;
} else {
ratio = ch1 / ch0;
ch0 *= 402 / iMs;
ch1 *= 402 / iMs;
if (!gain) {
ch0 *= 16;
ch1 *= 16;
}
if (ratio < 0.5) {
value = 0.0304 * ch0 - 0.062 * ch0 * Math.pow(ratio, 1.4);
} else if (ratio < 0.61) {
value = 0.0224 * ch0 - 0.031 * ch1;
} else if (ratio < 0.80) {
value = 0.0128 * ch0 - 0.0153 * ch1;
} else if (ratio < 1.30) {
value = 0.00146 * ch0 - 0.00112 * ch1;
} else {
value = 0;
}
}
dataHandler(value);
});
}
},
toIntensityLevel: {
value: function(raw) {
//
console.log("???", raw);
return __.scale(raw, 0.1, 40000, 0, 100);
}
}
},
};
/**
* Light
* @constructor
*
*/
function Light(opts) {
if (!(this instanceof Light)) {
return new Light(opts);
}
var controller = null;
var state = {};
var raw = 0;
var freq = opts.freq || 25;
var last = 0;
Board.Device.call(
this, opts = Board.Options(opts)
);
if (typeof opts.controller === "string") {
controller = Controllers[opts.controller];
} else {
controller = opts.controller || Controllers.DEFAULT;
}
Object.defineProperties(this, controller);
if (!this.toIntensityLevel) {
this.toIntensityLevel = opts.toIntensityLevel || function(x) {
return x;
};
}
priv.set(this, state);
Object.defineProperties(this, {
value: {
get: function() {
return raw;
}
},
level: {
get: function() {
return this.toIntensityLevel(raw);
}
},
});
if (typeof this.initialize === "function") {
this.initialize(opts, function(data) {
raw = data;
});
}
setInterval(function() {
if (raw === undefined) {
return;
}
var data = {
level: this.level
};
this.emit("data", data);
if (raw !== last) {
last = raw;
this.emit("change", data);
}
}.bind(this), freq);
}
util.inherits(Light, Emitter);
__.mixin(Light.prototype, within);
module.exports = Light;