diff --git a/serial-eeg-test-your-strength/.modules b/serial-eeg-test-your-strength/.modules
new file mode 100644
index 0000000..0df71d8
--- /dev/null
+++ b/serial-eeg-test-your-strength/.modules
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/serial-eeg-test-your-strength/.project b/serial-eeg-test-your-strength/.project
new file mode 100644
index 0000000..a4ca27d
--- /dev/null
+++ b/serial-eeg-test-your-strength/.project
@@ -0,0 +1,17 @@
+
+
+ Maker Faire 2015 demo
+
+
+
+
+
+ com.marvell.kinoma.kpr.kprBuilder
+
+
+
+
+
+ com.marvell.kinoma.kpr.application
+
+
diff --git a/serial-eeg-test-your-strength/application.xml b/serial-eeg-test-your-strength/application.xml
new file mode 100644
index 0000000..20eeda6
--- /dev/null
+++ b/serial-eeg-test-your-strength/application.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/serial-eeg-test-your-strength/device/MindSetSerial.js b/serial-eeg-test-your-strength/device/MindSetSerial.js
new file mode 100644
index 0000000..bb951c3
--- /dev/null
+++ b/serial-eeg-test-your-strength/device/MindSetSerial.js
@@ -0,0 +1,210 @@
+//@module
+/**************************************************************************************
+Mindset Serial BLL for Kinoma Create
+(c) 2015 Marvell Semiconductor, Inc.
+
+This BLL works with EEG headsets powered by the Neurosky Mindset chip,
+including the MindFlex and the Star Wars® Force Trainer™, when modified
+to connect the T pin (and R pin) and ground from the headset to the
+serial connections on the Kinoma Create.
+
+It exports one function, read() that is meant to be called from a repeat
+in the main program with timer=eeg as a query parameter instead of an interval, i.e.:
+
+msg = new MessageWithObject("pins:/sensor/read?repeat=on&timer=eeg&callback=/gotData")
+
+It will capture the packet, parse it into a JSON object and return it as the
+requestObject property of the message to the callback function in the main program.
+
+Based on mindset_communications_protocol.pdf (6/28/2010) from the Neurosky Mindset SDK.
+***************************************************************************************/
+var SYNC_BYTE=0xAA; // decimal 170, there are two preceding each packet
+var MAX_PAYLOAD_LENGTH = 169
+
+exports.pins = {
+ eeg:{type:"Serial", baud:9600}
+}
+
+exports.configure = function() {
+ trace("Initializing headset input...\n");
+ this.eeg.init();
+ this.eegPowerLength = 0;
+ this.lastByte = null
+ return
+}
+
+exports.read = function() {
+ var chunk = this.eeg.read("chunk");
+ if(chunk.length==0) return {}; // only needed when using intervals instead of timers in main
+ var buffer = {
+ checksum:0,
+ data:new Array(chunk.length),
+ payloadLength:0,
+ resultData: {},
+ };
+ // Need some array methods not available with chunks
+ for(var u = 0; u < chunk.length; u++) buffer.data[u] = chunk[u];
+
+ if (buffer.data.length < 8) return {error: "Partial Packet!"};
+ // if chunk doesn't start with two sync bytes, it's a bad packet
+ if(hasSyncBytes(buffer)) {
+ buffer.data.splice(0,2) // discard sync bytes
+ } else {
+ return {error:"Bad sync sequence!"};
+ }
+
+ // First byte should now be length byte, and be less than MAX_PAYLOAD_LENGTH
+ if(hasLengthByte(buffer)) {
+ buffer.payloadLength = buffer.data.shift();
+ } else {
+ return {error:"Invalid length byte!"};
+ }
+
+ buffer.checksum = buffer.data.pop(); //checksum is last byte
+
+ if(buffer.payloadLength != buffer.data.length) {
+ trace ("Bad packet: Says length is " + buffer.payloadLength + " but appears to actually be " + buffer.data.length + ".\n");
+ return {error:"Buffer size mismatch!"};
+ } else {
+ buffer.payload = buffer.data
+ }
+
+ if(checksumMatches(buffer.checksum, buffer.data)) {
+ buffer.resultData = parsePayload(buffer);
+ return buffer.resultData;
+ } else {
+ return {error:"Checksum failed!"}
+ }
+}
+
+var hasSyncBytes = function(packet) {
+ if(packet.data[0] == SYNC_BYTE && packet.data[1] == SYNC_BYTE) {
+ return true;
+ } else {
+ return false
+ }
+}
+
+var hasLengthByte = function(packet) {
+ var lengthByte = packet.data[0];
+ var packetLength = packet.data.length-2 // not considering length or checksum bytes
+ if(lengthByte == 0) {
+ trace("Bad packet: Says length is " + lengthByte + ".\n");
+ return false;
+ }
+
+ if(lengthByte > MAX_PAYLOAD_LENGTH) {
+ trace("Payload too long: " + lengthByte + "! (maximum " + MAX_PAYLOAD_LENGTH + ")\n");
+ return false;
+ }
+
+ if(lengthByte > packetLength) {
+ trace("Payload too long or packet truncated; says it is" + lengthByte + " bytes, but payload length is " + packetLength + " bytes.\n");
+ return false;
+ }
+
+ return true;
+}
+
+var numOfSyncBytes = function(chunk) {
+ var syncByteCount = 0;
+ for( var c = 0; c < chunk.length; c++) {
+ if(chunk[c] == SYNC_BYTE) syncByteCount++;
+ }
+ return syncByteCount;
+}
+
+var checksumMatches = function(checksum, data) {
+ var sum = 0;
+ for( var c = 0; c < data.length; c++) {
+ sum += data[c];
+ }
+ // Checksum byte is 1's complement of least significant byte of sum of all payload packets
+ sum = 255 - (sum % 256);
+ if (sum == checksum) {
+ return true;
+ } else {
+ // Checksum mismatch, send an error.
+ debugger;
+ trace("ERROR: Checksum does not match, was " + sum + ", expected " + checksum + ".\n");
+ return false;
+ }
+}
+
+var parsePayload = function(buffer) {
+ var payload = buffer.data;
+ var result = {
+ error:null,
+ signalQuality:200,
+ attention:0,
+ meditation:0
+ };
+ var payloadLength = buffer.payloadLength;
+ var parseSuccess = true
+ var excodeLevel = 0;
+ // Loop through the packet, extracting data.
+
+ for (var i = 0; i < payloadLength; i++) {
+ switch (payload[i]) {
+ case 0x2:
+ result.signalQuality = payload[++i];
+ break;
+ case 0x4:
+ result.attention = payload[++i];
+ break;
+ case 0x5:
+ result.meditation = payload[++i];
+ break;
+ case 0x83:
+ // Force Trainer only has this in first packet after powerup
+ /*
+ // Next byte is the length
+ if(payload[++i] != 24) {
+ result.error = "EEG band power data should be 24 bytes, but is " + payload[i] + "bytes.";
+ break;
+ }
+ // Eight sets of three bytes for the values. Documentation is contradictory but
+ // data appears to be big-endian
+ result.delta = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.theta = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.lowAlpha = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.highAlpha = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.lowBeta = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.highBeta = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.lowGamma = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ result.midGamma = (payload[++i] << 16) | (payload[++i] << 8) | payload[++i];
+ */
+ break;
+ case 0x80:
+ // Raw wave power. From the docs:
+ // "a single big -endian 16 -bit two's-compliment signed value (high -order byte followed by low -order byte) (-32768 to 32767)"
+ result.rawPower = (payload[++i] << 8) | payload[++i];
+ break;
+ case 0x55:
+ //Extended codes
+ while(payload[i] == 0x55) {
+ excodeLevel++
+ i++
+ }
+ trace("Extended code 0x" + payload[i].toString(16) + " not currently supported, skipping over data.\n");
+ if(payload[i] < 0x80) { //single byte code
+ i++
+ } else { // multibyte code, next byte is length
+ for (var s = 0; s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file