Skip to content

Commit

Permalink
Merge pull request #154 from aj-ptw/master
Browse files Browse the repository at this point in the history
2.1.1
  • Loading branch information
AJ Keller authored Jul 20, 2017
2 parents c11d3a6 + f09d26e commit 7e7ccf3
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 20 deletions.
10 changes: 10 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 2.1.1

### Bug Fixes

* Closes forgot parentheses in `getBoardType()` #152 (thanks @nateGeorge)

### Enhancements

* Add support for v3 cyton firmware.

# 2.1.0

### Breaking changes
Expand Down
2 changes: 1 addition & 1 deletion examples/getStreaming/getStreaming.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
const debug = false; // Pretty print any bytes in and out... it's amazing...
const verbose = true; // Adds verbosity to functions

const Cyton = require('openbci').Cyton;
const Cyton = require('../../index').Cyton;
let ourBoard = new Cyton({
debug: debug,
verbose: verbose
Expand Down
2 changes: 1 addition & 1 deletion examples/getStreamingDaisy/getStreamingDaisy.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
const debug = false; // Pretty print any bytes in and out... it's amazing...
const verbose = true; // Adds verbosity to functions

const Cyton = require('openbci').Cyton;
const Cyton = require('../../index').Cyton;
let ourBoard = new Cyton({
boardType: 'daisy',
debug: debug,
Expand Down
62 changes: 48 additions & 14 deletions openBCICyton.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ var _options = {
simulatorBoardFailure: false,
simulatorDaisyModuleAttached: false,
simulatorDaisyModuleCanBeAttached: true,
simulatorFirmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2],
simulatorFirmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2, k.OBCIFirmwareV3],
simulatorFragmentation: [k.OBCISimulatorFragmentationNone, k.OBCISimulatorFragmentationRandom, k.OBCISimulatorFragmentationFullBuffers, k.OBCISimulatorFragmentationOneByOne],
simulatorLatencyTime: 16,
simulatorBufferSize: 4096,
Expand Down Expand Up @@ -254,6 +254,7 @@ Cyton.prototype.connect = function (portName) {
return new Promise((resolve, reject) => {
if (this.isConnected()) return reject(Error('already connected!'));
this.overrideInfoForBoardType(this.options.boardType);
this.buffer = null;
/* istanbul ignore else */
if (this.options.simulate || portName === k.OBCISimulatorPortName) {
this.options.simulate = true;
Expand Down Expand Up @@ -637,6 +638,34 @@ Cyton.prototype.usingVersionTwoFirmware = function () {
}
};

/**
* @description Convenience method to determine if you can use firmware v2.x.x
* or greater capabilities.
* @returns {boolean} - True if using firmware version 2 or greater. Should
* be called after a `.softReset()` because we can parse the output of that
* to determine if we are using firmware version 2.
* @author AJ Keller (@pushtheworldllc)
*/
Cyton.prototype.usingAtLeastVersionTwoFirmware = function () {
return this.usingVersionTwoFirmware() || this.usingVersionThreeFirmware();
};

/**
* @description Convenience method to determine if you can use firmware v2.x.x
* capabilities.
* @returns {boolean} - True if using firmware version 2 or greater. Should
* be called after a `.softReset()` because we can parse the output of that
* to determine if we are using firmware version 2.
* @author AJ Keller (@pushtheworldllc)
*/
Cyton.prototype.usingVersionThreeFirmware = function () {
if (this.options.simulate) {
return this.options.simulatorFirmwareVersion === k.OBCIFirmwareV3;
} else {
return this.info.firmware === k.OBCIFirmwareV3;
}
};

/**
* @description Used to set the system radio channel number. The function will reject if not
* connected to the serial port of the dongle. Further the function should reject if currently streaming.
Expand All @@ -653,7 +682,7 @@ Cyton.prototype.radioChannelSet = function (channelNumber) {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error('Don\'t query for the radio while streaming'));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware version 2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
if (channelNumber === undefined || channelNumber === null) return reject(Error('Must input a new channel number to switch too!'));
if (!k.isNumber(channelNumber)) return reject(Error('Must input type Number'));
if (channelNumber > k.OBCIRadioChannelMax) return reject(Error(`New channel number must be less than ${k.OBCIRadioChannelMax}`));
Expand Down Expand Up @@ -755,7 +784,7 @@ Cyton.prototype.radioChannelGet = function () {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error("Don't query for the radio while streaming"));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));

// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
// important if the module was connected, not streaming and using the old firmware
Expand Down Expand Up @@ -803,7 +832,7 @@ Cyton.prototype.radioPollTimeGet = function () {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error("Don't query for the poll time while streaming"));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
// important if the module was connected, not streaming and using the old firmware
badCommsTimeout = setTimeout(() => {
Expand Down Expand Up @@ -850,7 +879,7 @@ Cyton.prototype.radioPollTimeSet = function (pollTime) {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error("Don't change the poll time while streaming"));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
if (pollTime === undefined || pollTime === null) return reject(Error('Must input a new poll time to switch too!'));
if (!k.isNumber(pollTime)) return reject(Error('Must input type Number'));
if (pollTime > k.OBCIRadioPollTimeMax) return reject(Error(`New polltime must be less than ${k.OBCIRadioPollTimeMax}`));
Expand Down Expand Up @@ -904,7 +933,7 @@ Cyton.prototype.radioBaudRateSet = function (speed) {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error("Don't change the baud rate while streaming"));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
if (!k.isString(speed)) return reject(Error('Must input type String'));
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
// important if the module was connected, not streaming and using the old firmware
Expand Down Expand Up @@ -975,7 +1004,7 @@ Cyton.prototype.radioSystemStatusGet = function () {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
if (this.isStreaming()) return reject(Error("Don't check the radio status while streaming"));
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware version 2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));

// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
// important if the module was connected, not streaming and using the old firmware
Expand Down Expand Up @@ -1695,7 +1724,7 @@ Cyton.prototype.syncClocks = function () {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to the device'));
if (!this.isStreaming()) return reject(Error('Must be streaming to sync clocks'));
if (!this.usingVersionTwoFirmware()) return reject(Error('Time sync not implemented on v1 firmware, please update to v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
this.sync.curSyncObj = obciUtils.newSyncObject();
this.sync.curSyncObj.timeSyncSent = this.time();
this.curParsingMode = k.OBCIParsingTimeSyncSent;
Expand All @@ -1716,7 +1745,7 @@ Cyton.prototype.syncClocksFull = function () {
return new Promise((resolve, reject) => {
if (!this.isConnected()) return reject(Error('Must be connected to the device'));
if (!this.isStreaming()) return reject(Error('Must be streaming to sync clocks'));
if (!this.usingVersionTwoFirmware()) return reject(Error('Time sync not implemented on v1 firmware, please update to v2'));
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
var timeout = setTimeout(() => {
return reject(Error('syncClocksFull timeout after 500ms with no sync'));
}, 500); // Should not take more than 1s to sync up
Expand Down Expand Up @@ -1773,7 +1802,7 @@ Cyton.prototype._processBytes = function (data) {
if (obciUtils.doesBufferHaveEOT(data)) {
this._processParseBufferForReset(data);
if (this.options.hardSet) {
if (this.getBoardType() !== this.options.boardType) {
if (!_.eq(this.getBoardType(), this.options.boardType)) {
this.emit(k.OBCIEmitterHardSet);
this.hardSetBoardType(this.options.boardType)
.then(() => {
Expand All @@ -1788,7 +1817,7 @@ Cyton.prototype._processBytes = function (data) {
this.buffer = obciUtils.stripToEOTBuffer(data);
}
} else {
if (this.getBoardType() !== this.options.boardType && this.options.verbose) {
if (_.eq(this.getBoardType(), this.options.boardType) && this.options.verbose) {
console.log(`Module detected ${this.getBoardType()} board type but you specified ${this.options.boardType}, use 'hardSet' to force the module to correct itself`);
}
this.curParsingMode = k.OBCIParsingNormal;
Expand Down Expand Up @@ -1863,8 +1892,13 @@ Cyton.prototype._processParseBufferForReset = function (dataBuffer) {
this.overrideInfoForBoardType(k.OBCIBoardCyton);
}

if (obciUtils.findV2Firmware(dataBuffer)) {
this.info.firmware = k.OBCIFirmwareV2;
const firmware = obciUtils.getFirmware(dataBuffer);
if (firmware) {
if (firmware.major === 2) {
this.info.firmware = k.OBCIFirmwareV2;
} else {
this.info.firmware = k.OBCIFirmwareV3;
}
this.writeOutDelay = k.OBCIWriteIntervalDelayMSNone;
} else {
this.info.firmware = k.OBCIFirmwareV1;
Expand Down Expand Up @@ -2073,7 +2107,7 @@ Cyton.prototype._finalizeNewSample = function (sampleObject) {
} else {
// With the daisy board attached, lower channels (1-8) come in packets with odd sample numbers and upper
// channels (9-16) come in packets with even sample numbers
if (this.getBoardType() === k.OBCIBoardDaisy) {
if (_.eq(this.getBoardType(), k.OBCIBoardDaisy)) {
// Send the sample for downstream sample compaction
this._finalizeNewSampleForDaisy(sampleObject);
} else {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openbci",
"version": "2.1.0",
"version": "2.1.1",
"description": "The official Node.js SDK for the OpenBCI Biosensor Board.",
"main": "index.js",
"scripts": {
Expand All @@ -21,7 +21,7 @@
"gaussian": "^1.0.0",
"lodash": "^4.17.4",
"mathjs": "^3.14.2",
"openbci-utilities": "0.0.10",
"openbci-utilities": "0.1.0",
"performance-now": "^2.1.0",
"safe-buffer": "^5.1.1",
"serialport": "4.0.7",
Expand Down
69 changes: 67 additions & 2 deletions test/openBCICyton-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2038,7 +2038,7 @@ $$$`);
var buf = new Buffer(`OpenBCI V3 Simulator
On Board ADS1299 Device ID: 0x12345
LIS3DH Device ID: 0x38422
Firmware: v2
Firmware: v2.0.0
$$$`);

ourBoard._processParseBufferForReset(buf);
Expand All @@ -2048,12 +2048,26 @@ $$$`);
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate250);
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsCyton);
});
it('should recognize firmware version 3 with no daisy', () => {
var buf = new Buffer(`OpenBCI V3 Simulator
On Board ADS1299 Device ID: 0x12345
LIS3DH Device ID: 0x38422
Firmware: v3.0.1
$$$`);

ourBoard._processParseBufferForReset(buf);

ourBoard.info.firmware.should.equal(k.OBCIFirmwareV3);
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardCyton);
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate250);
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsCyton);
});
it('should recognize firmware version 2 with daisy', () => {
var buf = new Buffer(`OpenBCI V3 Simulator
On Board ADS1299 Device ID: 0x12345
On Daisy ADS1299 Device ID: 0xFFFFF
LIS3DH Device ID: 0x38422
Firmware: v2
Firmware: v2.0.0
$$$`);

ourBoard._processParseBufferForReset(buf);
Expand All @@ -2063,6 +2077,21 @@ $$$`);
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate125);
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsDaisy);
});
it('should recognize firmware version 3 with daisy', () => {
var buf = new Buffer(`OpenBCI V3 Simulator
On Board ADS1299 Device ID: 0x12345
On Daisy ADS1299 Device ID: 0xFFFFF
LIS3DH Device ID: 0x38422
Firmware: v3.1.69
$$$`);

ourBoard._processParseBufferForReset(buf);

ourBoard.info.firmware.should.equal(k.OBCIFirmwareV3);
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardDaisy);
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate125);
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsDaisy);
});
});

describe('#_processBytes', function () {
Expand Down Expand Up @@ -2507,6 +2536,42 @@ $$$`);
});
});

describe('#usingVersionThreeFirmware', function () {
after(() => bluebirdChecks.noPendingPromises());
it('should return true if firmware is version 3', () => {
ourBoard = new Cyton();
ourBoard.info.firmware = 'v3';

expect(ourBoard.usingVersionThreeFirmware()).to.be.true();
});
it('should return false if not firmware version 3', () => {
ourBoard = new Cyton();

expect(ourBoard.usingVersionThreeFirmware()).to.be.false();
});
});

describe('#usingAtLeastVersionTwoFirmware', function () {
after(() => bluebirdChecks.noPendingPromises());
it('should return true if firmware is version 3', () => {
ourBoard = new Cyton();
ourBoard.info.firmware = 'v2';

expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.true();
});
it('should return true if firmware is version 3', () => {
ourBoard = new Cyton();
ourBoard.info.firmware = 'v3';

expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.true();
});
it('should return false if not firmware version 3', () => {
ourBoard = new Cyton();

expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.false();
});
});

xdescribe('#hardwareValidation', function () {
this.timeout(20000); // long timeout for pleanty of stream time :)
var runHardwareValidation = true;
Expand Down

0 comments on commit 7e7ccf3

Please sign in to comment.