Bar-graph visualisation demo of reading data from Neurosky's Mindwave Mobile headset, reading via BlueSMIRF Silver bluetooth modem and displaying via MikroElektronika's TFT Proto 320x240 touchscreen.

Dependencies:   SPI_TFT TFT_fonts mbed

/media/uploads/RorschachUK/_scaled_p6040001.jpg

Uses MikroElektronika's low-cost TFT Proto 2.8" 320x240 touchscreen to display a bar graph representation of data coming in from NeuroSky's Mindwave Mobile brainwave-reading headset. Graphs the two main values coming in - Attention and Meditation, as well as the 8 individual frequency bands the headset processes. Also implements rudimentary blink-detection (top left) and quality of connection indicator (top right).

For a simpler program which doesn't use the screen and sends data to serial-debug, or for instructions on preparing the BlueSMIRF unit to connect to the Mindwave Mobile headset, visit:

Import programMindwave-basic

Basic serial-debug demo of reading and parsing data from Neurosky's Mindwave Mobile EEG headset via BlueSMIRF Silver bluetooth modem.

For info on how to connect the screen, see Peter Drescher's library page.

Committer:
RorschachUK
Date:
Tue Jun 04 17:55:00 2013 +0000
Revision:
0:b36d13636379
First commit of screen version of Mindwave demo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RorschachUK 0:b36d13636379 1 /* Mindwave Mobile demo - Bob Stone June 2013
RorschachUK 0:b36d13636379 2 * Visual demo of reading data packets from Neurosky's Mindwave Mobile headset
RorschachUK 0:b36d13636379 3 * via BlueSMIRF Silver bluetooth modem and displaying a simple visualisation on
RorschachUK 0:b36d13636379 4 * MikroElektronika's ProtoTFT screen.
RorschachUK 0:b36d13636379 5 * Adapted from http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino
RorschachUK 0:b36d13636379 6 * Display library from Peter Drescher: http://mbed.org/cookbook/SPI-driven-QVGA-TFT
RorschachUK 0:b36d13636379 7 *
RorschachUK 0:b36d13636379 8 * Connect pin9 to BlueSMIRF's RX and pin10 to BlueSMIRF's TX,
RorschachUK 0:b36d13636379 9 * also hook up GND to GND and VCC to the mbed's 3V3 supply.
RorschachUK 0:b36d13636379 10 *
RorschachUK 0:b36d13636379 11 * To prepare the BlueSMIRF to auto-connect to the Mindwave Mobile:
RorschachUK 0:b36d13636379 12 *
RorschachUK 0:b36d13636379 13 * First wire it up and power it using the mbed's power pins. Once it's powered,
RorschachUK 0:b36d13636379 14 * pair your computer to the Mindwave Mobile headset to you can
RorschachUK 0:b36d13636379 15 * find out its MAC address. Write that down as you will need it.
RorschachUK 0:b36d13636379 16 *
RorschachUK 0:b36d13636379 17 * Next pair your computer to the BlueSMIRF so we can configure it. It will
RorschachUK 0:b36d13636379 18 * appear as RN-42-5922 or similar (it's a Roving Networks RN-42 unit).
RorschachUK 0:b36d13636379 19 *
RorschachUK 0:b36d13636379 20 * Now we can use a terminal program to connect to the serial modem created on
RorschachUK 0:b36d13636379 21 * your computer that connects wirelessly to the BlueSMIRF - by default it's at
RorschachUK 0:b36d13636379 22 * 115200 baud, 8 N 1 - when you're connected the light will go green.
RorschachUK 0:b36d13636379 23 *
RorschachUK 0:b36d13636379 24 * If you've got a successful serial connection, put it into command mode by
RorschachUK 0:b36d13636379 25 * typing three dollar signs $$$ - if successful you should see a prompt saying
RorschachUK 0:b36d13636379 26 * 'CMD'. If not, power it down and try again till you get a CMD prompt.
RorschachUK 0:b36d13636379 27 *
RorschachUK 0:b36d13636379 28 * At that prompt we need to change some defaults so that the BlueSMIRF is set to
RorschachUK 0:b36d13636379 29 * master mode, 57600 baud and sends a pincode of '0000', and seeks to connect to
RorschachUK 0:b36d13636379 30 * the headset's MAC address. To do this, type:
RorschachUK 0:b36d13636379 31 * SP,0000
RorschachUK 0:b36d13636379 32 * SM,3
RorschachUK 0:b36d13636379 33 * SR,<the 12 digit MAC address of the headset written down earlier>
RorschachUK 0:b36d13636379 34 * SU,57.6
RorschachUK 0:b36d13636379 35 * D
RorschachUK 0:b36d13636379 36 * You should see AOK after each line, and after the D it will print out its
RorschachUK 0:b36d13636379 37 * settings so you can check it's now AUTO, 57600, using 0000 and the right MAC
RorschachUK 0:b36d13636379 38 * address. All being well, type three minuses '---' to exit command mode.
RorschachUK 0:b36d13636379 39 *
RorschachUK 0:b36d13636379 40 * To check it's working, close the terminal you've been using, reboot the
RorschachUK 0:b36d13636379 41 * BlueSMIRF (flashing red light) and switch on the Mindwave Mobile headset
RorschachUK 0:b36d13636379 42 * - the light on the BlueSMIRF should go green when it connects and the
RorschachUK 0:b36d13636379 43 * flashing blue light on the Mindwave Mobile headset should go steady blue.
RorschachUK 0:b36d13636379 44 */
RorschachUK 0:b36d13636379 45 #include "mbed.h"
RorschachUK 0:b36d13636379 46 #include "SPI_TFT.h"
RorschachUK 0:b36d13636379 47 #include "Arial12x12.h"
RorschachUK 0:b36d13636379 48 Serial blueSmirf(p9, p10); //for bluetooth comms (TX, RX)
RorschachUK 0:b36d13636379 49 SPI_TFT screen(p11, p12, p13, p14, p15, "TFT");
RorschachUK 0:b36d13636379 50 int quality=0;
RorschachUK 0:b36d13636379 51
RorschachUK 0:b36d13636379 52 //*****************************
RorschachUK 0:b36d13636379 53 //User routines to process data
RorschachUK 0:b36d13636379 54 //*****************************
RorschachUK 0:b36d13636379 55
RorschachUK 0:b36d13636379 56 /** Maps a value from one scale to another
RorschachUK 0:b36d13636379 57 *
RorschachUK 0:b36d13636379 58 * @param value Value we're trying to scale
RorschachUK 0:b36d13636379 59 * @param min,max The range that value came from
RorschachUK 0:b36d13636379 60 * @param newMin,newMax The new range we're scaling value into
RorschachUK 0:b36d13636379 61 * @returns value mapped into new scale
RorschachUK 0:b36d13636379 62 */
RorschachUK 0:b36d13636379 63 int map(int value, int min, int max, int newMin, int newMax) {
RorschachUK 0:b36d13636379 64 return newMin + (newMax-newMin) * (value-min) / (max-min);
RorschachUK 0:b36d13636379 65 }
RorschachUK 0:b36d13636379 66
RorschachUK 0:b36d13636379 67 /** Returns a 16-bit RGB565 colour from three 8-bit component values.
RorschachUK 0:b36d13636379 68 *
RorschachUK 0:b36d13636379 69 * @param red,green,blue primary colour channel values expressed as 0-255 each
RorschachUK 0:b36d13636379 70 * @returns 16-bit RGB565 colour constructed as RRRRRGGGGGGBBBBB
RorschachUK 0:b36d13636379 71 */
RorschachUK 0:b36d13636379 72 int RGBColour(int red, int green, int blue) {
RorschachUK 0:b36d13636379 73 //take most-significant parts of red, green and blue and bit-shift into RGB565 positions
RorschachUK 0:b36d13636379 74 return ((red & 0xf8) << 8) | ((green & 0xfc) << 3) | ((blue & 0xf8) >> 3);
RorschachUK 0:b36d13636379 75 }
RorschachUK 0:b36d13636379 76
RorschachUK 0:b36d13636379 77 /** Returns a colour mapped on a gradient from one colour to another.
RorschachUK 0:b36d13636379 78 *
RorschachUK 0:b36d13636379 79 * @param value Value we're trying to pick a colour for
RorschachUK 0:b36d13636379 80 * @param min,max Scale that value belongs in
RorschachUK 0:b36d13636379 81 * @param minColour,maxColour start and end colours of the gradient we're choosing from (16-bit RGB565)
RorschachUK 0:b36d13636379 82 * @returns colour that's as far along the gradient from minColour to maxColour as value is between min and max (16-bit RGB565)
RorschachUK 0:b36d13636379 83 */
RorschachUK 0:b36d13636379 84 int getMappedColour(int value, int min, int max, int minColour, int maxColour)
RorschachUK 0:b36d13636379 85 {
RorschachUK 0:b36d13636379 86 // TFT screen colours are 16-bit RGB565 i.e. RRRRRGGGGGGBBBBB
RorschachUK 0:b36d13636379 87 int minRed = (minColour & 0xf800) >> 11; //bitmask for 5 bits red
RorschachUK 0:b36d13636379 88 int maxRed = (maxColour & 0xf800) >> 11;
RorschachUK 0:b36d13636379 89 int minGreen = (minColour & 0x7e0) >> 5; //bitmask for 6 bits green
RorschachUK 0:b36d13636379 90 int maxGreen = (maxColour & 0x7e0) >> 5;
RorschachUK 0:b36d13636379 91 int minBlue = minColour & 0x1f; // bitmask for 5 bits blue
RorschachUK 0:b36d13636379 92 int maxBlue = maxColour & 0x1f;
RorschachUK 0:b36d13636379 93 int valRed = map(value, min, max, minRed, maxRed);
RorschachUK 0:b36d13636379 94 int valGreen = map(value, min, max, minGreen, maxGreen);
RorschachUK 0:b36d13636379 95 int valBlue = map(value, min, max, minBlue, maxBlue);
RorschachUK 0:b36d13636379 96 int valColour = ((valRed & 0x1F) << 11) | ((valGreen & 0x3F) << 5) | (valBlue & 0x1F);
RorschachUK 0:b36d13636379 97 return valColour;
RorschachUK 0:b36d13636379 98 }
RorschachUK 0:b36d13636379 99
RorschachUK 0:b36d13636379 100 /** Displays a bar graph showing 'value' on a scale 'min' to 'max', where coords (x0,y0) are at 'min' and (x1,y1) are at 'max'.
RorschachUK 0:b36d13636379 101 *
RorschachUK 0:b36d13636379 102 * @param x0,y0 coordinates of the 'min' end of the bargraph
RorschachUK 0:b36d13636379 103 * @param x1,y1 coordinates of the 'max' end of the bargraph
RorschachUK 0:b36d13636379 104 * @param isHorizontal If true, bar graph will be drawn with horizontal bars
RorschachUK 0:b36d13636379 105 * @param value Value of the bar, with bars drawn from min up to value, remaining 'backColour' from there to max
RorschachUK 0:b36d13636379 106 * @param min,max Scale of the bar graph that value should be found within
RorschachUK 0:b36d13636379 107 * @param minColour,maxColour colours at the min and max ends of the bar, drawn in a gradient between the two (16-bit RGB565)
RorschachUK 0:b36d13636379 108 * @param backColour background colour of the bar graph (16-bit RGB565)
RorschachUK 0:b36d13636379 109 */
RorschachUK 0:b36d13636379 110 void displayBarGraph(int x0, int y0, int x1, int y1, bool isHorizontal, int value, int min, int max, int minColour, int maxColour, int backColour)
RorschachUK 0:b36d13636379 111 {
RorschachUK 0:b36d13636379 112 int valColour;
RorschachUK 0:b36d13636379 113 if (isHorizontal) {
RorschachUK 0:b36d13636379 114 if (x1>x0)
RorschachUK 0:b36d13636379 115 {
RorschachUK 0:b36d13636379 116 for (int i = x0; i < x1; i+=5)
RorschachUK 0:b36d13636379 117 {
RorschachUK 0:b36d13636379 118 if (map(i, x0, x1, min, max) > value)
RorschachUK 0:b36d13636379 119 valColour = backColour;
RorschachUK 0:b36d13636379 120 else
RorschachUK 0:b36d13636379 121 valColour = getMappedColour(i, x0, x1, minColour, maxColour);
RorschachUK 0:b36d13636379 122 screen.fillrect(i, y0, i+3, y1, valColour);
RorschachUK 0:b36d13636379 123 }
RorschachUK 0:b36d13636379 124 } else {
RorschachUK 0:b36d13636379 125 for (int i = x1; i < x0; i+=5)
RorschachUK 0:b36d13636379 126 {
RorschachUK 0:b36d13636379 127 if (map(i, x0, x1, min, max) > value)
RorschachUK 0:b36d13636379 128 valColour = backColour;
RorschachUK 0:b36d13636379 129 else
RorschachUK 0:b36d13636379 130 valColour = getMappedColour(i, x0, x1, minColour, maxColour);
RorschachUK 0:b36d13636379 131 screen.fillrect(i-3, y0, i, y1, valColour);
RorschachUK 0:b36d13636379 132 }
RorschachUK 0:b36d13636379 133 }
RorschachUK 0:b36d13636379 134 } else {
RorschachUK 0:b36d13636379 135 if (y1>y0)
RorschachUK 0:b36d13636379 136 {
RorschachUK 0:b36d13636379 137 for (int i = y0; i < y1; i+=5)
RorschachUK 0:b36d13636379 138 {
RorschachUK 0:b36d13636379 139 if (map(i, y0, y1, min, max) > value)
RorschachUK 0:b36d13636379 140 valColour = backColour;
RorschachUK 0:b36d13636379 141 else
RorschachUK 0:b36d13636379 142 valColour = getMappedColour(i, y0, y1, minColour, maxColour);
RorschachUK 0:b36d13636379 143 screen.fillrect(x0, i, x1, i+3, valColour);
RorschachUK 0:b36d13636379 144 }
RorschachUK 0:b36d13636379 145 } else {
RorschachUK 0:b36d13636379 146 for (int i = y1; i < y0; i+=5)
RorschachUK 0:b36d13636379 147 {
RorschachUK 0:b36d13636379 148 if (map(i, y0, y1, min, max) > value)
RorschachUK 0:b36d13636379 149 valColour = backColour;
RorschachUK 0:b36d13636379 150 else
RorschachUK 0:b36d13636379 151 valColour = getMappedColour(i, y0, y1, minColour, maxColour);
RorschachUK 0:b36d13636379 152 screen.fillrect(x0, i-3, x1, i, valColour);
RorschachUK 0:b36d13636379 153 }
RorschachUK 0:b36d13636379 154 }
RorschachUK 0:b36d13636379 155 }
RorschachUK 0:b36d13636379 156 }
RorschachUK 0:b36d13636379 157
RorschachUK 0:b36d13636379 158 /** This will be called if you blink.
RorschachUK 0:b36d13636379 159 */
RorschachUK 0:b36d13636379 160 void blinked(void)
RorschachUK 0:b36d13636379 161 {
RorschachUK 0:b36d13636379 162 if (quality == 0) {
RorschachUK 0:b36d13636379 163 screen.locate(0,0);
RorschachUK 0:b36d13636379 164 printf("Blink!");
RorschachUK 0:b36d13636379 165 }
RorschachUK 0:b36d13636379 166 }
RorschachUK 0:b36d13636379 167
RorschachUK 0:b36d13636379 168 /** This will be called when processed eSense data comes in, about once a second.
RorschachUK 0:b36d13636379 169 *
RorschachUK 0:b36d13636379 170 * @param poorQuality will be 0 if connections are good, 200 if connections are useless, and somewhere in between if connection dodgy.
RorschachUK 0:b36d13636379 171 * @param attention processed percentage denoting focus and attention. 0 to 100
RorschachUK 0:b36d13636379 172 * @param meditation processed percentage denoting calmness and serenity. 0 to 100
RorschachUK 0:b36d13636379 173 * @param timeSinceLastPacket time since last packet processed, in milliseconds.
RorschachUK 0:b36d13636379 174 */
RorschachUK 0:b36d13636379 175 void eSenseData(int poorQuality, int attention, int meditation, int timeSinceLastPacket)
RorschachUK 0:b36d13636379 176 {
RorschachUK 0:b36d13636379 177 quality=poorQuality;
RorschachUK 0:b36d13636379 178 if (poorQuality == 200)
RorschachUK 0:b36d13636379 179 screen.fillrect(313, 3, 317, 7, Red);
RorschachUK 0:b36d13636379 180 else if (poorQuality == 0)
RorschachUK 0:b36d13636379 181 screen.fillrect(313, 3, 317, 7, Green);
RorschachUK 0:b36d13636379 182 else
RorschachUK 0:b36d13636379 183 screen.fillrect(313, 3, 317, 7, Yellow);
RorschachUK 0:b36d13636379 184
RorschachUK 0:b36d13636379 185 if (attention > 0) {
RorschachUK 0:b36d13636379 186 displayBarGraph(50, 210, 75, 30, false, attention, 0, 100, RGBColour(0x10,0x00,0x00), RGBColour(0xFF,0x00,0x00), 0x00);
RorschachUK 0:b36d13636379 187 screen.locate(50, 225);
RorschachUK 0:b36d13636379 188 screen.foreground(Red);
RorschachUK 0:b36d13636379 189 screen.printf("%d ",attention);
RorschachUK 0:b36d13636379 190 screen.foreground(White); // set chars to white
RorschachUK 0:b36d13636379 191 }
RorschachUK 0:b36d13636379 192 if (meditation > 0) {
RorschachUK 0:b36d13636379 193 displayBarGraph(85, 210, 110, 30, false, meditation, 0, 100, RGBColour(0x00,0x10,0x00), RGBColour(0x00,0xFF,0x00), 0x00);
RorschachUK 0:b36d13636379 194 screen.locate(85, 225);
RorschachUK 0:b36d13636379 195 screen.foreground(Green);
RorschachUK 0:b36d13636379 196 screen.printf("%d ",meditation);
RorschachUK 0:b36d13636379 197 screen.foreground(White); // set chars to white
RorschachUK 0:b36d13636379 198 }
RorschachUK 0:b36d13636379 199 }
RorschachUK 0:b36d13636379 200
RorschachUK 0:b36d13636379 201 /** This will be called when processed meter reading data arrives, about once a second.
RorschachUK 0:b36d13636379 202 * This is a breakdown of frequencies in the wave data into 8 named bands, these are:
RorschachUK 0:b36d13636379 203 * 0: Delta (0.5-2.75 Hz)
RorschachUK 0:b36d13636379 204 * 1: Theta (3.5-6.75 Hz)
RorschachUK 0:b36d13636379 205 * 2: Low-Alpha (7.5-9.25 Hz)
RorschachUK 0:b36d13636379 206 * 3: High-Alpha (10-11.75 Hz)
RorschachUK 0:b36d13636379 207 * 4: Low-Beta (13-16.75 Hz)
RorschachUK 0:b36d13636379 208 * 5: High-Beta (18-29.75 Hz)
RorschachUK 0:b36d13636379 209 * 6: Low-Gamma (31-39.75 Hz)
RorschachUK 0:b36d13636379 210 * 7: High-Gamma (41-49.75 Hz)
RorschachUK 0:b36d13636379 211 *
RorschachUK 0:b36d13636379 212 * @param meter array of meter data for different frequency bands
RorschachUK 0:b36d13636379 213 * @param meterMin array of minimum recorded samples of each band
RorschachUK 0:b36d13636379 214 * @param meterMax arrat if naximum recorded samples of each band
RorschachUK 0:b36d13636379 215 */
RorschachUK 0:b36d13636379 216 void meterData(int meter[8], int meterMin[8], int meterMax[8])
RorschachUK 0:b36d13636379 217 {
RorschachUK 0:b36d13636379 218 for (int j=0; j<8; j++) {
RorschachUK 0:b36d13636379 219 displayBarGraph(160 + j * 15, 210, 170 + j * 15, 100, false, meter[j], meterMin[j], meterMax[j], RGBColour(0, j*2, 0x10), RGBColour(0, j*32, 0xFF), 0x00);
RorschachUK 0:b36d13636379 220 }
RorschachUK 0:b36d13636379 221 screen.locate(0,0);
RorschachUK 0:b36d13636379 222 printf(" ");
RorschachUK 0:b36d13636379 223 }
RorschachUK 0:b36d13636379 224
RorschachUK 0:b36d13636379 225 /** This will be called when wave data arrives.
RorschachUK 0:b36d13636379 226 * There will be a lot of these, 512 a second, so if you're planning to do anything
RorschachUK 0:b36d13636379 227 * here, don't let it take long. Best not to printf this out as it will just choke.
RorschachUK 0:b36d13636379 228 *
RorschachUK 0:b36d13636379 229 * param wave Raw wave data point
RorschachUK 0:b36d13636379 230 */
RorschachUK 0:b36d13636379 231 void waveData(int wave)
RorschachUK 0:b36d13636379 232 {
RorschachUK 0:b36d13636379 233 }
RorschachUK 0:b36d13636379 234
RorschachUK 0:b36d13636379 235 //*****************
RorschachUK 0:b36d13636379 236 //End User routines
RorschachUK 0:b36d13636379 237 //*****************
RorschachUK 0:b36d13636379 238
RorschachUK 0:b36d13636379 239 //System routines to obtain and parse data
RorschachUK 0:b36d13636379 240
RorschachUK 0:b36d13636379 241 /** Simplify serial comms
RorschachUK 0:b36d13636379 242 */
RorschachUK 0:b36d13636379 243 unsigned char ReadOneByte()
RorschachUK 0:b36d13636379 244 {
RorschachUK 0:b36d13636379 245 int ByteRead;
RorschachUK 0:b36d13636379 246
RorschachUK 0:b36d13636379 247 while(!blueSmirf.readable());
RorschachUK 0:b36d13636379 248 ByteRead = blueSmirf.getc();
RorschachUK 0:b36d13636379 249
RorschachUK 0:b36d13636379 250 return ByteRead;
RorschachUK 0:b36d13636379 251 }
RorschachUK 0:b36d13636379 252
RorschachUK 0:b36d13636379 253 /** Main loop, sets up and keeps listening for serial
RorschachUK 0:b36d13636379 254 */
RorschachUK 0:b36d13636379 255 int main()
RorschachUK 0:b36d13636379 256 {
RorschachUK 0:b36d13636379 257 //Video setup
RorschachUK 0:b36d13636379 258 screen.claim(stdout); // send stdout to the TFT display
RorschachUK 0:b36d13636379 259 screen.background(Black); // set background to black
RorschachUK 0:b36d13636379 260 screen.foreground(White); // set chars to white
RorschachUK 0:b36d13636379 261 screen.cls(); // clear the screen
RorschachUK 0:b36d13636379 262 screen.set_font((unsigned char*) Arial12x12);
RorschachUK 0:b36d13636379 263 screen.set_orientation(1);
RorschachUK 0:b36d13636379 264
RorschachUK 0:b36d13636379 265 screen.locate(50, 213);
RorschachUK 0:b36d13636379 266 screen.foreground(Red);
RorschachUK 0:b36d13636379 267 screen.printf("Att");
RorschachUK 0:b36d13636379 268 screen.locate(85, 213);
RorschachUK 0:b36d13636379 269 screen.foreground(Green);
RorschachUK 0:b36d13636379 270 screen.printf("Med");
RorschachUK 0:b36d13636379 271 for (int j = 0; j < 8; j++)
RorschachUK 0:b36d13636379 272 {
RorschachUK 0:b36d13636379 273 screen.locate(160 + j * 15, 213);
RorschachUK 0:b36d13636379 274 screen.foreground(RGBColour(0, j*32, 0xFF));
RorschachUK 0:b36d13636379 275 screen.printf("%d", j);
RorschachUK 0:b36d13636379 276 }
RorschachUK 0:b36d13636379 277 screen.foreground(White); // set chars to white
RorschachUK 0:b36d13636379 278
RorschachUK 0:b36d13636379 279 Timer t; //packet timer
RorschachUK 0:b36d13636379 280 t.start();
RorschachUK 0:b36d13636379 281 Timer blinkTimer; //used for detecting blinks
RorschachUK 0:b36d13636379 282 int time;
RorschachUK 0:b36d13636379 283 int generatedChecksum = 0;
RorschachUK 0:b36d13636379 284 int checksum = 0;
RorschachUK 0:b36d13636379 285 int payloadLength = 0;
RorschachUK 0:b36d13636379 286 int payloadData[64] = {0};
RorschachUK 0:b36d13636379 287 int poorQuality = 0;
RorschachUK 0:b36d13636379 288 int attention = 0;
RorschachUK 0:b36d13636379 289 int meditation = 0;
RorschachUK 0:b36d13636379 290 int wave = 0;
RorschachUK 0:b36d13636379 291 int meter[8] = {0};
RorschachUK 0:b36d13636379 292 int meterMin[8];
RorschachUK 0:b36d13636379 293 int meterMax[8];
RorschachUK 0:b36d13636379 294 for (int j = 0; j < 8; j++)
RorschachUK 0:b36d13636379 295 {
RorschachUK 0:b36d13636379 296 meterMin[j]=99999999;
RorschachUK 0:b36d13636379 297 meterMax[j]=-99999999;
RorschachUK 0:b36d13636379 298 }
RorschachUK 0:b36d13636379 299 bool eSensePacket = false;
RorschachUK 0:b36d13636379 300 bool meterPacket = false;
RorschachUK 0:b36d13636379 301 bool wavePacket = false;
RorschachUK 0:b36d13636379 302
RorschachUK 0:b36d13636379 303 blueSmirf.baud(57600);
RorschachUK 0:b36d13636379 304 blinkTimer.reset();
RorschachUK 0:b36d13636379 305
RorschachUK 0:b36d13636379 306 while(1) {
RorschachUK 0:b36d13636379 307 // Look for sync bytes
RorschachUK 0:b36d13636379 308 if(ReadOneByte() == 170) {
RorschachUK 0:b36d13636379 309 if(ReadOneByte() == 170) {
RorschachUK 0:b36d13636379 310 //Synchronised to start of packet
RorschachUK 0:b36d13636379 311 payloadLength = ReadOneByte();
RorschachUK 0:b36d13636379 312 if(payloadLength > 169) //Payload length can not be greater than 169
RorschachUK 0:b36d13636379 313 return;
RorschachUK 0:b36d13636379 314
RorschachUK 0:b36d13636379 315 generatedChecksum = 0;
RorschachUK 0:b36d13636379 316 for(int i = 0; i < payloadLength; i++) {
RorschachUK 0:b36d13636379 317 payloadData[i] = ReadOneByte(); //Read payload into memory
RorschachUK 0:b36d13636379 318 generatedChecksum += payloadData[i];
RorschachUK 0:b36d13636379 319 }
RorschachUK 0:b36d13636379 320
RorschachUK 0:b36d13636379 321 checksum = ReadOneByte(); //Read checksum byte from stream
RorschachUK 0:b36d13636379 322 generatedChecksum = 255 - (generatedChecksum & 0xFF); //Take one's compliment of generated checksum
RorschachUK 0:b36d13636379 323
RorschachUK 0:b36d13636379 324 if(checksum == generatedChecksum) {
RorschachUK 0:b36d13636379 325 //Packet seems OK
RorschachUK 0:b36d13636379 326 poorQuality = 200;
RorschachUK 0:b36d13636379 327 attention = 0;
RorschachUK 0:b36d13636379 328 meditation = 0;
RorschachUK 0:b36d13636379 329 wave = 0;
RorschachUK 0:b36d13636379 330 for(int i = 0; i < payloadLength; i++) { // Parse the payload
RorschachUK 0:b36d13636379 331 switch (payloadData[i]) {
RorschachUK 0:b36d13636379 332 case 2: //quality
RorschachUK 0:b36d13636379 333 i++;
RorschachUK 0:b36d13636379 334 poorQuality = payloadData[i];
RorschachUK 0:b36d13636379 335 eSensePacket = true;
RorschachUK 0:b36d13636379 336 break;
RorschachUK 0:b36d13636379 337 case 4: //attention
RorschachUK 0:b36d13636379 338 i++;
RorschachUK 0:b36d13636379 339 attention = payloadData[i];
RorschachUK 0:b36d13636379 340 eSensePacket = true;
RorschachUK 0:b36d13636379 341 break;
RorschachUK 0:b36d13636379 342 case 5: //meditation
RorschachUK 0:b36d13636379 343 i++;
RorschachUK 0:b36d13636379 344 meditation = payloadData[i];
RorschachUK 0:b36d13636379 345 eSensePacket = true;
RorschachUK 0:b36d13636379 346 break;
RorschachUK 0:b36d13636379 347 case 0x80: //wave
RorschachUK 0:b36d13636379 348 wave = payloadData[i+2] * 256 + payloadData[i+3];
RorschachUK 0:b36d13636379 349 //We also want to try to detect blinks via analysing wave data
RorschachUK 0:b36d13636379 350 time = blinkTimer.read_ms();
RorschachUK 0:b36d13636379 351 if (wave > 32767) wave -= 65535; //cope with negatives
RorschachUK 0:b36d13636379 352 if (wave>200 && time == 0) {
RorschachUK 0:b36d13636379 353 blinkTimer.start();
RorschachUK 0:b36d13636379 354 } else if (wave<-90 && time > 10 && time < 350) {
RorschachUK 0:b36d13636379 355 blinkTimer.stop();
RorschachUK 0:b36d13636379 356 blinkTimer.reset();
RorschachUK 0:b36d13636379 357 blinked();
RorschachUK 0:b36d13636379 358 } else if (time>500) {
RorschachUK 0:b36d13636379 359 blinkTimer.stop();
RorschachUK 0:b36d13636379 360 blinkTimer.reset();
RorschachUK 0:b36d13636379 361 }
RorschachUK 0:b36d13636379 362 i = i + 3;
RorschachUK 0:b36d13636379 363 wavePacket = true;
RorschachUK 0:b36d13636379 364 break;
RorschachUK 0:b36d13636379 365 case 0x83: //meter readings for different frequency bands
RorschachUK 0:b36d13636379 366 for (int j=0; j<8; j++) {
RorschachUK 0:b36d13636379 367 //documentation is inconsistent about whether these values are big-endian or little-endian,
RorschachUK 0:b36d13636379 368 //and claims both in different places. But wave data is big-endian so assuming that here.
RorschachUK 0:b36d13636379 369 meter[j] = payloadData[i+j*3+2]*65536 + payloadData[i+j*3+3]*256 + payloadData[i+j*3+4];
RorschachUK 0:b36d13636379 370 if (meter[j]<meterMin[j])
RorschachUK 0:b36d13636379 371 meterMin[j]=meter[j];
RorschachUK 0:b36d13636379 372 if (meter[j]>meterMax[j])
RorschachUK 0:b36d13636379 373 meterMax[j]=meter[j];
RorschachUK 0:b36d13636379 374 }
RorschachUK 0:b36d13636379 375 meterPacket = true;
RorschachUK 0:b36d13636379 376 i = i + 25;
RorschachUK 0:b36d13636379 377 break;
RorschachUK 0:b36d13636379 378 default:
RorschachUK 0:b36d13636379 379 break;
RorschachUK 0:b36d13636379 380 } // switch
RorschachUK 0:b36d13636379 381 } // for loop
RorschachUK 0:b36d13636379 382
RorschachUK 0:b36d13636379 383 //Call routines to process data
RorschachUK 0:b36d13636379 384 if(eSensePacket) {
RorschachUK 0:b36d13636379 385 eSenseData(poorQuality, attention, meditation, t.read_ms());
RorschachUK 0:b36d13636379 386 eSensePacket = false;
RorschachUK 0:b36d13636379 387 }
RorschachUK 0:b36d13636379 388 if (meterPacket) {
RorschachUK 0:b36d13636379 389 meterData(meter, meterMin, meterMax);
RorschachUK 0:b36d13636379 390 t.reset();
RorschachUK 0:b36d13636379 391 meterPacket=false;
RorschachUK 0:b36d13636379 392 }
RorschachUK 0:b36d13636379 393 if (wavePacket) {
RorschachUK 0:b36d13636379 394 waveData(wave);
RorschachUK 0:b36d13636379 395 wavePacket=false;
RorschachUK 0:b36d13636379 396 }
RorschachUK 0:b36d13636379 397 } else {
RorschachUK 0:b36d13636379 398 // Checksum Error
RorschachUK 0:b36d13636379 399 } // end if else for checksum
RorschachUK 0:b36d13636379 400 } // end if read 0xAA byte
RorschachUK 0:b36d13636379 401 } // end if read 0xAA byte
RorschachUK 0:b36d13636379 402 }
RorschachUK 0:b36d13636379 403 }