Skip to content

Commit 7e7ccf3

Browse files
author
AJ Keller
authored
Merge pull request #154 from aj-ptw/master
2.1.1
2 parents c11d3a6 + f09d26e commit 7e7ccf3

File tree

6 files changed

+129
-20
lines changed

6 files changed

+129
-20
lines changed

changelog.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# 2.1.1
2+
3+
### Bug Fixes
4+
5+
* Closes forgot parentheses in `getBoardType()` #152 (thanks @nateGeorge)
6+
7+
### Enhancements
8+
9+
* Add support for v3 cyton firmware.
10+
111
# 2.1.0
212

313
### Breaking changes

examples/getStreaming/getStreaming.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
const debug = false; // Pretty print any bytes in and out... it's amazing...
1313
const verbose = true; // Adds verbosity to functions
1414

15-
const Cyton = require('openbci').Cyton;
15+
const Cyton = require('../../index').Cyton;
1616
let ourBoard = new Cyton({
1717
debug: debug,
1818
verbose: verbose

examples/getStreamingDaisy/getStreamingDaisy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
const debug = false; // Pretty print any bytes in and out... it's amazing...
1313
const verbose = true; // Adds verbosity to functions
1414

15-
const Cyton = require('openbci').Cyton;
15+
const Cyton = require('../../index').Cyton;
1616
let ourBoard = new Cyton({
1717
boardType: 'daisy',
1818
debug: debug,

openBCICyton.js

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ var _options = {
110110
simulatorBoardFailure: false,
111111
simulatorDaisyModuleAttached: false,
112112
simulatorDaisyModuleCanBeAttached: true,
113-
simulatorFirmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2],
113+
simulatorFirmwareVersion: [k.OBCIFirmwareV1, k.OBCIFirmwareV2, k.OBCIFirmwareV3],
114114
simulatorFragmentation: [k.OBCISimulatorFragmentationNone, k.OBCISimulatorFragmentationRandom, k.OBCISimulatorFragmentationFullBuffers, k.OBCISimulatorFragmentationOneByOne],
115115
simulatorLatencyTime: 16,
116116
simulatorBufferSize: 4096,
@@ -254,6 +254,7 @@ Cyton.prototype.connect = function (portName) {
254254
return new Promise((resolve, reject) => {
255255
if (this.isConnected()) return reject(Error('already connected!'));
256256
this.overrideInfoForBoardType(this.options.boardType);
257+
this.buffer = null;
257258
/* istanbul ignore else */
258259
if (this.options.simulate || portName === k.OBCISimulatorPortName) {
259260
this.options.simulate = true;
@@ -637,6 +638,34 @@ Cyton.prototype.usingVersionTwoFirmware = function () {
637638
}
638639
};
639640

641+
/**
642+
* @description Convenience method to determine if you can use firmware v2.x.x
643+
* or greater capabilities.
644+
* @returns {boolean} - True if using firmware version 2 or greater. Should
645+
* be called after a `.softReset()` because we can parse the output of that
646+
* to determine if we are using firmware version 2.
647+
* @author AJ Keller (@pushtheworldllc)
648+
*/
649+
Cyton.prototype.usingAtLeastVersionTwoFirmware = function () {
650+
return this.usingVersionTwoFirmware() || this.usingVersionThreeFirmware();
651+
};
652+
653+
/**
654+
* @description Convenience method to determine if you can use firmware v2.x.x
655+
* capabilities.
656+
* @returns {boolean} - True if using firmware version 2 or greater. Should
657+
* be called after a `.softReset()` because we can parse the output of that
658+
* to determine if we are using firmware version 2.
659+
* @author AJ Keller (@pushtheworldllc)
660+
*/
661+
Cyton.prototype.usingVersionThreeFirmware = function () {
662+
if (this.options.simulate) {
663+
return this.options.simulatorFirmwareVersion === k.OBCIFirmwareV3;
664+
} else {
665+
return this.info.firmware === k.OBCIFirmwareV3;
666+
}
667+
};
668+
640669
/**
641670
* @description Used to set the system radio channel number. The function will reject if not
642671
* connected to the serial port of the dongle. Further the function should reject if currently streaming.
@@ -653,7 +682,7 @@ Cyton.prototype.radioChannelSet = function (channelNumber) {
653682
return new Promise((resolve, reject) => {
654683
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
655684
if (this.isStreaming()) return reject(Error('Don\'t query for the radio while streaming'));
656-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware version 2'));
685+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
657686
if (channelNumber === undefined || channelNumber === null) return reject(Error('Must input a new channel number to switch too!'));
658687
if (!k.isNumber(channelNumber)) return reject(Error('Must input type Number'));
659688
if (channelNumber > k.OBCIRadioChannelMax) return reject(Error(`New channel number must be less than ${k.OBCIRadioChannelMax}`));
@@ -755,7 +784,7 @@ Cyton.prototype.radioChannelGet = function () {
755784
return new Promise((resolve, reject) => {
756785
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
757786
if (this.isStreaming()) return reject(Error("Don't query for the radio while streaming"));
758-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
787+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
759788

760789
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
761790
// important if the module was connected, not streaming and using the old firmware
@@ -803,7 +832,7 @@ Cyton.prototype.radioPollTimeGet = function () {
803832
return new Promise((resolve, reject) => {
804833
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
805834
if (this.isStreaming()) return reject(Error("Don't query for the poll time while streaming"));
806-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
835+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
807836
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
808837
// important if the module was connected, not streaming and using the old firmware
809838
badCommsTimeout = setTimeout(() => {
@@ -850,7 +879,7 @@ Cyton.prototype.radioPollTimeSet = function (pollTime) {
850879
return new Promise((resolve, reject) => {
851880
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
852881
if (this.isStreaming()) return reject(Error("Don't change the poll time while streaming"));
853-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
882+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
854883
if (pollTime === undefined || pollTime === null) return reject(Error('Must input a new poll time to switch too!'));
855884
if (!k.isNumber(pollTime)) return reject(Error('Must input type Number'));
856885
if (pollTime > k.OBCIRadioPollTimeMax) return reject(Error(`New polltime must be less than ${k.OBCIRadioPollTimeMax}`));
@@ -904,7 +933,7 @@ Cyton.prototype.radioBaudRateSet = function (speed) {
904933
return new Promise((resolve, reject) => {
905934
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
906935
if (this.isStreaming()) return reject(Error("Don't change the baud rate while streaming"));
907-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware v2'));
936+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
908937
if (!k.isString(speed)) return reject(Error('Must input type String'));
909938
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
910939
// important if the module was connected, not streaming and using the old firmware
@@ -975,7 +1004,7 @@ Cyton.prototype.radioSystemStatusGet = function () {
9751004
return new Promise((resolve, reject) => {
9761005
if (!this.isConnected()) return reject(Error('Must be connected to Dongle. Pro tip: Call .connect()'));
9771006
if (this.isStreaming()) return reject(Error("Don't check the radio status while streaming"));
978-
if (!this.usingVersionTwoFirmware()) return reject(Error('Must be using firmware version 2'));
1007+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
9791008

9801009
// Set a timeout. Since poll times can be max of 255 seconds, we should set that as our timeout. This is
9811010
// important if the module was connected, not streaming and using the old firmware
@@ -1695,7 +1724,7 @@ Cyton.prototype.syncClocks = function () {
16951724
return new Promise((resolve, reject) => {
16961725
if (!this.isConnected()) return reject(Error('Must be connected to the device'));
16971726
if (!this.isStreaming()) return reject(Error('Must be streaming to sync clocks'));
1698-
if (!this.usingVersionTwoFirmware()) return reject(Error('Time sync not implemented on v1 firmware, please update to v2'));
1727+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
16991728
this.sync.curSyncObj = obciUtils.newSyncObject();
17001729
this.sync.curSyncObj.timeSyncSent = this.time();
17011730
this.curParsingMode = k.OBCIParsingTimeSyncSent;
@@ -1716,7 +1745,7 @@ Cyton.prototype.syncClocksFull = function () {
17161745
return new Promise((resolve, reject) => {
17171746
if (!this.isConnected()) return reject(Error('Must be connected to the device'));
17181747
if (!this.isStreaming()) return reject(Error('Must be streaming to sync clocks'));
1719-
if (!this.usingVersionTwoFirmware()) return reject(Error('Time sync not implemented on v1 firmware, please update to v2'));
1748+
if (!this.usingAtLeastVersionTwoFirmware()) return reject(Error('Must be using greater than firmware version 2'));
17201749
var timeout = setTimeout(() => {
17211750
return reject(Error('syncClocksFull timeout after 500ms with no sync'));
17221751
}, 500); // Should not take more than 1s to sync up
@@ -1773,7 +1802,7 @@ Cyton.prototype._processBytes = function (data) {
17731802
if (obciUtils.doesBufferHaveEOT(data)) {
17741803
this._processParseBufferForReset(data);
17751804
if (this.options.hardSet) {
1776-
if (this.getBoardType() !== this.options.boardType) {
1805+
if (!_.eq(this.getBoardType(), this.options.boardType)) {
17771806
this.emit(k.OBCIEmitterHardSet);
17781807
this.hardSetBoardType(this.options.boardType)
17791808
.then(() => {
@@ -1788,7 +1817,7 @@ Cyton.prototype._processBytes = function (data) {
17881817
this.buffer = obciUtils.stripToEOTBuffer(data);
17891818
}
17901819
} else {
1791-
if (this.getBoardType() !== this.options.boardType && this.options.verbose) {
1820+
if (_.eq(this.getBoardType(), this.options.boardType) && this.options.verbose) {
17921821
console.log(`Module detected ${this.getBoardType()} board type but you specified ${this.options.boardType}, use 'hardSet' to force the module to correct itself`);
17931822
}
17941823
this.curParsingMode = k.OBCIParsingNormal;
@@ -1863,8 +1892,13 @@ Cyton.prototype._processParseBufferForReset = function (dataBuffer) {
18631892
this.overrideInfoForBoardType(k.OBCIBoardCyton);
18641893
}
18651894

1866-
if (obciUtils.findV2Firmware(dataBuffer)) {
1867-
this.info.firmware = k.OBCIFirmwareV2;
1895+
const firmware = obciUtils.getFirmware(dataBuffer);
1896+
if (firmware) {
1897+
if (firmware.major === 2) {
1898+
this.info.firmware = k.OBCIFirmwareV2;
1899+
} else {
1900+
this.info.firmware = k.OBCIFirmwareV3;
1901+
}
18681902
this.writeOutDelay = k.OBCIWriteIntervalDelayMSNone;
18691903
} else {
18701904
this.info.firmware = k.OBCIFirmwareV1;
@@ -2073,7 +2107,7 @@ Cyton.prototype._finalizeNewSample = function (sampleObject) {
20732107
} else {
20742108
// With the daisy board attached, lower channels (1-8) come in packets with odd sample numbers and upper
20752109
// channels (9-16) come in packets with even sample numbers
2076-
if (this.getBoardType() === k.OBCIBoardDaisy) {
2110+
if (_.eq(this.getBoardType(), k.OBCIBoardDaisy)) {
20772111
// Send the sample for downstream sample compaction
20782112
this._finalizeNewSampleForDaisy(sampleObject);
20792113
} else {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openbci",
3-
"version": "2.1.0",
3+
"version": "2.1.1",
44
"description": "The official Node.js SDK for the OpenBCI Biosensor Board.",
55
"main": "index.js",
66
"scripts": {
@@ -21,7 +21,7 @@
2121
"gaussian": "^1.0.0",
2222
"lodash": "^4.17.4",
2323
"mathjs": "^3.14.2",
24-
"openbci-utilities": "0.0.10",
24+
"openbci-utilities": "0.1.0",
2525
"performance-now": "^2.1.0",
2626
"safe-buffer": "^5.1.1",
2727
"serialport": "4.0.7",

test/openBCICyton-test.js

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ $$$`);
20382038
var buf = new Buffer(`OpenBCI V3 Simulator
20392039
On Board ADS1299 Device ID: 0x12345
20402040
LIS3DH Device ID: 0x38422
2041-
Firmware: v2
2041+
Firmware: v2.0.0
20422042
$$$`);
20432043

20442044
ourBoard._processParseBufferForReset(buf);
@@ -2048,12 +2048,26 @@ $$$`);
20482048
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate250);
20492049
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsCyton);
20502050
});
2051+
it('should recognize firmware version 3 with no daisy', () => {
2052+
var buf = new Buffer(`OpenBCI V3 Simulator
2053+
On Board ADS1299 Device ID: 0x12345
2054+
LIS3DH Device ID: 0x38422
2055+
Firmware: v3.0.1
2056+
$$$`);
2057+
2058+
ourBoard._processParseBufferForReset(buf);
2059+
2060+
ourBoard.info.firmware.should.equal(k.OBCIFirmwareV3);
2061+
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardCyton);
2062+
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate250);
2063+
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsCyton);
2064+
});
20512065
it('should recognize firmware version 2 with daisy', () => {
20522066
var buf = new Buffer(`OpenBCI V3 Simulator
20532067
On Board ADS1299 Device ID: 0x12345
20542068
On Daisy ADS1299 Device ID: 0xFFFFF
20552069
LIS3DH Device ID: 0x38422
2056-
Firmware: v2
2070+
Firmware: v2.0.0
20572071
$$$`);
20582072

20592073
ourBoard._processParseBufferForReset(buf);
@@ -2063,6 +2077,21 @@ $$$`);
20632077
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate125);
20642078
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsDaisy);
20652079
});
2080+
it('should recognize firmware version 3 with daisy', () => {
2081+
var buf = new Buffer(`OpenBCI V3 Simulator
2082+
On Board ADS1299 Device ID: 0x12345
2083+
On Daisy ADS1299 Device ID: 0xFFFFF
2084+
LIS3DH Device ID: 0x38422
2085+
Firmware: v3.1.69
2086+
$$$`);
2087+
2088+
ourBoard._processParseBufferForReset(buf);
2089+
2090+
ourBoard.info.firmware.should.equal(k.OBCIFirmwareV3);
2091+
expect(ourBoard.getBoardType()).to.equal(k.OBCIBoardDaisy);
2092+
expect(ourBoard.sampleRate()).to.equal(k.OBCISampleRate125);
2093+
expect(ourBoard.numberOfChannels()).to.equal(k.OBCINumberOfChannelsDaisy);
2094+
});
20662095
});
20672096

20682097
describe('#_processBytes', function () {
@@ -2507,6 +2536,42 @@ $$$`);
25072536
});
25082537
});
25092538

2539+
describe('#usingVersionThreeFirmware', function () {
2540+
after(() => bluebirdChecks.noPendingPromises());
2541+
it('should return true if firmware is version 3', () => {
2542+
ourBoard = new Cyton();
2543+
ourBoard.info.firmware = 'v3';
2544+
2545+
expect(ourBoard.usingVersionThreeFirmware()).to.be.true();
2546+
});
2547+
it('should return false if not firmware version 3', () => {
2548+
ourBoard = new Cyton();
2549+
2550+
expect(ourBoard.usingVersionThreeFirmware()).to.be.false();
2551+
});
2552+
});
2553+
2554+
describe('#usingAtLeastVersionTwoFirmware', function () {
2555+
after(() => bluebirdChecks.noPendingPromises());
2556+
it('should return true if firmware is version 3', () => {
2557+
ourBoard = new Cyton();
2558+
ourBoard.info.firmware = 'v2';
2559+
2560+
expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.true();
2561+
});
2562+
it('should return true if firmware is version 3', () => {
2563+
ourBoard = new Cyton();
2564+
ourBoard.info.firmware = 'v3';
2565+
2566+
expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.true();
2567+
});
2568+
it('should return false if not firmware version 3', () => {
2569+
ourBoard = new Cyton();
2570+
2571+
expect(ourBoard.usingAtLeastVersionTwoFirmware()).to.be.false();
2572+
});
2573+
});
2574+
25102575
xdescribe('#hardwareValidation', function () {
25112576
this.timeout(20000); // long timeout for pleanty of stream time :)
25122577
var runHardwareValidation = true;

0 commit comments

Comments
 (0)