Bob Stone / Mbed 2 deprecated Mindwave-basic

Dependencies:   mbed

Revision:
0:7a3f4ba1851c
Child:
1:fac5c6ba2f07
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jun 02 16:04:19 2013 +0000
@@ -0,0 +1,235 @@
+/* Mindwave Mobile demo - Bob Stone June 2013
+ * Basic demo of reading data packets from Neurosky's Mindwave Mobile headset
+ * via BlueSMIRF Silver bluetooth modem.
+ * Adapted from http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino
+ *
+ * Connect pin9 to BlueSMIRF's RX and pin10 to BlueSMIRF's TX,
+ * also hook up GND to GND and VCC to the mbed's 3V3 supply.
+ *
+ * To prepare the BlueSMIRF to auto-connect to the Mindwave Mobile:
+ *
+ * First wire it up and power it using the mbed's power pins.  Once it's powered,
+ * pair your computer to the Mindwave Mobile headset to you can
+ * find out its MAC address.  Write that down as you will need it.
+ *
+ * Next pair your computer to the BlueSMIRF so we can configure it.  It will
+ * appear as RN-42-5922 or similar (it's a Roving Networks RN-42 unit).
+ *
+ * Now we can use a terminal program to connect to the serial modem created on
+ * your computer that connects wirelessly to the BlueSMIRF - by default it's at
+ * 115200 baud, 8 N 1 - when you're connected the light will go green.
+ *
+ * If you've got a successful serial connection, put it into command mode by
+ * typing three dollar signs $$$ - if successful you should see a prompt saying 
+ * 'CMD'.  If not, power it down and try again till you get a CMD prompt.
+ * 
+ * At that prompt we need to change some defaults so that the BlueSMIRF is set to
+ * master mode, 57600 baud and sends a pincode of '0000', and seeks to connect to
+ * the headset's MAC address.  To do this, type:
+ *  SP,0000
+ *  SM,3
+ *  SR,<the 12 digit MAC address of the headset written down earlier>
+ *  SU,57.6
+ *  D
+ * You should see AOK after each line, and after the D it will print out its 
+ * settings so you can check it's now AUTO, 57600, using 0000 and the right MAC
+ * address.  All being well, type three minuses '---' to exit command mode.
+ * 
+ * To check it's working, close the terminal you've been using, reboot the 
+ * BlueSMIRF (flashing red light) and switch on the Mindwave Mobile headset
+ * - the light on the BlueSMIRF should go green when it connects and the 
+ * flashing blue light on the Mindwave Mobile headset should go steady blue.
+ */
+#include "mbed.h"
+Serial pc(USBTX, USBRX);    //for debug
+Serial blueSmirf(p9, p10);  //for bluetooth comms (TX, RX)
+
+//*****************************
+//User routines to process data
+//*****************************
+
+//This will be called if you blink.
+void blinked(void)
+{
+    printf("\nBlink!\n\n");
+}
+
+//This will be called when processed eSense data comes in, about once a second.  If the
+//connection's good, poorQuality will be zero, if the connection's useless (e.g. ear clip
+//or forehead electrode not connected)it will be 200, and it can be somewhere in between 
+//for varying degrees of confidence in the data.  Values for attention and meditation are 
+//0-100, and the time since last packet is in milliseconds.
+void eSenseData(int poorQuality, int attention, int meditation, int timeSinceLastPacket)
+{
+    if (poorQuality < 200) {
+        printf("PoorQuality: %d", poorQuality);
+    }
+    if (attention > 0) {
+        printf(" Attention: %d", attention);
+    }
+    if (meditation > 0) {
+        printf(" Meditation: %d", meditation);
+    }
+    printf(" Time since last packet: %d", timeSinceLastPacket);
+    printf("\n");
+}
+
+//This will be called when processed meter reading data arrives, about once a second.
+//This is a breakdown of frequencies in the wave data into 8 named bands, these are:
+//  0: Delta        (0.5-2.75 Hz)
+//  1: Theta        (3.5-6.75 Hz)
+//  2: Low-Alpha    (7.5-9.25 Hz)
+//  3: High-Alpha   (10-11.75 Hz)
+//  4: Low-Beta     (13-16.75 Hz)
+//  5: High-Beta    (18-29.75 Hz)
+//  6: Low-Gamma    (31-39.75 Hz)
+//  7: High-Gamma   (41-49.75 Hz)
+void meterData(int meter[8])
+{
+    printf("Meters: ");
+    for (int j=0; j<8; j++) {
+        printf("%d = %d, ", j, meter[j]);
+    }
+    printf("\n");
+}
+
+//This will be called when wave data arrives.  There will be a lot of these,
+//512 a second, so if you're planning to do anything here, don't let it take long.
+//Best not to printf this out as it will just choke.
+void waveData(int wave)
+{
+}
+
+//*****************
+//End User routines
+//*****************
+
+//System routines to obtain and parse data
+//Simplify serial comms
+unsigned char ReadOneByte()
+{
+    int ByteRead;
+
+    while(!blueSmirf.readable());
+    ByteRead = blueSmirf.getc();
+
+    return ByteRead;
+}
+//Main loop, sets up and keeps listening for serial
+int main()
+{
+    Timer t; //packet timer
+    t.start();
+    Timer blinkTimer; //used for detecting blinks
+    int time;
+    int generatedChecksum = 0;
+    int checksum = 0;
+    int payloadLength = 0;
+    int payloadData[64] = {0};
+    int poorQuality = 0;
+    int attention = 0;
+    int meditation = 0;
+    int wave = 0;
+    int meter[8] = {0};
+
+    bool eSensePacket = false;
+    bool meterPacket = false;
+    bool wavePacket = false;
+
+    blueSmirf.baud(57600);
+    pc.baud(115200);
+    printf("\n\nStarted\n\n");
+    blinkTimer.reset();
+
+    while(1) {
+        // Look for sync bytes
+        if(ReadOneByte() == 170) {
+            if(ReadOneByte() == 170) {
+                //Synchronised to start of packet
+                payloadLength = ReadOneByte();
+                if(payloadLength > 169) //Payload length can not be greater than 169
+                    return;
+
+                generatedChecksum = 0;
+                for(int i = 0; i < payloadLength; i++) {
+                    payloadData[i] = ReadOneByte();            //Read payload into memory
+                    generatedChecksum += payloadData[i];
+                }
+
+                checksum = ReadOneByte();                      //Read checksum byte from stream
+                generatedChecksum = 255 - (generatedChecksum & 0xFF);   //Take one's compliment of generated checksum
+
+                if(checksum == generatedChecksum) {
+                    //Packet seems OK
+                    poorQuality = 200;
+                    attention = 0;
+                    meditation = 0;
+                    wave = 0;
+                    for(int i = 0; i < payloadLength; i++) {    // Parse the payload
+                        switch (payloadData[i]) {
+                            case 2: //quality
+                                i++;
+                                poorQuality = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 4: //attention
+                                i++;
+                                attention = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 5: //meditation
+                                i++;
+                                meditation = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 0x80: //wave
+                                wave = payloadData[i+2] * 256 + payloadData[i+3];
+                                //We also want to try to detect blinks via analysing wave data
+                                time = blinkTimer.read_ms();
+                                if (wave > 32767) wave -= 65535; //cope with negatives
+                                if (wave>200 && blinkTimer.read_ms() == 0) {
+                                    blinkTimer.start();
+                                } else if (wave<-90 && time > 10 && time < 100) {
+                                    blinkTimer.stop();
+                                    blinkTimer.reset();
+                                    blinked();
+                                } else if (time>500) {
+                                    blinkTimer.stop();
+                                    blinkTimer.reset();
+                                }
+                                i = i + 3;
+                                wavePacket = true;
+                                break;
+                            case 0x83: //meter readings for different frequency bands
+                                for (int j=0; j<8; j++) {
+                                    meter[j] = payloadData[i+j*3+2] + payloadData[i+j*3+3]*256 + payloadData[i+j*3+4]*65536;
+                                }
+                                meterPacket = true;
+                                i = i + 25;
+                                break;
+                            default:
+                                break;
+                        } // switch
+                    } // for loop
+
+                    //Call routines to process data
+                    if(eSensePacket) {
+                        eSenseData(poorQuality, attention, meditation, t.read_ms());
+                        eSensePacket = false;
+                    }
+                    if (meterPacket) {
+                        meterData(meter);
+                        t.reset();
+                        meterPacket=false;
+                    }
+                    if (wavePacket) {
+                        waveData(wave);
+                        wavePacket=false;
+                    }
+                } else {
+                    // Checksum Error
+                }  // end if else for checksum
+            } // end if read 0xAA byte
+        } // end if read 0xAA byte
+    }
+}
\ No newline at end of file