Joel Murphy / Mbed 2 deprecated ADS_StreamRawData

Dependencies:   mbed

Revision:
0:675506e540be
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Mar 23 19:22:04 2015 +0000
@@ -0,0 +1,351 @@
+
+#include "mbed.h"
+#include "ADS1299.h"
+
+Serial pc(USBTX, USBRX);    // set up the COM
+SPI spi (PTD2,PTD3,PTD1);   // mosi, miso, sck
+
+
+//define how I'd like my channels setup
+#define MAX_N_CHANNELS (8)  //must be less than or equal to length of channelData in ADS1299 object!!
+int nActiveChannels = 8;   //how many active channels would I like?
+byte gainCode = ADS_GAIN24;   //how much gain do I want
+byte inputType = ADSINPUT_NORMAL;   //here's the normal way to setup the channels
+//byte inputType = ADSINPUT_SHORTED;  //here's another way to setup the channels
+//byte inputType = ADSINPUT_TESTSIG;  //here's a third way to setup the channels
+
+//other variables
+long sampleCounter = 0;      // used to time the tesing loop
+boolean is_running = false;    // this flag is set in serialEvent on reciept of prompt
+#define PIN_STARTBINARY (7)  //pull this pin to ground to start binary transfer
+//define PIN_STARTBINARY_OPENEEG (6)
+boolean startBecauseOfPin = false;
+boolean startBecauseOfSerial = false;
+
+#define OUTPUT_NOTHING (0)
+#define OUTPUT_TEXT (1)
+#define OUTPUT_BINARY (2)
+#define OUTPUT_BINARY_4CHAN (4)
+#define OUTPUT_BINARY_OPENEEG (6)
+#define OUTPUT_BINARY_OPENEEG_SYNTHETIC (7)
+int outputType;
+
+//Design filters  (This BIQUAD class requires ~6K of program space!  Ouch.)
+//For frequency response of these filters: http://www.earlevel.com/main/2010/12/20/biquad-calculator/
+#include <Biquad_multiChan.h>   //modified from this source code:  http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
+#define SAMPLE_RATE_HZ (250.0)  //default setting for OpenBCI
+#define FILTER_Q (0.5)        //critically damped is 0.707 (Butterworth)
+#define FILTER_PEAK_GAIN_DB (0.0) //we don't want any gain in the passband
+#define HP_CUTOFF_HZ (0.5)  //set the desired cutoff for the highpass filter
+Biquad_multiChan stopDC_filter(MAX_N_CHANNELS,bq_type_highpass,HP_CUTOFF_HZ / SAMPLE_RATE_HZ, FILTER_Q, FILTER_PEAK_GAIN_DB); //one for each channel because the object maintains the filter states
+//Biquad_multiChan stopDC_filter(MAX_N_CHANNELS,bq_type_bandpass,10.0 / SAMPLE_RATE_HZ, 6.0, FILTER_PEAK_GAIN_DB); //one for each channel because the object maintains the filter states
+#define NOTCH_FREQ_HZ (60.0)
+#define NOTCH_Q (4.0)              //pretty shap notch
+#define NOTCH_PEAK_GAIN_DB (0.0)  //doesn't matter for this filter type
+Biquad_multiChan notch_filter1(MAX_N_CHANNELS,bq_type_notch,NOTCH_FREQ_HZ / SAMPLE_RATE_HZ, NOTCH_Q, NOTCH_PEAK_GAIN_DB); //one for each channel because the object maintains the filter states
+Biquad_multiChan notch_filter2(MAX_N_CHANNELS,bq_type_notch,NOTCH_FREQ_HZ / SAMPLE_RATE_HZ, NOTCH_Q, NOTCH_PEAK_GAIN_DB); //one for each channel because the object maintains the filter states
+boolean useFilters = false;
+
+
+
+DigitalOut CS (PTD0);       // arduino pin 10 - chip select
+DigitalOut RST(PTD5);       // arduino pin 9 - reset pin
+DigitalIn DRDY(PTA13);      // arduino pin 8 - data ready pin
+DigitalOut myled(LED3);     // debugging LED CONFLICT WITH SPI & LED1
+
+
+
+int main() {
+
+    ADS1299Manager ADSManager;
+    int OpenBCI_version = OPENBCI_V2;  //assume V2
+    ADSManager.initialize(OpenBCI_version);  //must do this VERY early in the setup...preferably first
+
+    spi.format(8,1);            // spi: 8 bit, mode 1
+    spi.frequency(1000000);     // spi sck frequency
+    
+    pc.baud(115200);
+    pc.printf("\nADS1299 Stream Raw Data\n");
+    wait(2.0);
+
+  pc.printf("ADS1299-Arduino UNO - Stream Raw Data"); //read the string from Flash to save RAM
+  pc.printf("Configured as OpenBCI_Version code = ");pc.printf(OpenBCI_version);
+  Serial.flush();
+  
+  // setup the channels as desired on the ADS1299..set gain, input type, referece (SRB1), and patient bias signal
+  for (int chan=1; chan <= nActiveChannels; chan++) {
+    ADSManager.activateChannel(chan, gainCode, inputType);
+  }
+
+  //print state of all registers
+  ADSManager.printAllRegisters();Serial.flush();
+
+  // setup hardware to allow a jumper or button to start the digitaltransfer
+  pinMode(PIN_STARTBINARY,INPUT); digitalWrite(PIN_STARTBINARY,HIGH); //activate pullup
+  //pinMode(PIN_STARTBINARY_OPENEEG,INPUT); digitalWrite(PIN_STARTBINARY_OPENEEG,HIGH);  //activate pullup
+  
+  // tell the controlling program that we're ready to start!
+  pc.printf("Press '?' to query and print ADS1299 register settings again"); //read it straight from flash
+  pc.printf("Press 1-8 to disable EEG Channels, q-i to enable (all enabled by default)");
+  pc.printf("Press 'F' to enable filters.  'f' to disable filters (disabled by default)");
+  pc.printf("Press 'x' (text) or 'b' (binary) to begin streaming data...");    
+ 
+boolean firstReport = true;
+unsigned long totalMicrosBusy = 0;  //use this to count time
+
+    while(1) {
+    
+        if (is_running) {
+ 
+        //is data ready?      
+        while(!(ADSManager.isDataAvailable())){            // watch the DRDY pin
+            delayMicroseconds(100);
+        }
+        unsigned long start_micros = micros();
+  
+        //get the data
+        ADSManager.updateChannelData();          // update the channelData array 
+        sampleCounter++;                        // increment my sample counter
+    
+        //Apply  filers to the data
+        if (useFilters) applyFilters();
+
+        //print the data
+        //if ((sampleCounter % 1) == 0) {
+        switch (outputType) {
+            case OUTPUT_NOTHING:
+                //don't output anything...the Arduino is still collecting data from the OpenBCI board...just nothing is being done with it
+            break;
+            case OUTPUT_BINARY:
+                ADSManager.writeChannelDataAsBinary(8,sampleCounter);  //print all channels, whether active or not
+            break;
+            case OUTPUT_BINARY_4CHAN:
+                ADSManager.writeChannelDataAsBinary(4,sampleCounter);  //print all channels, whether active or not
+              break; 
+            case OUTPUT_BINARY_OPENEEG:
+                ADSManager.writeChannelDataAsOpenEEG_P2(sampleCounter);  //print all channels, whether active or not
+            break; 
+            case OUTPUT_BINARY_OPENEEG_SYNTHETIC:
+                ADSManager.writeChannelDataAsOpenEEG_P2(sampleCounter,true);  //print all channels, whether active or not
+            break;           
+            default:
+                ADSManager.printChannelDataAsText(8,sampleCounter);  //print all channels, whether active or not
+            }// end of if(is_running)
+        }// end of while(1)
+
+        if(pc.readable()) {
+            serialEvent();
+        }
+    
+}// end of main()
+
+
+#define ACTIVATE_SHORTED (2)
+#define ACTIVATE (1)
+#define DEACTIVATE (0)
+void serialEvent(){            // 
+    char inChar = pc.getc();
+    switch (inChar)
+    {
+      case '1':
+        changeChannelState_maintainRunningState(1,DEACTIVATE); break;
+      case '2':
+        changeChannelState_maintainRunningState(2,DEACTIVATE); break;
+      case '3':
+        changeChannelState_maintainRunningState(3,DEACTIVATE); break;
+      case '4':
+        changeChannelState_maintainRunningState(4,DEACTIVATE); break;
+      case '5':
+        changeChannelState_maintainRunningState(5,DEACTIVATE); break;
+      case '6':
+        changeChannelState_maintainRunningState(6,DEACTIVATE); break;
+      case '7':
+        changeChannelState_maintainRunningState(7,DEACTIVATE); break;
+      case '8':
+        changeChannelState_maintainRunningState(8,DEACTIVATE); break;
+      case 'q':
+        changeChannelState_maintainRunningState(1,ACTIVATE); break;
+      case 'w':
+        changeChannelState_maintainRunningState(2,ACTIVATE); break;
+      case 'e':
+        changeChannelState_maintainRunningState(3,ACTIVATE); break;
+      case 'r':
+        changeChannelState_maintainRunningState(4,ACTIVATE); break;
+      case 't':
+        changeChannelState_maintainRunningState(5,ACTIVATE); break;
+      case 'y':
+        changeChannelState_maintainRunningState(6,ACTIVATE); break;
+      case 'u':
+        changeChannelState_maintainRunningState(7,ACTIVATE); break;
+      case 'i':
+        changeChannelState_maintainRunningState(8,ACTIVATE); break;
+      case '0':
+        activateAllChannelsToTestCondition(ADSINPUT_SHORTED,ADSTESTSIG_NOCHANGE,ADSTESTSIG_NOCHANGE); break;
+      case '-':
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_SLOW); break;
+      case '+':
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_FAST); break;
+      case '=':
+        //repeat the line above...just for human convenience
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_1X,ADSTESTSIG_PULSE_FAST); break;
+      case 'p':
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_DCSIG); break;
+      case '[':
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_SLOW); break;
+      case ']':
+        activateAllChannelsToTestCondition(ADSINPUT_TESTSIG,ADSTESTSIG_AMP_2X,ADSTESTSIG_PULSE_FAST); break;
+      case 'n':
+        toggleRunState(OUTPUT_NOTHING);
+        startBecauseOfSerial = is_running;
+        if (is_running) Serial.println(F("FRDM: Starting, but not outputing to PC..."));
+        break;
+      case 'b':
+        toggleRunState(OUTPUT_BINARY);
+        startBecauseOfSerial = is_running;
+        if (is_running) Serial.println(F("FRDM: Starting binary..."));
+        break;
+      case 'v':
+        toggleRunState(OUTPUT_BINARY_4CHAN);
+        startBecauseOfSerial = is_running;
+        if (is_running) Serial.println(F("FRDM: Starting binary 4-chan..."));
+        break;
+     case 's':
+        stopRunning();
+        startBecauseOfSerial = is_running;
+        break;
+     case 'x':
+        toggleRunState(OUTPUT_TEXT);
+        startBecauseOfSerial = is_running;
+        if (is_running) Serial.println(F("FRDM: Starting text..."));
+        break;
+     case 'f':
+        useFilters = false;
+        Serial.println(F("FRDM: disabling filters"));
+        break;
+     case 'F':
+        useFilters = true;
+        Serial.println(F("FRDM: enabaling filters"));
+        break;
+     case '?':
+        //print state of all registers
+        ADSManager.printAllRegisters();
+        break;
+      default:
+        break;
+    }
+  }
+}
+
+boolean toggleRunState(int OUT_TYPE)
+{
+  if (is_running) {
+    return stopRunning();
+  } else {
+    return startRunning(OUT_TYPE);
+  }
+}
+
+boolean stopRunning(void) {
+  ADSManager.stop();                    // stop the data acquisition
+  is_running = false;
+  return is_running;
+}
+
+boolean startRunning(int OUT_TYPE) {
+    outputType = OUT_TYPE;
+    ADSManager.start();    //start the data acquisition
+    is_running = true;
+    return is_running;
+}
+
+int changeChannelState_maintainRunningState(int chan, int start)
+{
+  boolean is_running_when_called = is_running;
+  int cur_outputType = outputType;
+  
+  //must stop running to change channel settings
+  stopRunning();
+  if (start == true) {
+    Serial.print("Activating channel ");
+    Serial.println(chan);
+    ADSManager.activateChannel(chan,gainCode,inputType);
+  } else {
+    Serial.print("Deactivating channel ");
+    Serial.println(chan);
+    ADSManager.deactivateChannel(chan);
+  }
+  
+  //restart, if it was running before
+  if (is_running_when_called == true) {
+    startRunning(cur_outputType);
+  }
+}
+
+int activateAllChannelsToTestCondition(int testInputCode, byte amplitudeCode, byte freqCode)
+{
+  boolean is_running_when_called = is_running;
+  int cur_outputType = outputType;
+  
+  //set the test signal to the desired state
+  ADSManager.configureInternalTestSignal(amplitudeCode,freqCode);
+  
+  //must stop running to change channel settings
+  stopRunning();
+    
+  //loop over all channels to change their state
+  for (int Ichan=1; Ichan <= 8; Ichan++) {
+    ADSManager.activateChannel(Ichan,gainCode,testInputCode);  //Ichan must be [1 8]...it does not start counting from zero
+  }
+      
+  //restart, if it was running before
+  if (is_running_when_called == true) {
+    startRunning(cur_outputType);
+  }
+}
+
+long int runningAve[MAX_N_CHANNELS];
+int applyFilters(void) {
+  //scale factor for these coefficients was 32768 = 2^15
+  const static long int a0 = 32360L; //16 bit shift?
+  const static long int a1 = -2L*a0;
+  const static long int a2 = a0;
+  const static long int b1 = -64718L; //this is a shift of 17 bits!
+  const static long int b2 = 31955L;
+  static long int z1[MAX_N_CHANNELS], z2[MAX_N_CHANNELS];
+  long int val_int, val_in_down9, val_out, val_out_down9;
+  float val;
+  for (int Ichan=0; Ichan < MAX_N_CHANNELS; Ichan++) {
+    switch (1) {
+      case 1:
+        //use BiQuad
+        val = (float) ADSManager.channelData[Ichan]; //get the stored value for this sample
+        val = stopDC_filter.process(val,Ichan);    //apply DC-blocking filter
+        break;
+      case 2:
+        //do fixed point, 1st order running ave
+        val_int = ADSManager.channelData[Ichan]; //get the stored value for this sample
+        //runningAve[Ichan]=( ((512-1)*(runningAve[Ichan]>>2)) + (val_int>>2) )>>7;  // fs/0.5Hz = ~512 points..9 bits
+        //runningAve[Ichan]=( ((256-1)*(runningAve[Ichan]>>2)) + (val_int>>2) )>>6;  // fs/1.0Hz = ~256 points...8 bits
+        runningAve[Ichan]=( ((128-1)*(runningAve[Ichan]>>1)) + (val_int>>1) )>>6;  // fs/2.0Hz = ~128 points...7 bits
+        val = (float)(val_int - runningAve[Ichan]);  //remove the DC
+        break;
+//      case 3:
+//        val_in_down9 = ADSManager.channelData[Ichan] >> 9; //get the stored value for this sample...bring 24-bit value down to 16-bit
+//        val_out = (val_in_down9 * a0  + (z1[Ichan]>>9)) >> (16-9);  //8bits were already removed...results in 24-bit value
+//        val_out_down9 = val_out >> 9;  //remove eight bits to go from 24-bit down to 16 bit
+//        z1[Ichan] = (val_in_down9 * a1 + (z2[Ichan] >> 9) - b1 * val_out_down9  ) >> (16-9);  //8-bits were pre-removed..end in 24 bit number
+//        z2[Ichan] = (val_in_down9 * a2  - b2 * val_out_down9) >> (16-9); //8-bits were pre-removed...end in 24-bit number
+//        val = (float)val_out;
+//        break;
+    }
+    val = notch_filter1.process(val,Ichan);     //apply 60Hz notch filter
+    val = notch_filter2.process(val,Ichan);     //apply it again
+    ADSManager.channelData[Ichan] = (long) val;  //save the value back into the main data-holding object
+  }
+  return 0;
+}
+
+
+
+
+