mindflex

Dependencies:   mbed Arduino millis

Committer:
harrisonstatham
Date:
Thu Oct 11 18:26:36 2018 +0000
Revision:
1:c8dd92fc8aa8
Parent:
0:6466440bff3a
Added harry;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kbeck8 0:6466440bff3a 1 #include "mbed.h"
kbeck8 0:6466440bff3a 2 #include "Brain.h"
kbeck8 0:6466440bff3a 3
kbeck8 0:6466440bff3a 4 Brain::Brain(Stream &_brainStream) {
kbeck8 0:6466440bff3a 5 brainStream = &_brainStream;
kbeck8 0:6466440bff3a 6
kbeck8 0:6466440bff3a 7 // Keep the rest of the initialization process in a separate method in case
kbeck8 0:6466440bff3a 8 // we overload the constructor.
kbeck8 0:6466440bff3a 9 init();
kbeck8 0:6466440bff3a 10 }
kbeck8 0:6466440bff3a 11
kbeck8 0:6466440bff3a 12 void Brain::init() {
kbeck8 0:6466440bff3a 13 // It's up to the calling code to start the stream
kbeck8 0:6466440bff3a 14 // Usually Serial.begin(9600);
kbeck8 0:6466440bff3a 15 freshPacket = false;
kbeck8 0:6466440bff3a 16 inPacket = false;
kbeck8 0:6466440bff3a 17 packetIndex = 0;
kbeck8 0:6466440bff3a 18 packetLength = 0;
kbeck8 0:6466440bff3a 19 eegPowerLength = 0;
kbeck8 0:6466440bff3a 20 hasPower = false;
kbeck8 0:6466440bff3a 21 checksum = 0;
kbeck8 0:6466440bff3a 22 checksumAccumulator = 0;
kbeck8 0:6466440bff3a 23
kbeck8 0:6466440bff3a 24 signalQuality = 200;
kbeck8 0:6466440bff3a 25 attention = 0;
kbeck8 0:6466440bff3a 26 meditation = 0;
kbeck8 0:6466440bff3a 27
kbeck8 0:6466440bff3a 28 clearEegPower();
kbeck8 0:6466440bff3a 29 }
kbeck8 0:6466440bff3a 30
kbeck8 0:6466440bff3a 31 boolean Brain::update() {
kbeck8 0:6466440bff3a 32 if (brainStream->available()) {
kbeck8 0:6466440bff3a 33 latestByte = brainStream->read();
kbeck8 0:6466440bff3a 34
kbeck8 0:6466440bff3a 35 // Build a packet if we know we're and not just listening for sync bytes.
kbeck8 0:6466440bff3a 36 if (inPacket) {
kbeck8 0:6466440bff3a 37
kbeck8 0:6466440bff3a 38 // First byte after the sync bytes is the length of the upcoming packet.
kbeck8 0:6466440bff3a 39 if (packetIndex == 0) {
kbeck8 0:6466440bff3a 40 packetLength = latestByte;
kbeck8 0:6466440bff3a 41
kbeck8 0:6466440bff3a 42 // Catch error if packet is too long
kbeck8 0:6466440bff3a 43 if (packetLength > MAX_PACKET_LENGTH) {
kbeck8 0:6466440bff3a 44 // Packet exceeded max length
kbeck8 0:6466440bff3a 45 // Send an error
kbeck8 0:6466440bff3a 46 sprintf(latestError, "ERROR: Packet too long %i", packetLength);
kbeck8 0:6466440bff3a 47 inPacket = false;
kbeck8 0:6466440bff3a 48 }
kbeck8 0:6466440bff3a 49 }
kbeck8 0:6466440bff3a 50 else if (packetIndex <= packetLength) {
kbeck8 0:6466440bff3a 51 // Run of the mill data bytes.
kbeck8 0:6466440bff3a 52
kbeck8 0:6466440bff3a 53 // Print them here
kbeck8 0:6466440bff3a 54
kbeck8 0:6466440bff3a 55 // Store the byte in an array for parsing later.
kbeck8 0:6466440bff3a 56 packetData[packetIndex - 1] = latestByte;
kbeck8 0:6466440bff3a 57
kbeck8 0:6466440bff3a 58 // Keep building the checksum.
kbeck8 0:6466440bff3a 59 checksumAccumulator += latestByte;
kbeck8 0:6466440bff3a 60 }
kbeck8 0:6466440bff3a 61 else if (packetIndex > packetLength) {
kbeck8 0:6466440bff3a 62 // We're at the end of the data payload.
kbeck8 0:6466440bff3a 63
kbeck8 0:6466440bff3a 64 // Check the checksum.
kbeck8 0:6466440bff3a 65 checksum = latestByte;
kbeck8 0:6466440bff3a 66 checksumAccumulator = 255 - checksumAccumulator;
kbeck8 0:6466440bff3a 67
kbeck8 0:6466440bff3a 68 // Do they match?
kbeck8 0:6466440bff3a 69 if (checksum == checksumAccumulator) {
kbeck8 0:6466440bff3a 70 boolean parseSuccess = parsePacket();
kbeck8 0:6466440bff3a 71
kbeck8 0:6466440bff3a 72 if (parseSuccess) {
kbeck8 0:6466440bff3a 73 freshPacket = true;
kbeck8 0:6466440bff3a 74 }
kbeck8 0:6466440bff3a 75 else {
kbeck8 0:6466440bff3a 76 // Parsing failed, send an error.
kbeck8 0:6466440bff3a 77 sprintf(latestError, "ERROR: Could not parse");
kbeck8 0:6466440bff3a 78 // good place to print the packet if debugging
kbeck8 0:6466440bff3a 79 }
kbeck8 0:6466440bff3a 80 }
kbeck8 0:6466440bff3a 81 else {
kbeck8 0:6466440bff3a 82 // Checksum mismatch, send an error.
kbeck8 0:6466440bff3a 83 sprintf(latestError, "ERROR: Checksum");
kbeck8 0:6466440bff3a 84 // good place to print the packet if debugging
kbeck8 0:6466440bff3a 85 }
kbeck8 0:6466440bff3a 86 // End of packet
kbeck8 0:6466440bff3a 87
kbeck8 0:6466440bff3a 88 // Reset, prep for next packet
kbeck8 0:6466440bff3a 89 inPacket = false;
kbeck8 0:6466440bff3a 90 }
kbeck8 0:6466440bff3a 91
kbeck8 0:6466440bff3a 92 packetIndex++;
kbeck8 0:6466440bff3a 93 }
kbeck8 0:6466440bff3a 94
kbeck8 0:6466440bff3a 95 // Look for the start of the packet
kbeck8 0:6466440bff3a 96 if ((latestByte == 170) && (lastByte == 170) && !inPacket) {
kbeck8 0:6466440bff3a 97 // Start of packet
kbeck8 0:6466440bff3a 98 inPacket = true;
kbeck8 0:6466440bff3a 99 packetIndex = 0;
kbeck8 0:6466440bff3a 100 checksumAccumulator = 0;
kbeck8 0:6466440bff3a 101 }
kbeck8 0:6466440bff3a 102
kbeck8 0:6466440bff3a 103 // Keep track of the last byte so we can find the sync byte pairs.
kbeck8 0:6466440bff3a 104 lastByte = latestByte;
kbeck8 0:6466440bff3a 105 }
kbeck8 0:6466440bff3a 106
kbeck8 0:6466440bff3a 107 if (freshPacket) {
kbeck8 0:6466440bff3a 108 freshPacket = false;
kbeck8 0:6466440bff3a 109 return true;
kbeck8 0:6466440bff3a 110 }
kbeck8 0:6466440bff3a 111 else {
kbeck8 0:6466440bff3a 112 return false;
kbeck8 0:6466440bff3a 113 }
kbeck8 0:6466440bff3a 114
kbeck8 0:6466440bff3a 115 }
kbeck8 0:6466440bff3a 116
kbeck8 0:6466440bff3a 117 void Brain::clearPacket() {
kbeck8 0:6466440bff3a 118 for (uint8_t i = 0; i < MAX_PACKET_LENGTH; i++) {
kbeck8 0:6466440bff3a 119 packetData[i] = 0;
kbeck8 0:6466440bff3a 120 }
kbeck8 0:6466440bff3a 121 }
kbeck8 0:6466440bff3a 122
kbeck8 0:6466440bff3a 123 void Brain::clearEegPower() {
kbeck8 0:6466440bff3a 124 // Zero the power bands.
kbeck8 0:6466440bff3a 125 for(uint8_t i = 0; i < EEG_POWER_BANDS; i++) {
kbeck8 0:6466440bff3a 126 eegPower[i] = 0;
kbeck8 0:6466440bff3a 127 }
kbeck8 0:6466440bff3a 128 }
kbeck8 0:6466440bff3a 129
kbeck8 0:6466440bff3a 130 boolean Brain::parsePacket() {
kbeck8 0:6466440bff3a 131 // Loop through the packet, extracting data.
kbeck8 0:6466440bff3a 132 // Based on mindset_communications_protocol.pdf from the Neurosky Mindset SDK.
kbeck8 0:6466440bff3a 133 // Returns true if passing succeeds
kbeck8 0:6466440bff3a 134 hasPower = false;
kbeck8 0:6466440bff3a 135 boolean parseSuccess = true;
kbeck8 0:6466440bff3a 136 int rawValue = 0;
kbeck8 0:6466440bff3a 137
kbeck8 0:6466440bff3a 138 clearEegPower(); // clear the eeg power to make sure we're honest about missing values
kbeck8 0:6466440bff3a 139
kbeck8 0:6466440bff3a 140 for (uint8_t i = 0; i < packetLength; i++) {
kbeck8 0:6466440bff3a 141 switch (packetData[i]) {
kbeck8 0:6466440bff3a 142 case 0x2:
kbeck8 0:6466440bff3a 143 signalQuality = packetData[++i];
kbeck8 0:6466440bff3a 144 break;
kbeck8 0:6466440bff3a 145 case 0x4:
kbeck8 0:6466440bff3a 146 attention = packetData[++i];
kbeck8 0:6466440bff3a 147 break;
kbeck8 0:6466440bff3a 148 case 0x5:
kbeck8 0:6466440bff3a 149 meditation = packetData[++i];
kbeck8 0:6466440bff3a 150 break;
kbeck8 0:6466440bff3a 151 case 0x83:
kbeck8 0:6466440bff3a 152 // ASIC_EEG_POWER: eight big-endian 3-uint8_t unsigned integer values representing delta, theta, low-alpha high-alpha, low-beta, high-beta, low-gamma, and mid-gamma EEG band power values
kbeck8 0:6466440bff3a 153 // The next uint8_t sets the length, usually 24 (Eight 24-bit numbers... big endian?)
kbeck8 0:6466440bff3a 154 // We dont' use this value so let's skip it and just increment i
kbeck8 0:6466440bff3a 155 i++;
kbeck8 0:6466440bff3a 156
kbeck8 0:6466440bff3a 157 // Extract the values
kbeck8 0:6466440bff3a 158 for (int j = 0; j < EEG_POWER_BANDS; j++) {
kbeck8 0:6466440bff3a 159 eegPower[j] = ((uint32_t)packetData[++i] << 16) | ((uint32_t)packetData[++i] << 8) | (uint32_t)packetData[++i];
kbeck8 0:6466440bff3a 160 }
kbeck8 0:6466440bff3a 161
kbeck8 0:6466440bff3a 162 hasPower = true;
kbeck8 0:6466440bff3a 163 // This seems to happen once during start-up on the force trainer. Strange. Wise to wait a couple of packets before
kbeck8 0:6466440bff3a 164 // you start reading.
kbeck8 0:6466440bff3a 165 break;
kbeck8 0:6466440bff3a 166 case 0x80:
kbeck8 0:6466440bff3a 167 // We dont' use this value so let's skip it and just increment i
kbeck8 0:6466440bff3a 168 // uint8_t packetLength = packetData[++i];
kbeck8 0:6466440bff3a 169 i++;
kbeck8 0:6466440bff3a 170 rawValue = ((int)packetData[++i] << 8) | packetData[++i];
kbeck8 0:6466440bff3a 171 break;
kbeck8 0:6466440bff3a 172 default:
kbeck8 0:6466440bff3a 173 // Broken packet ?
kbeck8 0:6466440bff3a 174 /*
kbeck8 0:6466440bff3a 175 Serial.print(F("parsePacket UNMATCHED data 0x"));
kbeck8 0:6466440bff3a 176 Serial.print(packetData[i], HEX);
kbeck8 0:6466440bff3a 177 Serial.print(F(" in position "));
kbeck8 0:6466440bff3a 178 Serial.print(i, DEC);
kbeck8 0:6466440bff3a 179 printPacket();
kbeck8 0:6466440bff3a 180 */
kbeck8 0:6466440bff3a 181 parseSuccess = false;
kbeck8 0:6466440bff3a 182 break;
kbeck8 0:6466440bff3a 183 }
kbeck8 0:6466440bff3a 184 }
kbeck8 0:6466440bff3a 185 return parseSuccess;
kbeck8 0:6466440bff3a 186 }
kbeck8 0:6466440bff3a 187
kbeck8 0:6466440bff3a 188 // Keeping this around for debug use
kbeck8 0:6466440bff3a 189 void Brain::printCSV() {
kbeck8 0:6466440bff3a 190 // Print the CSV over serial
kbeck8 0:6466440bff3a 191 brainStream->print(signalQuality, DEC);
kbeck8 0:6466440bff3a 192 brainStream->print(",");
kbeck8 0:6466440bff3a 193 brainStream->print(attention, DEC);
kbeck8 0:6466440bff3a 194 brainStream->print(",");
kbeck8 0:6466440bff3a 195 brainStream->print(meditation, DEC);
kbeck8 0:6466440bff3a 196
kbeck8 0:6466440bff3a 197 if (hasPower) {
kbeck8 0:6466440bff3a 198 for(int i = 0; i < EEG_POWER_BANDS; i++) {
kbeck8 0:6466440bff3a 199 brainStream->print(",");
kbeck8 0:6466440bff3a 200 brainStream->print(eegPower[i], DEC);
kbeck8 0:6466440bff3a 201 }
kbeck8 0:6466440bff3a 202 }
kbeck8 0:6466440bff3a 203
kbeck8 0:6466440bff3a 204 brainStream->println("");
kbeck8 0:6466440bff3a 205 }
kbeck8 0:6466440bff3a 206
kbeck8 0:6466440bff3a 207 char* Brain::readErrors() {
kbeck8 0:6466440bff3a 208 return latestError;
kbeck8 0:6466440bff3a 209 }
kbeck8 0:6466440bff3a 210
kbeck8 0:6466440bff3a 211 char* Brain::readCSV() {
kbeck8 0:6466440bff3a 212 // spit out a big string?
kbeck8 0:6466440bff3a 213 // find out how big this really needs to be
kbeck8 0:6466440bff3a 214 // should be popped off the stack once it goes out of scope?
kbeck8 0:6466440bff3a 215 // make the character array as small as possible
kbeck8 0:6466440bff3a 216
kbeck8 0:6466440bff3a 217 if(hasPower) {
kbeck8 0:6466440bff3a 218
kbeck8 0:6466440bff3a 219 sprintf(csvBuffer,"%d,%d,%d,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu",
kbeck8 0:6466440bff3a 220 signalQuality,
kbeck8 0:6466440bff3a 221 attention,
kbeck8 0:6466440bff3a 222 meditation,
kbeck8 0:6466440bff3a 223 eegPower[0],
kbeck8 0:6466440bff3a 224 eegPower[1],
kbeck8 0:6466440bff3a 225 eegPower[2],
kbeck8 0:6466440bff3a 226 eegPower[3],
kbeck8 0:6466440bff3a 227 eegPower[4],
kbeck8 0:6466440bff3a 228 eegPower[5],
kbeck8 0:6466440bff3a 229 eegPower[6],
kbeck8 0:6466440bff3a 230 eegPower[7]
kbeck8 0:6466440bff3a 231 );
kbeck8 0:6466440bff3a 232
kbeck8 0:6466440bff3a 233 return csvBuffer;
kbeck8 0:6466440bff3a 234 }
kbeck8 0:6466440bff3a 235 else {
kbeck8 0:6466440bff3a 236 sprintf(csvBuffer,"%d,%d,%d",
kbeck8 0:6466440bff3a 237 signalQuality,
kbeck8 0:6466440bff3a 238 attention,
kbeck8 0:6466440bff3a 239 meditation
kbeck8 0:6466440bff3a 240 );
kbeck8 0:6466440bff3a 241
kbeck8 0:6466440bff3a 242 return csvBuffer;
kbeck8 0:6466440bff3a 243 }
kbeck8 0:6466440bff3a 244 }
kbeck8 0:6466440bff3a 245
kbeck8 0:6466440bff3a 246 // For debugging, print the entire contents of the packet data array.
kbeck8 0:6466440bff3a 247 void Brain::printPacket() {
kbeck8 0:6466440bff3a 248 brainStream->print("[");
kbeck8 0:6466440bff3a 249 for (uint8_t i = 0; i < MAX_PACKET_LENGTH; i++) {
kbeck8 0:6466440bff3a 250 brainStream->print(packetData[i], DEC);
kbeck8 0:6466440bff3a 251
kbeck8 0:6466440bff3a 252 if (i < MAX_PACKET_LENGTH - 1) {
kbeck8 0:6466440bff3a 253 brainStream->print(", ");
kbeck8 0:6466440bff3a 254 }
kbeck8 0:6466440bff3a 255 }
kbeck8 0:6466440bff3a 256 brainStream->println("]");
kbeck8 0:6466440bff3a 257 }
kbeck8 0:6466440bff3a 258
kbeck8 0:6466440bff3a 259 void Brain::printDebug() {
kbeck8 0:6466440bff3a 260 brainStream->println("");
kbeck8 0:6466440bff3a 261 brainStream->println("--- Start Packet ---");
kbeck8 0:6466440bff3a 262 brainStream->print("Signal Quality: ");
kbeck8 0:6466440bff3a 263 brainStream->println(signalQuality, DEC);
kbeck8 0:6466440bff3a 264 brainStream->print("Attention: ");
kbeck8 0:6466440bff3a 265 brainStream->println(attention, DEC);
kbeck8 0:6466440bff3a 266 brainStream->print("Meditation: ");
kbeck8 0:6466440bff3a 267 brainStream->println(meditation, DEC);
kbeck8 0:6466440bff3a 268
kbeck8 0:6466440bff3a 269 if (hasPower) {
kbeck8 0:6466440bff3a 270 brainStream->println("");
kbeck8 0:6466440bff3a 271 brainStream->println("EEG POWER:");
kbeck8 0:6466440bff3a 272 brainStream->print("Delta: ");
kbeck8 0:6466440bff3a 273 brainStream->println(eegPower[0], DEC);
kbeck8 0:6466440bff3a 274 brainStream->print("Theta: ");
kbeck8 0:6466440bff3a 275 brainStream->println(eegPower[1], DEC);
kbeck8 0:6466440bff3a 276 brainStream->print("Low Alpha: ");
kbeck8 0:6466440bff3a 277 brainStream->println(eegPower[2], DEC);
kbeck8 0:6466440bff3a 278 brainStream->print("High Alpha: ");
kbeck8 0:6466440bff3a 279 brainStream->println(eegPower[3], DEC);
kbeck8 0:6466440bff3a 280 brainStream->print("Low Beta: ");
kbeck8 0:6466440bff3a 281 brainStream->println(eegPower[4], DEC);
kbeck8 0:6466440bff3a 282 brainStream->print("High Beta: ");
kbeck8 0:6466440bff3a 283 brainStream->println(eegPower[5], DEC);
kbeck8 0:6466440bff3a 284 brainStream->print("Low Gamma: ");
kbeck8 0:6466440bff3a 285 brainStream->println(eegPower[6], DEC);
kbeck8 0:6466440bff3a 286 brainStream->print("Mid Gamma: ");
kbeck8 0:6466440bff3a 287 brainStream->println(eegPower[7], DEC);
kbeck8 0:6466440bff3a 288 }
kbeck8 0:6466440bff3a 289
kbeck8 0:6466440bff3a 290 brainStream->println("");
kbeck8 0:6466440bff3a 291 brainStream->print("Checksum Calculated: ");
kbeck8 0:6466440bff3a 292 brainStream->println(checksumAccumulator, DEC);
kbeck8 0:6466440bff3a 293 brainStream->print("Checksum Expected: ");
kbeck8 0:6466440bff3a 294 brainStream->println(checksum, DEC);
kbeck8 0:6466440bff3a 295
kbeck8 0:6466440bff3a 296 brainStream->println("--- End Packet ---");
kbeck8 0:6466440bff3a 297 brainStream->println("");
kbeck8 0:6466440bff3a 298 }
kbeck8 0:6466440bff3a 299
kbeck8 0:6466440bff3a 300 uint8_t Brain::readSignalQuality() {
kbeck8 0:6466440bff3a 301 return signalQuality;
kbeck8 0:6466440bff3a 302 }
kbeck8 0:6466440bff3a 303
kbeck8 0:6466440bff3a 304 uint8_t Brain::readAttention() {
kbeck8 0:6466440bff3a 305 return attention;
kbeck8 0:6466440bff3a 306 }
kbeck8 0:6466440bff3a 307
kbeck8 0:6466440bff3a 308 uint8_t Brain::readMeditation() {
kbeck8 0:6466440bff3a 309 return meditation;
kbeck8 0:6466440bff3a 310 }
kbeck8 0:6466440bff3a 311
kbeck8 0:6466440bff3a 312 uint32_t* Brain::readPowerArray() {
kbeck8 0:6466440bff3a 313 return eegPower;
kbeck8 0:6466440bff3a 314 }
kbeck8 0:6466440bff3a 315
kbeck8 0:6466440bff3a 316 uint32_t Brain::readDelta() {
kbeck8 0:6466440bff3a 317 return eegPower[0];
kbeck8 0:6466440bff3a 318 }
kbeck8 0:6466440bff3a 319
kbeck8 0:6466440bff3a 320 uint32_t Brain::readTheta() {
kbeck8 0:6466440bff3a 321 return eegPower[1];
kbeck8 0:6466440bff3a 322 }
kbeck8 0:6466440bff3a 323
kbeck8 0:6466440bff3a 324 uint32_t Brain::readLowAlpha() {
kbeck8 0:6466440bff3a 325 return eegPower[2];
kbeck8 0:6466440bff3a 326 }
kbeck8 0:6466440bff3a 327
kbeck8 0:6466440bff3a 328 uint32_t Brain::readHighAlpha() {
kbeck8 0:6466440bff3a 329 return eegPower[3];
kbeck8 0:6466440bff3a 330 }
kbeck8 0:6466440bff3a 331
kbeck8 0:6466440bff3a 332 uint32_t Brain::readLowBeta() {
kbeck8 0:6466440bff3a 333 return eegPower[4];
kbeck8 0:6466440bff3a 334 }
kbeck8 0:6466440bff3a 335
kbeck8 0:6466440bff3a 336 uint32_t Brain::readHighBeta() {
kbeck8 0:6466440bff3a 337 return eegPower[5];
kbeck8 0:6466440bff3a 338 }
kbeck8 0:6466440bff3a 339
kbeck8 0:6466440bff3a 340 uint32_t Brain::readLowGamma() {
kbeck8 0:6466440bff3a 341 return eegPower[6];
kbeck8 0:6466440bff3a 342 }
kbeck8 0:6466440bff3a 343
kbeck8 0:6466440bff3a 344 uint32_t Brain::readMidGamma() {
kbeck8 0:6466440bff3a 345 return eegPower[7];
kbeck8 0:6466440bff3a 346 }